LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/tool - reffind.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 98 122 80.3 %
Date: 2012-12-27 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <string.h>
      21             : 
      22             : #include "reffind.hxx"
      23             : #include "global.hxx"
      24             : #include "compiler.hxx"
      25             : #include "document.hxx"
      26             : 
      27             : // STATIC DATA -----------------------------------------------------------
      28             : 
      29             : namespace {
      30             : 
      31             : //  include colon -> duplicate referenced are handled individual
      32             : const sal_Unicode pDelimiters[] = {
      33             :     '=','(',')','+','-','*','/','^','&',' ','{','}','<','>',':', 0
      34             : };
      35             : 
      36             : // =======================================================================
      37             : 
      38          52 : inline bool IsText( sal_Unicode c )
      39             : {
      40          52 :     bool bFound = ScGlobal::UnicodeStrChr( pDelimiters, c );
      41          52 :     if (bFound)
      42             :         // This is one of delimiters, therefore not text.
      43           8 :         return false;
      44             : 
      45             :     // argument separator is configurable.
      46          44 :     const sal_Unicode sep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
      47          44 :     return c != sep;
      48             : }
      49             : 
      50          20 : inline bool IsText( bool& bQuote, sal_Unicode c )
      51             : {
      52          20 :     if (c == '\'')
      53             :     {
      54           0 :         bQuote = !bQuote;
      55           0 :         return true;
      56             :     }
      57          20 :     if (bQuote)
      58           0 :         return true;
      59             : 
      60          20 :     return IsText(c);
      61             : }
      62             : 
      63             : /**
      64             :  * Find first character position that is considered text.  A character is
      65             :  * considered a text when it's within the ascii range and when it's not a
      66             :  * delimiter.
      67             :  */
      68           8 : xub_StrLen FindStartPos(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos)
      69             : {
      70          24 :     while (nStartPos <= nEndPos && !IsText(p[nStartPos]))
      71           8 :         ++nStartPos;
      72             : 
      73           8 :     return nStartPos;
      74             : }
      75             : 
      76           4 : xub_StrLen FindEndPosA1(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos)
      77             : {
      78           4 :     bool bQuote = false;
      79           4 :     xub_StrLen nNewEnd = nStartPos;
      80          28 :     while (nNewEnd <= nEndPos && IsText(bQuote, p[nNewEnd]))
      81          20 :         ++nNewEnd;
      82             : 
      83           4 :     return nNewEnd;
      84             : }
      85             : 
      86           8 : xub_StrLen FindEndPosR1C1(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos)
      87             : {
      88           8 :     xub_StrLen nNewEnd = nStartPos;
      89           8 :     p = &p[nStartPos];
      90          28 :     for (; nNewEnd <= nEndPos; ++p, ++nNewEnd)
      91             :     {
      92          20 :         if (*p == '\'')
      93             :         {
      94             :             // Skip until the closing quote.
      95           0 :             for (; nNewEnd <= nEndPos; ++p, ++nNewEnd)
      96           0 :                 if (*p == '\'')
      97           0 :                     break;
      98             :         }
      99          20 :         else if (*p == '[')
     100             :         {
     101             :             // Skip until the closing braket.
     102          16 :             for (; nNewEnd <= nEndPos; ++p, ++nNewEnd)
     103          16 :                 if (*p == ']')
     104           4 :                     break;
     105             :         }
     106          16 :         else if (!IsText(*p))
     107           0 :             break;
     108             :     }
     109             : 
     110           8 :     return nNewEnd;
     111             : }
     112             : 
     113             : /**
     114             :  * Find last character position that is considred text, from the specified
     115             :  * start position.
     116             :  */
     117           8 : xub_StrLen FindEndPos(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos,
     118             :                            formula::FormulaGrammar::AddressConvention eConv)
     119             : {
     120           8 :     switch (eConv)
     121             :     {
     122             :         case formula::FormulaGrammar::CONV_XL_R1C1:
     123           4 :             return FindEndPosR1C1(p, nStartPos, nEndPos);
     124             :         case formula::FormulaGrammar::CONV_OOO:
     125             :         case formula::FormulaGrammar::CONV_XL_A1:
     126             :         default:
     127           4 :             return FindEndPosA1(p, nStartPos, nEndPos);
     128             :     }
     129             : }
     130             : 
     131           4 : void ExpandToTextA1(const sal_Unicode* p, xub_StrLen nLen, xub_StrLen& rStartPos, xub_StrLen& rEndPos)
     132             : {
     133           8 :     while (rStartPos > 0 && IsText(p[rStartPos - 1]) )
     134           0 :         --rStartPos;
     135           4 :     if (rEndPos)
     136           4 :         --rEndPos;
     137           8 :     while (rEndPos+1 < nLen && IsText(p[rEndPos + 1]) )
     138           0 :         ++rEndPos;
     139           4 : }
     140             : 
     141           4 : void ExpandToTextR1C1(const sal_Unicode* p, xub_StrLen nLen, xub_StrLen& rStartPos, xub_StrLen& rEndPos)
     142             : {
     143             :     // move back the start position to the first text character.
     144           4 :     if (rStartPos > 0)
     145             :     {
     146           0 :         for (--rStartPos; rStartPos > 0; --rStartPos)
     147             :         {
     148           0 :             sal_Unicode c = p[rStartPos];
     149           0 :             if (c == '\'')
     150             :             {
     151             :                 // Skip until the opening quote.
     152           0 :                 for (--rStartPos; rStartPos > 0; --rStartPos)
     153             :                 {
     154           0 :                     c = p[rStartPos];
     155           0 :                     if (c == '\'')
     156           0 :                         break;
     157             :                 }
     158             :             }
     159           0 :             else if (c == ']')
     160             :             {
     161             :                 // Skip until the opening braket.
     162           0 :                 for (--rStartPos; rStartPos > 0; --rStartPos)
     163             :                 {
     164           0 :                     if (c == '[')
     165           0 :                         break;
     166             :                 }
     167             :             }
     168           0 :             else if (!IsText(c))
     169             :             {
     170           0 :                 ++rStartPos;
     171           0 :                 break;
     172             :             }
     173             :         }
     174             :     }
     175             : 
     176             :     // move forward the end position to the last text character.
     177           4 :     rEndPos = FindEndPosR1C1(p, rEndPos, nLen-1);
     178           4 : }
     179             : 
     180           8 : void ExpandToText(const sal_Unicode* p, xub_StrLen nLen, xub_StrLen& rStartPos, xub_StrLen& rEndPos,
     181             :                   formula::FormulaGrammar::AddressConvention eConv)
     182             : {
     183           8 :     switch (eConv)
     184             :     {
     185             :         case formula::FormulaGrammar::CONV_XL_R1C1:
     186           4 :             ExpandToTextR1C1(p, nLen, rStartPos, rEndPos);
     187           4 :         break;
     188             :         case formula::FormulaGrammar::CONV_OOO:
     189             :         case formula::FormulaGrammar::CONV_XL_A1:
     190             :         default:
     191           4 :             ExpandToTextA1(p, nLen, rStartPos, rEndPos);
     192             :     }
     193           8 : }
     194             : 
     195             : }
     196             : 
     197           2 : ScRefFinder::ScRefFinder(
     198             :     const String& rFormula, const ScAddress& rPos,
     199             :     ScDocument* pDocument, formula::FormulaGrammar::AddressConvention eConvP) :
     200             :     aFormula( rFormula ),
     201             :     eConv( eConvP ),
     202             :     pDoc( pDocument ),
     203           2 :     maPos(rPos)
     204             : {
     205           2 :     nSelStart = nSelEnd = nFound = 0;
     206           2 : }
     207             : 
     208           2 : ScRefFinder::~ScRefFinder()
     209             : {
     210           2 : }
     211             : 
     212           8 : static sal_uInt16 lcl_NextFlags( sal_uInt16 nOld )
     213             : {
     214           8 :     sal_uInt16 nNew = nOld & 7;                 // die drei Abs-Flags
     215           8 :     nNew = ( nNew - 1 ) & 7;                // weiterzaehlen
     216             : 
     217           8 :     if (!(nOld & SCA_TAB_3D))
     218           8 :         nNew &= ~SCA_TAB_ABSOLUTE;          // not 3D -> never absolute!
     219             : 
     220           8 :     return ( nOld & 0xfff8 ) | nNew;
     221             : }
     222             : 
     223           8 : void ScRefFinder::ToggleRel( xub_StrLen nStartPos, xub_StrLen nEndPos )
     224             : {
     225           8 :     xub_StrLen nLen = aFormula.Len();
     226           8 :     if (!nLen)
     227           8 :         return;
     228           8 :     const sal_Unicode* pSource = aFormula.GetBuffer();      // for quick access
     229             : 
     230             :     // expand selection, and instead of selection start- and end-index
     231             : 
     232           8 :     if ( nEndPos < nStartPos )
     233           0 :         ::std::swap(nEndPos, nStartPos);
     234             : 
     235           8 :     ExpandToText(pSource, nLen, nStartPos, nEndPos, eConv);
     236             : 
     237           8 :     String aResult;
     238           8 :     String aExpr;
     239           8 :     String aSep;
     240           8 :     ScAddress aAddr;
     241           8 :     nFound = 0;
     242             : 
     243           8 :     xub_StrLen nLoopStart = nStartPos;
     244          24 :     while ( nLoopStart <= nEndPos )
     245             :     {
     246             :         // Determine the stard and end positions of a text segment.
     247           8 :         xub_StrLen nEStart = FindStartPos(pSource, nLoopStart, nEndPos);
     248           8 :         xub_StrLen nEEnd  = FindEndPos(pSource, nEStart, nEndPos, eConv);
     249             : 
     250           8 :         aSep  = aFormula.Copy( nLoopStart, nEStart-nLoopStart );
     251           8 :         aExpr = aFormula.Copy( nEStart, nEEnd-nEStart );
     252             : 
     253             :         // Check the validity of the expression, and toggle the relative flag.
     254           8 :         ScAddress::Details aDetails(eConv, maPos.Row(), maPos.Col());
     255           8 :         sal_uInt16 nResult = aAddr.Parse(aExpr, pDoc, aDetails);
     256           8 :         if ( nResult & SCA_VALID )
     257             :         {
     258           8 :             sal_uInt16 nFlags = lcl_NextFlags( nResult );
     259           8 :             aAddr.Format(aExpr, nFlags, pDoc, aDetails);
     260             : 
     261           8 :             xub_StrLen nAbsStart = nStartPos+aResult.Len()+aSep.Len();
     262             : 
     263           8 :             if (!nFound)                            // first reference ?
     264           8 :                 nSelStart = nAbsStart;
     265           8 :             nSelEnd = nAbsStart+aExpr.Len();        // selection, no indizes
     266           8 :             ++nFound;
     267             :         }
     268             : 
     269             :         // assemble
     270             : 
     271           8 :         aResult += aSep;
     272           8 :         aResult += aExpr;
     273             : 
     274           8 :         nLoopStart = nEEnd;
     275             :     }
     276             : 
     277           8 :     String aTotal = aFormula.Copy( 0, nStartPos );
     278           8 :     aTotal += aResult;
     279           8 :     aTotal += aFormula.Copy( nEndPos+1 );
     280             : 
     281           8 :     aFormula = aTotal;
     282             : }
     283             : 
     284             : 
     285             : 
     286             : 
     287             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10