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 .
20 #include <osl/mutex.hxx>
21 #include <ucbhelper/content.hxx>
22 #include <vcl/msgbox.hxx>
24 #include <sfx2/dispatch.hxx>
25 #include <sfx2/docfile.hxx>
33 #include "utility.hxx"
36 #include "cfgitem.hxx"
38 #include "starmath.hrc"
41 using namespace ::com::sun::star
;
42 using namespace ::com::sun::star::ucb
;
43 using namespace ::com::sun::star::uno
;
44 using namespace ::rtl
;
47 /**************************************************************************/
50 m_aName(OUString("unknown")),
51 m_aSetName(OUString("unknown")),
56 m_aExportName
= m_aName
;
57 m_aFace
.SetTransparent(true);
58 m_aFace
.SetAlign(ALIGN_BASELINE
);
62 SmSym::SmSym(const SmSym
& rSymbol
)
68 SmSym::SmSym(const OUString
& rName
, const Font
& rFont
, sal_UCS4 cChar
,
69 const OUString
& rSet
, bool bIsPredefined
)
71 m_aName
= m_aExportName
= rName
;
74 m_aFace
.SetTransparent(true);
75 m_aFace
.SetAlign(ALIGN_BASELINE
);
79 m_bPredefined
= bIsPredefined
;
84 SmSym
& SmSym::operator = (const SmSym
& rSymbol
)
86 m_aName
= rSymbol
.m_aName
;
87 m_aExportName
= rSymbol
.m_aExportName
;
88 m_cChar
= rSymbol
.m_cChar
;
89 m_aFace
= rSymbol
.m_aFace
;
90 m_aSetName
= rSymbol
.m_aSetName
;
91 m_bPredefined
= rSymbol
.m_bPredefined
;
92 m_bDocSymbol
= rSymbol
.m_bDocSymbol
;
94 SmSymbolManager
* pSymSetManager
= &SM_MOD()->GetSymbolManager();
96 pSymSetManager
->SetModified(true);
102 bool SmSym::IsEqualInUI( const SmSym
& rSymbol
) const
104 return m_aName
== rSymbol
.m_aName
&&
105 m_aFace
== rSymbol
.m_aFace
&&
106 m_cChar
== rSymbol
.m_cChar
;
109 /**************************************************************************/
111 void SmSymbolManager::SFX_NOTIFY(SfxBroadcaster
& /*rBC*/, const TypeId
& rBCType
,
112 const SfxHint
& /*rHint*/, const TypeId
& rHintType
)
117 SmSymbolManager::SmSymbolManager()
123 SmSymbolManager::SmSymbolManager(const SmSymbolManager
& rSymbolSetManager
) :
126 m_aSymbols
= rSymbolSetManager
.m_aSymbols
;
131 SmSymbolManager::~SmSymbolManager()
136 SmSymbolManager
& SmSymbolManager::operator = (const SmSymbolManager
& rSymbolSetManager
)
138 m_aSymbols
= rSymbolSetManager
.m_aSymbols
;
144 SmSym
*SmSymbolManager::GetSymbolByName(const OUString
& rSymbolName
)
147 SymbolMap_t::iterator
aIt( m_aSymbols
.find( rSymbolName
) );
148 if (aIt
!= m_aSymbols
.end())
154 const SymbolPtrVec_t
SmSymbolManager::GetSymbols() const
157 SymbolMap_t::const_iterator
aIt( m_aSymbols
.begin() );
158 for ( ; aIt
!= m_aSymbols
.end(); ++aIt
)
159 aRes
.push_back( &aIt
->second
);
160 // OSL_ENSURE( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " );
165 bool SmSymbolManager::AddOrReplaceSymbol( const SmSym
&rSymbol
, bool bForceChange
)
169 const OUString
aSymbolName( rSymbol
.GetName() );
170 if (aSymbolName
.getLength() > 0 && rSymbol
.GetSymbolSetName().getLength() > 0)
172 const SmSym
*pFound
= GetSymbolByName( aSymbolName
);
173 const bool bSymbolConflict
= pFound
&& !pFound
->IsEqualInUI( rSymbol
);
175 // avoid having the same symbol name twice but with different symbols in use
176 if (!pFound
|| bForceChange
)
178 m_aSymbols
[ aSymbolName
] = rSymbol
;
181 else if (pFound
&& !bForceChange
&& bSymbolConflict
)
183 // TODO: to solve this a document owned symbol manager would be required ...
184 OSL_FAIL( "symbol conflict, different symbol with same name found!" );
185 // symbols in all formulas. A copy of the global one would be needed here
186 // and then the new symbol has to be forcefully applied. This would keep
187 // the current formula intact but will leave the set of symbols in the
188 // global symbol manager somewhat to chance.
191 OSL_ENSURE( bAdded
, "failed to add symbol" );
194 OSL_ENSURE( bAdded
|| (pFound
&& !bSymbolConflict
), "AddOrReplaceSymbol: unresolved symbol conflict" );
201 void SmSymbolManager::RemoveSymbol( const OUString
& rSymbolName
)
203 if (rSymbolName
.getLength() > 0)
205 size_t nOldSize
= m_aSymbols
.size();
206 m_aSymbols
.erase( rSymbolName
);
207 m_bModified
= nOldSize
!= m_aSymbols
.size();
212 std::set
< OUString
> SmSymbolManager::GetSymbolSetNames() const
214 std::set
< OUString
> aRes
;
215 SymbolMap_t::const_iterator
aIt( m_aSymbols
.begin() );
216 for ( ; aIt
!= m_aSymbols
.end(); ++aIt
)
217 aRes
.insert( aIt
->second
.GetSymbolSetName() );
222 const SymbolPtrVec_t
SmSymbolManager::GetSymbolSet( const OUString
& rSymbolSetName
)
225 if (rSymbolSetName
.getLength() > 0)
227 SymbolMap_t::const_iterator
aIt( m_aSymbols
.begin() );
228 for ( ; aIt
!= m_aSymbols
.end(); ++aIt
)
230 if (aIt
->second
.GetSymbolSetName() == rSymbolSetName
)
231 aRes
.push_back( &aIt
->second
);
238 void SmSymbolManager::Load()
240 std::vector
< SmSym
> aSymbols
;
241 SmMathConfig
&rCfg
= *SM_MOD()->GetConfig();
242 rCfg
.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
.GetName().getLength() > 0, "symbol without name!" );
250 if (rSym
.GetName().getLength() > 0)
251 AddOrReplaceSymbol( rSym
);
255 if (0 == nSymbolCount
)
257 OSL_FAIL( "no symbol set found" );
261 // now add a %i... symbol to the 'iGreek' set for every symbol found in the 'Greek' set.
262 SmLocalizedSymbolData aLocalizedData
;
263 const OUString
aGreekSymbolSetName(aLocalizedData
.GetUiSymbolSetName(OUString("Greek")));
264 const SymbolPtrVec_t
aGreekSymbols( GetSymbolSet( aGreekSymbolSetName
) );
265 OUString
aSymbolSetName('i');
266 aSymbolSetName
+= aGreekSymbolSetName
;
267 size_t nSymbols
= aGreekSymbols
.size();
268 for (size_t i
= 0; i
< nSymbols
; ++i
)
270 // make the new symbol a copy but with ITALIC_NORMAL, and add it to iGreek
271 const SmSym
&rSym
= *aGreekSymbols
[i
];
272 Font
aFont( rSym
.GetFace() );
273 OSL_ENSURE( aFont
.GetItalic() == ITALIC_NONE
, "expected Font with ITALIC_NONE, failed." );
274 aFont
.SetItalic( ITALIC_NORMAL
);
275 OUString
aSymbolName('i');
276 aSymbolName
+= rSym
.GetName();
277 SmSym
aSymbol( aSymbolName
, aFont
, rSym
.GetCharacter(),
278 aSymbolSetName
, true /*bIsPredefined*/ );
280 AddOrReplaceSymbol( aSymbol
);
284 void SmSymbolManager::Save()
288 SmMathConfig
&rCfg
= *SM_MOD()->GetConfig();
290 // prepare to skip symbols from iGreek on saving
291 SmLocalizedSymbolData aLocalizedData
;
292 OUString
aSymbolSetName('i');
293 aSymbolSetName
+= aLocalizedData
.GetUiSymbolSetName(OUString("Greek"));
295 SymbolPtrVec_t
aTmp( GetSymbols() );
296 std::vector
< SmSym
> aSymbols
;
297 for (size_t i
= 0; i
< aTmp
.size(); ++i
)
299 // skip symbols from iGreek set since those symbols always get added
300 // by computational means in SmSymbolManager::Load
301 if (aTmp
[i
]->GetSymbolSetName() != aSymbolSetName
)
302 aSymbols
.push_back( *aTmp
[i
] );
304 rCfg
.SetSymbols( aSymbols
);
311 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */