/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifdef _MSC_VER
#pragma hdrstop
#endif


#define ITEMID_FIELD EE_FEATURE_FIELD

#include <bf_sfx2/app.hxx>
#include <bf_svx/editobj.hxx>
#include <bf_svx/linkmgr.hxx>
#include <bf_svx/svdundo.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/waitobj.hxx>
#include <bf_svtools/zforlist.hxx>
#include <bf_svtools/PasswordHelper.hxx>

#include <list>

#include "docfunc.hxx"

#include "bf_sc.hrc"

#include "arealink.hxx"
#include "autoform.hxx"
#include "cell.hxx"
#include "detdata.hxx"
#include "detfunc.hxx"
#include "docpool.hxx"
#include "docsh.hxx"
#include "drwlayer.hxx"
#include "editutil.hxx"
#include "globstr.hrc"
#include "namecrea.hxx"     // NAME_TOP etc.
#include "olinetab.hxx"
#include "patattr.hxx"
#include "rangenam.hxx"
#include "scresid.hxx"
#include "stlpool.hxx"
#include "tablink.hxx"
#include "uiitems.hxx"
#include "undocell.hxx"
#include "undodraw.hxx"
#include "undotab.hxx"
#include "sizedev.hxx"
#include "scmod.hxx"
#include "editable.hxx"
namespace binfilter {

#define TABLEID_DOC                0xFFFF

using namespace ::com::sun::star;

// STATIC DATA -----------------------------------------------------------

//  Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight)

/*N*/ void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange )
/*N*/ {
/*N*/   USHORT nRow = rRange.aStart.Row();
/*N*/   if ( nRow > 0 )
/*N*/   {
/*N*/       USHORT nTab = rRange.aStart.Tab();  //! alle?
/*N*/       --nRow;
/*N*/       rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID );
/*N*/   }
/*N*/ }


/*N*/ BOOL ScDocFunc::AdjustRowHeight( const ScRange& rRange, BOOL bPaint )
/*N*/ {
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   if ( pDoc->IsImportingXML() )
/*N*/   {
/*N*/       //  for XML import, all row heights are updated together after importing
/*N*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   USHORT nTab      = rRange.aStart.Tab();
/*N*/   USHORT nStartRow = rRange.aStart.Row();
/*N*/   USHORT nEndRow   = rRange.aEnd.Row();
/*N*/
/*N*/   ScSizeDeviceProvider aProv( &rDocShell );
/*N*/   Fraction aOne(1,1);
/*N*/
/*N*/   BOOL bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(),
/*N*/                                           aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, FALSE );
/*N*/
/*N*/   if ( bPaint && bChanged )
/*N*/       rDocShell.PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
/*N*/                                           PAINT_GRID | PAINT_LEFT );
/*N*/
/*N*/   return bChanged;
/*N*/ }


//------------------------------------------------------------------------

/*N*/ BOOL ScDocFunc::DetectiveAddPred(const ScAddress& rPos)
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   rDocShell.MakeDrawLayer();
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   USHORT nCol = rPos.Col();
/*N*/   USHORT nRow = rPos.Row();
/*N*/   USHORT nTab = rPos.Tab();
/*N*/
/*N*/   BOOL bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow );
/*N*/   if (bDone)
/*N*/   {
/*N*/       ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED );
/*N*/       pDoc->AddDetectiveOperation( aOperation );
/*N*/       aModificator.SetDocumentModified();
/*N*/   }
/*N*/
/*N*/   return bDone;
/*N*/ }

/*N*/ BOOL ScDocFunc::DetectiveDelPred(const ScAddress& rPos)
/*N*/ {
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   ScDrawLayer* pModel = pDoc->GetDrawLayer();
/*N*/   if (!pModel)
/*N*/       return FALSE;
/*N*/
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   USHORT nCol = rPos.Col();
/*N*/   USHORT nRow = rPos.Row();
/*N*/   USHORT nTab = rPos.Tab();
/*N*/
/*N*/   BOOL bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow );
/*N*/   if (bDone)
/*N*/   {
/*N*/       ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED );
/*N*/       pDoc->AddDetectiveOperation( aOperation );
/*N*/       aModificator.SetDocumentModified();
/*N*/   }
/*N*/
/*N*/   return bDone;
/*N*/ }

/*N*/ BOOL ScDocFunc::DetectiveDelSucc(const ScAddress& rPos)
/*N*/ {
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   ScDrawLayer* pModel = pDoc->GetDrawLayer();
/*N*/   if (!pModel)
/*N*/       return FALSE;
/*N*/
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   USHORT nCol = rPos.Col();
/*N*/   USHORT nRow = rPos.Row();
/*N*/   USHORT nTab = rPos.Tab();
/*N*/
/*N*/   BOOL bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow );
/*N*/   if (bDone)
/*N*/   {
/*N*/       ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC );
/*N*/       pDoc->AddDetectiveOperation( aOperation );
/*N*/       aModificator.SetDocumentModified();
/*N*/   }
/*N*/
/*N*/   return bDone;
/*N*/ }

/*N*/ BOOL ScDocFunc::DetectiveAddError(const ScAddress& rPos)
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   rDocShell.MakeDrawLayer();
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   USHORT nCol = rPos.Col();
/*N*/   USHORT nRow = rPos.Row();
/*N*/   USHORT nTab = rPos.Tab();
/*N*/
/*N*/   BOOL bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow );
/*N*/   if (bDone)
/*N*/   {
/*N*/       ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR );
/*N*/       pDoc->AddDetectiveOperation( aOperation );
/*N*/       aModificator.SetDocumentModified();
/*N*/   }
/*N*/
/*N*/   return bDone;
/*N*/ }

/*N*/ BOOL ScDocFunc::DetectiveMarkInvalid(USHORT nTab)
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   rDocShell.MakeDrawLayer();
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   Window* pWaitWin = rDocShell.GetDialogParent();
/*N*/   if (pWaitWin)
/*N*/       pWaitWin->EnterWait();
/*N*/   BOOL bOverflow;
/*N*/   BOOL bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow );
/*N*/   if (pWaitWin)
/*N*/       pWaitWin->LeaveWait();
/*N*/   if (bDone)
/*N*/   {
/*N*/       aModificator.SetDocumentModified();
/*N*/       if ( bOverflow )
/*N*/       {
/*N*/           InfoBox( NULL,
/*N*/                   ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute();
/*N*/       }
/*N*/   }
/*N*/
/*N*/   return bDone;
/*N*/ }

/*N*/ BOOL ScDocFunc::DetectiveDelAll(USHORT nTab)
/*N*/ {
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   ScDrawLayer* pModel = pDoc->GetDrawLayer();
/*N*/   if (!pModel)
/*N*/       return FALSE;
/*N*/
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   BOOL bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE );
/*N*/   if (bDone)
/*N*/   {
/*N*/       pDoc->ClearDetectiveOperations();
/*N*/
/*N*/       aModificator.SetDocumentModified();
/*N*/   }
/*N*/
/*N*/   return bDone;
/*N*/ }

