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 "cfgitem.hxx"
36 : #include "smmod.hxx"
37 : #include "starmath.hrc"
38 :
39 :
40 : using namespace ::com::sun::star;
41 : using namespace ::com::sun::star::ucb;
42 : using namespace ::com::sun::star::uno;
43 :
44 :
45 : /**************************************************************************/
46 :
47 1860 : SmSym::SmSym() :
48 : m_aName(OUString("unknown")),
49 : m_aSetName(OUString("unknown")),
50 : m_cChar('\0'),
51 : m_bPredefined(false),
52 1860 : m_bDocSymbol(false)
53 : {
54 1860 : m_aExportName = m_aName;
55 1860 : m_aFace.SetTransparent(true);
56 1860 : m_aFace.SetAlign(ALIGN_BASELINE);
57 1860 : }
58 :
59 :
60 0 : SmSym::SmSym(const SmSym& rSymbol)
61 : {
62 0 : *this = rSymbol;
63 0 : }
64 :
65 :
66 1200 : SmSym::SmSym(const OUString& rName, const vcl::Font& rFont, sal_UCS4 cChar,
67 1200 : const OUString& rSet, bool bIsPredefined)
68 : {
69 1200 : m_aName = m_aExportName = rName;
70 :
71 1200 : m_aFace = rFont;
72 1200 : m_aFace.SetTransparent(true);
73 1200 : m_aFace.SetAlign(ALIGN_BASELINE);
74 :
75 1200 : m_cChar = cChar;
76 1200 : m_aSetName = rSet;
77 1200 : m_bPredefined = bIsPredefined;
78 1200 : m_bDocSymbol = false;
79 1200 : }
80 :
81 :
82 1860 : SmSym& SmSym::operator = (const SmSym& rSymbol)
83 : {
84 1860 : m_aName = rSymbol.m_aName;
85 1860 : m_aExportName = rSymbol.m_aExportName;
86 1860 : m_cChar = rSymbol.m_cChar;
87 1860 : m_aFace = rSymbol.m_aFace;
88 1860 : m_aSetName = rSymbol.m_aSetName;
89 1860 : m_bPredefined = rSymbol.m_bPredefined;
90 1860 : m_bDocSymbol = rSymbol.m_bDocSymbol;
91 :
92 1860 : SmSymbolManager * pSymSetManager = &SM_MOD()->GetSymbolManager();
93 1860 : if (pSymSetManager)
94 1860 : pSymSetManager->SetModified(true);
95 :
96 1860 : return *this;
97 : }
98 :
99 :
100 0 : bool SmSym::IsEqualInUI( const SmSym& rSymbol ) const
101 : {
102 0 : return m_aName == rSymbol.m_aName &&
103 0 : m_aFace == rSymbol.m_aFace &&
104 0 : m_cChar == rSymbol.m_cChar;
105 : }
106 :
107 : /**************************************************************************/
108 :
109 0 : void SmSymbolManager::SFX_NOTIFY(SfxBroadcaster& /*rBC*/, const TypeId& rBCType,
110 : const SfxHint& /*rHint*/, const TypeId& rHintType)
111 : {
112 0 : }
113 :
114 :
115 10 : SmSymbolManager::SmSymbolManager()
116 : {
117 10 : m_bModified = false;
118 10 : }
119 :
120 :
121 0 : SmSymbolManager::SmSymbolManager(const SmSymbolManager& rSymbolSetManager) :
122 0 : SfxListener()
123 : {
124 0 : m_aSymbols = rSymbolSetManager.m_aSymbols;
125 0 : m_bModified = true;
126 0 : }
127 :
128 :
129 0 : SmSymbolManager::~SmSymbolManager()
130 : {
131 0 : }
132 :
133 :
134 0 : SmSymbolManager& SmSymbolManager::operator = (const SmSymbolManager& rSymbolSetManager)
135 : {
136 0 : m_aSymbols = rSymbolSetManager.m_aSymbols;
137 0 : m_bModified = true;
138 0 : return *this;
139 : }
140 :
141 :
142 1462 : SmSym *SmSymbolManager::GetSymbolByName(const OUString& rSymbolName)
143 : {
144 1462 : SmSym *pRes = NULL;
145 1462 : SymbolMap_t::iterator aIt( m_aSymbols.find( rSymbolName ) );
146 1462 : if (aIt != m_aSymbols.end())
147 260 : pRes = &aIt->second;
148 1462 : return pRes;
149 : }
150 :
151 :
152 1122 : const SymbolPtrVec_t SmSymbolManager::GetSymbols() const
153 : {
154 1122 : SymbolPtrVec_t aRes;
155 1122 : SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
156 135762 : for ( ; aIt != m_aSymbols.end(); ++aIt)
157 134640 : aRes.push_back( &aIt->second );
158 : // OSL_ENSURE( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " );
159 1122 : return aRes;
160 : }
161 :
162 :
163 1200 : bool SmSymbolManager::AddOrReplaceSymbol( const SmSym &rSymbol, bool bForceChange )
164 : {
165 1200 : bool bAdded = false;
166 :
167 1200 : const OUString aSymbolName( rSymbol.GetName() );
168 1200 : if (aSymbolName.getLength() > 0 && rSymbol.GetSymbolSetName().getLength() > 0)
169 : {
170 1200 : const SmSym *pFound = GetSymbolByName( aSymbolName );
171 1200 : const bool bSymbolConflict = pFound && !pFound->IsEqualInUI( rSymbol );
172 :
173 : // avoid having the same symbol name twice but with different symbols in use
174 1200 : if (!pFound || bForceChange)
175 : {
176 1200 : m_aSymbols[ aSymbolName ] = rSymbol;
177 1200 : bAdded = true;
178 : }
179 0 : else if (pFound && !bForceChange && bSymbolConflict)
180 : {
181 : // TODO: to solve this a document owned symbol manager would be required ...
182 : SAL_WARN("starmath", "symbol conflict, different symbol with same name found!");
183 : // symbols in all formulas. A copy of the global one would be needed here
184 : // and then the new symbol has to be forcefully applied. This would keep
185 : // the current formula intact but will leave the set of symbols in the
186 : // global symbol manager somewhat to chance.
187 : }
188 :
189 : OSL_ENSURE( bAdded, "failed to add symbol" );
190 1200 : if (bAdded)
191 1200 : m_bModified = true;
192 : OSL_ENSURE( bAdded || (pFound && !bSymbolConflict), "AddOrReplaceSymbol: unresolved symbol conflict" );
193 : }
194 :
195 1200 : return bAdded;
196 : }
197 :
198 :
199 0 : void SmSymbolManager::RemoveSymbol( const OUString & rSymbolName )
200 : {
201 0 : if (rSymbolName.getLength() > 0)
202 : {
203 0 : size_t nOldSize = m_aSymbols.size();
204 0 : m_aSymbols.erase( rSymbolName );
205 0 : m_bModified = nOldSize != m_aSymbols.size();
206 : }
207 0 : }
208 :
209 :
210 0 : std::set< OUString > SmSymbolManager::GetSymbolSetNames() const
211 : {
212 0 : std::set< OUString > aRes;
213 0 : SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
214 0 : for ( ; aIt != m_aSymbols.end(); ++aIt )
215 0 : aRes.insert( aIt->second.GetSymbolSetName() );
216 0 : return aRes;
217 : }
218 :
219 :
220 10 : const SymbolPtrVec_t SmSymbolManager::GetSymbolSet( const OUString& rSymbolSetName )
221 : {
222 10 : SymbolPtrVec_t aRes;
223 10 : if (rSymbolSetName.getLength() > 0)
224 : {
225 10 : SymbolMap_t::const_iterator aIt( m_aSymbols.begin() );
226 670 : for ( ; aIt != m_aSymbols.end(); ++aIt )
227 : {
228 660 : if (aIt->second.GetSymbolSetName() == rSymbolSetName)
229 540 : aRes.push_back( &aIt->second );
230 : }
231 : }
232 10 : return aRes;
233 : }
234 :
235 :
236 10 : void SmSymbolManager::Load()
237 : {
238 10 : std::vector< SmSym > aSymbols;
239 10 : SmMathConfig &rCfg = *SM_MOD()->GetConfig();
240 10 : rCfg.GetSymbols( aSymbols );
241 10 : size_t nSymbolCount = aSymbols.size();
242 :
243 10 : m_aSymbols.clear();
244 670 : for (size_t i = 0; i < nSymbolCount; ++i)
245 : {
246 660 : const SmSym &rSym = aSymbols[i];
247 : OSL_ENSURE( rSym.GetName().getLength() > 0, "symbol without name!" );
248 660 : if (rSym.GetName().getLength() > 0)
249 660 : AddOrReplaceSymbol( rSym );
250 : }
251 10 : m_bModified = true;
252 :
253 10 : if (0 == nSymbolCount)
254 : {
255 : SAL_WARN("starmath", "no symbol set found");
256 0 : m_bModified = false;
257 : }
258 :
259 : // now add a %i... symbol to the 'iGreek' set for every symbol found in the 'Greek' set.
260 20 : const OUString aGreekSymbolSetName(SmLocalizedSymbolData::GetUiSymbolSetName(OUString("Greek")));
261 20 : const SymbolPtrVec_t aGreekSymbols( GetSymbolSet( aGreekSymbolSetName ) );
262 20 : OUString aSymbolSetName('i');
263 10 : aSymbolSetName += aGreekSymbolSetName;
264 10 : size_t nSymbols = aGreekSymbols.size();
265 550 : for (size_t i = 0; i < nSymbols; ++i)
266 : {
267 : // make the new symbol a copy but with ITALIC_NORMAL, and add it to iGreek
268 540 : const SmSym &rSym = *aGreekSymbols[i];
269 540 : vcl::Font aFont( rSym.GetFace() );
270 : OSL_ENSURE( aFont.GetItalic() == ITALIC_NONE, "expected Font with ITALIC_NONE, failed." );
271 540 : aFont.SetItalic( ITALIC_NORMAL );
272 1080 : OUString aSymbolName('i');
273 540 : aSymbolName += rSym.GetName();
274 : SmSym aSymbol( aSymbolName, aFont, rSym.GetCharacter(),
275 1080 : aSymbolSetName, true /*bIsPredefined*/ );
276 :
277 540 : AddOrReplaceSymbol( aSymbol );
278 550 : }
279 10 : }
280 :
281 0 : void SmSymbolManager::Save()
282 : {
283 0 : if (m_bModified)
284 : {
285 0 : SmMathConfig &rCfg = *SM_MOD()->GetConfig();
286 :
287 : // prepare to skip symbols from iGreek on saving
288 0 : OUString aSymbolSetName('i');
289 0 : aSymbolSetName += SmLocalizedSymbolData::GetUiSymbolSetName(OUString("Greek"));
290 :
291 0 : SymbolPtrVec_t aTmp( GetSymbols() );
292 0 : std::vector< SmSym > aSymbols;
293 0 : for (size_t i = 0; i < aTmp.size(); ++i)
294 : {
295 : // skip symbols from iGreek set since those symbols always get added
296 : // by computational means in SmSymbolManager::Load
297 0 : if (aTmp[i]->GetSymbolSetName() != aSymbolSetName)
298 0 : aSymbols.push_back( *aTmp[i] );
299 : }
300 0 : rCfg.SetSymbols( aSymbols );
301 :
302 0 : m_bModified = false;
303 : }
304 42 : }
305 :
306 :
307 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|