1*d107581fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*d107581fSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*d107581fSAndrew Rist * or more contributor license agreements. See the NOTICE file
5*d107581fSAndrew Rist * distributed with this work for additional information
6*d107581fSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*d107581fSAndrew Rist * to you under the Apache License, Version 2.0 (the
8*d107581fSAndrew Rist * "License"); you may not use this file except in compliance
9*d107581fSAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11*d107581fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13*d107581fSAndrew Rist * Unless required by applicable law or agreed to in writing,
14*d107581fSAndrew Rist * software distributed under the License is distributed on an
15*d107581fSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*d107581fSAndrew Rist * KIND, either express or implied. See the License for the
17*d107581fSAndrew Rist * specific language governing permissions and limitations
18*d107581fSAndrew Rist * under the License.
19cdf0e10cSrcweir *
20*d107581fSAndrew Rist *************************************************************/
21*d107581fSAndrew Rist
22*d107581fSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_starmath.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir
28cdf0e10cSrcweir #include <vector>
29cdf0e10cSrcweir #include <osl/mutex.hxx>
30cdf0e10cSrcweir #include <ucbhelper/content.hxx>
31cdf0e10cSrcweir #include <vcl/msgbox.hxx>
32cdf0e10cSrcweir
33cdf0e10cSrcweir #include <sfx2/dispatch.hxx>
34cdf0e10cSrcweir #include <sfx2/docfile.hxx>
35cdf0e10cSrcweir
36cdf0e10cSrcweir #include <map>
37cdf0e10cSrcweir #include <vector>
38cdf0e10cSrcweir #include <iterator>
39cdf0e10cSrcweir
40cdf0e10cSrcweir #include "symbol.hxx"
41cdf0e10cSrcweir #include "view.hxx"
42cdf0e10cSrcweir #include "utility.hxx"
43cdf0e10cSrcweir #include "dialog.hxx"
44cdf0e10cSrcweir #include "config.hxx"
45cdf0e10cSrcweir #include "cfgitem.hxx"
46cdf0e10cSrcweir #include "smmod.hxx"
47cdf0e10cSrcweir #include "starmath.hrc"
48cdf0e10cSrcweir
49cdf0e10cSrcweir
50cdf0e10cSrcweir using namespace ::com::sun::star;
51cdf0e10cSrcweir using namespace ::com::sun::star::ucb;
52cdf0e10cSrcweir using namespace ::com::sun::star::uno;
53cdf0e10cSrcweir using namespace ::rtl;
54cdf0e10cSrcweir
55cdf0e10cSrcweir
56cdf0e10cSrcweir /**************************************************************************/
57cdf0e10cSrcweir
SmSym()58cdf0e10cSrcweir SmSym::SmSym() :
59cdf0e10cSrcweir m_aName(C2S("unknown")),
60cdf0e10cSrcweir m_aSetName(C2S("unknown")),
61cdf0e10cSrcweir m_cChar('\0'),
62cdf0e10cSrcweir m_bPredefined(sal_False),
63cdf0e10cSrcweir m_bDocSymbol(sal_False)
64cdf0e10cSrcweir {
65cdf0e10cSrcweir m_aExportName = m_aName;
66cdf0e10cSrcweir m_aFace.SetTransparent(sal_True);
67cdf0e10cSrcweir m_aFace.SetAlign(ALIGN_BASELINE);
68cdf0e10cSrcweir }
69cdf0e10cSrcweir
70cdf0e10cSrcweir
SmSym(const SmSym & rSymbol)71cdf0e10cSrcweir SmSym::SmSym(const SmSym& rSymbol)
72cdf0e10cSrcweir {
73cdf0e10cSrcweir *this = rSymbol;
74cdf0e10cSrcweir }
75cdf0e10cSrcweir
76cdf0e10cSrcweir
SmSym(const String & rName,const Font & rFont,sal_UCS4 cChar,const String & rSet,sal_Bool bIsPredefined)77cdf0e10cSrcweir SmSym::SmSym(const String& rName, const Font& rFont, sal_UCS4 cChar,
78cdf0e10cSrcweir const String& rSet, sal_Bool bIsPredefined)
79cdf0e10cSrcweir {
80cdf0e10cSrcweir m_aName = m_aExportName = rName;
81cdf0e10cSrcweir
82cdf0e10cSrcweir m_aFace = rFont;
83cdf0e10cSrcweir m_aFace.SetTransparent(sal_True);
84cdf0e10cSrcweir m_aFace.SetAlign(ALIGN_BASELINE);
85cdf0e10cSrcweir
86cdf0e10cSrcweir m_cChar = cChar;
87cdf0e10cSrcweir //! according to HDU this should not be used anymore now
88cdf0e10cSrcweir //! since this was necessary in the early days but should
89cdf0e10cSrcweir //! not be done now since this is handled now at a more
90cdf0e10cSrcweir //! bottom layer by HDU.
91cdf0e10cSrcweir //! He can still imagine scenarios where this will be wrong
92cdf0e10cSrcweir //! now though, for example when importing *some* old documents.
93cdf0e10cSrcweir //! But overall it should be a large improvement, and
94cdf0e10cSrcweir //! likely everything will still work... #_- (eyes shut and "go"!)
95cdf0e10cSrcweir //
96cdf0e10cSrcweir // if (RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet())
97cdf0e10cSrcweir // Character |= 0xF000;
98cdf0e10cSrcweir m_aSetName = rSet;
99cdf0e10cSrcweir m_bPredefined = bIsPredefined;
100cdf0e10cSrcweir m_bDocSymbol = sal_False;
101cdf0e10cSrcweir }
102cdf0e10cSrcweir
103cdf0e10cSrcweir
operator =(const SmSym & rSymbol)104cdf0e10cSrcweir SmSym& SmSym::operator = (const SmSym& rSymbol)
105cdf0e10cSrcweir {
106cdf0e10cSrcweir m_aName = rSymbol.m_aName;
107cdf0e10cSrcweir m_aExportName = rSymbol.m_aExportName;
108cdf0e10cSrcweir m_cChar = rSymbol.m_cChar;
109cdf0e10cSrcweir m_aFace = rSymbol.m_aFace;
110cdf0e10cSrcweir m_aSetName = rSymbol.m_aSetName;
111cdf0e10cSrcweir m_bPredefined = rSymbol.m_bPredefined;
112cdf0e10cSrcweir m_bDocSymbol = rSymbol.m_bDocSymbol;
113cdf0e10cSrcweir
114cdf0e10cSrcweir SmSymbolManager * pSymSetManager = &SM_MOD()->GetSymbolManager();
115cdf0e10cSrcweir if (pSymSetManager)
116cdf0e10cSrcweir pSymSetManager->SetModified(true);
117cdf0e10cSrcweir
118cdf0e10cSrcweir return *this;
119cdf0e10cSrcweir }
120cdf0e10cSrcweir
121cdf0e10cSrcweir
IsEqualInUI(const SmSym & rSymbol) const122cdf0e10cSrcweir bool SmSym::IsEqualInUI( const SmSym& rSymbol ) const
123cdf0e10cSrcweir {
124cdf0e10cSrcweir return m_aName == rSymbol.m_aName &&
125cdf0e10cSrcweir m_aFace == rSymbol.m_aFace &&
126cdf0e10cSrcweir m_cChar == rSymbol.m_cChar;
127cdf0e10cSrcweir }
128cdf0e10cSrcweir
129cdf0e10cSrcweir /**************************************************************************/
130cdf0e10cSrcweir
SFX_NOTIFY(SfxBroadcaster &,const TypeId & rBCType,const SfxHint &,const TypeId & rHintType)131cdf0e10cSrcweir void SmSymbolManager::SFX_NOTIFY(SfxBroadcaster& /*rBC*/, const TypeId& rBCType,
132cdf0e10cSrcweir const SfxHint& /*rHint*/, const TypeId& rHintType)
133cdf0e10cSrcweir {
134cdf0e10cSrcweir }
135cdf0e10cSrcweir
136cdf0e10cSrcweir
Init()137cdf0e10cSrcweir void SmSymbolManager::Init()
138cdf0e10cSrcweir {
139cdf0e10cSrcweir SmModule *pp = SM_MOD();
140cdf0e10cSrcweir StartListening(*pp->GetConfig());
141cdf0e10cSrcweir }
142cdf0e10cSrcweir
143cdf0e10cSrcweir
Exit()144cdf0e10cSrcweir void SmSymbolManager::Exit()
145cdf0e10cSrcweir {
146cdf0e10cSrcweir SmModule *pp = SM_MOD();
147cdf0e10cSrcweir EndListening(*pp->GetConfig());
148cdf0e10cSrcweir }
149cdf0e10cSrcweir
150cdf0e10cSrcweir
SmSymbolManager()151cdf0e10cSrcweir SmSymbolManager::SmSymbolManager()
152cdf0e10cSrcweir {
153cdf0e10cSrcweir m_bModified = false;
154cdf0e10cSrcweir }
155cdf0e10cSrcweir
156cdf0e10cSrcweir
SmSymbolManager(const SmSymbolManager & rSymbolSetManager)157cdf0e10cSrcweir SmSymbolManager::SmSymbolManager(const SmSymbolManager& rSymbolSetManager) :
158cdf0e10cSrcweir SfxListener()
159cdf0e10cSrcweir {
160cdf0e10cSrcweir m_aSymbols = rSymbolSetManager.m_aSymbols;
161cdf0e10cSrcweir m_bModified = true;
162cdf0e10cSrcweir }
163cdf0e10cSrcweir
164cdf0e10cSrcweir
~SmSymbolManager()165cdf0e10cSrcweir SmSymbolManager::~SmSymbolManager()
166cdf0e10cSrcweir {
167cdf0e10cSrcweir }
168cdf0e10cSrcweir
169cdf0e10cSrcweir
operator =(const SmSymbolManager & rSymbolSetManager)170cdf0e10cSrcweir SmSymbolManager& SmSymbolManager::operator = (const SmSymbolManager& rSymbolSetManager)
171cdf0e10cSrcweir {
172cdf0e10cSrcweir m_aSymbols = rSymbolSetManager.m_aSymbols;
173cdf0e10cSrcweir m_bModified = true;
174cdf0e10cSrcweir return *this;
175cdf0e10cSrcweir }
176cdf0e10cSrcweir
177cdf0e10cSrcweir
GetSymbolByName(const String & rSymbolName)178cdf0e10cSrcweir SmSym *SmSymbolManager::GetSymbolByName(const String& rSymbolName)
179cdf0e10cSrcweir {
180cdf0e10cSrcweir SmSym *pRes = NULL;
181cdf0e10cSrcweir SymbolMap_t::iterator aIt( m_aSymbols.find( rSymbolName ) );
182cdf0e10cSrcweir if (aIt != m_aSymbols.end())
183cdf0e10cSrcweir pRes = &aIt->second;
184cdf0e10cSrcweir return pRes;
185cdf0e10cSrcweir }
186cdf0e10cSrcweir
187cdf0e10cSrcweir
GetSymbols() const188cdf0e10cSrcweir const SymbolPtrVec_t SmSymbolManager::GetSymbols() const
189cdf0e10cSrcweir {
190cdf0e10cSrcweir SymbolPtrVec_t aRes;
191cdf0e10cSrcweir SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
192cdf0e10cSrcweir for ( ; aIt != m_aSymbols.end(); ++aIt)
193cdf0e10cSrcweir aRes.push_back( &aIt->second );
194cdf0e10cSrcweir // DBG_ASSERT( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " );
195cdf0e10cSrcweir return aRes;
196cdf0e10cSrcweir }
197cdf0e10cSrcweir
198cdf0e10cSrcweir
AddOrReplaceSymbol(const SmSym & rSymbol,bool bForceChange)199cdf0e10cSrcweir bool SmSymbolManager::AddOrReplaceSymbol( const SmSym &rSymbol, bool bForceChange )
200cdf0e10cSrcweir {
201cdf0e10cSrcweir bool bAdded = false;
202cdf0e10cSrcweir
203cdf0e10cSrcweir const String aSymbolName( rSymbol.GetName() );
204cdf0e10cSrcweir if (aSymbolName.Len() > 0 && rSymbol.GetSymbolSetName().Len() > 0)
205cdf0e10cSrcweir {
206cdf0e10cSrcweir const SmSym *pFound = GetSymbolByName( aSymbolName );
207cdf0e10cSrcweir const bool bSymbolConflict = pFound && !pFound->IsEqualInUI( rSymbol );
208cdf0e10cSrcweir
209cdf0e10cSrcweir // avoid having the same symbol name twice but with different symbols in use
210cdf0e10cSrcweir if (!pFound || bForceChange)
211cdf0e10cSrcweir {
212cdf0e10cSrcweir m_aSymbols[ aSymbolName ] = rSymbol;
213cdf0e10cSrcweir bAdded = true;
214cdf0e10cSrcweir }
215cdf0e10cSrcweir else if (pFound && !bForceChange && bSymbolConflict)
216cdf0e10cSrcweir {
217cdf0e10cSrcweir // TODO: to solve this a document owned symbol manager would be required ...
218cdf0e10cSrcweir // But for now we have a global one to easily support availability of all
219cdf0e10cSrcweir // symbols in all formulas. A copy of the global one would be needed here
220cdf0e10cSrcweir // and then the new symbol has to be forcefully applied. This would keep
221cdf0e10cSrcweir // the current formula intact but will leave the set of symbols in the
222cdf0e10cSrcweir // global symbol manager somewhat to chance.
223cdf0e10cSrcweir DBG_ASSERT( 0, "symbol conflict, different symbol with same name found!" );
224cdf0e10cSrcweir }
225cdf0e10cSrcweir
226cdf0e10cSrcweir if (bAdded)
227cdf0e10cSrcweir m_bModified = true;
228cdf0e10cSrcweir DBG_ASSERT( bAdded || (pFound && !bSymbolConflict), "AddOrReplaceSymbol: unresolved symbol conflict" );
229cdf0e10cSrcweir }
230cdf0e10cSrcweir
231cdf0e10cSrcweir return bAdded;
232cdf0e10cSrcweir }
233cdf0e10cSrcweir
234cdf0e10cSrcweir
RemoveSymbol(const String & rSymbolName)235cdf0e10cSrcweir void SmSymbolManager::RemoveSymbol( const String & rSymbolName )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir if (rSymbolName.Len() > 0)
238cdf0e10cSrcweir {
239cdf0e10cSrcweir size_t nOldSize = m_aSymbols.size();
240cdf0e10cSrcweir m_aSymbols.erase( rSymbolName );
241cdf0e10cSrcweir m_bModified = nOldSize != m_aSymbols.size();
242cdf0e10cSrcweir }
243cdf0e10cSrcweir }
244cdf0e10cSrcweir
245cdf0e10cSrcweir
GetSymbolSetNames() const246cdf0e10cSrcweir std::set< String > SmSymbolManager::GetSymbolSetNames() const
247cdf0e10cSrcweir {
248cdf0e10cSrcweir std::set< String > aRes;
249cdf0e10cSrcweir SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
250cdf0e10cSrcweir for ( ; aIt != m_aSymbols.end(); ++aIt )
251cdf0e10cSrcweir aRes.insert( aIt->second.GetSymbolSetName() );
252cdf0e10cSrcweir return aRes;
253cdf0e10cSrcweir }
254cdf0e10cSrcweir
255cdf0e10cSrcweir
GetSymbolSet(const String & rSymbolSetName)256cdf0e10cSrcweir const SymbolPtrVec_t SmSymbolManager::GetSymbolSet( const String& rSymbolSetName )
257cdf0e10cSrcweir {
258cdf0e10cSrcweir SymbolPtrVec_t aRes;
259cdf0e10cSrcweir if (rSymbolSetName.Len() > 0)
260cdf0e10cSrcweir {
261cdf0e10cSrcweir SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
262cdf0e10cSrcweir for ( ; aIt != m_aSymbols.end(); ++aIt )
263cdf0e10cSrcweir {
264cdf0e10cSrcweir if (aIt->second.GetSymbolSetName() == rSymbolSetName)
265cdf0e10cSrcweir aRes.push_back( &aIt->second );
266cdf0e10cSrcweir }
267cdf0e10cSrcweir }
268cdf0e10cSrcweir return aRes;
269cdf0e10cSrcweir }
270cdf0e10cSrcweir
271cdf0e10cSrcweir
Load()272cdf0e10cSrcweir void SmSymbolManager::Load()
273cdf0e10cSrcweir {
274cdf0e10cSrcweir std::vector< SmSym > aSymbols;
275cdf0e10cSrcweir SmMathConfig &rCfg = *SM_MOD()->GetConfig();
276cdf0e10cSrcweir rCfg.GetSymbols( aSymbols );
277cdf0e10cSrcweir size_t nSymbolCount = aSymbols.size();
278cdf0e10cSrcweir
279cdf0e10cSrcweir m_aSymbols.clear();
280cdf0e10cSrcweir for (size_t i = 0; i < nSymbolCount; ++i)
281cdf0e10cSrcweir {
282cdf0e10cSrcweir const SmSym &rSym = aSymbols[i];
283cdf0e10cSrcweir DBG_ASSERT( rSym.GetName().Len() > 0, "symbol without name!" );
284cdf0e10cSrcweir if (rSym.GetName().Len() > 0)
285cdf0e10cSrcweir AddOrReplaceSymbol( rSym );
286cdf0e10cSrcweir }
287cdf0e10cSrcweir m_bModified = true;
288cdf0e10cSrcweir
289cdf0e10cSrcweir if (0 == nSymbolCount)
290cdf0e10cSrcweir {
291cdf0e10cSrcweir DBG_ERROR( "no symbol set found" );
292cdf0e10cSrcweir m_bModified = false;
293cdf0e10cSrcweir }
294cdf0e10cSrcweir
295cdf0e10cSrcweir // now add a %i... symbol to the 'iGreek' set for every symbol found in the 'Greek' set.
296cdf0e10cSrcweir SmLocalizedSymbolData aLocalizedData;
297cdf0e10cSrcweir const String aGreekSymbolSetName( aLocalizedData.GetUiSymbolSetName( A2OU("Greek") ) );
298cdf0e10cSrcweir const SymbolPtrVec_t aGreekSymbols( GetSymbolSet( aGreekSymbolSetName ) );
299cdf0e10cSrcweir String aSymbolSetName( (sal_Unicode) 'i' );
300cdf0e10cSrcweir aSymbolSetName += aGreekSymbolSetName;
301cdf0e10cSrcweir size_t nSymbols = aGreekSymbols.size();
302cdf0e10cSrcweir for (size_t i = 0; i < nSymbols; ++i)
303cdf0e10cSrcweir {
304cdf0e10cSrcweir // make the new symbol a copy but with ITALIC_NORMAL, and add it to iGreek
305cdf0e10cSrcweir const SmSym &rSym = *aGreekSymbols[i];
306cdf0e10cSrcweir Font aFont( rSym.GetFace() );
307cdf0e10cSrcweir DBG_ASSERT( aFont.GetItalic() == ITALIC_NONE, "expected Font with ITALIC_NONE, failed." );
308cdf0e10cSrcweir aFont.SetItalic( ITALIC_NORMAL );
309cdf0e10cSrcweir String aSymbolName( (sal_Unicode)'i' );
310cdf0e10cSrcweir aSymbolName += rSym.GetName();
311cdf0e10cSrcweir SmSym aSymbol( aSymbolName, aFont, rSym.GetCharacter(),
312cdf0e10cSrcweir aSymbolSetName, sal_True /*bIsPredefined*/ );
313cdf0e10cSrcweir
314cdf0e10cSrcweir AddOrReplaceSymbol( aSymbol );
315cdf0e10cSrcweir }
316cdf0e10cSrcweir }
317cdf0e10cSrcweir
Save()318cdf0e10cSrcweir void SmSymbolManager::Save()
319cdf0e10cSrcweir {
320cdf0e10cSrcweir if (m_bModified)
321cdf0e10cSrcweir {
322cdf0e10cSrcweir SmMathConfig &rCfg = *SM_MOD()->GetConfig();
323cdf0e10cSrcweir
324cdf0e10cSrcweir #if 0
325cdf0e10cSrcweir sal_uInt16 nSymbolCount = GetSymbolCount();
326cdf0e10cSrcweir sal_uInt16 nSaveSymbolCnt = 0;
327cdf0e10cSrcweir const SmSym **pSymbols = new const SmSym* [ nSymbolCount ];
328cdf0e10cSrcweir const SmSym **pSym = pSymbols;
329cdf0e10cSrcweir for (sal_uInt16 j = 0; j < nSymbolCount; ++j)
330cdf0e10cSrcweir {
331cdf0e10cSrcweir const SmSym &rSym = *pSymSet->GetSymbol( j );
332cdf0e10cSrcweir if (!rSym.IsDocSymbol())
333cdf0e10cSrcweir {
334cdf0e10cSrcweir *pSym++ = &rSym;
335cdf0e10cSrcweir ++nSaveSymbolCnt;
336cdf0e10cSrcweir }
337cdf0e10cSrcweir }
338cdf0e10cSrcweir DBG_ASSERT(pSym - pSymbols == nSaveSymbolCnt, "wrong number of symbols" );
339cdf0e10cSrcweir #endif
340cdf0e10cSrcweir
341cdf0e10cSrcweir // prepare to skip symbols from iGreek on saving
342cdf0e10cSrcweir SmLocalizedSymbolData aLocalizedData;
343cdf0e10cSrcweir String aSymbolSetName( (sal_Unicode) 'i' );
344cdf0e10cSrcweir aSymbolSetName += aLocalizedData.GetUiSymbolSetName( A2OU("Greek") );
345cdf0e10cSrcweir
346cdf0e10cSrcweir SymbolPtrVec_t aTmp( GetSymbols() );
347cdf0e10cSrcweir std::vector< SmSym > aSymbols;
348cdf0e10cSrcweir for (size_t i = 0; i < aTmp.size(); ++i)
349cdf0e10cSrcweir {
350cdf0e10cSrcweir // skip symbols from iGreek set since those symbols always get added
351cdf0e10cSrcweir // by computational means in SmSymbolManager::Load
352cdf0e10cSrcweir if (aTmp[i]->GetSymbolSetName() != aSymbolSetName)
353cdf0e10cSrcweir aSymbols.push_back( *aTmp[i] );
354cdf0e10cSrcweir }
355cdf0e10cSrcweir rCfg.SetSymbols( aSymbols );
356cdf0e10cSrcweir #if 0
357cdf0e10cSrcweir delete [] pSymbols;
358cdf0e10cSrcweir #endif
359cdf0e10cSrcweir
360cdf0e10cSrcweir m_bModified = false;
361cdf0e10cSrcweir }
362cdf0e10cSrcweir }
363cdf0e10cSrcweir
364cdf0e10cSrcweir
365