/*N*/ BOOL ScDocFunc::DetectiveRefresh()
/*N*/ {
/*N*/   BOOL bDone = FALSE;
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   ScDetOpList* pList = pDoc->GetDetOpList();
/*N*/   if ( pList && pList->Count() )
/*N*/   {
/*N*/       rDocShell.MakeDrawLayer();
/*N*/
/*N*/       //  Loeschen auf allen Tabellen
/*N*/
/*N*/       USHORT nTabCount = pDoc->GetTableCount();
/*N*/       for (USHORT nTab=0; nTab<nTabCount; nTab++)
/*N*/           ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS );    // don't remove circles
/*N*/
/*N*/       //  Wiederholen
/*N*/
/*N*/       USHORT nCount = pList->Count();
/*N*/       for (USHORT i=0; i<nCount; i++)
/*N*/       {
/*N*/           ScDetOpData* pData = (*pList)[i];
/*N*/           if (pData)
/*N*/           {
/*N*/               ScAddress aPos = pData->GetPos();
/*N*/               ScDetectiveFunc aFunc( pDoc, aPos.Tab() );
/*N*/               USHORT nCol = aPos.Col();
/*N*/               USHORT nRow = aPos.Row();
/*N*/               switch (pData->GetOperation())
/*N*/               {
/*N*/                   case SCDETOP_ADDSUCC:
/*N*/                       aFunc.ShowSucc( nCol, nRow );
/*N*/                       break;
/*N*/                   case SCDETOP_DELSUCC:
/*N*/                       aFunc.DeleteSucc( nCol, nRow );
/*N*/                       break;
/*N*/                   case SCDETOP_ADDPRED:
/*N*/                       aFunc.ShowPred( nCol, nRow );
/*N*/                       break;
/*N*/                   case SCDETOP_DELPRED:
/*N*/                       aFunc.DeletePred( nCol, nRow );
/*N*/                       break;
/*N*/                   case SCDETOP_ADDERROR:
/*N*/                       aFunc.ShowError( nCol, nRow );
/*N*/                       break;
/*N*/                   default:
/*N*/                       OSL_FAIL("falsche Op bei DetectiveRefresh");
/*N*/               }
/*N*/           }
/*N*/       }
/*N*/
/*N*/       rDocShell.SetDrawModified();
/*N*/       bDone = TRUE;
/*N*/   }
/*N*/   return bDone;
/*N*/ }

//------------------------------------------------------------------------

/*N*/ BOOL ScDocFunc::DeleteContents( const ScMarkData& rMark, USHORT nFlags,
/*N*/                                   BOOL /*bRecord*/, BOOL )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
/*N*/   {
/*N*/       OSL_FAIL("ScDocFunc::DeleteContents ohne Markierung");
/*N*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   ScEditableTester aTester( pDoc, rMark );
/*N*/   if (!aTester.IsEditable())
/*N*/   {
/*N*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   ScRange aMarkRange;
/*N*/   BOOL bSimple = FALSE;
/*N*/
/*N*/   ScMarkData aMultiMark = rMark;
/*N*/   aMultiMark.SetMarking(FALSE);       // fuer MarkToMulti
/*N*/
/*N*/   if (!bSimple)
/*N*/   {
/*N*/       aMultiMark.MarkToMulti();
/*N*/       aMultiMark.GetMultiMarkArea( aMarkRange );
/*N*/   }
/*N*/   ScRange aExtendedRange(aMarkRange);
/*N*/   if (!bSimple)
/*N*/       pDoc->ExtendMerge( aExtendedRange, TRUE );
/*N*/
/*N*/   // keine Objekte auf geschuetzten Tabellen
/*N*/   if ( nFlags & IDF_OBJECTS )
/*N*/   {
/*N*/       USHORT nTabCount = pDoc->GetTableCount();
/*N*/       for (USHORT nTab=0; nTab<nTabCount; nTab++)
/*N*/           aMultiMark.GetTableSelect(nTab);
/*N*/   }
/*N*/
/*N*/   USHORT nExtFlags = 0;                       // Linien interessieren nur, wenn Attribute
/*N*/   if ( nFlags & IDF_ATTRIB )                  // geloescht werden
/*N*/       if (pDoc->HasAttrib( aMarkRange, HASATTR_PAINTEXT ))
/*N*/           nExtFlags |= SC_PF_LINES;
/*N*/
/*N*/   if (bSimple)
/*N*/       pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
/*N*/                         aMarkRange.aEnd.Col(),   aMarkRange.aEnd.Row(),
/*N*/                         aMultiMark, nFlags );
/*N*/
/*N*/   if (!AdjustRowHeight( aExtendedRange ))
/*N*/       rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
/*N*/
/*N*/   aModificator.SetDocumentModified();
/*N*/
/*N*/   return TRUE;
/*N*/ }

//------------------------------------------------------------------------


//------------------------------------------------------------------------

/*N*/ BOOL ScDocFunc::SetNormalString( const ScAddress& rPos, const String& rText, BOOL bApi )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
/*N*/   if (!aTester.IsEditable())
/*N*/   {
/*N*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   ScBaseCell* pDocCell = pDoc->GetCell( rPos );
/*N*/   BOOL bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
/*N*/
/*N*/   pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText );
/*N*/
/*N*/   if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) )
/*N*/       AdjustRowHeight( ScRange(rPos) );
/*N*/
/*N*/   rDocShell.PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() );
/*N*/   aModificator.SetDocumentModified();
/*N*/
/*N*/     // #107160# notify input handler here the same way as in PutCell
/*N*/     if (bApi)
/*?*/         NotifyInputHandler( rPos );
/*N*/
/*N*/   return TRUE;
/*N*/ }

/*N*/ BOOL ScDocFunc::PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, BOOL bApi )
/*N*/ {
/*N*/
/*N*/     ScDocShellModificator aModificator( rDocShell );
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/     BOOL bXMLLoading(pDoc->IsImportingXML());
/*N*/
/*N*/     // #i925#; it is not neccessary to test whether the cell is editable on loading a XML document
/*N*/     if (!bXMLLoading)
/*N*/     {
/*N*/       ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
/*N*/       if (!aTester.IsEditable())
/*N*/       {
/*N*/           pNewCell->Delete();
/*N*/           return FALSE;
/*N*/       }
/*N*/     }
/*N*/
/*N*/   BOOL bHeight = FALSE;
/*N*/   pDoc->PutCell( rPos, pNewCell );
/*N*/
/*N*/   //  wegen ChangeTracking darf UndoAction erst nach PutCell angelegt werden
/*N*/
/*N*/   if (bHeight)
/*N*/       AdjustRowHeight( ScRange(rPos) );
/*N*/
/*N*/     if (!bXMLLoading)
/*N*/       rDocShell.PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() );
/*N*/
/*N*/     aModificator.SetDocumentModified();
/*N*/
/*N*/     // #i925#; it is not neccessary to notify on loading a XML document
/*N*/     // #103934#; notify editline and cell in edit mode
/*N*/     if (bApi && !bXMLLoading)
/*N*/         NotifyInputHandler( rPos );
/*N*/
/*N*/   return TRUE;
/*N*/ }

/*N*/ void ScDocFunc::NotifyInputHandler( const ScAddress& /*rPos*/ )
/*N*/ {
/*N*/ }

/*N*/       struct ScMyRememberItem
/*N*/       {
/*N*/           USHORT      nIndex;
/*N*/           SfxItemSet  aItemSet;
/*N*/
/*N*/           ScMyRememberItem(const SfxItemSet& rItemSet, USHORT nTempIndex)
                            : nIndex(nTempIndex)
                            , aItemSet(rItemSet)
                            {}
/*N*/       };

/*N*/       typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList;

