1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/logfile.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 <sfx2/sfx.hrc>
72 #include <document.hxx>
78 #include <starmath.hrc>
80 #include <toolbox.hxx>
81 #include <unomodel.hxx>
82 #include <utility.hxx>
84 #include "mathtype.hxx"
85 #include "ooxmlexport.hxx"
86 #include "ooxmlimport.hxx"
87 #include "rtfexport.hxx"
88 #include "mathmlimport.hxx"
89 #include "mathmlexport.hxx"
90 #include <sfx2/sfxsids.hrc>
91 #include <svx/svxids.hrc>
93 #include <tools/diagnose_ex.h>
94 #include "visitors.hxx"
95 #include "accessibility.hxx"
97 using namespace ::com::sun::star
;
98 using namespace ::com::sun::star::accessibility
;
99 using namespace ::com::sun::star::lang
;
100 using namespace ::com::sun::star::ucb
;
101 using namespace ::com::sun::star::uno
;
104 #include "smslots.hxx"
106 ////////////////////////////////////////////////////////////
109 TYPEINIT1( SmDocShell
, SfxObjectShell
);
111 SFX_IMPL_INTERFACE(SmDocShell
, SfxObjectShell
, SmResId(0))
113 SFX_POPUPMENU_REGISTRATION(SmResId(RID_VIEWMENU
));
114 SFX_POPUPMENU_REGISTRATION(SmResId(RID_COMMANDMENU
));
117 SFX_IMPL_OBJECTFACTORY(SmDocShell
, SvGlobalName(SO3_SM_CLASSID
), SFXOBJECTSHELL_STD_NORMAL
, "smath" )
119 void SmDocShell::SFX_NOTIFY(SfxBroadcaster
&, const TypeId
&,
120 const SfxHint
& rHint
, const TypeId
&)
122 switch (((SfxSimpleHint
&)rHint
).GetId())
124 case HINT_FORMATCHANGED
:
125 SetFormulaArranged(false);
127 nModifyCount
++; //! see comment for SID_GAPHIC_SM in SmDocShell::GetState
134 void SmDocShell::LoadSymbols()
136 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::LoadSymbols" );
138 SmModule
*pp
= SM_MOD();
139 pp
->GetSymbolManager().Load();
143 const String
SmDocShell::GetComment() const
145 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::GetComment" );
146 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
147 const_cast<SmDocShell
*>(this)->GetModel(), uno::UNO_QUERY_THROW
);
148 uno::Reference
<document::XDocumentProperties
> xDocProps(
149 xDPS
->getDocumentProperties());
150 return xDocProps
->getDescription();
154 void SmDocShell::SetText(const OUString
& rBuffer
)
156 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SetText" );
158 if (rBuffer
!= OUString(aText
))
160 bool bIsEnabled
= IsEnableSetModified();
162 EnableSetModified( false );
165 SetFormulaArranged( false );
169 SmViewShell
*pViewSh
= SmGetActiveView();
172 pViewSh
->GetViewFrame()->GetBindings().Invalidate(SID_TEXT
);
173 if ( SFX_CREATE_MODE_EMBEDDED
== GetCreateMode() )
175 // have SwOleClient::FormatChanged() to align the modified formula properly
176 // even if the vis area does not change (e.g. when formula text changes from
177 // "{a over b + c} over d" to "d over {a over b + c}"
178 SFX_APP()->NotifyEvent(SfxEventHint( SFX_EVENT_VISAREACHANGED
, GlobalEventConfig::GetEventName(STR_EVENT_VISAREACHANGED
), this));
183 pViewSh
->GetGraphicWindow().Invalidate();
187 EnableSetModified( bIsEnabled
);
190 // launch accessible event if necessary
191 SmGraphicAccessible
*pAcc
= pViewSh
? pViewSh
->GetGraphicWindow().GetAccessible_Impl() : 0;
194 Any aOldValue
, aNewValue
;
195 if ( comphelper::OCommonAccessibleText::implInitTextChangedEvent( aText
, rBuffer
, aOldValue
, aNewValue
) )
197 pAcc
->LaunchEvent( AccessibleEventId::TEXT_CHANGED
,
198 aOldValue
, aNewValue
);
202 if ( GetCreateMode() == SFX_CREATE_MODE_EMBEDDED
)
203 OnDocumentPrinterChanged(0);
207 void SmDocShell::SetFormat(SmFormat
& rFormat
)
209 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SetFormat" );
212 SetFormulaArranged( false );
215 nModifyCount
++; //! see comment for SID_GAPHIC_SM in SmDocShell::GetState
217 // don't use SmGetActiveView since the view shell might not be active (0 pointer)
218 // if for example the Basic Macro dialog currently has the focus. Thus:
219 SfxViewFrame
* pFrm
= SfxViewFrame::GetFirst( this );
222 pFrm
->GetBindings().Invalidate(SID_GAPHIC_SM
);
223 pFrm
= SfxViewFrame::GetNext( *pFrm
, this );
227 OUString
SmDocShell::GetAccessibleText()
229 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::GetAccessibleText" );
231 if (!IsFormulaArranged())
233 if (aAccText
.isEmpty())
235 OSL_ENSURE( pTree
, "Tree missing" );
239 pTree
->GetAccessibleText(aBuf
);
240 aAccText
= aBuf
.makeStringAndClear();
246 void SmDocShell::Parse()
248 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::Parse" );
253 pTree
= aInterpreter
.Parse(aText
);
254 nModifyCount
++; //! see comment for SID_GAPHIC_SM in SmDocShell::GetState
255 SetFormulaArranged( false );
257 aUsedSymbols
= aInterpreter
.GetUsedSymbols();
261 void SmDocShell::ArrangeFormula()
263 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::ArrangeFormula" );
265 if (IsFormulaArranged())
268 // Only for the duration of the existence of this object the correct settings
269 // at the printer are guaranteed!
270 SmPrinterAccess
aPrtAcc(*this);
271 OutputDevice
* pOutDev
= aPrtAcc
.GetRefDev();
275 #if OSL_DEBUG_LEVEL > 1
276 OSL_FAIL("!! SmDocShell::ArrangeFormula: reference device missing !!");
280 // if necessary get another OutputDevice for which we format
283 SmViewShell
*pView
= SmGetActiveView();
285 pOutDev
= &pView
->GetGraphicWindow();
288 pOutDev
= &SM_MOD()->GetDefaultVirtualDev();
289 pOutDev
->SetMapMode( MapMode(MAP_100TH_MM
) );
292 OSL_ENSURE(pOutDev
->GetMapMode().GetMapUnit() == MAP_100TH_MM
,
293 "Sm : falscher MapMode");
295 const SmFormat
&rFormat
= GetFormat();
296 pTree
->Prepare(rFormat
, *this);
298 // format/draw formulas always from left to right,
299 // and numbers should not be converted
300 sal_uLong nLayoutMode
= pOutDev
->GetLayoutMode();
301 pOutDev
->SetLayoutMode( TEXT_LAYOUT_BIDI_LTR
);
302 sal_Int16 nDigitLang
= pOutDev
->GetDigitLanguage();
303 pOutDev
->SetDigitLanguage( LANGUAGE_ENGLISH
);
305 pTree
->Arrange(*pOutDev
, rFormat
);
307 pOutDev
->SetLayoutMode( nLayoutMode
);
308 pOutDev
->SetDigitLanguage( nDigitLang
);
310 SetFormulaArranged(true);
312 // invalidate accessible text
313 aAccText
= OUString();
317 void SetEditEngineDefaultFonts(SfxItemPool
&rEditEngineItemPool
)
320 // set fonts to be used
322 SvtLinguOptions aOpt
;
323 SvtLinguConfig().GetOptions( aOpt
);
326 sal_Int16 nFallbackLang
;
328 sal_uInt16 nFontType
;
329 sal_uInt16 nFontInfoId
;
332 // info to get western font to be used
333 { LANGUAGE_ENGLISH_US
, LANGUAGE_NONE
,
334 DEFAULTFONT_FIXED
, EE_CHAR_FONTINFO
},
335 // info to get CJK font to be used
336 { LANGUAGE_JAPANESE
, LANGUAGE_NONE
,
337 DEFAULTFONT_CJK_TEXT
, EE_CHAR_FONTINFO_CJK
},
338 // info to get CTL font to be used
339 { LANGUAGE_ARABIC_SAUDI_ARABIA
, LANGUAGE_NONE
,
340 DEFAULTFONT_CTL_TEXT
, EE_CHAR_FONTINFO_CTL
}
342 aTable
[0].nLang
= aOpt
.nDefaultLanguage
;
343 aTable
[1].nLang
= aOpt
.nDefaultLanguage_CJK
;
344 aTable
[2].nLang
= aOpt
.nDefaultLanguage_CTL
;
346 for (int i
= 0; i
< 3; ++i
)
348 const FontDta
&rFntDta
= aTable
[i
];
349 LanguageType nLang
= (LANGUAGE_NONE
== rFntDta
.nLang
) ?
350 rFntDta
.nFallbackLang
: rFntDta
.nLang
;
351 Font aFont
= Application::GetDefaultDevice()->GetDefaultFont(
352 rFntDta
.nFontType
, nLang
, DEFAULTFONT_FLAGS_ONLYONE
);
353 rEditEngineItemPool
.SetPoolDefaultItem(
354 SvxFontItem( aFont
.GetFamily(), aFont
.GetName(),
355 aFont
.GetStyleName(), aFont
.GetPitch(), aFont
.GetCharSet(),
356 rFntDta
.nFontInfoId
) );
360 SvxFontHeightItem
aFontHeigt(
361 Application::GetDefaultDevice()->LogicToPixel(
362 Size( 0, 11 ), MapMode( MAP_POINT
) ).Height(), 100,
363 EE_CHAR_FONTHEIGHT
);
364 rEditEngineItemPool
.SetPoolDefaultItem( aFontHeigt
);
365 aFontHeigt
.SetWhich( EE_CHAR_FONTHEIGHT_CJK
);
366 rEditEngineItemPool
.SetPoolDefaultItem( aFontHeigt
);
367 aFontHeigt
.SetWhich( EE_CHAR_FONTHEIGHT_CTL
);
368 rEditEngineItemPool
.SetPoolDefaultItem( aFontHeigt
);
372 EditEngine
& SmDocShell::GetEditEngine()
374 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::GetEditEngine" );
379 //! see also SmEditWindow::DataChanged !
382 pEditEngineItemPool
= EditEngine::CreatePool();
384 SetEditEngineDefaultFonts(*pEditEngineItemPool
);
386 pEditEngine
= new EditEngine( pEditEngineItemPool
);
388 pEditEngine
->EnableUndo( true );
389 pEditEngine
->SetDefTab( sal_uInt16(
390 Application::GetDefaultDevice()->GetTextWidth(OUString("XXXX"))) );
392 pEditEngine
->SetControlWord(
393 (pEditEngine
->GetControlWord() | EE_CNTRL_AUTOINDENTING
) &
394 (~EE_CNTRL_UNDOATTRIBS
) &
395 (~EE_CNTRL_PASTESPECIAL
) );
397 pEditEngine
->SetWordDelimiters( OUString(" .=+-*/(){}[];\"" ) );
398 pEditEngine
->SetRefMapMode( MAP_PIXEL
);
400 pEditEngine
->SetPaperSize( Size( 800, 0 ) );
402 pEditEngine
->EraseVirtualDevice();
404 // set initial text if the document already has some...
405 // (may be the case when reloading a doc)
406 String
aTxt( GetText() );
408 pEditEngine
->SetText( aTxt
);
410 pEditEngine
->ClearModifyFlag();
417 SfxItemPool
& SmDocShell::GetEditEngineItemPool()
419 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::GetEditEngineItemPool" );
421 if (!pEditEngineItemPool
)
423 OSL_ENSURE( pEditEngineItemPool
, "EditEngineItemPool missing" );
424 return *pEditEngineItemPool
;
427 void SmDocShell::DrawFormula(OutputDevice
&rDev
, Point
&rPosition
, bool bDrawSelection
)
429 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::Draw" );
433 OSL_ENSURE(pTree
, "Sm : NULL pointer");
435 if (!IsFormulaArranged())
438 // Problem: What happens to WYSIWYG? While we're active inplace, we don't have a reference
439 // device and aren't aligned to that either. So now there can be a difference between the
440 // VisArea (i.e. the size within the client) and the current size.
441 // Idea: The difference could be adapted with SmNod::SetSize (no long-term solution)
443 rPosition
.X() += aFormat
.GetDistance( DIS_LEFTSPACE
);
444 rPosition
.Y() += aFormat
.GetDistance( DIS_TOPSPACE
);
446 //! in case of high contrast-mode (accessibility option!)
447 //! the draw mode needs to be set to default, because when imbedding
448 //! Math for example in Calc in "a over b" the fraction bar may not
449 //! be visible else. More generally: the FillColor may have been changed.
450 sal_uLong nOldDrawMode
= DRAWMODE_DEFAULT
;
451 bool bRestoreDrawMode
= false;
452 if (OUTDEV_WINDOW
== rDev
.GetOutDevType() &&
453 ((Window
&) rDev
).GetSettings().GetStyleSettings().GetHighContrastMode())
455 nOldDrawMode
= rDev
.GetDrawMode();
456 rDev
.SetDrawMode( DRAWMODE_DEFAULT
);
457 bRestoreDrawMode
= true;
460 // format/draw formulas always from left to right
461 // and numbers should not be converted
462 sal_uLong nLayoutMode
= rDev
.GetLayoutMode();
463 rDev
.SetLayoutMode( TEXT_LAYOUT_BIDI_LTR
);
464 sal_Int16 nDigitLang
= rDev
.GetDigitLanguage();
465 rDev
.SetDigitLanguage( LANGUAGE_ENGLISH
);
467 //Set selection if any
468 if(pCursor
&& bDrawSelection
){
469 pCursor
->AnnotateSelection();
470 SmSelectionDrawingVisitor(rDev
, pTree
, rPosition
);
473 //Drawing using visitor
474 SmDrawingVisitor(rDev
, rPosition
, pTree
);
477 rDev
.SetLayoutMode( nLayoutMode
);
478 rDev
.SetDigitLanguage( nDigitLang
);
480 if (bRestoreDrawMode
)
481 rDev
.SetDrawMode( nOldDrawMode
);
484 Size
SmDocShell::GetSize()
486 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::GetSize" );
495 if (!IsFormulaArranged())
497 aRet
= pTree
->GetSize();
502 aRet
.Width() += aFormat
.GetDistance( DIS_LEFTSPACE
) +
503 aFormat
.GetDistance( DIS_RIGHTSPACE
);
504 if ( !aRet
.Height() )
505 aRet
.Height() = 1000;
507 aRet
.Height() += aFormat
.GetDistance( DIS_TOPSPACE
) +
508 aFormat
.GetDistance( DIS_BOTTOMSPACE
);
514 void SmDocShell::InvalidateCursor(){
519 SmCursor
& SmDocShell::GetCursor(){
521 pCursor
= new SmCursor(pTree
, this);
525 ////////////////////////////////////////
527 SmPrinterAccess::SmPrinterAccess( SmDocShell
&rDocShell
)
529 if ( 0 != (pPrinter
= rDocShell
.GetPrt()) )
531 pPrinter
->Push( PUSH_MAPMODE
);
532 if ( SFX_CREATE_MODE_EMBEDDED
== rDocShell
.GetCreateMode() )
534 // if it is an embedded object (without it's own printer)
535 // we change the MapMode temporarily.
536 //!If it is a document with it's own printer the MapMode should
537 //!be set correct (once) elsewhere(!), in order to avoid numerous
538 //!superfluous pushing and poping of the MapMode when using
541 const MapUnit eOld
= pPrinter
->GetMapMode().GetMapUnit();
542 if ( MAP_100TH_MM
!= eOld
)
544 MapMode
aMap( pPrinter
->GetMapMode() );
545 aMap
.SetMapUnit( MAP_100TH_MM
);
546 Point
aTmp( aMap
.GetOrigin() );
547 aTmp
.X() = OutputDevice::LogicToLogic( aTmp
.X(), eOld
, MAP_100TH_MM
);
548 aTmp
.Y() = OutputDevice::LogicToLogic( aTmp
.Y(), eOld
, MAP_100TH_MM
);
549 aMap
.SetOrigin( aTmp
);
550 pPrinter
->SetMapMode( aMap
);
554 if ( 0 != (pRefDev
= rDocShell
.GetRefDev()) && pPrinter
!= pRefDev
)
556 pRefDev
->Push( PUSH_MAPMODE
);
557 if ( SFX_CREATE_MODE_EMBEDDED
== rDocShell
.GetCreateMode() )
559 // if it is an embedded object (without it's own printer)
560 // we change the MapMode temporarily.
561 //!If it is a document with it's own printer the MapMode should
562 //!be set correct (once) elsewhere(!), in order to avoid numerous
563 //!superfluous pushing and poping of the MapMode when using
566 const MapUnit eOld
= pRefDev
->GetMapMode().GetMapUnit();
567 if ( MAP_100TH_MM
!= eOld
)
569 MapMode
aMap( pRefDev
->GetMapMode() );
570 aMap
.SetMapUnit( MAP_100TH_MM
);
571 Point
aTmp( aMap
.GetOrigin() );
572 aTmp
.X() = OutputDevice::LogicToLogic( aTmp
.X(), eOld
, MAP_100TH_MM
);
573 aTmp
.Y() = OutputDevice::LogicToLogic( aTmp
.Y(), eOld
, MAP_100TH_MM
);
574 aMap
.SetOrigin( aTmp
);
575 pRefDev
->SetMapMode( aMap
);
581 SmPrinterAccess::~SmPrinterAccess()
585 if ( pRefDev
&& pRefDev
!= pPrinter
)
589 ////////////////////////////////////////
591 Printer
* SmDocShell::GetPrt()
593 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::GetPrt" );
595 if ( SFX_CREATE_MODE_EMBEDDED
== GetCreateMode() )
597 // Normally the server provides the printer. But if it doesn't provide one (e.g. because
598 // there is no connection) it still can be the case that we know the printer because it
599 // has been passed on by the server in OnDocumentPrinterChanged and being kept temporarily.
600 Printer
*pPrt
= GetDocumentPrinter();
601 if ( !pPrt
&& pTmpPrinter
)
605 else if ( !pPrinter
)
607 SfxItemSet
*pOptions
=
608 new SfxItemSet(GetPool(),
609 SID_PRINTSIZE
, SID_PRINTSIZE
,
610 SID_PRINTZOOM
, SID_PRINTZOOM
,
611 SID_PRINTTITLE
, SID_PRINTTITLE
,
612 SID_PRINTTEXT
, SID_PRINTTEXT
,
613 SID_PRINTFRAME
, SID_PRINTFRAME
,
614 SID_NO_RIGHT_SPACES
, SID_NO_RIGHT_SPACES
,
615 SID_SAVE_ONLY_USED_SYMBOLS
, SID_SAVE_ONLY_USED_SYMBOLS
,
618 SmModule
*pp
= SM_MOD();
619 pp
->GetConfig()->ConfigToItemSet(*pOptions
);
620 pPrinter
= new SfxPrinter(pOptions
);
621 pPrinter
->SetMapMode( MapMode(MAP_100TH_MM
) );
626 OutputDevice
* SmDocShell::GetRefDev()
628 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::GetRefDev" );
630 if ( SFX_CREATE_MODE_EMBEDDED
== GetCreateMode() )
632 OutputDevice
* pOutDev
= GetDocumentRefDev();
641 void SmDocShell::SetPrinter( SfxPrinter
*pNew
)
643 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SetPrinter" );
646 pPrinter
= pNew
; //Transfer ownership
647 pPrinter
->SetMapMode( MapMode(MAP_100TH_MM
) );
648 SetFormulaArranged(false);
652 void SmDocShell::OnDocumentPrinterChanged( Printer
*pPrt
)
654 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::OnDocumentPrinterChanged" );
657 SetFormulaArranged(false);
658 Size aOldSize
= GetVisArea().GetSize();
660 if( aOldSize
!= GetVisArea().GetSize() && aText
.Len() )
665 void SmDocShell::Repaint()
667 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::Repaint" );
669 bool bIsEnabled
= IsEnableSetModified();
671 EnableSetModified( false );
673 SetFormulaArranged( false );
675 Size aVisSize
= GetSize();
676 SetVisAreaSize( aVisSize
);
677 SmViewShell
*pViewSh
= SmGetActiveView();
679 pViewSh
->GetGraphicWindow().Invalidate();
682 EnableSetModified( bIsEnabled
);
686 SmDocShell::SmDocShell( const sal_uInt64 i_nSfxCreationFlags
) :
687 SfxObjectShell( i_nSfxCreationFlags
),
689 pEditEngineItemPool ( 0 ),
694 bIsFormulaArranged ( false )
697 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SmDocShell" );
699 SetPool(&SFX_APP()->GetPool());
701 SmModule
*pp
= SM_MOD();
702 aFormat
= pp
->GetConfig()->GetStandardFormat();
704 StartListening(aFormat
);
705 StartListening(*pp
->GetConfig());
707 SetBaseModel( new SmModel(this) );
712 SmDocShell::~SmDocShell()
714 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::~SmDocShell" );
716 SmModule
*pp
= SM_MOD();
718 EndListening(aFormat
);
719 EndListening(*pp
->GetConfig());
727 SfxItemPool::Free(pEditEngineItemPool
);
733 sal_Bool
SmDocShell::SetData( const String
& rData
)
735 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SetData" );
742 sal_Bool
SmDocShell::ConvertFrom(SfxMedium
&rMedium
)
744 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::ConvertFrom" );
746 bool bSuccess
= false;
747 const String
& rFltName
= rMedium
.GetFilter()->GetFilterName();
749 OSL_ENSURE( !rFltName
.EqualsAscii( STAROFFICE_XML
), "Wrong filter!");
751 if ( rFltName
.EqualsAscii( MATHML_XML
) )
759 Reference
<com::sun::star::frame::XModel
> xModel(GetModel());
760 SmXMLImportWrapper
aEquation(xModel
);
761 bSuccess
= 0 == aEquation
.Import(rMedium
);
765 SvStream
*pStream
= rMedium
.GetInStream();
768 if ( SotStorage::IsStorageFile( pStream
) )
770 SvStorageRef aStorage
= new SotStorage( pStream
, false );
771 if ( aStorage
->IsStream(OUString("Equation Native")) )
773 // is this a MathType Storage?
774 MathType
aEquation( aText
);
775 if ( true == (bSuccess
= (1 == aEquation
.Parse( aStorage
)) ))
782 if ( GetCreateMode() == SFX_CREATE_MODE_EMBEDDED
)
784 SetFormulaArranged( false );
788 FinishedLoading( SFX_LOADED_ALL
);
793 sal_Bool
SmDocShell::InitNew( const uno::Reference
< embed::XStorage
>& xStorage
)
795 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::InitNew" );
798 if ( SfxObjectShell::InitNew( xStorage
) )
801 SetVisArea(Rectangle(Point(0, 0), Size(2000, 1000)));
807 sal_Bool
SmDocShell::Load( SfxMedium
& rMedium
)
809 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::Load" );
812 if( SfxObjectShell::Load( rMedium
))
814 uno::Reference
< embed::XStorage
> xStorage
= GetMedium()->GetStorage();
815 uno::Reference
< container::XNameAccess
> xAccess (xStorage
, uno::UNO_QUERY
);
818 xAccess
->hasByName( OUString("content.xml") ) &&
819 xStorage
->isStreamElement( OUString("content.xml") )
822 xAccess
->hasByName( OUString("Content.xml") ) &&
823 xStorage
->isStreamElement( OUString("Content.xml") )
827 // is this a fabulous math package ?
828 Reference
<com::sun::star::frame::XModel
> xModel(GetModel());
829 SmXMLImportWrapper
aEquation(xModel
);
830 sal_uLong nError
= aEquation
.Import(rMedium
);
832 SetError( nError
, OSL_LOG_PREFIX
);
836 if ( GetCreateMode() == SFX_CREATE_MODE_EMBEDDED
)
838 SetFormulaArranged( false );
842 FinishedLoading( SFX_LOADED_ALL
);
846 //------------------------------------------------------------------
848 sal_Bool
SmDocShell::Save()
850 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::Save" );
852 //! apply latest changes if necessary
855 if ( SfxObjectShell::Save() )
859 if( pTree
&& !IsFormulaArranged() )
862 Reference
<com::sun::star::frame::XModel
> xModel(GetModel());
863 SmXMLExportWrapper
aEquation(xModel
);
864 aEquation
.SetFlat(sal_False
);
865 return aEquation
.Export(*GetMedium());
872 * replace bad characters that can not be saved. (#i74144)
874 sal_Bool
SmDocShell::ReplaceBadChars()
876 sal_Bool bReplace
= sal_False
;
879 String
aEngTxt( pEditEngine
->GetText( LINEEND_LF
) );
880 const sal_Unicode
*pEngTxt
= aEngTxt
.GetBuffer();
881 xub_StrLen nLen
= aEngTxt
.Len();
882 for (xub_StrLen i
= 0; i
< nLen
&& !bReplace
; ++i
)
884 const sal_Unicode c
= *pEngTxt
++;
885 if (c
< ' ' && c
!= '\r' && c
!= '\n' && c
!= '\t')
890 sal_Unicode
*pChgTxt
= aEngTxt
.GetBufferAccess();
891 for (xub_StrLen i
= 0; i
< nLen
; ++i
)
893 sal_Unicode
&rc
= *pChgTxt
++;
894 if (rc
< ' ' && rc
!= '\r' && rc
!= '\n' && rc
!= '\t')
897 aEngTxt
.ReleaseBufferAccess( nLen
);
906 void SmDocShell::UpdateText()
908 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::UpdateText" );
910 if (pEditEngine
&& pEditEngine
->IsModified())
912 OUString
aEngTxt( pEditEngine
->GetText( LINEEND_LF
) );
913 if (GetText() != aEngTxt
)
919 sal_Bool
SmDocShell::SaveAs( SfxMedium
& rMedium
)
921 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SaveAs" );
925 //! apply latest changes if necessary
928 if ( SfxObjectShell::SaveAs( rMedium
) )
932 if( pTree
&& !IsFormulaArranged() )
935 Reference
<com::sun::star::frame::XModel
> xModel(GetModel());
936 SmXMLExportWrapper
aEquation(xModel
);
937 aEquation
.SetFlat(sal_False
);
938 bRet
= aEquation
.Export(rMedium
);
943 sal_Bool
SmDocShell::ConvertTo( SfxMedium
&rMedium
)
945 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::ConvertTo" );
948 const SfxFilter
* pFlt
= rMedium
.GetFilter();
953 if( pTree
&& !IsFormulaArranged() )
956 const String
& rFltName
= pFlt
->GetFilterName();
957 if(rFltName
.EqualsAscii( STAROFFICE_XML
))
959 Reference
<com::sun::star::frame::XModel
> xModel(GetModel());
960 SmXMLExportWrapper
aEquation(xModel
);
961 aEquation
.SetFlat(sal_False
);
962 bRet
= aEquation
.Export(rMedium
);
964 else if(rFltName
.EqualsAscii( MATHML_XML
))
966 Reference
<com::sun::star::frame::XModel
> xModel(GetModel());
967 SmXMLExportWrapper
aEquation(xModel
);
968 aEquation
.SetFlat(sal_True
);
969 bRet
= aEquation
.Export(rMedium
);
971 else if (pFlt
->GetFilterName().equalsAscii("MathType 3.x"))
972 bRet
= WriteAsMathType3( rMedium
);
977 bool SmDocShell::writeFormulaOoxml( ::sax_fastparser::FSHelperPtr pSerializer
, oox::core::OoxmlVersion version
)
979 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::writeFormulaOoxml" );
983 if( pTree
&& !IsFormulaArranged() )
985 SmOoxmlExport
aEquation( pTree
, version
);
986 return aEquation
.ConvertFromStarMath( pSerializer
);
989 void SmDocShell::writeFormulaRtf(OStringBuffer
& rBuffer
, rtl_TextEncoding nEncoding
)
993 if (pTree
&& !IsFormulaArranged())
995 SmRtfExport
aEquation(pTree
);
996 aEquation
.ConvertFromStarMath(rBuffer
, nEncoding
);
999 void SmDocShell::readFormulaOoxml( oox::formulaimport::XmlStream
& stream
)
1001 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::readFormulaOoxml" );
1003 SmOoxmlImport
aEquation( stream
);
1004 SetText( aEquation
.ConvertToStarMath());
1007 sal_Bool
SmDocShell::SaveCompleted( const ::com::sun::star::uno::Reference
< ::com::sun::star::embed::XStorage
>& xStorage
)
1009 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SaveCompleted" );
1011 if( SfxObjectShell::SaveCompleted( xStorage
))
1018 void SmDocShell::Execute(SfxRequest
& rReq
)
1020 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::Execute" );
1022 switch (rReq
.GetSlot())
1026 SmFormat aOldFormat
= GetFormat();
1027 SmFormat
aNewFormat( aOldFormat
);
1028 aNewFormat
.SetTextmode(!aOldFormat
.IsTextmode());
1030 ::svl::IUndoManager
*pTmpUndoMgr
= GetUndoManager();
1032 pTmpUndoMgr
->AddUndoAction(
1033 new SmFormatAction(this, aOldFormat
, aNewFormat
));
1035 SetFormat( aNewFormat
);
1040 case SID_AUTO_REDRAW
:
1042 SmModule
*pp
= SM_MOD();
1043 bool bRedraw
= pp
->GetConfig()->IsAutoRedraw();
1044 pp
->GetConfig()->SetAutoRedraw(!bRedraw
);
1048 case SID_LOADSYMBOLS
:
1052 case SID_SAVESYMBOLS
:
1058 // get device used to retrieve the FontList
1059 OutputDevice
*pDev
= GetPrinter();
1060 if (!pDev
|| pDev
->GetDevFontCount() == 0)
1061 pDev
= &SM_MOD()->GetDefaultVirtualDev();
1062 OSL_ENSURE (pDev
, "device for font list missing" );
1064 SmFontTypeDialog
*pFontTypeDialog
= new SmFontTypeDialog( NULL
, pDev
);
1066 SmFormat aOldFormat
= GetFormat();
1067 pFontTypeDialog
->ReadFrom( aOldFormat
);
1068 if (pFontTypeDialog
->Execute() == RET_OK
)
1070 SmFormat
aNewFormat( aOldFormat
);
1072 pFontTypeDialog
->WriteTo(aNewFormat
);
1073 ::svl::IUndoManager
*pTmpUndoMgr
= GetUndoManager();
1075 pTmpUndoMgr
->AddUndoAction(
1076 new SmFormatAction(this, aOldFormat
, aNewFormat
));
1078 SetFormat( aNewFormat
);
1081 delete pFontTypeDialog
;
1087 SmFontSizeDialog
*pFontSizeDialog
= new SmFontSizeDialog(NULL
);
1089 SmFormat aOldFormat
= GetFormat();
1090 pFontSizeDialog
->ReadFrom( aOldFormat
);
1091 if (pFontSizeDialog
->Execute() == RET_OK
)
1093 SmFormat
aNewFormat( aOldFormat
);
1095 pFontSizeDialog
->WriteTo(aNewFormat
);
1097 ::svl::IUndoManager
*pTmpUndoMgr
= GetUndoManager();
1099 pTmpUndoMgr
->AddUndoAction(
1100 new SmFormatAction(this, aOldFormat
, aNewFormat
));
1102 SetFormat( aNewFormat
);
1105 delete pFontSizeDialog
;
1111 SmDistanceDialog
*pDistanceDialog
= new SmDistanceDialog(NULL
);
1113 SmFormat aOldFormat
= GetFormat();
1114 pDistanceDialog
->ReadFrom( aOldFormat
);
1115 if (pDistanceDialog
->Execute() == RET_OK
)
1117 SmFormat
aNewFormat( aOldFormat
);
1119 pDistanceDialog
->WriteTo(aNewFormat
);
1121 ::svl::IUndoManager
*pTmpUndoMgr
= GetUndoManager();
1123 pTmpUndoMgr
->AddUndoAction(
1124 new SmFormatAction(this, aOldFormat
, aNewFormat
));
1126 SetFormat( aNewFormat
);
1129 delete pDistanceDialog
;
1135 SmAlignDialog
*pAlignDialog
= new SmAlignDialog(NULL
);
1137 SmFormat aOldFormat
= GetFormat();
1138 pAlignDialog
->ReadFrom( aOldFormat
);
1139 if (pAlignDialog
->Execute() == RET_OK
)
1141 SmFormat
aNewFormat( aOldFormat
);
1143 pAlignDialog
->WriteTo(aNewFormat
);
1145 SmModule
*pp
= SM_MOD();
1146 SmFormat
aFmt( pp
->GetConfig()->GetStandardFormat() );
1147 pAlignDialog
->WriteTo( aFmt
);
1148 pp
->GetConfig()->SetStandardFormat( aFmt
);
1150 ::svl::IUndoManager
*pTmpUndoMgr
= GetUndoManager();
1152 pTmpUndoMgr
->AddUndoAction(
1153 new SmFormatAction(this, aOldFormat
, aNewFormat
));
1155 SetFormat( aNewFormat
);
1158 delete pAlignDialog
;
1164 const SfxStringItem
& rItem
= (const SfxStringItem
&)rReq
.GetArgs()->Get(SID_TEXT
);
1165 if (GetText() != OUString(rItem
.GetValue()))
1166 SetText(rItem
.GetValue());
1173 ::svl::IUndoManager
* pTmpUndoMgr
= GetUndoManager();
1176 sal_uInt16 nId
= rReq
.GetSlot(), nCnt
= 1;
1177 const SfxItemSet
* pArgs
= rReq
.GetArgs();
1178 const SfxPoolItem
* pItem
;
1179 if( pArgs
&& SFX_ITEM_SET
== pArgs
->GetItemState( nId
, false, &pItem
))
1180 nCnt
= ((SfxUInt16Item
*)pItem
)->GetValue();
1182 sal_Bool (::svl::IUndoManager:: *fnDo
)();
1185 if( SID_UNDO
== rReq
.GetSlot() )
1187 nCount
= pTmpUndoMgr
->GetUndoActionCount();
1188 fnDo
= &::svl::IUndoManager::Undo
;
1192 nCount
= pTmpUndoMgr
->GetRedoActionCount();
1193 fnDo
= &::svl::IUndoManager::Redo
;
1198 for( ; nCnt
&& nCount
; --nCnt
, --nCount
)
1199 (pTmpUndoMgr
->*fnDo
)();
1201 catch( const Exception
& )
1203 DBG_UNHANDLED_EXCEPTION();
1208 SfxViewFrame
* pFrm
= SfxViewFrame::GetFirst( this );
1211 SfxBindings
& rBind
= pFrm
->GetBindings();
1212 rBind
.Invalidate(SID_UNDO
);
1213 rBind
.Invalidate(SID_REDO
);
1214 rBind
.Invalidate(SID_REPEAT
);
1215 rBind
.Invalidate(SID_CLEARHISTORY
);
1216 pFrm
= SfxViewFrame::GetNext( *pFrm
, this );
1226 void SmDocShell::GetState(SfxItemSet
&rSet
)
1228 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::GetState" );
1230 SfxWhichIter
aIter(rSet
);
1232 for (sal_uInt16 nWh
= aIter
.FirstWhich(); 0 != nWh
; nWh
= aIter
.NextWhich())
1237 rSet
.Put(SfxBoolItem(SID_TEXTMODE
, GetFormat().IsTextmode()));
1240 case SID_DOCTEMPLATE
:
1241 rSet
.DisableItem(SID_DOCTEMPLATE
);
1244 case SID_AUTO_REDRAW
:
1246 SmModule
*pp
= SM_MOD();
1247 bool bRedraw
= pp
->GetConfig()->IsAutoRedraw();
1249 rSet
.Put(SfxBoolItem(SID_AUTO_REDRAW
, bRedraw
));
1253 case SID_MODIFYSTATUS
:
1255 sal_Unicode cMod
= ' ';
1258 rSet
.Put(SfxStringItem(SID_MODIFYSTATUS
, OUString(cMod
)));
1263 rSet
.Put(SfxStringItem(SID_TEXT
, GetText()));
1267 //! very old (pre UNO) and ugly hack to invalidate the SmGraphicWindow.
1268 //! If nModifyCount gets changed then the call below will implicitly notify
1269 //! SmGraphicController::StateChanged and there the window gets invalidated.
1270 //! Thus all the 'nModifyCount++' before invalidating this slot.
1271 rSet
.Put(SfxInt16Item(SID_GAPHIC_SM
, nModifyCount
));
1277 SfxViewFrame
* pFrm
= SfxViewFrame::GetFirst( this );
1279 pFrm
->GetSlotState( nWh
, NULL
, &rSet
);
1281 rSet
.DisableItem( nWh
);
1285 case SID_GETUNDOSTRINGS
:
1286 case SID_GETREDOSTRINGS
:
1288 ::svl::IUndoManager
* pTmpUndoMgr
= GetUndoManager();
1291 OUString(::svl::IUndoManager:: *fnGetComment
)( size_t, bool const ) const;
1294 if( SID_GETUNDOSTRINGS
== nWh
)
1296 nCount
= pTmpUndoMgr
->GetUndoActionCount();
1297 fnGetComment
= &::svl::IUndoManager::GetUndoActionComment
;
1301 nCount
= pTmpUndoMgr
->GetRedoActionCount();
1302 fnGetComment
= &::svl::IUndoManager::GetRedoActionComment
;
1307 for( sal_uInt16 n
= 0; n
< nCount
; ++n
)
1308 ( sList
+= (pTmpUndoMgr
->*fnGetComment
)( n
, ::svl::IUndoManager::TopLevel
) )
1311 SfxStringListItem
aItem( nWh
);
1312 aItem
.SetString( sList
);
1317 rSet
.DisableItem( nWh
);
1325 ::svl::IUndoManager
*SmDocShell::GetUndoManager()
1327 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::GetUndoManager" );
1331 return &pEditEngine
->GetUndoManager();
1335 void SmDocShell::SaveSymbols()
1337 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SaveSymbols" );
1339 SmModule
*pp
= SM_MOD();
1340 pp
->GetSymbolManager().Save();
1344 void SmDocShell::Draw(OutputDevice
*pDevice
,
1346 sal_uInt16
/*nAspect*/)
1348 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::Draw" );
1350 pDevice
->IntersectClipRegion(GetVisArea());
1352 DrawFormula(*pDevice
, atmppoint
);
1355 SfxItemPool
& SmDocShell::GetPool() const
1357 return SFX_APP()->GetPool();
1360 void SmDocShell::SetVisArea(const Rectangle
& rVisArea
)
1362 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SetVisArea" );
1364 Rectangle
aNewRect(rVisArea
);
1366 aNewRect
.SetPos(Point());
1368 if (! aNewRect
.Right()) aNewRect
.Right() = 2000;
1369 if (! aNewRect
.Bottom()) aNewRect
.Bottom() = 1000;
1371 bool bIsEnabled
= IsEnableSetModified();
1373 EnableSetModified( false );
1375 //TODO/LATER: it's unclear how this interacts with the SFX code
1376 // If outplace editing, then dont resize the OutplaceWindow. But the
1377 // ObjectShell has to resize. Bug 56470
1379 if( GetCreateMode() == SFX_CREATE_MODE_EMBEDDED
&& !IsInPlaceActive() && GetFrame() )
1381 GetFrame()->LockAdjustPosSizePixel();
1382 bUnLockFrame
= true;
1385 bUnLockFrame
= false;
1387 SfxObjectShell::SetVisArea( aNewRect
);
1390 GetFrame()->UnlockAdjustPosSizePixel();
1393 EnableSetModified( bIsEnabled
);
1397 void SmDocShell::FillClass(SvGlobalName
* pClassName
,
1398 sal_uInt32
* pFormat
,
1399 OUString
* /*pAppName*/,
1400 OUString
* pFullTypeName
,
1401 OUString
* pShortTypeName
,
1402 sal_Int32 nFileFormat
,
1403 sal_Bool bTemplate
/* = sal_False */) const
1405 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::FillClass" );
1407 if (nFileFormat
== SOFFICE_FILEFORMAT_60
)
1409 *pClassName
= SvGlobalName(SO3_SM_CLASSID_60
);
1410 *pFormat
= SOT_FORMATSTR_ID_STARMATH_60
;
1411 *pFullTypeName
= String(SmResId(STR_MATH_DOCUMENT_FULLTYPE_CURRENT
));
1412 *pShortTypeName
= String(SmResId(RID_DOCUMENTSTR
));
1414 else if (nFileFormat
== SOFFICE_FILEFORMAT_8
)
1416 *pClassName
= SvGlobalName(SO3_SM_CLASSID_60
);
1417 *pFormat
= bTemplate
? SOT_FORMATSTR_ID_STARMATH_8_TEMPLATE
: SOT_FORMATSTR_ID_STARMATH_8
;
1418 *pFullTypeName
= String(SmResId(STR_MATH_DOCUMENT_FULLTYPE_CURRENT
));
1419 *pShortTypeName
= String(SmResId(RID_DOCUMENTSTR
));
1423 sal_uLong
SmDocShell::GetMiscStatus() const
1425 return SfxObjectShell::GetMiscStatus() | SVOBJ_MISCSTATUS_NOTRESIZEABLE
1426 | SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE
;
1429 void SmDocShell::SetModified(sal_Bool bModified
)
1431 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::SetModified" );
1433 if( IsEnableSetModified() )
1435 SfxObjectShell::SetModified( bModified
);
1436 Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED
));
1440 bool SmDocShell::WriteAsMathType3( SfxMedium
& rMedium
)
1442 RTL_LOGFILE_CONTEXT( aLog
, "starmath: SmDocShell::WriteAsMathType3" );
1444 MathType
aEquation( aText
, pTree
);
1446 bool bRet
= 0 != aEquation
.ConvertFromStarMath( rMedium
);
1450 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */