1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_starmath.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir 32*cdf0e10cSrcweir #include <vector> 33*cdf0e10cSrcweir #include <osl/mutex.hxx> 34*cdf0e10cSrcweir #include <ucbhelper/content.hxx> 35*cdf0e10cSrcweir #include <vcl/msgbox.hxx> 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir #include <sfx2/dispatch.hxx> 38*cdf0e10cSrcweir #include <sfx2/docfile.hxx> 39*cdf0e10cSrcweir 40*cdf0e10cSrcweir #include <map> 41*cdf0e10cSrcweir #include <vector> 42*cdf0e10cSrcweir #include <iterator> 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir #include "symbol.hxx" 45*cdf0e10cSrcweir #include "view.hxx" 46*cdf0e10cSrcweir #include "utility.hxx" 47*cdf0e10cSrcweir #include "dialog.hxx" 48*cdf0e10cSrcweir #include "config.hxx" 49*cdf0e10cSrcweir #include "cfgitem.hxx" 50*cdf0e10cSrcweir #include "smmod.hxx" 51*cdf0e10cSrcweir #include "starmath.hrc" 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir using namespace ::com::sun::star; 55*cdf0e10cSrcweir using namespace ::com::sun::star::ucb; 56*cdf0e10cSrcweir using namespace ::com::sun::star::uno; 57*cdf0e10cSrcweir using namespace ::rtl; 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir /**************************************************************************/ 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir SmSym::SmSym() : 63*cdf0e10cSrcweir m_aName(C2S("unknown")), 64*cdf0e10cSrcweir m_aSetName(C2S("unknown")), 65*cdf0e10cSrcweir m_cChar('\0'), 66*cdf0e10cSrcweir m_bPredefined(sal_False), 67*cdf0e10cSrcweir m_bDocSymbol(sal_False) 68*cdf0e10cSrcweir { 69*cdf0e10cSrcweir m_aExportName = m_aName; 70*cdf0e10cSrcweir m_aFace.SetTransparent(sal_True); 71*cdf0e10cSrcweir m_aFace.SetAlign(ALIGN_BASELINE); 72*cdf0e10cSrcweir } 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir SmSym::SmSym(const SmSym& rSymbol) 76*cdf0e10cSrcweir { 77*cdf0e10cSrcweir *this = rSymbol; 78*cdf0e10cSrcweir } 79*cdf0e10cSrcweir 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir SmSym::SmSym(const String& rName, const Font& rFont, sal_UCS4 cChar, 82*cdf0e10cSrcweir const String& rSet, sal_Bool bIsPredefined) 83*cdf0e10cSrcweir { 84*cdf0e10cSrcweir m_aName = m_aExportName = rName; 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir m_aFace = rFont; 87*cdf0e10cSrcweir m_aFace.SetTransparent(sal_True); 88*cdf0e10cSrcweir m_aFace.SetAlign(ALIGN_BASELINE); 89*cdf0e10cSrcweir 90*cdf0e10cSrcweir m_cChar = cChar; 91*cdf0e10cSrcweir //! according to HDU this should not be used anymore now 92*cdf0e10cSrcweir //! since this was necessary in the early days but should 93*cdf0e10cSrcweir //! not be done now since this is handled now at a more 94*cdf0e10cSrcweir //! bottom layer by HDU. 95*cdf0e10cSrcweir //! He can still imagine scenarios where this will be wrong 96*cdf0e10cSrcweir //! now though, for example when importing *some* old documents. 97*cdf0e10cSrcweir //! But overall it should be a large improvement, and 98*cdf0e10cSrcweir //! likely everything will still work... #_- (eyes shut and "go"!) 99*cdf0e10cSrcweir // 100*cdf0e10cSrcweir // if (RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet()) 101*cdf0e10cSrcweir // Character |= 0xF000; 102*cdf0e10cSrcweir m_aSetName = rSet; 103*cdf0e10cSrcweir m_bPredefined = bIsPredefined; 104*cdf0e10cSrcweir m_bDocSymbol = sal_False; 105*cdf0e10cSrcweir } 106*cdf0e10cSrcweir 107*cdf0e10cSrcweir 108*cdf0e10cSrcweir SmSym& SmSym::operator = (const SmSym& rSymbol) 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir m_aName = rSymbol.m_aName; 111*cdf0e10cSrcweir m_aExportName = rSymbol.m_aExportName; 112*cdf0e10cSrcweir m_cChar = rSymbol.m_cChar; 113*cdf0e10cSrcweir m_aFace = rSymbol.m_aFace; 114*cdf0e10cSrcweir m_aSetName = rSymbol.m_aSetName; 115*cdf0e10cSrcweir m_bPredefined = rSymbol.m_bPredefined; 116*cdf0e10cSrcweir m_bDocSymbol = rSymbol.m_bDocSymbol; 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir SmSymbolManager * pSymSetManager = &SM_MOD()->GetSymbolManager(); 119*cdf0e10cSrcweir if (pSymSetManager) 120*cdf0e10cSrcweir pSymSetManager->SetModified(true); 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir return *this; 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir bool SmSym::IsEqualInUI( const SmSym& rSymbol ) const 127*cdf0e10cSrcweir { 128*cdf0e10cSrcweir return m_aName == rSymbol.m_aName && 129*cdf0e10cSrcweir m_aFace == rSymbol.m_aFace && 130*cdf0e10cSrcweir m_cChar == rSymbol.m_cChar; 131*cdf0e10cSrcweir } 132*cdf0e10cSrcweir 133*cdf0e10cSrcweir /**************************************************************************/ 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir void SmSymbolManager::SFX_NOTIFY(SfxBroadcaster& /*rBC*/, const TypeId& rBCType, 136*cdf0e10cSrcweir const SfxHint& /*rHint*/, const TypeId& rHintType) 137*cdf0e10cSrcweir { 138*cdf0e10cSrcweir } 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir void SmSymbolManager::Init() 142*cdf0e10cSrcweir { 143*cdf0e10cSrcweir SmModule *pp = SM_MOD(); 144*cdf0e10cSrcweir StartListening(*pp->GetConfig()); 145*cdf0e10cSrcweir } 146*cdf0e10cSrcweir 147*cdf0e10cSrcweir 148*cdf0e10cSrcweir void SmSymbolManager::Exit() 149*cdf0e10cSrcweir { 150*cdf0e10cSrcweir SmModule *pp = SM_MOD(); 151*cdf0e10cSrcweir EndListening(*pp->GetConfig()); 152*cdf0e10cSrcweir } 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir 155*cdf0e10cSrcweir SmSymbolManager::SmSymbolManager() 156*cdf0e10cSrcweir { 157*cdf0e10cSrcweir m_bModified = false; 158*cdf0e10cSrcweir } 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir SmSymbolManager::SmSymbolManager(const SmSymbolManager& rSymbolSetManager) : 162*cdf0e10cSrcweir SfxListener() 163*cdf0e10cSrcweir { 164*cdf0e10cSrcweir m_aSymbols = rSymbolSetManager.m_aSymbols; 165*cdf0e10cSrcweir m_bModified = true; 166*cdf0e10cSrcweir } 167*cdf0e10cSrcweir 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir SmSymbolManager::~SmSymbolManager() 170*cdf0e10cSrcweir { 171*cdf0e10cSrcweir } 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir 174*cdf0e10cSrcweir SmSymbolManager& SmSymbolManager::operator = (const SmSymbolManager& rSymbolSetManager) 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir m_aSymbols = rSymbolSetManager.m_aSymbols; 177*cdf0e10cSrcweir m_bModified = true; 178*cdf0e10cSrcweir return *this; 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir SmSym *SmSymbolManager::GetSymbolByName(const String& rSymbolName) 183*cdf0e10cSrcweir { 184*cdf0e10cSrcweir SmSym *pRes = NULL; 185*cdf0e10cSrcweir SymbolMap_t::iterator aIt( m_aSymbols.find( rSymbolName ) ); 186*cdf0e10cSrcweir if (aIt != m_aSymbols.end()) 187*cdf0e10cSrcweir pRes = &aIt->second; 188*cdf0e10cSrcweir return pRes; 189*cdf0e10cSrcweir } 190*cdf0e10cSrcweir 191*cdf0e10cSrcweir 192*cdf0e10cSrcweir const SymbolPtrVec_t SmSymbolManager::GetSymbols() const 193*cdf0e10cSrcweir { 194*cdf0e10cSrcweir SymbolPtrVec_t aRes; 195*cdf0e10cSrcweir SymbolMap_t::const_iterator aIt( m_aSymbols.begin() ); 196*cdf0e10cSrcweir for ( ; aIt != m_aSymbols.end(); ++aIt) 197*cdf0e10cSrcweir aRes.push_back( &aIt->second ); 198*cdf0e10cSrcweir // DBG_ASSERT( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " ); 199*cdf0e10cSrcweir return aRes; 200*cdf0e10cSrcweir } 201*cdf0e10cSrcweir 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir bool SmSymbolManager::AddOrReplaceSymbol( const SmSym &rSymbol, bool bForceChange ) 204*cdf0e10cSrcweir { 205*cdf0e10cSrcweir bool bAdded = false; 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir const String aSymbolName( rSymbol.GetName() ); 208*cdf0e10cSrcweir if (aSymbolName.Len() > 0 && rSymbol.GetSymbolSetName().Len() > 0) 209*cdf0e10cSrcweir { 210*cdf0e10cSrcweir const SmSym *pFound = GetSymbolByName( aSymbolName ); 211*cdf0e10cSrcweir const bool bSymbolConflict = pFound && !pFound->IsEqualInUI( rSymbol ); 212*cdf0e10cSrcweir 213*cdf0e10cSrcweir // avoid having the same symbol name twice but with different symbols in use 214*cdf0e10cSrcweir if (!pFound || bForceChange) 215*cdf0e10cSrcweir { 216*cdf0e10cSrcweir m_aSymbols[ aSymbolName ] = rSymbol; 217*cdf0e10cSrcweir bAdded = true; 218*cdf0e10cSrcweir } 219*cdf0e10cSrcweir else if (pFound && !bForceChange && bSymbolConflict) 220*cdf0e10cSrcweir { 221*cdf0e10cSrcweir // TODO: to solve this a document owned symbol manager would be required ... 222*cdf0e10cSrcweir // But for now we have a global one to easily support availability of all 223*cdf0e10cSrcweir // symbols in all formulas. A copy of the global one would be needed here 224*cdf0e10cSrcweir // and then the new symbol has to be forcefully applied. This would keep 225*cdf0e10cSrcweir // the current formula intact but will leave the set of symbols in the 226*cdf0e10cSrcweir // global symbol manager somewhat to chance. 227*cdf0e10cSrcweir DBG_ASSERT( 0, "symbol conflict, different symbol with same name found!" ); 228*cdf0e10cSrcweir } 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir if (bAdded) 231*cdf0e10cSrcweir m_bModified = true; 232*cdf0e10cSrcweir DBG_ASSERT( bAdded || (pFound && !bSymbolConflict), "AddOrReplaceSymbol: unresolved symbol conflict" ); 233*cdf0e10cSrcweir } 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir return bAdded; 236*cdf0e10cSrcweir } 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir void SmSymbolManager::RemoveSymbol( const String & rSymbolName ) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir if (rSymbolName.Len() > 0) 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir size_t nOldSize = m_aSymbols.size(); 244*cdf0e10cSrcweir m_aSymbols.erase( rSymbolName ); 245*cdf0e10cSrcweir m_bModified = nOldSize != m_aSymbols.size(); 246*cdf0e10cSrcweir } 247*cdf0e10cSrcweir } 248*cdf0e10cSrcweir 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir std::set< String > SmSymbolManager::GetSymbolSetNames() const 251*cdf0e10cSrcweir { 252*cdf0e10cSrcweir std::set< String > aRes; 253*cdf0e10cSrcweir SymbolMap_t::const_iterator aIt( m_aSymbols.begin() ); 254*cdf0e10cSrcweir for ( ; aIt != m_aSymbols.end(); ++aIt ) 255*cdf0e10cSrcweir aRes.insert( aIt->second.GetSymbolSetName() ); 256*cdf0e10cSrcweir return aRes; 257*cdf0e10cSrcweir } 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir const SymbolPtrVec_t SmSymbolManager::GetSymbolSet( const String& rSymbolSetName ) 261*cdf0e10cSrcweir { 262*cdf0e10cSrcweir SymbolPtrVec_t aRes; 263*cdf0e10cSrcweir if (rSymbolSetName.Len() > 0) 264*cdf0e10cSrcweir { 265*cdf0e10cSrcweir SymbolMap_t::const_iterator aIt( m_aSymbols.begin() ); 266*cdf0e10cSrcweir for ( ; aIt != m_aSymbols.end(); ++aIt ) 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir if (aIt->second.GetSymbolSetName() == rSymbolSetName) 269*cdf0e10cSrcweir aRes.push_back( &aIt->second ); 270*cdf0e10cSrcweir } 271*cdf0e10cSrcweir } 272*cdf0e10cSrcweir return aRes; 273*cdf0e10cSrcweir } 274*cdf0e10cSrcweir 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir void SmSymbolManager::Load() 277*cdf0e10cSrcweir { 278*cdf0e10cSrcweir std::vector< SmSym > aSymbols; 279*cdf0e10cSrcweir SmMathConfig &rCfg = *SM_MOD()->GetConfig(); 280*cdf0e10cSrcweir rCfg.GetSymbols( aSymbols ); 281*cdf0e10cSrcweir size_t nSymbolCount = aSymbols.size(); 282*cdf0e10cSrcweir 283*cdf0e10cSrcweir m_aSymbols.clear(); 284*cdf0e10cSrcweir for (size_t i = 0; i < nSymbolCount; ++i) 285*cdf0e10cSrcweir { 286*cdf0e10cSrcweir const SmSym &rSym = aSymbols[i]; 287*cdf0e10cSrcweir DBG_ASSERT( rSym.GetName().Len() > 0, "symbol without name!" ); 288*cdf0e10cSrcweir if (rSym.GetName().Len() > 0) 289*cdf0e10cSrcweir AddOrReplaceSymbol( rSym ); 290*cdf0e10cSrcweir } 291*cdf0e10cSrcweir m_bModified = true; 292*cdf0e10cSrcweir 293*cdf0e10cSrcweir if (0 == nSymbolCount) 294*cdf0e10cSrcweir { 295*cdf0e10cSrcweir DBG_ERROR( "no symbol set found" ); 296*cdf0e10cSrcweir m_bModified = false; 297*cdf0e10cSrcweir } 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir // now add a %i... symbol to the 'iGreek' set for every symbol found in the 'Greek' set. 300*cdf0e10cSrcweir SmLocalizedSymbolData aLocalizedData; 301*cdf0e10cSrcweir const String aGreekSymbolSetName( aLocalizedData.GetUiSymbolSetName( A2OU("Greek") ) ); 302*cdf0e10cSrcweir const SymbolPtrVec_t aGreekSymbols( GetSymbolSet( aGreekSymbolSetName ) ); 303*cdf0e10cSrcweir String aSymbolSetName( (sal_Unicode) 'i' ); 304*cdf0e10cSrcweir aSymbolSetName += aGreekSymbolSetName; 305*cdf0e10cSrcweir size_t nSymbols = aGreekSymbols.size(); 306*cdf0e10cSrcweir for (size_t i = 0; i < nSymbols; ++i) 307*cdf0e10cSrcweir { 308*cdf0e10cSrcweir // make the new symbol a copy but with ITALIC_NORMAL, and add it to iGreek 309*cdf0e10cSrcweir const SmSym &rSym = *aGreekSymbols[i]; 310*cdf0e10cSrcweir Font aFont( rSym.GetFace() ); 311*cdf0e10cSrcweir DBG_ASSERT( aFont.GetItalic() == ITALIC_NONE, "expected Font with ITALIC_NONE, failed." ); 312*cdf0e10cSrcweir aFont.SetItalic( ITALIC_NORMAL ); 313*cdf0e10cSrcweir String aSymbolName( (sal_Unicode)'i' ); 314*cdf0e10cSrcweir aSymbolName += rSym.GetName(); 315*cdf0e10cSrcweir SmSym aSymbol( aSymbolName, aFont, rSym.GetCharacter(), 316*cdf0e10cSrcweir aSymbolSetName, sal_True /*bIsPredefined*/ ); 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir AddOrReplaceSymbol( aSymbol ); 319*cdf0e10cSrcweir } 320*cdf0e10cSrcweir } 321*cdf0e10cSrcweir 322*cdf0e10cSrcweir void SmSymbolManager::Save() 323*cdf0e10cSrcweir { 324*cdf0e10cSrcweir if (m_bModified) 325*cdf0e10cSrcweir { 326*cdf0e10cSrcweir SmMathConfig &rCfg = *SM_MOD()->GetConfig(); 327*cdf0e10cSrcweir 328*cdf0e10cSrcweir #if 0 329*cdf0e10cSrcweir sal_uInt16 nSymbolCount = GetSymbolCount(); 330*cdf0e10cSrcweir sal_uInt16 nSaveSymbolCnt = 0; 331*cdf0e10cSrcweir const SmSym **pSymbols = new const SmSym* [ nSymbolCount ]; 332*cdf0e10cSrcweir const SmSym **pSym = pSymbols; 333*cdf0e10cSrcweir for (sal_uInt16 j = 0; j < nSymbolCount; ++j) 334*cdf0e10cSrcweir { 335*cdf0e10cSrcweir const SmSym &rSym = *pSymSet->GetSymbol( j ); 336*cdf0e10cSrcweir if (!rSym.IsDocSymbol()) 337*cdf0e10cSrcweir { 338*cdf0e10cSrcweir *pSym++ = &rSym; 339*cdf0e10cSrcweir ++nSaveSymbolCnt; 340*cdf0e10cSrcweir } 341*cdf0e10cSrcweir } 342*cdf0e10cSrcweir DBG_ASSERT(pSym - pSymbols == nSaveSymbolCnt, "wrong number of symbols" ); 343*cdf0e10cSrcweir #endif 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir // prepare to skip symbols from iGreek on saving 346*cdf0e10cSrcweir SmLocalizedSymbolData aLocalizedData; 347*cdf0e10cSrcweir String aSymbolSetName( (sal_Unicode) 'i' ); 348*cdf0e10cSrcweir aSymbolSetName += aLocalizedData.GetUiSymbolSetName( A2OU("Greek") ); 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir SymbolPtrVec_t aTmp( GetSymbols() ); 351*cdf0e10cSrcweir std::vector< SmSym > aSymbols; 352*cdf0e10cSrcweir for (size_t i = 0; i < aTmp.size(); ++i) 353*cdf0e10cSrcweir { 354*cdf0e10cSrcweir // skip symbols from iGreek set since those symbols always get added 355*cdf0e10cSrcweir // by computational means in SmSymbolManager::Load 356*cdf0e10cSrcweir if (aTmp[i]->GetSymbolSetName() != aSymbolSetName) 357*cdf0e10cSrcweir aSymbols.push_back( *aTmp[i] ); 358*cdf0e10cSrcweir } 359*cdf0e10cSrcweir rCfg.SetSymbols( aSymbols ); 360*cdf0e10cSrcweir #if 0 361*cdf0e10cSrcweir delete [] pSymbols; 362*cdf0e10cSrcweir #endif 363*cdf0e10cSrcweir 364*cdf0e10cSrcweir m_bModified = false; 365*cdf0e10cSrcweir } 366*cdf0e10cSrcweir } 367*cdf0e10cSrcweir 368*cdf0e10cSrcweir 369