[Libreoffice-commits] .: Branch 'libreoffice-3-4' - sc/inc sc/source
Kohei Yoshida
kohei at kemper.freedesktop.org
Fri Apr 15 22:40:58 PDT 2011
sc/inc/reffind.hxx | 5 -
sc/source/core/tool/reffind.cxx | 196 ++++++++++++++++++++++++++++++++--------
sc/source/ui/view/editsh.cxx | 7 -
sc/source/ui/view/viewfun4.cxx | 2
4 files changed, 168 insertions(+), 42 deletions(-)
New commits:
commit c5c1064a780f1e94b75e050fc811dc348dfa7dd1
Author: Kohei Yoshida <kyoshida at novell.com>
Date: Fri Apr 15 16:25:33 2011 -0400
fdo#36124: Fix relative/absolute toggling in R1C1 mode.
diff --git a/sc/inc/reffind.hxx b/sc/inc/reffind.hxx
index 3544eae..6b7b419 100644
--- a/sc/inc/reffind.hxx
+++ b/sc/inc/reffind.hxx
@@ -42,14 +42,13 @@ private:
String aFormula;
formula::FormulaGrammar::AddressConvention eConv;
ScDocument* pDoc;
+ ScAddress maPos;
xub_StrLen nFound;
xub_StrLen nSelStart;
xub_StrLen nSelEnd;
public:
- static const sal_Unicode pDelimiters[];
-
- ScRefFinder( const String& rFormula,
+ ScRefFinder( const String& rFormula, const ScAddress& rPos,
ScDocument* pDocument = NULL,
formula::FormulaGrammar::AddressConvention eConvP = formula::FormulaGrammar::CONV_OOO );
~ScRefFinder();
diff --git a/sc/source/core/tool/reffind.cxx b/sc/source/core/tool/reffind.cxx
index 6a34c72..a0924cd 100644
--- a/sc/source/core/tool/reffind.cxx
+++ b/sc/source/core/tool/reffind.cxx
@@ -42,16 +42,18 @@
// STATIC DATA -----------------------------------------------------------
+namespace {
+
// incl. Doppelpunkt -> Doppelte Referenzen werden einzeln behandelt
-const sal_Unicode ScRefFinder::pDelimiters[] = {
+const sal_Unicode pDelimiters[] = {
'=','(',')','+','-','*','/','^','&',' ','{','}','<','>',':', 0
};
// =======================================================================
-inline sal_Bool IsText( sal_Unicode c )
+inline bool IsText( sal_Unicode c )
{
- bool bFound = ScGlobal::UnicodeStrChr( ScRefFinder::pDelimiters, c );
+ bool bFound = ScGlobal::UnicodeStrChr( pDelimiters, c );
if (bFound)
// This is one of delimiters, therefore not text.
return false;
@@ -61,23 +63,160 @@ inline sal_Bool IsText( sal_Unicode c )
return c != sep;
}
-inline sal_Bool IsText( sal_Bool& bQuote, sal_Unicode c )
+inline bool IsText( bool& bQuote, sal_Unicode c )
{
- if ( c == '\'' )
+ if (c == '\'')
{
bQuote = !bQuote;
- return sal_True;
+ return true;
+ }
+ if (bQuote)
+ return true;
+
+ return IsText(c);
+}
+
+/**
+ * Find first character position that is considered text. A character is
+ * considered a text when it's within the ascii range and when it's not a
+ * delimiter.
+ */
+xub_StrLen FindStartPos(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos)
+{
+ while (nStartPos <= nEndPos && !IsText(p[nStartPos]))
+ ++nStartPos;
+
+ return nStartPos;
+}
+
+xub_StrLen FindEndPosA1(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos)
+{
+ bool bQuote = false;
+ xub_StrLen nNewEnd = nStartPos;
+ while (nNewEnd <= nEndPos && IsText(bQuote, p[nNewEnd]))
+ ++nNewEnd;
+
+ return nNewEnd;
+}
+
+xub_StrLen FindEndPosR1C1(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos)
+{
+ xub_StrLen nNewEnd = nStartPos;
+ p = &p[nStartPos];
+ for (; nNewEnd <= nEndPos; ++p, ++nNewEnd)
+ {
+ if (*p == '\'')
+ {
+ // Skip until the closing quote.
+ for (; nNewEnd <= nEndPos; ++p, ++nNewEnd)
+ if (*p == '\'')
+ break;
+ }
+ else if (*p == '[')
+ {
+ // Skip until the closing braket.
+ for (; nNewEnd <= nEndPos; ++p, ++nNewEnd)
+ if (*p == ']')
+ break;
+ }
+ else if (!IsText(*p))
+ break;
+ }
+
+ return nNewEnd;
+}
+
+/**
+ * Find last character position that is considred text, from the specified
+ * start position.
+ */
+xub_StrLen FindEndPos(const sal_Unicode* p, xub_StrLen nStartPos, xub_StrLen nEndPos,
+ formula::FormulaGrammar::AddressConvention eConv)
+{
+ switch (eConv)
+ {
+ case formula::FormulaGrammar::CONV_XL_R1C1:
+ return FindEndPosR1C1(p, nStartPos, nEndPos);
+ case formula::FormulaGrammar::CONV_OOO:
+ case formula::FormulaGrammar::CONV_XL_A1:
+ default:
+ return FindEndPosA1(p, nStartPos, nEndPos);
}
- if ( bQuote )
- return sal_True;
- return IsText( c );
}
-ScRefFinder::ScRefFinder(const String& rFormula, ScDocument* pDocument,
- formula::FormulaGrammar::AddressConvention eConvP) :
+void ExpandToTextA1(const sal_Unicode* p, xub_StrLen nLen, xub_StrLen& rStartPos, xub_StrLen& rEndPos)
+{
+ while (rStartPos > 0 && IsText(p[rStartPos - 1]) )
+ --rStartPos;
+ if (rEndPos)
+ --rEndPos;
+ while (rEndPos+1 < nLen && IsText(p[rEndPos + 1]) )
+ ++rEndPos;
+}
+
+void ExpandToTextR1C1(const sal_Unicode* p, xub_StrLen nLen, xub_StrLen& rStartPos, xub_StrLen& rEndPos)
+{
+ // move back the start position to the first text character.
+ if (rStartPos > 0)
+ {
+ for (--rStartPos; rStartPos > 0; --rStartPos)
+ {
+ sal_Unicode c = p[rStartPos];
+ if (c == '\'')
+ {
+ // Skip until the opening quote.
+ for (--rStartPos; rStartPos > 0; --rStartPos)
+ {
+ c = p[rStartPos];
+ if (c == '\'')
+ break;
+ }
+ }
+ else if (c == ']')
+ {
+ // Skip until the opening braket.
+ for (--rStartPos; rStartPos > 0; --rStartPos)
+ {
+ if (c == '[')
+ break;
+ }
+ }
+ else if (!IsText(c))
+ {
+ ++rStartPos;
+ break;
+ }
+ }
+ }
+
+ // move forward the end position to the last text character.
+ rEndPos = FindEndPosR1C1(p, rEndPos, nLen-1);
+}
+
+void ExpandToText(const sal_Unicode* p, xub_StrLen nLen, xub_StrLen& rStartPos, xub_StrLen& rEndPos,
+ formula::FormulaGrammar::AddressConvention eConv)
+{
+ switch (eConv)
+ {
+ case formula::FormulaGrammar::CONV_XL_R1C1:
+ ExpandToTextR1C1(p, nLen, rStartPos, rEndPos);
+ break;
+ case formula::FormulaGrammar::CONV_OOO:
+ case formula::FormulaGrammar::CONV_XL_A1:
+ default:
+ ExpandToTextA1(p, nLen, rStartPos, rEndPos);
+ }
+}
+
+}
+
+ScRefFinder::ScRefFinder(
+ const String& rFormula, const ScAddress& rPos,
+ ScDocument* pDocument, formula::FormulaGrammar::AddressConvention eConvP) :
aFormula( rFormula ),
eConv( eConvP ),
- pDoc( pDocument )
+ pDoc( pDocument ),
+ maPos(rPos)
{
nSelStart = nSelEnd = nFound = 0;
}
@@ -107,15 +246,9 @@ void ScRefFinder::ToggleRel( xub_StrLen nStartPos, xub_StrLen nEndPos )
// Selektion erweitern, und statt Selektion Start- und Endindex
if ( nEndPos < nStartPos )
- {
- xub_StrLen nTemp = nStartPos; nStartPos = nEndPos; nEndPos = nTemp;
- }
- while (nStartPos > 0 && IsText(pSource[nStartPos - 1]) )
- --nStartPos;
- if (nEndPos)
- --nEndPos;
- while (nEndPos+1 < nLen && IsText(pSource[nEndPos + 1]) )
- ++nEndPos;
+ ::std::swap(nEndPos, nStartPos);
+
+ ExpandToText(pSource, nLen, nStartPos, nEndPos, eConv);
String aResult;
String aExpr;
@@ -126,27 +259,20 @@ void ScRefFinder::ToggleRel( xub_StrLen nStartPos, xub_StrLen nEndPos )
xub_StrLen nLoopStart = nStartPos;
while ( nLoopStart <= nEndPos )
{
- // Formel zerlegen
-
- xub_StrLen nEStart = nLoopStart;
- while ( nEStart <= nEndPos && !IsText(pSource[nEStart]) )
- ++nEStart;
-
- sal_Bool bQuote = false;
- xub_StrLen nEEnd = nEStart;
- while ( nEEnd <= nEndPos && IsText(bQuote,pSource[nEEnd]) )
- ++nEEnd;
+ // Determine the stard and end positions of a text segment.
+ xub_StrLen nEStart = FindStartPos(pSource, nLoopStart, nEndPos);
+ xub_StrLen nEEnd = FindEndPos(pSource, nEStart, nEndPos, eConv);
aSep = aFormula.Copy( nLoopStart, nEStart-nLoopStart );
aExpr = aFormula.Copy( nEStart, nEEnd-nEStart );
- // Test, ob aExpr eine Referenz ist
-
- sal_uInt16 nResult = aAddr.Parse( aExpr, pDoc, pDoc->GetAddressConvention() );
+ // Check the validity of the expression, and toggle the relative flag.
+ ScAddress::Details aDetails(eConv, maPos.Row(), maPos.Col());
+ sal_uInt16 nResult = aAddr.Parse(aExpr, pDoc, aDetails);
if ( nResult & SCA_VALID )
{
sal_uInt16 nFlags = lcl_NextFlags( nResult );
- aAddr.Format( aExpr, nFlags, pDoc, pDoc->GetAddressConvention() );
+ aAddr.Format(aExpr, nFlags, pDoc, aDetails);
xub_StrLen nAbsStart = nStartPos+aResult.Len()+aSep.Len();
diff --git a/sc/source/ui/view/editsh.cxx b/sc/source/ui/view/editsh.cxx
index 3f6b1ae..4479cb7 100644
--- a/sc/source/ui/view/editsh.cxx
+++ b/sc/source/ui/view/editsh.cxx
@@ -484,13 +484,14 @@ void ScEditShell::Execute( SfxRequest& rReq )
case SID_TOGGLE_REL:
{
- sal_Bool bOk = false;
+ bool bOk = false;
if (pEngine->GetParagraphCount() == 1)
{
String aText = pEngine->GetText();
ESelection aSel = pEditView->GetSelection(); // aktuelle View
- ScRefFinder aFinder( aText, pViewData->GetDocument() );
+ ScDocument* pDoc = pViewData->GetDocument();
+ ScRefFinder aFinder(aText, pViewData->GetCurPos(), pDoc, pDoc->GetAddressConvention());
aFinder.ToggleRel( aSel.nStartPos, aSel.nEndPos );
if (aFinder.GetFound())
{
@@ -503,7 +504,7 @@ void ScEditShell::Execute( SfxRequest& rReq )
pTopView->GetEditEngine()->SetText( aNew );
pTopView->SetSelection( aNewSel );
}
- bOk = sal_True;
+ bOk = true;
// Referenz wird selektiert -> beim Tippen nicht ueberschreiben
bSetSelIsRef = sal_True;
diff --git a/sc/source/ui/view/viewfun4.cxx b/sc/source/ui/view/viewfun4.cxx
index 5a9c647..818f3f5 100644
--- a/sc/source/ui/view/viewfun4.cxx
+++ b/sc/source/ui/view/viewfun4.cxx
@@ -259,7 +259,7 @@ void ScViewFunc::DoRefConversion( sal_Bool bRecord )
String aOld;
((ScFormulaCell*)pCell)->GetFormula(aOld);
xub_StrLen nLen = aOld.Len();
- ScRefFinder aFinder( aOld, pDoc );
+ ScRefFinder aFinder( aOld, aIter.GetPos(), pDoc, pDoc->GetAddressConvention() );
aFinder.ToggleRel( 0, nLen );
if (aFinder.GetFound())
{
More information about the Libreoffice-commits
mailing list