xref: /AOO41X/main/sc/source/core/tool/reffind.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include <string.h>
32 
33 #include "reffind.hxx"
34 #include "global.hxx"
35 #include "compiler.hxx"
36 #include "document.hxx"
37 
38 // STATIC DATA -----------------------------------------------------------
39 
40 //  incl. Doppelpunkt -> Doppelte Referenzen werden einzeln behandelt
41 const sal_Unicode __FAR_DATA ScRefFinder::pDelimiters[] = {
42     '=','(',')',';','+','-','*','/','^','&',' ','{','}','<','>',':', 0
43 };
44 
45 // =======================================================================
46 
IsText(sal_Unicode c)47 inline sal_Bool IsText( sal_Unicode c )
48 {
49     return !ScGlobal::UnicodeStrChr( ScRefFinder::pDelimiters, c );
50 }
51 
IsText(sal_Bool & bQuote,sal_Unicode c)52 inline sal_Bool IsText( sal_Bool& bQuote, sal_Unicode c )
53 {
54     if ( c == '\'' )
55     {
56         bQuote = !bQuote;
57         return sal_True;
58     }
59     if ( bQuote )
60         return sal_True;
61     return IsText( c );
62 }
63 
ScRefFinder(const String & rFormula,ScDocument * pDocument,formula::FormulaGrammar::AddressConvention eConvP)64 ScRefFinder::ScRefFinder(const String& rFormula, ScDocument* pDocument,
65              formula::FormulaGrammar::AddressConvention eConvP) :
66     aFormula( rFormula ),
67     eConv( eConvP ),
68     pDoc( pDocument )
69 {
70     nSelStart = nSelEnd = nFound = 0;
71 }
72 
~ScRefFinder()73 ScRefFinder::~ScRefFinder()
74 {
75 }
76 
lcl_NextFlags(sal_uInt16 nOld)77 sal_uInt16 lcl_NextFlags( sal_uInt16 nOld )
78 {
79     sal_uInt16 nNew = nOld & 7;                 // die drei Abs-Flags
80     nNew = ( nNew - 1 ) & 7;                // weiterzaehlen
81 
82     if (!(nOld & SCA_TAB_3D))
83         nNew &= ~SCA_TAB_ABSOLUTE;          // nicht 3D -> nie absolut!
84 
85     return ( nOld & 0xfff8 ) | nNew;
86 }
87 
ToggleRel(xub_StrLen nStartPos,xub_StrLen nEndPos)88 void ScRefFinder::ToggleRel( xub_StrLen nStartPos, xub_StrLen nEndPos )
89 {
90     xub_StrLen nLen = aFormula.Len();
91     if (!nLen)
92         return;
93     const sal_Unicode* pSource = aFormula.GetBuffer();      // fuer schnellen Zugriff
94 
95     //  Selektion erweitern, und statt Selektion Start- und Endindex
96 
97     if ( nEndPos < nStartPos )
98     {
99         xub_StrLen nTemp = nStartPos; nStartPos = nEndPos; nEndPos = nTemp;
100     }
101     while (nStartPos > 0 && IsText(pSource[nStartPos - 1]) )
102         --nStartPos;
103     if (nEndPos)
104         --nEndPos;
105     while (nEndPos+1 < nLen && IsText(pSource[nEndPos + 1]) )
106         ++nEndPos;
107 
108     String aResult;
109     String aExpr;
110     String aSep;
111     ScAddress aAddr;
112     nFound = 0;
113 
114     xub_StrLen nLoopStart = nStartPos;
115     while ( nLoopStart <= nEndPos )
116     {
117         //  Formel zerlegen
118 
119         xub_StrLen nEStart = nLoopStart;
120         while ( nEStart <= nEndPos && !IsText(pSource[nEStart]) )
121             ++nEStart;
122 
123         sal_Bool bQuote = sal_False;
124         xub_StrLen nEEnd = nEStart;
125         while ( nEEnd <= nEndPos && IsText(bQuote,pSource[nEEnd]) )
126             ++nEEnd;
127 
128         aSep  = aFormula.Copy( nLoopStart, nEStart-nLoopStart );
129         aExpr = aFormula.Copy( nEStart, nEEnd-nEStart );
130 
131         //  Test, ob aExpr eine Referenz ist
132 
133         sal_uInt16 nResult = aAddr.Parse( aExpr, pDoc, pDoc->GetAddressConvention() );
134         if ( nResult & SCA_VALID )
135         {
136             sal_uInt16 nFlags = lcl_NextFlags( nResult );
137             aAddr.Format( aExpr, nFlags, pDoc, pDoc->GetAddressConvention() );
138 
139             xub_StrLen nAbsStart = nStartPos+aResult.Len()+aSep.Len();
140 
141             if (!nFound)                            // erste Referenz ?
142                 nSelStart = nAbsStart;
143             nSelEnd = nAbsStart+aExpr.Len();        // Selektion, keine Indizes
144             ++nFound;
145         }
146 
147         //  zusammenbauen
148 
149         aResult += aSep;
150         aResult += aExpr;
151 
152         nLoopStart = nEEnd;
153     }
154 
155     String aTotal = aFormula.Copy( 0, nStartPos );
156     aTotal += aResult;
157     aTotal += aFormula.Copy( nEndPos+1 );
158 
159     aFormula = aTotal;
160 }
161 
162 
163 
164 
165