Branch data 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 : 1116 : SmSym::SmSym() :
50 : : m_aName(rtl::OUString("unknown")),
51 : : m_aSetName(rtl::OUString("unknown")),
52 : : m_cChar('\0'),
53 : : m_bPredefined(false),
54 [ + - ][ + - ]: 1116 : m_bDocSymbol(false)
[ + - ]
55 : : {
56 [ + - ]: 1116 : m_aExportName = m_aName;
57 [ + - ]: 1116 : m_aFace.SetTransparent(true);
58 [ + - ]: 1116 : m_aFace.SetAlign(ALIGN_BASELINE);
59 : 1116 : }
60 : :
61 : :
62 [ + - ][ + - ]: 1440 : SmSym::SmSym(const SmSym& rSymbol)
[ + - ]
63 : : {
64 [ + - ]: 1440 : *this = rSymbol;
65 : 1440 : }
66 : :
67 : :
68 : 720 : SmSym::SmSym(const String& rName, const Font& rFont, sal_UCS4 cChar,
69 [ + - ][ + - ]: 720 : const String& rSet, bool bIsPredefined)
[ + - ]
70 : : {
71 [ + - ][ + - ]: 720 : m_aName = m_aExportName = rName;
72 : :
73 [ + - ][ + - ]: 720 : m_aFace = rFont;
[ + - ]
74 [ + - ]: 720 : m_aFace.SetTransparent(true);
75 [ + - ]: 720 : m_aFace.SetAlign(ALIGN_BASELINE);
76 : :
77 : 720 : m_cChar = cChar;
78 [ + - ]: 720 : m_aSetName = rSet;
79 : 720 : m_bPredefined = bIsPredefined;
80 : 720 : m_bDocSymbol = false;
81 : 720 : }
82 : :
83 : :
84 : 2556 : SmSym& SmSym::operator = (const SmSym& rSymbol)
85 : : {
86 : 2556 : m_aName = rSymbol.m_aName;
87 : 2556 : m_aExportName = rSymbol.m_aExportName;
88 : 2556 : m_cChar = rSymbol.m_cChar;
89 : 2556 : m_aFace = rSymbol.m_aFace;
90 : 2556 : m_aSetName = rSymbol.m_aSetName;
91 : 2556 : m_bPredefined = rSymbol.m_bPredefined;
92 : 2556 : m_bDocSymbol = rSymbol.m_bDocSymbol;
93 : :
94 : 2556 : SmSymbolManager * pSymSetManager = &SM_MOD()->GetSymbolManager();
95 [ + - ]: 2556 : if (pSymSetManager)
96 : 2556 : pSymSetManager->SetModified(true);
97 : :
98 : 2556 : 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 [ + - ]: 6 : SmSymbolManager::SmSymbolManager()
118 : : {
119 : 6 : m_bModified = false;
120 : 6 : }
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 : 720 : SmSym *SmSymbolManager::GetSymbolByName(const String& rSymbolName)
145 : : {
146 : 720 : SmSym *pRes = NULL;
147 [ + - ]: 720 : SymbolMap_t::iterator aIt( m_aSymbols.find( rSymbolName ) );
148 [ - + ]: 720 : if (aIt != m_aSymbols.end())
149 : 0 : pRes = &aIt->second;
150 : 720 : return pRes;
151 : : }
152 : :
153 : :
154 : 1704 : const SymbolPtrVec_t SmSymbolManager::GetSymbols() const
155 : : {
156 [ + - ]: 1704 : SymbolPtrVec_t aRes;
157 : 1704 : SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
158 [ + + ]: 206184 : for ( ; aIt != m_aSymbols.end(); ++aIt)
159 [ + - ]: 204480 : aRes.push_back( &aIt->second );
160 : : // OSL_ENSURE( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " );
161 : 1704 : return aRes;
162 : : }
163 : :
164 : :
165 : 720 : bool SmSymbolManager::AddOrReplaceSymbol( const SmSym &rSymbol, bool bForceChange )
166 : : {
167 : 720 : bool bAdded = false;
168 : :
169 [ + - ]: 720 : const String aSymbolName( rSymbol.GetName() );
170 [ + - ][ + - ]: 720 : if (aSymbolName.Len() > 0 && rSymbol.GetSymbolSetName().Len() > 0)
[ + - ]
171 : : {
172 [ + - ]: 720 : const SmSym *pFound = GetSymbolByName( aSymbolName );
173 [ - + ][ # # ]: 720 : const bool bSymbolConflict = pFound && !pFound->IsEqualInUI( rSymbol );
[ # # ]
174 : :
175 : : // avoid having the same symbol name twice but with different symbols in use
176 [ - + ][ # # ]: 720 : if (!pFound || bForceChange)
177 : : {
178 [ + - ][ + - ]: 720 : m_aSymbols[ aSymbolName ] = rSymbol;
179 : 720 : 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 [ + - ]: 720 : if (bAdded)
193 : 720 : m_bModified = true;
194 : : OSL_ENSURE( bAdded || (pFound && !bSymbolConflict), "AddOrReplaceSymbol: unresolved symbol conflict" );
195 : : }
196 : :
197 [ + - ]: 720 : return bAdded;
198 : : }
199 : :
200 : :
201 : 0 : void SmSymbolManager::RemoveSymbol( const String & rSymbolName )
202 : : {
203 [ # # ]: 0 : if (rSymbolName.Len() > 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< String > SmSymbolManager::GetSymbolSetNames() const
213 : : {
214 [ # # ]: 0 : std::set< String > 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 : 6 : const SymbolPtrVec_t SmSymbolManager::GetSymbolSet( const String& rSymbolSetName )
223 : : {
224 : 6 : SymbolPtrVec_t aRes;
225 [ + - ]: 6 : if (rSymbolSetName.Len() > 0)
226 : : {
227 : 6 : SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
228 [ + + ]: 402 : for ( ; aIt != m_aSymbols.end(); ++aIt )
229 : : {
230 [ + - ][ + + ]: 396 : if (aIt->second.GetSymbolSetName() == rSymbolSetName)
231 [ + - ]: 324 : aRes.push_back( &aIt->second );
232 : : }
233 : : }
234 : 6 : return aRes;
235 : : }
236 : :
237 : :
238 : 6 : void SmSymbolManager::Load()
239 : : {
240 [ + - ]: 6 : std::vector< SmSym > aSymbols;
241 [ + - ][ + - ]: 6 : SmMathConfig &rCfg = *SM_MOD()->GetConfig();
242 [ + - ]: 6 : rCfg.GetSymbols( aSymbols );
243 : 6 : size_t nSymbolCount = aSymbols.size();
244 : :
245 : 6 : m_aSymbols.clear();
246 [ + + ]: 402 : for (size_t i = 0; i < nSymbolCount; ++i)
247 : : {
248 : 396 : const SmSym &rSym = aSymbols[i];
249 : : OSL_ENSURE( rSym.GetName().Len() > 0, "symbol without name!" );
250 [ + - ]: 396 : if (rSym.GetName().Len() > 0)
251 [ + - ]: 396 : AddOrReplaceSymbol( rSym );
252 : : }
253 : 6 : m_bModified = true;
254 : :
255 [ - + ]: 6 : 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 [ + - ]: 6 : SmLocalizedSymbolData aLocalizedData;
263 [ + - ][ + - ]: 6 : const String aGreekSymbolSetName( aLocalizedData.GetUiSymbolSetName( OUString::createFromAscii( "Greek" ) ));
[ + - ]
264 [ + - ]: 6 : const SymbolPtrVec_t aGreekSymbols( GetSymbolSet( aGreekSymbolSetName ) );
265 [ + - ]: 6 : String aSymbolSetName = rtl::OUString('i');
266 [ + - ]: 6 : aSymbolSetName += aGreekSymbolSetName;
267 : 6 : size_t nSymbols = aGreekSymbols.size();
268 [ + + ]: 330 : 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 : 324 : const SmSym &rSym = *aGreekSymbols[i];
272 [ + - ]: 324 : Font aFont( rSym.GetFace() );
273 : : OSL_ENSURE( aFont.GetItalic() == ITALIC_NONE, "expected Font with ITALIC_NONE, failed." );
274 [ + - ]: 324 : aFont.SetItalic( ITALIC_NORMAL );
275 [ + - ]: 324 : String aSymbolName = rtl::OUString('i');
276 [ + - ]: 324 : aSymbolName += rSym.GetName();
277 : : SmSym aSymbol( aSymbolName, aFont, rSym.GetCharacter(),
278 [ + - ]: 324 : aSymbolSetName, true /*bIsPredefined*/ );
279 : :
280 [ + - ]: 324 : AddOrReplaceSymbol( aSymbol );
281 [ + - ][ + - ]: 330 : }
[ + - ][ + - ]
[ + - ][ + - ]
282 : 6 : }
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 : String aSymbolSetName = rtl::OUString('i');
293 [ # # ][ # # ]: 0 : aSymbolSetName += aLocalizedData.GetUiSymbolSetName( OUString::createFromAscii( "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 [ + - ][ + - ]: 30 : }
309 : :
310 : :
311 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|