Bump version to 5.0-14
[LibreOffice.git] / starmath / source / document.cxx
blob26e95ad24fb9a3640a1df2191b37e3a7a788b6f9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
21 #include <com/sun/star/lang/Locale.hpp>
22 #include <com/sun/star/uno/Any.h>
24 #include <comphelper/accessibletexthelper.hxx>
25 #include <comphelper/processfactory.hxx>
26 #include <comphelper/storagehelper.hxx>
27 #include <rtl/ustrbuf.hxx>
28 #include <rtl/ustring.hxx>
29 #include <unotools/eventcfg.hxx>
30 #include <sfx2/event.hxx>
31 #include <sfx2/app.hxx>
32 #include <sfx2/dispatch.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <sfx2/docfilt.hxx>
35 #include <sfx2/fcontnr.hxx>
36 #include <sfx2/msg.hxx>
37 #include <sfx2/objface.hxx>
38 #include <sfx2/printer.hxx>
39 #include <sfx2/request.hxx>
40 #include <sfx2/viewfrm.hxx>
41 #include <comphelper/classids.hxx>
42 #include <sot/exchange.hxx>
43 #include <sot/formats.hxx>
44 #include <sot/storage.hxx>
45 #include <svl/eitem.hxx>
46 #include <svl/fstathelper.hxx>
47 #include <svl/intitem.hxx>
48 #include <svl/itempool.hxx>
49 #include <unotools/lingucfg.hxx>
50 #include <unotools/linguprops.hxx>
51 #include <unotools/pathoptions.hxx>
52 #include <svl/ptitem.hxx>
53 #include <svtools/sfxecode.hxx>
54 #include <svl/slstitm.hxx>
55 #include <svl/smplhint.hxx>
56 #include <svl/stritem.hxx>
57 #include <svtools/transfer.hxx>
58 #include <svl/undo.hxx>
59 #include <svl/urihelper.hxx>
60 #include <svl/whiter.hxx>
61 #include <editeng/editeng.hxx>
62 #include <editeng/editstat.hxx>
63 #include <editeng/eeitem.hxx>
64 #include <editeng/fhgtitem.hxx>
65 #include <editeng/fontitem.hxx>
66 #include <editeng/unolingu.hxx>
67 #include <ucbhelper/content.hxx>
68 #include <vcl/mapmod.hxx>
69 #include <tools/mapunit.hxx>
70 #include <vcl/msgbox.hxx>
71 #include <vcl/settings.hxx>
73 #include <sfx2/sfx.hrc>
74 #include <document.hxx>
75 #include <action.hxx>
76 #include <config.hxx>
77 #include <dialog.hxx>
78 #include <format.hxx>
79 #include <smdll.hxx>
80 #include <starmath.hrc>
81 #include <symbol.hxx>
82 #include <unomodel.hxx>
83 #include <utility.hxx>
84 #include <view.hxx>
85 #include "mathtype.hxx"
86 #include "ooxmlexport.hxx"
87 #include "ooxmlimport.hxx"
88 #include "rtfexport.hxx"
89 #include "mathmlimport.hxx"
90 #include "mathmlexport.hxx"
91 #include <sfx2/sfxsids.hrc>
92 #include <svx/svxids.hrc>
93 #include "cursor.hxx"
94 #include <tools/diagnose_ex.h>
95 #include "visitors.hxx"
96 #include "accessibility.hxx"
97 #include <memory>
99 using namespace ::com::sun::star;
100 using namespace ::com::sun::star::accessibility;
101 using namespace ::com::sun::star::lang;
102 using namespace ::com::sun::star::ucb;
103 using namespace ::com::sun::star::uno;
105 #define SmDocShell
106 #include "smslots.hxx"
108 TYPEINIT1( SmDocShell, SfxObjectShell );
110 SFX_IMPL_SUPERCLASS_INTERFACE(SmDocShell, SfxObjectShell)
112 void SmDocShell::InitInterface_Impl()
114 GetStaticInterface()->RegisterPopupMenu(SmResId(RID_VIEWMENU));
115 GetStaticInterface()->RegisterPopupMenu(SmResId(RID_COMMANDMENU));
118 SFX_IMPL_OBJECTFACTORY(SmDocShell, SvGlobalName(SO3_SM_CLASSID), SfxObjectShellFlags::STD_NORMAL, "smath" )
120 void SmDocShell::SFX_NOTIFY(SfxBroadcaster&, const TypeId&,
121 const SfxHint& rHint, const TypeId&)
123 switch (static_cast<const SfxSimpleHint&>(rHint).GetId())
125 case HINT_FORMATCHANGED:
126 SetFormulaArranged(false);
128 nModifyCount++; //! see comment for SID_GAPHIC_SM in SmDocShell::GetState
130 Repaint();
131 break;
135 void SmDocShell::LoadSymbols()
137 SmModule *pp = SM_MOD();
138 pp->GetSymbolManager().Load();
142 const OUString SmDocShell::GetComment() const
144 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
145 GetModel(), uno::UNO_QUERY_THROW);
146 uno::Reference<document::XDocumentProperties> xDocProps(
147 xDPS->getDocumentProperties());
148 return xDocProps->getDescription();
152 void SmDocShell::SetText(const OUString& rBuffer)
154 if (rBuffer != aText)
156 bool bIsEnabled = IsEnableSetModified();
157 if( bIsEnabled )
158 EnableSetModified( false );
160 aText = rBuffer;
161 SetFormulaArranged( false );
163 Parse();
165 SmViewShell *pViewSh = SmGetActiveView();
166 if( pViewSh )
168 pViewSh->GetViewFrame()->GetBindings().Invalidate(SID_TEXT);
169 if ( SfxObjectCreateMode::EMBEDDED == GetCreateMode() )
171 // have SwOleClient::FormatChanged() to align the modified formula properly
172 // even if the vis area does not change (e.g. when formula text changes from
173 // "{a over b + c} over d" to "d over {a over b + c}"
174 SfxGetpApp()->NotifyEvent(SfxEventHint( SFX_EVENT_VISAREACHANGED, GlobalEventConfig::GetEventName(GlobalEventId::VISAREACHANGED), this));
176 Repaint();
178 else
179 pViewSh->GetGraphicWindow().Invalidate();
182 if ( bIsEnabled )
183 EnableSetModified( bIsEnabled );
184 SetModified(true);
186 // launch accessible event if necessary
187 SmGraphicAccessible *pAcc = pViewSh ? pViewSh->GetGraphicWindow().GetAccessible_Impl() : 0;
188 if (pAcc)
190 Any aOldValue, aNewValue;
191 if ( comphelper::OCommonAccessibleText::implInitTextChangedEvent( aText, rBuffer, aOldValue, aNewValue ) )
193 pAcc->LaunchEvent( AccessibleEventId::TEXT_CHANGED,
194 aOldValue, aNewValue );
198 if ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
199 OnDocumentPrinterChanged(0);
203 void SmDocShell::SetFormat(SmFormat& rFormat)
205 aFormat = rFormat;
206 SetFormulaArranged( false );
207 SetModified( true );
209 nModifyCount++; //! see comment for SID_GAPHIC_SM in SmDocShell::GetState
211 // don't use SmGetActiveView since the view shell might not be active (0 pointer)
212 // if for example the Basic Macro dialog currently has the focus. Thus:
213 SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this );
214 while (pFrm)
216 pFrm->GetBindings().Invalidate(SID_GAPHIC_SM);
217 pFrm = SfxViewFrame::GetNext( *pFrm, this );
221 OUString SmDocShell::GetAccessibleText()
223 if (!IsFormulaArranged())
224 ArrangeFormula();
225 if (aAccText.isEmpty())
227 OSL_ENSURE( pTree, "Tree missing" );
228 if (pTree)
230 OUStringBuffer aBuf;
231 pTree->GetAccessibleText(aBuf);
232 aAccText = aBuf.makeStringAndClear();
235 return aAccText;
238 void SmDocShell::Parse()
240 if (pTree)
241 delete pTree;
242 ReplaceBadChars();
243 pTree = aInterpreter.Parse(aText);
244 nModifyCount++; //! see comment for SID_GAPHIC_SM in SmDocShell::GetState
245 SetFormulaArranged( false );
246 InvalidateCursor();
247 aUsedSymbols = aInterpreter.GetUsedSymbols();
251 void SmDocShell::ArrangeFormula()
253 if (IsFormulaArranged())
254 return;
256 // Only for the duration of the existence of this object the correct settings
257 // at the printer are guaranteed!
258 SmPrinterAccess aPrtAcc(*this);
259 OutputDevice* pOutDev = aPrtAcc.GetRefDev();
261 if (!pOutDev)
263 #if OSL_DEBUG_LEVEL > 1
264 SAL_WARN( "starmath", "!! SmDocShell::ArrangeFormula: reference device missing !!");
265 #endif
268 // if necessary get another OutputDevice for which we format
269 if (!pOutDev)
271 SmViewShell *pView = SmGetActiveView();
272 if (pView)
273 pOutDev = &pView->GetGraphicWindow();
274 else
276 pOutDev = &SM_MOD()->GetDefaultVirtualDev();
277 pOutDev->SetMapMode( MapMode(MAP_100TH_MM) );
280 OSL_ENSURE(pOutDev->GetMapMode().GetMapUnit() == MAP_100TH_MM,
281 "Sm : falscher MapMode");
283 const SmFormat &rFormat = GetFormat();
284 pTree->Prepare(rFormat, *this);
286 // format/draw formulas always from left to right,
287 // and numbers should not be converted
288 ComplexTextLayoutMode nLayoutMode = pOutDev->GetLayoutMode();
289 pOutDev->SetLayoutMode( TEXT_LAYOUT_DEFAULT );
290 sal_Int16 nDigitLang = pOutDev->GetDigitLanguage();
291 pOutDev->SetDigitLanguage( LANGUAGE_ENGLISH );
293 pTree->Arrange(*pOutDev, rFormat);
295 pOutDev->SetLayoutMode( nLayoutMode );
296 pOutDev->SetDigitLanguage( nDigitLang );
298 SetFormulaArranged(true);
300 // invalidate accessible text
301 aAccText.clear();
305 void SetEditEngineDefaultFonts(SfxItemPool &rEditEngineItemPool)
308 // set fonts to be used
310 SvtLinguOptions aOpt;
311 SvtLinguConfig().GetOptions( aOpt );
313 struct FontDta {
314 sal_Int16 nFallbackLang;
315 sal_Int16 nLang;
316 DefaultFontType nFontType;
317 sal_uInt16 nFontInfoId;
318 } aTable[3] =
320 // info to get western font to be used
321 { LANGUAGE_ENGLISH_US, LANGUAGE_NONE,
322 DefaultFontType::FIXED, EE_CHAR_FONTINFO },
323 // info to get CJK font to be used
324 { LANGUAGE_JAPANESE, LANGUAGE_NONE,
325 DefaultFontType::CJK_TEXT, EE_CHAR_FONTINFO_CJK },
326 // info to get CTL font to be used
327 { LANGUAGE_ARABIC_SAUDI_ARABIA, LANGUAGE_NONE,
328 DefaultFontType::CTL_TEXT, EE_CHAR_FONTINFO_CTL }
330 aTable[0].nLang = aOpt.nDefaultLanguage;
331 aTable[1].nLang = aOpt.nDefaultLanguage_CJK;
332 aTable[2].nLang = aOpt.nDefaultLanguage_CTL;
334 for (int i = 0; i < 3; ++i)
336 const FontDta &rFntDta = aTable[i];
337 LanguageType nLang = (LANGUAGE_NONE == rFntDta.nLang) ?
338 rFntDta.nFallbackLang : rFntDta.nLang;
339 vcl::Font aFont = OutputDevice::GetDefaultFont(
340 rFntDta.nFontType, nLang, GetDefaultFontFlags::OnlyOne );
341 rEditEngineItemPool.SetPoolDefaultItem(
342 SvxFontItem( aFont.GetFamily(), aFont.GetName(),
343 aFont.GetStyleName(), aFont.GetPitch(), aFont.GetCharSet(),
344 rFntDta.nFontInfoId ) );
347 // set font heights
348 SvxFontHeightItem aFontHeigt(
349 Application::GetDefaultDevice()->LogicToPixel(
350 Size( 0, 11 ), MapMode( MAP_POINT ) ).Height(), 100,
351 EE_CHAR_FONTHEIGHT );
352 rEditEngineItemPool.SetPoolDefaultItem( aFontHeigt );
353 aFontHeigt.SetWhich( EE_CHAR_FONTHEIGHT_CJK );
354 rEditEngineItemPool.SetPoolDefaultItem( aFontHeigt );
355 aFontHeigt.SetWhich( EE_CHAR_FONTHEIGHT_CTL );
356 rEditEngineItemPool.SetPoolDefaultItem( aFontHeigt );
360 EditEngine& SmDocShell::GetEditEngine()
362 if (!pEditEngine)
365 //! see also SmEditWindow::DataChanged !
368 pEditEngineItemPool = EditEngine::CreatePool();
370 SetEditEngineDefaultFonts(*pEditEngineItemPool);
372 pEditEngine = new EditEngine( pEditEngineItemPool );
374 pEditEngine->EnableUndo( true );
375 pEditEngine->SetDefTab( sal_uInt16(
376 Application::GetDefaultDevice()->GetTextWidth(OUString("XXXX"))) );
378 pEditEngine->SetControlWord(
379 (pEditEngine->GetControlWord() | EEControlBits::AUTOINDENTING) &
380 EEControlBits(~EEControlBits::UNDOATTRIBS) &
381 EEControlBits(~EEControlBits::PASTESPECIAL) );
383 pEditEngine->SetWordDelimiters(" .=+-*/(){}[];\"");
384 pEditEngine->SetRefMapMode( MAP_PIXEL );
386 pEditEngine->SetPaperSize( Size( 800, 0 ) );
388 pEditEngine->EraseVirtualDevice();
390 // set initial text if the document already has some...
391 // (may be the case when reloading a doc)
392 OUString aTxt( GetText() );
393 if (!aTxt.isEmpty())
394 pEditEngine->SetText( aTxt );
396 pEditEngine->ClearModifyFlag();
399 return *pEditEngine;
403 SfxItemPool& SmDocShell::GetEditEngineItemPool()
405 if (!pEditEngineItemPool)
406 GetEditEngine();
407 assert(pEditEngineItemPool && "EditEngineItemPool missing");
408 return *pEditEngineItemPool;
411 void SmDocShell::DrawFormula(OutputDevice &rDev, Point &rPosition, bool bDrawSelection)
413 if (!pTree)
414 Parse();
415 OSL_ENSURE(pTree, "Sm : NULL pointer");
417 if (!IsFormulaArranged())
418 ArrangeFormula();
420 // Problem: What happens to WYSIWYG? While we're active inplace, we don't have a reference
421 // device and aren't aligned to that either. So now there can be a difference between the
422 // VisArea (i.e. the size within the client) and the current size.
423 // Idea: The difference could be adapted with SmNod::SetSize (no long-term solution)
425 rPosition.X() += aFormat.GetDistance( DIS_LEFTSPACE );
426 rPosition.Y() += aFormat.GetDistance( DIS_TOPSPACE );
428 //! in case of high contrast-mode (accessibility option!)
429 //! the draw mode needs to be set to default, because when imbedding
430 //! Math for example in Calc in "a over b" the fraction bar may not
431 //! be visible else. More generally: the FillColor may have been changed.
432 DrawModeFlags nOldDrawMode = DrawModeFlags::Default;
433 bool bRestoreDrawMode = false;
434 if (OUTDEV_WINDOW == rDev.GetOutDevType() &&
435 static_cast<vcl::Window &>(rDev).GetSettings().GetStyleSettings().GetHighContrastMode())
437 nOldDrawMode = rDev.GetDrawMode();
438 rDev.SetDrawMode( DrawModeFlags::Default );
439 bRestoreDrawMode = true;
442 // format/draw formulas always from left to right
443 // and numbers should not be converted
444 ComplexTextLayoutMode nLayoutMode = rDev.GetLayoutMode();
445 rDev.SetLayoutMode( TEXT_LAYOUT_DEFAULT );
446 sal_Int16 nDigitLang = rDev.GetDigitLanguage();
447 rDev.SetDigitLanguage( LANGUAGE_ENGLISH );
449 //Set selection if any
450 if(pCursor && bDrawSelection){
451 pCursor->AnnotateSelection();
452 SmSelectionDrawingVisitor(rDev, pTree, rPosition);
455 //Drawing using visitor
456 SmDrawingVisitor(rDev, rPosition, pTree);
459 rDev.SetLayoutMode( nLayoutMode );
460 rDev.SetDigitLanguage( nDigitLang );
462 if (bRestoreDrawMode)
463 rDev.SetDrawMode( nOldDrawMode );
466 Size SmDocShell::GetSize()
468 Size aRet;
470 if (!pTree)
471 Parse();
473 if (pTree)
475 if (!IsFormulaArranged())
476 ArrangeFormula();
477 aRet = pTree->GetSize();
479 if ( !aRet.Width() )
480 aRet.Width() = 2000;
481 else
482 aRet.Width() += aFormat.GetDistance( DIS_LEFTSPACE ) +
483 aFormat.GetDistance( DIS_RIGHTSPACE );
484 if ( !aRet.Height() )
485 aRet.Height() = 1000;
486 else
487 aRet.Height() += aFormat.GetDistance( DIS_TOPSPACE ) +
488 aFormat.GetDistance( DIS_BOTTOMSPACE );
491 return aRet;
494 void SmDocShell::InvalidateCursor(){
495 delete pCursor;
496 pCursor = NULL;
499 SmCursor& SmDocShell::GetCursor(){
500 if(!pCursor)
501 pCursor = new SmCursor(pTree, this);
502 return *pCursor;
507 SmPrinterAccess::SmPrinterAccess( SmDocShell &rDocShell )
509 pPrinter = rDocShell.GetPrt();
510 if ( pPrinter )
512 pPrinter->Push( PushFlags::MAPMODE );
513 if ( SfxObjectCreateMode::EMBEDDED == rDocShell.GetCreateMode() )
515 // if it is an embedded object (without it's own printer)
516 // we change the MapMode temporarily.
517 //!If it is a document with it's own printer the MapMode should
518 //!be set correct (once) elsewhere(!), in order to avoid numerous
519 //!superfluous pushing and poping of the MapMode when using
520 //!this class.
522 const MapUnit eOld = pPrinter->GetMapMode().GetMapUnit();
523 if ( MAP_100TH_MM != eOld )
525 MapMode aMap( pPrinter->GetMapMode() );
526 aMap.SetMapUnit( MAP_100TH_MM );
527 Point aTmp( aMap.GetOrigin() );
528 aTmp.X() = OutputDevice::LogicToLogic( aTmp.X(), eOld, MAP_100TH_MM );
529 aTmp.Y() = OutputDevice::LogicToLogic( aTmp.Y(), eOld, MAP_100TH_MM );
530 aMap.SetOrigin( aTmp );
531 pPrinter->SetMapMode( aMap );
535 if ( !!(pRefDev = rDocShell.GetRefDev()) && pPrinter.get() != pRefDev.get() )
537 pRefDev->Push( PushFlags::MAPMODE );
538 if ( SfxObjectCreateMode::EMBEDDED == rDocShell.GetCreateMode() )
540 // if it is an embedded object (without it's own printer)
541 // we change the MapMode temporarily.
542 //!If it is a document with it's own printer the MapMode should
543 //!be set correct (once) elsewhere(!), in order to avoid numerous
544 //!superfluous pushing and poping of the MapMode when using
545 //!this class.
547 const MapUnit eOld = pRefDev->GetMapMode().GetMapUnit();
548 if ( MAP_100TH_MM != eOld )
550 MapMode aMap( pRefDev->GetMapMode() );
551 aMap.SetMapUnit( MAP_100TH_MM );
552 Point aTmp( aMap.GetOrigin() );
553 aTmp.X() = OutputDevice::LogicToLogic( aTmp.X(), eOld, MAP_100TH_MM );
554 aTmp.Y() = OutputDevice::LogicToLogic( aTmp.Y(), eOld, MAP_100TH_MM );
555 aMap.SetOrigin( aTmp );
556 pRefDev->SetMapMode( aMap );
562 SmPrinterAccess::~SmPrinterAccess()
564 if ( pPrinter )
565 pPrinter->Pop();
566 if ( pRefDev && pRefDev != pPrinter )
567 pRefDev->Pop();
570 Printer* SmDocShell::GetPrt()
572 if (SfxObjectCreateMode::EMBEDDED == GetCreateMode())
574 // Normally the server provides the printer. But if it doesn't provide one (e.g. because
575 // there is no connection) it still can be the case that we know the printer because it
576 // has been passed on by the server in OnDocumentPrinterChanged and being kept temporarily.
577 Printer* pPrt = GetDocumentPrinter();
578 if (!pPrt && pTmpPrinter)
579 pPrt = pTmpPrinter;
580 return pPrt;
582 else if (!pPrinter)
584 SfxItemSet* pOptions = new SfxItemSet(GetPool(),
585 SID_PRINTSIZE, SID_PRINTSIZE,
586 SID_PRINTZOOM, SID_PRINTZOOM,
587 SID_PRINTTITLE, SID_PRINTTITLE,
588 SID_PRINTTEXT, SID_PRINTTEXT,
589 SID_PRINTFRAME, SID_PRINTFRAME,
590 SID_NO_RIGHT_SPACES, SID_NO_RIGHT_SPACES,
591 SID_SAVE_ONLY_USED_SYMBOLS, SID_SAVE_ONLY_USED_SYMBOLS,
593 SmModule *pp = SM_MOD();
594 pp->GetConfig()->ConfigToItemSet(*pOptions);
595 pPrinter = VclPtr<SfxPrinter>::Create(pOptions);
596 pPrinter->SetMapMode(MapMode(MAP_100TH_MM));
598 return pPrinter;
601 OutputDevice* SmDocShell::GetRefDev()
603 if (SfxObjectCreateMode::EMBEDDED == GetCreateMode())
605 OutputDevice* pOutDev = GetDocumentRefDev();
606 if (pOutDev)
607 return pOutDev;
610 return GetPrt();
613 void SmDocShell::SetPrinter( SfxPrinter *pNew )
615 pPrinter.disposeAndClear();
616 pPrinter = pNew; //Transfer ownership
617 pPrinter->SetMapMode( MapMode(MAP_100TH_MM) );
618 SetFormulaArranged(false);
619 Repaint();
622 void SmDocShell::OnDocumentPrinterChanged( Printer *pPrt )
624 pTmpPrinter = pPrt;
625 SetFormulaArranged(false);
626 Size aOldSize = GetVisArea().GetSize();
627 Repaint();
628 if( aOldSize != GetVisArea().GetSize() && !aText.isEmpty() )
629 SetModified( true );
630 pTmpPrinter = 0;
633 void SmDocShell::Repaint()
635 bool bIsEnabled = IsEnableSetModified();
636 if (bIsEnabled)
637 EnableSetModified( false );
639 SetFormulaArranged(false);
641 Size aVisSize = GetSize();
642 SetVisAreaSize(aVisSize);
643 SmViewShell* pViewSh = SmGetActiveView();
644 if (pViewSh)
645 pViewSh->GetGraphicWindow().Invalidate();
647 if (bIsEnabled)
648 EnableSetModified(bIsEnabled);
651 SmDocShell::SmDocShell( SfxModelFlags i_nSfxCreationFlags )
652 : SfxObjectShell(i_nSfxCreationFlags)
653 , pTree(0)
654 , pEditEngineItemPool(0)
655 , pEditEngine(0)
656 , pPrinter(0)
657 , pTmpPrinter(0)
658 , nModifyCount(0)
659 , bIsFormulaArranged(false)
661 pCursor = NULL;
663 SetPool(&SfxGetpApp()->GetPool());
665 SmModule *pp = SM_MOD();
666 aFormat = pp->GetConfig()->GetStandardFormat();
668 StartListening(aFormat);
669 StartListening(*pp->GetConfig());
671 SetBaseModel(new SmModel(this));
674 SmDocShell::~SmDocShell()
676 SmModule *pp = SM_MOD();
678 EndListening(aFormat);
679 EndListening(*pp->GetConfig());
682 if(pCursor)
683 delete pCursor;
684 pCursor = NULL;
686 delete pEditEngine;
687 SfxItemPool::Free(pEditEngineItemPool);
688 delete pTree;
689 pPrinter.disposeAndClear();
692 bool SmDocShell::ConvertFrom(SfxMedium &rMedium)
694 bool bSuccess = false;
695 const OUString& rFltName = rMedium.GetFilter()->GetFilterName();
697 OSL_ENSURE( rFltName != STAROFFICE_XML, "Wrong filter!");
699 if ( rFltName == MATHML_XML )
701 if (pTree)
703 delete pTree;
704 pTree = 0;
705 InvalidateCursor();
707 Reference<com::sun::star::frame::XModel> xModel(GetModel());
708 SmXMLImportWrapper aEquation(xModel);
709 bSuccess = 0 == aEquation.Import(rMedium);
711 else
713 SvStream *pStream = rMedium.GetInStream();
714 if ( pStream )
716 if ( SotStorage::IsStorageFile( pStream ) )
718 tools::SvRef<SotStorage> aStorage = new SotStorage( pStream, false );
719 if ( aStorage->IsStream(OUString("Equation Native")) )
721 // is this a MathType Storage?
722 MathType aEquation( aText );
723 if ( (bSuccess = (1 == aEquation.Parse( aStorage )) ))
724 Parse();
730 if ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
732 SetFormulaArranged( false );
733 Repaint();
736 FinishedLoading( SfxLoadedFlags::ALL );
737 return bSuccess;
741 bool SmDocShell::InitNew( const uno::Reference < embed::XStorage >& xStorage )
743 bool bRet = false;
744 if ( SfxObjectShell::InitNew( xStorage ) )
746 bRet = true;
747 SetVisArea(Rectangle(Point(0, 0), Size(2000, 1000)));
749 return bRet;
753 bool SmDocShell::Load( SfxMedium& rMedium )
755 bool bRet = false;
756 if( SfxObjectShell::Load( rMedium ))
758 uno::Reference < embed::XStorage > xStorage = GetMedium()->GetStorage();
759 uno::Reference < container::XNameAccess > xAccess (xStorage, uno::UNO_QUERY);
760 if (
762 xAccess->hasByName( OUString("content.xml") ) &&
763 xStorage->isStreamElement( OUString("content.xml") )
764 ) ||
766 xAccess->hasByName( OUString("Content.xml") ) &&
767 xStorage->isStreamElement( OUString("Content.xml") )
771 // is this a fabulous math package ?
772 Reference<com::sun::star::frame::XModel> xModel(GetModel());
773 SmXMLImportWrapper aEquation(xModel);
774 sal_uLong nError = aEquation.Import(rMedium);
775 bRet = 0 == nError;
776 SetError( nError, OSL_LOG_PREFIX );
780 if ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
782 SetFormulaArranged( false );
783 Repaint();
786 FinishedLoading( SfxLoadedFlags::ALL );
787 return bRet;
792 bool SmDocShell::Save()
794 //! apply latest changes if necessary
795 UpdateText();
797 if ( SfxObjectShell::Save() )
799 if (!pTree)
800 Parse();
801 if( pTree && !IsFormulaArranged() )
802 ArrangeFormula();
804 Reference<com::sun::star::frame::XModel> xModel(GetModel());
805 SmXMLExportWrapper aEquation(xModel);
806 aEquation.SetFlat(false);
807 return aEquation.Export(*GetMedium());
810 return false;
814 * replace bad characters that can not be saved. (#i74144)
815 * */
816 bool SmDocShell::ReplaceBadChars()
818 bool bReplace = false;
820 if (pEditEngine)
822 OUStringBuffer aBuf( pEditEngine->GetText( LINEEND_LF ) );
824 for (sal_Int32 i = 0; i < aBuf.getLength(); ++i)
826 if (aBuf[i] < ' ' && aBuf[i] != '\r' && aBuf[i] != '\n' && aBuf[i] != '\t')
828 aBuf[i] = ' ';
829 bReplace = true;
833 if (bReplace)
834 aText = aBuf.makeStringAndClear();
837 return bReplace;
841 void SmDocShell::UpdateText()
843 if (pEditEngine && pEditEngine->IsModified())
845 OUString aEngTxt( pEditEngine->GetText( LINEEND_LF ) );
846 if (GetText() != aEngTxt)
847 SetText( aEngTxt );
852 bool SmDocShell::SaveAs( SfxMedium& rMedium )
854 bool bRet = false;
856 //! apply latest changes if necessary
857 UpdateText();
859 if ( SfxObjectShell::SaveAs( rMedium ) )
861 if (!pTree)
862 Parse();
863 if( pTree && !IsFormulaArranged() )
864 ArrangeFormula();
866 Reference<com::sun::star::frame::XModel> xModel(GetModel());
867 SmXMLExportWrapper aEquation(xModel);
868 aEquation.SetFlat(false);
869 bRet = aEquation.Export(rMedium);
871 return bRet;
874 bool SmDocShell::ConvertTo( SfxMedium &rMedium )
876 bool bRet = false;
877 const SfxFilter* pFlt = rMedium.GetFilter();
878 if( pFlt )
880 if( !pTree )
881 Parse();
882 if( pTree && !IsFormulaArranged() )
883 ArrangeFormula();
885 const OUString& rFltName = pFlt->GetFilterName();
886 if(rFltName == STAROFFICE_XML)
888 Reference<com::sun::star::frame::XModel> xModel(GetModel());
889 SmXMLExportWrapper aEquation(xModel);
890 aEquation.SetFlat(false);
891 bRet = aEquation.Export(rMedium);
893 else if(rFltName == MATHML_XML)
895 Reference<com::sun::star::frame::XModel> xModel(GetModel());
896 SmXMLExportWrapper aEquation(xModel);
897 aEquation.SetFlat(true);
898 bRet = aEquation.Export(rMedium);
900 else if (pFlt->GetFilterName() == "MathType 3.x")
901 bRet = WriteAsMathType3( rMedium );
903 return bRet;
906 bool SmDocShell::writeFormulaOoxml( ::sax_fastparser::FSHelperPtr pSerializer, oox::core::OoxmlVersion version )
908 if( !pTree )
909 Parse();
910 if( pTree && !IsFormulaArranged() )
911 ArrangeFormula();
912 SmOoxmlExport aEquation( pTree, version );
913 return aEquation.ConvertFromStarMath( pSerializer );
916 void SmDocShell::writeFormulaRtf(OStringBuffer& rBuffer, rtl_TextEncoding nEncoding)
918 if (!pTree)
919 Parse();
920 if (pTree && !IsFormulaArranged())
921 ArrangeFormula();
922 SmRtfExport aEquation(pTree);
923 aEquation.ConvertFromStarMath(rBuffer, nEncoding);
926 void SmDocShell::readFormulaOoxml( oox::formulaimport::XmlStream& stream )
928 SmOoxmlImport aEquation( stream );
929 SetText( aEquation.ConvertToStarMath());
932 bool SmDocShell::SaveCompleted( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage )
934 if( SfxObjectShell::SaveCompleted( xStorage ))
935 return true;
937 return false;
941 void SmDocShell::Execute(SfxRequest& rReq)
943 switch (rReq.GetSlot())
945 case SID_TEXTMODE:
947 SmFormat aOldFormat = GetFormat();
948 SmFormat aNewFormat( aOldFormat );
949 aNewFormat.SetTextmode(!aOldFormat.IsTextmode());
951 ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager();
952 if (pTmpUndoMgr)
953 pTmpUndoMgr->AddUndoAction(
954 new SmFormatAction(this, aOldFormat, aNewFormat));
956 SetFormat( aNewFormat );
957 Repaint();
959 break;
961 case SID_AUTO_REDRAW :
963 SmModule *pp = SM_MOD();
964 bool bRedraw = pp->GetConfig()->IsAutoRedraw();
965 pp->GetConfig()->SetAutoRedraw(!bRedraw);
967 break;
969 case SID_LOADSYMBOLS:
970 LoadSymbols();
971 break;
973 case SID_SAVESYMBOLS:
974 SaveSymbols();
975 break;
977 case SID_FONT:
979 // get device used to retrieve the FontList
980 OutputDevice *pDev = GetPrinter();
981 if (!pDev || pDev->GetDevFontCount() == 0)
982 pDev = &SM_MOD()->GetDefaultVirtualDev();
983 OSL_ENSURE (pDev, "device for font list missing" );
985 VclPtrInstance< SmFontTypeDialog > xFontTypeDialog( nullptr, pDev );
987 SmFormat aOldFormat = GetFormat();
988 xFontTypeDialog->ReadFrom( aOldFormat );
989 if (xFontTypeDialog->Execute() == RET_OK)
991 SmFormat aNewFormat( aOldFormat );
993 xFontTypeDialog->WriteTo(aNewFormat);
994 ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager();
995 if (pTmpUndoMgr)
996 pTmpUndoMgr->AddUndoAction(
997 new SmFormatAction(this, aOldFormat, aNewFormat));
999 SetFormat( aNewFormat );
1000 Repaint();
1003 break;
1005 case SID_FONTSIZE:
1007 VclPtrInstance< SmFontSizeDialog > xFontSizeDialog(nullptr);
1009 SmFormat aOldFormat = GetFormat();
1010 xFontSizeDialog->ReadFrom( aOldFormat );
1011 if (xFontSizeDialog->Execute() == RET_OK)
1013 SmFormat aNewFormat( aOldFormat );
1015 xFontSizeDialog->WriteTo(aNewFormat);
1017 ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager();
1018 if (pTmpUndoMgr)
1019 pTmpUndoMgr->AddUndoAction(
1020 new SmFormatAction(this, aOldFormat, aNewFormat));
1022 SetFormat( aNewFormat );
1023 Repaint();
1026 break;
1028 case SID_DISTANCE:
1030 VclPtrInstance< SmDistanceDialog > xDistanceDialog(nullptr);
1032 SmFormat aOldFormat = GetFormat();
1033 xDistanceDialog->ReadFrom( aOldFormat );
1034 if (xDistanceDialog->Execute() == RET_OK)
1036 SmFormat aNewFormat( aOldFormat );
1038 xDistanceDialog->WriteTo(aNewFormat);
1040 ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager();
1041 if (pTmpUndoMgr)
1042 pTmpUndoMgr->AddUndoAction(
1043 new SmFormatAction(this, aOldFormat, aNewFormat));
1045 SetFormat( aNewFormat );
1046 Repaint();
1049 break;
1051 case SID_ALIGN:
1053 VclPtrInstance< SmAlignDialog > xAlignDialog(nullptr);
1055 SmFormat aOldFormat = GetFormat();
1056 xAlignDialog->ReadFrom( aOldFormat );
1057 if (xAlignDialog->Execute() == RET_OK)
1059 SmFormat aNewFormat( aOldFormat );
1061 xAlignDialog->WriteTo(aNewFormat);
1063 SmModule *pp = SM_MOD();
1064 SmFormat aFmt( pp->GetConfig()->GetStandardFormat() );
1065 xAlignDialog->WriteTo( aFmt );
1066 pp->GetConfig()->SetStandardFormat( aFmt );
1068 ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager();
1069 if (pTmpUndoMgr)
1070 pTmpUndoMgr->AddUndoAction(
1071 new SmFormatAction(this, aOldFormat, aNewFormat));
1073 SetFormat( aNewFormat );
1074 Repaint();
1077 break;
1079 case SID_TEXT:
1081 const SfxStringItem& rItem = static_cast<const SfxStringItem&>(rReq.GetArgs()->Get(SID_TEXT));
1082 if (GetText() != OUString(rItem.GetValue()))
1083 SetText(rItem.GetValue());
1085 break;
1087 case SID_UNDO:
1088 case SID_REDO:
1090 ::svl::IUndoManager* pTmpUndoMgr = GetUndoManager();
1091 if( pTmpUndoMgr )
1093 sal_uInt16 nId = rReq.GetSlot(), nCnt = 1;
1094 const SfxItemSet* pArgs = rReq.GetArgs();
1095 const SfxPoolItem* pItem;
1096 if( pArgs && SfxItemState::SET == pArgs->GetItemState( nId, false, &pItem ))
1097 nCnt = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
1099 bool (::svl::IUndoManager:: *fnDo)();
1101 std::size_t nCount;
1102 if( SID_UNDO == rReq.GetSlot() )
1104 nCount = pTmpUndoMgr->GetUndoActionCount();
1105 fnDo = &::svl::IUndoManager::Undo;
1107 else
1109 nCount = pTmpUndoMgr->GetRedoActionCount();
1110 fnDo = &::svl::IUndoManager::Redo;
1115 for( ; nCnt && nCount; --nCnt, --nCount )
1116 (pTmpUndoMgr->*fnDo)();
1118 catch( const Exception& )
1120 DBG_UNHANDLED_EXCEPTION();
1123 Repaint();
1124 UpdateText();
1125 SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this );
1126 while( pFrm )
1128 SfxBindings& rBind = pFrm->GetBindings();
1129 rBind.Invalidate(SID_UNDO);
1130 rBind.Invalidate(SID_REDO);
1131 rBind.Invalidate(SID_REPEAT);
1132 rBind.Invalidate(SID_CLEARHISTORY);
1133 pFrm = SfxViewFrame::GetNext( *pFrm, this );
1136 break;
1139 rReq.Done();
1143 void SmDocShell::GetState(SfxItemSet &rSet)
1145 SfxWhichIter aIter(rSet);
1147 for (sal_uInt16 nWh = aIter.FirstWhich(); 0 != nWh; nWh = aIter.NextWhich())
1149 switch (nWh)
1151 case SID_TEXTMODE:
1152 rSet.Put(SfxBoolItem(SID_TEXTMODE, GetFormat().IsTextmode()));
1153 break;
1155 case SID_DOCTEMPLATE :
1156 rSet.DisableItem(SID_DOCTEMPLATE);
1157 break;
1159 case SID_AUTO_REDRAW :
1161 SmModule *pp = SM_MOD();
1162 bool bRedraw = pp->GetConfig()->IsAutoRedraw();
1164 rSet.Put(SfxBoolItem(SID_AUTO_REDRAW, bRedraw));
1166 break;
1168 case SID_MODIFYSTATUS:
1170 sal_Unicode cMod = ' ';
1171 if (IsModified())
1172 cMod = '*';
1173 rSet.Put(SfxStringItem(SID_MODIFYSTATUS, OUString(cMod)));
1175 break;
1177 case SID_TEXT:
1178 rSet.Put(SfxStringItem(SID_TEXT, GetText()));
1179 break;
1181 case SID_GAPHIC_SM:
1182 //! very old (pre UNO) and ugly hack to invalidate the SmGraphicWindow.
1183 //! If nModifyCount gets changed then the call below will implicitly notify
1184 //! SmGraphicController::StateChanged and there the window gets invalidated.
1185 //! Thus all the 'nModifyCount++' before invalidating this slot.
1186 rSet.Put(SfxInt16Item(SID_GAPHIC_SM, nModifyCount));
1187 break;
1189 case SID_UNDO:
1190 case SID_REDO:
1192 SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this );
1193 if( pFrm )
1194 pFrm->GetSlotState( nWh, NULL, &rSet );
1195 else
1196 rSet.DisableItem( nWh );
1198 break;
1200 case SID_GETUNDOSTRINGS:
1201 case SID_GETREDOSTRINGS:
1203 ::svl::IUndoManager* pTmpUndoMgr = GetUndoManager();
1204 if( pTmpUndoMgr )
1206 OUString(::svl::IUndoManager:: *fnGetComment)( size_t, bool const ) const;
1208 sal_uInt16 nCount;
1209 if( SID_GETUNDOSTRINGS == nWh )
1211 nCount = pTmpUndoMgr->GetUndoActionCount();
1212 fnGetComment = &::svl::IUndoManager::GetUndoActionComment;
1214 else
1216 nCount = pTmpUndoMgr->GetRedoActionCount();
1217 fnGetComment = &::svl::IUndoManager::GetRedoActionComment;
1219 if( nCount )
1221 OUStringBuffer aBuf;
1222 for( sal_uInt16 n = 0; n < nCount; ++n )
1224 aBuf.append((pTmpUndoMgr->*fnGetComment)( n, ::svl::IUndoManager::TopLevel ));
1225 aBuf.append('\n');
1228 SfxStringListItem aItem( nWh );
1229 aItem.SetString( aBuf.makeStringAndClear() );
1230 rSet.Put( aItem );
1233 else
1234 rSet.DisableItem( nWh );
1236 break;
1242 ::svl::IUndoManager *SmDocShell::GetUndoManager()
1244 if (!pEditEngine)
1245 GetEditEngine();
1246 return &pEditEngine->GetUndoManager();
1250 void SmDocShell::SaveSymbols()
1252 SmModule *pp = SM_MOD();
1253 pp->GetSymbolManager().Save();
1257 void SmDocShell::Draw(OutputDevice *pDevice,
1258 const JobSetup &,
1259 sal_uInt16 /*nAspect*/)
1261 pDevice->IntersectClipRegion(GetVisArea());
1262 Point atmppoint;
1263 DrawFormula(*pDevice, atmppoint);
1266 SfxItemPool& SmDocShell::GetPool()
1268 return SfxGetpApp()->GetPool();
1271 void SmDocShell::SetVisArea(const Rectangle & rVisArea)
1273 Rectangle aNewRect(rVisArea);
1275 aNewRect.SetPos(Point());
1277 if (! aNewRect.Right()) aNewRect.Right() = 2000;
1278 if (! aNewRect.Bottom()) aNewRect.Bottom() = 1000;
1280 bool bIsEnabled = IsEnableSetModified();
1281 if ( bIsEnabled )
1282 EnableSetModified( false );
1284 //TODO/LATER: it's unclear how this interacts with the SFX code
1285 // If outplace editing, then dont resize the OutplaceWindow. But the
1286 // ObjectShell has to resize. Bug 56470
1287 bool bUnLockFrame;
1288 if( GetCreateMode() == SfxObjectCreateMode::EMBEDDED && !IsInPlaceActive() && GetFrame() )
1290 GetFrame()->LockAdjustPosSizePixel();
1291 bUnLockFrame = true;
1293 else
1294 bUnLockFrame = false;
1296 SfxObjectShell::SetVisArea( aNewRect );
1298 if( bUnLockFrame )
1299 GetFrame()->UnlockAdjustPosSizePixel();
1301 if ( bIsEnabled )
1302 EnableSetModified( bIsEnabled );
1306 void SmDocShell::FillClass(SvGlobalName* pClassName,
1307 SotClipboardFormatId* pFormat,
1308 OUString* /*pAppName*/,
1309 OUString* pFullTypeName,
1310 OUString* pShortTypeName,
1311 sal_Int32 nFileFormat,
1312 bool bTemplate /* = false */) const
1314 if (nFileFormat == SOFFICE_FILEFORMAT_60 )
1316 *pClassName = SvGlobalName(SO3_SM_CLASSID_60);
1317 *pFormat = SotClipboardFormatId::STARMATH_60;
1318 *pFullTypeName = SM_RESSTR(STR_MATH_DOCUMENT_FULLTYPE_CURRENT);
1319 *pShortTypeName = SM_RESSTR(RID_DOCUMENTSTR);
1321 else if (nFileFormat == SOFFICE_FILEFORMAT_8 )
1323 *pClassName = SvGlobalName(SO3_SM_CLASSID_60);
1324 *pFormat = bTemplate ? SotClipboardFormatId::STARMATH_8_TEMPLATE : SotClipboardFormatId::STARMATH_8;
1325 *pFullTypeName = SM_RESSTR(STR_MATH_DOCUMENT_FULLTYPE_CURRENT);
1326 *pShortTypeName = SM_RESSTR(RID_DOCUMENTSTR);
1330 sal_uLong SmDocShell::GetMiscStatus() const
1332 return SfxObjectShell::GetMiscStatus() | SVOBJ_MISCSTATUS_NOTRESIZEABLE
1333 | SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE;
1336 void SmDocShell::SetModified(bool bModified)
1338 if( IsEnableSetModified() )
1340 SfxObjectShell::SetModified( bModified );
1341 Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED));
1345 bool SmDocShell::WriteAsMathType3( SfxMedium& rMedium )
1347 MathType aEquation( aText, pTree );
1349 bool bRet = 0 != aEquation.ConvertFromStarMath( rMedium );
1350 return bRet;
1353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */