LCOV - code coverage report
Current view: top level - sc/source/core/tool - detfunc.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 266 880 30.2 %
Date: 2012-08-25 Functions: 23 57 40.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 311 1722 18.1 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include "scitems.hxx"
      30                 :            : #include <svtools/colorcfg.hxx>
      31                 :            : #include <editeng/eeitem.hxx>
      32                 :            : #include <editeng/outlobj.hxx>
      33                 :            : #include <svx/sdshitm.hxx>
      34                 :            : #include <svx/sdsxyitm.hxx>
      35                 :            : #include <svx/sdtditm.hxx>
      36                 :            : #include <svx/svditer.hxx>
      37                 :            : #include <svx/svdocapt.hxx>
      38                 :            : #include <svx/svdocirc.hxx>
      39                 :            : #include <svx/svdopath.hxx>
      40                 :            : #include <svx/svdorect.hxx>
      41                 :            : #include <svx/svdpage.hxx>
      42                 :            : #include <svx/svdundo.hxx>
      43                 :            : #include <svx/xfillit0.hxx>
      44                 :            : #include <svx/xflclit.hxx>
      45                 :            : #include <svx/xlnclit.hxx>
      46                 :            : #include <svx/xlnedcit.hxx>
      47                 :            : #include <svx/xlnedit.hxx>
      48                 :            : #include <svx/xlnedwit.hxx>
      49                 :            : #include <svx/xlnstcit.hxx>
      50                 :            : #include <svx/xlnstit.hxx>
      51                 :            : #include <svx/xlnstwit.hxx>
      52                 :            : #include <svx/xlnwtit.hxx>
      53                 :            : #include <svx/xtable.hxx>
      54                 :            : #include <editeng/outliner.hxx>
      55                 :            : #include <editeng/editobj.hxx>
      56                 :            : #include <svx/sxcecitm.hxx>
      57                 :            : #include <svl/whiter.hxx>
      58                 :            : #include <editeng/writingmodeitem.hxx>
      59                 :            : 
      60                 :            : #include <basegfx/point/b2dpoint.hxx>
      61                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      62                 :            : #include <basegfx/polygon/b2dpolygon.hxx>
      63                 :            : 
      64                 :            : #include "detfunc.hxx"
      65                 :            : #include "document.hxx"
      66                 :            : #include "dociter.hxx"
      67                 :            : #include "drwlayer.hxx"
      68                 :            : #include "userdat.hxx"
      69                 :            : #include "validat.hxx"
      70                 :            : #include "cell.hxx"
      71                 :            : #include "docpool.hxx"
      72                 :            : #include "patattr.hxx"
      73                 :            : #include "attrib.hxx"
      74                 :            : #include "scmod.hxx"
      75                 :            : #include "postit.hxx"
      76                 :            : #include "rangelst.hxx"
      77                 :            : #include "reftokenhelper.hxx"
      78                 :            : 
      79                 :            : #include <vector>
      80                 :            : 
      81                 :            : using ::std::vector;
      82                 :            : 
      83                 :            : //------------------------------------------------------------------------
      84                 :            : 
      85                 :            : // line ends are now created with an empty name.
      86                 :            : // The checkForUniqueItem method then finds a unique name for the item's value.
      87                 :            : #define SC_LINEEND_NAME     EMPTY_STRING
      88                 :            : 
      89                 :            : //------------------------------------------------------------------------
      90                 :            : 
      91                 :            : enum DetInsertResult {              // Return-Werte beim Einfuegen in einen Level
      92                 :            :             DET_INS_CONTINUE,
      93                 :            :             DET_INS_INSERTED,
      94                 :            :             DET_INS_EMPTY,
      95                 :            :             DET_INS_CIRCULAR };
      96                 :            : 
      97                 :            : 
      98                 :            : //------------------------------------------------------------------------
      99                 :            : 
     100 [ +  - ][ +  - ]:         13 : class ScDetectiveData
         [ +  - ][ +  - ]
     101                 :            : {
     102                 :            : private:
     103                 :            :     SfxItemSet  aBoxSet;
     104                 :            :     SfxItemSet  aArrowSet;
     105                 :            :     SfxItemSet  aToTabSet;
     106                 :            :     SfxItemSet  aFromTabSet;
     107                 :            :     SfxItemSet  aCircleSet;         //! einzeln ?
     108                 :            :     sal_uInt16      nMaxLevel;
     109                 :            : 
     110                 :            : public:
     111                 :            :                 ScDetectiveData( SdrModel* pModel );
     112                 :            : 
     113                 :          0 :     SfxItemSet& GetBoxSet()     { return aBoxSet; }
     114                 :          1 :     SfxItemSet& GetArrowSet()   { return aArrowSet; }
     115                 :          0 :     SfxItemSet& GetToTabSet()   { return aToTabSet; }
     116                 :         12 :     SfxItemSet& GetFromTabSet() { return aFromTabSet; }
     117                 :          0 :     SfxItemSet& GetCircleSet()  { return aCircleSet; }
     118                 :            : 
     119                 :         13 :     void        SetMaxLevel( sal_uInt16 nVal )      { nMaxLevel = nVal; }
     120                 :          0 :     sal_uInt16      GetMaxLevel() const             { return nMaxLevel; }
     121                 :            : };
     122                 :            : 
     123                 :          0 : class ScCommentData
     124                 :            : {
     125                 :            : public:
     126                 :            :                         ScCommentData( ScDocument& rDoc, SdrModel* pModel );
     127                 :            : 
     128                 :          0 :     SfxItemSet&         GetCaptionSet() { return aCaptionSet; }
     129                 :            :     void                UpdateCaptionSet( const SfxItemSet& rItemSet );
     130                 :            : 
     131                 :            : private:
     132                 :            :     SfxItemSet          aCaptionSet;
     133                 :            : };
     134                 :            : 
     135                 :            : //------------------------------------------------------------------------
     136                 :            : 
     137                 :            : ColorData ScDetectiveFunc::nArrowColor = 0;
     138                 :            : ColorData ScDetectiveFunc::nErrorColor = 0;
     139                 :            : ColorData ScDetectiveFunc::nCommentColor = 0;
     140                 :            : sal_Bool ScDetectiveFunc::bColorsInitialized = false;
     141                 :            : 
     142                 :            : //------------------------------------------------------------------------
     143                 :            : 
     144                 :          0 : sal_Bool lcl_HasThickLine( SdrObject& rObj )
     145                 :            : {
     146                 :            :     // thin lines get width 0 -> everything greater 0 is a thick line
     147                 :            : 
     148                 :          0 :     return ( ((const XLineWidthItem&)rObj.GetMergedItem(XATTR_LINEWIDTH)).GetValue() > 0 );
     149                 :            : }
     150                 :            : 
     151                 :            : //------------------------------------------------------------------------
     152                 :            : 
     153                 :         13 : ScDetectiveData::ScDetectiveData( SdrModel* pModel ) :
     154                 :         13 :     aBoxSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ),
     155                 :         13 :     aArrowSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ),
     156                 :         13 :     aToTabSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ),
     157                 :         13 :     aFromTabSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ),
     158 [ +  - ][ +  -  :         52 :     aCircleSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END )
             +  -  +  - ]
     159                 :            : {
     160                 :         13 :     nMaxLevel = 0;
     161                 :            : 
     162 [ +  - ][ +  - ]:         13 :     aBoxSet.Put( XLineColorItem( EMPTY_STRING, Color( ScDetectiveFunc::GetArrowColor() ) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     163 [ +  - ][ +  - ]:         13 :     aBoxSet.Put( XFillStyleItem( XFILL_NONE ) );
                 [ +  - ]
     164                 :            : 
     165                 :            :     //  Standard-Linienenden (wie aus XLineEndList::Create) selber zusammenbasteln,
     166                 :            :     //  um von den konfigurierten Linienenden unabhaengig zu sein
     167                 :            : 
     168         [ +  - ]:         13 :     basegfx::B2DPolygon aTriangle;
     169         [ +  - ]:         13 :     aTriangle.append(basegfx::B2DPoint(10.0, 0.0));
     170         [ +  - ]:         13 :     aTriangle.append(basegfx::B2DPoint(0.0, 30.0));
     171         [ +  - ]:         13 :     aTriangle.append(basegfx::B2DPoint(20.0, 30.0));
     172         [ +  - ]:         13 :     aTriangle.setClosed(true);
     173                 :            : 
     174         [ +  - ]:         13 :     basegfx::B2DPolygon aSquare;
     175         [ +  - ]:         13 :     aSquare.append(basegfx::B2DPoint(0.0, 0.0));
     176         [ +  - ]:         13 :     aSquare.append(basegfx::B2DPoint(10.0, 0.0));
     177         [ +  - ]:         13 :     aSquare.append(basegfx::B2DPoint(10.0, 10.0));
     178         [ +  - ]:         13 :     aSquare.append(basegfx::B2DPoint(0.0, 10.0));
     179         [ +  - ]:         13 :     aSquare.setClosed(true);
     180                 :            : 
     181         [ +  - ]:         13 :     basegfx::B2DPolygon aCircle(basegfx::tools::createPolygonFromEllipse(basegfx::B2DPoint(0.0, 0.0), 100.0, 100.0));
     182         [ +  - ]:         13 :     aCircle.setClosed(true);
     183                 :            : 
     184 [ +  - ][ +  - ]:         13 :     String aName = SC_LINEEND_NAME;
     185                 :            : 
     186 [ +  - ][ +  - ]:         13 :     aArrowSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aCircle) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     187 [ +  - ][ +  - ]:         13 :     aArrowSet.Put( XLineStartWidthItem( 200 ) );
                 [ +  - ]
     188 [ +  - ][ +  - ]:         13 :     aArrowSet.Put( XLineStartCenterItem( sal_True ) );
                 [ +  - ]
     189 [ +  - ][ +  - ]:         13 :     aArrowSet.Put( XLineEndItem( aName, basegfx::B2DPolyPolygon(aTriangle) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     190 [ +  - ][ +  - ]:         13 :     aArrowSet.Put( XLineEndWidthItem( 200 ) );
                 [ +  - ]
     191 [ +  - ][ +  - ]:         13 :     aArrowSet.Put( XLineEndCenterItem( false ) );
                 [ +  - ]
     192                 :            : 
     193 [ +  - ][ +  - ]:         13 :     aToTabSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aCircle) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     194 [ +  - ][ +  - ]:         13 :     aToTabSet.Put( XLineStartWidthItem( 200 ) );
                 [ +  - ]
     195 [ +  - ][ +  - ]:         13 :     aToTabSet.Put( XLineStartCenterItem( sal_True ) );
                 [ +  - ]
     196 [ +  - ][ +  - ]:         13 :     aToTabSet.Put( XLineEndItem( aName, basegfx::B2DPolyPolygon(aSquare) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     197 [ +  - ][ +  - ]:         13 :     aToTabSet.Put( XLineEndWidthItem( 300 ) );
                 [ +  - ]
     198 [ +  - ][ +  - ]:         13 :     aToTabSet.Put( XLineEndCenterItem( false ) );
                 [ +  - ]
     199                 :            : 
     200 [ +  - ][ +  - ]:         13 :     aFromTabSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aSquare) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     201 [ +  - ][ +  - ]:         13 :     aFromTabSet.Put( XLineStartWidthItem( 300 ) );
                 [ +  - ]
     202 [ +  - ][ +  - ]:         13 :     aFromTabSet.Put( XLineStartCenterItem( sal_True ) );
                 [ +  - ]
     203 [ +  - ][ +  - ]:         13 :     aFromTabSet.Put( XLineEndItem( aName, basegfx::B2DPolyPolygon(aTriangle) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     204 [ +  - ][ +  - ]:         13 :     aFromTabSet.Put( XLineEndWidthItem( 200 ) );
                 [ +  - ]
     205 [ +  - ][ +  - ]:         13 :     aFromTabSet.Put( XLineEndCenterItem( false ) );
                 [ +  - ]
     206                 :            : 
     207 [ +  - ][ +  - ]:         13 :     aCircleSet.Put( XLineColorItem( String(), Color( ScDetectiveFunc::GetErrorColor() ) ) );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     208 [ +  - ][ +  - ]:         13 :     aCircleSet.Put( XFillStyleItem( XFILL_NONE ) );
                 [ +  - ]
     209                 :         13 :     sal_uInt16 nWidth = 55;     // 54 = 1 Pixel
     210 [ +  - ][ +  - ]:         13 :     aCircleSet.Put( XLineWidthItem( nWidth ) );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     211                 :         13 : }
     212                 :            : 
     213                 :          0 : ScCommentData::ScCommentData( ScDocument& rDoc, SdrModel* pModel ) :
     214                 :          0 :     aCaptionSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END, EE_ITEMS_START, EE_ITEMS_END, 0, 0 )
     215                 :            : {
     216         [ #  # ]:          0 :     basegfx::B2DPolygon aTriangle;
     217         [ #  # ]:          0 :     aTriangle.append(basegfx::B2DPoint(10.0, 0.0));
     218         [ #  # ]:          0 :     aTriangle.append(basegfx::B2DPoint(0.0, 30.0));
     219         [ #  # ]:          0 :     aTriangle.append(basegfx::B2DPoint(20.0, 30.0));
     220         [ #  # ]:          0 :     aTriangle.setClosed(true);
     221                 :            : 
     222 [ #  # ][ #  # ]:          0 :     String aName = SC_LINEEND_NAME;
     223                 :            : 
     224 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aTriangle) ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     225 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( XLineStartWidthItem( 200 ) );
                 [ #  # ]
     226 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( XLineStartCenterItem( false ) );
                 [ #  # ]
     227 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( XFillStyleItem( XFILL_SOLID ) );
                 [ #  # ]
     228         [ #  # ]:          0 :     Color aYellow( ScDetectiveFunc::GetCommentColor() );
     229 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( XFillColorItem( String(), aYellow ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     230                 :            : 
     231                 :            :     //  shadow
     232                 :            :     //  SdrShadowItem has sal_False, instead the shadow is set for the rectangle
     233                 :            :     //  only with SetSpecialTextBoxShadow when the object is created
     234                 :            :     //  (item must be set to adjust objects from older files)
     235 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrShadowItem( false ) );
                 [ #  # ]
     236 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrShadowXDistItem( 100 ) );
                 [ #  # ]
     237 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrShadowYDistItem( 100 ) );
                 [ #  # ]
     238                 :            : 
     239                 :            :     //  text attributes
     240 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrTextLeftDistItem( 100 ) );
                 [ #  # ]
     241 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrTextRightDistItem( 100 ) );
                 [ #  # ]
     242 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrTextUpperDistItem( 100 ) );
                 [ #  # ]
     243 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrTextLowerDistItem( 100 ) );
                 [ #  # ]
     244                 :            : 
     245 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrTextAutoGrowWidthItem( false ) );
                 [ #  # ]
     246 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrTextAutoGrowHeightItem( sal_True ) );
                 [ #  # ]
     247                 :            : 
     248                 :            :     //  do use the default cell style, so the user has a chance to
     249                 :            :     //  modify the font for the annotations
     250 [ #  # ][ #  # ]:          0 :     ((const ScPatternAttr&)rDoc.GetPool()->GetDefaultItem(ATTR_PATTERN)).
     251         [ #  # ]:          0 :         FillEditItemSet( &aCaptionSet );
     252                 :            : 
     253                 :            :     // support the best position for the tail connector now that
     254                 :            :     // that notes can be resized and repositioned.
     255 [ #  # ][ #  # ]:          0 :     aCaptionSet.Put( SdrCaptionEscDirItem( SDRCAPT_ESCBESTFIT) );
         [ #  # ][ #  # ]
                 [ #  # ]
     256                 :          0 : }
     257                 :            : 
     258                 :          0 : void ScCommentData::UpdateCaptionSet( const SfxItemSet& rItemSet )
     259                 :            : {
     260         [ #  # ]:          0 :     SfxWhichIter aWhichIter( rItemSet );
     261                 :          0 :     const SfxPoolItem* pPoolItem = 0;
     262                 :            : 
     263 [ #  # ][ #  # ]:          0 :     for( sal_uInt16 nWhich = aWhichIter.FirstWhich(); nWhich > 0; nWhich = aWhichIter.NextWhich() )
                 [ #  # ]
     264                 :            :     {
     265 [ #  # ][ #  # ]:          0 :         if(rItemSet.GetItemState(nWhich, false, &pPoolItem) == SFX_ITEM_SET)
     266                 :            :         {
     267   [ #  #  #  # ]:          0 :             switch(nWhich)
     268                 :            :             {
     269                 :            :                 case SDRATTR_SHADOW:
     270                 :            :                     // use existing Caption default - appears that setting this
     271                 :            :                     // to true screws up the tail appearance. See also comment
     272                 :            :                     // for default setting above.
     273                 :          0 :                 break;
     274                 :            :                 case SDRATTR_SHADOWXDIST:
     275                 :            :                     // use existing Caption default - svx sets a value of 35
     276                 :            :                     // but default 100 gives a better appearance.
     277                 :          0 :                 break;
     278                 :            :                 case SDRATTR_SHADOWYDIST:
     279                 :            :                     // use existing Caption default - svx sets a value of 35
     280                 :            :                     // but default 100 gives a better appearance.
     281                 :          0 :                 break;
     282                 :            : 
     283                 :            :                 default:
     284         [ #  # ]:          0 :                     aCaptionSet.Put(*pPoolItem);
     285                 :            :            }
     286                 :            :         }
     287         [ #  # ]:          0 :     }
     288                 :          0 : }
     289                 :            : 
     290                 :            : //------------------------------------------------------------------------
     291                 :            : 
     292                 :         25 : void ScDetectiveFunc::Modified()
     293                 :            : {
     294         [ -  + ]:         25 :     if (pDoc->IsStreamValid(nTab))
     295                 :          0 :         pDoc->SetStreamValid(nTab, false);
     296                 :         25 : }
     297                 :            : 
     298                 :          0 : inline sal_Bool Intersect( SCCOL nStartCol1, SCROW nStartRow1, SCCOL nEndCol1, SCROW nEndRow1,
     299                 :            :                         SCCOL nStartCol2, SCROW nStartRow2, SCCOL nEndCol2, SCROW nEndRow2 )
     300                 :            : {
     301                 :            :     return nEndCol1 >= nStartCol2 && nEndCol2 >= nStartCol1 &&
     302 [ #  # ][ #  # ]:          0 :             nEndRow1 >= nStartRow2 && nEndRow2 >= nStartRow1;
         [ #  # ][ #  # ]
     303                 :            : }
     304                 :            : 
     305                 :         13 : sal_Bool ScDetectiveFunc::HasError( const ScRange& rRange, ScAddress& rErrPos )
     306                 :            : {
     307                 :         13 :     rErrPos = rRange.aStart;
     308                 :         13 :     sal_uInt16 nError = 0;
     309                 :            : 
     310         [ +  - ]:         13 :     ScCellIterator aCellIter( pDoc, rRange);
     311         [ +  - ]:         13 :     ScBaseCell* pCell = aCellIter.GetFirst();
     312         [ +  + ]:         26 :     while (pCell)
     313                 :            :     {
     314         [ -  + ]:         13 :         if (pCell->GetCellType() == CELLTYPE_FORMULA)
     315                 :            :         {
     316 [ #  # ][ #  # ]:          0 :             nError = ((ScFormulaCell*)pCell)->GetErrCode();
     317         [ #  # ]:          0 :             if (nError)
     318                 :          0 :                 rErrPos.Set( aCellIter.GetCol(), aCellIter.GetRow(), aCellIter.GetTab() );
     319                 :            :         }
     320         [ +  - ]:         13 :         pCell = aCellIter.GetNext();
     321                 :            :     }
     322                 :            : 
     323                 :         13 :     return (nError != 0);
     324                 :            : }
     325                 :            : 
     326                 :         54 : Point ScDetectiveFunc::GetDrawPos( SCCOL nCol, SCROW nRow, DrawPosMode eMode ) const
     327                 :            : {
     328                 :            :     OSL_ENSURE( ValidColRow( nCol, nRow ), "ScDetectiveFunc::GetDrawPos - invalid cell address" );
     329                 :         54 :     SanitizeCol( nCol );
     330                 :         54 :     SanitizeRow( nRow );
     331                 :            : 
     332                 :         54 :     Point aPos;
     333                 :            : 
     334   [ +  +  +  -  :         54 :     switch( eMode )
                   -  - ]
     335                 :            :     {
     336                 :            :         case DRAWPOS_TOPLEFT:
     337                 :         14 :         break;
     338                 :            :         case DRAWPOS_BOTTOMRIGHT:
     339                 :         14 :             ++nCol;
     340                 :         14 :             ++nRow;
     341                 :         14 :         break;
     342                 :            :         case DRAWPOS_DETARROW:
     343                 :         26 :             aPos.X() += pDoc->GetColWidth( nCol, nTab ) / 4;
     344                 :         26 :             aPos.Y() += pDoc->GetRowHeight( nRow, nTab ) / 2;
     345                 :         26 :         break;
     346                 :            :         case DRAWPOS_CAPTIONLEFT:
     347                 :          0 :             aPos.X() += 6;
     348                 :          0 :         break;
     349                 :            :         case DRAWPOS_CAPTIONRIGHT:
     350                 :            :         {
     351                 :            :             // find right end of passed cell position
     352                 :          0 :             const ScMergeAttr* pMerge = static_cast< const ScMergeAttr* >( pDoc->GetAttr( nCol, nRow, nTab, ATTR_MERGE ) );
     353         [ #  # ]:          0 :             if ( pMerge->GetColMerge() > 1 )
     354                 :          0 :                 nCol = nCol + pMerge->GetColMerge();
     355                 :            :             else
     356                 :          0 :                 ++nCol;
     357                 :          0 :             aPos.X() -= 6;
     358                 :            :         }
     359                 :          0 :         break;
     360                 :            :     }
     361                 :            : 
     362         [ +  + ]:        392 :     for ( SCCOL i = 0; i < nCol; ++i )
     363                 :        338 :         aPos.X() += pDoc->GetColWidth( i, nTab );
     364                 :         54 :     aPos.Y() += pDoc->GetRowHeight( 0, nRow - 1, nTab );
     365                 :            : 
     366                 :         54 :     aPos.X() = static_cast< long >( aPos.X() * HMM_PER_TWIPS );
     367                 :         54 :     aPos.Y() = static_cast< long >( aPos.Y() * HMM_PER_TWIPS );
     368                 :            : 
     369         [ -  + ]:         54 :     if ( pDoc->IsNegativePage( nTab ) )
     370                 :          0 :         aPos.X() *= -1;
     371                 :            : 
     372                 :         54 :     return aPos;
     373                 :            : }
     374                 :            : 
     375                 :         14 : Rectangle ScDetectiveFunc::GetDrawRect( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const
     376                 :            : {
     377                 :            :     Rectangle aRect(
     378 [ +  - ][ +  - ]:         14 :         GetDrawPos( ::std::min( nCol1, nCol2 ), ::std::min( nRow1, nRow2 ), DRAWPOS_TOPLEFT ),
     379 [ +  - ][ +  - ]:         28 :         GetDrawPos( ::std::max( nCol1, nCol2 ), ::std::max( nRow1, nRow2 ), DRAWPOS_BOTTOMRIGHT ) );
     380                 :         14 :     aRect.Justify();    // reorder left/right in RTL sheets
     381                 :         14 :     return aRect;
     382                 :            : }
     383                 :            : 
     384                 :         14 : Rectangle ScDetectiveFunc::GetDrawRect( SCCOL nCol, SCROW nRow ) const
     385                 :            : {
     386                 :         14 :     return GetDrawRect( nCol, nRow, nCol, nRow );
     387                 :            : }
     388                 :            : 
     389                 :          0 : sal_Bool lcl_IsOtherTab( const basegfx::B2DPolyPolygon& rPolyPolygon )
     390                 :            : {
     391                 :            :     //  test if rPolygon is the line end for "other table" (rectangle)
     392         [ #  # ]:          0 :     if(1L == rPolyPolygon.count())
     393                 :            :     {
     394         [ #  # ]:          0 :         const basegfx::B2DPolygon aSubPoly(rPolyPolygon.getB2DPolygon(0L));
     395                 :            : 
     396                 :            :         // #i73305# circle consists of 4 segments, too, distinguishable from square by
     397                 :            :         // the use of control points
     398 [ #  # ][ #  # ]:          0 :         if(4L == aSubPoly.count() && aSubPoly.isClosed() && !aSubPoly.areControlPointsUsed())
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     399                 :            :         {
     400                 :          0 :             return true;
     401 [ #  # ][ #  # ]:          0 :         }
     402                 :            :     }
     403                 :            : 
     404                 :          0 :     return false;
     405                 :            : }
     406                 :            : 
     407                 :         13 : sal_Bool ScDetectiveFunc::HasArrow( const ScAddress& rStart,
     408                 :            :                                     SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab )
     409                 :            : {
     410                 :         13 :     sal_Bool bStartAlien = ( rStart.Tab() != nTab );
     411                 :         13 :     sal_Bool bEndAlien   = ( nEndTab != nTab );
     412                 :            : 
     413 [ -  + ][ +  + ]:         13 :     if (bStartAlien && bEndAlien)
     414                 :            :     {
     415                 :            :         OSL_FAIL("bStartAlien && bEndAlien");
     416                 :          0 :         return true;
     417                 :            :     }
     418                 :            : 
     419         [ +  - ]:         13 :     Rectangle aStartRect;
     420         [ +  - ]:         13 :     Rectangle aEndRect;
     421         [ +  + ]:         13 :     if (!bStartAlien)
     422         [ +  - ]:          1 :         aStartRect = GetDrawRect( rStart.Col(), rStart.Row() );
     423         [ +  - ]:         13 :     if (!bEndAlien)
     424         [ +  - ]:         13 :         aEndRect = GetDrawRect( nEndCol, nEndRow );
     425                 :            : 
     426         [ +  - ]:         13 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
     427         [ +  - ]:         13 :     SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
     428                 :            :     OSL_ENSURE(pPage,"Page ?");
     429                 :            : 
     430                 :         13 :     sal_Bool bFound = false;
     431         [ +  - ]:         13 :     SdrObjListIter aIter( *pPage, IM_FLAT );
     432         [ +  - ]:         13 :     SdrObject* pObject = aIter.Next();
     433 [ -  + ][ #  # ]:         13 :     while (pObject && !bFound)
                 [ -  + ]
     434                 :            :     {
     435 [ #  # ][ #  # ]:          0 :         if ( pObject->GetLayer()==SC_LAYER_INTERN &&
         [ #  # ][ #  # ]
                 [ #  # ]
     436 [ #  # ][ #  # ]:          0 :                 pObject->IsPolyObj() && pObject->GetPointCount()==2 )
     437                 :            :         {
     438         [ #  # ]:          0 :             const SfxItemSet& rSet = pObject->GetMergedItemSet();
     439                 :            : 
     440                 :            :             sal_Bool bObjStartAlien =
     441 [ #  # ][ #  # ]:          0 :                 lcl_IsOtherTab( ((const XLineStartItem&)rSet.Get(XATTR_LINESTART)).GetLineStartValue() );
         [ #  # ][ #  # ]
     442                 :            :             sal_Bool bObjEndAlien =
     443 [ #  # ][ #  # ]:          0 :                 lcl_IsOtherTab( ((const XLineEndItem&)rSet.Get(XATTR_LINEEND)).GetLineEndValue() );
         [ #  # ][ #  # ]
     444                 :            : 
     445                 :            :             sal_Bool bStartHit = bStartAlien ? bObjStartAlien :
     446 [ #  # ][ #  # ]:          0 :                                 ( !bObjStartAlien && aStartRect.IsInside(pObject->GetPoint(0)) );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     447                 :            :             sal_Bool bEndHit = bEndAlien ? bObjEndAlien :
     448 [ #  # ][ #  # ]:          0 :                                 ( !bObjEndAlien && aEndRect.IsInside(pObject->GetPoint(1)) );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     449                 :            : 
     450 [ #  # ][ #  # ]:          0 :             if ( bStartHit && bEndHit )
     451                 :          0 :                 bFound = sal_True;
     452                 :            :         }
     453         [ #  # ]:          0 :         pObject = aIter.Next();
     454                 :            :     }
     455                 :            : 
     456                 :         13 :     return bFound;
     457                 :            : }
     458                 :            : 
     459                 :          0 : sal_Bool ScDetectiveFunc::IsNonAlienArrow( SdrObject* pObject )
     460                 :            : {
     461   [ #  #  #  #  :          0 :     if ( pObject->GetLayer()==SC_LAYER_INTERN &&
           #  # ][ #  # ]
     462                 :          0 :             pObject->IsPolyObj() && pObject->GetPointCount()==2 )
     463                 :            :     {
     464                 :          0 :         const SfxItemSet& rSet = pObject->GetMergedItemSet();
     465                 :            : 
     466                 :            :         sal_Bool bObjStartAlien =
     467         [ #  # ]:          0 :             lcl_IsOtherTab( ((const XLineStartItem&)rSet.Get(XATTR_LINESTART)).GetLineStartValue() );
     468                 :            :         sal_Bool bObjEndAlien =
     469         [ #  # ]:          0 :             lcl_IsOtherTab( ((const XLineEndItem&)rSet.Get(XATTR_LINEEND)).GetLineEndValue() );
     470                 :            : 
     471 [ #  # ][ #  # ]:          0 :         return !bObjStartAlien && !bObjEndAlien;
     472                 :            :     }
     473                 :            : 
     474                 :          0 :     return false;
     475                 :            : }
     476                 :            : 
     477                 :            : //------------------------------------------------------------------------
     478                 :            : 
     479                 :            : //  InsertXXX: called from DrawEntry/DrawAlienEntry and InsertObject
     480                 :            : 
     481                 :         13 : sal_Bool ScDetectiveFunc::InsertArrow( SCCOL nCol, SCROW nRow,
     482                 :            :                                 SCCOL nRefStartCol, SCROW nRefStartRow,
     483                 :            :                                 SCCOL nRefEndCol, SCROW nRefEndRow,
     484                 :            :                                 sal_Bool bFromOtherTab, sal_Bool bRed,
     485                 :            :                                 ScDetectiveData& rData )
     486                 :            : {
     487         [ +  - ]:         13 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
     488         [ +  - ]:         13 :     SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
     489                 :            : 
     490 [ +  - ][ -  + ]:         13 :     sal_Bool bArea = ( nRefStartCol != nRefEndCol || nRefStartRow != nRefEndRow );
     491 [ -  + ][ #  # ]:         13 :     if (bArea && !bFromOtherTab)
     492                 :            :     {
     493                 :            :         // insert the rectangle before the arrow - this is relied on in FindFrameForObject
     494                 :            : 
     495         [ #  # ]:          0 :         Rectangle aRect = GetDrawRect( nRefStartCol, nRefStartRow, nRefEndCol, nRefEndRow );
     496 [ #  # ][ #  # ]:          0 :         SdrRectObj* pBox = new SdrRectObj( aRect );
     497                 :            : 
     498         [ #  # ]:          0 :         pBox->SetMergedItemSetAndBroadcast(rData.GetBoxSet());
     499                 :            : 
     500         [ #  # ]:          0 :         pBox->SetLayer( SC_LAYER_INTERN );
     501         [ #  # ]:          0 :         pPage->InsertObject( pBox );
     502 [ #  # ][ #  # ]:          0 :         pModel->AddCalcUndo( new SdrUndoInsertObj( *pBox ) );
                 [ #  # ]
     503                 :            : 
     504         [ #  # ]:          0 :         ScDrawObjData* pData = ScDrawLayer::GetObjData( pBox, sal_True );
     505                 :          0 :         pData->maStart.Set( nRefStartCol, nRefStartRow, nTab);
     506                 :          0 :         pData->maEnd.Set( nRefEndCol, nRefEndRow, nTab);
     507                 :            :     }
     508                 :            : 
     509         [ +  - ]:         13 :     Point aStartPos = GetDrawPos( nRefStartCol, nRefStartRow, DRAWPOS_DETARROW );
     510         [ +  - ]:         13 :     Point aEndPos = GetDrawPos( nCol, nRow, DRAWPOS_DETARROW );
     511                 :            : 
     512         [ +  + ]:         13 :     if (bFromOtherTab)
     513                 :            :     {
     514         [ +  - ]:         12 :         sal_Bool bNegativePage = pDoc->IsNegativePage( nTab );
     515         [ -  + ]:         12 :         long nPageSign = bNegativePage ? -1 : 1;
     516                 :            : 
     517                 :         12 :         aStartPos = Point( aEndPos.X() - 1000 * nPageSign, aEndPos.Y() - 1000 );
     518         [ -  + ]:         12 :         if (aStartPos.X() * nPageSign < 0)
     519                 :          0 :             aStartPos.X() += 2000 * nPageSign;
     520         [ -  + ]:         12 :         if (aStartPos.Y() < 0)
     521                 :          0 :             aStartPos.Y() += 2000;
     522                 :            :     }
     523                 :            : 
     524         [ +  + ]:         13 :     SfxItemSet& rAttrSet = bFromOtherTab ? rData.GetFromTabSet() : rData.GetArrowSet();
     525                 :            : 
     526 [ -  + ][ #  # ]:         13 :     if (bArea && !bFromOtherTab)
     527 [ #  # ][ #  # ]:          0 :         rAttrSet.Put( XLineWidthItem( 50 ) );               // Bereich
                 [ #  # ]
     528                 :            :     else
     529 [ +  - ][ +  - ]:         13 :         rAttrSet.Put( XLineWidthItem( 0 ) );                // einzelne Referenz
                 [ +  - ]
     530                 :            : 
     531 [ -  + ][ #  # ]:         13 :     ColorData nColorData = ( bRed ? GetErrorColor() : GetArrowColor() );
                 [ +  - ]
     532 [ +  - ][ +  - ]:         13 :     rAttrSet.Put( XLineColorItem( String(), Color( nColorData ) ) );
         [ +  - ][ +  - ]
                 [ +  - ]
     533                 :            : 
     534         [ +  - ]:         13 :     basegfx::B2DPolygon aTempPoly;
     535         [ +  - ]:         13 :     aTempPoly.append(basegfx::B2DPoint(aStartPos.X(), aStartPos.Y()));
     536         [ +  - ]:         13 :     aTempPoly.append(basegfx::B2DPoint(aEndPos.X(), aEndPos.Y()));
     537 [ +  - ][ +  - ]:         13 :     SdrPathObj* pArrow = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aTempPoly));
         [ +  - ][ +  - ]
     538 [ +  - ][ +  - ]:         13 :     pArrow->NbcSetLogicRect(Rectangle(aStartPos,aEndPos));  //! noetig ???
     539         [ +  - ]:         13 :     pArrow->SetMergedItemSetAndBroadcast(rAttrSet);
     540                 :            : 
     541         [ +  - ]:         13 :     pArrow->SetLayer( SC_LAYER_INTERN );
     542         [ +  - ]:         13 :     pPage->InsertObject( pArrow );
     543 [ +  - ][ +  - ]:         13 :     pModel->AddCalcUndo( new SdrUndoInsertObj( *pArrow ) );
                 [ +  - ]
     544                 :            : 
     545         [ +  - ]:         13 :     ScDrawObjData* pData = ScDrawLayer::GetObjData(pArrow, true);
     546         [ +  + ]:         13 :     if (bFromOtherTab)
     547                 :         12 :         pData->maStart.SetInvalid();
     548                 :            :     else
     549                 :          1 :         pData->maStart.Set( nRefStartCol, nRefStartRow, nTab);
     550                 :            : 
     551                 :         13 :     pData->maEnd.Set( nCol, nRow, nTab);
     552                 :         13 :     pData->meType = ScDrawObjData::DetectiveArrow;
     553                 :            : 
     554         [ +  - ]:         13 :     Modified();
     555         [ +  - ]:         13 :     return true;
     556                 :            : }
     557                 :            : 
     558                 :          0 : sal_Bool ScDetectiveFunc::InsertToOtherTab( SCCOL nStartCol, SCROW nStartRow,
     559                 :            :                                 SCCOL nEndCol, SCROW nEndRow, sal_Bool bRed,
     560                 :            :                                 ScDetectiveData& rData )
     561                 :            : {
     562         [ #  # ]:          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
     563         [ #  # ]:          0 :     SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
     564                 :            : 
     565 [ #  # ][ #  # ]:          0 :     sal_Bool bArea = ( nStartCol != nEndCol || nStartRow != nEndRow );
     566         [ #  # ]:          0 :     if (bArea)
     567                 :            :     {
     568         [ #  # ]:          0 :         Rectangle aRect = GetDrawRect( nStartCol, nStartRow, nEndCol, nEndRow );
     569 [ #  # ][ #  # ]:          0 :         SdrRectObj* pBox = new SdrRectObj( aRect );
     570                 :            : 
     571         [ #  # ]:          0 :         pBox->SetMergedItemSetAndBroadcast(rData.GetBoxSet());
     572                 :            : 
     573         [ #  # ]:          0 :         pBox->SetLayer( SC_LAYER_INTERN );
     574         [ #  # ]:          0 :         pPage->InsertObject( pBox );
     575 [ #  # ][ #  # ]:          0 :         pModel->AddCalcUndo( new SdrUndoInsertObj( *pBox ) );
                 [ #  # ]
     576                 :            : 
     577         [ #  # ]:          0 :         ScDrawObjData* pData = ScDrawLayer::GetObjData( pBox, sal_True );
     578                 :          0 :         pData->maStart.Set( nStartCol, nStartRow, nTab);
     579                 :          0 :         pData->maEnd.Set( nEndCol, nEndRow, nTab);
     580                 :            :     }
     581                 :            : 
     582         [ #  # ]:          0 :     sal_Bool bNegativePage = pDoc->IsNegativePage( nTab );
     583         [ #  # ]:          0 :     long nPageSign = bNegativePage ? -1 : 1;
     584                 :            : 
     585         [ #  # ]:          0 :     Point aStartPos = GetDrawPos( nStartCol, nStartRow, DRAWPOS_DETARROW );
     586                 :          0 :     Point aEndPos   = Point( aStartPos.X() + 1000 * nPageSign, aStartPos.Y() - 1000 );
     587         [ #  # ]:          0 :     if (aEndPos.Y() < 0)
     588                 :          0 :         aEndPos.Y() += 2000;
     589                 :            : 
     590                 :          0 :     SfxItemSet& rAttrSet = rData.GetToTabSet();
     591         [ #  # ]:          0 :     if (bArea)
     592 [ #  # ][ #  # ]:          0 :         rAttrSet.Put( XLineWidthItem( 50 ) );               // Bereich
                 [ #  # ]
     593                 :            :     else
     594 [ #  # ][ #  # ]:          0 :         rAttrSet.Put( XLineWidthItem( 0 ) );                // einzelne Referenz
                 [ #  # ]
     595                 :            : 
     596 [ #  # ][ #  # ]:          0 :     ColorData nColorData = ( bRed ? GetErrorColor() : GetArrowColor() );
                 [ #  # ]
     597 [ #  # ][ #  # ]:          0 :     rAttrSet.Put( XLineColorItem( String(), Color( nColorData ) ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     598                 :            : 
     599         [ #  # ]:          0 :     basegfx::B2DPolygon aTempPoly;
     600         [ #  # ]:          0 :     aTempPoly.append(basegfx::B2DPoint(aStartPos.X(), aStartPos.Y()));
     601         [ #  # ]:          0 :     aTempPoly.append(basegfx::B2DPoint(aEndPos.X(), aEndPos.Y()));
     602 [ #  # ][ #  # ]:          0 :     SdrPathObj* pArrow = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aTempPoly));
         [ #  # ][ #  # ]
     603 [ #  # ][ #  # ]:          0 :     pArrow->NbcSetLogicRect(Rectangle(aStartPos,aEndPos));  //! noetig ???
     604                 :            : 
     605         [ #  # ]:          0 :     pArrow->SetMergedItemSetAndBroadcast(rAttrSet);
     606                 :            : 
     607         [ #  # ]:          0 :     pArrow->SetLayer( SC_LAYER_INTERN );
     608         [ #  # ]:          0 :     pPage->InsertObject( pArrow );
     609 [ #  # ][ #  # ]:          0 :     pModel->AddCalcUndo( new SdrUndoInsertObj( *pArrow ) );
                 [ #  # ]
     610                 :            : 
     611         [ #  # ]:          0 :     ScDrawObjData* pData = ScDrawLayer::GetObjData( pArrow, sal_True );
     612                 :          0 :     pData->maStart.Set( nStartCol, nStartRow, nTab);
     613                 :          0 :     pData->maEnd.SetInvalid();
     614                 :            : 
     615         [ #  # ]:          0 :     Modified();
     616         [ #  # ]:          0 :     return sal_True;
     617                 :            : }
     618                 :            : 
     619                 :            : //------------------------------------------------------------------------
     620                 :            : 
     621                 :            : //  DrawEntry:      Formel auf dieser Tabelle,
     622                 :            : //                  Referenz auf dieser oder anderer
     623                 :            : //  DrawAlienEntry: Formel auf anderer Tabelle,
     624                 :            : //                  Referenz auf dieser
     625                 :            : 
     626                 :            : //      return FALSE: da war schon ein Pfeil
     627                 :            : 
     628                 :         13 : sal_Bool ScDetectiveFunc::DrawEntry( SCCOL nCol, SCROW nRow,
     629                 :            :                                     const ScRange& rRef,
     630                 :            :                                     ScDetectiveData& rData )
     631                 :            : {
     632 [ +  - ][ -  + ]:         13 :     if ( HasArrow( rRef.aStart, nCol, nRow, nTab ) )
     633                 :          0 :         return false;
     634                 :            : 
     635                 :         13 :     ScAddress aErrorPos;
     636         [ +  - ]:         13 :     sal_Bool bError = HasError( rRef, aErrorPos );
     637 [ +  + ][ -  + ]:         13 :     sal_Bool bAlien = ( rRef.aEnd.Tab() < nTab || rRef.aStart.Tab() > nTab );
     638                 :            : 
     639                 :            :     return InsertArrow( nCol, nRow,
     640                 :         13 :                         rRef.aStart.Col(), rRef.aStart.Row(),
     641                 :         13 :                         rRef.aEnd.Col(), rRef.aEnd.Row(),
     642         [ +  - ]:         39 :                         bAlien, bError, rData );
     643                 :            : }
     644                 :            : 
     645                 :          0 : sal_Bool ScDetectiveFunc::DrawAlienEntry( const ScRange& rRef,
     646                 :            :                                         ScDetectiveData& rData )
     647                 :            : {
     648 [ #  # ][ #  # ]:          0 :     if ( HasArrow( rRef.aStart, 0, 0, nTab+1 ) )
     649                 :          0 :         return false;
     650                 :            : 
     651                 :          0 :     ScAddress aErrorPos;
     652         [ #  # ]:          0 :     sal_Bool bError = HasError( rRef, aErrorPos );
     653                 :            : 
     654                 :          0 :     return InsertToOtherTab( rRef.aStart.Col(), rRef.aStart.Row(),
     655                 :          0 :                                 rRef.aEnd.Col(), rRef.aEnd.Row(),
     656         [ #  # ]:          0 :                                 bError, rData );
     657                 :            : }
     658                 :            : 
     659                 :          0 : void ScDetectiveFunc::DrawCircle( SCCOL nCol, SCROW nRow, ScDetectiveData& rData )
     660                 :            : {
     661         [ #  # ]:          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
     662         [ #  # ]:          0 :     SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
     663                 :            : 
     664         [ #  # ]:          0 :     Rectangle aRect = GetDrawRect( nCol, nRow );
     665                 :          0 :     aRect.Left()    -= 250;
     666                 :          0 :     aRect.Right()   += 250;
     667                 :          0 :     aRect.Top()     -= 70;
     668                 :          0 :     aRect.Bottom()  += 70;
     669                 :            : 
     670 [ #  # ][ #  # ]:          0 :     SdrCircObj* pCircle = new SdrCircObj( OBJ_CIRC, aRect );
     671                 :          0 :     SfxItemSet& rAttrSet = rData.GetCircleSet();
     672                 :            : 
     673         [ #  # ]:          0 :     pCircle->SetMergedItemSetAndBroadcast(rAttrSet);
     674                 :            : 
     675         [ #  # ]:          0 :     pCircle->SetLayer( SC_LAYER_INTERN );
     676         [ #  # ]:          0 :     pPage->InsertObject( pCircle );
     677 [ #  # ][ #  # ]:          0 :     pModel->AddCalcUndo( new SdrUndoInsertObj( *pCircle ) );
                 [ #  # ]
     678                 :            : 
     679         [ #  # ]:          0 :     ScDrawObjData* pData = ScDrawLayer::GetObjData( pCircle, sal_True );
     680                 :          0 :     pData->maStart.Set( nCol, nRow, nTab);
     681                 :          0 :     pData->maEnd.SetInvalid();
     682                 :          0 :     pData->meType = ScDrawObjData::ValidationCircle;
     683                 :            : 
     684         [ #  # ]:          0 :     Modified();
     685                 :          0 : }
     686                 :            : 
     687                 :          0 : void ScDetectiveFunc::DeleteArrowsAt( SCCOL nCol, SCROW nRow, sal_Bool bDestPnt )
     688                 :            : {
     689         [ #  # ]:          0 :     Rectangle aRect = GetDrawRect( nCol, nRow );
     690                 :            : 
     691         [ #  # ]:          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
     692         [ #  # ]:          0 :     SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
     693                 :            :     OSL_ENSURE(pPage,"Page ?");
     694                 :            : 
     695         [ #  # ]:          0 :     pPage->RecalcObjOrdNums();
     696                 :            : 
     697         [ #  # ]:          0 :     sal_uLong nObjCount = pPage->GetObjCount();
     698         [ #  # ]:          0 :     if (nObjCount)
     699                 :            :     {
     700                 :          0 :         long nDelCount = 0;
     701         [ #  # ]:          0 :         SdrObject** ppObj = new SdrObject*[nObjCount];
     702                 :            : 
     703         [ #  # ]:          0 :         SdrObjListIter aIter( *pPage, IM_FLAT );
     704         [ #  # ]:          0 :         SdrObject* pObject = aIter.Next();
     705         [ #  # ]:          0 :         while (pObject)
     706                 :            :         {
     707 [ #  # ][ #  # ]:          0 :             if ( pObject->GetLayer()==SC_LAYER_INTERN &&
         [ #  # ][ #  # ]
                 [ #  # ]
     708 [ #  # ][ #  # ]:          0 :                     pObject->IsPolyObj() && pObject->GetPointCount()==2 )
     709                 :            :             {
     710 [ #  # ][ #  # ]:          0 :                 if (aRect.IsInside(pObject->GetPoint(bDestPnt)))            // Start/Zielpunkt
                 [ #  # ]
     711                 :          0 :                     ppObj[nDelCount++] = pObject;
     712                 :            :             }
     713                 :            : 
     714         [ #  # ]:          0 :             pObject = aIter.Next();
     715                 :            :         }
     716                 :            : 
     717                 :            :         long i;
     718         [ #  # ]:          0 :         for (i=1; i<=nDelCount; i++)
     719 [ #  # ][ #  # ]:          0 :             pModel->AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
                 [ #  # ]
     720                 :            : 
     721         [ #  # ]:          0 :         for (i=1; i<=nDelCount; i++)
     722 [ #  # ][ #  # ]:          0 :             pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
     723                 :            : 
     724         [ #  # ]:          0 :         delete[] ppObj;
     725                 :            : 
     726         [ #  # ]:          0 :         Modified();
     727                 :            :     }
     728                 :          0 : }
     729                 :            : 
     730                 :            :         //      Box um Referenz loeschen
     731                 :            : 
     732                 :            : #define SC_DET_TOLERANCE    50
     733                 :            : 
     734                 :          0 : inline sal_Bool RectIsPoints( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
     735                 :            : {
     736                 :          0 :     return rRect.Left()   >= rStart.X() - SC_DET_TOLERANCE
     737                 :          0 :         && rRect.Left()   <= rStart.X() + SC_DET_TOLERANCE
     738                 :          0 :         && rRect.Right()  >= rEnd.X()   - SC_DET_TOLERANCE
     739                 :          0 :         && rRect.Right()  <= rEnd.X()   + SC_DET_TOLERANCE
     740                 :          0 :         && rRect.Top()    >= rStart.Y() - SC_DET_TOLERANCE
     741                 :          0 :         && rRect.Top()    <= rStart.Y() + SC_DET_TOLERANCE
     742                 :          0 :         && rRect.Bottom() >= rEnd.Y()   - SC_DET_TOLERANCE
     743 [ #  # ][ #  #  :          0 :         && rRect.Bottom() <= rEnd.Y()   + SC_DET_TOLERANCE;
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     744                 :            : }
     745                 :            : 
     746                 :            : #undef SC_DET_TOLERANCE
     747                 :            : 
     748                 :          0 : void ScDetectiveFunc::DeleteBox( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
     749                 :            : {
     750         [ #  # ]:          0 :     Rectangle aCornerRect = GetDrawRect( nCol1, nRow1, nCol2, nRow2 );
     751                 :          0 :     Point aStartCorner = aCornerRect.TopLeft();
     752         [ #  # ]:          0 :     Point aEndCorner = aCornerRect.BottomRight();
     753         [ #  # ]:          0 :     Rectangle aObjRect;
     754                 :            : 
     755         [ #  # ]:          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
     756         [ #  # ]:          0 :     SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
     757                 :            :     OSL_ENSURE(pPage,"Page ?");
     758                 :            : 
     759         [ #  # ]:          0 :     pPage->RecalcObjOrdNums();
     760                 :            : 
     761         [ #  # ]:          0 :     sal_uLong nObjCount = pPage->GetObjCount();
     762         [ #  # ]:          0 :     if (nObjCount)
     763                 :            :     {
     764                 :          0 :         long nDelCount = 0;
     765         [ #  # ]:          0 :         SdrObject** ppObj = new SdrObject*[nObjCount];
     766                 :            : 
     767         [ #  # ]:          0 :         SdrObjListIter aIter( *pPage, IM_FLAT );
     768         [ #  # ]:          0 :         SdrObject* pObject = aIter.Next();
     769         [ #  # ]:          0 :         while (pObject)
     770                 :            :         {
     771 [ #  # ][ #  # ]:          0 :             if ( pObject->GetLayer() == SC_LAYER_INTERN &&
         [ #  # ][ #  # ]
     772 [ #  # ][ #  # ]:          0 :                     pObject->Type() == TYPE(SdrRectObj) )
     773                 :            :             {
     774         [ #  # ]:          0 :                 aObjRect = ((SdrRectObj*)pObject)->GetLogicRect();
     775         [ #  # ]:          0 :                 aObjRect.Justify();
     776         [ #  # ]:          0 :                 if ( RectIsPoints( aObjRect, aStartCorner, aEndCorner ) )
     777                 :          0 :                     ppObj[nDelCount++] = pObject;
     778                 :            :             }
     779                 :            : 
     780         [ #  # ]:          0 :             pObject = aIter.Next();
     781                 :            :         }
     782                 :            : 
     783                 :            :         long i;
     784         [ #  # ]:          0 :         for (i=1; i<=nDelCount; i++)
     785 [ #  # ][ #  # ]:          0 :             pModel->AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
                 [ #  # ]
     786                 :            : 
     787         [ #  # ]:          0 :         for (i=1; i<=nDelCount; i++)
     788 [ #  # ][ #  # ]:          0 :             pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
     789                 :            : 
     790         [ #  # ]:          0 :         delete[] ppObj;
     791                 :            : 
     792         [ #  # ]:          0 :         Modified();
     793                 :            :     }
     794                 :          0 : }
     795                 :            : 
     796                 :            : //------------------------------------------------------------------------
     797                 :            : 
     798                 :          0 : sal_uInt16 ScDetectiveFunc::InsertPredLevelArea( const ScRange& rRef,
     799                 :            :                                         ScDetectiveData& rData, sal_uInt16 nLevel )
     800                 :            : {
     801                 :          0 :     sal_uInt16 nResult = DET_INS_EMPTY;
     802                 :            : 
     803         [ #  # ]:          0 :     ScCellIterator aCellIter( pDoc, rRef);
     804         [ #  # ]:          0 :     ScBaseCell* pCell = aCellIter.GetFirst();
     805         [ #  # ]:          0 :     while (pCell)
     806                 :            :     {
     807         [ #  # ]:          0 :         if (pCell->GetCellType() == CELLTYPE_FORMULA)
     808         [ #  # ]:          0 :             switch( InsertPredLevel( aCellIter.GetCol(), aCellIter.GetRow(), rData, nLevel ) )
           [ #  #  #  # ]
     809                 :            :             {
     810                 :            :                 case DET_INS_INSERTED:
     811                 :          0 :                     nResult = DET_INS_INSERTED;
     812                 :          0 :                     break;
     813                 :            :                 case DET_INS_CONTINUE:
     814         [ #  # ]:          0 :                     if (nResult != DET_INS_INSERTED)
     815                 :          0 :                         nResult = DET_INS_CONTINUE;
     816                 :          0 :                     break;
     817                 :            :                 case DET_INS_CIRCULAR:
     818         [ #  # ]:          0 :                     if (nResult == DET_INS_EMPTY)
     819                 :          0 :                         nResult = DET_INS_CIRCULAR;
     820                 :          0 :                     break;
     821                 :            :             }
     822                 :            : 
     823         [ #  # ]:          0 :         pCell = aCellIter.GetNext();
     824                 :            :     }
     825                 :            : 
     826                 :          0 :     return nResult;
     827                 :            : }
     828                 :            : 
     829                 :         13 : sal_uInt16 ScDetectiveFunc::InsertPredLevel( SCCOL nCol, SCROW nRow, ScDetectiveData& rData,
     830                 :            :                                             sal_uInt16 nLevel )
     831                 :            : {
     832                 :            :     ScBaseCell* pCell;
     833         [ +  - ]:         13 :     pDoc->GetCell( nCol, nRow, nTab, pCell );
     834         [ -  + ]:         13 :     if (!pCell)
     835                 :          0 :         return DET_INS_EMPTY;
     836         [ -  + ]:         13 :     if (pCell->GetCellType() != CELLTYPE_FORMULA)
     837                 :          0 :         return DET_INS_EMPTY;
     838                 :            : 
     839         [ +  - ]:         13 :     ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
     840         [ -  + ]:         13 :     if (pFCell->IsRunning())
     841                 :          0 :         return DET_INS_CIRCULAR;
     842                 :            : 
     843         [ +  + ]:         13 :     if (pFCell->GetDirty())
     844         [ +  - ]:          1 :         pFCell->Interpret();                // nach SetRunning geht's nicht mehr!
     845                 :         13 :     pFCell->SetRunning(sal_True);
     846                 :            : 
     847                 :         13 :     sal_uInt16 nResult = DET_INS_EMPTY;
     848                 :            : 
     849 [ +  - ][ +  - ]:         13 :     ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
     850                 :         13 :     ScRange aRef;
     851 [ +  - ][ +  + ]:         26 :     while ( aIter.GetNextRef( aRef ) )
     852                 :            :     {
     853 [ +  - ][ +  - ]:         13 :         if (DrawEntry( nCol, nRow, aRef, rData ))
     854                 :            :         {
     855                 :         13 :             nResult = DET_INS_INSERTED;         //  neuer Pfeil eingetragen
     856                 :            :         }
     857                 :            :         else
     858                 :            :         {
     859                 :            :             //  weiterverfolgen
     860                 :            : 
     861         [ #  # ]:          0 :             if ( nLevel < rData.GetMaxLevel() )
     862                 :            :             {
     863                 :            :                 sal_uInt16 nSubResult;
     864                 :          0 :                 sal_Bool bArea = (aRef.aStart != aRef.aEnd);
     865         [ #  # ]:          0 :                 if (bArea)
     866         [ #  # ]:          0 :                     nSubResult = InsertPredLevelArea( aRef, rData, nLevel+1 );
     867                 :            :                 else
     868                 :          0 :                     nSubResult = InsertPredLevel( aRef.aStart.Col(), aRef.aStart.Row(),
     869         [ #  # ]:          0 :                                                     rData, nLevel+1 );
     870                 :            : 
     871   [ #  #  #  # ]:          0 :                 switch (nSubResult)
     872                 :            :                 {
     873                 :            :                     case DET_INS_INSERTED:
     874                 :          0 :                         nResult = DET_INS_INSERTED;
     875                 :          0 :                         break;
     876                 :            :                     case DET_INS_CONTINUE:
     877         [ #  # ]:          0 :                         if (nResult != DET_INS_INSERTED)
     878                 :          0 :                             nResult = DET_INS_CONTINUE;
     879                 :          0 :                         break;
     880                 :            :                     case DET_INS_CIRCULAR:
     881         [ #  # ]:          0 :                         if (nResult == DET_INS_EMPTY)
     882                 :          0 :                             nResult = DET_INS_CIRCULAR;
     883                 :          0 :                         break;
     884                 :            :                     // DET_INS_EMPTY: unveraendert lassen
     885                 :            :                 }
     886                 :            :             }
     887                 :            :             else                                    //  nMaxLevel erreicht
     888         [ #  # ]:          0 :                 if (nResult != DET_INS_INSERTED)
     889                 :          0 :                     nResult = DET_INS_CONTINUE;
     890                 :            :         }
     891                 :            :     }
     892                 :            : 
     893                 :         13 :     pFCell->SetRunning(false);
     894                 :            : 
     895                 :         13 :     return nResult;
     896                 :            : }
     897                 :            : 
     898                 :          0 : sal_uInt16 ScDetectiveFunc::FindPredLevelArea( const ScRange& rRef,
     899                 :            :                                                 sal_uInt16 nLevel, sal_uInt16 nDeleteLevel )
     900                 :            : {
     901                 :          0 :     sal_uInt16 nResult = nLevel;
     902                 :            : 
     903         [ #  # ]:          0 :     ScCellIterator aCellIter( pDoc, rRef);
     904         [ #  # ]:          0 :     ScBaseCell* pCell = aCellIter.GetFirst();
     905         [ #  # ]:          0 :     while (pCell)
     906                 :            :     {
     907         [ #  # ]:          0 :         if (pCell->GetCellType() == CELLTYPE_FORMULA)
     908                 :            :         {
     909         [ #  # ]:          0 :             sal_uInt16 nTemp = FindPredLevel( aCellIter.GetCol(), aCellIter.GetRow(), nLevel, nDeleteLevel );
     910         [ #  # ]:          0 :             if (nTemp > nResult)
     911                 :          0 :                 nResult = nTemp;
     912                 :            :         }
     913         [ #  # ]:          0 :         pCell = aCellIter.GetNext();
     914                 :            :     }
     915                 :            : 
     916                 :          0 :     return nResult;
     917                 :            : }
     918                 :            : 
     919                 :            :                                             //  nDeleteLevel != 0   -> loeschen
     920                 :            : 
     921                 :          0 : sal_uInt16 ScDetectiveFunc::FindPredLevel( SCCOL nCol, SCROW nRow, sal_uInt16 nLevel, sal_uInt16 nDeleteLevel )
     922                 :            : {
     923                 :            :     OSL_ENSURE( nLevel<1000, "Level" );
     924                 :            : 
     925                 :            :     ScBaseCell* pCell;
     926         [ #  # ]:          0 :     pDoc->GetCell( nCol, nRow, nTab, pCell );
     927         [ #  # ]:          0 :     if (!pCell)
     928                 :          0 :         return nLevel;
     929         [ #  # ]:          0 :     if (pCell->GetCellType() != CELLTYPE_FORMULA)
     930                 :          0 :         return nLevel;
     931                 :            : 
     932         [ #  # ]:          0 :     ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
     933         [ #  # ]:          0 :     if (pFCell->IsRunning())
     934                 :          0 :         return nLevel;
     935                 :            : 
     936         [ #  # ]:          0 :     if (pFCell->GetDirty())
     937         [ #  # ]:          0 :         pFCell->Interpret();                // nach SetRunning geht's nicht mehr!
     938                 :          0 :     pFCell->SetRunning(sal_True);
     939                 :            : 
     940                 :          0 :     sal_uInt16 nResult = nLevel;
     941 [ #  # ][ #  # ]:          0 :     sal_Bool bDelete = ( nDeleteLevel && nLevel == nDeleteLevel-1 );
     942                 :            : 
     943         [ #  # ]:          0 :     if ( bDelete )
     944                 :            :     {
     945         [ #  # ]:          0 :         DeleteArrowsAt( nCol, nRow, sal_True );                 // Pfeile, die hierher zeigen
     946                 :            :     }
     947                 :            : 
     948 [ #  # ][ #  # ]:          0 :     ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
     949                 :          0 :     ScRange aRef;
     950 [ #  # ][ #  # ]:          0 :     while ( aIter.GetNextRef( aRef) )
     951                 :            :     {
     952                 :          0 :         sal_Bool bArea = ( aRef.aStart != aRef.aEnd );
     953                 :            : 
     954         [ #  # ]:          0 :         if ( bDelete )                  // Rahmen loeschen ?
     955                 :            :         {
     956         [ #  # ]:          0 :             if (bArea)
     957                 :            :             {
     958         [ #  # ]:          0 :                 DeleteBox( aRef.aStart.Col(), aRef.aStart.Row(), aRef.aEnd.Col(), aRef.aEnd.Row() );
     959                 :            :             }
     960                 :            :         }
     961                 :            :         else                            // weitersuchen
     962                 :            :         {
     963 [ #  # ][ #  # ]:          0 :             if ( HasArrow( aRef.aStart, nCol,nRow,nTab ) )
     964                 :            :             {
     965                 :            :                 sal_uInt16 nTemp;
     966         [ #  # ]:          0 :                 if (bArea)
     967         [ #  # ]:          0 :                     nTemp = FindPredLevelArea( aRef, nLevel+1, nDeleteLevel );
     968                 :            :                 else
     969                 :          0 :                     nTemp = FindPredLevel( aRef.aStart.Col(),aRef.aStart.Row(),
     970         [ #  # ]:          0 :                                                         nLevel+1, nDeleteLevel );
     971         [ #  # ]:          0 :                 if (nTemp > nResult)
     972                 :          0 :                     nResult = nTemp;
     973                 :            :             }
     974                 :            :         }
     975                 :            :     }
     976                 :            : 
     977                 :          0 :     pFCell->SetRunning(false);
     978                 :            : 
     979                 :          0 :     return nResult;
     980                 :            : }
     981                 :            : 
     982                 :            : //------------------------------------------------------------------------
     983                 :            : 
     984                 :          0 : sal_uInt16 ScDetectiveFunc::InsertErrorLevel( SCCOL nCol, SCROW nRow, ScDetectiveData& rData,
     985                 :            :                                             sal_uInt16 nLevel )
     986                 :            : {
     987                 :            :     ScBaseCell* pCell;
     988         [ #  # ]:          0 :     pDoc->GetCell( nCol, nRow, nTab, pCell );
     989         [ #  # ]:          0 :     if (!pCell)
     990                 :          0 :         return DET_INS_EMPTY;
     991         [ #  # ]:          0 :     if (pCell->GetCellType() != CELLTYPE_FORMULA)
     992                 :          0 :         return DET_INS_EMPTY;
     993                 :            : 
     994         [ #  # ]:          0 :     ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
     995         [ #  # ]:          0 :     if (pFCell->IsRunning())
     996                 :          0 :         return DET_INS_CIRCULAR;
     997                 :            : 
     998         [ #  # ]:          0 :     if (pFCell->GetDirty())
     999         [ #  # ]:          0 :         pFCell->Interpret();                // nach SetRunning geht's nicht mehr!
    1000                 :          0 :     pFCell->SetRunning(sal_True);
    1001                 :            : 
    1002                 :          0 :     sal_uInt16 nResult = DET_INS_EMPTY;
    1003                 :            : 
    1004 [ #  # ][ #  # ]:          0 :     ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
    1005                 :          0 :     ScRange aRef;
    1006                 :          0 :     ScAddress aErrorPos;
    1007                 :          0 :     sal_Bool bHasError = false;
    1008 [ #  # ][ #  # ]:          0 :     while ( aIter.GetNextRef( aRef ) )
    1009                 :            :     {
    1010 [ #  # ][ #  # ]:          0 :         if (HasError( aRef, aErrorPos ))
    1011                 :            :         {
    1012                 :          0 :             bHasError = sal_True;
    1013 [ #  # ][ #  # ]:          0 :             if (DrawEntry( nCol, nRow, ScRange( aErrorPos), rData ))
    1014                 :          0 :                 nResult = DET_INS_INSERTED;
    1015                 :            : 
    1016                 :            :             //  und weiterverfolgen
    1017                 :            : 
    1018         [ #  # ]:          0 :             if ( nLevel < rData.GetMaxLevel() )         // praktisch immer
    1019                 :            :             {
    1020         [ #  # ]:          0 :                 if (InsertErrorLevel( aErrorPos.Col(), aErrorPos.Row(),
    1021         [ #  # ]:          0 :                                                         rData, nLevel+1 ) == DET_INS_INSERTED)
    1022                 :          0 :                     nResult = DET_INS_INSERTED;
    1023                 :            :             }
    1024                 :            :         }
    1025                 :            :     }
    1026                 :            : 
    1027                 :          0 :     pFCell->SetRunning(false);
    1028                 :            : 
    1029                 :            :                                                     // Blaetter ?
    1030         [ #  # ]:          0 :     if (!bHasError)
    1031 [ #  # ][ #  # ]:          0 :         if (InsertPredLevel( nCol, nRow, rData, rData.GetMaxLevel() ) == DET_INS_INSERTED)
    1032                 :          0 :             nResult = DET_INS_INSERTED;
    1033                 :            : 
    1034                 :          0 :     return nResult;
    1035                 :            : }
    1036                 :            : 
    1037                 :            : //------------------------------------------------------------------------
    1038                 :            : 
    1039                 :          0 : sal_uInt16 ScDetectiveFunc::InsertSuccLevel( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
    1040                 :            :                                         ScDetectiveData& rData, sal_uInt16 nLevel )
    1041                 :            : {
    1042                 :            :     //  ueber ganzes Dokument
    1043                 :            : 
    1044                 :          0 :     sal_uInt16 nResult = DET_INS_EMPTY;
    1045         [ #  # ]:          0 :     ScCellIterator aCellIter( pDoc, 0,0,0, MAXCOL,MAXROW,MAXTAB );          // alle Tabellen
    1046         [ #  # ]:          0 :     ScBaseCell* pCell = aCellIter.GetFirst();
    1047         [ #  # ]:          0 :     while (pCell)
    1048                 :            :     {
    1049         [ #  # ]:          0 :         if (pCell->GetCellType() == CELLTYPE_FORMULA)
    1050                 :            :         {
    1051         [ #  # ]:          0 :             ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
    1052                 :          0 :             sal_Bool bRunning = pFCell->IsRunning();
    1053                 :            : 
    1054         [ #  # ]:          0 :             if (pFCell->GetDirty())
    1055         [ #  # ]:          0 :                 pFCell->Interpret();                // nach SetRunning geht's nicht mehr!
    1056                 :          0 :             pFCell->SetRunning(sal_True);
    1057                 :            : 
    1058 [ #  # ][ #  # ]:          0 :             ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
    1059                 :          0 :             ScRange aRef;
    1060 [ #  # ][ #  # ]:          0 :             while ( aIter.GetNextRef( aRef) )
    1061                 :            :             {
    1062 [ #  # ][ #  # ]:          0 :                 if (aRef.aStart.Tab() <= nTab && aRef.aEnd.Tab() >= nTab)
                 [ #  # ]
    1063                 :            :                 {
    1064         [ #  # ]:          0 :                     if (Intersect( nCol1,nRow1,nCol2,nRow2,
    1065                 :          0 :                             aRef.aStart.Col(),aRef.aStart.Row(),
    1066                 :          0 :                             aRef.aEnd.Col(),aRef.aEnd.Row() ))
    1067                 :            :                     {
    1068                 :          0 :                         sal_Bool bAlien = ( aCellIter.GetTab() != nTab );
    1069                 :            :                         sal_Bool bDrawRet;
    1070         [ #  # ]:          0 :                         if (bAlien)
    1071         [ #  # ]:          0 :                             bDrawRet = DrawAlienEntry( aRef, rData );
    1072                 :            :                         else
    1073                 :          0 :                             bDrawRet = DrawEntry( aCellIter.GetCol(), aCellIter.GetRow(),
    1074         [ #  # ]:          0 :                                                     aRef, rData );
    1075         [ #  # ]:          0 :                         if (bDrawRet)
    1076                 :            :                         {
    1077                 :          0 :                             nResult = DET_INS_INSERTED;         //  neuer Pfeil eingetragen
    1078                 :            :                         }
    1079                 :            :                         else
    1080                 :            :                         {
    1081         [ #  # ]:          0 :                             if (bRunning)
    1082                 :            :                             {
    1083         [ #  # ]:          0 :                                 if (nResult == DET_INS_EMPTY)
    1084                 :          0 :                                     nResult = DET_INS_CIRCULAR;
    1085                 :            :                             }
    1086                 :            :                             else
    1087                 :            :                             {
    1088                 :            :                                         //  weiterverfolgen
    1089                 :            : 
    1090         [ #  # ]:          0 :                                 if ( nLevel < rData.GetMaxLevel() )
    1091                 :            :                                 {
    1092                 :            :                                     sal_uInt16 nSubResult = InsertSuccLevel(
    1093                 :          0 :                                                             aCellIter.GetCol(), aCellIter.GetRow(),
    1094                 :          0 :                                                             aCellIter.GetCol(), aCellIter.GetRow(),
    1095         [ #  # ]:          0 :                                                             rData, nLevel+1 );
    1096   [ #  #  #  # ]:          0 :                                     switch (nSubResult)
    1097                 :            :                                     {
    1098                 :            :                                         case DET_INS_INSERTED:
    1099                 :          0 :                                             nResult = DET_INS_INSERTED;
    1100                 :          0 :                                             break;
    1101                 :            :                                         case DET_INS_CONTINUE:
    1102         [ #  # ]:          0 :                                             if (nResult != DET_INS_INSERTED)
    1103                 :          0 :                                                 nResult = DET_INS_CONTINUE;
    1104                 :          0 :                                             break;
    1105                 :            :                                         case DET_INS_CIRCULAR:
    1106         [ #  # ]:          0 :                                             if (nResult == DET_INS_EMPTY)
    1107                 :          0 :                                                 nResult = DET_INS_CIRCULAR;
    1108                 :          0 :                                             break;
    1109                 :            :                                         // DET_INS_EMPTY: unveraendert lassen
    1110                 :            :                                     }
    1111                 :            :                                 }
    1112                 :            :                                 else                                    //  nMaxLevel erreicht
    1113         [ #  # ]:          0 :                                     if (nResult != DET_INS_INSERTED)
    1114                 :          0 :                                         nResult = DET_INS_CONTINUE;
    1115                 :            :                             }
    1116                 :            :                         }
    1117                 :            :                     }
    1118                 :            :                 }
    1119                 :            :             }
    1120                 :          0 :             pFCell->SetRunning(bRunning);
    1121                 :            :         }
    1122         [ #  # ]:          0 :         pCell = aCellIter.GetNext();
    1123                 :            :     }
    1124                 :            : 
    1125                 :          0 :     return nResult;
    1126                 :            : }
    1127                 :            : 
    1128                 :          0 : sal_uInt16 ScDetectiveFunc::FindSuccLevel( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
    1129                 :            :                                         sal_uInt16 nLevel, sal_uInt16 nDeleteLevel )
    1130                 :            : {
    1131                 :            :     OSL_ENSURE( nLevel<1000, "Level" );
    1132                 :            : 
    1133                 :          0 :     sal_uInt16 nResult = nLevel;
    1134 [ #  # ][ #  # ]:          0 :     sal_Bool bDelete = ( nDeleteLevel && nLevel == nDeleteLevel-1 );
    1135                 :            : 
    1136         [ #  # ]:          0 :     ScCellIterator aCellIter( pDoc, 0,0, nTab, MAXCOL,MAXROW, nTab );
    1137         [ #  # ]:          0 :     ScBaseCell* pCell = aCellIter.GetFirst();
    1138         [ #  # ]:          0 :     while (pCell)
    1139                 :            :     {
    1140         [ #  # ]:          0 :         if (pCell->GetCellType() == CELLTYPE_FORMULA)
    1141                 :            :         {
    1142         [ #  # ]:          0 :             ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
    1143                 :          0 :             sal_Bool bRunning = pFCell->IsRunning();
    1144                 :            : 
    1145         [ #  # ]:          0 :             if (pFCell->GetDirty())
    1146         [ #  # ]:          0 :                 pFCell->Interpret();                // nach SetRunning geht's nicht mehr!
    1147                 :          0 :             pFCell->SetRunning(sal_True);
    1148                 :            : 
    1149 [ #  # ][ #  # ]:          0 :             ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
    1150                 :          0 :             ScRange aRef;
    1151 [ #  # ][ #  # ]:          0 :             while ( aIter.GetNextRef( aRef) )
    1152                 :            :             {
    1153 [ #  # ][ #  # ]:          0 :                 if (aRef.aStart.Tab() <= nTab && aRef.aEnd.Tab() >= nTab)
                 [ #  # ]
    1154                 :            :                 {
    1155         [ #  # ]:          0 :                     if (Intersect( nCol1,nRow1,nCol2,nRow2,
    1156                 :          0 :                             aRef.aStart.Col(),aRef.aStart.Row(),
    1157                 :          0 :                             aRef.aEnd.Col(),aRef.aEnd.Row() ))
    1158                 :            :                     {
    1159         [ #  # ]:          0 :                         if ( bDelete )                          // Pfeile, die hier anfangen
    1160                 :            :                         {
    1161         [ #  # ]:          0 :                             if (aRef.aStart != aRef.aEnd)
    1162                 :            :                             {
    1163                 :          0 :                                 DeleteBox( aRef.aStart.Col(), aRef.aStart.Row(),
    1164         [ #  # ]:          0 :                                                 aRef.aEnd.Col(), aRef.aEnd.Row() );
    1165                 :            :                             }
    1166         [ #  # ]:          0 :                             DeleteArrowsAt( aRef.aStart.Col(), aRef.aStart.Row(), false );
    1167                 :            :                         }
    1168 [ #  # ][ #  # ]:          0 :                         else if ( !bRunning &&
                 [ #  # ]
    1169                 :            :                                 HasArrow( aRef.aStart,
    1170         [ #  # ]:          0 :                                             aCellIter.GetCol(),aCellIter.GetRow(),aCellIter.GetTab() ) )
    1171                 :            :                         {
    1172                 :          0 :                             sal_uInt16 nTemp = FindSuccLevel( aCellIter.GetCol(), aCellIter.GetRow(),
    1173                 :          0 :                                                             aCellIter.GetCol(), aCellIter.GetRow(),
    1174         [ #  # ]:          0 :                                                             nLevel+1, nDeleteLevel );
    1175         [ #  # ]:          0 :                             if (nTemp > nResult)
    1176                 :          0 :                                 nResult = nTemp;
    1177                 :            :                         }
    1178                 :            :                     }
    1179                 :            :                 }
    1180                 :            :             }
    1181                 :            : 
    1182                 :          0 :             pFCell->SetRunning(bRunning);
    1183                 :            :         }
    1184         [ #  # ]:          0 :         pCell = aCellIter.GetNext();
    1185                 :            :     }
    1186                 :            : 
    1187                 :          0 :     return nResult;
    1188                 :            : }
    1189                 :            : 
    1190                 :            : 
    1191                 :            : //
    1192                 :            : //  --------------------------------------------------------------------------------
    1193                 :            : //
    1194                 :            : 
    1195                 :         13 : sal_Bool ScDetectiveFunc::ShowPred( SCCOL nCol, SCROW nRow )
    1196                 :            : {
    1197         [ +  - ]:         13 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1198         [ -  + ]:         13 :     if (!pModel)
    1199                 :          0 :         return false;
    1200                 :            : 
    1201         [ +  - ]:         13 :     ScDetectiveData aData( pModel );
    1202                 :            : 
    1203                 :         13 :     sal_uInt16 nMaxLevel = 0;
    1204                 :         13 :     sal_uInt16 nResult = DET_INS_CONTINUE;
    1205 [ +  + ][ +  - ]:         26 :     while (nResult == DET_INS_CONTINUE && nMaxLevel < 1000)
                 [ +  + ]
    1206                 :            :     {
    1207                 :         13 :         aData.SetMaxLevel( nMaxLevel );
    1208         [ +  - ]:         13 :         nResult = InsertPredLevel( nCol, nRow, aData, 0 );
    1209                 :         13 :         ++nMaxLevel;
    1210                 :            :     }
    1211                 :            : 
    1212         [ +  - ]:         13 :     return ( nResult == DET_INS_INSERTED );
    1213                 :            : }
    1214                 :            : 
    1215                 :          0 : sal_Bool ScDetectiveFunc::ShowSucc( SCCOL nCol, SCROW nRow )
    1216                 :            : {
    1217         [ #  # ]:          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1218         [ #  # ]:          0 :     if (!pModel)
    1219                 :          0 :         return false;
    1220                 :            : 
    1221         [ #  # ]:          0 :     ScDetectiveData aData( pModel );
    1222                 :            : 
    1223                 :          0 :     sal_uInt16 nMaxLevel = 0;
    1224                 :          0 :     sal_uInt16 nResult = DET_INS_CONTINUE;
    1225 [ #  # ][ #  # ]:          0 :     while (nResult == DET_INS_CONTINUE && nMaxLevel < 1000)
                 [ #  # ]
    1226                 :            :     {
    1227                 :          0 :         aData.SetMaxLevel( nMaxLevel );
    1228         [ #  # ]:          0 :         nResult = InsertSuccLevel( nCol, nRow, nCol, nRow, aData, 0 );
    1229                 :          0 :         ++nMaxLevel;
    1230                 :            :     }
    1231                 :            : 
    1232         [ #  # ]:          0 :     return ( nResult == DET_INS_INSERTED );
    1233                 :            : }
    1234                 :            : 
    1235                 :          0 : sal_Bool ScDetectiveFunc::ShowError( SCCOL nCol, SCROW nRow )
    1236                 :            : {
    1237         [ #  # ]:          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1238         [ #  # ]:          0 :     if (!pModel)
    1239                 :          0 :         return false;
    1240                 :            : 
    1241                 :          0 :     ScRange aRange( nCol, nRow, nTab );
    1242                 :          0 :     ScAddress aErrPos;
    1243 [ #  # ][ #  # ]:          0 :     if ( !HasError( aRange,aErrPos ) )
    1244                 :          0 :         return false;
    1245                 :            : 
    1246         [ #  # ]:          0 :     ScDetectiveData aData( pModel );
    1247                 :            : 
    1248                 :          0 :     aData.SetMaxLevel( 1000 );
    1249         [ #  # ]:          0 :     sal_uInt16 nResult = InsertErrorLevel( nCol, nRow, aData, 0 );
    1250                 :            : 
    1251         [ #  # ]:          0 :     return ( nResult == DET_INS_INSERTED );
    1252                 :            : }
    1253                 :            : 
    1254                 :          0 : sal_Bool ScDetectiveFunc::DeleteSucc( SCCOL nCol, SCROW nRow )
    1255                 :            : {
    1256                 :          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1257         [ #  # ]:          0 :     if (!pModel)
    1258                 :          0 :         return false;
    1259                 :            : 
    1260                 :          0 :     sal_uInt16 nLevelCount = FindSuccLevel( nCol, nRow, nCol, nRow, 0, 0 );
    1261         [ #  # ]:          0 :     if ( nLevelCount )
    1262                 :          0 :         FindSuccLevel( nCol, nRow, nCol, nRow, 0, nLevelCount );            // loeschen
    1263                 :            : 
    1264                 :          0 :     return ( nLevelCount != 0 );
    1265                 :            : }
    1266                 :            : 
    1267                 :          0 : sal_Bool ScDetectiveFunc::DeletePred( SCCOL nCol, SCROW nRow )
    1268                 :            : {
    1269                 :          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1270         [ #  # ]:          0 :     if (!pModel)
    1271                 :          0 :         return false;
    1272                 :            : 
    1273                 :          0 :     sal_uInt16 nLevelCount = FindPredLevel( nCol, nRow, 0, 0 );
    1274         [ #  # ]:          0 :     if ( nLevelCount )
    1275                 :          0 :         FindPredLevel( nCol, nRow, 0, nLevelCount );            // loeschen
    1276                 :            : 
    1277                 :          0 :     return ( nLevelCount != 0 );
    1278                 :            : }
    1279                 :            : 
    1280                 :         24 : sal_Bool ScDetectiveFunc::DeleteAll( ScDetectiveDelete eWhat )
    1281                 :            : {
    1282                 :         24 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1283         [ -  + ]:         24 :     if (!pModel)
    1284                 :          0 :         return false;
    1285                 :            : 
    1286                 :         24 :     SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
    1287                 :            :     OSL_ENSURE(pPage,"Page ?");
    1288                 :            : 
    1289                 :         24 :     pPage->RecalcObjOrdNums();
    1290                 :            : 
    1291                 :         24 :     long    nDelCount = 0;
    1292                 :         24 :     sal_uLong   nObjCount = pPage->GetObjCount();
    1293         [ +  + ]:         24 :     if (nObjCount)
    1294                 :            :     {
    1295         [ +  - ]:         12 :         SdrObject** ppObj = new SdrObject*[nObjCount];
    1296                 :            : 
    1297         [ +  - ]:         12 :         SdrObjListIter aIter( *pPage, IM_FLAT );
    1298         [ +  - ]:         12 :         SdrObject* pObject = aIter.Next();
    1299         [ +  + ]:         24 :         while (pObject)
    1300                 :            :         {
    1301 [ +  - ][ +  - ]:         12 :             if ( pObject->GetLayer() == SC_LAYER_INTERN )
    1302                 :            :             {
    1303                 :         12 :                 sal_Bool bDoThis = sal_True;
    1304         [ +  - ]:         12 :                 if ( eWhat != SC_DET_ALL )
    1305                 :            :                 {
    1306 [ +  - ][ +  - ]:         12 :                     sal_Bool bCircle = ( pObject->ISA(SdrCircObj) );
    1307         [ +  - ]:         12 :                     sal_Bool bCaption = ScDrawLayer::IsNoteCaption( pObject );
    1308         [ -  + ]:         12 :                     if ( eWhat == SC_DET_DETECTIVE )        // Detektiv, aus Menue
    1309                 :          0 :                         bDoThis = !bCaption;                // auch Kreise
    1310         [ -  + ]:         12 :                     else if ( eWhat == SC_DET_CIRCLES )     // Kreise, wenn neue erzeugt werden
    1311                 :          0 :                         bDoThis = bCircle;
    1312         [ +  - ]:         12 :                     else if ( eWhat == SC_DET_ARROWS )      // DetectiveRefresh
    1313 [ +  - ][ +  - ]:         12 :                         bDoThis = !bCaption && !bCircle;    // don't include circles
    1314                 :            :                     else
    1315                 :            :                     {
    1316                 :            :                         OSL_FAIL("wat?");
    1317                 :            :                     }
    1318                 :            :                 }
    1319         [ +  - ]:         12 :                 if ( bDoThis )
    1320                 :         12 :                     ppObj[nDelCount++] = pObject;
    1321                 :            :             }
    1322                 :            : 
    1323         [ +  - ]:         12 :             pObject = aIter.Next();
    1324                 :            :         }
    1325                 :            : 
    1326                 :            :         long i;
    1327         [ +  + ]:         24 :         for (i=1; i<=nDelCount; i++)
    1328 [ +  - ][ +  - ]:         12 :             pModel->AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
                 [ +  - ]
    1329                 :            : 
    1330         [ +  + ]:         24 :         for (i=1; i<=nDelCount; i++)
    1331 [ +  - ][ +  - ]:         12 :             pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
    1332                 :            : 
    1333         [ +  - ]:         12 :         delete[] ppObj;
    1334                 :            : 
    1335         [ +  - ]:         12 :         Modified();
    1336                 :            :     }
    1337                 :            : 
    1338                 :         24 :     return ( nDelCount != 0 );
    1339                 :            : }
    1340                 :            : 
    1341                 :          0 : sal_Bool ScDetectiveFunc::MarkInvalid(sal_Bool& rOverflow)
    1342                 :            : {
    1343                 :          0 :     rOverflow = false;
    1344         [ #  # ]:          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1345         [ #  # ]:          0 :     if (!pModel)
    1346                 :          0 :         return false;
    1347                 :            : 
    1348         [ #  # ]:          0 :     sal_Bool bDeleted = DeleteAll( SC_DET_CIRCLES );        // nur die Kreise
    1349                 :            : 
    1350         [ #  # ]:          0 :     ScDetectiveData aData( pModel );
    1351                 :          0 :     long nInsCount = 0;
    1352                 :            : 
    1353                 :            :     //  Stellen suchen, wo Gueltigkeit definiert ist
    1354                 :            : 
    1355         [ #  # ]:          0 :     ScDocAttrIterator aAttrIter( pDoc, nTab, 0,0,MAXCOL,MAXROW );
    1356                 :            :     SCCOL nCol;
    1357                 :            :     SCROW nRow1;
    1358                 :            :     SCROW nRow2;
    1359         [ #  # ]:          0 :     const ScPatternAttr* pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 );
    1360 [ #  # ][ #  # ]:          0 :     while ( pPattern && nInsCount < SC_DET_MAXCIRCLE )
                 [ #  # ]
    1361                 :            :     {
    1362         [ #  # ]:          0 :         sal_uLong nIndex = ((const SfxUInt32Item&)pPattern->GetItem(ATTR_VALIDDATA)).GetValue();
    1363         [ #  # ]:          0 :         if (nIndex)
    1364                 :            :         {
    1365         [ #  # ]:          0 :             const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
    1366         [ #  # ]:          0 :             if ( pData )
    1367                 :            :             {
    1368                 :            :                 //  Zellen in dem Bereich durchgehen
    1369                 :            : 
    1370                 :          0 :                 sal_Bool bMarkEmpty = !pData->IsIgnoreBlank();
    1371                 :          0 :                 SCROW nNextRow = nRow1;
    1372                 :            :                 SCROW nRow;
    1373         [ #  # ]:          0 :                 ScCellIterator aCellIter( pDoc, nCol,nRow1,nTab, nCol,nRow2,nTab );
    1374         [ #  # ]:          0 :                 ScBaseCell* pCell = aCellIter.GetFirst();
    1375 [ #  # ][ #  # ]:          0 :                 while ( pCell && nInsCount < SC_DET_MAXCIRCLE )
                 [ #  # ]
    1376                 :            :                 {
    1377                 :          0 :                     SCROW nCellRow = aCellIter.GetRow();
    1378         [ #  # ]:          0 :                     if ( bMarkEmpty )
    1379 [ #  # ][ #  # ]:          0 :                         for ( nRow = nNextRow; nRow < nCellRow && nInsCount < SC_DET_MAXCIRCLE; nRow++ )
                 [ #  # ]
    1380                 :            :                         {
    1381         [ #  # ]:          0 :                             DrawCircle( nCol, nRow, aData );
    1382                 :          0 :                             ++nInsCount;
    1383                 :            :                         }
    1384 [ #  # ][ #  # ]:          0 :                     if ( !pData->IsDataValid( pCell, ScAddress( nCol, nCellRow, nTab ) ) )
    1385                 :            :                     {
    1386         [ #  # ]:          0 :                         DrawCircle( nCol, nCellRow, aData );
    1387                 :          0 :                         ++nInsCount;
    1388                 :            :                     }
    1389                 :          0 :                     nNextRow = nCellRow + 1;
    1390         [ #  # ]:          0 :                     pCell = aCellIter.GetNext();
    1391                 :            :                 }
    1392         [ #  # ]:          0 :                 if ( bMarkEmpty )
    1393 [ #  # ][ #  # ]:          0 :                     for ( nRow = nNextRow; nRow <= nRow2 && nInsCount < SC_DET_MAXCIRCLE; nRow++ )
                 [ #  # ]
    1394                 :            :                     {
    1395         [ #  # ]:          0 :                         DrawCircle( nCol, nRow, aData );
    1396                 :          0 :                         ++nInsCount;
    1397                 :            :                     }
    1398                 :            :             }
    1399                 :            :         }
    1400                 :            : 
    1401         [ #  # ]:          0 :         pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 );
    1402                 :            :     }
    1403                 :            : 
    1404         [ #  # ]:          0 :     if ( nInsCount >= SC_DET_MAXCIRCLE )
    1405                 :          0 :         rOverflow = sal_True;
    1406                 :            : 
    1407 [ #  # ][ #  # ]:          0 :     return ( bDeleted || nInsCount != 0 );
         [ #  # ][ #  # ]
    1408                 :            : }
    1409                 :            : 
    1410                 :          6 : void ScDetectiveFunc::GetAllPreds(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
    1411                 :            :                                   vector<ScTokenRef>& rRefTokens)
    1412                 :            : {
    1413         [ +  - ]:          6 :     ScCellIterator aCellIter(pDoc, nCol1, nRow1, nTab, nCol2, nRow2, nTab);
    1414 [ +  - ][ +  - ]:         12 :     for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = aCellIter.GetNext())
                 [ +  + ]
    1415                 :            :     {
    1416         [ -  + ]:          6 :         if (pCell->GetCellType() != CELLTYPE_FORMULA)
    1417                 :          0 :             continue;
    1418                 :            : 
    1419         [ +  - ]:          6 :         ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
    1420         [ +  - ]:          6 :         ScDetectiveRefIter aRefIter(pFCell);
    1421 [ +  - ][ +  - ]:         18 :         for (ScToken* p = aRefIter.GetNextRefToken(); p; p = aRefIter.GetNextRefToken())
                 [ +  + ]
    1422                 :            :         {
    1423         [ +  - ]:         12 :             ScTokenRef pRef(static_cast<ScToken*>(p->Clone()));
    1424         [ +  - ]:         12 :             pRef->CalcAbsIfRel(aCellIter.GetPos());
    1425         [ +  - ]:         12 :             ScRefTokenHelper::join(rRefTokens, pRef);
    1426         [ +  - ]:         12 :         }
    1427                 :            :     }
    1428                 :          6 : }
    1429                 :            : 
    1430                 :          3 : void ScDetectiveFunc::GetAllSuccs(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
    1431                 :            :                                   vector<ScTokenRef>& rRefTokens)
    1432                 :            : {
    1433         [ +  - ]:          3 :     vector<ScTokenRef> aSrcRange;
    1434                 :            :     aSrcRange.push_back(
    1435 [ +  - ][ +  - ]:          3 :         ScRefTokenHelper::createRefToken(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab)));
                 [ +  - ]
    1436                 :            : 
    1437         [ +  - ]:          3 :     ScCellIterator aCellIter(pDoc, 0, 0, nTab, MAXCOL, MAXROW, nTab);
    1438 [ +  - ][ +  - ]:         18 :     for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = aCellIter.GetNext())
                 [ +  + ]
    1439                 :            :     {
    1440         [ +  + ]:         15 :         if (pCell->GetCellType() != CELLTYPE_FORMULA)
    1441                 :          9 :             continue;
    1442                 :            : 
    1443         [ +  - ]:          6 :         ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
    1444         [ +  - ]:          6 :         ScDetectiveRefIter aRefIter(pFCell);
    1445 [ +  - ][ +  - ]:         18 :         for (ScToken* p = aRefIter.GetNextRefToken(); p; p = aRefIter.GetNextRefToken())
                 [ +  + ]
    1446                 :            :         {
    1447                 :         12 :             ScAddress aPos = aCellIter.GetPos();
    1448         [ +  - ]:         12 :             ScTokenRef pRef(static_cast<ScToken*>(p->Clone()));
    1449         [ +  - ]:         12 :             pRef->CalcAbsIfRel(aPos);
    1450 [ +  - ][ +  + ]:         12 :             if (ScRefTokenHelper::intersects(aSrcRange, pRef))
    1451                 :            :             {
    1452                 :            :                 // This address is absolute.
    1453 [ +  - ][ +  - ]:          6 :                 pRef = ScRefTokenHelper::createRefToken(aPos);
                 [ +  - ]
    1454         [ +  - ]:          6 :                 ScRefTokenHelper::join(rRefTokens, pRef);
    1455                 :            :             }
    1456         [ +  - ]:         12 :         }
    1457                 :          3 :     }
    1458                 :          3 : }
    1459                 :            : 
    1460                 :       1794 : void ScDetectiveFunc::UpdateAllComments( ScDocument& rDoc )
    1461                 :            : {
    1462                 :            :     //  for all caption objects, update attributes and SpecialTextBoxShadow flag
    1463                 :            :     //  (on all tables - nTab is ignored!)
    1464                 :            : 
    1465                 :            :     //  no undo actions, this is refreshed after undo
    1466                 :            : 
    1467                 :       1794 :     ScDrawLayer* pModel = rDoc.GetDrawLayer();
    1468         [ +  + ]:       1794 :     if (!pModel)
    1469                 :       1794 :         return;
    1470                 :            : 
    1471         [ +  + ]:        114 :     for( SCTAB nObjTab = 0, nTabCount = rDoc.GetTableCount(); nObjTab < nTabCount; ++nObjTab )
    1472                 :            :     {
    1473                 :         57 :         rDoc.InitializeNoteCaptions( nObjTab );
    1474                 :         57 :         SdrPage* pPage = pModel->GetPage( static_cast< sal_uInt16 >( nObjTab ) );
    1475                 :            :         OSL_ENSURE( pPage, "Page ?" );
    1476         [ +  - ]:         57 :         if( pPage )
    1477                 :            :         {
    1478         [ +  - ]:         57 :             SdrObjListIter aIter( *pPage, IM_FLAT );
    1479 [ +  - ][ #  # ]:         57 :             for( SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next() )
                 [ -  + ]
    1480                 :            :             {
    1481 [ #  # ][ #  # ]:          0 :                 if ( ScDrawObjData* pData = ScDrawLayer::GetNoteCaptionData( pObject, nObjTab ) )
    1482                 :            :                 {
    1483 [ #  # ][ #  # ]:          0 :                     ScPostIt* pNote = rDoc.GetNotes( pData->maStart.Tab() )->findByAddress( pData->maStart );
    1484                 :            :                     // caption should exist, we iterate over drawing objects...
    1485                 :            :                     OSL_ENSURE( pNote && (pNote->GetCaption() == pObject), "ScDetectiveFunc::UpdateAllComments - invalid cell note" );
    1486         [ #  # ]:          0 :                     if( pNote )
    1487                 :            :                     {
    1488         [ #  # ]:          0 :                         ScCommentData aData( rDoc, pModel );
    1489 [ #  # ][ #  # ]:          0 :                         SfxItemSet aAttrColorSet = pObject->GetMergedItemSet();
    1490 [ #  # ][ #  # ]:          0 :                         aAttrColorSet.Put( XFillColorItem( String(), GetCommentColor() ) );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1491         [ #  # ]:          0 :                         aData.UpdateCaptionSet( aAttrColorSet );
    1492         [ #  # ]:          0 :                         pObject->SetMergedItemSetAndBroadcast( aData.GetCaptionSet() );
    1493 [ #  # ][ #  # ]:          0 :                         if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) )
    1494                 :            :                         {
    1495                 :          0 :                             pCaption->SetSpecialTextBoxShadow();
    1496                 :          0 :                             pCaption->SetFixedTail();
    1497 [ #  # ][ #  # ]:          0 :                         }
    1498                 :            :                     }
    1499                 :            :                 }
    1500                 :         57 :             }
    1501                 :            :         }
    1502                 :            :     }
    1503                 :            : }
    1504                 :            : 
    1505                 :          0 : void ScDetectiveFunc::UpdateAllArrowColors()
    1506                 :            : {
    1507                 :            :     //  no undo actions necessary
    1508                 :            : 
    1509                 :          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1510         [ #  # ]:          0 :     if (!pModel)
    1511                 :          0 :         return;
    1512                 :            : 
    1513         [ #  # ]:          0 :     for( SCTAB nObjTab = 0, nTabCount = pDoc->GetTableCount(); nObjTab < nTabCount; ++nObjTab )
    1514                 :            :     {
    1515                 :          0 :         SdrPage* pPage = pModel->GetPage( static_cast< sal_uInt16 >( nObjTab ) );
    1516                 :            :         OSL_ENSURE( pPage, "Page ?" );
    1517         [ #  # ]:          0 :         if( pPage )
    1518                 :            :         {
    1519         [ #  # ]:          0 :             SdrObjListIter aIter( *pPage, IM_FLAT );
    1520 [ #  # ][ #  # ]:          0 :             for( SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next() )
                 [ #  # ]
    1521                 :            :             {
    1522 [ #  # ][ #  # ]:          0 :                 if ( pObject->GetLayer() == SC_LAYER_INTERN )
    1523                 :            :                 {
    1524                 :          0 :                     sal_Bool bArrow = false;
    1525                 :          0 :                     sal_Bool bError = false;
    1526                 :            : 
    1527                 :          0 :                     ScAddress aPos;
    1528                 :          0 :                     ScRange aSource;
    1529                 :            :                     bool bDummy;
    1530         [ #  # ]:          0 :                     ScDetectiveObjType eType = GetDetectiveObjectType( pObject, nObjTab, aPos, aSource, bDummy );
    1531 [ #  # ][ #  # ]:          0 :                     if ( eType == SC_DETOBJ_ARROW || eType == SC_DETOBJ_TOOTHERTAB )
    1532                 :            :                     {
    1533                 :            :                         //  source is valid, determine error flag from source range
    1534                 :            : 
    1535                 :          0 :                         ScAddress aErrPos;
    1536 [ #  # ][ #  # ]:          0 :                         if ( HasError( aSource, aErrPos ) )
    1537                 :          0 :                             bError = sal_True;
    1538                 :            :                         else
    1539                 :          0 :                             bArrow = sal_True;
    1540                 :            :                     }
    1541         [ #  # ]:          0 :                     else if ( eType == SC_DETOBJ_FROMOTHERTAB )
    1542                 :            :                     {
    1543                 :            :                         //  source range is no longer known, take error flag from formula itself
    1544                 :            :                         //  (this means, if the formula has an error, all references to other tables
    1545                 :            :                         //  are marked red)
    1546                 :            : 
    1547                 :          0 :                         ScAddress aErrPos;
    1548 [ #  # ][ #  # ]:          0 :                         if ( HasError( ScRange( aPos), aErrPos ) )
    1549                 :          0 :                             bError = sal_True;
    1550                 :            :                         else
    1551                 :          0 :                             bArrow = sal_True;
    1552                 :            :                     }
    1553         [ #  # ]:          0 :                     else if ( eType == SC_DETOBJ_CIRCLE )
    1554                 :            :                     {
    1555                 :            :                         //  circles (error marks) are always red
    1556                 :            : 
    1557                 :          0 :                         bError = sal_True;
    1558                 :            :                     }
    1559         [ #  # ]:          0 :                     else if ( eType == SC_DETOBJ_NONE )
    1560                 :            :                     {
    1561                 :            :                         //  frame for area reference has no ObjType, always gets arrow color
    1562                 :            : 
    1563 [ #  # ][ #  # ]:          0 :                         if ( pObject->ISA( SdrRectObj ) && !pObject->ISA( SdrCaptionObj ) )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1564                 :            :                         {
    1565                 :          0 :                             bArrow = sal_True;
    1566                 :            :                         }
    1567                 :            :                     }
    1568                 :            : 
    1569 [ #  # ][ #  # ]:          0 :                     if ( bArrow || bError )
    1570                 :            :                     {
    1571 [ #  # ][ #  # ]:          0 :                         ColorData nColorData = ( bError ? GetErrorColor() : GetArrowColor() );
                 [ #  # ]
    1572 [ #  # ][ #  # ]:          0 :                         pObject->SetMergedItem( XLineColorItem( String(), Color( nColorData ) ) );
         [ #  # ][ #  # ]
                 [ #  # ]
    1573                 :            : 
    1574                 :            :                         // repaint only
    1575         [ #  # ]:          0 :                         pObject->ActionChanged();
    1576                 :            :                     }
    1577                 :            :                 }
    1578                 :          0 :             }
    1579                 :            :         }
    1580                 :            :     }
    1581                 :            : }
    1582                 :            : 
    1583                 :          0 : sal_Bool ScDetectiveFunc::FindFrameForObject( SdrObject* pObject, ScRange& rRange )
    1584                 :            : {
    1585                 :            :     //  find the rectangle for an arrow (always the object directly before the arrow)
    1586                 :            :     //  rRange must be initialized to the source cell of the arrow (start of area)
    1587                 :            : 
    1588                 :          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1589         [ #  # ]:          0 :     if (!pModel) return false;
    1590                 :            : 
    1591                 :          0 :     SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
    1592                 :            :     OSL_ENSURE(pPage,"Page ?");
    1593         [ #  # ]:          0 :     if (!pPage) return false;
    1594                 :            : 
    1595                 :            :     // test if the object is a direct page member
    1596 [ #  # ][ #  # ]:          0 :     if( pObject && pObject->GetPage() && (pObject->GetPage() == pObject->GetObjList()) )
         [ #  # ][ #  # ]
    1597                 :            :     {
    1598                 :            :         // Is there a previous object?
    1599                 :          0 :         const sal_uInt32 nOrdNum(pObject->GetOrdNum());
    1600                 :            : 
    1601         [ #  # ]:          0 :         if(nOrdNum > 0)
    1602                 :            :         {
    1603                 :          0 :             SdrObject* pPrevObj = pPage->GetObj(nOrdNum - 1);
    1604                 :            : 
    1605 [ #  # ][ #  # ]:          0 :             if ( pPrevObj && pPrevObj->GetLayer() == SC_LAYER_INTERN && pPrevObj->ISA(SdrRectObj) )
         [ #  # ][ #  # ]
    1606                 :            :             {
    1607                 :          0 :                 ScDrawObjData* pPrevData = ScDrawLayer::GetObjDataTab( pPrevObj, rRange.aStart.Tab() );
    1608 [ #  # ][ #  # ]:          0 :                 if ( pPrevData && pPrevData->maStart.IsValid() && pPrevData->maEnd.IsValid() && (pPrevData->maStart == rRange.aStart) )
         [ #  # ][ #  # ]
                 [ #  # ]
    1609                 :            :                 {
    1610                 :          0 :                     rRange.aEnd = pPrevData->maEnd;
    1611                 :          0 :                     return sal_True;
    1612                 :            :                 }
    1613                 :            :             }
    1614                 :            :         }
    1615                 :            :     }
    1616                 :          0 :     return false;
    1617                 :            : }
    1618                 :            : 
    1619                 :          0 : ScDetectiveObjType ScDetectiveFunc::GetDetectiveObjectType( SdrObject* pObject, SCTAB nObjTab,
    1620                 :            :                                 ScAddress& rPosition, ScRange& rSource, bool& rRedLine )
    1621                 :            : {
    1622                 :          0 :     rRedLine = false;
    1623                 :          0 :     ScDetectiveObjType eType = SC_DETOBJ_NONE;
    1624                 :            : 
    1625 [ #  # ][ #  # ]:          0 :     if ( pObject && pObject->GetLayer() == SC_LAYER_INTERN )
                 [ #  # ]
    1626                 :            :     {
    1627         [ #  # ]:          0 :         if ( ScDrawObjData* pData = ScDrawLayer::GetObjDataTab( pObject, nObjTab ) )
    1628                 :            :         {
    1629                 :          0 :             bool bValidStart = pData->maStart.IsValid();
    1630                 :          0 :             bool bValidEnd = pData->maEnd.IsValid();
    1631                 :            : 
    1632 [ #  # ][ #  # ]:          0 :             if ( pObject->IsPolyObj() && pObject->GetPointCount() == 2 )
                 [ #  # ]
    1633                 :            :             {
    1634                 :            :                 // line object -> arrow
    1635                 :            : 
    1636         [ #  # ]:          0 :                 if ( bValidStart )
    1637         [ #  # ]:          0 :                     eType = bValidEnd ? SC_DETOBJ_ARROW : SC_DETOBJ_TOOTHERTAB;
    1638         [ #  # ]:          0 :                 else if ( bValidEnd )
    1639                 :          0 :                     eType = SC_DETOBJ_FROMOTHERTAB;
    1640                 :            : 
    1641         [ #  # ]:          0 :                 if ( bValidStart )
    1642                 :          0 :                     rSource = pData->maStart;
    1643         [ #  # ]:          0 :                 if ( bValidEnd )
    1644                 :          0 :                     rPosition = pData->maEnd;
    1645                 :            : 
    1646 [ #  # ][ #  # ]:          0 :                 if ( bValidStart && lcl_HasThickLine( *pObject ) )
                 [ #  # ]
    1647                 :            :                 {
    1648                 :            :                     // thick line -> look for frame before this object
    1649                 :            : 
    1650                 :          0 :                     FindFrameForObject( pObject, rSource );     // modifies rSource
    1651                 :            :                 }
    1652                 :            : 
    1653                 :          0 :                 ColorData nObjColor = ((const XLineColorItem&)pObject->GetMergedItem(XATTR_LINECOLOR)).GetColorValue().GetColor();
    1654 [ #  # ][ #  # ]:          0 :                 if ( nObjColor == GetErrorColor() && nObjColor != GetArrowColor() )
                 [ #  # ]
    1655                 :          0 :                     rRedLine = true;
    1656                 :            :             }
    1657         [ #  # ]:          0 :             else if ( pObject->ISA(SdrCircObj) )
    1658                 :            :             {
    1659         [ #  # ]:          0 :                 if ( bValidStart )
    1660                 :            :                 {
    1661                 :            :                     // cell position is returned in rPosition
    1662                 :            : 
    1663                 :          0 :                     rPosition = pData->maStart;
    1664                 :          0 :                     eType = SC_DETOBJ_CIRCLE;
    1665                 :            :                 }
    1666                 :            :             }
    1667                 :            :         }
    1668                 :            :     }
    1669                 :            : 
    1670                 :          0 :     return eType;
    1671                 :            : }
    1672                 :            : 
    1673                 :          0 : void ScDetectiveFunc::InsertObject( ScDetectiveObjType eType,
    1674                 :            :                             const ScAddress& rPosition, const ScRange& rSource,
    1675                 :            :                             sal_Bool bRedLine )
    1676                 :            : {
    1677         [ #  # ]:          0 :     ScDrawLayer* pModel = pDoc->GetDrawLayer();
    1678         [ #  # ]:          0 :     if (!pModel) return;
    1679         [ #  # ]:          0 :     ScDetectiveData aData( pModel );
    1680                 :            : 
    1681   [ #  #  #  # ]:          0 :     switch (eType)
    1682                 :            :     {
    1683                 :            :         case SC_DETOBJ_ARROW:
    1684                 :            :         case SC_DETOBJ_FROMOTHERTAB:
    1685                 :          0 :             InsertArrow( rPosition.Col(), rPosition.Row(),
    1686                 :          0 :                          rSource.aStart.Col(), rSource.aStart.Row(),
    1687                 :          0 :                          rSource.aEnd.Col(), rSource.aEnd.Row(),
    1688         [ #  # ]:          0 :                          (eType == SC_DETOBJ_FROMOTHERTAB), bRedLine, aData );
    1689                 :          0 :             break;
    1690                 :            :         case SC_DETOBJ_TOOTHERTAB:
    1691                 :          0 :             InsertToOtherTab( rSource.aStart.Col(), rSource.aStart.Row(),
    1692                 :          0 :                               rSource.aEnd.Col(), rSource.aEnd.Row(),
    1693         [ #  # ]:          0 :                               bRedLine, aData );
    1694                 :          0 :             break;
    1695                 :            :         case SC_DETOBJ_CIRCLE:
    1696         [ #  # ]:          0 :             DrawCircle( rPosition.Col(), rPosition.Row(), aData );
    1697                 :          0 :             break;
    1698                 :            :         default:
    1699                 :            :         {
    1700                 :            :             // added to avoid warnings
    1701                 :            :         }
    1702         [ #  # ]:          0 :     }
    1703                 :            : }
    1704                 :            : 
    1705                 :         26 : ColorData ScDetectiveFunc::GetArrowColor()
    1706                 :            : {
    1707         [ -  + ]:         26 :     if (!bColorsInitialized)
    1708                 :          0 :         InitializeColors();
    1709                 :         26 :     return nArrowColor;
    1710                 :            : }
    1711                 :            : 
    1712                 :         13 : ColorData ScDetectiveFunc::GetErrorColor()
    1713                 :            : {
    1714         [ -  + ]:         13 :     if (!bColorsInitialized)
    1715                 :          0 :         InitializeColors();
    1716                 :         13 :     return nErrorColor;
    1717                 :            : }
    1718                 :            : 
    1719                 :         10 : ColorData ScDetectiveFunc::GetCommentColor()
    1720                 :            : {
    1721         [ +  + ]:         10 :     if (!bColorsInitialized)
    1722                 :          4 :         InitializeColors();
    1723                 :         10 :     return nCommentColor;
    1724                 :            : }
    1725                 :            : 
    1726                 :          4 : void ScDetectiveFunc::InitializeColors()
    1727                 :            : {
    1728                 :            :     // may be called several times to update colors from configuration
    1729                 :            : 
    1730                 :          4 :     const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
    1731                 :          4 :     nArrowColor   = rColorCfg.GetColorValue(svtools::CALCDETECTIVE).nColor;
    1732                 :          4 :     nErrorColor   = rColorCfg.GetColorValue(svtools::CALCDETECTIVEERROR).nColor;
    1733                 :          4 :     nCommentColor = rColorCfg.GetColorValue(svtools::CALCNOTESBACKGROUND).nColor;
    1734                 :            : 
    1735                 :          4 :     bColorsInitialized = sal_True;
    1736                 :          4 : }
    1737                 :            : 
    1738                 :          0 : sal_Bool ScDetectiveFunc::IsColorsInitialized()
    1739                 :            : {
    1740                 :          0 :     return bColorsInitialized;
    1741                 :            : }
    1742                 :            : 
    1743                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10