diff options
author | Oliver Bolte <obo@openoffice.org> | 2004-01-20 11:38:49 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2004-01-20 11:38:49 +0000 |
commit | 94ab3f5bd87c0defe431e2573a04851ccd488311 (patch) | |
tree | 1728b62cc7853d1e69213fe7b6312f8a611ed218 | |
parent | ab81f236db0363d2b97a46bded65f3caa627907b (diff) |
INTEGRATION: CWS impress1 (1.1.2); FILE ADDED
2004/01/09 16:32:39 af 1.1.2.3: #111996# Renamed header files DrawView.hxx, Fader.hxx, and ShowView.hxx back to lowercase version.
2003/10/06 08:16:48 af 1.1.2.2: #111996# Adapted Outliner to new view shell architecture.
2003/09/17 08:59:34 af 1.1.2.1: #111996# Renamed from sdoutl.cxx.
-rw-r--r-- | sd/source/ui/view/Outliner.cxx | 1454 |
1 files changed, 1454 insertions, 0 deletions
diff --git a/sd/source/ui/view/Outliner.cxx b/sd/source/ui/view/Outliner.cxx new file mode 100644 index 000000000000..70bf6d491996 --- /dev/null +++ b/sd/source/ui/view/Outliner.cxx @@ -0,0 +1,1454 @@ +/************************************************************************* + * + * $RCSfile: Outliner.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: obo $ $Date: 2004-01-20 12:38:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include "Outliner.hxx" + +#ifndef _SV_WRKWIN_HXX +#include <vcl/wrkwin.hxx> +#endif +#ifndef _EEITEMID_HXX //autogen +#include <svx/eeitemid.hxx> +#endif +#ifndef _SVX_FONTITEM_HXX //autogen +#include <svx/fontitem.hxx> +#endif +#ifndef _SVX_FHGTITEM_HXX //autogen +#include <svx/fhgtitem.hxx> +#endif +#ifdef ITEMID_SEARCH +#undef ITEMID_SEARCH +#endif +#define ITEMID_SEARCH SID_SEARCH_ITEM +#ifndef _SVXIDS_HRC +#include <svx/svxids.hrc> +#endif +#ifndef _SRCHITEM_HXX +#include <svx/srchitem.hxx> +#endif +#ifndef _OSPLCFG_HXX +#include <offmgr/osplcfg.hxx> +#endif +#ifndef _SVX_COLRITEM_HXX //autogen +#include <svx/colritem.hxx> +#endif +#ifndef _EEITEM_HXX //autogen +#include <svx/eeitem.hxx> +#endif +#ifndef _EDITSTAT_HXX //autogen +#include <svx/editstat.hxx> +#endif +#ifndef _SV_OUTDEV_HXX //autogen +#include <vcl/outdev.hxx> +#endif +#ifndef _DLGUTIL_HXX +#include <svx/dlgutil.hxx> +#endif +#ifndef _XTABLE_HXX +#include <svx/xtable.hxx> +#endif +#ifndef _SV_MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#ifndef _SFXDISPATCH_HXX //autogen +#include <sfx2/dispatch.hxx> +#endif +#ifndef _SFX_PRINTER_HXX //autogen +#include <sfx2/printer.hxx> +#endif +#ifndef _SVXERR_HXX //autogen +#include <svx/svxerr.hxx> +#endif +#ifndef _SVDOTEXT_HXX //autogen +#include <svx/svdotext.hxx> +#endif +#ifndef _UNO_LINGU_HXX +#include <svx/unolingu.hxx> +#endif +#ifndef _OFFAPP_HXX //autogen +#include <offmgr/app.hxx> +#endif +#ifndef _SVDITER_HXX //autogen +#include <svx/svditer.hxx> +#endif +#include <comphelper/extract.hxx> +#ifndef _COM_SUN_STAR_LINGUISTIC2_XSPELLCHECKER1_HPP_ +#include <com/sun/star/linguistic2/XSpellChecker1.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COMPHELPER_PROCESSFACTORY_HXX_ +#include <comphelper/processfactory.hxx> +#endif +#ifndef _EEITEM_HXX +#include <svx/eeitem.hxx> +#endif +#ifndef _FORBIDDENCHARACTERSTABLE_HXX +#include <svx/forbiddencharacterstable.hxx> +#endif +#ifndef _SVX_SRCHDLG_HXX +#include <svx/srchdlg.hxx> +#endif +#ifndef _SVTOOLS_LINGUPROPS_HXX_ +#include <svtools/linguprops.hxx> +#endif +#ifndef _SVTOOLS_LINGUCFG_HXX_ +#include <svtools/lingucfg.hxx> +#endif +#ifndef _MyEDITENG_HXX +#include <svx/editeng.hxx> +#endif + +#include "strings.hrc" +#include "sdstring.hrc" +#include "eetext.hxx" +#include "sdpage.hxx" +#include "app.hxx" +#ifndef SD_WINDOW_HXX +#include "Window.hxx" +#endif +#include "sdresid.hxx" +#ifndef SD_DRAW_VIEW_SHELL_HXX +#include "DrawViewShell.hxx" +#endif +#ifndef SD_OUTLINE_VIEW_SHELL_HXX +#include "OutlineViewShell.hxx" +#endif +#include "drawdoc.hxx" +#include "DrawDocShell.hxx" +#ifndef SD_FRAME_VIEW_HXX +#include "FrameView.hxx" +#endif +#include "optsitem.hxx" +#ifndef SD_DRAW_VIEW_HXX +#include "drawview.hxx" +#endif +#ifndef SD_VIEW_SHELL_BASE_HXX +#include "ViewShellBase.hxx" +#endif + + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::linguistic2; + +class SfxStyleSheetPool; + +namespace sd { + +/************************************************************************* +|* +|* Ctor +|* +\************************************************************************/ + +Outliner::Outliner( SdDrawDocument* pDoc, USHORT nMode ) + : SdrOutliner( &pDoc->GetItemPool(), nMode ), + mpDrawDocument(pDoc), + mbOwnOutlineView(false), + mpOutlineView(NULL), + mpViewShell(NULL), + mpView(NULL), + mbStringFound(FALSE), + mbEndOfSearch(FALSE), + mbFoundObject(FALSE), + mbError(FALSE), + mbDirectionIsForward(true), + mbRestrictSearchToSelection(false), + mpObj(NULL), + mpTextObj(NULL), + mpParaObj(NULL), + mpSearchItem(NULL) +{ + SetStyleSheetPool((SfxStyleSheetPool*) mpDrawDocument->GetStyleSheetPool()); + SetEditTextObjectPool( &pDoc->GetItemPool() ); + SetCalcFieldValueHdl(LINK(SD_MOD(), SdModule, CalcFieldValueHdl)); + SetForbiddenCharsTable( pDoc->GetForbiddenCharsTable() ); + + ULONG nCntrl = GetControlWord(); + nCntrl |= EE_CNTRL_ALLOWBIGOBJS; + nCntrl |= EE_CNTRL_URLSFXEXECUTE; + nCntrl |= EE_CNTRL_MARKFIELDS; + nCntrl |= EE_CNTRL_AUTOCORRECT; + + BOOL bHideSpell = TRUE; + BOOL bOnlineSpell = FALSE; + + DrawDocShell* pDocSh = mpDrawDocument->GetDocSh(); + + if (pDocSh) + { + bHideSpell = mpDrawDocument->GetHideSpell(); + bOnlineSpell = mpDrawDocument->GetOnlineSpell(); + } + else + { + bHideSpell = sal_True; + bOnlineSpell = sal_False; + + try + { + const SvtLinguConfig aLinguConfig; + Any aAny; + + aAny = aLinguConfig.GetProperty( rtl::OUString::createFromAscii( UPN_IS_SPELL_HIDE ) ); + aAny >>= bHideSpell; + + aAny = aLinguConfig.GetProperty( rtl::OUString::createFromAscii( UPN_IS_SPELL_AUTO ) ); + aAny >>= bOnlineSpell; + } + catch( ... ) + { + DBG_ERROR( "Ill. type in linguistic property" ); + } + } + + if (bHideSpell) + nCntrl |= EE_CNTRL_NOREDLINES; else + nCntrl &= ~EE_CNTRL_NOREDLINES; + + if (bOnlineSpell) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + + SetControlWord(nCntrl); + + Reference< XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() ); + if ( xSpellChecker.is() ) + SetSpeller( xSpellChecker ); + + Reference< XHyphenator > xHyphenator( LinguMgr::GetHyphenator() ); + if( xHyphenator.is() ) + SetHyphenator( xHyphenator ); + + SetDefaultLanguage( Application::GetSettings().GetLanguage() ); +} + + + + +/// Nothing spectecular in the destructor. +Outliner::~Outliner (void) +{} + + + + +/** Prepare find&replace or spellchecking. This distinguishes between three + cases: + <ol> + <li>The current shell is a <type>DrawViewShell</type>: Create a + <type>OutlinerView</type> object and search all objects of (i) the + current mark list, (ii) of the current view, or (iii) of all the view + combinations: + <ol> + <li>Draw view, slide view</li> + <li>Draw view, background view</li> + <li>Notes view, slide view</li> + <li>Notes view, background view</li> + <li>Handout view, slide view</li> + <li>Handout view, background view</li> + </ol> + + <li>When the current shell is a <type>SdOutlineViewShell</type> then + directly operate on it. No switching into other views takes place.</li> + + <li>For a <type>SlideViewShell</type> no action is performed.</li> + </ol> +*/ +void Outliner::PrepareSpelling (void) +{ + SetRefDevice( SD_MOD()->GetRefDevice( *mpDrawDocument->GetDocSh() ) ); + + ViewShellBase* pBase = PTR_CAST(ViewShellBase, SfxViewShell::Current()); + if (pBase != NULL) + SetViewShell (pBase->GetSubShellManager().GetMainSubShell()); + + if (mpViewShell != NULL) + { + mbStringFound = FALSE; + + // Supposed that we are not located at the very beginning/end of the + // document then there may be a match in the document prior/after + // the current position. + mbMatchMayExist = TRUE; + + maObjectIterator = ::sd::outliner::Iterator(); + maSearchStartPosition = ::sd::outliner::Iterator(); + RememberStartPosition(); + + if (mpViewShell->ISA(DrawViewShell)) + { + // Create a new outline view to do the search on. + mpOutlineView = new OutlinerView( this, mpWindow ); + mbOwnOutlineView = true; + ULONG nStat = mpOutlineView->GetControlWord(); + nStat &= ~EV_CNTRL_AUTOSCROLL; + mpOutlineView->SetControlWord(nStat); + InsertView( mpOutlineView ); + SetUpdateMode(FALSE); + mpOutlineView->SetOutputArea( Rectangle( Point(), Size(1, 1) ) ); + SetPaperSize( Size(1, 1) ); + SetText( String(), GetParagraph( 0 ) ); + + meOriginalEditMode = + static_cast<DrawViewShell*>(mpViewShell)->GetEditMode(); + } + else if (mpViewShell->ISA(OutlineViewShell)) + { + mpOutlineView = GetView(0); + mbOwnOutlineView = false; + } + // else do nothing. + + HandleChangedSelection (); + } + ClearModifyFlag(); +} + + + + +/************************************************************************* +|* +|* Spelling: Pruefung starten +|* +\************************************************************************/ + +void Outliner::StartSpelling (void) +{ + BOOL bMultiDoc = FALSE; + meMode = SPELL; + mbDirectionIsForward = true; + mpSearchItem = NULL; + + // InitPage (mnStartPageIndex); + + if (mpViewShell->ISA(DrawViewShell)) + bMultiDoc = TRUE; + + EESpellState eState = mpOutlineView->StartSpeller( bMultiDoc ); + + if (bMultiDoc) + { + ESelection aSelection; + mpOutlineView->SetSelection(aSelection); + mpView->UnmarkAllObj (mpView->GetPageViewPvNum(0)); + mpView->EndTextEdit(); + } + + // Restore the start position before displaying a dialog. + RestoreStartPosition (); + + if (eState == EE_SPELL_NOLANGUAGE) + { + ::Window* pParent=GetParentForDialog(); + ErrorBox (pParent, + WB_OK, + String(SdResId(STR_NOLANGUAGE))).Execute(); + } + else + { + ::Window* pParent=GetParentForDialog(); + if (mpView->HasMarkedObj()) + { + InfoBox(pParent, + String(SdResId(STR_END_SPELLING_OBJ))).Execute(); + } + else + { + InfoBox(pParent, + String(SdResId(STR_END_SPELLING))).Execute(); + } + } +} + + + + +/** Free all resources acquired during the search/spell check. After a + spell check the start position is restored here. +*/ +void Outliner::EndSpelling (void) +{ + ViewShellBase* pBase = PTR_CAST(ViewShellBase, SfxViewShell::Current()); + if (pBase != NULL) + mpViewShell = pBase->GetSubShellManager().GetMainSubShell(); + else + mpViewShell = NULL; + + // When in <member>PrepareSpelling()</member> a new outline view has been + // created then delete it here. + sal_Bool bViewIsDrawViewShell(mpViewShell!=NULL + && mpViewShell->ISA(DrawViewShell)); + if (bViewIsDrawViewShell) + { + SetStatusEventHdl(Link()); + mpView = mpViewShell->GetView(); + mpView->UnmarkAllObj (mpView->GetPageViewPvNum(0)); + mpView->EndTextEdit(); + // Make FuSelection the current function. + mpViewShell->GetDispatcher()->Execute( + SID_OBJECT_SELECT, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD); + + // Remove and, if previously created by us, delete the outline view. + RemoveView( mpOutlineView ); + if (mbOwnOutlineView) + delete mpOutlineView; + + SetUpdateMode(TRUE); + } + + // #95811# Before clearing the modify flag use it as a hint that + // changes were done at SpellCheck + if(IsModified()) + { + if(mpView && mpView->ISA(OutlineView)) + static_cast<OutlineView*>(mpView)->PrepareClose(FALSE); + if(mpDrawDocument && !mpDrawDocument->IsChanged()) + mpDrawDocument->SetChanged(TRUE); + } + + // #95811# now clear the modify flag to have a specified state of Outliner + ClearModifyFlag(); + + // When spell checking then restore the start position. + if (meMode == SPELL) + RestoreStartPosition (); + + mpViewShell = NULL; + mpView = NULL; + mpWindow = NULL; + mpOutlineView = NULL; +} + + + + +/************************************************************************* +|* +|* Spelling: naechstes TextObjekt pruefen +|* +\************************************************************************/ + +BOOL Outliner::SpellNextDocument (void) +{ + mpDrawDocument->GetDocSh()->SetWaitCursor( TRUE ); + + // Extract the search direction. + BOOL bBackwards = FALSE; + Reference<beans::XPropertySet> xProperties (SvxGetLinguPropertySet()); + if (xProperties.is()) + { + Any aValue = xProperties->getPropertyValue(OUString( + RTL_CONSTASCII_USTRINGPARAM(UPN_IS_WRAP_REVERSE))); + aValue >>= bBackwards; + } + + Initialize ( ! bBackwards); + + mpWindow = mpViewShell->GetActiveWindow(); + mpOutlineView->SetWindow(mpWindow); + ProvideNextTextObject (); + + mpDrawDocument->GetDocSh()->SetWaitCursor( FALSE ); + ClearModifyFlag(); + + return !mbEndOfSearch; +} + + + + +/** Go to next match. +*/ +BOOL Outliner::StartSearchAndReplace (const SvxSearchItem* pSearchItem) +{ + mpDrawDocument->GetDocSh()->SetWaitCursor( TRUE ); + ViewShellBase* pBase = PTR_CAST(ViewShellBase, SfxViewShell::Current()); + if (pBase != NULL) + SetViewShell (pBase->GetSubShellManager().GetMainSubShell()); + + meMode = SEARCH; + mpSearchItem = pSearchItem; + + mbFoundObject = FALSE; + + Initialize ( ! mpSearchItem->GetBackward()); + + USHORT nCommand = mpSearchItem->GetCommand(); + BOOL bEndOfSearch; + if (nCommand == SVX_SEARCHCMD_REPLACE_ALL) + bEndOfSearch = SearchAndReplaceAll (); + else + { + RememberStartPosition (); + bEndOfSearch = SearchAndReplaceOnce (); + //#107233# restore start position if nothing was found + if(!mbStringFound) + RestoreStartPosition (); + else + mnStartPageIndex = -1; + } + return bEndOfSearch; +} + + + + +void Outliner::Initialize (bool bDirectionIsForward) +{ + bool bOldDirectionIsForward = mbDirectionIsForward; + mbDirectionIsForward = bDirectionIsForward; + + if (maObjectIterator == ::sd::outliner::Iterator()) + { + // Initialize a new search. + maObjectIterator = ::sd::outliner::OutlinerContainer(this).current(); + maCurrentPosition = *maObjectIterator; + + // In case we are searching in an outline view then first remove the + // current selection and place cursor at its start or end. + if (mpViewShell->ISA(OutlineViewShell)) + { + ESelection aSelection = mpOutlineView->GetSelection (); + if (mbDirectionIsForward) + { + aSelection.nEndPara = aSelection.nStartPara; + aSelection.nEndPos = aSelection.nStartPos; + } + else + { + aSelection.nStartPara = aSelection.nEndPara; + aSelection.nStartPos = aSelection.nEndPos; + } + mpOutlineView->SetSelection (aSelection); + } + + // When not beginning the search at the beginning of the search area + // then there may be matches before the current position. + mbMatchMayExist = (maObjectIterator!=::sd::outliner::OutlinerContainer(this).begin()); + } + else if (bOldDirectionIsForward != mbDirectionIsForward) + { + // Requested iteration direction has changed. Turn arround the iterator. + maObjectIterator.Reverse(); + // The iterator has pointed to the object one ahead/before the current + // one. Now move it to the one before/ahead the current one. + ++maObjectIterator; + ++maObjectIterator; + + mbMatchMayExist = true; + } +} + + + + +BOOL Outliner::SearchAndReplaceAll (void) +{ + // Save the current position to be restored after having replaced all + // matches. + RememberStartPosition (); + + if (mpViewShell->ISA(OutlineViewShell)) + { + // Put the cursor to the beginning/end of the outliner. + mpOutlineView->SetSelection (GetSearchStartPosition ()); + + // The outliner does all the work for us when we are in this mode. + SearchAndReplaceOnce(); + } + else if (mpViewShell->ISA(DrawViewShell)) + { + // Go to beginning/end of document. + maObjectIterator = ::sd::outliner::OutlinerContainer(this).begin(); + // Switch to the current object only if it is a valid text object. + ::sd::outliner::IteratorPosition aNewPosition (*maObjectIterator); + if (IsValidTextObject (aNewPosition)) + { + maCurrentPosition = aNewPosition; + SetObject (maCurrentPosition); + } + + // Search/replace until the end of the document is reached. + bool bFoundMatch; + do + { + bFoundMatch = ! SearchAndReplaceOnce(); + } + while (bFoundMatch); + } + + RestoreStartPosition (); + + return TRUE; +} + + + + +BOOL Outliner::SearchAndReplaceOnce (void) +{ + DetectChange (); + + DBG_ASSERT( mpOutlineView && GetEditEngine().HasView( &mpOutlineView->GetEditView() ), "SearchAndReplace without valid view!" ); + + if( NULL == mpOutlineView || !GetEditEngine().HasView( &mpOutlineView->GetEditView() ) ) + return true; + + if (mpViewShell != NULL) + { + mpView = mpViewShell->GetView(); + mpWindow = mpViewShell->GetActiveWindow(); + DBG_ASSERT (mpOutlineView!=NULL, "Outliner::SearchAndReplaceOnce(): mpOutlineView!=NULL"); + mpOutlineView->SetWindow(mpWindow); + + if (mpViewShell->ISA(DrawViewShell) ) + { + // When replacing we first check if there is a selection + // indicating a match. If there is then replace it. The + // following call to StartSearchAndReplace will then search for + // the next match. + if (meMode == SEARCH + && mpSearchItem->GetCommand() == SVX_SEARCHCMD_REPLACE) + if (mpOutlineView != NULL) + if (mpOutlineView->GetSelection().HasRange()) + mpOutlineView->StartSearchAndReplace(*mpSearchItem); + + // Search for the next match. + ULONG nMatchCount = 0; + if (mpSearchItem->GetCommand() != SVX_SEARCHCMD_REPLACE_ALL) + nMatchCount = mpOutlineView->StartSearchAndReplace(*mpSearchItem); + + // Go to the next text object when there have been no matches in + // the current object or the whole object has already been + // processed. + if (nMatchCount==0 || mpSearchItem->GetCommand()==SVX_SEARCHCMD_REPLACE_ALL) + { + ProvideNextTextObject (); + + if ( ! mbEndOfSearch) + { + // Now that the mbEndOfSearch flag guards this block the + // following assertion and return should not be + // necessary anymore. + DBG_ASSERT( mpOutlineView && GetEditEngine().HasView( + &mpOutlineView->GetEditView() ), "SearchAndReplace without valid view!" ); + if( NULL == mpOutlineView + || !GetEditEngine().HasView( &mpOutlineView->GetEditView() ) ) + { + mpDrawDocument->GetDocSh()->SetWaitCursor( FALSE ); + return true; + } + + if (meMode == SEARCH) + nMatchCount = mpOutlineView->StartSearchAndReplace(*mpSearchItem); + } + } + } + else if (mpViewShell->ISA(OutlineViewShell)) + { + mpDrawDocument->GetDocSh()->SetWaitCursor (FALSE); + // The following loop is executed more then once only when a + // wrap arround search is done. + while (true) + { + int nResult = mpOutlineView->StartSearchAndReplace(*mpSearchItem); + if (nResult == 0) + { + if (HandleFailedSearch ()) + if (mpOutlineView != NULL) + { + mpOutlineView->SetSelection (GetSearchStartPosition ()); + continue; + } + } + else + mbStringFound = true; + break; + } + } + } + + mpDrawDocument->GetDocSh()->SetWaitCursor( FALSE ); + + return mbEndOfSearch; +} + + + + +/** Try to detect whether the document or the view (shell) has changed since + the last time <member>StartSearchAndReplace()</member> has been called. +*/ +void Outliner::DetectChange (void) +{ + ::sd::outliner::IteratorPosition aPosition (maCurrentPosition); + + DrawViewShell* pDrawViewShell = NULL; + if (mpViewShell->ISA(DrawViewShell)) + pDrawViewShell = static_cast<DrawViewShell*>(mpViewShell); + + // Detect whether the view has been switched from the outside. + if (pDrawViewShell != NULL + && (aPosition.meEditMode != pDrawViewShell->GetEditMode() + || aPosition.mePageKind != pDrawViewShell->GetPageKind())) + { + // Either the edit mode or the page kind has changed. + SetStatusEventHdl(Link()); + + SdrPageView* pPageView = mpView->GetPageViewPvNum(0); + if (pPageView != NULL) + mpView->UnmarkAllObj (pPageView); + mpView->EndTextEdit(); + SetUpdateMode(FALSE); + mpOutlineView->SetOutputArea( Rectangle( Point(), Size(1, 1) ) ); + if (meMode == SPELL) + SetPaperSize( Size(1, 1) ); + SetText( String(), GetParagraph( 0 ) ); + + RememberStartPosition (); + + mnPageCount = mpDrawDocument->GetSdPageCount(pDrawViewShell->GetPageKind()); + maObjectIterator = ::sd::outliner::OutlinerContainer(this).current(); + } + + // Detect change of the set of selected objects. If their number has + // changed start again with the first selected object. + else if (DetectSelectionChange()) + { + HandleChangedSelection (); + maObjectIterator = ::sd::outliner::OutlinerContainer(this).current(); + } + + // Detect change of page count. Restart search at first/last page in + // that case. + else if (aPosition.meEditMode == EM_PAGE + && mpDrawDocument->GetSdPageCount(aPosition.mePageKind) != mnPageCount) + { + // The number of pages has changed. + mnPageCount = mpDrawDocument->GetSdPageCount(aPosition.mePageKind); + maObjectIterator = ::sd::outliner::OutlinerContainer(this).current(); + } + else if (aPosition.meEditMode == EM_MASTERPAGE + && mpDrawDocument->GetSdPageCount(aPosition.mePageKind) != mnPageCount) + { + // The number of master pages has changed. + mnPageCount = mpDrawDocument->GetSdPageCount(aPosition.mePageKind); + maObjectIterator = ::sd::outliner::OutlinerContainer(this).current(); + } +} + + + + +bool Outliner::DetectSelectionChange (void) +{ + bool bSelectionHasChanged = false; + ULONG nMarkCount = mpView->GetMarkList().GetMarkCount(); + + // If mpObj is NULL then we have not yet found our first match. + // Detecting a change makes no sense. + if (mpObj != NULL) + switch (nMarkCount) + { + case 0: + // The selection has changed when previously there have been + // selected objects. + bSelectionHasChanged = mbRestrictSearchToSelection; + break; + case 1: + // Check if the only selected object is not the one that we + // had selected. + if (mpView != NULL) + { + SdrMark* pMark = mpView->GetMarkList().GetMark(0); + if (pMark != NULL) + bSelectionHasChanged = (mpObj != pMark->GetObj ()); + } + break; + default: + // We had selected exactly one object. + bSelectionHasChanged = true; + break; + } + + return bSelectionHasChanged; +} + + + + +void Outliner::RememberStartPosition (void) +{ + if (mpViewShell->ISA(DrawViewShell)) + { + DrawViewShell* pDrawViewShell = + static_cast<DrawViewShell*>(mpViewShell); + if (pDrawViewShell != NULL) + { + meStartViewMode = pDrawViewShell->GetPageKind(); + meStartEditMode = pDrawViewShell->GetEditMode(); + mnStartPageIndex = pDrawViewShell->GetCurPageId() - 1; + } + + if (mpView != NULL) + { + mpStartEditedObject = mpView->GetTextEditObject(); + if (mpStartEditedObject != NULL) + { + // Try to retrieve current caret position only when there is an + // edited object. + ::Outliner* pOutliner = + static_cast<DrawView*>(mpView)->GetTextEditOutliner(); + if (pOutliner!=NULL && pOutliner->GetViewCount()>0) + { + OutlinerView* pOutlinerView = pOutliner->GetView(0); + maStartSelection = pOutlinerView->GetSelection(); + } + } + } + } + else if (mpViewShell->ISA(OutlineViewShell)) + { + // Remember the current cursor position. + maStartSelection = GetView(0)->GetSelection(); + } + else + { + mnStartPageIndex = -1; + } +} + + + + +void Outliner::RestoreStartPosition (void) +{ + // Take a negative start page index as inidicater that restoring the + // start position is not requested. + if (mnStartPageIndex < 0) + return; + + if (mpViewShell->ISA(DrawViewShell)) + { + DrawViewShell* pDrawViewShell = + static_cast<DrawViewShell*>(mpViewShell); + SetViewMode (meStartViewMode); + if (pDrawViewShell != NULL) + SetPage (meStartEditMode, mnStartPageIndex); + + if (mpStartEditedObject != NULL) + { + SdrPageView* pPageView = mpView->GetPageViewPvNum(0); + mpView->BegTextEdit (mpStartEditedObject); + ::Outliner* pOutliner = + static_cast<DrawView*>(mpView)->GetTextEditOutliner(); + if (pOutliner!=NULL && pOutliner->GetViewCount()>0) + { + OutlinerView* pOutlinerView = pOutliner->GetView(0); + pOutlinerView->SetSelection(maStartSelection); + } + } + } + else if (mpViewShell->ISA(OutlineViewShell)) + { + // Set cursor to its old position. + GetView(0)->SetSelection (maStartSelection); + } +} + + + + +/** The main purpose of this method is to iterate over all shape objects of + the search area (current selection, current view, or whole document) + until a text object has been found that contains at least one match or + until no such object can be found anymore. These two conditions are + expressed by setting one of the flags <member>mbFoundObject</member> or + <member>mbEndOfSearch</member> to <TRUE/>. +*/ +void Outliner::ProvideNextTextObject (void) +{ + mbEndOfSearch = FALSE; + mbFoundObject = FALSE; + + mpView->UnmarkAllObj (mpView->GetPageViewPvNum(0)); + try + { + mpView->EndTextEdit(); + } + catch (::com::sun::star::uno::Exception e) + { + OSL_TRACE ("caught exception while ending text edit mode"); + } + SetUpdateMode(FALSE); + mpOutlineView->SetOutputArea( Rectangle( Point(), Size(1, 1) ) ); + if (meMode == SPELL) + SetPaperSize( Size(1, 1) ); + SetText( String(), GetParagraph( 0 ) ); + + mpTextObj = NULL; + + // Iterate until a valid text object has been found or the search ends. + do + { + mpObj = NULL; + mpParaObj = NULL; + + if (maObjectIterator != ::sd::outliner::OutlinerContainer(this).end()) + { + maCurrentPosition = *maObjectIterator; + // Switch to the current object only if it is a valid text object. + if (IsValidTextObject (maCurrentPosition)) + mpObj = SetObject (maCurrentPosition); + ++maObjectIterator; + + if (mpObj != NULL) + { + PutTextIntoOutliner (); + + if (mpViewShell != NULL) + if (meMode == SEARCH) + PrepareSearchAndReplace (); + else + PrepareSpellCheck (); + } + } + else + { + mbEndOfSearch = true; + EndOfSearch (); + } + } + while ( ! (mbFoundObject || mbEndOfSearch)); +} + + + + +void Outliner::EndOfSearch (void) +{ + if (mbRestrictSearchToSelection) + ShowEndOfSearchDialog (); + else + { + // When no match has been found so far then terminate the search. + if ( ! mbMatchMayExist) + { + ShowEndOfSearchDialog (); + mbEndOfSearch = TRUE; + } + // Ask the user whether to wrap arround and continue the search or + // to terminate. + else if (ShowWrapArroundDialog ()) + { + mbMatchMayExist = false; + maObjectIterator = ::sd::outliner::OutlinerContainer(this).begin(); + mbEndOfSearch = FALSE; + } + else + { + // No wrap arround. + mbEndOfSearch = TRUE; + } + } +} + + + + +void Outliner::InitPage (USHORT nPageIndex) +{ + ::sd::outliner::IteratorPosition aPosition (*maObjectIterator); + if (aPosition.meEditMode == EM_PAGE) + mnPageCount = mpDrawDocument->GetSdPageCount(aPosition.mePageKind); + else + mnPageCount = mpDrawDocument->GetMasterSdPageCount(aPosition.mePageKind); +} + + + + +void Outliner::ShowEndOfSearchDialog (void) +{ + if (meMode == SEARCH) + { + String aString; + + if (mbStringFound) + aString = String( SdResId(STR_END_SEARCHING) ); + else + aString = String( SdResId(STR_STRING_NOTFOUND) ); + + ::Window* pParent = GetParentForDialog(); + if (pParent != NULL) + InfoBox (pParent, aString).Execute(); + } +} + + + + +bool Outliner::ShowWrapArroundDialog (void) +{ + bool bDoWrapArround = false; + + // Determine whether to show the dialog. + bool bShowDialog = false; + if (mpSearchItem != NULL) + { + // When searching display the dialog only for single find&replace. + USHORT nCommand = mpSearchItem->GetCommand(); + bShowDialog = (nCommand==SVX_SEARCHCMD_REPLACE) + || (nCommand==SVX_SEARCHCMD_FIND); + } + else + // Spell checking needs the dialog, too. + bShowDialog = (meMode == SPELL); + + if (bShowDialog) + { + // The question text depends on the search direction. + BOOL bImpress = mpDrawDocument && mpDrawDocument->GetDocumentType() == DOCUMENT_TYPE_IMPRESS; + USHORT nStringId; + if (mbDirectionIsForward) + nStringId = bImpress ? STR_SAR_WRAP_FORWARD : STR_SAR_WRAP_FORWARD_DRAW; + else + nStringId = bImpress ? STR_SAR_WRAP_BACKWARD : STR_SAR_WRAP_BACKWARD_DRAW; + + // Pop up question box that asks the user whether + // to wrap arround. + ::Window* pParent = GetParentForDialog(); + if (pParent != NULL) + { + QueryBox aQuestionBox (pParent, + WB_YES_NO | WB_DEF_YES, + String(SdResId(nStringId))); + aQuestionBox.SetImage (QueryBox::GetStandardImage()); + USHORT nBoxResult = aQuestionBox.Execute(); + bDoWrapArround = (nBoxResult == BUTTONID_YES); + } + } + + return bDoWrapArround; +} + + + + +bool Outliner::IsValidTextObject (const ::sd::outliner::IteratorPosition& rPosition) +{ + SdrObject* pObject = rPosition.mpObject; + return pObject != NULL + && pObject->ISA(SdrTextObj) + && static_cast<SdrTextObj*>(pObject)->HasText() + && ! pObject->IsEmptyPresObj(); +} + + + + +void Outliner::PutTextIntoOutliner (void) +{ + if ( mpObj && mpObj->ISA(SdrTextObj) + && static_cast<SdrTextObj*>(mpObj)->HasText() + && !mpObj->IsEmptyPresObj() ) + { + mpTextObj = (SdrTextObj*) mpObj; + mpParaObj = mpTextObj->GetOutlinerParaObject(); + + if (mpParaObj != NULL) + { + SetText(*mpParaObj); + + ClearModifyFlag(); + } + } + else + { + mpTextObj = NULL; + } +} + + + + +void Outliner::PrepareSpellCheck (void) +{ + EESpellState eState = HasSpellErrors(); + DBG_ASSERT(eState != EE_SPELL_NOSPELLER, "No SpellChecker"); + + if (eState == EE_SPELL_NOLANGUAGE) + { + mbError = TRUE; + mbEndOfSearch = TRUE; + ::Window* pParent = GetParentForDialog(); + ErrorBox (pParent, + WB_OK, + String(SdResId(STR_NOLANGUAGE))).Execute(); + } + else if (eState != EE_SPELL_OK) + { + // When spell checking we have to test whether we have processed the + // whole document and have reached the start page again. + DrawViewShell* pDrawViewShell = + static_cast<DrawViewShell*>(mpViewShell); + if (meMode == SPELL) + if (maSearchStartPosition == ::sd::outliner::Iterator()) + // Remember the position of the first text object so that we + // know when we have processed the whole document. + maSearchStartPosition = maObjectIterator; + else if (maSearchStartPosition == maObjectIterator) + { + mbEndOfSearch = TRUE; + } + + + EnterEditMode (); + } +} + + + + +void Outliner::PrepareSearchAndReplace (void) +{ + ULONG nMatchCount = 0; + if (HasText( *mpSearchItem )) + { + mbStringFound = TRUE; + mbMatchMayExist = TRUE; + + EnterEditMode (); + + mpDrawDocument->GetDocSh()->SetWaitCursor( FALSE ); + // Start seach at the right end of the current object's text + // depending on the search direction. + mpOutlineView->SetSelection (GetSearchStartPosition ()); + } +} + + + + +void Outliner::SetViewMode (PageKind ePageKind) +{ + if (ePageKind != static_cast<DrawViewShell*>(mpViewShell)->GetPageKind()) + { + // Restore old edit mode. + DrawViewShell* pDrawViewShell = + static_cast<DrawViewShell*>(mpViewShell); + pDrawViewShell->ChangeEditMode(meOriginalEditMode, FALSE); + + SetStatusEventHdl(Link()); + mpViewShell->GetFrameView()->SetPageKind(ePageKind); + try + { + mpViewShell->GetDispatcher()->Execute( + SID_VIEWSHELL0, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD ); + } + catch (::com::sun::star::uno::Exception e) + { + OSL_TRACE ("caught exception while switching view shell"); + } + SetViewShell (mpDrawDocument->GetDocSh()->GetViewShell()); + + // Update the number of pages so that + // <member>DetectChange()</member> has the correct value to compare + // to. + mnPageCount = mpDrawDocument->GetSdPageCount(ePageKind); + + // Save edit mode so that it can be restored when switching the view + // shell again. + meOriginalEditMode = pDrawViewShell->GetEditMode(); + } +} + + + + +void Outliner::SetPage (EditMode eEditMode, USHORT nPageIndex) +{ + if ( ! mbRestrictSearchToSelection) + { + static_cast<DrawViewShell*>(mpViewShell)->ChangeEditMode( + eEditMode, FALSE); + static_cast<DrawViewShell*>(mpViewShell)->SwitchPage(nPageIndex); + } +} + + + + +void Outliner::EnterEditMode (void) +{ + mpOutlineView->SetOutputArea( Rectangle( Point(), Size(1, 1))); + SetPaperSize( mpTextObj->GetLogicRect().GetSize() ); + SdrPageView* pPV = mpView->GetPageViewPvNum(0); + FASTBOOL bIsNewObj = TRUE; + + // Make FuText the current function. + SfxUInt16Item aItem (SID_TEXTEDIT, 1); + mpViewShell->GetDispatcher()-> + Execute(SID_TEXTEDIT, SFX_CALLMODE_SYNCHRON | + SFX_CALLMODE_RECORD, &aItem, 0L); + + // To be consistent with the usual behaviour in the Office the text + // object that is put into edit mode would have also to be selected. + // Starting the text edit mode is not enough so we do it here by hand. + mbExpectingSelectionChangeEvent = true; + mpView->UnmarkAllObj (pPV); + mpView->MarkObj (mpTextObj, pPV); + + // Turn on the edit mode for the text object. + mpView->BegTextEdit(mpTextObj, pPV, mpWindow, bIsNewObj, this, + mpOutlineView, TRUE, TRUE); + + + SetUpdateMode(TRUE); + mbFoundObject = TRUE; +} + + + + +/************************************************************************* +|* +|* SpellChecker: Error-LinkHdl +|* +\************************************************************************/ + +IMPL_LINK_INLINE_START( Outliner, SpellError, void *, nLang ) +{ + mbError = TRUE; + String aError( ::GetLanguageString( (LanguageType)(ULONG)nLang ) ); + ErrorHandler::HandleError(* new StringErrorInfo( + ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aError) ); + return 0; +} +IMPL_LINK_INLINE_END( Outliner, SpellError, void *, nLang ) + + + + +ESelection Outliner::GetSearchStartPosition (void) +{ + ESelection aPosition; + if (mbDirectionIsForward) + { + // The default constructor uses the beginning of the text as default. + aPosition = ESelection (); + } + else + { + // Retrieve the position after the last character in the last + // paragraph. + USHORT nParagraphCount = static_cast<USHORT>(GetParagraphCount()); + if (nParagraphCount == 0) + aPosition = ESelection(); + else + { + xub_StrLen nLastParagraphLength = GetEditEngine().GetTextLen ( + nParagraphCount-1); + aPosition = ESelection (nParagraphCount-1, nLastParagraphLength); + } + } + + return aPosition; +} + + + + +bool Outliner::HasNoPreviousMatch (void) +{ + DBG_ASSERT (mpOutlineView!=NULL, "outline view in Outliner::HasNoPreviousMatch is NULL"); + + // Detect whether the cursor stands at the beginning + // resp. at the end of the text. + return mpOutlineView->GetSelection().IsEqual ( + GetSearchStartPosition ()) == TRUE; +} + + + + +bool Outliner::HandleFailedSearch (void) +{ + bool bContinueSearch = false; + + if (mpOutlineView != NULL && mpSearchItem != NULL) + { + // Prepare to open a message box. Get the search dialog's window. + ::Window* pParent = GetParentForDialog(); + + // Detect whether there is/may be a prior match. If there is then + // ask the user whether to wrap arround. Otherwise tell the user + // that there is no match. + if (HasNoPreviousMatch ()) + { + // No match found in the whole presentation. Tell the user. + InfoBox aInfoBox (pParent, + String(SdResId(STR_SAR_NOT_FOUND))); + USHORT nBoxResult = aInfoBox.Execute(); + } + + else + { + // No further matches found. Ask the user whether to wrap + // arround and start again. + bContinueSearch = ShowWrapArroundDialog (); + } + } + + return bContinueSearch; +} + + + + +/** See task #95227# for discussion about correct parent for dialogs/info boxes. +*/ +::Window* Outliner::GetParentForDialog (void) +{ + ::Window* pParent = NULL; + + if (meMode == SEARCH) + pParent = static_cast<SvxSearchDialog*>( + SfxViewFrame::Current()->GetChildWindow( + SvxSearchDialogWrapper::GetChildWindowId())->GetWindow()); + + if (pParent == NULL) + pParent = mpViewShell->GetActiveWindow(); + + if (pParent == NULL) + pParent = Application::GetDefModalDialogParent(); + + return pParent; +} + + + + +SdrObject* Outliner::SetObject ( + const ::sd::outliner::IteratorPosition& rPosition) +{ + SetViewMode (rPosition.mePageKind); + SetPage (rPosition.meEditMode, (USHORT)rPosition.mnPageIndex); + return rPosition.mpObject; +} + + + + +void Outliner::SetViewShell (ViewShell* pViewShell) +{ + if (mpViewShell != pViewShell) + { + // Set the new view shell. + mpViewShell = pViewShell; + if (mpViewShell != NULL) + { + mpView = mpViewShell->GetView(); + + mpWindow = mpViewShell->GetActiveWindow(); + if (mpOutlineView != NULL) + mpOutlineView->SetWindow(mpWindow); + } + else + { + mpView = NULL; + mpWindow = NULL; + } + } +} + + + + +void Outliner::HandleChangedSelection (void) +{ + maMarkListCopy.clear(); + mbRestrictSearchToSelection = (mpView->HasMarkedObj()==TRUE); + if (mbRestrictSearchToSelection) + { + // Make a copy of the current mark list. + const SdrMarkList& rMarkList = mpView->GetMarkList(); + ULONG nCount = rMarkList.GetMarkCount(); + if (nCount > 0) + { + maMarkListCopy.clear(); + maMarkListCopy.reserve (nCount); + for (ULONG i=0; i<nCount; i++) + maMarkListCopy.push_back (rMarkList.GetMark(i)->GetObj ()); + } + else + // No marked object. Is this case possible? + mbRestrictSearchToSelection = false; + } +} + +} // end of namespace sd |