merged tag ooo/DEV300_m102
[LibreOffice.git] / starmath / source / symbol.cxx
blob7347dbcd705fe3c4f05a247c1cfcfe3c36e675bd
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_starmath.hxx"
32 #include <vector>
33 #include <osl/mutex.hxx>
34 #include <ucbhelper/content.hxx>
35 #include <vcl/msgbox.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/docfile.hxx>
40 #include <map>
41 #include <vector>
42 #include <iterator>
44 #include "symbol.hxx"
45 #include "view.hxx"
46 #include "utility.hxx"
47 #include "dialog.hxx"
48 #include "config.hxx"
49 #include "cfgitem.hxx"
50 #include "smmod.hxx"
51 #include "starmath.hrc"
54 using namespace ::com::sun::star;
55 using namespace ::com::sun::star::ucb;
56 using namespace ::com::sun::star::uno;
57 using namespace ::rtl;
60 /**************************************************************************/
62 SmSym::SmSym() :
63 m_aName(C2S("unknown")),
64 m_aSetName(C2S("unknown")),
65 m_cChar('\0'),
66 m_bPredefined(sal_False),
67 m_bDocSymbol(sal_False)
69 m_aExportName = m_aName;
70 m_aFace.SetTransparent(sal_True);
71 m_aFace.SetAlign(ALIGN_BASELINE);
75 SmSym::SmSym(const SmSym& rSymbol)
77 *this = rSymbol;
81 SmSym::SmSym(const String& rName, const Font& rFont, sal_UCS4 cChar,
82 const String& rSet, sal_Bool bIsPredefined)
84 m_aName = m_aExportName = rName;
86 m_aFace = rFont;
87 m_aFace.SetTransparent(sal_True);
88 m_aFace.SetAlign(ALIGN_BASELINE);
90 m_cChar = cChar;
91 //! according to HDU this should not be used anymore now
92 //! since this was necessary in the early days but should
93 //! not be done now since this is handled now at a more
94 //! bottom layer by HDU.
95 //! He can still imagine scenarios where this will be wrong
96 //! now though, for example when importing *some* old documents.
97 //! But overall it should be a large improvement, and
98 //! likely everything will still work... #_- (eyes shut and "go"!)
100 // if (RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet())
101 // Character |= 0xF000;
102 m_aSetName = rSet;
103 m_bPredefined = bIsPredefined;
104 m_bDocSymbol = sal_False;
108 SmSym& SmSym::operator = (const SmSym& rSymbol)
110 m_aName = rSymbol.m_aName;
111 m_aExportName = rSymbol.m_aExportName;
112 m_cChar = rSymbol.m_cChar;
113 m_aFace = rSymbol.m_aFace;
114 m_aSetName = rSymbol.m_aSetName;
115 m_bPredefined = rSymbol.m_bPredefined;
116 m_bDocSymbol = rSymbol.m_bDocSymbol;
118 SmSymbolManager * pSymSetManager = &SM_MOD()->GetSymbolManager();
119 if (pSymSetManager)
120 pSymSetManager->SetModified(true);
122 return *this;
126 bool SmSym::IsEqualInUI( const SmSym& rSymbol ) const
128 return m_aName == rSymbol.m_aName &&
129 m_aFace == rSymbol.m_aFace &&
130 m_cChar == rSymbol.m_cChar;
133 /**************************************************************************/
135 void SmSymbolManager::SFX_NOTIFY(SfxBroadcaster& /*rBC*/, const TypeId& rBCType,
136 const SfxHint& /*rHint*/, const TypeId& rHintType)
141 void SmSymbolManager::Init()
143 SmModule *pp = SM_MOD();
144 StartListening(*pp->GetConfig());
148 void SmSymbolManager::Exit()
150 SmModule *pp = SM_MOD();
151 EndListening(*pp->GetConfig());
155 SmSymbolManager::SmSymbolManager()
157 m_bModified = false;
161 SmSymbolManager::SmSymbolManager(const SmSymbolManager& rSymbolSetManager) :
162 SfxListener()
164 m_aSymbols = rSymbolSetManager.m_aSymbols;
165 m_bModified = true;
169 SmSymbolManager::~SmSymbolManager()
174 SmSymbolManager& SmSymbolManager::operator = (const SmSymbolManager& rSymbolSetManager)
176 m_aSymbols = rSymbolSetManager.m_aSymbols;
177 m_bModified = true;
178 return *this;
182 SmSym *SmSymbolManager::GetSymbolByName(const String& rSymbolName)
184 SmSym *pRes = NULL;
185 SymbolMap_t::iterator aIt( m_aSymbols.find( rSymbolName ) );
186 if (aIt != m_aSymbols.end())
187 pRes = &aIt->second;
188 return pRes;
192 const SymbolPtrVec_t SmSymbolManager::GetSymbols() const
194 SymbolPtrVec_t aRes;
195 SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
196 for ( ; aIt != m_aSymbols.end(); ++aIt)
197 aRes.push_back( &aIt->second );
198 // DBG_ASSERT( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " );
199 return aRes;
203 bool SmSymbolManager::AddOrReplaceSymbol( const SmSym &rSymbol, bool bForceChange )
205 bool bAdded = false;
207 const String aSymbolName( rSymbol.GetName() );
208 if (aSymbolName.Len() > 0 && rSymbol.GetSymbolSetName().Len() > 0)
210 const SmSym *pFound = GetSymbolByName( aSymbolName );
211 const bool bSymbolConflict = pFound && !pFound->IsEqualInUI( rSymbol );
213 // avoid having the same symbol name twice but with different symbols in use
214 if (!pFound || bForceChange)
216 m_aSymbols[ aSymbolName ] = rSymbol;
217 bAdded = true;
219 else if (pFound && !bForceChange && bSymbolConflict)
221 // TODO: to solve this a document owned symbol manager would be required ...
222 // But for now we have a global one to easily support availability of all
223 // symbols in all formulas. A copy of the global one would be needed here
224 // and then the new symbol has to be forcefully applied. This would keep
225 // the current formula intact but will leave the set of symbols in the
226 // global symbol manager somewhat to chance.
227 DBG_ASSERT( 0, "symbol conflict, different symbol with same name found!" );
230 if (bAdded)
231 m_bModified = true;
232 DBG_ASSERT( bAdded || (pFound && !bSymbolConflict), "AddOrReplaceSymbol: unresolved symbol conflict" );
235 return bAdded;
239 void SmSymbolManager::RemoveSymbol( const String & rSymbolName )
241 if (rSymbolName.Len() > 0)
243 size_t nOldSize = m_aSymbols.size();
244 m_aSymbols.erase( rSymbolName );
245 m_bModified = nOldSize != m_aSymbols.size();
250 std::set< String > SmSymbolManager::GetSymbolSetNames() const
252 std::set< String > aRes;
253 SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
254 for ( ; aIt != m_aSymbols.end(); ++aIt )
255 aRes.insert( aIt->second.GetSymbolSetName() );
256 return aRes;
260 const SymbolPtrVec_t SmSymbolManager::GetSymbolSet( const String& rSymbolSetName )
262 SymbolPtrVec_t aRes;
263 if (rSymbolSetName.Len() > 0)
265 SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
266 for ( ; aIt != m_aSymbols.end(); ++aIt )
268 if (aIt->second.GetSymbolSetName() == rSymbolSetName)
269 aRes.push_back( &aIt->second );
272 return aRes;
276 void SmSymbolManager::Load()
278 std::vector< SmSym > aSymbols;
279 SmMathConfig &rCfg = *SM_MOD()->GetConfig();
280 rCfg.GetSymbols( aSymbols );
281 size_t nSymbolCount = aSymbols.size();
283 m_aSymbols.clear();
284 for (size_t i = 0; i < nSymbolCount; ++i)
286 const SmSym &rSym = aSymbols[i];
287 DBG_ASSERT( rSym.GetName().Len() > 0, "symbol without name!" );
288 if (rSym.GetName().Len() > 0)
289 AddOrReplaceSymbol( rSym );
291 m_bModified = true;
293 if (0 == nSymbolCount)
295 DBG_ERROR( "no symbol set found" );
296 m_bModified = false;
299 // now add a %i... symbol to the 'iGreek' set for every symbol found in the 'Greek' set.
300 SmLocalizedSymbolData aLocalizedData;
301 const String aGreekSymbolSetName( aLocalizedData.GetUiSymbolSetName( A2OU("Greek") ) );
302 const SymbolPtrVec_t aGreekSymbols( GetSymbolSet( aGreekSymbolSetName ) );
303 String aSymbolSetName( (sal_Unicode) 'i' );
304 aSymbolSetName += aGreekSymbolSetName;
305 size_t nSymbols = aGreekSymbols.size();
306 for (size_t i = 0; i < nSymbols; ++i)
308 // make the new symbol a copy but with ITALIC_NORMAL, and add it to iGreek
309 const SmSym &rSym = *aGreekSymbols[i];
310 Font aFont( rSym.GetFace() );
311 DBG_ASSERT( aFont.GetItalic() == ITALIC_NONE, "expected Font with ITALIC_NONE, failed." );
312 aFont.SetItalic( ITALIC_NORMAL );
313 String aSymbolName( (sal_Unicode)'i' );
314 aSymbolName += rSym.GetName();
315 SmSym aSymbol( aSymbolName, aFont, rSym.GetCharacter(),
316 aSymbolSetName, sal_True /*bIsPredefined*/ );
318 AddOrReplaceSymbol( aSymbol );
322 void SmSymbolManager::Save()
324 if (m_bModified)
326 SmMathConfig &rCfg = *SM_MOD()->GetConfig();
328 #if 0
329 sal_uInt16 nSymbolCount = GetSymbolCount();
330 sal_uInt16 nSaveSymbolCnt = 0;
331 const SmSym **pSymbols = new const SmSym* [ nSymbolCount ];
332 const SmSym **pSym = pSymbols;
333 for (sal_uInt16 j = 0; j < nSymbolCount; ++j)
335 const SmSym &rSym = *pSymSet->GetSymbol( j );
336 if (!rSym.IsDocSymbol())
338 *pSym++ = &rSym;
339 ++nSaveSymbolCnt;
342 DBG_ASSERT(pSym - pSymbols == nSaveSymbolCnt, "wrong number of symbols" );
343 #endif
345 // prepare to skip symbols from iGreek on saving
346 SmLocalizedSymbolData aLocalizedData;
347 String aSymbolSetName( (sal_Unicode) 'i' );
348 aSymbolSetName += aLocalizedData.GetUiSymbolSetName( A2OU("Greek") );
350 SymbolPtrVec_t aTmp( GetSymbols() );
351 std::vector< SmSym > aSymbols;
352 for (size_t i = 0; i < aTmp.size(); ++i)
354 // skip symbols from iGreek set since those symbols always get added
355 // by computational means in SmSymbolManager::Load
356 if (aTmp[i]->GetSymbolSetName() != aSymbolSetName)
357 aSymbols.push_back( *aTmp[i] );
359 rCfg.SetSymbols( aSymbols );
360 #if 0
361 delete [] pSymbols;
362 #endif
364 m_bModified = false;