Avoid potential negative array index access to cached text.
[LibreOffice.git] / sc / source / core / tool / cellform.cxx
blob9d1a7319292379d7f62cd29f2fe8775d87fb236a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <cellform.hxx>
22 #include <svl/numformat.hxx>
23 #include <svl/sharedstring.hxx>
25 #include <formulacell.hxx>
26 #include <document.hxx>
27 #include <cellvalue.hxx>
28 #include <formula/errorcodes.hxx>
29 #include <editutil.hxx>
31 OUString ScCellFormat::GetString( const ScRefCellValue& rCell, sal_uInt32 nFormat,
32 const Color** ppColor, SvNumberFormatter& rFormatter, const ScDocument& rDoc,
33 bool bNullVals, bool bFormula, bool bUseStarFormat )
35 *ppColor = nullptr;
37 switch (rCell.getType())
39 case CELLTYPE_STRING:
41 OUString str;
42 rFormatter.GetOutputString(rCell.getSharedString()->getString(), nFormat, str, ppColor, bUseStarFormat);
43 return str;
45 case CELLTYPE_EDIT:
47 OUString str;
48 rFormatter.GetOutputString(rCell.getString(&rDoc), nFormat, str, ppColor );
49 return str;
51 case CELLTYPE_VALUE:
53 const double nValue = rCell.getDouble();
54 if (!bNullVals && nValue == 0.0)
55 return OUString();
56 else
58 OUString str;
59 rFormatter.GetOutputString( nValue, nFormat, str, ppColor, bUseStarFormat );
60 return str;
63 case CELLTYPE_FORMULA:
65 ScFormulaCell* pFCell = rCell.getFormula();
66 if ( bFormula )
68 return pFCell->GetFormula();
70 else
72 // A macro started from the interpreter, which has
73 // access to Formula Cells, becomes a CellText, even if
74 // that triggers further interpretation, except if those
75 // cells are already being interpreted.
76 // IdleCalc generally doesn't trigger further interpretation,
77 // as not to get Err522 (circular).
78 if ( pFCell->GetDocument().IsInInterpreter() &&
79 (!pFCell->GetDocument().GetMacroInterpretLevel()
80 || pFCell->IsRunning()) )
82 return "...";
84 else
86 const FormulaError nErrCode = pFCell->GetErrCode();
88 if (nErrCode != FormulaError::NONE)
89 return ScGlobal::GetErrorString(nErrCode);
90 else if ( pFCell->IsEmptyDisplayedAsString() )
91 return OUString();
92 else if ( pFCell->IsValue() )
94 double fValue = pFCell->GetValue();
95 if ( !bNullVals && fValue == 0.0 )
96 return OUString();
97 else
99 OUString str;
100 rFormatter.GetOutputString( fValue, nFormat, str, ppColor, bUseStarFormat );
101 return str;
104 else
106 OUString str;
107 rFormatter.GetOutputString( pFCell->GetString().getString(),
108 nFormat, str, ppColor, bUseStarFormat );
109 return str;
114 default:
115 return OUString();
119 OUString ScCellFormat::GetString(
120 ScDocument& rDoc, const ScAddress& rPos, sal_uInt32 nFormat, const Color** ppColor,
121 SvNumberFormatter& rFormatter, bool bNullVals, bool bFormula )
123 *ppColor = nullptr;
125 ScRefCellValue aCell(rDoc, rPos);
126 return GetString(aCell, nFormat, ppColor, rFormatter, rDoc, bNullVals, bFormula);
129 OUString ScCellFormat::GetInputString(
130 const ScRefCellValue& rCell, sal_uInt32 nFormat, SvNumberFormatter& rFormatter, const ScDocument& rDoc,
131 const svl::SharedString** pShared, bool bFiltering, bool bForceSystemLocale )
133 if(pShared != nullptr)
134 *pShared = nullptr;
135 switch (rCell.getType())
137 case CELLTYPE_STRING:
138 case CELLTYPE_EDIT:
139 return rCell.getString(&rDoc);
140 case CELLTYPE_VALUE:
142 OUString str;
143 rFormatter.GetInputLineString(rCell.getDouble(), nFormat, str, bFiltering, bForceSystemLocale);
144 return str;
146 break;
147 case CELLTYPE_FORMULA:
149 std::optional<OUString> str;
150 ScFormulaCell* pFC = rCell.getFormula();
151 if (pFC->IsEmptyDisplayedAsString())
152 ; // empty
153 else if (pFC->IsValue())
155 str.emplace();
156 rFormatter.GetInputLineString(pFC->GetValue(), nFormat, *str, bFiltering, bForceSystemLocale);
158 else
160 const svl::SharedString& shared = pFC->GetString();
161 // Allow callers to optimize by avoiding converting later back to OUString.
162 // To avoid refcounting that won't be needed, do not even return the OUString.
163 if( pShared != nullptr )
164 *pShared = &shared;
165 else
166 str = shared.getString();
169 const FormulaError nErrCode = pFC->GetErrCode();
170 if (nErrCode != FormulaError::NONE)
172 str.reset();
173 if( pShared != nullptr )
174 *pShared = nullptr;
177 return str ? std::move(*str) : svl::SharedString::EMPTY_STRING;
179 case CELLTYPE_NONE:
180 if( pShared != nullptr )
181 *pShared = &svl::SharedString::getEmptyString();
182 return svl::SharedString::EMPTY_STRING;
183 default:
184 return svl::SharedString::EMPTY_STRING;
188 OUString ScCellFormat::GetOutputString( ScDocument& rDoc, const ScAddress& rPos, const ScRefCellValue& rCell )
190 if (rCell.isEmpty())
191 return OUString();
193 if (rCell.getType() == CELLTYPE_EDIT)
195 // GetString converts line breaks into spaces in EditCell,
196 // but here we need the line breaks
197 const EditTextObject* pData = rCell.getEditText();
198 if (pData)
200 ScFieldEditEngine& rEngine = rDoc.GetEditEngine();
201 rEngine.SetTextCurrentDefaults(*pData);
202 return rEngine.GetText();
204 // also do not format EditCells as numbers
205 // (fitting to output)
206 return OUString();
208 else
210 // like in GetString for document (column)
211 const Color* pColor;
212 sal_uInt32 nNumFmt = rDoc.GetNumberFormat(rPos);
213 return GetString(rCell, nNumFmt, &pColor, *rDoc.GetFormatTable(), rDoc);
217 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */