Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "Outliner.hxx"
21 : #include <vcl/wrkwin.hxx>
22 : #include <svl/srchitem.hxx>
23 : #include <editeng/colritem.hxx>
24 : #include <editeng/eeitem.hxx>
25 : #include <editeng/editstat.hxx>
26 : #include <vcl/outdev.hxx>
27 : #include <svx/dlgutil.hxx>
28 : #include <svx/xtable.hxx>
29 : #include <vcl/msgbox.hxx>
30 : #include <sfx2/dispatch.hxx>
31 : #include <sfx2/printer.hxx>
32 : #include <svx/svxerr.hxx>
33 : #include <svx/svdotext.hxx>
34 : #include <editeng/unolingu.hxx>
35 : #include <svx/svditer.hxx>
36 : #include <comphelper/extract.hxx>
37 : #include <com/sun/star/linguistic2/XSpellChecker1.hpp>
38 : #include <com/sun/star/beans/XPropertySet.hpp>
39 : #include <comphelper/processfactory.hxx>
40 : #include <editeng/forbiddencharacterstable.hxx>
41 : #include <svx/srchdlg.hxx>
42 : #include <unotools/linguprops.hxx>
43 : #include <unotools/lingucfg.hxx>
44 : #include <editeng/editeng.hxx>
45 : #include <vcl/metric.hxx>
46 : #include <sfx2/viewfrm.hxx>
47 : #include <svtools/langtab.hxx>
48 : #include <tools/diagnose_ex.h>
49 :
50 : #include "strings.hrc"
51 : #include "sdstring.hrc"
52 : #include "eetext.hxx"
53 : #include "sdpage.hxx"
54 : #include "app.hxx"
55 : #include "Window.hxx"
56 : #include "sdresid.hxx"
57 : #include "DrawViewShell.hxx"
58 : #include "OutlineViewShell.hxx"
59 : #include "drawdoc.hxx"
60 : #include "DrawDocShell.hxx"
61 : #include "FrameView.hxx"
62 : #include "optsitem.hxx"
63 : #include "drawview.hxx"
64 : #include "ViewShellBase.hxx"
65 : #include "SpellDialogChildWindow.hxx"
66 : #include "ToolBarManager.hxx"
67 : #include "framework/FrameworkHelper.hxx"
68 : #include <svx/svxids.hrc>
69 : #include <editeng/editerr.hxx>
70 :
71 : using ::rtl::OUString;
72 : using namespace ::com::sun::star;
73 : using namespace ::com::sun::star::uno;
74 : using namespace ::com::sun::star::lang;
75 : using namespace ::com::sun::star::linguistic2;
76 :
77 : class SfxStyleSheetPool;
78 :
79 : namespace sd {
80 :
81 : class Outliner::Implementation
82 : {
83 : public:
84 : /** The original edit mode directly after switching to a different view
85 : mode. Used for restoring the edit mode when leaving that view mode
86 : again.
87 : */
88 : EditMode meOriginalEditMode;
89 :
90 : Implementation (void);
91 : ~Implementation (void);
92 :
93 : /** Return the OutlinerView that was provided by the last call to
94 : ProvideOutlinerView() (or NULL when there was no such call.)
95 : */
96 : OutlinerView* GetOutlinerView (void);
97 :
98 : /** Provide in the member mpOutlineView an instance of OutlinerView that
99 : is either taken from the ViewShell, when it is an OutlineViewShell,
100 : or is created. When an OutlinerView already exists it is initialied.
101 : */
102 : void ProvideOutlinerView (
103 : Outliner& rOutliner,
104 : const ::boost::shared_ptr<ViewShell>& rpViewShell,
105 : ::Window* pWindow);
106 :
107 : /** This method is called when the OutlinerView is no longer used.
108 : */
109 : void ReleaseOutlinerView (void);
110 :
111 : private:
112 : /** Flag that specifies whether we own the outline view pointed to by
113 : <member>mpOutlineView</member> and thus have to
114 : delete it in <member>EndSpelling()</member>.
115 : */
116 : bool mbOwnOutlineView;
117 :
118 : /** The outline view used for searching and spelling. If searching or
119 : spell checking an outline view this data member points to that view.
120 : For all other views an instance is created. The
121 : <member>mbOwnOutlineView</member> distinguishes between both cases.
122 : */
123 : OutlinerView* mpOutlineView;
124 : };
125 :
126 :
127 :
128 :
129 : /*************************************************************************
130 : |*
131 : |* Ctor
132 : |*
133 : \************************************************************************/
134 :
135 11 : Outliner::Outliner( SdDrawDocument* pDoc, sal_uInt16 nMode )
136 11 : : SdrOutliner( &pDoc->GetItemPool(), nMode ),
137 : mpImpl(new Implementation()),
138 : meMode(SEARCH),
139 : mpView(NULL),
140 : mpWeakViewShell(),
141 : mpWindow(NULL),
142 : mpDrawDocument(pDoc),
143 : mnConversionLanguage(LANGUAGE_NONE),
144 : mnIgnoreCurrentPageChangesLevel(0),
145 : mbStringFound(sal_False),
146 : mbMatchMayExist(false),
147 : mnPageCount(0),
148 : mnObjectCount(0),
149 : mbEndOfSearch(sal_False),
150 : mbFoundObject(sal_False),
151 : mbError(sal_False),
152 : mbDirectionIsForward(true),
153 : mbRestrictSearchToSelection(false),
154 : maMarkListCopy(),
155 : mbProcessCurrentViewOnly(false),
156 : mpObj(NULL),
157 : mpFirstObj(NULL),
158 : mpTextObj(NULL),
159 : mnText(0),
160 : mpParaObj(NULL),
161 : meStartViewMode(PK_STANDARD),
162 : meStartEditMode(EM_PAGE),
163 : mnStartPageIndex((sal_uInt16)-1),
164 : mpStartEditedObject(NULL),
165 : maStartSelection(),
166 : mpSearchItem(NULL),
167 : maObjectIterator(),
168 : maCurrentPosition(),
169 : maSearchStartPosition(),
170 : maLastValidPosition(),
171 : mbSelectionHasChanged(false),
172 : mbExpectingSelectionChangeEvent(false),
173 : mbWholeDocumentProcessed(false),
174 22 : mbPrepareSpellingPending(true)
175 : {
176 11 : SetStyleSheetPool((SfxStyleSheetPool*) mpDrawDocument->GetStyleSheetPool());
177 11 : SetEditTextObjectPool( &pDoc->GetItemPool() );
178 11 : SetCalcFieldValueHdl(LINK(SD_MOD(), SdModule, CalcFieldValueHdl));
179 11 : SetForbiddenCharsTable( pDoc->GetForbiddenCharsTable() );
180 :
181 11 : sal_uLong nCntrl = GetControlWord();
182 11 : nCntrl |= EE_CNTRL_ALLOWBIGOBJS;
183 11 : nCntrl |= EE_CNTRL_URLSFXEXECUTE;
184 11 : nCntrl |= EE_CNTRL_MARKFIELDS;
185 11 : nCntrl |= EE_CNTRL_AUTOCORRECT;
186 :
187 11 : sal_Bool bOnlineSpell = false;
188 :
189 11 : DrawDocShell* pDocSh = mpDrawDocument->GetDocSh();
190 :
191 11 : if (pDocSh)
192 : {
193 11 : bOnlineSpell = mpDrawDocument->GetOnlineSpell();
194 : }
195 : else
196 : {
197 0 : bOnlineSpell = false;
198 :
199 : try
200 : {
201 0 : const SvtLinguConfig aLinguConfig;
202 0 : Any aAny;
203 :
204 0 : aAny = aLinguConfig.GetProperty( UPN_IS_SPELL_AUTO );
205 0 : aAny >>= bOnlineSpell;
206 : }
207 0 : catch( ... )
208 : {
209 : OSL_FAIL( "Ill. type in linguistic property" );
210 : }
211 : }
212 :
213 11 : if (bOnlineSpell)
214 11 : nCntrl |= EE_CNTRL_ONLINESPELLING;
215 : else
216 0 : nCntrl &= ~EE_CNTRL_ONLINESPELLING;
217 :
218 11 : SetControlWord(nCntrl);
219 :
220 11 : Reference< XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() );
221 11 : if ( xSpellChecker.is() )
222 11 : SetSpeller( xSpellChecker );
223 :
224 11 : Reference< XHyphenator > xHyphenator( LinguMgr::GetHyphenator() );
225 11 : if( xHyphenator.is() )
226 11 : SetHyphenator( xHyphenator );
227 :
228 11 : SetDefaultLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
229 11 : }
230 :
231 :
232 :
233 :
234 : /// Nothing spectecular in the destructor.
235 27 : Outliner::~Outliner (void)
236 : {
237 9 : mpImpl.reset();
238 18 : }
239 :
240 :
241 :
242 :
243 : /** Prepare find&replace or spellchecking. This distinguishes between three
244 : cases:
245 : <ol>
246 : <li>The current shell is a <type>DrawViewShell</type>: Create a
247 : <type>OutlinerView</type> object and search all objects of (i) the
248 : current mark list, (ii) of the current view, or (iii) of all the view
249 : combinations:
250 : <ol>
251 : <li>Draw view, slide view</li>
252 : <li>Draw view, background view</li>
253 : <li>Notes view, slide view</li>
254 : <li>Notes view, background view</li>
255 : <li>Handout view, slide view</li>
256 : <li>Handout view, background view</li>
257 : </ol>
258 :
259 : <li>When the current shell is a <type>SdOutlineViewShell</type> then
260 : directly operate on it. No switching into other views takes place.</li>
261 : </ol>
262 : */
263 0 : void Outliner::PrepareSpelling (void)
264 : {
265 0 : mbPrepareSpellingPending = false;
266 :
267 0 : ViewShellBase* pBase = PTR_CAST(ViewShellBase,SfxViewShell::Current());
268 0 : if (pBase != NULL)
269 0 : SetViewShell (pBase->GetMainViewShell());
270 0 : SetRefDevice( SD_MOD()->GetRefDevice( *mpDrawDocument->GetDocSh() ) );
271 :
272 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
273 0 : if (pViewShell)
274 : {
275 0 : mbStringFound = sal_False;
276 :
277 0 : mbWholeDocumentProcessed = false;
278 : // Supposed that we are not located at the very beginning/end of
279 : // the document then there may be a match in the document
280 : // prior/after the current position.
281 0 : mbMatchMayExist = sal_True;
282 :
283 0 : maObjectIterator = ::sd::outliner::Iterator();
284 0 : maSearchStartPosition = ::sd::outliner::Iterator();
285 0 : RememberStartPosition();
286 :
287 0 : mpImpl->ProvideOutlinerView(*this, pViewShell, mpWindow);
288 :
289 0 : HandleChangedSelection ();
290 : }
291 0 : ClearModifyFlag();
292 0 : }
293 :
294 :
295 :
296 :
297 :
298 0 : void Outliner::StartSpelling (void)
299 : {
300 0 : meMode = SPELL;
301 0 : mbDirectionIsForward = true;
302 0 : mpSearchItem = NULL;
303 0 : }
304 :
305 : /** Proxy for method from base class to avoid compiler warning */
306 0 : void Outliner::StartSpelling(EditView& rView, unsigned char c)
307 : {
308 0 : SdrOutliner::StartSpelling( rView, c );
309 0 : }
310 :
311 : /** Free all resources acquired during the search/spell check. After a
312 : spell check the start position is restored here.
313 : */
314 0 : void Outliner::EndSpelling (void)
315 : {
316 : // Keep old view shell alive until we release the outliner view.
317 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
318 0 : ::boost::shared_ptr<ViewShell> pOldViewShell (pViewShell);
319 :
320 0 : ViewShellBase* pBase = PTR_CAST(ViewShellBase,SfxViewShell::Current());
321 0 : if (pBase != NULL)
322 0 : pViewShell = pBase->GetMainViewShell();
323 : else
324 0 : pViewShell.reset();
325 0 : mpWeakViewShell = pViewShell;
326 :
327 : // When in <member>PrepareSpelling()</member> a new outline view has
328 : // been created then delete it here.
329 0 : sal_Bool bViewIsDrawViewShell(pViewShell && pViewShell->ISA(DrawViewShell));
330 0 : if (bViewIsDrawViewShell)
331 : {
332 0 : SetStatusEventHdl(Link());
333 0 : mpView = pViewShell->GetView();
334 0 : mpView->UnmarkAllObj (mpView->GetSdrPageView());
335 0 : mpView->SdrEndTextEdit();
336 : // Make FuSelection the current function.
337 0 : pViewShell->GetDispatcher()->Execute(
338 : SID_OBJECT_SELECT,
339 0 : SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD);
340 :
341 : // Remove and, if previously created by us, delete the outline
342 : // view.
343 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
344 0 : if (pOutlinerView != NULL)
345 : {
346 0 : RemoveView(pOutlinerView);
347 0 : mpImpl->ReleaseOutlinerView();
348 : }
349 :
350 0 : SetUpdateMode(sal_True);
351 : }
352 :
353 : // Before clearing the modify flag use it as a hint that
354 : // changes were done at SpellCheck
355 0 : if(IsModified())
356 : {
357 0 : if(mpView && mpView->ISA(OutlineView))
358 0 : static_cast<OutlineView*>(mpView)->PrepareClose(sal_False);
359 0 : if(mpDrawDocument && !mpDrawDocument->IsChanged())
360 0 : mpDrawDocument->SetChanged(sal_True);
361 : }
362 :
363 : // Now clear the modify flag to have a specified state of
364 : // Outliner
365 0 : ClearModifyFlag();
366 :
367 : // When spell checking then restore the start position.
368 0 : if (meMode==SPELL || meMode==TEXT_CONVERSION)
369 0 : RestoreStartPosition ();
370 :
371 0 : mpWeakViewShell.reset();
372 0 : mpView = NULL;
373 0 : mpWindow = NULL;
374 0 : mnStartPageIndex = (sal_uInt16) -1;
375 0 : }
376 :
377 :
378 :
379 :
380 0 : sal_Bool Outliner::SpellNextDocument (void)
381 : {
382 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
383 0 : if (pViewShell->ISA(OutlineViewShell))
384 : {
385 : // When doing a spell check in the outline view then there is
386 : // only one document.
387 0 : mbEndOfSearch = true;
388 0 : EndOfSearch ();
389 : }
390 : else
391 : {
392 0 : if (mpView->ISA(OutlineView))
393 0 : ((OutlineView*)mpView)->PrepareClose(sal_False);
394 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_True );
395 :
396 0 : Initialize (true);
397 :
398 0 : mpWindow = pViewShell->GetActiveWindow();
399 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
400 0 : if (pOutlinerView != NULL)
401 0 : pOutlinerView->SetWindow(mpWindow);
402 0 : ProvideNextTextObject ();
403 :
404 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_False );
405 0 : ClearModifyFlag();
406 : }
407 :
408 0 : return mbEndOfSearch ? sal_False : sal_True;
409 :
410 : }
411 :
412 :
413 : /*************************************************************************
414 : |*
415 : |* Spelling: naechstes TextObjekt pruefen
416 : |*
417 : \************************************************************************/
418 :
419 0 : ::svx::SpellPortions Outliner::GetNextSpellSentence (void)
420 : {
421 0 : ::svx::SpellPortions aResult;
422 :
423 0 : DetectChange();
424 : // Iterate over sentences and text shapes until a sentence with a
425 : // spelling error has been found. If no such sentence can be
426 : // found the loop is left through a break.
427 : // It is the responsibility of the sd outliner object to correctly
428 : // iterate over all text shapes, i.e. switch between views, wrap
429 : // arround at the end of the document, stop when all text shapes
430 : // have been examined exactly once.
431 0 : bool bFoundNextSentence = false;
432 0 : while ( ! bFoundNextSentence)
433 : {
434 0 : OutlinerView* pOutlinerView = GetView(0);
435 0 : if (pOutlinerView != NULL)
436 : {
437 0 : ESelection aCurrentSelection (pOutlinerView->GetSelection());
438 0 : if ( ! mbMatchMayExist
439 0 : && maStartSelection.IsLess(aCurrentSelection))
440 0 : EndOfSearch();
441 :
442 : // Advance to the next sentence.
443 : bFoundNextSentence = SpellSentence (
444 0 : pOutlinerView->GetEditView(),
445 0 : aResult, false);
446 : }
447 :
448 : // When no sentence with spelling errors has been found in the
449 : // currently selected text shape or there is no selected text
450 : // shape then advance to the next text shape.
451 0 : if ( ! bFoundNextSentence)
452 0 : if ( ! SpellNextDocument())
453 : // All text objects have been processed so exit the
454 : // loop and return an empty portions list.
455 0 : break;
456 : }
457 :
458 0 : return aResult;
459 : }
460 :
461 :
462 :
463 :
464 : /** Go to next match.
465 : */
466 0 : bool Outliner::StartSearchAndReplace (const SvxSearchItem* pSearchItem)
467 : {
468 0 : sal_Bool bEndOfSearch = sal_True;
469 :
470 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_True );
471 0 : if (mbPrepareSpellingPending)
472 0 : PrepareSpelling();
473 0 : ViewShellBase* pBase = PTR_CAST(ViewShellBase,SfxViewShell::Current());
474 : // Determine whether we have to abort the search. This is necessary
475 : // when the main view shell does not support searching.
476 0 : bool bAbort = false;
477 0 : if (pBase != NULL)
478 : {
479 0 : ::boost::shared_ptr<ViewShell> pShell (pBase->GetMainViewShell());
480 0 : SetViewShell(pShell);
481 0 : if (pShell.get() == NULL)
482 0 : bAbort = true;
483 : else
484 0 : switch (pShell->GetShellType())
485 : {
486 : case ViewShell::ST_DRAW:
487 : case ViewShell::ST_IMPRESS:
488 : case ViewShell::ST_NOTES:
489 : case ViewShell::ST_HANDOUT:
490 : case ViewShell::ST_OUTLINE:
491 0 : bAbort = false;
492 0 : break;
493 : default:
494 0 : bAbort = true;
495 0 : break;
496 0 : }
497 : }
498 :
499 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
500 0 : if ( ! pViewShell)
501 : {
502 : OSL_ASSERT(pViewShell);
503 0 : return true;
504 : }
505 :
506 0 : if ( ! bAbort)
507 : {
508 0 : meMode = SEARCH;
509 0 : mpSearchItem = pSearchItem;
510 :
511 0 : mbFoundObject = sal_False;
512 :
513 0 : Initialize ( ! mpSearchItem->GetBackward());
514 :
515 0 : const sal_uInt16 nCommand (mpSearchItem->GetCommand());
516 0 : if (nCommand == SVX_SEARCHCMD_REPLACE_ALL)
517 0 : bEndOfSearch = SearchAndReplaceAll ();
518 : else
519 : {
520 0 : RememberStartPosition ();
521 0 : bEndOfSearch = SearchAndReplaceOnce ();
522 : // restore start position if nothing was found
523 0 : if(!mbStringFound)
524 0 : RestoreStartPosition ();
525 0 : mnStartPageIndex = (sal_uInt16)-1;
526 : }
527 : }
528 : else
529 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_False );
530 :
531 0 : return bEndOfSearch;
532 : }
533 :
534 :
535 :
536 :
537 0 : void Outliner::Initialize (bool bDirectionIsForward)
538 : {
539 0 : const bool bIsAtEnd (maObjectIterator == ::sd::outliner::OutlinerContainer(this).end());
540 0 : const bool bOldDirectionIsForward = mbDirectionIsForward;
541 0 : mbDirectionIsForward = bDirectionIsForward;
542 :
543 0 : if (maObjectIterator == ::sd::outliner::Iterator())
544 : {
545 : // Initialize a new search.
546 0 : maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
547 0 : maCurrentPosition = *maObjectIterator;
548 :
549 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
550 0 : if ( ! pViewShell)
551 : {
552 : OSL_ASSERT(pViewShell);
553 0 : return;
554 : }
555 :
556 : // In case we are searching in an outline view then first remove the
557 : // current selection and place cursor at its start or end.
558 0 : if (pViewShell->ISA(OutlineViewShell))
559 : {
560 0 : ESelection aSelection = mpImpl->GetOutlinerView()->GetSelection ();
561 0 : if (mbDirectionIsForward)
562 : {
563 0 : aSelection.nEndPara = aSelection.nStartPara;
564 0 : aSelection.nEndPos = aSelection.nStartPos;
565 : }
566 : else
567 : {
568 0 : aSelection.nStartPara = aSelection.nEndPara;
569 0 : aSelection.nStartPos = aSelection.nEndPos;
570 : }
571 0 : mpImpl->GetOutlinerView()->SetSelection (aSelection);
572 : }
573 :
574 : // When not beginning the search at the beginning of the search area
575 : // then there may be matches before the current position.
576 0 : mbMatchMayExist = (maObjectIterator!=::sd::outliner::OutlinerContainer(this).begin());
577 : }
578 0 : else if (bOldDirectionIsForward != mbDirectionIsForward)
579 : {
580 : // Requested iteration direction has changed. Turn arround the iterator.
581 0 : maObjectIterator.Reverse();
582 0 : if (bIsAtEnd)
583 : {
584 : // The iterator has pointed to end(), which after the search
585 : // direction is reversed, becomes begin().
586 0 : maObjectIterator = ::sd::outliner::OutlinerContainer(this).begin();
587 : }
588 : else
589 : {
590 : // The iterator has pointed to the object one ahead/before the current
591 : // one. Now move it to the one before/ahead the current one.
592 0 : ++maObjectIterator;
593 0 : ++maObjectIterator;
594 : }
595 :
596 0 : mbMatchMayExist = true;
597 : }
598 :
599 : // Initialize the last valid position with where the search starts so
600 : // that it always points to a valid position.
601 0 : maLastValidPosition = *::sd::outliner::OutlinerContainer(this).current();
602 : }
603 :
604 :
605 :
606 :
607 0 : bool Outliner::SearchAndReplaceAll (void)
608 : {
609 : // Save the current position to be restored after having replaced all
610 : // matches.
611 0 : RememberStartPosition ();
612 :
613 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
614 0 : if ( ! pViewShell)
615 : {
616 : OSL_ASSERT(pViewShell);
617 0 : return true;
618 : }
619 :
620 0 : if (pViewShell->ISA(OutlineViewShell))
621 : {
622 : // Put the cursor to the beginning/end of the outliner.
623 0 : mpImpl->GetOutlinerView()->SetSelection (GetSearchStartPosition ());
624 :
625 : // The outliner does all the work for us when we are in this mode.
626 0 : SearchAndReplaceOnce();
627 : }
628 0 : else if (pViewShell->ISA(DrawViewShell))
629 : {
630 : // Go to beginning/end of document.
631 0 : maObjectIterator = ::sd::outliner::OutlinerContainer(this).begin();
632 : // Switch to the current object only if it is a valid text object.
633 0 : ::sd::outliner::IteratorPosition aNewPosition (*maObjectIterator);
634 0 : if (IsValidTextObject (aNewPosition))
635 : {
636 0 : maCurrentPosition = aNewPosition;
637 0 : SetObject (maCurrentPosition);
638 : }
639 :
640 : // Search/replace until the end of the document is reached.
641 : bool bFoundMatch;
642 0 : do
643 : {
644 0 : bFoundMatch = ! SearchAndReplaceOnce();
645 : }
646 0 : while (bFoundMatch);
647 : }
648 :
649 0 : RestoreStartPosition ();
650 0 : mnStartPageIndex = (sal_uInt16)-1;
651 :
652 0 : return true;
653 : }
654 :
655 :
656 :
657 :
658 0 : bool Outliner::SearchAndReplaceOnce (void)
659 : {
660 0 : DetectChange ();
661 :
662 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
663 : DBG_ASSERT(pOutlinerView!=NULL && GetEditEngine().HasView( &pOutlinerView->GetEditView() ),
664 : "SearchAndReplace without valid view!" );
665 :
666 0 : if( NULL == pOutlinerView || !GetEditEngine().HasView( &pOutlinerView->GetEditView() ) )
667 0 : return true;
668 :
669 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
670 0 : if (pViewShell != NULL)
671 : {
672 0 : mpView = pViewShell->GetView();
673 0 : mpWindow = pViewShell->GetActiveWindow();
674 0 : pOutlinerView->SetWindow(mpWindow);
675 :
676 0 : if (pViewShell->ISA(DrawViewShell) )
677 : {
678 : // When replacing we first check if there is a selection
679 : // indicating a match. If there is then replace it. The
680 : // following call to StartSearchAndReplace will then search for
681 : // the next match.
682 0 : if (meMode == SEARCH
683 0 : && mpSearchItem->GetCommand() == SVX_SEARCHCMD_REPLACE)
684 0 : if (pOutlinerView->GetSelection().HasRange())
685 0 : pOutlinerView->StartSearchAndReplace(*mpSearchItem);
686 :
687 : // Search for the next match.
688 0 : sal_uLong nMatchCount = 0;
689 0 : if (mpSearchItem->GetCommand() != SVX_SEARCHCMD_REPLACE_ALL)
690 0 : nMatchCount = pOutlinerView->StartSearchAndReplace(*mpSearchItem);
691 :
692 : // Go to the next text object when there have been no matches in
693 : // the current object or the whole object has already been
694 : // processed.
695 0 : if (nMatchCount==0 || mpSearchItem->GetCommand()==SVX_SEARCHCMD_REPLACE_ALL)
696 : {
697 0 : ProvideNextTextObject ();
698 :
699 0 : if ( ! mbEndOfSearch)
700 : {
701 : // Remember the current position as the last one with a
702 : // text object.
703 0 : maLastValidPosition = maCurrentPosition;
704 :
705 : // Now that the mbEndOfSearch flag guards this block the
706 : // following assertion and return should not be
707 : // necessary anymore.
708 : DBG_ASSERT(GetEditEngine().HasView(&pOutlinerView->GetEditView() ),
709 : "SearchAndReplace without valid view!" );
710 0 : if ( ! GetEditEngine().HasView( &pOutlinerView->GetEditView() ) )
711 : {
712 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_False );
713 0 : return true;
714 : }
715 :
716 0 : if (meMode == SEARCH)
717 0 : nMatchCount = pOutlinerView->StartSearchAndReplace(*mpSearchItem);
718 : }
719 : }
720 : }
721 0 : else if (pViewShell->ISA(OutlineViewShell))
722 : {
723 0 : mpDrawDocument->GetDocSh()->SetWaitCursor (sal_False);
724 : // The following loop is executed more then once only when a
725 : // wrap arround search is done.
726 0 : while (true)
727 : {
728 0 : int nResult = pOutlinerView->StartSearchAndReplace(*mpSearchItem);
729 0 : if (nResult == 0)
730 : {
731 0 : if (HandleFailedSearch ())
732 : {
733 0 : pOutlinerView->SetSelection (GetSearchStartPosition ());
734 0 : continue;
735 : }
736 : }
737 : else
738 0 : mbStringFound = true;
739 0 : break;
740 : }
741 : }
742 : }
743 :
744 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_False );
745 :
746 0 : return mbEndOfSearch;
747 : }
748 :
749 :
750 :
751 :
752 : /** Try to detect whether the document or the view (shell) has changed since
753 : the last time <member>StartSearchAndReplace()</member> has been called.
754 : */
755 0 : void Outliner::DetectChange (void)
756 : {
757 0 : ::sd::outliner::IteratorPosition aPosition (maCurrentPosition);
758 :
759 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
760 : ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
761 0 : ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
762 :
763 : // Detect whether the view has been switched from the outside.
764 0 : if (pDrawViewShell.get() != NULL
765 0 : && (aPosition.meEditMode != pDrawViewShell->GetEditMode()
766 0 : || aPosition.mePageKind != pDrawViewShell->GetPageKind()))
767 : {
768 : // Either the edit mode or the page kind has changed.
769 0 : SetStatusEventHdl(Link());
770 :
771 0 : SdrPageView* pPageView = mpView->GetSdrPageView();
772 0 : if (pPageView != NULL)
773 0 : mpView->UnmarkAllObj (pPageView);
774 0 : mpView->SdrEndTextEdit();
775 0 : SetUpdateMode(sal_False);
776 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
777 0 : if (pOutlinerView != NULL)
778 0 : pOutlinerView->SetOutputArea( Rectangle( Point(), Size(1, 1) ) );
779 0 : if (meMode == SPELL)
780 0 : SetPaperSize( Size(1, 1) );
781 0 : SetText( String(), GetParagraph( 0 ) );
782 :
783 0 : RememberStartPosition ();
784 :
785 0 : mnPageCount = mpDrawDocument->GetSdPageCount(pDrawViewShell->GetPageKind());
786 0 : maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
787 : }
788 :
789 : // Detect change of the set of selected objects. If their number has
790 : // changed start again with the first selected object.
791 0 : else if (DetectSelectionChange())
792 : {
793 0 : HandleChangedSelection ();
794 0 : maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
795 : }
796 :
797 : // Detect change of page count. Restart search at first/last page in
798 : // that case.
799 0 : else if (aPosition.meEditMode == EM_PAGE
800 0 : && mpDrawDocument->GetSdPageCount(aPosition.mePageKind) != mnPageCount)
801 : {
802 : // The number of pages has changed.
803 0 : mnPageCount = mpDrawDocument->GetSdPageCount(aPosition.mePageKind);
804 0 : maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
805 : }
806 0 : else if (aPosition.meEditMode == EM_MASTERPAGE
807 0 : && mpDrawDocument->GetSdPageCount(aPosition.mePageKind) != mnPageCount)
808 : {
809 : // The number of master pages has changed.
810 0 : mnPageCount = mpDrawDocument->GetSdPageCount(aPosition.mePageKind);
811 0 : maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
812 0 : }
813 0 : }
814 :
815 :
816 :
817 :
818 0 : bool Outliner::DetectSelectionChange (void)
819 : {
820 0 : bool bSelectionHasChanged = false;
821 0 : sal_uLong nMarkCount = mpView->GetMarkedObjectList().GetMarkCount();
822 :
823 : // If mpObj is NULL then we have not yet found our first match.
824 : // Detecting a change makes no sense.
825 0 : if (mpObj != NULL)
826 0 : switch (nMarkCount)
827 : {
828 : case 0:
829 : // The selection has changed when previously there have been
830 : // selected objects.
831 0 : bSelectionHasChanged = mbRestrictSearchToSelection;
832 0 : break;
833 : case 1:
834 : // Check if the only selected object is not the one that we
835 : // had selected.
836 0 : if (mpView != NULL)
837 : {
838 0 : SdrMark* pMark = mpView->GetMarkedObjectList().GetMark(0);
839 0 : if (pMark != NULL)
840 0 : bSelectionHasChanged = (mpObj != pMark->GetMarkedSdrObj ());
841 : }
842 0 : break;
843 : default:
844 : // We had selected exactly one object.
845 0 : bSelectionHasChanged = true;
846 0 : break;
847 : }
848 :
849 0 : return bSelectionHasChanged;
850 : }
851 :
852 :
853 :
854 :
855 0 : void Outliner::RememberStartPosition (void)
856 : {
857 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
858 0 : if ( ! pViewShell)
859 : {
860 : OSL_ASSERT(pViewShell);
861 : return;
862 : }
863 :
864 0 : if ( mnStartPageIndex != (sal_uInt16) -1 )
865 : return;
866 :
867 0 : if (pViewShell->ISA(DrawViewShell))
868 : {
869 : ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
870 0 : ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
871 0 : if (pDrawViewShell.get() != NULL)
872 : {
873 0 : meStartViewMode = pDrawViewShell->GetPageKind();
874 0 : meStartEditMode = pDrawViewShell->GetEditMode();
875 0 : mnStartPageIndex = pDrawViewShell->GetCurPageId() - 1;
876 : }
877 :
878 0 : if (mpView != NULL)
879 : {
880 0 : mpStartEditedObject = mpView->GetTextEditObject();
881 0 : if (mpStartEditedObject != NULL)
882 : {
883 : // Try to retrieve current caret position only when there is an
884 : // edited object.
885 : ::Outliner* pOutliner =
886 0 : static_cast<DrawView*>(mpView)->GetTextEditOutliner();
887 0 : if (pOutliner!=NULL && pOutliner->GetViewCount()>0)
888 : {
889 0 : OutlinerView* pOutlinerView = pOutliner->GetView(0);
890 0 : maStartSelection = pOutlinerView->GetSelection();
891 : }
892 : }
893 0 : }
894 : }
895 0 : else if (pViewShell->ISA(OutlineViewShell))
896 : {
897 : // Remember the current cursor position.
898 0 : OutlinerView* pView = GetView(0);
899 0 : if (pView != NULL)
900 0 : pView->GetSelection();
901 : }
902 : else
903 : {
904 0 : mnStartPageIndex = (sal_uInt16)-1;
905 0 : }
906 : }
907 :
908 :
909 :
910 :
911 0 : void Outliner::RestoreStartPosition (void)
912 : {
913 0 : bool bRestore = true;
914 : // Take a negative start page index as inidicator that restoring the
915 : // start position is not requested.
916 0 : if (mnStartPageIndex == (sal_uInt16)-1 )
917 0 : bRestore = false;
918 : // Dont't restore when the view shell is not valid.
919 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
920 0 : if (pViewShell == NULL)
921 0 : bRestore = false;
922 :
923 0 : if (bRestore)
924 : {
925 0 : if (pViewShell->ISA(DrawViewShell))
926 : {
927 : ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
928 0 : ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
929 0 : SetViewMode (meStartViewMode);
930 0 : if (pDrawViewShell.get() != NULL)
931 0 : SetPage (meStartEditMode, mnStartPageIndex);
932 :
933 :
934 0 : if (mpStartEditedObject != NULL)
935 : {
936 : // Turn on the text toolbar as it is done in FuText so that
937 : // undo manager setting/restoring in
938 : // sd::View::{Beg,End}TextEdit() works on the same view shell.
939 0 : pViewShell->GetViewShellBase().GetToolBarManager()->SetToolBarShell(
940 : ToolBarManager::TBG_FUNCTION,
941 0 : RID_DRAW_TEXT_TOOLBOX);
942 :
943 0 : mpView->SdrBeginTextEdit(mpStartEditedObject);
944 : ::Outliner* pOutliner =
945 0 : static_cast<DrawView*>(mpView)->GetTextEditOutliner();
946 0 : if (pOutliner!=NULL && pOutliner->GetViewCount()>0)
947 : {
948 0 : OutlinerView* pOutlinerView = pOutliner->GetView(0);
949 0 : pOutlinerView->SetSelection(maStartSelection);
950 : }
951 0 : }
952 : }
953 0 : else if (pViewShell->ISA(OutlineViewShell))
954 : {
955 : // Set cursor to its old position.
956 0 : OutlinerView* pView = GetView(0);
957 0 : if (pView != NULL)
958 0 : pView->SetSelection (maStartSelection);
959 : }
960 0 : }
961 0 : }
962 :
963 :
964 :
965 :
966 : /** The main purpose of this method is to iterate over all shape objects of
967 : the search area (current selection, current view, or whole document)
968 : until a text object has been found that contains at least one match or
969 : until no such object can be found anymore. These two conditions are
970 : expressed by setting one of the flags <member>mbFoundObject</member> or
971 : <member>mbEndOfSearch</member> to <TRUE/>.
972 : */
973 0 : void Outliner::ProvideNextTextObject (void)
974 : {
975 0 : mbEndOfSearch = false;
976 0 : mbFoundObject = false;
977 :
978 0 : mpView->UnmarkAllObj (mpView->GetSdrPageView());
979 : try
980 : {
981 0 : mpView->SdrEndTextEdit();
982 : }
983 0 : catch (const ::com::sun::star::uno::Exception&)
984 : {
985 : DBG_UNHANDLED_EXCEPTION();
986 : }
987 0 : SetUpdateMode(sal_False);
988 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
989 0 : if (pOutlinerView != NULL)
990 0 : pOutlinerView->SetOutputArea( Rectangle( Point(), Size(1, 1) ) );
991 0 : if (meMode == SPELL)
992 0 : SetPaperSize( Size(1, 1) );
993 0 : SetText( String(), GetParagraph( 0 ) );
994 :
995 0 : mpTextObj = NULL;
996 :
997 : // Iterate until a valid text object has been found or the search ends.
998 0 : do
999 : {
1000 0 : mpObj = NULL;
1001 0 : mpParaObj = NULL;
1002 :
1003 0 : if (maObjectIterator != ::sd::outliner::OutlinerContainer(this).end())
1004 : {
1005 0 : maCurrentPosition = *maObjectIterator;
1006 : // Switch to the current object only if it is a valid text object.
1007 0 : if (IsValidTextObject (maCurrentPosition))
1008 : {
1009 0 : mpObj = SetObject (maCurrentPosition);
1010 : }
1011 0 : ++maObjectIterator;
1012 :
1013 0 : if (mpObj != NULL)
1014 : {
1015 0 : PutTextIntoOutliner ();
1016 :
1017 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1018 0 : if (pViewShell != NULL)
1019 0 : switch (meMode)
1020 : {
1021 : case SEARCH:
1022 0 : PrepareSearchAndReplace ();
1023 0 : break;
1024 : case SPELL:
1025 0 : PrepareSpellCheck ();
1026 0 : break;
1027 : case TEXT_CONVERSION:
1028 0 : PrepareConversion();
1029 0 : break;
1030 0 : }
1031 : }
1032 : }
1033 : else
1034 : {
1035 0 : mbEndOfSearch = true;
1036 0 : EndOfSearch ();
1037 : }
1038 : }
1039 0 : while ( ! (mbFoundObject || mbEndOfSearch));
1040 0 : }
1041 :
1042 :
1043 :
1044 :
1045 0 : void Outliner::EndOfSearch (void)
1046 : {
1047 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1048 0 : if ( ! pViewShell)
1049 : {
1050 : OSL_ASSERT(pViewShell);
1051 0 : return;
1052 : }
1053 :
1054 : // Before we display a dialog we first jump to where the last valid text
1055 : // object was found. All page and view mode switching since then was
1056 : // temporary and should not be visible to the user.
1057 0 : if ( ! pViewShell->ISA(OutlineViewShell))
1058 0 : SetObject (maLastValidPosition);
1059 :
1060 0 : if (mbRestrictSearchToSelection)
1061 0 : ShowEndOfSearchDialog ();
1062 : else
1063 : {
1064 : // When no match has been found so far then terminate the search.
1065 0 : if ( ! mbMatchMayExist)
1066 : {
1067 0 : ShowEndOfSearchDialog ();
1068 0 : mbEndOfSearch = sal_True;
1069 : }
1070 : // Ask the user whether to wrap arround and continue the search or
1071 : // to terminate.
1072 0 : else if (meMode==TEXT_CONVERSION || ShowWrapArroundDialog ())
1073 : {
1074 0 : mbMatchMayExist = false;
1075 : // Everything back to beginning (or end?) of the document.
1076 0 : maObjectIterator = ::sd::outliner::OutlinerContainer(this).begin();
1077 0 : if (pViewShell->ISA(OutlineViewShell))
1078 : {
1079 : // Set cursor to first character of the document.
1080 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1081 0 : if (pOutlinerView != NULL)
1082 0 : pOutlinerView->SetSelection (GetSearchStartPosition ());
1083 : }
1084 :
1085 0 : mbEndOfSearch = false;
1086 : }
1087 : else
1088 : {
1089 : // No wrap arround.
1090 0 : mbEndOfSearch = true;
1091 : }
1092 0 : }
1093 : }
1094 :
1095 0 : void Outliner::ShowEndOfSearchDialog (void)
1096 : {
1097 0 : String aString;
1098 0 : if (meMode == SEARCH)
1099 : {
1100 0 : if (mbStringFound)
1101 0 : aString = String( SdResId(STR_END_SEARCHING) );
1102 : else
1103 0 : aString = String( SdResId(STR_STRING_NOTFOUND) );
1104 : }
1105 : else
1106 : {
1107 0 : if (mpView->AreObjectsMarked())
1108 0 : aString = String(SdResId(STR_END_SPELLING_OBJ));
1109 : else
1110 0 : aString = String(SdResId(STR_END_SPELLING));
1111 : }
1112 :
1113 : // Show the message in an info box that is modal with respect to the
1114 : // whole application.
1115 0 : InfoBox aInfoBox (NULL, aString);
1116 0 : ShowModalMessageBox (aInfoBox);
1117 :
1118 0 : mbWholeDocumentProcessed = true;
1119 0 : }
1120 :
1121 :
1122 :
1123 :
1124 0 : bool Outliner::ShowWrapArroundDialog (void)
1125 : {
1126 0 : bool bDoWrapArround = false;
1127 :
1128 : // Determine whether to show the dialog.
1129 0 : bool bShowDialog = false;
1130 0 : if (mpSearchItem != NULL)
1131 : {
1132 : // When searching display the dialog only for single find&replace.
1133 0 : const sal_uInt16 nCommand (mpSearchItem->GetCommand());
1134 : bShowDialog = (nCommand==SVX_SEARCHCMD_REPLACE)
1135 0 : || (nCommand==SVX_SEARCHCMD_FIND);
1136 : }
1137 : else
1138 : // Spell checking needs the dialog, too.
1139 0 : bShowDialog = (meMode == SPELL);
1140 :
1141 0 : if (bShowDialog)
1142 : {
1143 : // The question text depends on the search direction.
1144 : sal_Bool bImpress = mpDrawDocument!=NULL
1145 0 : && mpDrawDocument->GetDocumentType() == DOCUMENT_TYPE_IMPRESS;
1146 : sal_uInt16 nStringId;
1147 0 : if (mbDirectionIsForward)
1148 : nStringId = bImpress
1149 : ? STR_SAR_WRAP_FORWARD
1150 0 : : STR_SAR_WRAP_FORWARD_DRAW;
1151 : else
1152 : nStringId = bImpress
1153 : ? STR_SAR_WRAP_BACKWARD
1154 0 : : STR_SAR_WRAP_BACKWARD_DRAW;
1155 :
1156 : // Pop up question box that asks the user whether to wrap arround.
1157 : // The dialog is made modal with respect to the whole application.
1158 : QueryBox aQuestionBox (
1159 : NULL,
1160 : WB_YES_NO | WB_DEF_YES,
1161 0 : String(SdResId(nStringId)));
1162 0 : aQuestionBox.SetImage (QueryBox::GetStandardImage());
1163 0 : sal_uInt16 nBoxResult = ShowModalMessageBox(aQuestionBox);
1164 0 : bDoWrapArround = (nBoxResult == BUTTONID_YES);
1165 : }
1166 :
1167 0 : return bDoWrapArround;
1168 : }
1169 :
1170 :
1171 :
1172 :
1173 0 : bool Outliner::IsValidTextObject (const ::sd::outliner::IteratorPosition& rPosition)
1174 : {
1175 0 : SdrTextObj* pObject = dynamic_cast< SdrTextObj* >( rPosition.mxObject.get() );
1176 0 : return (pObject != NULL) && pObject->HasText() && ! pObject->IsEmptyPresObj();
1177 : }
1178 :
1179 :
1180 :
1181 :
1182 0 : void Outliner::PutTextIntoOutliner()
1183 : {
1184 0 : mpTextObj = dynamic_cast<SdrTextObj*>( mpObj );
1185 0 : if ( mpTextObj && mpTextObj->HasText() && !mpTextObj->IsEmptyPresObj() )
1186 : {
1187 0 : SdrText* pText = mpTextObj->getText( mnText );
1188 0 : mpParaObj = pText ? pText->GetOutlinerParaObject() : NULL;
1189 :
1190 0 : if (mpParaObj != NULL)
1191 : {
1192 0 : SetText(*mpParaObj);
1193 :
1194 0 : ClearModifyFlag();
1195 : }
1196 : }
1197 : else
1198 : {
1199 0 : mpTextObj = NULL;
1200 : }
1201 0 : }
1202 :
1203 :
1204 :
1205 :
1206 0 : void Outliner::PrepareSpellCheck (void)
1207 : {
1208 0 : EESpellState eState = HasSpellErrors();
1209 : DBG_ASSERT(eState != EE_SPELL_NOSPELLER, "No SpellChecker");
1210 :
1211 0 : if (eState == EE_SPELL_NOLANGUAGE)
1212 : {
1213 0 : mbError = sal_True;
1214 0 : mbEndOfSearch = sal_True;
1215 : ErrorBox aErrorBox (NULL,
1216 : WB_OK,
1217 0 : String(SdResId(STR_NOLANGUAGE)));
1218 0 : ShowModalMessageBox (aErrorBox);
1219 : }
1220 0 : else if (eState != EE_SPELL_OK)
1221 : {
1222 : // When spell checking we have to test whether we have processed the
1223 : // whole document and have reached the start page again.
1224 0 : if (meMode == SPELL)
1225 : {
1226 0 : if (maSearchStartPosition == ::sd::outliner::Iterator())
1227 : // Remember the position of the first text object so that we
1228 : // know when we have processed the whole document.
1229 0 : maSearchStartPosition = maObjectIterator;
1230 0 : else if (maSearchStartPosition == maObjectIterator)
1231 : {
1232 0 : mbEndOfSearch = true;
1233 : }
1234 : }
1235 :
1236 0 : EnterEditMode( sal_False );
1237 : }
1238 0 : }
1239 :
1240 :
1241 :
1242 :
1243 0 : void Outliner::PrepareSearchAndReplace (void)
1244 : {
1245 0 : if (HasText( *mpSearchItem ))
1246 : {
1247 0 : mbStringFound = true;
1248 0 : mbMatchMayExist = true;
1249 :
1250 0 : EnterEditMode ();
1251 :
1252 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_False );
1253 : // Start seach at the right end of the current object's text
1254 : // depending on the search direction.
1255 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1256 0 : if (pOutlinerView != NULL)
1257 0 : pOutlinerView->SetSelection (GetSearchStartPosition ());
1258 : }
1259 0 : }
1260 :
1261 :
1262 :
1263 :
1264 0 : void Outliner::SetViewMode (PageKind ePageKind)
1265 : {
1266 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1267 : ::boost::shared_ptr<DrawViewShell> pDrawViewShell(
1268 0 : ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
1269 0 : if (pDrawViewShell.get()!=NULL && ePageKind != pDrawViewShell->GetPageKind())
1270 : {
1271 : // Restore old edit mode.
1272 0 : pDrawViewShell->ChangeEditMode(mpImpl->meOriginalEditMode, sal_False);
1273 :
1274 0 : SetStatusEventHdl(Link());
1275 0 : ::rtl::OUString sViewURL;
1276 0 : switch (ePageKind)
1277 : {
1278 : case PK_STANDARD:
1279 : default:
1280 0 : sViewURL = framework::FrameworkHelper::msImpressViewURL;
1281 0 : break;
1282 : case PK_NOTES:
1283 0 : sViewURL = framework::FrameworkHelper::msNotesViewURL;
1284 0 : break;
1285 : case PK_HANDOUT:
1286 0 : sViewURL = framework::FrameworkHelper::msHandoutViewURL;
1287 0 : break;
1288 : }
1289 : // The text object iterator is destroyed when the shells are
1290 : // switched but we need it so save it and restore it afterwards.
1291 0 : ::sd::outliner::Iterator aIterator (maObjectIterator);
1292 0 : bool bMatchMayExist = mbMatchMayExist;
1293 :
1294 0 : ViewShellBase& rBase = pViewShell->GetViewShellBase();
1295 0 : SetViewShell(::boost::shared_ptr<ViewShell>());
1296 : framework::FrameworkHelper::Instance(rBase)->RequestView(
1297 : sViewURL,
1298 0 : framework::FrameworkHelper::msCenterPaneURL);
1299 :
1300 : // Force (well, request) a synchronous update of the configuration.
1301 : // In a better world we would handle the asynchronous view update
1302 : // instead. But that would involve major restucturing of the
1303 : // Outliner code.
1304 0 : framework::FrameworkHelper::Instance(rBase)->RequestSynchronousUpdate();
1305 0 : SetViewShell(rBase.GetMainViewShell());
1306 :
1307 : // Switching to another view shell has intermediatly called
1308 : // EndSpelling(). A PrepareSpelling() is pending, so call that now.
1309 0 : PrepareSpelling();
1310 :
1311 : // Update the number of pages so that
1312 : // <member>DetectChange()</member> has the correct value to compare
1313 : // to.
1314 0 : mnPageCount = mpDrawDocument->GetSdPageCount(ePageKind);
1315 :
1316 0 : maObjectIterator = aIterator;
1317 0 : mbMatchMayExist = bMatchMayExist;
1318 :
1319 : // Save edit mode so that it can be restored when switching the view
1320 : // shell again.
1321 0 : pDrawViewShell = ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell);
1322 : OSL_ASSERT(pDrawViewShell.get()!=NULL);
1323 0 : if (pDrawViewShell.get() != NULL)
1324 0 : mpImpl->meOriginalEditMode = pDrawViewShell->GetEditMode();
1325 0 : }
1326 0 : }
1327 :
1328 :
1329 :
1330 :
1331 0 : void Outliner::SetPage (EditMode eEditMode, sal_uInt16 nPageIndex)
1332 : {
1333 0 : if ( ! mbRestrictSearchToSelection)
1334 : {
1335 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1336 : ::boost::shared_ptr<DrawViewShell> pDrawViewShell(
1337 0 : ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
1338 : OSL_ASSERT(pDrawViewShell.get()!=NULL);
1339 0 : if (pDrawViewShell.get() != NULL)
1340 : {
1341 0 : pDrawViewShell->ChangeEditMode(eEditMode, sal_False);
1342 0 : pDrawViewShell->SwitchPage(nPageIndex);
1343 0 : }
1344 : }
1345 0 : }
1346 :
1347 :
1348 :
1349 :
1350 0 : void Outliner::EnterEditMode (sal_Bool bGrabFocus)
1351 : {
1352 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1353 0 : if (pOutlinerView != NULL)
1354 : {
1355 0 : pOutlinerView->SetOutputArea( Rectangle( Point(), Size(1, 1)));
1356 0 : SetPaperSize( mpTextObj->GetLogicRect().GetSize() );
1357 0 : SdrPageView* pPV = mpView->GetSdrPageView();
1358 :
1359 : // Make FuText the current function.
1360 0 : SfxUInt16Item aItem (SID_TEXTEDIT, 1);
1361 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1362 0 : pViewShell->GetDispatcher()->
1363 : Execute(SID_TEXTEDIT, SFX_CALLMODE_SYNCHRON |
1364 0 : SFX_CALLMODE_RECORD, &aItem, 0L);
1365 :
1366 : // To be consistent with the usual behaviour in the Office the text
1367 : // object that is put into edit mode would have also to be selected.
1368 : // Starting the text edit mode is not enough so we do it here by
1369 : // hand.
1370 0 : mbExpectingSelectionChangeEvent = true;
1371 0 : mpView->UnmarkAllObj (pPV);
1372 0 : mpView->MarkObj (mpTextObj, pPV);
1373 :
1374 0 : if( mpTextObj )
1375 0 : mpTextObj->setActiveText( mnText );
1376 :
1377 : // Turn on the edit mode for the text object.
1378 0 : mpView->SdrBeginTextEdit(mpTextObj, pPV, mpWindow, sal_True, this, pOutlinerView, sal_True, sal_True, bGrabFocus);
1379 :
1380 0 : SetUpdateMode(sal_True);
1381 0 : mbFoundObject = sal_True;
1382 : }
1383 0 : }
1384 :
1385 :
1386 :
1387 :
1388 : /*************************************************************************
1389 : |*
1390 : |* SpellChecker: Error-LinkHdl
1391 : |*
1392 : \************************************************************************/
1393 :
1394 0 : IMPL_LINK_INLINE_START( Outliner, SpellError, void *, nLang )
1395 : {
1396 0 : mbError = true;
1397 0 : String aError( SvtLanguageTable::GetLanguageString( (LanguageType)(sal_uLong)nLang ) );
1398 : ErrorHandler::HandleError(* new StringErrorInfo(
1399 0 : ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aError) );
1400 0 : return 0;
1401 : }
1402 0 : IMPL_LINK_INLINE_END( Outliner, SpellError, void *, nLang )
1403 :
1404 :
1405 :
1406 :
1407 0 : ESelection Outliner::GetSearchStartPosition (void)
1408 : {
1409 0 : ESelection aPosition;
1410 0 : if (mbDirectionIsForward)
1411 : {
1412 : // The default constructor uses the beginning of the text as default.
1413 0 : aPosition = ESelection ();
1414 : }
1415 : else
1416 : {
1417 : // Retrieve the position after the last character in the last
1418 : // paragraph.
1419 0 : sal_uInt16 nParagraphCount = static_cast<sal_uInt16>(GetParagraphCount());
1420 0 : if (nParagraphCount == 0)
1421 0 : aPosition = ESelection();
1422 : else
1423 : {
1424 0 : xub_StrLen nLastParagraphLength = GetEditEngine().GetTextLen (
1425 0 : nParagraphCount-1);
1426 0 : aPosition = ESelection (nParagraphCount-1, nLastParagraphLength);
1427 : }
1428 : }
1429 :
1430 0 : return aPosition;
1431 : }
1432 :
1433 :
1434 :
1435 :
1436 0 : bool Outliner::HasNoPreviousMatch (void)
1437 : {
1438 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1439 :
1440 : DBG_ASSERT (pOutlinerView!=NULL, "outline view in Outliner::HasNoPreviousMatch is NULL");
1441 :
1442 : // Detect whether the cursor stands at the beginning
1443 : // resp. at the end of the text.
1444 0 : return pOutlinerView->GetSelection().IsEqual(GetSearchStartPosition ()) == sal_True;
1445 : }
1446 :
1447 :
1448 :
1449 :
1450 0 : bool Outliner::HandleFailedSearch (void)
1451 : {
1452 0 : bool bContinueSearch = false;
1453 :
1454 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1455 0 : if (pOutlinerView != NULL && mpSearchItem != NULL)
1456 : {
1457 : // Detect whether there is/may be a prior match. If there is then
1458 : // ask the user whether to wrap arround. Otherwise tell the user
1459 : // that there is no match.
1460 0 : if (HasNoPreviousMatch ())
1461 : {
1462 : // No match found in the whole presentation. Tell the user.
1463 : InfoBox aInfoBox (NULL,
1464 0 : String(SdResId(STR_SAR_NOT_FOUND)));
1465 0 : ShowModalMessageBox (aInfoBox);
1466 : }
1467 :
1468 : else
1469 : {
1470 : // No further matches found. Ask the user whether to wrap
1471 : // arround and start again.
1472 0 : bContinueSearch = ShowWrapArroundDialog ();
1473 : }
1474 : }
1475 :
1476 0 : return bContinueSearch;
1477 : }
1478 :
1479 :
1480 0 : SdrObject* Outliner::SetObject (
1481 : const ::sd::outliner::IteratorPosition& rPosition)
1482 : {
1483 0 : SetViewMode (rPosition.mePageKind);
1484 0 : SetPage (rPosition.meEditMode, (sal_uInt16)rPosition.mnPageIndex);
1485 0 : mnText = rPosition.mnText;
1486 0 : return rPosition.mxObject.get();
1487 : }
1488 :
1489 :
1490 :
1491 :
1492 0 : void Outliner::SetViewShell (const ::boost::shared_ptr<ViewShell>& rpViewShell)
1493 : {
1494 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1495 0 : if (pViewShell != rpViewShell)
1496 : {
1497 : // Set the new view shell.
1498 0 : mpWeakViewShell = rpViewShell;
1499 : // When the outline view is not owned by us then we have to clear
1500 : // that pointer so that the current one for the new view shell will
1501 : // be used (in ProvideOutlinerView).
1502 0 : if (rpViewShell)
1503 : {
1504 0 : mpView = rpViewShell->GetView();
1505 :
1506 0 : mpWindow = rpViewShell->GetActiveWindow();
1507 :
1508 0 : mpImpl->ProvideOutlinerView(*this, rpViewShell, mpWindow);
1509 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1510 0 : if (pOutlinerView != NULL)
1511 0 : pOutlinerView->SetWindow(mpWindow);
1512 : }
1513 : else
1514 : {
1515 0 : mpView = NULL;
1516 0 : mpWindow = NULL;
1517 : }
1518 0 : }
1519 0 : }
1520 :
1521 :
1522 :
1523 :
1524 0 : void Outliner::HandleChangedSelection (void)
1525 : {
1526 0 : maMarkListCopy.clear();
1527 0 : mbRestrictSearchToSelection = (mpView->AreObjectsMarked()==sal_True);
1528 0 : if (mbRestrictSearchToSelection)
1529 : {
1530 : // Make a copy of the current mark list.
1531 0 : const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
1532 0 : sal_uLong nCount = rMarkList.GetMarkCount();
1533 0 : if (nCount > 0)
1534 : {
1535 0 : maMarkListCopy.clear();
1536 0 : maMarkListCopy.reserve (nCount);
1537 0 : for (sal_uLong i=0; i<nCount; i++)
1538 0 : maMarkListCopy.push_back (rMarkList.GetMark(i)->GetMarkedSdrObj ());
1539 : }
1540 : else
1541 : // No marked object. Is this case possible?
1542 0 : mbRestrictSearchToSelection = false;
1543 : }
1544 0 : }
1545 :
1546 :
1547 :
1548 :
1549 :
1550 0 : void Outliner::StartConversion( sal_Int16 nSourceLanguage, sal_Int16 nTargetLanguage,
1551 : const Font *pTargetFont, sal_Int32 nOptions, sal_Bool bIsInteractive )
1552 : {
1553 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1554 0 : sal_Bool bMultiDoc = pViewShell->ISA(DrawViewShell);
1555 :
1556 0 : meMode = TEXT_CONVERSION;
1557 0 : mbDirectionIsForward = true;
1558 0 : mpSearchItem = NULL;
1559 0 : mnConversionLanguage = nSourceLanguage;
1560 :
1561 0 : BeginConversion();
1562 :
1563 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1564 0 : if (pOutlinerView != NULL)
1565 : {
1566 : pOutlinerView->StartTextConversion(
1567 : nSourceLanguage,
1568 : nTargetLanguage,
1569 : pTargetFont,
1570 : nOptions,
1571 : bIsInteractive,
1572 0 : bMultiDoc);
1573 : }
1574 :
1575 0 : EndConversion();
1576 0 : }
1577 :
1578 :
1579 :
1580 :
1581 : /** Prepare to do a text conversion on the current text object. This
1582 : includes putting it into edit mode.
1583 : */
1584 0 : void Outliner::PrepareConversion (void)
1585 : {
1586 0 : SetUpdateMode(sal_True);
1587 0 : if( HasConvertibleTextPortion( mnConversionLanguage ) )
1588 : {
1589 0 : SetUpdateMode(sal_False);
1590 0 : mbStringFound = sal_True;
1591 0 : mbMatchMayExist = sal_True;
1592 :
1593 0 : EnterEditMode ();
1594 :
1595 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_False );
1596 : // Start seach at the right end of the current object's text
1597 : // depending on the search direction.
1598 : }
1599 : else
1600 : {
1601 0 : SetUpdateMode(sal_False);
1602 : }
1603 0 : }
1604 :
1605 :
1606 :
1607 :
1608 0 : void Outliner::BeginConversion (void)
1609 : {
1610 0 : SetRefDevice( SD_MOD()->GetRefDevice( *mpDrawDocument->GetDocSh() ) );
1611 :
1612 0 : ViewShellBase* pBase = PTR_CAST(ViewShellBase, SfxViewShell::Current());
1613 0 : if (pBase != NULL)
1614 0 : SetViewShell (pBase->GetMainViewShell());
1615 :
1616 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1617 0 : if (pViewShell)
1618 : {
1619 0 : mbStringFound = sal_False;
1620 :
1621 : // Supposed that we are not located at the very beginning/end of the
1622 : // document then there may be a match in the document prior/after
1623 : // the current position.
1624 0 : mbMatchMayExist = sal_True;
1625 :
1626 0 : maObjectIterator = ::sd::outliner::Iterator();
1627 0 : maSearchStartPosition = ::sd::outliner::Iterator();
1628 0 : RememberStartPosition();
1629 :
1630 0 : mpImpl->ProvideOutlinerView(*this, pViewShell, mpWindow);
1631 :
1632 0 : HandleChangedSelection ();
1633 : }
1634 0 : ClearModifyFlag();
1635 0 : }
1636 :
1637 :
1638 :
1639 :
1640 0 : void Outliner::EndConversion()
1641 : {
1642 0 : EndSpelling();
1643 0 : }
1644 :
1645 :
1646 :
1647 :
1648 0 : sal_Bool Outliner::ConvertNextDocument()
1649 : {
1650 0 : ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1651 0 : if (pViewShell && pViewShell->ISA(OutlineViewShell) )
1652 0 : return false;
1653 :
1654 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_True );
1655 :
1656 0 : Initialize ( true );
1657 :
1658 0 : OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1659 0 : if (pOutlinerView != NULL)
1660 : {
1661 0 : mpWindow = pViewShell->GetActiveWindow();
1662 0 : pOutlinerView->SetWindow(mpWindow);
1663 : }
1664 0 : ProvideNextTextObject ();
1665 :
1666 0 : mpDrawDocument->GetDocSh()->SetWaitCursor( sal_False );
1667 0 : ClearModifyFlag();
1668 :
1669 : // for text conversion we automaticly wrap around one
1670 : // time and stop at the start shape
1671 0 : if( mpFirstObj )
1672 : {
1673 0 : if( (mnText == 0) && (mpFirstObj == mpObj) )
1674 0 : return false;
1675 : }
1676 : else
1677 : {
1678 0 : mpFirstObj = mpObj;
1679 : }
1680 :
1681 0 : return !mbEndOfSearch;
1682 : }
1683 :
1684 :
1685 :
1686 :
1687 0 : sal_uInt16 Outliner::ShowModalMessageBox (Dialog& rMessageBox)
1688 : {
1689 : // We assume that the parent of the given messge box is NULL, i.e. it is
1690 : // modal with respect to the top application window. However, this
1691 : // does not affect the search dialog. Therefore we have to lock it here
1692 : // while the message box is being shown. We also have to take into
1693 : // account that we are called during a spell check and the search dialog
1694 : // is not available.
1695 0 : ::Window* pSearchDialog = NULL;
1696 0 : SfxChildWindow* pChildWindow = NULL;
1697 0 : switch (meMode)
1698 : {
1699 : case SEARCH:
1700 : pChildWindow = SfxViewFrame::Current()->GetChildWindow(
1701 0 : SvxSearchDialogWrapper::GetChildWindowId());
1702 0 : break;
1703 :
1704 : case SPELL:
1705 : pChildWindow = SfxViewFrame::Current()->GetChildWindow(
1706 0 : SpellDialogChildWindow::GetChildWindowId());
1707 0 : break;
1708 :
1709 : case TEXT_CONVERSION:
1710 : // There should no messages boxes be displayed while doing the
1711 : // hangul hanja conversion.
1712 0 : break;
1713 : }
1714 :
1715 0 : if (pChildWindow != NULL)
1716 0 : pSearchDialog = pChildWindow->GetWindow();
1717 0 : if (pSearchDialog != NULL)
1718 0 : pSearchDialog->EnableInput(sal_False,sal_True);
1719 :
1720 0 : sal_uInt16 nResult = rMessageBox.Execute();
1721 :
1722 : // Unlock the search dialog.
1723 0 : if (pSearchDialog != NULL)
1724 0 : pSearchDialog->EnableInput(sal_True,sal_True);
1725 :
1726 0 : return nResult;
1727 : }
1728 :
1729 :
1730 :
1731 :
1732 : //===== Outliner::Implementation ==============================================
1733 :
1734 11 : Outliner::Implementation::Implementation (void)
1735 : : meOriginalEditMode(EM_PAGE),
1736 : mbOwnOutlineView(false),
1737 11 : mpOutlineView(NULL)
1738 : {
1739 11 : }
1740 :
1741 :
1742 :
1743 :
1744 9 : Outliner::Implementation::~Implementation (void)
1745 : {
1746 9 : if (mbOwnOutlineView && mpOutlineView!=NULL)
1747 : {
1748 0 : mpOutlineView->SetWindow(NULL);
1749 0 : delete mpOutlineView;
1750 0 : mpOutlineView = NULL;
1751 : }
1752 9 : }
1753 :
1754 :
1755 :
1756 :
1757 0 : OutlinerView* Outliner::Implementation::GetOutlinerView ()
1758 : {
1759 0 : return mpOutlineView;
1760 : }
1761 :
1762 :
1763 :
1764 :
1765 : /** We try to create a new OutlinerView only when there is none available,
1766 : either from an OutlinerViewShell or a previous call to
1767 : ProvideOutlinerView(). This is necessary to support the spell checker
1768 : which can not cope with exchanging the OutlinerView.
1769 : */
1770 0 : void Outliner::Implementation::ProvideOutlinerView (
1771 : Outliner& rOutliner,
1772 : const ::boost::shared_ptr<ViewShell>& rpViewShell,
1773 : ::Window* pWindow)
1774 : {
1775 0 : if (rpViewShell.get() != NULL)
1776 : {
1777 0 : switch (rpViewShell->GetShellType())
1778 : {
1779 : case ViewShell::ST_DRAW:
1780 : case ViewShell::ST_IMPRESS:
1781 : case ViewShell::ST_NOTES:
1782 : case ViewShell::ST_HANDOUT:
1783 : {
1784 : // Create a new outline view to do the search on.
1785 0 : bool bInsert = false;
1786 0 : if (mpOutlineView!=NULL && !mbOwnOutlineView)
1787 0 : mpOutlineView = NULL;
1788 0 : if (mpOutlineView == NULL)
1789 : {
1790 0 : mpOutlineView = new OutlinerView(&rOutliner, pWindow);
1791 0 : mbOwnOutlineView = true;
1792 0 : bInsert = true;
1793 : }
1794 : else
1795 0 : mpOutlineView->SetWindow(pWindow);
1796 0 : sal_uLong nStat = mpOutlineView->GetControlWord();
1797 0 : nStat &= ~EV_CNTRL_AUTOSCROLL;
1798 0 : mpOutlineView->SetControlWord(nStat);
1799 0 : if (bInsert)
1800 0 : rOutliner.InsertView( mpOutlineView );
1801 0 : rOutliner.SetUpdateMode(sal_False);
1802 0 : mpOutlineView->SetOutputArea (Rectangle (Point(), Size(1, 1)));
1803 0 : rOutliner.SetPaperSize( Size(1, 1) );
1804 0 : rOutliner.SetText( String(), rOutliner.GetParagraph( 0 ) );
1805 :
1806 : meOriginalEditMode =
1807 0 : ::boost::static_pointer_cast<DrawViewShell>(rpViewShell)->GetEditMode();
1808 : }
1809 0 : break;
1810 :
1811 : case ViewShell::ST_OUTLINE:
1812 : {
1813 0 : if (mpOutlineView!=NULL && mbOwnOutlineView)
1814 0 : delete mpOutlineView;
1815 0 : mpOutlineView = rOutliner.GetView(0);
1816 0 : mbOwnOutlineView = false;
1817 : }
1818 0 : break;
1819 :
1820 : default:
1821 : case ViewShell::ST_NONE:
1822 : case ViewShell::ST_PRESENTATION:
1823 : // Ignored
1824 0 : break;
1825 : }
1826 : }
1827 0 : }
1828 :
1829 :
1830 :
1831 :
1832 0 : void Outliner::Implementation::ReleaseOutlinerView (void)
1833 : {
1834 0 : if (mbOwnOutlineView)
1835 : {
1836 0 : OutlinerView* pView = mpOutlineView;
1837 0 : mpOutlineView = NULL;
1838 0 : mbOwnOutlineView = false;
1839 0 : if (pView != NULL)
1840 : {
1841 0 : pView->SetWindow(NULL);
1842 0 : delete pView;
1843 : }
1844 : }
1845 : else
1846 : {
1847 0 : mpOutlineView = NULL;
1848 : }
1849 0 : }
1850 :
1851 9 : } // end of namespace sd
1852 :
1853 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|