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