/*N*/ BOOL ScDocFunc::PutData( const ScAddress& rPos, EditEngine& rEngine, BOOL bInterpret, BOOL bApi )
/*N*/ {
/*N*/   //  PutData ruft PutCell oder SetNormalString
/*N*/
/*N*/   BOOL bRet = FALSE;
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   ScEditAttrTester aTester( &rEngine );
/*N*/   BOOL bEditCell = aTester.NeedsObject();
/*N*/   if ( bEditCell )
/*N*/   {
/*N*/       sal_Bool bUpdateMode(rEngine.GetUpdateMode());
/*N*/       if (bUpdateMode)
/*N*/           rEngine.SetUpdateMode(sal_False);
/*N*/
/*N*/       ScMyRememberItemList aRememberItems;
/*N*/       ScMyRememberItem* pRememberItem = NULL;
/*N*/
/*N*/       //  All paragraph attributes must be removed before calling CreateTextObject,
/*N*/       //  not only alignment, so the object doesn't contain the cell attributes as
/*N*/       //  paragraph attributes. Before remove the attributes store they in a list to
/*N*/       //  set they back to the EditEngine.
/*N*/       USHORT nCount = rEngine.GetParagraphCount();
/*N*/       for (USHORT i=0; i<nCount; i++)
/*N*/       {
/*N*/           const SfxItemSet& rOld = rEngine.GetParaAttribs( i );
/*N*/           if ( rOld.Count() )
/*N*/           {
/*N*/               pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i);
/*N*/               aRememberItems.push_back(pRememberItem);
/*N*/               rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) );
/*N*/           }
/*N*/       }
/*N*/
/*N*/       EditTextObject* pNewData = rEngine.CreateTextObject();
/*N*/       bRet = PutCell( rPos,
/*N*/                       new ScEditCell( pNewData, pDoc, rEngine.GetEditTextObjectPool() ),
/*N*/                       bApi );
/*N*/       delete pNewData;
/*N*/
/*N*/       // Set the paragraph attributes back to the EditEngine.
/*N*/       if (!aRememberItems.empty())
/*N*/       {
/*N*/           ScMyRememberItem* pInnerRememberItem = NULL;
/*N*/           ScMyRememberItemList::iterator aItr = aRememberItems.begin();
/*N*/           while (aItr != aRememberItems.end())
/*N*/           {
/*N*/               pInnerRememberItem = *aItr;
/*N*/               rEngine.SetParaAttribs(pInnerRememberItem->nIndex, pInnerRememberItem->aItemSet);
/*N*/               delete pInnerRememberItem;
/*N*/               aItr = aRememberItems.erase(aItr);
/*N*/           }
/*N*/       }
/*N*/
/*N*/       if (bUpdateMode)
/*N*/           rEngine.SetUpdateMode(sal_True);
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/        String aText = rEngine.GetText();
/*N*/       if ( bInterpret || !aText.Len() )
/*N*/           bRet = SetNormalString( rPos, aText, bApi );
/*N*/       else
/*N*/           bRet = PutCell( rPos, new ScStringCell( aText ), bApi );
/*N*/   }
/*N*/
/*N*/   if ( bRet && aTester.NeedsCellAttr() )
/*N*/   {
/*N*/       const SfxItemSet& rEditAttr = aTester.GetAttribs();
/*N*/       ScPatternAttr aPattern( pDoc->GetPool() );
/*N*/       aPattern.GetFromEditItemSet( &rEditAttr );
/*N*/       aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) );
/*N*/       aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY );    // wasn't removed above if no edit object
/*N*/       if ( aPattern.GetItemSet().Count() > 0 )
/*N*/       {
/*?*/           ScMarkData aMark;
/*?*/           aMark.SelectTable( rPos.Tab(), TRUE );
/*?*/           aMark.SetMarkArea( ScRange( rPos ) );
/*?*/           ApplyAttributes( aMark, aPattern, TRUE, bApi );
/*N*/       }
/*N*/   }
/*N*/
/*N*/   return bRet;
/*N*/ }


/*N*/  ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText )
/*N*/  {
/*N*/   ScTokenArray* pCode = new ScTokenArray;
/*N*/      pCode->AddString( rText );
/*N*/   return pCode;
/*N*/  }


/*N*/ ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos, const String& rText )
/*N*/ {
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   ScBaseCell* pNewCell = NULL;
/*N*/
/*N*/   if ( rText.Len() > 1 && rText.GetChar(0) == '=' )
/*N*/   {
/*N*/       ScTokenArray* pCode;
/*N*/       if ( pDoc->IsImportingXML() )
/*N*/       {   // temporary formula string as string tokens
/*N*/           pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText );
/*N*/             pDoc->IncXMLImportedFormulaCount( rText.Len() );
/*N*/       }
/*N*/       else
/*N*/       {
/*N*/           ScCompiler aComp( pDoc, rPos );
/*N*/           aComp.SetCompileEnglish( TRUE );
/*N*/           pCode = aComp.CompileString( rText );
/*N*/       }
/*N*/       pNewCell = new ScFormulaCell( pDoc, rPos, pCode, 0 );
/*N*/       delete pCode;   // Zell-ctor hat das TokenArray kopiert
/*N*/   }
/*N*/   else if ( rText.Len() > 1 && rText.GetChar(0) == '\'' )
/*N*/   {
/*N*/       //  for bEnglish, "'" at the beginning is always interpreted as text
/*N*/       //  marker and stripped
/*?*/       pNewCell = ScBaseCell::CreateTextCell( rText.Copy( 1 ), pDoc );
/*N*/   }
/*N*/   else        // (nur) auf englisches Zahlformat testen
/*N*/   {
/*?*/       SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
/*?*/       sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
/*?*/       double fVal;
/*?*/       if ( pFormatter->IsNumberFormat( rText, nEnglish, fVal ) )
/*?*/           pNewCell = new ScValueCell( fVal );
/*?*/       else if ( rText.Len() )
/*?*/           pNewCell = ScBaseCell::CreateTextCell( rText, pDoc );
/*?*/
/*?*/       //  das (englische) Zahlformat wird nicht gesetzt
/*?*/       //! passendes lokales Format suchen und setzen???
/*N*/   }
/*N*/
/*N*/   return pNewCell;
/*N*/ }


/*N*/ BOOL ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText,
/*N*/                               BOOL bInterpret, BOOL bEnglish, BOOL bApi )
/*N*/ {
/*N*/   //  SetCellText ruft PutCell oder SetNormalString
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   ScBaseCell* pNewCell = NULL;
/*N*/   if ( bInterpret )
/*N*/   {
/*N*/       if ( bEnglish )
/*N*/       {
/*N*/           //  code moved to own method InterpretEnglishString because it is also used in
/*N*/           //  ScCellRangeObj::setFormulaArray
/*N*/
/*N*/           pNewCell = InterpretEnglishString( rPos, rText );
/*N*/       }
/*N*/       // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
/*N*/   }
/*N*/   else if ( rText.Len() )
/*N*/       pNewCell = ScBaseCell::CreateTextCell( rText, pDoc );   // immer Text
/*N*/
/*N*/   if (pNewCell)
/*N*/       return PutCell( rPos, pNewCell, bApi );
/*N*/   else
/*?*/       return SetNormalString( rPos, rText, bApi );
/*N*/ }

//------------------------------------------------------------------------

