merge the formfield patch from ooo-build
[ooovba.git] / starmath / source / symbol.cxx
blob1e2aeb781a32a7c610fed439d3226b717898476d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: symbol.cxx,v $
10 * $Revision: 1.31 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_starmath.hxx"
35 #include <vector>
36 #include <osl/mutex.hxx>
37 #include <ucbhelper/content.hxx>
38 #include <vcl/msgbox.hxx>
40 #ifndef _SV_RESARY_HXX
41 #include <tools/resary.hxx>
42 #endif
43 #include <sfx2/dispatch.hxx>
44 #include <sfx2/docfile.hxx>
46 #include "symbol.hxx"
47 #include "view.hxx"
48 #include "utility.hxx"
49 #include "dialog.hxx"
50 #include "config.hxx"
51 #include "cfgitem.hxx"
52 #include "smmod.hxx"
53 #include "starmath.hrc"
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::ucb;
58 using namespace ::com::sun::star::uno;
59 using namespace ::rtl;
61 // Das hier muss auch mal alles "uberarbeitet werden. Insbesondere die nicht
62 // funktionierende und bei l"oschen/"andern von Symbolen nicht gepflegte
63 // Hash Tabelle!!! Diese aktualisert sich erst im Wertzuweisungsoperator
64 // beim Verlassen des 'SmSymDefineDialog's!
66 /**************************************************************************/
69 ** MACRO DEFINTION
71 **/
73 #define SF_SM20IDENT 0x03031963L
74 #define SF_IDENT 0x30334D53L
77 SV_IMPL_PTRARR( SymbolArray, SmSym * );
79 /**************************************************************************/
82 ** DATA DEFINITION
84 **/
86 long SF_Ident = SF_IDENT;
88 /**************************************************************************/
91 ** CLASS IMPLEMENTATION
93 **/
95 SmSym::SmSym() :
96 Name(C2S("unknown")),
97 aSetName(C2S("unknown")),
98 pHashNext(0),
99 pSymSetManager(0),
100 Character('\0'),
101 bPredefined(FALSE),
102 bDocSymbol(FALSE)
104 aExportName = Name;
105 Face.SetTransparent(TRUE);
106 Face.SetAlign(ALIGN_BASELINE);
110 SmSym::SmSym(const SmSym& rSymbol)
112 pSymSetManager = 0;
113 *this = rSymbol;
117 SmSym::SmSym(const String& rName, const Font& rFont, sal_Unicode aChar,
118 const String& rSet, BOOL bIsPredefined)
120 Name = aExportName = rName;
122 Face = rFont;
123 Face.SetTransparent(TRUE);
124 Face.SetAlign(ALIGN_BASELINE);
126 Character = aChar;
127 //! according to HDU this should not be used anymore now
128 //! since this was necessary in the early days but should
129 //! not be done now since this is handled now at a more
130 //! bottom layer by HDU.
131 //! He can still imagine scenarios where this will be wrong
132 //! now though, for example when importing *some* old documents.
133 //! But overall it should be a large improvement, and
134 //! likely everything will still work... #_- (eyes shut and "go"!)
136 // if (RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet())
137 // Character |= 0xF000;
138 aSetName = rSet;
139 bPredefined = bIsPredefined;
140 bDocSymbol = FALSE;
142 pHashNext = 0;
143 pSymSetManager = 0;
147 SmSym& SmSym::operator = (const SmSym& rSymbol)
149 Name = rSymbol.Name;
150 Face = rSymbol.Face;
151 Character = rSymbol.Character;
152 aSetName = rSymbol.aSetName;
153 bPredefined = rSymbol.bPredefined;
154 bDocSymbol = rSymbol.bDocSymbol;
155 aExportName = rSymbol.aExportName;
157 pHashNext = 0;
159 if (pSymSetManager)
160 pSymSetManager->SetModified(TRUE);
162 return *this;
165 /**************************************************************************/
167 SmSymSet::SmSymSet() :
168 Name(C2S("unknown")),
169 pSymSetManager(0)
171 SymbolList.Clear();
174 SmSymSet::SmSymSet(const SmSymSet& rSymbolSet)
176 pSymSetManager = 0;
177 *this = rSymbolSet;
180 SmSymSet::SmSymSet(const String& rName)
182 Name = rName;
183 SymbolList.Clear();
185 pSymSetManager = 0;
188 SmSymSet::~SmSymSet()
190 for (USHORT i = 0; i < GetCount(); i++)
191 delete SymbolList.GetObject(i);
194 SmSymSet& SmSymSet::operator = (const SmSymSet& rSymbolSet)
196 USHORT i;
197 for (i = 0; i < GetCount(); i++)
198 delete SymbolList.GetObject(i);
200 Name = rSymbolSet.Name;
201 SymbolList.Clear();
202 for (i = 0; i < rSymbolSet.GetCount(); i++)
203 AddSymbol(new SmSym(rSymbolSet.GetSymbol(i)));
205 if (pSymSetManager)
206 pSymSetManager->SetModified(TRUE);
208 return *this;
211 USHORT SmSymSet::AddSymbol(SmSym* pSymbol)
213 DBG_ASSERT(pSymbol, "Kein Symbol");
215 if (pSymbol)
216 pSymbol->SetSetName( GetName() );
217 SymbolList.Insert(pSymbol, LIST_APPEND);
218 DBG_ASSERT(SymbolList.GetPos(pSymbol) == SymbolList.Count() - 1,
219 "Sm : ... ergibt falschen return Wert");
221 if (pSymSetManager)
222 pSymSetManager->SetModified(TRUE);
224 return (USHORT) SymbolList.Count() - 1;
227 void SmSymSet::DeleteSymbol(USHORT SymbolNo)
229 delete RemoveSymbol(SymbolNo);
232 SmSym * SmSymSet::RemoveSymbol(USHORT SymbolNo)
234 DBG_ASSERT(SymbolList.GetObject(SymbolNo), "Symbol nicht vorhanden");
236 SmSym *pSym = SymbolList.GetObject(SymbolNo);
237 SymbolList.Remove(SymbolNo);
239 if (pSymSetManager)
240 pSymSetManager->SetModified(TRUE);
242 return pSym;
245 USHORT SmSymSet::GetSymbolPos(const String& rName)
247 for (USHORT i = 0; i < GetCount(); i++)
248 if (SymbolList.GetObject(i)->GetName() == rName)
249 return (i);
251 return SYMBOL_NONE;
254 /**************************************************************************/
256 SmSymSetManager_Impl::SmSymSetManager_Impl(
257 SmSymSetManager &rMgr, USHORT HashTableSize ) :
259 rSymSetMgr (rMgr)
261 NoSymbolSets = 0;
262 NoHashEntries = HashTableSize;
263 HashEntries = new SmSym *[NoHashEntries];
264 memset( HashEntries, 0, sizeof(SmSym *) * NoHashEntries );
265 Modified = FALSE;
269 SmSymSetManager_Impl::~SmSymSetManager_Impl()
271 for (USHORT i = 0; i < NoSymbolSets; ++i)
272 delete SymbolSets.Get(i);
273 SymbolSets.Clear();
275 NoSymbolSets = 0;
276 if (HashEntries)
278 delete[] HashEntries;
279 HashEntries = 0;
281 NoHashEntries = 0;
282 Modified = FALSE;
286 SmSymSetManager_Impl & SmSymSetManager_Impl::operator = ( const SmSymSetManager_Impl &rImpl )
288 //! rMySymSetMgr remains unchanged
290 NoHashEntries = rImpl.NoHashEntries;
291 if (HashEntries)
292 delete [] HashEntries;
293 HashEntries = new SmSym *[NoHashEntries];
294 memset( HashEntries, 0, sizeof(SmSym *) * NoHashEntries );
296 NoSymbolSets = 0;
297 SymbolSets.Clear();
298 for (USHORT i = 0; i < rImpl.NoSymbolSets; ++i)
300 rSymSetMgr.AddSymbolSet( new SmSymSet( *rImpl.rSymSetMgr.GetSymbolSet(i) ) );
302 DBG_ASSERT( NoSymbolSets == rImpl.NoSymbolSets,
303 "incorrect number of symbolsets" );
305 Modified = TRUE;
306 return *this;
309 /**************************************************************************/
311 void SmSymSetManager::SFX_NOTIFY(SfxBroadcaster& /*rBC*/, const TypeId& rBCType,
312 const SfxHint& /*rHint*/, const TypeId& rHintType)
317 UINT32 SmSymSetManager::GetHashIndex(const String& rSymbolName)
319 UINT32 x = 1;
320 for (xub_StrLen i = 0; i < rSymbolName.Len(); i++)
321 x += x * rSymbolName.GetChar(i) + i;
323 return x % pImpl->NoHashEntries;
327 void SmSymSetManager::EnterHashTable(SmSym& rSymbol)
329 int j = GetHashIndex( rSymbol.GetName() );
330 if (pImpl->HashEntries[j] == 0)
331 pImpl->HashEntries[j] = &rSymbol;
332 else
334 SmSym *p = pImpl->HashEntries[j];
335 while (p->pHashNext)
336 p = p->pHashNext;
337 p->pHashNext = &rSymbol;
339 rSymbol.pHashNext = 0;
343 void SmSymSetManager::EnterHashTable(SmSymSet& rSymbolSet)
345 for (USHORT i = 0; i < rSymbolSet.GetCount(); i++)
346 EnterHashTable( *rSymbolSet.SymbolList.GetObject(i) );
349 void SmSymSetManager::FillHashTable()
351 if (pImpl->HashEntries)
353 memset( pImpl->HashEntries, 0, pImpl->NoHashEntries * sizeof(SmSym *) );
355 for (UINT32 i = 0; i < pImpl->NoSymbolSets; i++)
356 EnterHashTable( *GetSymbolSet( (USHORT) i ) );
360 void SmSymSetManager::Init()
362 SmModule *pp = SM_MOD1();
363 StartListening(*pp->GetConfig());
367 void SmSymSetManager::Exit()
369 SmModule *pp = SM_MOD1();
370 EndListening(*pp->GetConfig());
374 SmSymSetManager::SmSymSetManager(USHORT HashTableSize)
376 pImpl = new SmSymSetManager_Impl( *this, HashTableSize );
380 SmSymSetManager::SmSymSetManager(const SmSymSetManager& rSymbolSetManager) :
381 SfxListener()
383 pImpl = new SmSymSetManager_Impl( *this, rSymbolSetManager.pImpl->NoHashEntries );
384 *pImpl = *rSymbolSetManager.pImpl;
388 SmSymSetManager::~SmSymSetManager()
390 delete pImpl;
391 pImpl = 0;
394 SmSymSetManager& SmSymSetManager::operator = (const SmSymSetManager& rSymbolSetManager)
396 *pImpl = *rSymbolSetManager.pImpl;
397 return *this;
400 USHORT SmSymSetManager::AddSymbolSet(SmSymSet* pSymbolSet)
402 if (pImpl->NoSymbolSets >= pImpl->SymbolSets.GetSize())
403 pImpl->SymbolSets.SetSize(pImpl->NoSymbolSets + 1);
405 pImpl->SymbolSets.Put(pImpl->NoSymbolSets++, pSymbolSet);
407 pSymbolSet->pSymSetManager = this;
409 for (USHORT i = 0; i < pSymbolSet->GetCount(); i++)
410 pSymbolSet->SymbolList.GetObject(i)->pSymSetManager = this;
412 FillHashTable();
413 pImpl->Modified = TRUE;
415 return (USHORT) (pImpl->NoSymbolSets - 1);
418 void SmSymSetManager::ChangeSymbolSet(SmSymSet* pSymbolSet)
420 if (pSymbolSet)
422 FillHashTable();
423 pImpl->Modified = TRUE;
427 void SmSymSetManager::DeleteSymbolSet(USHORT SymbolSetNo)
429 delete pImpl->SymbolSets.Get(SymbolSetNo);
430 pImpl->NoSymbolSets--;
432 for (UINT32 i = SymbolSetNo; i < pImpl->NoSymbolSets; i++)
433 pImpl->SymbolSets.Put(i, pImpl->SymbolSets.Get(i + 1));
435 FillHashTable();
437 pImpl->Modified = TRUE;
441 USHORT SmSymSetManager::GetSymbolSetPos(const String& rSymbolSetName) const
443 for (USHORT i = 0; i < pImpl->NoSymbolSets; i++)
444 if (pImpl->SymbolSets.Get(i)->GetName() == rSymbolSetName)
445 return (i);
447 return SYMBOLSET_NONE;
450 SmSym *SmSymSetManager::GetSymbolByName(const String& rSymbolName)
452 SmSym *pSym = pImpl->HashEntries[GetHashIndex(rSymbolName)];
453 while (pSym)
455 if (pSym->Name == rSymbolName)
456 break;
457 pSym = pSym->pHashNext;
460 return pSym;
464 void SmSymSetManager::AddReplaceSymbol( const SmSym &rSymbol )
466 SmSym *pSym = GetSymbolByName( rSymbol.GetName() );
467 if (pSym)
469 *pSym = rSymbol;
471 else
473 USHORT nPos = GetSymbolSetPos( rSymbol.GetSetName() );
474 if (SYMBOLSET_NONE == nPos)
476 AddSymbolSet( new SmSymSet( rSymbol.GetSetName() ) );
477 nPos = GetSymbolSetPos( rSymbol.GetSetName() );
479 DBG_ASSERT( nPos != SYMBOLSET_NONE, "SymbolSet not found");
480 SmSym *pTmpSym = new SmSym( rSymbol );
481 GetSymbolSet( nPos )->AddSymbol( pTmpSym );
482 EnterHashTable( *pTmpSym );
484 SetModified( TRUE );
488 USHORT SmSymSetManager::GetSymbolCount() const
490 USHORT nRes = 0;
491 USHORT nSets = GetSymbolSetCount();
492 for (USHORT i = 0; i < nSets; ++i)
493 nRes = nRes + GetSymbolSet(i)->GetCount();
494 return nRes;
498 const SmSym * SmSymSetManager::GetSymbolByPos( USHORT nPos ) const
500 const SmSym *pRes = 0;
502 INT16 nIdx = 0;
503 USHORT nSets = GetSymbolSetCount();
504 USHORT i = 0;
505 while (i < nSets && !pRes)
507 USHORT nEntries = GetSymbolSet(i)->GetCount();
508 if (nPos < nIdx + nEntries)
509 pRes = &GetSymbolSet(i)->GetSymbol( nPos - nIdx );
510 else
511 nIdx = nIdx + nEntries;
512 ++i;
515 return pRes;
519 void SmSymSetManager::GetSymbols( std::vector< SmSym > &rSymbols ) const
521 INT32 nCount = GetSymbolCount();
522 rSymbols.resize( nCount );
523 USHORT nPos = 0;
524 std::vector< SmSym >::iterator aIt( rSymbols.begin() );
525 std::vector< SmSym >::iterator aEnd( rSymbols.end() );
526 while (aIt != aEnd)
528 const SmSym *pSym = GetSymbolByPos( nPos++ );
529 DBG_ASSERT( pSym, "symbol missing" );
530 if (pSym)
531 *aIt++ = *pSym;
533 DBG_ASSERT( nPos == nCount, "index out of range?" );
537 void SmSymSetManager::Load()
539 std::vector< SmSym > aSymbols;
540 SmMathConfig &rCfg = *SM_MOD1()->GetConfig();
541 rCfg.GetSymbols( aSymbols );
542 INT32 nSymbolCount = aSymbols.size();
544 USHORT i;
545 for (i = 0; i < nSymbolCount; ++i)
547 const SmSym &rSym = aSymbols[i];
548 DBG_ASSERT( rSym.Name.Len() > 0, "symbol without name!" );
549 if (rSym.Name.Len() > 0)
551 SmSymSet *pSymSet = 0;
552 const String &rSetName = rSym.GetSetName();
553 USHORT nSetPos = GetSymbolSetPos( rSetName );
554 if (SYMBOLSET_NONE != nSetPos)
555 pSymSet = GetSymbolSet( nSetPos );
556 else
558 pSymSet = new SmSymSet( rSetName );
559 AddSymbolSet( pSymSet );
562 pSymSet->AddSymbol( new SmSym( rSym ) );
565 // build HashTables
566 INT32 nSymbolSetCount = GetSymbolSetCount();
567 for (i = 0; i < nSymbolSetCount; ++i)
568 ChangeSymbolSet( GetSymbolSet( i ) );
570 if (0 == nSymbolCount)
572 DBG_ERROR( "no symbol set found" );
573 pImpl->Modified = FALSE;
577 void SmSymSetManager::Save()
579 SmMathConfig &rCfg = *SM_MOD1()->GetConfig();
581 // get number of Symbols
582 USHORT nSymbolCount = 0;
583 USHORT nSetCount = GetSymbolSetCount();
584 USHORT i;
585 for (i = 0; i < nSetCount; ++i)
586 nSymbolCount = nSymbolCount + GetSymbolSet( i )->GetCount();
588 if (nSymbolCount)
590 USHORT nSaveSymbolCnt = 0;
591 const SmSym **pSymbols = new const SmSym* [ nSymbolCount ];
592 const SmSym **pSym = pSymbols;
593 for (i = 0; i < nSetCount; ++i)
595 const SmSymSet *pSymSet = GetSymbolSet( i );
596 USHORT n = pSymSet->GetCount();
597 for (USHORT j = 0; j < n; ++j)
599 const SmSym &rSym = pSymSet->GetSymbol( j );
600 if (!rSym.IsDocSymbol())
602 *pSym++ = &rSym;
603 ++nSaveSymbolCnt;
607 DBG_ASSERT(pSym - pSymbols == nSaveSymbolCnt, "wrong number of symbols" );
609 std::vector< SmSym > aSymbols;
610 GetSymbols( aSymbols );
611 rCfg.SetSymbols( aSymbols );
612 delete [] pSymbols;