Bump version to 21.06.18.1
[LibreOffice.git] / starmath / source / symbol.cxx
blob5e6a6486a3373d4033af87ea74a7c903c90c3523
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 <vector>
22 #include <symbol.hxx>
23 #include <utility.hxx>
24 #include "cfgitem.hxx"
25 #include <smmod.hxx>
26 #include <sal/log.hxx>
27 #include <osl/diagnose.h>
30 SmSym::SmSym() :
31 m_aName(OUString("unknown")),
32 m_aSetName(OUString("unknown")),
33 m_cChar('\0'),
34 m_bPredefined(false)
36 m_aExportName = m_aName;
37 m_aFace.SetTransparent(true);
38 m_aFace.SetAlignment(ALIGN_BASELINE);
42 SmSym::SmSym(const SmSym& rSymbol)
44 *this = rSymbol;
48 SmSym::SmSym(const OUString& rName, const vcl::Font& rFont, sal_UCS4 cChar,
49 const OUString& rSet, bool bIsPredefined)
51 m_aName = m_aExportName = rName;
53 m_aFace = rFont;
54 m_aFace.SetTransparent(true);
55 m_aFace.SetAlignment(ALIGN_BASELINE);
57 m_cChar = cChar;
58 m_aSetName = rSet;
59 m_bPredefined = bIsPredefined;
63 SmSym& SmSym::operator = (const SmSym& rSymbol)
65 m_aName = rSymbol.m_aName;
66 m_aExportName = rSymbol.m_aExportName;
67 m_cChar = rSymbol.m_cChar;
68 m_aFace = rSymbol.m_aFace;
69 m_aSetName = rSymbol.m_aSetName;
70 m_bPredefined = rSymbol.m_bPredefined;
72 SM_MOD()->GetSymbolManager().SetModified(true);
74 return *this;
78 bool SmSym::IsEqualInUI( const SmSym& rSymbol ) const
80 return m_aName == rSymbol.m_aName &&
81 m_aFace == rSymbol.m_aFace &&
82 m_cChar == rSymbol.m_cChar;
85 /**************************************************************************/
88 SmSymbolManager::SmSymbolManager()
90 m_bModified = false;
94 SmSymbolManager::SmSymbolManager(const SmSymbolManager& rSymbolSetManager)
96 m_aSymbols = rSymbolSetManager.m_aSymbols;
97 m_bModified = true;
101 SmSymbolManager::~SmSymbolManager()
106 SmSymbolManager& SmSymbolManager::operator = (const SmSymbolManager& rSymbolSetManager)
108 m_aSymbols = rSymbolSetManager.m_aSymbols;
109 m_bModified = true;
110 return *this;
114 SmSym *SmSymbolManager::GetSymbolByName(const OUString& rSymbolName)
116 SmSym *pRes = nullptr;
117 SymbolMap_t::iterator aIt( m_aSymbols.find( rSymbolName ) );
118 if (aIt != m_aSymbols.end())
119 pRes = &aIt->second;
120 return pRes;
124 SymbolPtrVec_t SmSymbolManager::GetSymbols() const
126 SymbolPtrVec_t aRes;
127 for (const auto& rEntry : m_aSymbols)
128 aRes.push_back( &rEntry.second );
129 // OSL_ENSURE( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " );
130 return aRes;
134 bool SmSymbolManager::AddOrReplaceSymbol( const SmSym &rSymbol, bool bForceChange )
136 bool bAdded = false;
138 const OUString& aSymbolName( rSymbol.GetName() );
139 if (!aSymbolName.isEmpty() && !rSymbol.GetSymbolSetName().isEmpty())
141 const SmSym *pFound = GetSymbolByName( aSymbolName );
142 const bool bSymbolConflict = pFound && !pFound->IsEqualInUI( rSymbol );
144 // avoid having the same symbol name twice but with different symbols in use
145 if (!pFound || bForceChange)
147 m_aSymbols[ aSymbolName ] = rSymbol;
148 bAdded = true;
150 else if (bSymbolConflict)
152 // TODO: to solve this a document owned symbol manager would be required ...
153 SAL_WARN("starmath", "symbol conflict, different symbol with same name found!");
154 // symbols in all formulas. A copy of the global one would be needed here
155 // and then the new symbol has to be forcefully applied. This would keep
156 // the current formula intact but will leave the set of symbols in the
157 // global symbol manager somewhat to chance.
160 OSL_ENSURE( bAdded, "failed to add symbol" );
161 if (bAdded)
162 m_bModified = true;
163 OSL_ENSURE( bAdded || (pFound && !bSymbolConflict), "AddOrReplaceSymbol: unresolved symbol conflict" );
166 return bAdded;
170 void SmSymbolManager::RemoveSymbol( const OUString & rSymbolName )
172 if (!rSymbolName.isEmpty())
174 size_t nOldSize = m_aSymbols.size();
175 m_aSymbols.erase( rSymbolName );
176 m_bModified = nOldSize != m_aSymbols.size();
181 std::set< OUString > SmSymbolManager::GetSymbolSetNames() const
183 std::set< OUString > aRes;
184 for (const auto& rEntry : m_aSymbols)
185 aRes.insert( rEntry.second.GetSymbolSetName() );
186 return aRes;
190 SymbolPtrVec_t SmSymbolManager::GetSymbolSet( const OUString& rSymbolSetName )
192 SymbolPtrVec_t aRes;
193 if (!rSymbolSetName.isEmpty())
195 for (const auto& rEntry : m_aSymbols)
197 if (rEntry.second.GetSymbolSetName() == rSymbolSetName)
198 aRes.push_back( &rEntry.second );
201 return aRes;
205 void SmSymbolManager::Load()
207 std::vector< SmSym > aSymbols;
208 SmMathConfig &rCfg = *SM_MOD()->GetConfig();
209 rCfg.GetSymbols( aSymbols );
210 size_t nSymbolCount = aSymbols.size();
212 m_aSymbols.clear();
213 for (size_t i = 0; i < nSymbolCount; ++i)
215 const SmSym &rSym = aSymbols[i];
216 OSL_ENSURE( !rSym.GetName().isEmpty(), "symbol without name!" );
217 if (!rSym.GetName().isEmpty())
218 AddOrReplaceSymbol( rSym );
220 m_bModified = true;
222 if (0 == nSymbolCount)
224 SAL_WARN("starmath", "no symbol set found");
225 m_bModified = false;
228 // now add a %i... symbol to the 'iGreek' set for every symbol found in the 'Greek' set.
229 const OUString aGreekSymbolSetName(SmLocalizedSymbolData::GetUiSymbolSetName("Greek"));
230 const SymbolPtrVec_t aGreekSymbols( GetSymbolSet( aGreekSymbolSetName ) );
231 OUString aSymbolSetName = "i" + aGreekSymbolSetName;
232 size_t nSymbols = aGreekSymbols.size();
233 for (size_t i = 0; i < nSymbols; ++i)
235 // make the new symbol a copy but with ITALIC_NORMAL, and add it to iGreek
236 const SmSym &rSym = *aGreekSymbols[i];
237 vcl::Font aFont( rSym.GetFace() );
238 OSL_ENSURE( aFont.GetItalic() == ITALIC_NONE, "expected Font with ITALIC_NONE, failed." );
239 aFont.SetItalic( ITALIC_NORMAL );
240 OUString aSymbolName = "i" + rSym.GetName();
241 SmSym aSymbol( aSymbolName, aFont, rSym.GetCharacter(),
242 aSymbolSetName, true /*bIsPredefined*/ );
244 AddOrReplaceSymbol( aSymbol );
248 void SmSymbolManager::Save()
250 if (!m_bModified)
251 return;
253 SmMathConfig &rCfg = *SM_MOD()->GetConfig();
255 // prepare to skip symbols from iGreek on saving
256 OUString aSymbolSetName = "i" +
257 SmLocalizedSymbolData::GetUiSymbolSetName("Greek");
259 SymbolPtrVec_t aTmp( GetSymbols() );
260 std::vector< SmSym > aSymbols;
261 for (const SmSym* i : aTmp)
263 // skip symbols from iGreek set since those symbols always get added
264 // by computational means in SmSymbolManager::Load
265 if (i->GetSymbolSetName() != aSymbolSetName)
266 aSymbols.push_back( *i );
268 rCfg.SetSymbols( aSymbols );
270 m_bModified = false;
274 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */