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"
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>
46 #include "utility.hxx"
49 #include "cfgitem.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 /**************************************************************************/
63 m_aName(C2S("unknown")),
64 m_aSetName(C2S("unknown")),
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
)
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
;
87 m_aFace
.SetTransparent(sal_True
);
88 m_aFace
.SetAlign(ALIGN_BASELINE
);
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;
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();
120 pSymSetManager
->SetModified(true);
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()
161 SmSymbolManager::SmSymbolManager(const SmSymbolManager
& rSymbolSetManager
) :
164 m_aSymbols
= rSymbolSetManager
.m_aSymbols
;
169 SmSymbolManager::~SmSymbolManager()
174 SmSymbolManager
& SmSymbolManager::operator = (const SmSymbolManager
& rSymbolSetManager
)
176 m_aSymbols
= rSymbolSetManager
.m_aSymbols
;
182 SmSym
*SmSymbolManager::GetSymbolByName(const String
& rSymbolName
)
185 SymbolMap_t::iterator
aIt( m_aSymbols
.find( rSymbolName
) );
186 if (aIt
!= m_aSymbols
.end())
192 const SymbolPtrVec_t
SmSymbolManager::GetSymbols() const
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 " );
203 bool SmSymbolManager::AddOrReplaceSymbol( const SmSym
&rSymbol
, bool bForceChange
)
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
;
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!" );
232 DBG_ASSERT( bAdded
|| (pFound
&& !bSymbolConflict
), "AddOrReplaceSymbol: unresolved symbol conflict" );
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() );
260 const SymbolPtrVec_t
SmSymbolManager::GetSymbolSet( const String
& rSymbolSetName
)
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
);
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();
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
);
293 if (0 == nSymbolCount
)
295 DBG_ERROR( "no symbol set found" );
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()
326 SmMathConfig
&rCfg
= *SM_MOD()->GetConfig();
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())
342 DBG_ASSERT(pSym
- pSymbols
== nSaveSymbolCnt
, "wrong number of symbols" );
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
);