/*N*/ BOOL ScDocFunc::SetNoteText( const ScAddress& rPos, const String& rText, BOOL )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
/*N*/   if (!aTester.IsEditable())
/*N*/   {
/*?*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   String aNewText = rText;
/*N*/   aNewText.ConvertLineEnd();      //! ist das noetig ???
/*N*/
/*N*/   ScPostIt aNote;
/*N*/   pDoc->GetNote( rPos.Col(), rPos.Row(), rPos.Tab(), aNote );
/*N*/   aNote.AutoSetText( aNewText );      // setzt auch Author und Date
/*N*/   pDoc->SetNote( rPos.Col(), rPos.Row(), rPos.Tab(), aNote );
/*N*/
/*N*/   if ( aNote.IsShown() )
/*N*/   {
/*N*/       //  Zeichenobjekt updaten
/*N*/       //! bei gelocktem Paint auch erst spaeter !!!
/*N*/
/*N*/       ScDetectiveFunc aDetFunc( pDoc, rPos.Tab() );
/*N*/       aDetFunc.HideComment( rPos.Col(), rPos.Row() );
/*N*/       aDetFunc.ShowComment( rPos.Col(), rPos.Row(), FALSE );  // FALSE: nur wenn gefunden
/*N*/   }
/*N*/
/*N*/   //! Undo !!!
/*N*/
/*N*/   rDocShell.PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() );
/*N*/   aModificator.SetDocumentModified();
/*N*/
/*N*/   return TRUE;
/*N*/ }

//------------------------------------------------------------------------

/*N*/ BOOL ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
/*N*/                                   BOOL /*bRecord*/, BOOL )
/*N*/ {
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
/*N*/   BOOL bOnlyNotBecauseOfMatrix;
/*N*/   if ( !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
/*N*/           && !bOnlyNotBecauseOfMatrix )
/*N*/   {
/*?*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   //! Umrandung
/*N*/
/*N*/   ScRange aMultiRange;
/*N*/   BOOL bMulti = rMark.IsMultiMarked();
/*N*/   if ( bMulti )
/*N*/       rMark.GetMultiMarkArea( aMultiRange );
/*N*/   else
/*N*/       rMark.GetMarkArea( aMultiRange );
/*N*/
/*N*/
/*N*/   // While loading XML it is not neccessary to ask HasAttrib. It needs too much time.
/*N*/   BOOL bPaintExt = pDoc->IsImportingXML() || pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
/*N*/   pDoc->ApplySelectionPattern( rPattern, rMark );
/*N*/
/*N*/   if (!bPaintExt)
/*N*/       bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
/*N*/   USHORT nExtFlags = bPaintExt ? SC_PF_LINES : 0;
/*N*/   if (!AdjustRowHeight( aMultiRange ))
/*N*/       rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
/*N*/   else if (nExtFlags & SC_PF_LINES)
/*N*/   lcl_PaintAbove( rDocShell, aMultiRange );   // fuer Linien ueber dem Bereich
/*N*/
/*N*/   aModificator.SetDocumentModified();
/*N*/
/*N*/   return TRUE;
/*N*/ }


/*N*/ BOOL ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleName,
/*N*/                                   BOOL /*bRecord*/, BOOL )
/*N*/ {
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
/*N*/   BOOL bOnlyNotBecauseOfMatrix;
/*N*/   if ( !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
/*N*/           && !bOnlyNotBecauseOfMatrix )
/*N*/   {
/*?*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find(
/*N*/                                               rStyleName, SFX_STYLE_FAMILY_PARA );
/*N*/   if (!pStyleSheet)
/*N*/       return FALSE;
/*N*/
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScRange aMultiRange;
/*N*/   BOOL bMulti = rMark.IsMultiMarked();
/*N*/   if ( bMulti )
/*N*/       rMark.GetMultiMarkArea( aMultiRange );
/*N*/   else
/*N*/       rMark.GetMarkArea( aMultiRange );
/*N*/
/*N*/   pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark );
/*N*/
/*N*/   USHORT nExtFlags = 0;
/*N*/   if (!AdjustRowHeight( aMultiRange ))
/*N*/       rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
/*N*/
/*N*/   aModificator.SetDocumentModified();
/*N*/
/*N*/   return TRUE;
/*N*/ }

//------------------------------------------------------------------------

/*N*/ BOOL ScDocFunc::InsertTable( USHORT nTab, const String& rName, BOOL /*bRecord*/, BOOL )
/*N*/ {
/*N*/   BOOL bSuccess = FALSE;
/*N*/   WaitObject aWait( rDocShell.GetDialogParent() );
/*N*/
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   USHORT nTabCount = pDoc->GetTableCount();
/*N*/   BOOL bAppend = ( nTab >= nTabCount );
/*N*/   if ( bAppend )
/*N*/       nTab = nTabCount;       // wichtig fuer Undo
/*N*/
/*N*/   if (pDoc->InsertTab( nTab, rName ))
/*N*/   {
/*N*/       //  Views updaten:
/*N*/       rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) );
/*N*/
/*N*/       rDocShell.PostPaintExtras();
/*N*/       aModificator.SetDocumentModified();
/*N*/       SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
/*N*/       bSuccess = TRUE;
/*N*/   }
/*N*/
/*N*/   return bSuccess;
/*N*/ }

