1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <utility.hxx>
22 #include <cfgitem.hxx>
25 #include <sal/log.hxx>
26 #include <osl/diagnose.h>
30 m_aUiName(u
"unknown"_ustr
),
31 m_aSetName(u
"unknown"_ustr
),
35 m_aExportName
= m_aUiName
;
36 m_aFace
.SetTransparent(true);
37 m_aFace
.SetAlignment(ALIGN_BASELINE
);
41 SmSym::SmSym(const SmSym
& rSymbol
)
47 SmSym::SmSym(const OUString
& rName
, const vcl::Font
& rFont
, sal_UCS4 cChar
,
48 const OUString
& rSet
, bool bIsPredefined
)
50 m_aUiName
= m_aExportName
= rName
;
52 m_aFace
= SmFace(rFont
);
53 m_aFace
.SetTransparent(true);
54 m_aFace
.SetAlignment(ALIGN_BASELINE
);
58 m_bPredefined
= bIsPredefined
;
62 SmSym
& SmSym::operator = (const SmSym
& rSymbol
)
64 m_aUiName
= rSymbol
.m_aUiName
;
65 m_aExportName
= rSymbol
.m_aExportName
;
66 m_cChar
= rSymbol
.m_cChar
;
67 m_aFace
= rSymbol
.m_aFace
;
68 m_aSetName
= rSymbol
.m_aSetName
;
69 m_bPredefined
= rSymbol
.m_bPredefined
;
71 SmModule::get()->GetSymbolManager().SetModified(true);
77 bool SmSym::IsEqualInUI( const SmSym
& rSymbol
) const
79 return m_aUiName
== rSymbol
.m_aUiName
&&
80 m_aFace
== rSymbol
.m_aFace
&&
81 m_cChar
== rSymbol
.m_cChar
;
84 const vcl::Font
& SmSym::GetFace(const SmFormat
* pFormat
) const
86 if (m_aFace
.GetFamilyName().isEmpty())
89 pFormat
= &SmModule::get()->GetConfig()->GetStandardFormat();
90 return pFormat
->GetFont(FNT_VARIABLE
);
95 /**************************************************************************/
98 SmSymbolManager::SmSymbolManager()
104 SmSymbolManager::SmSymbolManager(const SmSymbolManager
& rSymbolSetManager
)
106 m_aSymbols
= rSymbolSetManager
.m_aSymbols
;
111 SmSymbolManager::~SmSymbolManager()
116 SmSymbolManager
& SmSymbolManager::operator = (const SmSymbolManager
& rSymbolSetManager
)
118 m_aSymbols
= rSymbolSetManager
.m_aSymbols
;
123 SmSym
* SmSymbolManager::GetSymbolByName(std::u16string_view rSymbolName
)
125 SmSym
* pRes
= GetSymbolByUiName(rSymbolName
);
127 pRes
= GetSymbolByExportName(rSymbolName
);
131 SmSym
*SmSymbolManager::GetSymbolByUiName(std::u16string_view rSymbolName
)
133 OUString
aSymbolName(rSymbolName
);
134 SmSym
*pRes
= nullptr;
135 SymbolMap_t::iterator
aIt( m_aSymbols
.find( aSymbolName
) );
136 if (aIt
!= m_aSymbols
.end())
141 SmSym
* SmSymbolManager::GetSymbolByExportName(std::u16string_view rSymbolName
)
143 SmSym
* pRes
= nullptr;
144 for (auto& rPair
: m_aSymbols
)
146 SmSym
& rSymbol
= rPair
.second
;
147 if (rSymbol
.GetExportName() == rSymbolName
)
157 SymbolPtrVec_t
SmSymbolManager::GetSymbols() const
160 aRes
.reserve(m_aSymbols
.size());
161 for (const auto& rEntry
: m_aSymbols
)
162 aRes
.push_back( &rEntry
.second
);
163 // OSL_ENSURE( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " );
168 bool SmSymbolManager::AddOrReplaceSymbol( const SmSym
&rSymbol
, bool bForceChange
)
172 const OUString
& aSymbolName( rSymbol
.GetUiName() );
173 if (!aSymbolName
.isEmpty() && !rSymbol
.GetSymbolSetName().isEmpty())
175 const SmSym
*pFound
= GetSymbolByUiName( aSymbolName
);
176 const bool bSymbolConflict
= pFound
&& !pFound
->IsEqualInUI( rSymbol
);
178 // avoid having the same symbol name twice but with different symbols in use
179 if (!pFound
|| bForceChange
)
181 m_aSymbols
[ aSymbolName
] = rSymbol
;
184 else if (bSymbolConflict
)
186 // TODO: to solve this a document owned symbol manager would be required ...
187 SAL_WARN("starmath", "symbol conflict, different symbol with same name found!");
188 // symbols in all formulas. A copy of the global one would be needed here
189 // and then the new symbol has to be forcefully applied. This would keep
190 // the current formula intact but will leave the set of symbols in the
191 // global symbol manager somewhat to chance.
194 OSL_ENSURE( bAdded
, "failed to add symbol" );
197 OSL_ENSURE( bAdded
|| (pFound
&& !bSymbolConflict
), "AddOrReplaceSymbol: unresolved symbol conflict" );
204 void SmSymbolManager::RemoveSymbol( const OUString
& rSymbolName
)
206 if (!rSymbolName
.isEmpty())
208 size_t nOldSize
= m_aSymbols
.size();
209 m_aSymbols
.erase( rSymbolName
);
210 m_bModified
= nOldSize
!= m_aSymbols
.size();
215 std::set
< OUString
> SmSymbolManager::GetSymbolSetNames() const
217 std::set
< OUString
> aRes
;
218 for (const auto& rEntry
: m_aSymbols
)
219 aRes
.insert( rEntry
.second
.GetSymbolSetName() );
224 SymbolPtrVec_t
SmSymbolManager::GetSymbolSet( std::u16string_view rSymbolSetName
)
227 if (!rSymbolSetName
.empty())
229 for (const auto& rEntry
: m_aSymbols
)
231 if (rEntry
.second
.GetSymbolSetName() == rSymbolSetName
)
232 aRes
.push_back( &rEntry
.second
);
239 void SmSymbolManager::Load()
241 std::vector
< SmSym
> aSymbols
;
242 SmModule::get()->GetConfig()->GetSymbols(aSymbols
);
243 size_t nSymbolCount
= aSymbols
.size();
246 for (size_t i
= 0; i
< nSymbolCount
; ++i
)
248 const SmSym
&rSym
= aSymbols
[i
];
249 OSL_ENSURE( !rSym
.GetUiName().isEmpty(), "symbol without name!" );
250 if (!rSym
.GetUiName().isEmpty())
251 AddOrReplaceSymbol( rSym
);
255 if (0 == nSymbolCount
)
257 SAL_WARN("starmath", "no symbol set found");
261 // now add a %i... symbol to the 'iGreek' set for every symbol found in the 'Greek' set.
262 const OUString
aGreekSymbolSetName(SmLocalizedSymbolData::GetUiSymbolSetName(u
"Greek"));
263 const SymbolPtrVec_t
aGreekSymbols( GetSymbolSet( aGreekSymbolSetName
) );
264 OUString aSymbolSetName
= "i" + aGreekSymbolSetName
;
265 size_t nSymbols
= aGreekSymbols
.size();
266 for (size_t i
= 0; i
< nSymbols
; ++i
)
268 // make the new symbol a copy but with ITALIC_NORMAL, and add it to iGreek
269 const SmSym
&rSym
= *aGreekSymbols
[i
];
270 vcl::Font
aFont( rSym
.GetFace() );
271 OSL_ENSURE( aFont
.GetItalic() == ITALIC_NONE
, "expected Font with ITALIC_NONE, failed." );
272 aFont
.SetItalic( ITALIC_NORMAL
);
273 OUString aSymbolName
= "i" + rSym
.GetUiName();
274 SmSym
aSymbol( aSymbolName
, aFont
, rSym
.GetCharacter(),
275 aSymbolSetName
, true /*bIsPredefined*/ );
276 aSymbol
.SetExportName("i" + rSym
.GetExportName());
278 AddOrReplaceSymbol( aSymbol
);
282 void SmSymbolManager::Save()
287 // prepare to skip symbols from iGreek on saving
288 OUString aSymbolSetName
= "i" +
289 SmLocalizedSymbolData::GetUiSymbolSetName(u
"Greek");
291 SymbolPtrVec_t
aTmp( GetSymbols() );
292 std::vector
< SmSym
> aSymbols
;
293 for (const SmSym
* i
: aTmp
)
295 // skip symbols from iGreek set since those symbols always get added
296 // by computational means in SmSymbolManager::Load
297 if (i
->GetSymbolSetName() != aSymbolSetName
)
298 aSymbols
.push_back( *i
);
300 SmModule::get()->GetConfig()->SetSymbols(aSymbols
);
306 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */