Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <osl/mutex.hxx>
21 : #include <ucbhelper/content.hxx>
22 : #include <vcl/msgbox.hxx>
23 :
24 : #include <sfx2/dispatch.hxx>
25 : #include <sfx2/docfile.hxx>
26 :
27 : #include <map>
28 : #include <vector>
29 : #include <iterator>
30 :
31 : #include "symbol.hxx"
32 : #include "view.hxx"
33 : #include "utility.hxx"
34 : #include "dialog.hxx"
35 : #include "config.hxx"
36 : #include "cfgitem.hxx"
37 : #include "smmod.hxx"
38 : #include "starmath.hrc"
39 :
40 :
41 : using namespace ::com::sun::star;
42 : using namespace ::com::sun::star::ucb;
43 : using namespace ::com::sun::star::uno;
44 : using namespace ::rtl;
45 :
46 :
47 : /**************************************************************************/
48 :
49 744 : SmSym::SmSym() :
50 : m_aName(OUString("unknown")),
51 : m_aSetName(OUString("unknown")),
52 : m_cChar('\0'),
53 : m_bPredefined(false),
54 744 : m_bDocSymbol(false)
55 : {
56 744 : m_aExportName = m_aName;
57 744 : m_aFace.SetTransparent(true);
58 744 : m_aFace.SetAlign(ALIGN_BASELINE);
59 744 : }
60 :
61 :
62 960 : SmSym::SmSym(const SmSym& rSymbol)
63 : {
64 960 : *this = rSymbol;
65 960 : }
66 :
67 :
68 480 : SmSym::SmSym(const OUString& rName, const Font& rFont, sal_UCS4 cChar,
69 480 : const OUString& rSet, bool bIsPredefined)
70 : {
71 480 : m_aName = m_aExportName = rName;
72 :
73 480 : m_aFace = rFont;
74 480 : m_aFace.SetTransparent(true);
75 480 : m_aFace.SetAlign(ALIGN_BASELINE);
76 :
77 480 : m_cChar = cChar;
78 480 : m_aSetName = rSet;
79 480 : m_bPredefined = bIsPredefined;
80 480 : m_bDocSymbol = false;
81 480 : }
82 :
83 :
84 1704 : SmSym& SmSym::operator = (const SmSym& rSymbol)
85 : {
86 1704 : m_aName = rSymbol.m_aName;
87 1704 : m_aExportName = rSymbol.m_aExportName;
88 1704 : m_cChar = rSymbol.m_cChar;
89 1704 : m_aFace = rSymbol.m_aFace;
90 1704 : m_aSetName = rSymbol.m_aSetName;
91 1704 : m_bPredefined = rSymbol.m_bPredefined;
92 1704 : m_bDocSymbol = rSymbol.m_bDocSymbol;
93 :
94 1704 : SmSymbolManager * pSymSetManager = &SM_MOD()->GetSymbolManager();
95 1704 : if (pSymSetManager)
96 1704 : pSymSetManager->SetModified(true);
97 :
98 1704 : return *this;
99 : }
100 :
101 :
102 0 : bool SmSym::IsEqualInUI( const SmSym& rSymbol ) const
103 : {
104 0 : return m_aName == rSymbol.m_aName &&
105 0 : m_aFace == rSymbol.m_aFace &&
106 0 : m_cChar == rSymbol.m_cChar;
107 : }
108 :
109 : /**************************************************************************/
110 :
111 0 : void SmSymbolManager::SFX_NOTIFY(SfxBroadcaster& /*rBC*/, const TypeId& rBCType,
112 : const SfxHint& /*rHint*/, const TypeId& rHintType)
113 : {
114 0 : }
115 :
116 :
117 4 : SmSymbolManager::SmSymbolManager()
118 : {
119 4 : m_bModified = false;
120 4 : }
121 :
122 :
123 0 : SmSymbolManager::SmSymbolManager(const SmSymbolManager& rSymbolSetManager) :
124 0 : SfxListener()
125 : {
126 0 : m_aSymbols = rSymbolSetManager.m_aSymbols;
127 0 : m_bModified = true;
128 0 : }
129 :
130 :
131 0 : SmSymbolManager::~SmSymbolManager()
132 : {
133 0 : }
134 :
135 :
136 0 : SmSymbolManager& SmSymbolManager::operator = (const SmSymbolManager& rSymbolSetManager)
137 : {
138 0 : m_aSymbols = rSymbolSetManager.m_aSymbols;
139 0 : m_bModified = true;
140 0 : return *this;
141 : }
142 :
143 :
144 740 : SmSym *SmSymbolManager::GetSymbolByName(const OUString& rSymbolName)
145 : {
146 740 : SmSym *pRes = NULL;
147 740 : SymbolMap_t::iterator aIt( m_aSymbols.find( rSymbolName ) );
148 740 : if (aIt != m_aSymbols.end())
149 260 : pRes = &aIt->second;
150 740 : return pRes;
151 : }
152 :
153 :
154 572 : const SymbolPtrVec_t SmSymbolManager::GetSymbols() const
155 : {
156 572 : SymbolPtrVec_t aRes;
157 572 : SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
158 69212 : for ( ; aIt != m_aSymbols.end(); ++aIt)
159 68640 : aRes.push_back( &aIt->second );
160 : // OSL_ENSURE( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " );
161 572 : return aRes;
162 : }
163 :
164 :
165 480 : bool SmSymbolManager::AddOrReplaceSymbol( const SmSym &rSymbol, bool bForceChange )
166 : {
167 480 : bool bAdded = false;
168 :
169 480 : const OUString aSymbolName( rSymbol.GetName() );
170 480 : if (aSymbolName.getLength() > 0 && rSymbol.GetSymbolSetName().getLength() > 0)
171 : {
172 480 : const SmSym *pFound = GetSymbolByName( aSymbolName );
173 480 : const bool bSymbolConflict = pFound && !pFound->IsEqualInUI( rSymbol );
174 :
175 : // avoid having the same symbol name twice but with different symbols in use
176 480 : if (!pFound || bForceChange)
177 : {
178 480 : m_aSymbols[ aSymbolName ] = rSymbol;
179 480 : bAdded = true;
180 : }
181 : else if (pFound && !bForceChange && bSymbolConflict)
182 : {
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.
189 : }
190 :
191 : OSL_ENSURE( bAdded, "failed to add symbol" );
192 480 : if (bAdded)
193 480 : m_bModified = true;
194 : OSL_ENSURE( bAdded || (pFound && !bSymbolConflict), "AddOrReplaceSymbol: unresolved symbol conflict" );
195 : }
196 :
197 480 : return bAdded;
198 : }
199 :
200 :
201 0 : void SmSymbolManager::RemoveSymbol( const OUString & rSymbolName )
202 : {
203 0 : if (rSymbolName.getLength() > 0)
204 : {
205 0 : size_t nOldSize = m_aSymbols.size();
206 0 : m_aSymbols.erase( rSymbolName );
207 0 : m_bModified = nOldSize != m_aSymbols.size();
208 : }
209 0 : }
210 :
211 :
212 0 : std::set< OUString > SmSymbolManager::GetSymbolSetNames() const
213 : {
214 0 : std::set< OUString > aRes;
215 0 : SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
216 0 : for ( ; aIt != m_aSymbols.end(); ++aIt )
217 0 : aRes.insert( aIt->second.GetSymbolSetName() );
218 0 : return aRes;
219 : }
220 :
221 :
222 4 : const SymbolPtrVec_t SmSymbolManager::GetSymbolSet( const OUString& rSymbolSetName )
223 : {
224 4 : SymbolPtrVec_t aRes;
225 4 : if (rSymbolSetName.getLength() > 0)
226 : {
227 4 : SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
228 268 : for ( ; aIt != m_aSymbols.end(); ++aIt )
229 : {
230 264 : if (aIt->second.GetSymbolSetName() == rSymbolSetName)
231 216 : aRes.push_back( &aIt->second );
232 : }
233 : }
234 4 : return aRes;
235 : }
236 :
237 :
238 4 : void SmSymbolManager::Load()
239 : {
240 4 : std::vector< SmSym > aSymbols;
241 4 : SmMathConfig &rCfg = *SM_MOD()->GetConfig();
242 4 : rCfg.GetSymbols( aSymbols );
243 4 : size_t nSymbolCount = aSymbols.size();
244 :
245 4 : m_aSymbols.clear();
246 268 : for (size_t i = 0; i < nSymbolCount; ++i)
247 : {
248 264 : const SmSym &rSym = aSymbols[i];
249 : OSL_ENSURE( rSym.GetName().getLength() > 0, "symbol without name!" );
250 264 : if (rSym.GetName().getLength() > 0)
251 264 : AddOrReplaceSymbol( rSym );
252 : }
253 4 : m_bModified = true;
254 :
255 4 : if (0 == nSymbolCount)
256 : {
257 : OSL_FAIL( "no symbol set found" );
258 0 : m_bModified = false;
259 : }
260 :
261 : // now add a %i... symbol to the 'iGreek' set for every symbol found in the 'Greek' set.
262 4 : SmLocalizedSymbolData aLocalizedData;
263 4 : const OUString aGreekSymbolSetName(aLocalizedData.GetUiSymbolSetName(OUString("Greek")));
264 4 : const SymbolPtrVec_t aGreekSymbols( GetSymbolSet( aGreekSymbolSetName ) );
265 4 : OUString aSymbolSetName('i');
266 4 : aSymbolSetName += aGreekSymbolSetName;
267 4 : size_t nSymbols = aGreekSymbols.size();
268 220 : for (size_t i = 0; i < nSymbols; ++i)
269 : {
270 : // make the new symbol a copy but with ITALIC_NORMAL, and add it to iGreek
271 216 : const SmSym &rSym = *aGreekSymbols[i];
272 216 : Font aFont( rSym.GetFace() );
273 : OSL_ENSURE( aFont.GetItalic() == ITALIC_NONE, "expected Font with ITALIC_NONE, failed." );
274 216 : aFont.SetItalic( ITALIC_NORMAL );
275 216 : OUString aSymbolName('i');
276 216 : aSymbolName += rSym.GetName();
277 : SmSym aSymbol( aSymbolName, aFont, rSym.GetCharacter(),
278 216 : aSymbolSetName, true /*bIsPredefined*/ );
279 :
280 216 : AddOrReplaceSymbol( aSymbol );
281 220 : }
282 4 : }
283 :
284 0 : void SmSymbolManager::Save()
285 : {
286 0 : if (m_bModified)
287 : {
288 0 : SmMathConfig &rCfg = *SM_MOD()->GetConfig();
289 :
290 : // prepare to skip symbols from iGreek on saving
291 0 : SmLocalizedSymbolData aLocalizedData;
292 0 : OUString aSymbolSetName('i');
293 0 : aSymbolSetName += aLocalizedData.GetUiSymbolSetName(OUString("Greek"));
294 :
295 0 : SymbolPtrVec_t aTmp( GetSymbols() );
296 0 : std::vector< SmSym > aSymbols;
297 0 : for (size_t i = 0; i < aTmp.size(); ++i)
298 : {
299 : // skip symbols from iGreek set since those symbols always get added
300 : // by computational means in SmSymbolManager::Load
301 0 : if (aTmp[i]->GetSymbolSetName() != aSymbolSetName)
302 0 : aSymbols.push_back( *aTmp[i] );
303 : }
304 0 : rCfg.SetSymbols( aSymbols );
305 :
306 0 : m_bModified = false;
307 : }
308 12 : }
309 :
310 :
311 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|