/*N*/ BOOL ScDocFunc::SetTableVisible( USHORT nTab, BOOL bVisible, BOOL )
/*N*/ {
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   if ( pDoc->IsVisible( nTab ) == bVisible )
/*N*/       return TRUE;                                // nichts zu tun - ok
/*N*/
/*N*/   if ( !pDoc->IsDocEditable() )
/*N*/   {
/*N*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   if ( !bVisible )
/*N*/   {
/*N*/       //  nicht alle Tabellen ausblenden
/*N*/
/*N*/       USHORT nVisCount = 0;
/*N*/       USHORT nCount = pDoc->GetTableCount();
/*N*/       for (USHORT i=0; i<nCount; i++)
/*N*/           if (pDoc->IsVisible(i))
/*N*/               ++nVisCount;
/*N*/
/*N*/       if (nVisCount <= 1)
/*N*/       {
/*N*/           return FALSE;
/*N*/       }
/*N*/   }
/*N*/
/*N*/   pDoc->SetVisible( nTab, bVisible );
/*N*/
/*N*/   //  Views updaten:
/*N*/   if (!bVisible)
/*N*/       rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
/*N*/
/*N*/   SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
/*N*/   rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
/*N*/   aModificator.SetDocumentModified();
/*N*/
/*N*/   return TRUE;
/*N*/ }

/*N*/ BOOL ScDocFunc::RenameTable( USHORT nTab, const String& rName, BOOL /*bRecord*/, BOOL )
/*N*/ {
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   if ( !pDoc->IsDocEditable() )
/*N*/   {
/*?*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   BOOL bSuccess = FALSE;
/*N*/   String sOldName;
/*N*/   pDoc->GetName(nTab, sOldName);
/*N*/   if (pDoc->RenameTab( nTab, rName ))
/*N*/   {
/*N*/       rDocShell.PostPaintExtras();
/*N*/       aModificator.SetDocumentModified();
/*N*/       SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
/*N*/
/*N*/       bSuccess = TRUE;
/*N*/   }
/*N*/   return bSuccess;
/*N*/ }

//------------------------------------------------------------------------

//! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!!
//! Probleme:
//! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm
//! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen

/*N*/ USHORT lcl_GetOptimalColWidth( ScDocShell& rDocShell, USHORT nCol, USHORT nTab, BOOL bFormula )
/*N*/ {
/*N*/   USHORT nTwips = 0;
/*N*/
/*N*/   ScSizeDeviceProvider aProv(&rDocShell);
/*N*/   OutputDevice* pDev = aProv.GetDevice();         // has pixel MapMode
/*N*/   double nPPTX = aProv.GetPPTX();
/*N*/   double nPPTY = aProv.GetPPTY();
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   Fraction aOne(1,1);
/*N*/   nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne,
/*N*/                                       bFormula, NULL );
/*N*/
/*N*/   return nTwips;
/*N*/ }

/*N*/ BOOL ScDocFunc::SetWidthOrHeight( BOOL bWidth, USHORT nRangeCnt, USHORT* pRanges, USHORT nTab,
/*N*/                                       ScSizeMode eMode, USHORT nSizeTwips,
/*N*/                                       BOOL /*bRecord*/, BOOL )
/*N*/ {
/*N*/   if (!nRangeCnt)
/*N*/       return TRUE;
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   if ( !rDocShell.IsEditable() )
/*N*/   {
/*?*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   BOOL bSuccess = FALSE;
/*N*/   BOOL bFormula = FALSE;
/*N*/
/*N*/   ScOutlineTable* pUndoTab = NULL;
/*N*/
/*N*/   BOOL bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
/*N*/   BOOL bOutline = FALSE;
/*N*/
/*N*/   pDoc->IncSizeRecalcLevel( nTab );       // nicht fuer jede Spalte einzeln
/*N*/   for (USHORT nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
/*N*/   {
/*N*/       USHORT nStartNo = *(pRanges++);
/*N*/       USHORT nEndNo = *(pRanges++);
/*N*/
/*N*/       if ( !bWidth )                      // Hoehen immer blockweise
/*N*/       {
/*N*/           if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
/*N*/           {
/*?*/               BOOL bAll = ( eMode==SC_SIZE_OPTIMAL );
/*?*/               if (!bAll)
/*?*/               {
/*?*/                   //  fuer alle eingeblendeten CR_MANUALSIZE loeschen,
/*?*/                   //  dann SetOptimalHeight mit bShrink = FALSE
/*?*/                   for (USHORT nRow=nStartNo; nRow<=nEndNo; nRow++)
/*?*/                   {
/*?*/                       BYTE nOld = pDoc->GetRowFlags(nRow,nTab);
/*?*/                       if ( (nOld & CR_HIDDEN) == 0 && ( nOld & CR_MANUALSIZE ) )
/*?*/                           pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE );
/*?*/                   }
/*?*/               }
/*?*/
/*?*/               ScSizeDeviceProvider aProv( &rDocShell );
/*?*/               Fraction aOne(1,1);
/*?*/               pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(),
/*?*/                                       aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, bAll );
/*?*/
/*?*/               if (bAll)
/*?*/                   pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
/*?*/
/*?*/               //  Manual-Flag wird bei bAll=TRUE schon in SetOptimalHeight gesetzt
/*?*/               //  (an bei Extra-Height, sonst aus).
/*N*/           }
/*N*/           else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL )
/*N*/           {
/*N*/               if (nSizeTwips)
/*N*/               {
/*N*/                   pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
/*N*/                   pDoc->SetManualHeight( nStartNo, nEndNo, nTab, TRUE );          // height was set manually
/*N*/               }
/*N*/               if ( eMode != SC_SIZE_ORIGINAL )
/*N*/                   pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
/*N*/           }
/*N*/           else if ( eMode==SC_SIZE_SHOW )
/*N*/           {
/*?*/               pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
/*N*/           }
/*N*/       }
/*N*/       else                                // Spaltenbreiten
/*N*/       {
/*N*/           for (USHORT nCol=nStartNo; nCol<=nEndNo; nCol++)
/*N*/           {
/*N*/               if ( eMode != SC_SIZE_VISOPT ||
/*N*/                    (pDoc->GetColFlags( nCol, nTab ) & CR_HIDDEN) == 0 )
/*N*/               {
/*N*/                   USHORT nThisSize = nSizeTwips;
/*N*/
/*N*/                   if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
/*N*/                    nThisSize = nSizeTwips +
/*N*/                                   lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula );
/*N*/                   if ( nThisSize )
/*N*/                       pDoc->SetColWidth( nCol, nTab, nThisSize );
/*N*/
/*N*/                   if ( eMode != SC_SIZE_ORIGINAL )
/*N*/                       pDoc->ShowCol( nCol, nTab, bShow );
/*N*/               }
/*N*/           }
/*N*/       }
/*N*/
/*N*/                           //  adjust outlines
/*N*/
/*N*/       if ( eMode != SC_SIZE_ORIGINAL )
/*N*/       {
/*N*/           if (bWidth)
/*N*/               bOutline = bOutline;
/*N*/           else
/*N*/               bOutline = bOutline || pDoc->UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow );
/*N*/       }
/*N*/   }
/*N*/   pDoc->DecSizeRecalcLevel( nTab );       // nicht fuer jede Spalte einzeln
/*N*/
/*N*/   if (!bOutline)
/*N*/       DELETEZ(pUndoTab);
/*N*/
/*N*/   pDoc->UpdatePageBreaks( nTab );
/*N*/
/*N*/   rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL);
/*N*/
/*N*/   return bSuccess;
/*N*/ }


/*N*/ BOOL ScDocFunc::RemovePageBreak( BOOL bColumn, const ScAddress& rPos,
/*N*/                               BOOL /*bRecord*/, BOOL bSetModified )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   USHORT nTab = rPos.Tab();
/*N*/
/*N*/   USHORT nPos = bColumn ? rPos.Col() : rPos.Row();
/*N*/   BYTE nFlags = bColumn ? pDoc->GetColFlags( nPos, nTab ) : pDoc->GetRowFlags( nPos, nTab );
/*N*/   if ((nFlags & CR_MANUALBREAK)==0)
/*N*/       return FALSE;                           // kein Umbruch gesetzt
/*N*/
/*?*/   nFlags &= ~CR_MANUALBREAK;
/*?*/   if ( !bColumn )
/*?*/       pDoc->SetRowFlags( nPos, nTab, nFlags );
/*?*/   pDoc->UpdatePageBreaks( nTab );
/*?*/
/*?*/   if (bColumn)
/*?*/   {
/*?*/       rDocShell.PostPaint( nPos-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
/*?*/   }
/*?*/   else
/*?*/   {
/*?*/       rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
/*?*/   }
/*?*/
/*?*/   if (bSetModified)
/*?*/       aModificator.SetDocumentModified();
/*?*/
/*?*/   return TRUE;
/*N*/ }

//------------------------------------------------------------------------

/*N*/ BOOL lcl_ValidPassword( ScDocument* pDoc, USHORT nTab,
/*N*/                       const String& rPassword,
/*N*/                       uno::Sequence<sal_Int8>* pReturnOld = NULL )
/*N*/ {
/*N*/   uno::Sequence<sal_Int8> aOldPassword;
/*N*/   if ( nTab == TABLEID_DOC )
/*N*/   {
/*N*/       if (pDoc->IsDocProtected())
/*N*/           aOldPassword = pDoc->GetDocPassword();
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/       if (pDoc->IsTabProtected(nTab))
/*N*/           aOldPassword = pDoc->GetTabPassword(nTab);
/*N*/   }
/*N*/
/*N*/   if (pReturnOld)
/*N*/       *pReturnOld = aOldPassword;
/*N*/
/*N*/   return ((aOldPassword.getLength() == 0) || SvPasswordHelper::CompareHashPassword(aOldPassword, rPassword));
/*N*/ }

/*N*/ BOOL ScDocFunc::Protect( USHORT nTab, const String& rPassword, BOOL bApi )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   BOOL bOk = lcl_ValidPassword( pDoc, nTab, rPassword);
/*N*/   if ( bOk )
/*N*/   {
/*N*/       uno::Sequence<sal_Int8> aPass;
/*N*/       if (rPassword.Len())
/*N*/           SvPasswordHelper::GetHashPassword(aPass, rPassword);
/*N*/
/*N*/       if ( nTab == TABLEID_DOC )
/*N*/           pDoc->SetDocProtection( TRUE, aPass );
/*N*/       else
/*N*/           pDoc->SetTabProtection( nTab, TRUE, aPass );
/*N*/
/*N*/       rDocShell.PostPaintGridAll();
/*N*/       aModificator.SetDocumentModified();
/*N*/   }
/*N*/   else if (!bApi)
/*N*/   {
/*N*/       //  different password was set before
/*N*/       InfoBox aBox( rDocShell.GetDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
/*N*/       aBox.Execute();
/*N*/   }
/*N*/
/*N*/   return bOk;
/*N*/ }

/*N*/ BOOL ScDocFunc::Unprotect( USHORT nTab, const String& rPassword, BOOL bApi )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   uno::Sequence<sal_Int8> aOldPassword;
/*N*/   uno::Sequence<sal_Int8> aPass;
/*N*/   BOOL bOk = lcl_ValidPassword( pDoc, nTab, rPassword, &aOldPassword );
/*N*/   if ( bOk )
/*N*/   {
/*N*/       uno::Sequence<sal_Int8> aEmptyPass;
/*N*/       if ( nTab == TABLEID_DOC )
/*N*/           pDoc->SetDocProtection( FALSE, aEmptyPass );
/*N*/       else
/*N*/           pDoc->SetTabProtection( nTab, FALSE, aEmptyPass );
/*N*/
/*N*/       rDocShell.PostPaintGridAll();
/*N*/       aModificator.SetDocumentModified();
/*N*/   }
/*N*/   else if (!bApi)
/*N*/   {
/*N*/       InfoBox aBox( rDocShell.GetDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
/*N*/       aBox.Execute();
/*N*/   }
/*N*/
/*N*/   return bOk;
/*N*/ }

//------------------------------------------------------------------------

/*N*/ BOOL ScDocFunc::ClearItems( const ScMarkData& rMark, const USHORT* /*pWhich*/, BOOL )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   ScEditableTester aTester( pDoc, rMark );
/*N*/   if (!aTester.IsEditable())
/*N*/   {
/*?*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   ScRange aMarkRange;
/*N*/   ScMarkData aMultiMark = rMark;
/*N*/   aMultiMark.SetMarking(FALSE);       // for MarkToMulti
/*N*/   aMultiMark.MarkToMulti();
/*N*/   aMultiMark.GetMultiMarkArea( aMarkRange );
/*N*/
/*N*/   rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
/*N*/   aModificator.SetDocumentModified();
/*N*/
/*N*/   return TRUE;
/*N*/ }

/*N*/ BOOL ScDocFunc::ChangeIndent( const ScMarkData& rMark, BOOL /*bIncrement*/, BOOL )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   ScEditableTester aTester( pDoc, rMark );
/*N*/   if (!aTester.IsEditable())
/*N*/   {
/*N*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   ScRange aMarkRange;
/*N*/   rMark.GetMultiMarkArea( aMarkRange );
/*N*/
/*N*/   rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
/*N*/   aModificator.SetDocumentModified();
/*N*/
/*N*/   return TRUE;
/*N*/ }

/*N*/ BOOL ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
/*N*/                           USHORT nFormatNo, BOOL /*bRecord*/, BOOL )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   BOOL bSuccess = FALSE;
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   USHORT nStartCol = rRange.aStart.Col();
/*N*/   USHORT nStartRow = rRange.aStart.Row();
/*N*/   USHORT nStartTab = rRange.aStart.Tab();
/*N*/   USHORT nEndCol = rRange.aEnd.Col();
/*N*/   USHORT nEndRow = rRange.aEnd.Row();
/*N*/   USHORT nEndTab = rRange.aEnd.Tab();
/*N*/
/*N*/   ScMarkData aMark;
/*N*/   if (pTabMark)
/*N*/       aMark = *pTabMark;
/*N*/   else
/*N*/   {
/*N*/       for (USHORT nTab=nStartTab; nTab<=nEndTab; nTab++)
/*N*/           aMark.SelectTable( nTab, TRUE );
/*N*/   }
/*N*/
/*N*/   ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
/*N*/   ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
/*N*/   if ( pAutoFormat && nFormatNo < pAutoFormat->GetCount() && aTester.IsEditable() )
/*N*/   {
/*N*/       WaitObject aWait( rDocShell.GetDialogParent() );
/*N*/
/*N*/       BOOL bSize = (*pAutoFormat)[nFormatNo]->GetIncludeWidthHeight();
/*N*/
/*N*/       USHORT nTabCount = pDoc->GetTableCount();
/*N*/
/*N*/       if (bSize)
/*N*/       {
/*N*/           USHORT nCols[2] = { nStartCol, nEndCol };
/*N*/           USHORT nRows[2] = { nStartRow, nEndRow };
/*N*/
/*N*/           for (USHORT nTab=0; nTab<nTabCount; nTab++)
/*N*/               if (aMark.GetTableSelect(nTab))
/*N*/               {
/*N*/                   SetWidthOrHeight( TRUE, 1,nCols, nTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, FALSE, TRUE );
/*N*/                   SetWidthOrHeight( FALSE,1,nRows, nTab, SC_SIZE_VISOPT, 0, FALSE, FALSE );
/*N*/                   rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
/*N*/                                   PAINT_GRID | PAINT_LEFT | PAINT_TOP );
/*N*/               }
/*N*/       }
/*N*/       else
/*N*/       {
/*N*/           for (USHORT nTab=0; nTab<nTabCount; nTab++)
/*N*/               if (aMark.GetTableSelect(nTab))
/*N*/               {
/*N*/                   BOOL bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, nTab,
/*N*/                                                       nEndCol, nEndRow, nTab), FALSE );
/*N*/                   if (bAdj)
/*N*/                       rDocShell.PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab,
/*N*/                                           PAINT_GRID | PAINT_LEFT );
/*N*/                   else
/*N*/                       rDocShell.PostPaint( nStartCol, nStartRow, nTab,
/*N*/                                           nEndCol, nEndRow, nTab, PAINT_GRID );
/*N*/               }
/*N*/       }
/*N*/
/*N*/       aModificator.SetDocumentModified();
/*N*/   }
/*N*/
/*N*/   return bSuccess;
/*N*/ }

