/************************************************************************* * * $RCSfile: symbol.cxx,v $ * * $Revision: 1.18 $ * * last change: $Author: tl $ $Date: 2001-10-02 12:58:24 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #pragma hdrstop #ifndef _OSL_MUTEX_HXX_ #include #endif #ifndef _UCBHELPER_CONTENT_HXX #include #endif #ifndef _SV_MSGBOX_HXX //autogen #include #endif #ifndef _SV_RESARY_HXX #include #endif #ifndef _SFXDISPATCH_HXX //autogen #include #endif #ifndef _SFXDOCFILE_HXX #include #endif #include "symbol.hxx" #include "view.hxx" #include "utility.hxx" #include "dialog.hxx" #include "config.hxx" #include "cfgitem.hxx" #include "smmod.hxx" #include "starmath.hrc" using namespace ::com::sun::star; using namespace ::com::sun::star::ucb; using namespace ::com::sun::star::uno; using namespace ::rtl; // Das hier muss auch mal alles "uberarbeitet werden. Insbesondere die nicht // funktionierende und bei l"oschen/"andern von Symbolen nicht gepflegte // Hash Tabelle!!! Diese aktualisert sich erst im Wertzuweisungsoperator // beim Verlassen des 'SmSymDefineDialog's! /**************************************************************************/ /* ** ** MACRO DEFINTION ** **/ #define SF_SM20IDENT 0x03031963L #define SF_IDENT 0x30334D53L SV_IMPL_PTRARR( SymbolArray, SmSym * ); /**************************************************************************/ /* ** ** DATA DEFINITION ** **/ long SF_Ident = SF_IDENT; /**************************************************************************/ /* ** ** CLASS IMPLEMENTATION ** **/ SmSym::SmSym() : Name(C2S("unknown")), Character('\0'), pHashNext(0), pSymSetManager(0), bPredefined(FALSE), bDocSymbol(FALSE), aSetName(C2S("unknown")) { aExportName = Name; Face.SetTransparent(TRUE); } SmSym::SmSym(const SmSym& rSymbol) { pSymSetManager = 0; *this = rSymbol; } SmSym::SmSym(const String& rName, const Font& rFont, sal_Unicode aChar, const String& rSet, BOOL bIsPredefined) { Name = aExportName = rName; Face = rFont; Character = aChar; if (RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet()) Character |= 0xF000; aSetName = rSet; bPredefined = bIsPredefined; bDocSymbol = FALSE; pHashNext = 0; pSymSetManager = 0; } SmSym& SmSym::operator = (const SmSym& rSymbol) { Name = rSymbol.Name; Face = rSymbol.Face; Character = rSymbol.Character; aSetName = rSymbol.aSetName; bPredefined = rSymbol.bPredefined; bDocSymbol = rSymbol.bDocSymbol; aExportName = rSymbol.aExportName; pHashNext = 0; if (pSymSetManager) pSymSetManager->SetModified(TRUE); return *this; } void SmSym::SetSymbolName(const String& rName) { Name = rName; if (pSymSetManager) pSymSetManager->SetModified(TRUE); } SvStream& operator << (SvStream& rStream, const SmSym& rSymbol) { rStream.WriteByteString( ExportString(rSymbol.Name) ); rStream << rSymbol.Face; rtl_TextEncoding eEnc = rSymbol.Face.GetCharSet(); if (RTL_TEXTENCODING_DONTKNOW == eEnc) eEnc = RTL_TEXTENCODING_SYMBOL; rStream << ByteString::ConvertFromUnicode( rSymbol.Character, eEnc ); return rStream; } SvStream& operator >> (SvStream& rStream, SmSym& rSymbol) { ByteString aByteStr; rStream.ReadByteString( aByteStr ); rSymbol.Name = ImportString( aByteStr ); if (SF_Ident == SF_SM20IDENT) ReadSM20Font(rStream, rSymbol.Face); else rStream >> rSymbol.Face; sal_Char cTemp; rStream >> cTemp; rtl_TextEncoding eEnc = rSymbol.Face.GetCharSet(); if (RTL_TEXTENCODING_DONTKNOW == eEnc) eEnc = RTL_TEXTENCODING_SYMBOL; rSymbol.Character = ByteString::ConvertToUnicode( cTemp, eEnc ); return rStream; } /**************************************************************************/ SmSymSet::SmSymSet() : Name(C2S("unknown")), pSymSetManager(0) { SymbolList.Clear(); } SmSymSet::SmSymSet(const SmSymSet& rSymbolSet) { pSymSetManager = 0; *this = rSymbolSet; } SmSymSet::SmSymSet(const String& rName) { Name = rName; SymbolList.Clear(); pSymSetManager = 0; } SmSymSet::~SmSymSet() { for (int i = 0; i < GetCount(); i++) delete SymbolList.GetObject(i); } SmSymSet& SmSymSet::operator = (const SmSymSet& rSymbolSet) { int i; for (i = 0; i < GetCount(); i++) delete SymbolList.GetObject(i); Name = rSymbolSet.Name; SymbolList.Clear(); for (i = 0; i < rSymbolSet.GetCount(); i++) AddSymbol(new SmSym(rSymbolSet.GetSymbol(i))); if (pSymSetManager) pSymSetManager->SetModified(TRUE); return *this; } void SmSymSet::SetName(String& rName) { Name = rName; if (pSymSetManager) pSymSetManager->SetModified(TRUE); } USHORT SmSymSet::AddSymbol(SmSym* pSymbol) { DBG_ASSERT(pSymbol, "Kein Symbol"); if (pSymbol) pSymbol->SetSetName( GetName() ); SymbolList.Insert(pSymbol, LIST_APPEND); DBG_ASSERT(SymbolList.GetPos(pSymbol) == SymbolList.Count() - 1, "Sm : ... ergibt falschen return Wert"); if (pSymSetManager) pSymSetManager->SetModified(TRUE); return (USHORT) SymbolList.Count() - 1; } void SmSymSet::DeleteSymbol(USHORT SymbolNo) { delete RemoveSymbol(SymbolNo); } SmSym * SmSymSet::RemoveSymbol(USHORT SymbolNo) { DBG_ASSERT(SymbolList.GetObject(SymbolNo), "Symbol nicht vorhanden"); SmSym *pSym = SymbolList.GetObject(SymbolNo); SymbolList.Remove(SymbolNo); if (pSymSetManager) pSymSetManager->SetModified(TRUE); return pSym; } USHORT SmSymSet::GetSymbolPos(const String& rName) { for (USHORT i = 0; i < GetCount(); i++) if (SymbolList.GetObject(i)->GetName() == rName) return (i); return SYMBOL_NONE; } SvStream& operator << (SvStream& rStream, const SmSymSet& rSymbolSet) { rStream.WriteByteString(ExportString(rSymbolSet.Name)); rStream << rSymbolSet.GetCount(); for (int i = 0; i < rSymbolSet.GetCount(); i++) rStream << rSymbolSet.GetSymbol(i); return rStream; } SvStream& operator >> (SvStream& rStream, SmSymSet& rSymbolSet) { USHORT n; SmSym *pSymbol; ByteString aByteStr; rStream.ReadByteString( aByteStr ); rSymbolSet.Name = ImportString( aByteStr ); rStream >> n; for (int i = 0; i < n; i++) { if ((pSymbol = new SmSym) == 0) break; rStream >> *pSymbol; rSymbolSet.AddSymbol(pSymbol); } return rStream; } /**************************************************************************/ SmSymSetManager_Impl::SmSymSetManager_Impl( SmSymSetManager &rMgr, USHORT HashTableSize ) : rSymSetMgr (rMgr) { NoSymbolSets = 0; NoHashEntries = HashTableSize; HashEntries = new SmSym *[NoHashEntries]; memset( HashEntries, 0, sizeof(SmSym *) * NoHashEntries ); Modified = FALSE; } SmSymSetManager_Impl::~SmSymSetManager_Impl() { for (USHORT i = 0; i < NoSymbolSets; ++i) delete SymbolSets.Get(i); SymbolSets.Clear(); NoSymbolSets = 0; if (HashEntries) { delete[] HashEntries; HashEntries = 0; } NoHashEntries = 0; Modified = FALSE; } SmSymSetManager_Impl & SmSymSetManager_Impl::operator = ( const SmSymSetManager_Impl &rImpl ) { //! rMySymSetMgr remains unchanged NoHashEntries = rImpl.NoHashEntries; if (HashEntries) delete [] HashEntries; HashEntries = new SmSym *[NoHashEntries]; memset( HashEntries, 0, sizeof(SmSym *) * NoHashEntries ); NoSymbolSets = 0; SymbolSets.Clear(); for (USHORT i = 0; i < rImpl.NoSymbolSets; ++i) { rSymSetMgr.AddSymbolSet( new SmSymSet( *rImpl.rSymSetMgr.GetSymbolSet(i) ) ); } DBG_ASSERT( NoSymbolSets == rImpl.NoSymbolSets, "incorrect number of symbolsets" ); Modified = TRUE; return *this; } /**************************************************************************/ static osl::Mutex & lcl_GetSymSetMgrMutex() { static osl::Mutex aMutex; return aMutex; } void SmSymSetManager::SFX_NOTIFY(SfxBroadcaster& rBC, const TypeId& rBCType, const SfxHint& rHint, const TypeId& rHintType) { } UINT32 SmSymSetManager::GetHashIndex(const String& rSymbolName) { UINT32 x = 1; for (xub_StrLen i = 0; i < rSymbolName.Len(); i++) x += x * rSymbolName.GetChar(i) + i; return x % pImpl->NoHashEntries; } void SmSymSetManager::EnterHashTable(SmSym& rSymbol) { int j = GetHashIndex( rSymbol.GetName() ); if (pImpl->HashEntries[j] == 0) pImpl->HashEntries[j] = &rSymbol; else { SmSym *p = pImpl->HashEntries[j]; while (p->pHashNext) p = p->pHashNext; p->pHashNext = &rSymbol; } rSymbol.pHashNext = 0; } void SmSymSetManager::EnterHashTable(SmSymSet& rSymbolSet) { for (int i = 0; i < rSymbolSet.GetCount(); i++) EnterHashTable( *rSymbolSet.SymbolList.GetObject(i) ); } void SmSymSetManager::FillHashTable() { if (pImpl->HashEntries) { memset( pImpl->HashEntries, 0, pImpl->NoHashEntries * sizeof(SmSym *) ); for (UINT32 i = 0; i < pImpl->NoSymbolSets; i++) EnterHashTable( *GetSymbolSet( (USHORT) i ) ); } } void SmSymSetManager::Init() { SmModule *pp = SM_MOD1(); StartListening(*pp->GetConfig()); } void SmSymSetManager::Exit() { SmModule *pp = SM_MOD1(); EndListening(*pp->GetConfig()); } SmSymSetManager::SmSymSetManager(USHORT HashTableSize) { pImpl = new SmSymSetManager_Impl( *this, HashTableSize ); } SmSymSetManager::SmSymSetManager(const SmSymSetManager& rSymbolSetManager) { pImpl = new SmSymSetManager_Impl( *this, rSymbolSetManager.pImpl->NoHashEntries ); *pImpl = *rSymbolSetManager.pImpl; } SmSymSetManager::~SmSymSetManager() { delete pImpl; pImpl = 0; } SmSymSetManager& SmSymSetManager::operator = (const SmSymSetManager& rSymbolSetManager) { *pImpl = *rSymbolSetManager.pImpl; return *this; } USHORT SmSymSetManager::AddSymbolSet(SmSymSet* pSymbolSet) { if (pImpl->NoSymbolSets >= pImpl->SymbolSets.GetSize()) pImpl->SymbolSets.SetSize(pImpl->NoSymbolSets + 1); pImpl->SymbolSets.Put(pImpl->NoSymbolSets++, pSymbolSet); pSymbolSet->pSymSetManager = this; for (int i = 0; i < pSymbolSet->GetCount(); i++) pSymbolSet->SymbolList.GetObject(i)->pSymSetManager = this; FillHashTable(); pImpl->Modified = TRUE; return (USHORT) (pImpl->NoSymbolSets - 1); } void SmSymSetManager::ChangeSymbolSet(SmSymSet* pSymbolSet) { if (pSymbolSet) { FillHashTable(); pImpl->Modified = TRUE; } } void SmSymSetManager::DeleteSymbolSet(USHORT SymbolSetNo) { delete pImpl->SymbolSets.Get(SymbolSetNo); pImpl->NoSymbolSets--; for (UINT32 i = SymbolSetNo; i < pImpl->NoSymbolSets; i++) pImpl->SymbolSets.Put(i, pImpl->SymbolSets.Get(i + 1)); FillHashTable(); pImpl->Modified = TRUE; } USHORT SmSymSetManager::GetSymbolSetPos(const String& rSymbolSetName) const { for (USHORT i = 0; i < pImpl->NoSymbolSets; i++) if (pImpl->SymbolSets.Get(i)->GetName() == rSymbolSetName) return (i); return SYMBOLSET_NONE; } SmSym *SmSymSetManager::GetSymbolByName(const String& rSymbolName) { SmSym *pSym = pImpl->HashEntries[GetHashIndex(rSymbolName)]; while (pSym) { if (pSym->Name == rSymbolName) break; pSym = pSym->pHashNext; } return pSym; } void SmSymSetManager::AddReplaceSymbol( const SmSym &rSymbol ) { SmSym *pSym = GetSymbolByName( rSymbol.GetName() ); if (pSym) { *pSym = rSymbol; } else { USHORT nPos = GetSymbolSetPos( rSymbol.GetSetName() ); if (SYMBOLSET_NONE == nPos) { AddSymbolSet( new SmSymSet( rSymbol.GetSetName() ) ); nPos = GetSymbolSetPos( rSymbol.GetSetName() ); } DBG_ASSERT( nPos != SYMBOLSET_NONE, "SymbolSet not found"); SmSym *pSym = new SmSym( rSymbol ); GetSymbolSet( nPos )->AddSymbol( pSym ); EnterHashTable( *pSym ); } SetModified( TRUE ); } USHORT SmSymSetManager::GetSymbolCount() const { USHORT nRes = 0; USHORT nSets = GetSymbolSetCount(); for (USHORT i = 0; i < nSets; ++i) nRes += GetSymbolSet(i)->GetCount(); return nRes; } const SmSym * SmSymSetManager::GetSymbolByPos( USHORT nPos ) const { const SmSym *pRes = 0; INT16 nIdx = 0; USHORT nSets = GetSymbolSetCount(); USHORT i = 0; while (i < nSets && !pRes) { USHORT nEntries = GetSymbolSet(i)->GetCount(); if (nPos < nIdx + nEntries) pRes = &GetSymbolSet(i)->GetSymbol( nPos - nIdx ); else nIdx += nEntries; ++i; } return pRes; } void SmSymSetManager::Load() { SmMathConfig &rCfg = *SM_MOD1()->GetConfig(); USHORT nCount = rCfg.GetSymbolCount(); USHORT i; for (i = 0; i < nCount; ++i) { const SmSym *pSym = rCfg.GetSymbol(i); if (pSym) { SmSymSet *pSymSet = 0; const String &rSetName = pSym->GetSetName(); USHORT nSetPos = GetSymbolSetPos( rSetName ); if (SYMBOLSET_NONE != nSetPos) pSymSet = GetSymbolSet( nSetPos ); else { pSymSet = new SmSymSet( rSetName ); AddSymbolSet( pSymSet ); } pSymSet->AddSymbol( new SmSym( *pSym ) ); } } // build HashTables nCount = GetSymbolSetCount(); for (i = 0; i < nCount; ++i) ChangeSymbolSet( GetSymbolSet( i ) ); if (0 == nCount) { SmModule *pp = SM_MOD1(); if ( pp->GetConfig()->IsNoSymbolsWarning() ) { ErrorBox aErrorBox( NULL, SmResId( RID_READSYMBOLERROR ) ); aErrorBox.Execute(); pImpl->Modified = FALSE; pp->GetConfig()->SetNoSymbolsWarning(FALSE); } } } void SmSymSetManager::Save() { SmMathConfig &rCfg = *SM_MOD1()->GetConfig(); // get number of Symbols USHORT nSymbolCount = 0; USHORT nSetCount = GetSymbolSetCount(); USHORT i; for (i = 0; i < nSetCount; ++i) nSymbolCount += GetSymbolSet( i )->GetCount(); if (nSymbolCount) { USHORT nSaveSymbolCnt = 0; const SmSym **pSymbols = new const SmSym* [ nSymbolCount ]; const SmSym **pSym = pSymbols; for (i = 0; i < nSetCount; ++i) { const SmSymSet *pSymSet = GetSymbolSet( i ); USHORT n = pSymSet->GetCount(); for (USHORT j = 0; j < n; ++j) { const SmSym &rSym = pSymSet->GetSymbol( j ); if (!rSym.IsDocSymbol()) { *pSym++ = &rSym; ++nSaveSymbolCnt; } } } DBG_ASSERT(pSym - pSymbols == nSaveSymbolCnt, "wrong number of symbols" ); rCfg.ReplaceSymbols( pSymbols, nSaveSymbolCnt ); delete pSymbols; } } void ReadSM20SymSet(SvStream *pStream, SmSymSet *pSymbolSet) { SF_Ident = SF_SM20IDENT; *pStream >> *pSymbolSet; SF_Ident = SF_IDENT; }