1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: symbol.cxx,v $
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"
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>
43 #include <sfx2/dispatch.hxx>
44 #include <sfx2/docfile.hxx>
48 #include "utility.hxx"
51 #include "cfgitem.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 /**************************************************************************/
73 #define SF_SM20IDENT 0x03031963L
74 #define SF_IDENT 0x30334D53L
77 SV_IMPL_PTRARR( SymbolArray
, SmSym
* );
79 /**************************************************************************/
86 long SF_Ident
= SF_IDENT
;
88 /**************************************************************************/
91 ** CLASS IMPLEMENTATION
97 aSetName(C2S("unknown")),
105 Face
.SetTransparent(TRUE
);
106 Face
.SetAlign(ALIGN_BASELINE
);
110 SmSym::SmSym(const SmSym
& rSymbol
)
117 SmSym::SmSym(const String
& rName
, const Font
& rFont
, sal_Unicode aChar
,
118 const String
& rSet
, BOOL bIsPredefined
)
120 Name
= aExportName
= rName
;
123 Face
.SetTransparent(TRUE
);
124 Face
.SetAlign(ALIGN_BASELINE
);
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;
139 bPredefined
= bIsPredefined
;
147 SmSym
& SmSym::operator = (const SmSym
& rSymbol
)
151 Character
= rSymbol
.Character
;
152 aSetName
= rSymbol
.aSetName
;
153 bPredefined
= rSymbol
.bPredefined
;
154 bDocSymbol
= rSymbol
.bDocSymbol
;
155 aExportName
= rSymbol
.aExportName
;
160 pSymSetManager
->SetModified(TRUE
);
165 /**************************************************************************/
167 SmSymSet::SmSymSet() :
168 Name(C2S("unknown")),
174 SmSymSet::SmSymSet(const SmSymSet
& rSymbolSet
)
180 SmSymSet::SmSymSet(const String
& rName
)
188 SmSymSet::~SmSymSet()
190 for (USHORT i
= 0; i
< GetCount(); i
++)
191 delete SymbolList
.GetObject(i
);
194 SmSymSet
& SmSymSet::operator = (const SmSymSet
& rSymbolSet
)
197 for (i
= 0; i
< GetCount(); i
++)
198 delete SymbolList
.GetObject(i
);
200 Name
= rSymbolSet
.Name
;
202 for (i
= 0; i
< rSymbolSet
.GetCount(); i
++)
203 AddSymbol(new SmSym(rSymbolSet
.GetSymbol(i
)));
206 pSymSetManager
->SetModified(TRUE
);
211 USHORT
SmSymSet::AddSymbol(SmSym
* pSymbol
)
213 DBG_ASSERT(pSymbol
, "Kein Symbol");
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");
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
);
240 pSymSetManager
->SetModified(TRUE
);
245 USHORT
SmSymSet::GetSymbolPos(const String
& rName
)
247 for (USHORT i
= 0; i
< GetCount(); i
++)
248 if (SymbolList
.GetObject(i
)->GetName() == rName
)
254 /**************************************************************************/
256 SmSymSetManager_Impl::SmSymSetManager_Impl(
257 SmSymSetManager
&rMgr
, USHORT HashTableSize
) :
262 NoHashEntries
= HashTableSize
;
263 HashEntries
= new SmSym
*[NoHashEntries
];
264 memset( HashEntries
, 0, sizeof(SmSym
*) * NoHashEntries
);
269 SmSymSetManager_Impl::~SmSymSetManager_Impl()
271 for (USHORT i
= 0; i
< NoSymbolSets
; ++i
)
272 delete SymbolSets
.Get(i
);
278 delete[] HashEntries
;
286 SmSymSetManager_Impl
& SmSymSetManager_Impl::operator = ( const SmSymSetManager_Impl
&rImpl
)
288 //! rMySymSetMgr remains unchanged
290 NoHashEntries
= rImpl
.NoHashEntries
;
292 delete [] HashEntries
;
293 HashEntries
= new SmSym
*[NoHashEntries
];
294 memset( HashEntries
, 0, sizeof(SmSym
*) * NoHashEntries
);
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" );
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
)
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
;
334 SmSym
*p
= pImpl
->HashEntries
[j
];
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
) :
383 pImpl
= new SmSymSetManager_Impl( *this, rSymbolSetManager
.pImpl
->NoHashEntries
);
384 *pImpl
= *rSymbolSetManager
.pImpl
;
388 SmSymSetManager::~SmSymSetManager()
394 SmSymSetManager
& SmSymSetManager::operator = (const SmSymSetManager
& rSymbolSetManager
)
396 *pImpl
= *rSymbolSetManager
.pImpl
;
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;
413 pImpl
->Modified
= TRUE
;
415 return (USHORT
) (pImpl
->NoSymbolSets
- 1);
418 void SmSymSetManager::ChangeSymbolSet(SmSymSet
* pSymbolSet
)
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));
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
)
447 return SYMBOLSET_NONE
;
450 SmSym
*SmSymSetManager::GetSymbolByName(const String
& rSymbolName
)
452 SmSym
*pSym
= pImpl
->HashEntries
[GetHashIndex(rSymbolName
)];
455 if (pSym
->Name
== rSymbolName
)
457 pSym
= pSym
->pHashNext
;
464 void SmSymSetManager::AddReplaceSymbol( const SmSym
&rSymbol
)
466 SmSym
*pSym
= GetSymbolByName( rSymbol
.GetName() );
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
);
488 USHORT
SmSymSetManager::GetSymbolCount() const
491 USHORT nSets
= GetSymbolSetCount();
492 for (USHORT i
= 0; i
< nSets
; ++i
)
493 nRes
= nRes
+ GetSymbolSet(i
)->GetCount();
498 const SmSym
* SmSymSetManager::GetSymbolByPos( USHORT nPos
) const
500 const SmSym
*pRes
= 0;
503 USHORT nSets
= GetSymbolSetCount();
505 while (i
< nSets
&& !pRes
)
507 USHORT nEntries
= GetSymbolSet(i
)->GetCount();
508 if (nPos
< nIdx
+ nEntries
)
509 pRes
= &GetSymbolSet(i
)->GetSymbol( nPos
- nIdx
);
511 nIdx
= nIdx
+ nEntries
;
519 void SmSymSetManager::GetSymbols( std::vector
< SmSym
> &rSymbols
) const
521 INT32 nCount
= GetSymbolCount();
522 rSymbols
.resize( nCount
);
524 std::vector
< SmSym
>::iterator
aIt( rSymbols
.begin() );
525 std::vector
< SmSym
>::iterator
aEnd( rSymbols
.end() );
528 const SmSym
*pSym
= GetSymbolByPos( nPos
++ );
529 DBG_ASSERT( pSym
, "symbol missing" );
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();
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
);
558 pSymSet
= new SmSymSet( rSetName
);
559 AddSymbolSet( pSymSet
);
562 pSymSet
->AddSymbol( new SmSym( rSym
) );
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();
585 for (i
= 0; i
< nSetCount
; ++i
)
586 nSymbolCount
= nSymbolCount
+ GetSymbolSet( i
)->GetCount();
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())
607 DBG_ASSERT(pSym
- pSymbols
== nSaveSymbolCnt
, "wrong number of symbols" );
609 std::vector
< SmSym
> aSymbols
;
610 GetSymbols( aSymbols
);
611 rCfg
.SetSymbols( aSymbols
);