/*N*/ BOOL ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
/*N*/                               const String& rString, BOOL , BOOL bEnglish )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   BOOL bSuccess = FALSE;
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   USHORT nStartCol = rRange.aStart.Col();
/*N*/   USHORT nStartRow = rRange.aStart.Row();
/*N*/   USHORT nStartTab = rRange.aStart.Tab();
/*N*/   USHORT nEndCol = rRange.aEnd.Col();
/*N*/   USHORT nEndRow = rRange.aEnd.Row();
/*N*/   USHORT nEndTab = rRange.aEnd.Tab();
/*N*/
/*N*/   ScMarkData aMark;
/*N*/   if (pTabMark)
/*N*/       aMark = *pTabMark;
/*N*/   else
/*N*/   {
/*N*/       for (USHORT nTab=nStartTab; nTab<=nEndTab; nTab++)
/*N*/           aMark.SelectTable( nTab, TRUE );
/*N*/   }
/*N*/
/*N*/   ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
/*N*/   if ( aTester.IsEditable() )
/*N*/   {
/*N*/       WaitObject aWait( rDocShell.GetDialogParent() );
/*N*/
/*N*/       if ( pDoc->IsImportingXML() )
/*N*/       {
/*N*/           ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString );
/*N*/           pDoc->InsertMatrixFormula(nStartCol,nStartRow,nEndCol,nEndRow,aMark,EMPTY_STRING,pCode);
/*N*/           delete pCode;
/*N*/             pDoc->IncXMLImportedFormulaCount( rString.Len() );
/*N*/       }
/*N*/       else if (bEnglish)
/*N*/         {
/*N*/           ScCompiler aComp( pDoc, rRange.aStart );
/*N*/           aComp.SetCompileEnglish( TRUE );
/*N*/           ScTokenArray* pCode = aComp.CompileString( rString );
/*N*/           pDoc->InsertMatrixFormula(nStartCol,nStartRow,nEndCol,nEndRow,aMark,EMPTY_STRING,pCode);
/*N*/           delete pCode;
/*N*/         }
/*N*/         else
/*N*/           pDoc->InsertMatrixFormula(nStartCol,nStartRow,nEndCol,nEndRow,aMark,rString);
/*N*/
/*N*/       //  Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen
/*N*/       rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID );
/*N*/       aModificator.SetDocumentModified();
/*N*/
/*N*/       bSuccess = TRUE;
/*N*/   }
/*N*/
/*N*/   return bSuccess;
/*N*/ }

/*N*/ inline ScDirection DirFromFillDir( FillDir eDir )
/*N*/ {
/*N*/   if (eDir==FILL_TO_BOTTOM)
/*N*/       return DIR_BOTTOM;
/*N*/   else if (eDir==FILL_TO_RIGHT)
/*N*/       return DIR_RIGHT;
/*N*/   else if (eDir==FILL_TO_TOP)
/*N*/       return DIR_TOP;
/*N*/   else // if (eDir==FILL_TO_LEFT)
/*N*/       return DIR_LEFT;
/*N*/ }

/*N*/ BOOL ScDocFunc::MergeCells( const ScRange& rRange, BOOL /*bContents*/, BOOL /*bRecord*/, BOOL )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   USHORT nStartCol = rRange.aStart.Col();
/*N*/   USHORT nStartRow = rRange.aStart.Row();
/*N*/   USHORT nEndCol = rRange.aEnd.Col();
/*N*/   USHORT nEndRow = rRange.aEnd.Row();
/*N*/   USHORT nTab = rRange.aStart.Tab();
/*N*/
/*N*/   ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow );
/*N*/   if (!aTester.IsEditable())
/*N*/   {
/*?*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   if ( nStartCol == nEndCol && nStartRow == nEndRow )
/*N*/   {
/*N*/       // nichts zu tun
/*N*/       return TRUE;
/*N*/   }
/*N*/
/*N*/   if ( pDoc->HasAttrib( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
/*N*/                           HASATTR_MERGED | HASATTR_OVERLAPPED ) )
/*N*/   {
/*?*/       return FALSE;
/*N*/   }
/*N*/
/*N*/   pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
/*N*/
/*N*/   if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
/*N*/       rDocShell.PostPaint( nStartCol, nStartRow, nTab,
/*N*/                                           nEndCol, nEndRow, nTab, PAINT_GRID );
/*N*/   aModificator.SetDocumentModified();
/*N*/
/*N*/   return TRUE;
/*N*/ }

/*N*/ BOOL ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   pDoc->CompileNameFormula( TRUE );   // CreateFormulaString
/*N*/   pDoc->SetRangeName( new ScRangeName( rNewRanges ) );
/*N*/   pDoc->CompileNameFormula( FALSE );  // CompileFormulaString
/*N*/
/*N*/   aModificator.SetDocumentModified();
/*N*/   SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
/*N*/
/*N*/   return TRUE;
/*N*/ }

/*N*/ void ScDocFunc::CreateOneName( ScRangeName& rList,
/*N*/                               USHORT nPosX, USHORT nPosY, USHORT nTab,
/*N*/                               USHORT nX1, USHORT nY1, USHORT nX2, USHORT nY2,
/*N*/                               BOOL& rCancel, BOOL bApi )
/*N*/ {
/*N*/   if (rCancel)
/*N*/       return;
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   if (!pDoc->HasValueData( nPosX, nPosY, nTab ))
/*N*/   {
/*N*/       String aName;
/*N*/       pDoc->GetString( nPosX, nPosY, nTab, aName );
/*N*/       ScRangeData::MakeValidName(aName);
/*N*/       if (aName.Len())
/*N*/       {
/*N*/           String aContent;
/*N*/             ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format( aContent, SCR_ABS_3D, pDoc );
/*N*/
/*N*/           BOOL bInsert = FALSE;
/*N*/           USHORT nOldPos;
/*N*/           if (rList.SearchName( aName, nOldPos ))         // vorhanden ?
/*N*/           {
/*N*/               ScRangeData* pOld = rList[nOldPos];
/*N*/               String aOldStr;
/*N*/               pOld->GetSymbol( aOldStr );
/*N*/               if (aOldStr != aContent)
/*N*/               {
/*N*/                   if (bApi)
/*N*/                       bInsert = TRUE;     // per API nicht nachfragen
/*N*/                   else
/*N*/                   {
/*N*/                       String aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE );
/*N*/
/*N*/                       String aMessage = aTemplate.GetToken( 0, '#' );
/*N*/                       aMessage += aName;
/*N*/                       aMessage += aTemplate.GetToken( 1, '#' );
/*N*/
/*N*/                       short nResult = QueryBox( rDocShell.GetDialogParent(),
/*N*/                                                   WinBits(WB_YES_NO_CANCEL | WB_DEF_YES),
/*N*/                                                   aMessage ).Execute();
/*N*/                       if ( nResult == RET_YES )
/*N*/                       {
/*N*/                           rList.AtFree(nOldPos);
/*N*/                           bInsert = TRUE;
/*N*/                       }
/*N*/                       else if ( nResult == RET_CANCEL )
/*N*/                           rCancel = TRUE;
/*N*/                   }
/*N*/               }
/*N*/           }
/*N*/           else
/*N*/               bInsert = TRUE;
/*N*/
/*N*/           if (bInsert)
/*N*/           {
/*N*/               ScRangeData* pData = new ScRangeData( pDoc, aName, aContent, nPosX, nPosY, nTab );
/*N*/               if (!rList.Insert(pData))
/*N*/               {
/*N*/                   OSL_FAIL("nanu?");
/*N*/                   delete pData;
/*N*/               }
/*N*/           }
/*N*/       }
/*N*/   }
/*N*/ }

