xref: /aoo4110/main/sc/source/core/tool/reffind.cxx (revision b1cdbd2c)
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