/*N*/ BOOL ScDocFunc::CreateNames( const ScRange& rRange, USHORT nFlags, BOOL bApi )
/*N*/ {
/*N*/   if (!nFlags)
/*N*/       return FALSE;       // war nix
/*N*/
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/   BOOL bDone = FALSE;
/*N*/   USHORT nStartCol = rRange.aStart.Col();
/*N*/   USHORT nStartRow = rRange.aStart.Row();
/*N*/   USHORT nEndCol = rRange.aEnd.Col();
/*N*/   USHORT nEndRow = rRange.aEnd.Row();
/*N*/   USHORT nTab = rRange.aStart.Tab();
/*N*/   DBG_ASSERT(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht");
/*N*/
/*N*/   BOOL bValid = TRUE;
/*N*/   if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) )
/*N*/       if ( nStartRow == nEndRow )
/*N*/           bValid = FALSE;
/*N*/   if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) )
/*N*/       if ( nStartCol == nEndCol )
/*N*/           bValid = FALSE;
/*N*/
/*N*/   if (bValid)
/*N*/   {
/*N*/       ScDocument* pDoc = rDocShell.GetDocument();
/*N*/       ScRangeName* pNames = pDoc->GetRangeName();
/*N*/       if (!pNames)
/*N*/           return FALSE;   // soll nicht sein
/*N*/       ScRangeName aNewRanges( *pNames );
/*N*/
/*N*/       BOOL bTop    = ( ( nFlags & NAME_TOP ) != 0 );
/*N*/       BOOL bLeft   = ( ( nFlags & NAME_LEFT ) != 0 );
/*N*/       BOOL bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 );
/*N*/       BOOL bRight  = ( ( nFlags & NAME_RIGHT ) != 0 );
/*N*/
/*N*/       USHORT nContX1 = nStartCol;
/*N*/       USHORT nContY1 = nStartRow;
/*N*/       USHORT nContX2 = nEndCol;
/*N*/       USHORT nContY2 = nEndRow;
/*N*/
/*N*/       if ( bTop )
/*N*/           ++nContY1;
/*N*/       if ( bLeft )
/*N*/           ++nContX1;
/*N*/       if ( bBottom )
/*N*/           --nContY2;
/*N*/       if ( bRight )
/*N*/           --nContX2;
/*N*/
/*N*/       BOOL bCancel = FALSE;
/*N*/       USHORT i;
/*N*/
/*N*/       if ( bTop )
/*N*/           for (i=nContX1; i<=nContX2; i++)
/*N*/               CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
/*N*/       if ( bLeft )
/*N*/           for (i=nContY1; i<=nContY2; i++)
/*N*/               CreateOneName( aNewRanges, nStartCol,i,nTab, nContX1,i,nContX2,i, bCancel, bApi );
/*N*/       if ( bBottom )
/*N*/           for (i=nContX1; i<=nContX2; i++)
/*N*/               CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
/*N*/       if ( bRight )
/*N*/           for (i=nContY1; i<=nContY2; i++)
/*N*/               CreateOneName( aNewRanges, nEndCol,i,nTab, nContX1,i,nContX2,i, bCancel, bApi );
/*N*/
/*N*/       if ( bTop && bLeft )
/*N*/           CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
/*N*/       if ( bTop && bRight )
/*N*/           CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
/*N*/       if ( bBottom && bLeft )
/*N*/           CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
/*N*/       if ( bBottom && bRight )
/*N*/           CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
/*N*/
/*N*/       bDone = ModifyRangeNames( aNewRanges );
/*N*/
/*N*/       aModificator.SetDocumentModified();
/*N*/       SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
/*N*/   }
/*N*/
/*N*/   return bDone;
/*N*/ }

/*N*/ BOOL ScDocFunc::InsertNameList( const ScAddress& rStartPos, BOOL )
/*N*/ {
/*N*/   ScDocShellModificator aModificator( rDocShell );
/*N*/
/*N*/
/*N*/   BOOL bDone = FALSE;
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/   USHORT nTab = rStartPos.Tab();
/*N*/
/*N*/   ScRangeName* pList = pDoc->GetRangeName();
/*N*/   USHORT nCount = pList->GetCount();
/*N*/   USHORT nValidCount = 0;
/*N*/   USHORT i;
/*N*/   for (i=0; i<nCount; i++)
/*N*/   {
/*N*/       ScRangeData* pData = (*pList)[i];
/*N*/       if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
/*N*/           ++nValidCount;
/*N*/   }
/*N*/
/*N*/   if (nValidCount)
/*N*/   {
/*N*/       USHORT nStartCol = rStartPos.Col();
/*N*/       USHORT nStartRow = rStartPos.Row();
/*N*/       USHORT nEndCol = nStartCol + 1;
/*N*/       USHORT nEndRow = nStartRow + nValidCount - 1;
/*N*/
/*N*/       ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
/*N*/       if (aTester.IsEditable())
/*N*/       {
/*N*/           ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ];
/*N*/           USHORT j = 0;
/*N*/           for (i=0; i<nCount; i++)
/*N*/           {
/*N*/               ScRangeData* pData = (*pList)[i];
/*N*/               if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
/*N*/                   ppSortArray[j++] = pData;
/*N*/           }
/*N*/ #ifndef ICC
/*N*/           qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
/*N*/               &ScRangeData::QsortNameCompare );
/*N*/ #else
/*N*/           qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
/*N*/               ICCQsortNameCompare );
/*N*/ #endif
/*N*/           String aName;
/*N*/           String aContent;
/*N*/           String aFormula;
/*N*/           USHORT nOutRow = nStartRow;
/*N*/           for (j=0; j<nValidCount; j++)
/*N*/           {
/*N*/               ScRangeData* pData = ppSortArray[j];
/*N*/               pData->GetName(aName);
/*N*/               // relative Referenzen Excel-konform auf die linke Spalte anpassen:
/*N*/               pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab ));
/*N*/               aFormula = '=';
/*N*/               aFormula += aContent;
/*N*/               pDoc->PutCell( nStartCol,nOutRow,nTab, new ScStringCell( aName ) );
/*N*/               pDoc->PutCell( nEndCol  ,nOutRow,nTab, new ScStringCell( aFormula ) );
/*N*/               ++nOutRow;
/*N*/           }
/*N*/
/*N*/           delete [] ppSortArray;
/*N*/
/*N*/           if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab)))
/*N*/               rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID );
/*N*/ //!           rDocShell.UpdateOle(GetViewData());
/*N*/           aModificator.SetDocumentModified();
/*N*/           bDone = TRUE;
/*N*/       }
/*N*/   }
/*N*/   return bDone;
/*N*/ }

/*N*/ BOOL ScDocFunc::InsertAreaLink( const String& rFile, const String& rFilter,
/*N*/                               const String& rOptions, const String& rSource,
/*N*/                               const ScRange& rDestRange, ULONG nRefresh,
/*N*/                               BOOL bFitBlock )
/*N*/ {
/*N*/   //! auch fuer ScViewFunc::InsertAreaLink benutzen!
/*N*/
/*N*/   ScDocument* pDoc = rDocShell.GetDocument();
/*N*/
/*N*/   String aFilterName = rFilter;
/*N*/   String aNewOptions = rOptions;
/*N*/   if (!aFilterName.Len())
/*N*/       ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions );
/*N*/
/*N*/   //  remove application prefix from filter name here, so the filter options
/*N*/   //  aren't reset when the filter name is changed in ScAreaLink::DataChanged
/*N*/   ScDocumentLoader::RemoveAppPrefix( aFilterName );
/*N*/
/*N*/   SvxLinkManager* pLinkManager = pDoc->GetLinkManager();
/*N*/
/*N*/   ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName,
/*N*/                                       aNewOptions, rSource, rDestRange, nRefresh );
/*N*/   pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aFilterName, &rSource );
/*N*/
/*N*/   pLink->SetDoInsert(bFitBlock);  // beim ersten Update ggf. nichts einfuegen
/*N*/   pLink->Update();                // kein SetInCreate -> Update ausfuehren
/*N*/   pLink->SetDoInsert(TRUE);       // Default = TRUE
/*N*/
/*N*/
/*N*/   SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );     // Navigator
/*N*/
/*N*/   return TRUE;
/*N*/ }




}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
