diff options
Diffstat (limited to 'starmath/source')
47 files changed, 41032 insertions, 0 deletions
diff --git a/starmath/source/accessibility.cxx b/starmath/source/accessibility.cxx new file mode 100644 index 000000000000..96f40993c3ce --- /dev/null +++ b/starmath/source/accessibility.cxx @@ -0,0 +1,1986 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/accessibility/XAccessibleEventListener.hpp> +#include <com/sun/star/accessibility/AccessibleEventObject.hpp> +#include <com/sun/star/awt/FocusEvent.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +#include <unotools/accessiblerelationsethelper.hxx> + + +#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> +#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp> +#include <com/sun/star/i18n/WordType.hpp> +#include <unotools/accessiblestatesethelper.hxx> +#include <comphelper/accessibleeventnotifier.hxx> +#include <osl/diagnose.h> +#include <vcl/svapp.hxx> +#include <vcl/window.hxx> +#include <vcl/unohelp2.hxx> +#include <tools/gen.hxx> +#include <osl/mutex.hxx> +#include <svl/itemset.hxx> + +#include <editeng/editobj.hxx> +#include <editeng/editdata.hxx> +#include <editeng/editview.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/outliner.hxx> +#include <editeng/unoedhlp.hxx> + + +#include "accessibility.hxx" +#include <applicat.hxx> +#include <unomodel.hxx> +#include <document.hxx> +#include <view.hxx> + +using rtl::OUString; +using namespace com::sun::star; +using namespace com::sun::star::lang; +using namespace com::sun::star::uno; +using namespace com::sun::star::accessibility; + +////////////////////////////////////////////////////////////////////// + +static awt::Rectangle lcl_GetBounds( Window *pWin ) +{ + // !! see VCLXAccessibleComponent::implGetBounds() + + //! the coordinates returned are relativ to the parent window ! + //! Thus the top-left point may be different from (0, 0) ! + + awt::Rectangle aBounds; + if (pWin) + { + Rectangle aRect = pWin->GetWindowExtentsRelative( NULL ); + aBounds.X = aRect.Left(); + aBounds.Y = aRect.Top(); + aBounds.Width = aRect.GetWidth(); + aBounds.Height = aRect.GetHeight(); + Window* pParent = pWin->GetAccessibleParentWindow(); + if (pParent) + { + Rectangle aParentRect = pParent->GetWindowExtentsRelative( NULL ); + awt::Point aParentScreenLoc( aParentRect.Left(), aParentRect.Top() ); + aBounds.X -= aParentScreenLoc.X; + aBounds.Y -= aParentScreenLoc.Y; + } + } + return aBounds; +} + +static awt::Point lcl_GetLocationOnScreen( Window *pWin ) +{ + // !! see VCLXAccessibleComponent::getLocationOnScreen() + + awt::Point aPos; + if (pWin) + { + Rectangle aRect = pWin->GetWindowExtentsRelative( NULL ); + aPos.X = aRect.Left(); + aPos.Y = aRect.Top(); + } + return aPos; +} + +////////////////////////////////////////////////////////////////////// + +SmGraphicAccessible::SmGraphicAccessible( SmGraphicWindow *pGraphicWin ) : + aAccName ( String(SmResId(RID_DOCUMENTSTR)) ), + nClientId (0), + pWin (pGraphicWin) +{ + OSL_ENSURE( pWin, "SmGraphicAccessible: window missing" ); +} + + +SmGraphicAccessible::SmGraphicAccessible( const SmGraphicAccessible &rSmAcc ) : + SmGraphicAccessibleBaseClass(), + aAccName ( String(SmResId(RID_DOCUMENTSTR)) ), + nClientId (0) +{ + pWin = rSmAcc.pWin; + OSL_ENSURE( pWin, "SmGraphicAccessible: window missing" ); +} + + +SmGraphicAccessible::~SmGraphicAccessible() +{ +} + + +SmDocShell * SmGraphicAccessible::GetDoc_Impl() +{ + SmViewShell *pView = pWin ? pWin->GetView() : 0; + return pView ? pView->GetDoc() : 0; +} + +String SmGraphicAccessible::GetAccessibleText_Impl() +{ + String aTxt; + SmDocShell *pDoc = GetDoc_Impl(); + if (pDoc) + aTxt = pDoc->GetAccessibleText(); + return aTxt; +} + +void SmGraphicAccessible::ClearWin() +{ + pWin = 0; // implicitly results in AccessibleStateType::DEFUNC set + + if ( nClientId ) + { + comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this ); + nClientId = 0; + } +} + +void SmGraphicAccessible::LaunchEvent( + const sal_Int16 nAccesibleEventId, + const uno::Any &rOldVal, + const uno::Any &rNewVal) +{ + AccessibleEventObject aEvt; + aEvt.Source = (XAccessible *) this; + aEvt.EventId = nAccesibleEventId; + aEvt.OldValue = rOldVal; + aEvt.NewValue = rNewVal ; + + // pass event on to event-listener's + if (nClientId) + comphelper::AccessibleEventNotifier::addEvent( nClientId, aEvt ); +} + +uno::Reference< XAccessibleContext > SAL_CALL SmGraphicAccessible::getAccessibleContext() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return this; +} + +sal_Bool SAL_CALL SmGraphicAccessible::containsPoint( const awt::Point& aPoint ) + throw (RuntimeException) +{ + //! the arguments coordinates are relativ to the current window ! + //! Thus the top-left point is (0, 0) + + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + + Size aSz( pWin->GetSizePixel() ); + return aPoint.X >= 0 && aPoint.Y >= 0 && + aPoint.X < aSz.Width() && aPoint.Y < aSz.Height(); +} + +uno::Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleAtPoint( + const awt::Point& aPoint ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + XAccessible *pRes = 0; + if (containsPoint( aPoint )) + pRes = this; + return pRes; +} + +awt::Rectangle SAL_CALL SmGraphicAccessible::getBounds() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(), + "mismatch of window parent and accessible parent" ); + return lcl_GetBounds( pWin ); +} + +awt::Point SAL_CALL SmGraphicAccessible::getLocation() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(), + "mismatch of window parent and accessible parent" ); + awt::Rectangle aRect( lcl_GetBounds( pWin ) ); + return awt::Point( aRect.X, aRect.Y ); +} + +awt::Point SAL_CALL SmGraphicAccessible::getLocationOnScreen() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(), + "mismatch of window parent and accessible parent" ); + return lcl_GetLocationOnScreen( pWin ); +} + +awt::Size SAL_CALL SmGraphicAccessible::getSize() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(), + "mismatch of window parent and accessible parent" ); + + Size aSz( pWin->GetSizePixel() ); +#if OSL_DEBUG_LEVEL > 1 + awt::Rectangle aRect( lcl_GetBounds( pWin ) ); + Size aSz2( aRect.Width, aRect.Height ); + OSL_ENSURE( aSz == aSz2, "mismatch in width" ); +#endif + return awt::Size( aSz.Width(), aSz.Height() ); +} + +void SAL_CALL SmGraphicAccessible::grabFocus() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + + pWin->GrabFocus(); +} + +sal_Int32 SAL_CALL SmGraphicAccessible::getForeground() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + + if (!pWin) + throw RuntimeException(); + return (sal_Int32) pWin->GetTextColor().GetColor(); +} + +sal_Int32 SAL_CALL SmGraphicAccessible::getBackground() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + + if (!pWin) + throw RuntimeException(); + Wallpaper aWall( pWin->GetDisplayBackground() ); + ColorData nCol; + if (aWall.IsBitmap() || aWall.IsGradient()) + nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor().GetColor(); + else + nCol = aWall.GetColor().GetColor(); + return (sal_Int32) nCol; +} + +sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleChildCount() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return 0; +} + +Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleChild( + sal_Int32 /*i*/ ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + SolarMutexGuard aGuard; + throw IndexOutOfBoundsException(); // there is no child... +} + +Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleParent() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + + Window *pAccParent = pWin->GetAccessibleParentWindow(); + OSL_ENSURE( pAccParent, "accessible parent missing" ); + return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >(); +} + +sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleIndexInParent() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + sal_Int32 nIdx = -1; + Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : 0; + if (pAccParent) + { + sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount(); + for (sal_uInt16 i = 0; i < nCnt && nIdx == -1; ++i) + if (pAccParent->GetAccessibleChildWindow( i ) == pWin) + nIdx = i; + } + return nIdx; +} + +sal_Int16 SAL_CALL SmGraphicAccessible::getAccessibleRole() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return AccessibleRole::DOCUMENT; +} + +OUString SAL_CALL SmGraphicAccessible::getAccessibleDescription() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + SmDocShell *pDoc = GetDoc_Impl(); + return pDoc ? OUString(pDoc->GetText()) : OUString(); +} + +OUString SAL_CALL SmGraphicAccessible::getAccessibleName() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return aAccName; +} + +Reference< XAccessibleRelationSet > SAL_CALL SmGraphicAccessible::getAccessibleRelationSet() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper(); + return xRelSet; // empty relation set +} + +Reference< XAccessibleStateSet > SAL_CALL SmGraphicAccessible::getAccessibleStateSet() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + ::utl::AccessibleStateSetHelper *pStateSet = + new ::utl::AccessibleStateSetHelper; + + Reference<XAccessibleStateSet> xStateSet( pStateSet ); + + if (!pWin) + pStateSet->AddState( AccessibleStateType::DEFUNC ); + else + { + pStateSet->AddState( AccessibleStateType::ENABLED ); + pStateSet->AddState( AccessibleStateType::FOCUSABLE ); + if (pWin->HasFocus()) + pStateSet->AddState( AccessibleStateType::FOCUSED ); + if (pWin->IsActive()) + pStateSet->AddState( AccessibleStateType::ACTIVE ); + if (pWin->IsVisible()) + pStateSet->AddState( AccessibleStateType::SHOWING ); + if (pWin->IsReallyVisible()) + pStateSet->AddState( AccessibleStateType::VISIBLE ); + if (COL_TRANSPARENT != pWin->GetBackground().GetColor().GetColor()) + pStateSet->AddState( AccessibleStateType::OPAQUE ); + } + + return xStateSet; +} + +Locale SAL_CALL SmGraphicAccessible::getLocale() + throw (IllegalAccessibleComponentStateException, RuntimeException) +{ + SolarMutexGuard aGuard; + // should be the document language... + // We use the language of the localized symbol names here. + return Application::GetSettings().GetUILocale(); +} + + +void SAL_CALL SmGraphicAccessible::addEventListener( + const Reference< XAccessibleEventListener >& xListener ) + throw (RuntimeException) +{ + if (xListener.is()) + { + SolarMutexGuard aGuard; + if (pWin) + { + if (!nClientId) + nClientId = comphelper::AccessibleEventNotifier::registerClient( ); + comphelper::AccessibleEventNotifier::addEventListener( nClientId, xListener ); + } + } +} + +void SAL_CALL SmGraphicAccessible::removeEventListener( + const Reference< XAccessibleEventListener >& xListener ) + throw (RuntimeException) +{ + if (xListener.is()) + { + SolarMutexGuard aGuard; + sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( nClientId, xListener ); + if ( !nListenerCount ) + { + // no listeners anymore + // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), + // and at least to us not firing any events anymore, in case somebody calls + // NotifyAccessibleEvent, again + comphelper::AccessibleEventNotifier::revokeClient( nClientId ); + nClientId = 0; + } + } +} + +sal_Int32 SAL_CALL SmGraphicAccessible::getCaretPosition() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return 0; +} + +sal_Bool SAL_CALL SmGraphicAccessible::setCaretPosition( sal_Int32 nIndex ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + SolarMutexGuard aGuard; + xub_StrLen nIdx = (xub_StrLen) nIndex; + String aTxt( GetAccessibleText_Impl() ); + if (!(nIdx < aTxt.Len())) + throw IndexOutOfBoundsException(); + return sal_False; +} + +sal_Unicode SAL_CALL SmGraphicAccessible::getCharacter( sal_Int32 nIndex ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + SolarMutexGuard aGuard; + + xub_StrLen nIdx = (xub_StrLen) nIndex; + String aTxt( GetAccessibleText_Impl() ); + if (!(nIdx < aTxt.Len())) + throw IndexOutOfBoundsException(); + return aTxt.GetChar( nIdx ); +} + +Sequence< beans::PropertyValue > SAL_CALL SmGraphicAccessible::getCharacterAttributes( + sal_Int32 nIndex, + const uno::Sequence< ::rtl::OUString > & /*rRequestedAttributes*/ ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + SolarMutexGuard aGuard; + sal_Int32 nLen = GetAccessibleText_Impl().Len(); + if (!(0 <= nIndex && nIndex < nLen)) + throw IndexOutOfBoundsException(); + return Sequence< beans::PropertyValue >(); +} + +awt::Rectangle SAL_CALL SmGraphicAccessible::getCharacterBounds( sal_Int32 nIndex ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + SolarMutexGuard aGuard; + + awt::Rectangle aRes; + + if (!pWin) + throw RuntimeException(); + else + { + // get accessible text + SmViewShell *pView = pWin->GetView(); + SmDocShell *pDoc = pView ? pView->GetDoc() : 0; + if (!pDoc) + throw RuntimeException(); + String aTxt( GetAccessibleText_Impl() ); + if (!(0 <= nIndex && nIndex <= aTxt.Len())) // aTxt.Len() is valid + throw IndexOutOfBoundsException(); + + // find a reasonable rectangle for position aTxt.Len(). + bool bWasBehindText = (nIndex == aTxt.Len()); + if (bWasBehindText && nIndex) + --nIndex; + + const SmNode *pTree = pDoc->GetFormulaTree(); + const SmNode *pNode = pTree->FindNodeWithAccessibleIndex( (xub_StrLen) nIndex ); + //! pNode may be 0 if the index belongs to a char that was inserted + //! only for the accessible text! + if (pNode) + { + sal_Int32 nAccIndex = pNode->GetAccessibleIndex(); + OSL_ENSURE( nAccIndex >= 0, "invalid accessible index" ); + OSL_ENSURE( nIndex >= nAccIndex, "index out of range" ); + + String aNodeText; + pNode->GetAccessibleText( aNodeText ); + sal_Int32 nNodeIndex = nIndex - nAccIndex; + if (0 <= nNodeIndex && nNodeIndex < aNodeText.Len()) + { + // get appropriate rectangle + Point aOffset(pNode->GetTopLeft() - pTree->GetTopLeft()); + Point aTLPos (pWin->GetFormulaDrawPos() + aOffset); + aTLPos.X() -= 0; + Size aSize (pNode->GetSize()); + + sal_Int32 *pXAry = new sal_Int32[ aNodeText.Len() ]; + pWin->SetFont( pNode->GetFont() ); + pWin->GetTextArray( aNodeText, pXAry, 0, aNodeText.Len() ); + aTLPos.X() += nNodeIndex > 0 ? pXAry[nNodeIndex - 1] : 0; + aSize.Width() = nNodeIndex > 0 ? pXAry[nNodeIndex] - pXAry[nNodeIndex - 1] : pXAry[nNodeIndex]; + delete[] pXAry; + +#if OSL_DEBUG_LEVEL > 1 + Point aLP00( pWin->LogicToPixel( Point(0,0)) ); + Point aPL00( pWin->PixelToLogic( Point(0,0)) ); +#endif + aTLPos = pWin->LogicToPixel( aTLPos ); + aSize = pWin->LogicToPixel( aSize ); + aRes.X = aTLPos.X(); + aRes.Y = aTLPos.Y(); + aRes.Width = aSize.Width(); + aRes.Height = aSize.Height(); + } + } + + // take rectangle from last character and move it to the right + if (bWasBehindText) + aRes.X += aRes.Width; + } + + return aRes; +} + +sal_Int32 SAL_CALL SmGraphicAccessible::getCharacterCount() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return GetAccessibleText_Impl().Len(); +} + +sal_Int32 SAL_CALL SmGraphicAccessible::getIndexAtPoint( const awt::Point& aPoint ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + + sal_Int32 nRes = -1; + if (pWin) + { + const SmNode *pTree = pWin->GetView()->GetDoc()->GetFormulaTree(); + //! kann NULL sein! ZB wenn bereits beim laden des Dokuments (bevor der + //! Parser angeworfen wurde) ins Fenster geklickt wird. + if (!pTree) + return nRes; + + // get position relativ to formula draw position + Point aPos( aPoint.X, aPoint.Y ); + aPos = pWin->PixelToLogic( aPos ); + aPos -= pWin->GetFormulaDrawPos(); + + // if it was inside the formula then get the appropriate node + const SmNode *pNode = 0; + if (pTree->OrientedDist(aPos) <= 0) + pNode = pTree->FindRectClosestTo(aPos); + + if (pNode) + { + // get appropriate rectangle + Point aOffset( pNode->GetTopLeft() - pTree->GetTopLeft() ); + Point aTLPos ( aOffset ); + aTLPos.X() -= 0; + Size aSize( pNode->GetSize() ); +#if OSL_DEBUG_LEVEL > 1 + Point aLP00( pWin->LogicToPixel( Point(0,0)) ); + Point aPL00( pWin->PixelToLogic( Point(0,0)) ); +#endif + + Rectangle aRect( aTLPos, aSize ); + if (aRect.IsInside( aPos )) + { + OSL_ENSURE( pNode->IsVisible(), "node is not a leaf" ); + String aTxt; + pNode->GetAccessibleText( aTxt ); + OSL_ENSURE( aTxt.Len(), "no accessible text available" ); + + long nNodeX = pNode->GetLeft(); + + sal_Int32 *pXAry = new sal_Int32[ aTxt.Len() ]; + pWin->SetFont( pNode->GetFont() ); + pWin->GetTextArray( aTxt, pXAry, 0, aTxt.Len() ); + for (sal_Int32 i = 0; i < aTxt.Len() && nRes == -1; ++i) + { + if (pXAry[i] + nNodeX > aPos.X()) + nRes = i; + } + delete[] pXAry; + OSL_ENSURE( nRes >= 0 && nRes < aTxt.Len(), "index out of range" ); + OSL_ENSURE( pNode->GetAccessibleIndex() >= 0, + "invalid accessible index" ); + + nRes = pNode->GetAccessibleIndex() + nRes; + } + } + } + return nRes; +} + +OUString SAL_CALL SmGraphicAccessible::getSelectedText() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return OUString(); +} + +sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionStart() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return -1; +} + +sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionEnd() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return -1; +} + +sal_Bool SAL_CALL SmGraphicAccessible::setSelection( + sal_Int32 nStartIndex, + sal_Int32 nEndIndex ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + SolarMutexGuard aGuard; + sal_Int32 nLen = GetAccessibleText_Impl().Len(); + if (!(0 <= nStartIndex && nStartIndex < nLen) || + !(0 <= nEndIndex && nEndIndex < nLen)) + throw IndexOutOfBoundsException(); + return sal_False; +} + +OUString SAL_CALL SmGraphicAccessible::getText() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return GetAccessibleText_Impl(); +} + +OUString SAL_CALL SmGraphicAccessible::getTextRange( + sal_Int32 nStartIndex, + sal_Int32 nEndIndex ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + //!! nEndIndex may be the string length per definition of the interface !! + //!! text should be copied exclusive that end index though. And arguments + //!! may be switched. + + SolarMutexGuard aGuard; + String aTxt( GetAccessibleText_Impl() ); + xub_StrLen nStart = (xub_StrLen) Min(nStartIndex, nEndIndex); + xub_StrLen nEnd = (xub_StrLen) Max(nStartIndex, nEndIndex); + if (!(nStart <= aTxt.Len()) || + !(nEnd <= aTxt.Len())) + throw IndexOutOfBoundsException(); + return aTxt.Copy( nStart, nEnd - nStart ); +} + +::com::sun::star::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + String aTxt( GetAccessibleText_Impl() ); + xub_StrLen nIdx = (xub_StrLen) nIndex; + //!! nIndex is allowed to be the string length + if (!(nIdx <= aTxt.Len())) + throw IndexOutOfBoundsException(); + + ::com::sun::star::accessibility::TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + if ( (AccessibleTextType::CHARACTER == aTextType) && (nIdx < aTxt.Len()) ) + { + aResult.SegmentText = aTxt.Copy(nIdx, 1); + aResult.SegmentStart = nIdx; + aResult.SegmentEnd = nIdx+1; + } + return aResult; +} + +::com::sun::star::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + String aTxt( GetAccessibleText_Impl() ); + xub_StrLen nIdx = (xub_StrLen) nIndex; + //!! nIndex is allowed to be the string length + if (!(nIdx <= aTxt.Len())) + throw IndexOutOfBoundsException(); + + ::com::sun::star::accessibility::TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + if ( (AccessibleTextType::CHARACTER == aTextType) && nIdx ) + { + aResult.SegmentText = aTxt.Copy(nIdx-1, 1); + aResult.SegmentStart = nIdx-1; + aResult.SegmentEnd = nIdx; + } + return aResult; +} + +::com::sun::star::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + String aTxt( GetAccessibleText_Impl() ); + xub_StrLen nIdx = (xub_StrLen) nIndex; + //!! nIndex is allowed to be the string length + if (!(nIdx <= aTxt.Len())) + throw IndexOutOfBoundsException(); + + ::com::sun::star::accessibility::TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + nIdx++; // text *behind* + if ( (AccessibleTextType::CHARACTER == aTextType) && (nIdx < aTxt.Len()) ) + { + aResult.SegmentText = aTxt.Copy(nIdx, 1); + aResult.SegmentStart = nIdx; + aResult.SegmentEnd = nIdx+1; + } + return aResult; +} + +sal_Bool SAL_CALL SmGraphicAccessible::copyText( + sal_Int32 nStartIndex, + sal_Int32 nEndIndex ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + SolarMutexGuard aGuard; + sal_Bool bReturn = sal_False; + + if (!pWin) + throw RuntimeException(); + else + { + Reference< datatransfer::clipboard::XClipboard > xClipboard = pWin->GetClipboard(); + if ( xClipboard.is() ) + { + ::rtl::OUString sText( getTextRange(nStartIndex, nEndIndex) ); + + ::vcl::unohelper::TextDataObject* pDataObj = new ::vcl::unohelper::TextDataObject( sText ); + const sal_uInt32 nRef = Application::ReleaseSolarMutex(); + xClipboard->setContents( pDataObj, NULL ); + + Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY ); + if( xFlushableClipboard.is() ) + xFlushableClipboard->flushClipboard(); + + Application::AcquireSolarMutex( nRef ); + + bReturn = sal_True; + } + } + + return bReturn; +} + +OUString SAL_CALL SmGraphicAccessible::getImplementationName() + throw (RuntimeException) +{ + return A2OU("SmGraphicAccessible"); +} + +sal_Bool SAL_CALL SmGraphicAccessible::supportsService( + const OUString& rServiceName ) + throw (RuntimeException) +{ + return rServiceName == A2OU( "com::sun::star::accessibility::Accessible" ) || + rServiceName == A2OU( "com::sun::star::accessibility::AccessibleComponent" ) || + rServiceName == A2OU( "com::sun::star::accessibility::AccessibleContext" ) || + rServiceName == A2OU( "com::sun::star::accessibility::AccessibleText" ); +} + +Sequence< OUString > SAL_CALL SmGraphicAccessible::getSupportedServiceNames() + throw (RuntimeException) +{ + Sequence< OUString > aNames(4); + OUString *pNames = aNames.getArray(); + pNames[0] = A2OU( "com::sun::star::accessibility::Accessible" ); + pNames[1] = A2OU( "com::sun::star::accessibility::AccessibleComponent" ); + pNames[2] = A2OU( "com::sun::star::accessibility::AccessibleContext" ); + pNames[3] = A2OU( "com::sun::star::accessibility::AccessibleText" ); + return aNames; +} + +////////////////////////////////////////////////////////////////////// + +//------------------------------------------------------------------------ + +SmEditSource::SmEditSource( SmEditWindow * /*pWin*/, SmEditAccessible &rAcc ) : + aViewFwd (rAcc), + aTextFwd (rAcc, *this), + aEditViewFwd(rAcc), + rEditAcc (rAcc) +{ +} + +SmEditSource::SmEditSource( const SmEditSource &rSrc ) : + SvxEditSource(), + aViewFwd (rSrc.rEditAcc), + aTextFwd (rSrc.rEditAcc, *this), + aEditViewFwd(rSrc.rEditAcc), + rEditAcc (rSrc.rEditAcc) +{ +} + +SmEditSource::~SmEditSource() +{ +} + +SvxEditSource* SmEditSource::Clone() const +{ + return new SmEditSource( *this ); +} + +SvxTextForwarder* SmEditSource::GetTextForwarder() +{ + return &aTextFwd; +} + +SvxViewForwarder* SmEditSource::GetViewForwarder() +{ + return &aViewFwd; +} + +SvxEditViewForwarder* SmEditSource::GetEditViewForwarder( sal_Bool /*bCreate*/ ) +{ + return &aEditViewFwd; +} + +void SmEditSource::UpdateData() +{ + // would possibly only by needed if the XText inteface is implemented + // and its text needs to be updated. +} + +SfxBroadcaster & SmEditSource::GetBroadcaster() const +{ + return ((SmEditSource *) this)->aBroadCaster; +} + +//------------------------------------------------------------------------ + +SmViewForwarder::SmViewForwarder( SmEditAccessible &rAcc ) : + rEditAcc(rAcc) +{ +} + +SmViewForwarder::~SmViewForwarder() +{ +} + +sal_Bool SmViewForwarder::IsValid() const +{ + return rEditAcc.GetEditView() != 0; +} + +Rectangle SmViewForwarder::GetVisArea() const +{ + EditView *pEditView = rEditAcc.GetEditView(); + OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0; + + if( pOutDev && pEditView) + { + Rectangle aVisArea = pEditView->GetVisArea(); + + // figure out map mode from edit engine + EditEngine* pEditEngine = pEditView->GetEditEngine(); + + if( pEditEngine ) + { + MapMode aMapMode(pOutDev->GetMapMode()); + aVisArea = OutputDevice::LogicToLogic( aVisArea, + pEditEngine->GetRefMapMode(), + aMapMode.GetMapUnit() ); + aMapMode.SetOrigin(Point()); + return pOutDev->LogicToPixel( aVisArea, aMapMode ); + } + } + + return Rectangle(); +} + +Point SmViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const +{ + EditView *pEditView = rEditAcc.GetEditView(); + OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0; + + if( pOutDev ) + { + MapMode aMapMode(pOutDev->GetMapMode()); + Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode, + aMapMode.GetMapUnit() ) ); + aMapMode.SetOrigin(Point()); + return pOutDev->LogicToPixel( aPoint, aMapMode ); + } + + return Point(); +} + +Point SmViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const +{ + EditView *pEditView = rEditAcc.GetEditView(); + OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0; + + if( pOutDev ) + { + MapMode aMapMode(pOutDev->GetMapMode()); + aMapMode.SetOrigin(Point()); + Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) ); + return OutputDevice::LogicToLogic( aPoint, + aMapMode.GetMapUnit(), + rMapMode ); + } + + return Point(); +} + + +//------------------------------------------------------------------------ + +SmTextForwarder::SmTextForwarder( SmEditAccessible& rAcc, SmEditSource & rSource) : + rEditAcc ( rAcc ), + rEditSource (rSource) +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + pEditEngine->SetNotifyHdl( LINK(this, SmTextForwarder, NotifyHdl) ); +} + +SmTextForwarder::~SmTextForwarder() +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + pEditEngine->SetNotifyHdl( Link() ); +} + +IMPL_LINK(SmTextForwarder, NotifyHdl, EENotify*, aNotify) +{ + if (aNotify) + { + ::std::auto_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( aNotify ); + if (aHint.get()) + rEditSource.GetBroadcaster().Broadcast( *aHint.get() ); + } + + return 0; +} + +sal_uInt16 SmTextForwarder::GetParagraphCount() const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetParagraphCount() : 0; +} + +sal_uInt16 SmTextForwarder::GetTextLen( sal_uInt16 nParagraph ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetTextLen( nParagraph ) : 0; +} + +String SmTextForwarder::GetText( const ESelection& rSel ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + String aRet; + if (pEditEngine) + aRet = pEditEngine->GetText( rSel, LINEEND_LF ); + aRet.ConvertLineEnd(); + return aRet; +} + +SfxItemSet SmTextForwarder::GetAttribs( const ESelection& rSel, sal_Bool bOnlyHardAttrib ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + OSL_ENSURE( pEditEngine, "EditEngine missing" ); + if( rSel.nStartPara == rSel.nEndPara ) + { + sal_uInt8 nFlags = 0; + switch( bOnlyHardAttrib ) + { + case EditEngineAttribs_All: + nFlags = GETATTRIBS_ALL; + break; + case EditEngineAttribs_HardAndPara: + nFlags = GETATTRIBS_PARAATTRIBS|GETATTRIBS_CHARATTRIBS; + break; + case EditEngineAttribs_OnlyHard: + nFlags = GETATTRIBS_CHARATTRIBS; + break; + default: + OSL_FAIL("unknown flags for SmTextForwarder::GetAttribs"); + } + + return pEditEngine->GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags ); + } + else + { + return pEditEngine->GetAttribs( rSel, bOnlyHardAttrib ); + } +} + +SfxItemSet SmTextForwarder::GetParaAttribs( sal_uInt16 nPara ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + OSL_ENSURE( pEditEngine, "EditEngine missing" ); + + SfxItemSet aSet( pEditEngine->GetParaAttribs( nPara ) ); + + sal_uInt16 nWhich = EE_PARA_START; + while( nWhich <= EE_PARA_END ) + { + if( aSet.GetItemState( nWhich, sal_True ) != SFX_ITEM_ON ) + { + if( pEditEngine->HasParaAttrib( nPara, nWhich ) ) + aSet.Put( pEditEngine->GetParaAttrib( nPara, nWhich ) ); + } + nWhich++; + } + + return aSet; +} + +void SmTextForwarder::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet ) +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + pEditEngine->SetParaAttribs( nPara, rSet ); +} + +SfxItemPool* SmTextForwarder::GetPool() const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetEmptyItemSet().GetPool() : 0; +} + +void SmTextForwarder::RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich ) +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + pEditEngine->RemoveAttribs( rSelection, bRemoveParaAttribs, nWhich ); +} + +void SmTextForwarder::GetPortions( sal_uInt16 nPara, std::vector<sal_uInt16>& rList ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + pEditEngine->GetPortions( nPara, rList ); +} + +void SmTextForwarder::QuickInsertText( const String& rText, const ESelection& rSel ) +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + pEditEngine->QuickInsertText( rText, rSel ); +} + +void SmTextForwarder::QuickInsertLineBreak( const ESelection& rSel ) +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + pEditEngine->QuickInsertLineBreak( rSel ); +} + +void SmTextForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel ) +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + pEditEngine->QuickInsertField( rFld, rSel ); +} + +void SmTextForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel ) +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + pEditEngine->QuickSetAttribs( rSet, rSel ); +} + +sal_Bool SmTextForwarder::IsValid() const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + // cannot reliably query EditEngine state + // while in the middle of an update + return pEditEngine ? pEditEngine->GetUpdateMode() : sal_False; +} + +XubString SmTextForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_uInt16 nPara, sal_uInt16 nPos, Color*& rpTxtColor, Color*& rpFldColor ) +{ + XubString aTxt; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + aTxt = pEditEngine->CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor ); + return aTxt; +} + +void SmTextForwarder::FieldClicked(const SvxFieldItem&, sal_uInt16, sal_uInt16) +{ +} + +sal_uInt16 GetSvxEditEngineItemState( EditEngine& rEditEngine, const ESelection& rSel, sal_uInt16 nWhich ) +{ + EECharAttribArray aAttribs; + + const SfxPoolItem* pLastItem = NULL; + + SfxItemState eState = SFX_ITEM_DEFAULT; + + // check all paragraphs inside the selection + for( sal_uInt16 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ ) + { + SfxItemState eParaState = SFX_ITEM_DEFAULT; + + // calculate start and endpos for this paragraph + sal_uInt16 nPos = 0; + if( rSel.nStartPara == nPara ) + nPos = rSel.nStartPos; + + sal_uInt16 nEndPos = rSel.nEndPos; + if( rSel.nEndPara != nPara ) + nEndPos = rEditEngine.GetTextLen( nPara ); + + + // get list of char attribs + rEditEngine.GetCharAttribs( nPara, aAttribs ); + + bool bEmpty = true; // we found no item inside the selektion of this paragraph + bool bGaps = false; // we found items but theire gaps between them + sal_uInt16 nLastEnd = nPos; + + const SfxPoolItem* pParaItem = NULL; + + for( sal_uInt16 nAttrib = 0; nAttrib < aAttribs.Count(); nAttrib++ ) + { + struct EECharAttrib aAttrib = aAttribs.GetObject( nAttrib ); + OSL_ENSURE( aAttrib.pAttr, "GetCharAttribs gives corrupt data" ); + + const sal_Bool bEmptyPortion = aAttrib.nStart == aAttrib.nEnd; + if( (!bEmptyPortion && (aAttrib.nStart >= nEndPos)) || (bEmptyPortion && (aAttrib.nStart > nEndPos)) ) + break; // break if we are already behind our selektion + + if( (!bEmptyPortion && (aAttrib.nEnd <= nPos)) || (bEmptyPortion && (aAttrib.nEnd < nPos)) ) + continue; // or if the attribute ends before our selektion + + if( aAttrib.pAttr->Which() != nWhich ) + continue; // skip if is not the searched item + + // if we already found an item + if( pParaItem ) + { + // ... and its different to this one than the state is dont care + if( *pParaItem != *aAttrib.pAttr ) + return SFX_ITEM_DONTCARE; + } + else + { + pParaItem = aAttrib.pAttr; + } + + if( bEmpty ) + bEmpty = false; + + if( !bGaps && aAttrib.nStart > nLastEnd ) + bGaps = true; + + nLastEnd = aAttrib.nEnd; + } + + if( !bEmpty && !bGaps && nLastEnd < ( nEndPos - 1 ) ) + bGaps = true; + if( bEmpty ) + eParaState = SFX_ITEM_DEFAULT; + else if( bGaps ) + eParaState = SFX_ITEM_DONTCARE; + else + eParaState = SFX_ITEM_SET; + + // if we already found an item check if we found the same + if( pLastItem ) + { + if( (pParaItem == NULL) || (*pLastItem != *pParaItem) ) + return SFX_ITEM_DONTCARE; + } + else + { + pLastItem = pParaItem; + eState = eParaState; + } + } + + return eState; +} + +sal_uInt16 SmTextForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const +{ + sal_uInt16 nState = SFX_ITEM_DISABLED; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + nState = GetSvxEditEngineItemState( *pEditEngine, rSel, nWhich ); + return nState; +} + +sal_uInt16 SmTextForwarder::GetItemState( sal_uInt16 nPara, sal_uInt16 nWhich ) const +{ + sal_uInt16 nState = SFX_ITEM_DISABLED; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + { + const SfxItemSet& rSet = pEditEngine->GetParaAttribs( nPara ); + nState = rSet.GetItemState( nWhich ); + } + return nState; +} + +LanguageType SmTextForwarder::GetLanguage( sal_uInt16 nPara, sal_uInt16 nIndex ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetLanguage(nPara, nIndex) : LANGUAGE_NONE; +} + +sal_uInt16 SmTextForwarder::GetFieldCount( sal_uInt16 nPara ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetFieldCount(nPara) : 0; +} + +EFieldInfo SmTextForwarder::GetFieldInfo( sal_uInt16 nPara, sal_uInt16 nField ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetFieldInfo( nPara, nField ) : EFieldInfo(); +} + +EBulletInfo SmTextForwarder::GetBulletInfo( sal_uInt16 /*nPara*/ ) const +{ + return EBulletInfo(); +} + +Rectangle SmTextForwarder::GetCharBounds( sal_uInt16 nPara, sal_uInt16 nIndex ) const +{ + Rectangle aRect(0,0,0,0); + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + + if (pEditEngine) + { + // Handle virtual position one-past-the end of the string + if( nIndex >= pEditEngine->GetTextLen(nPara) ) + { + if( nIndex ) + aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex-1) ); + + aRect.Move( aRect.Right() - aRect.Left(), 0 ); + aRect.SetSize( Size(1, pEditEngine->GetTextHeight()) ); + } + else + { + aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex) ); + } + } + return aRect; +} + +Rectangle SmTextForwarder::GetParaBounds( sal_uInt16 nPara ) const +{ + Rectangle aRect(0,0,0,0); + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + + if (pEditEngine) + { + const Point aPnt = pEditEngine->GetDocPosTopLeft( nPara ); + const sal_uLong nWidth = pEditEngine->CalcTextWidth(); + const sal_uLong nHeight = pEditEngine->GetTextHeight( nPara ); + aRect = Rectangle( aPnt.X(), aPnt.Y(), aPnt.X() + nWidth, aPnt.Y() + nHeight ); + } + + return aRect; +} + +MapMode SmTextForwarder::GetMapMode() const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetRefMapMode() : MapMode( MAP_100TH_MM ); +} + +OutputDevice* SmTextForwarder::GetRefDevice() const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetRefDevice() : 0; +} + +sal_Bool SmTextForwarder::GetIndexAtPoint( const Point& rPos, sal_uInt16& nPara, sal_uInt16& nIndex ) const +{ + sal_Bool bRes = sal_False; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + { + EPosition aDocPos = pEditEngine->FindDocPosition( rPos ); + nPara = aDocPos.nPara; + nIndex = aDocPos.nIndex; + bRes = sal_True; + } + return bRes; +} + +sal_Bool SmTextForwarder::GetWordIndices( sal_uInt16 nPara, sal_uInt16 nIndex, sal_uInt16& nStart, sal_uInt16& nEnd ) const +{ + sal_Bool bRes = sal_False; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + { + ESelection aRes = pEditEngine->GetWord( ESelection(nPara, nIndex, nPara, nIndex), com::sun::star::i18n::WordType::DICTIONARY_WORD ); + + if( aRes.nStartPara == nPara && + aRes.nStartPara == aRes.nEndPara ) + { + nStart = aRes.nStartPos; + nEnd = aRes.nEndPos; + + bRes = sal_True; + } + } + + return bRes; +} + +sal_Bool SmTextForwarder::GetAttributeRun( sal_uInt16& nStartIndex, sal_uInt16& nEndIndex, sal_uInt16 nPara, sal_uInt16 nIndex ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? + SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, *pEditEngine, nPara, nIndex ) + : sal_False; +} + +sal_uInt16 SmTextForwarder::GetLineCount( sal_uInt16 nPara ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetLineCount(nPara) : 0; +} + +sal_uInt16 SmTextForwarder::GetLineLen( sal_uInt16 nPara, sal_uInt16 nLine ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetLineLen(nPara, nLine) : 0; +} + +void SmTextForwarder::GetLineBoundaries( /*out*/sal_uInt16 &rStart, /*out*/sal_uInt16 &rEnd, sal_uInt16 nPara, sal_uInt16 nLine ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + pEditEngine->GetLineBoundaries(rStart, rEnd, nPara, nLine); +} + +sal_uInt16 SmTextForwarder::GetLineNumberAtIndex( sal_uInt16 nPara, sal_uInt16 nIndex ) const +{ + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + return pEditEngine ? pEditEngine->GetLineNumberAtIndex(nPara, nIndex) : 0; +} + +sal_Bool SmTextForwarder::QuickFormatDoc( sal_Bool /*bFull*/ ) +{ + sal_Bool bRes = sal_False; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + { + pEditEngine->QuickFormatDoc(); + bRes = sal_True; + } + return bRes; +} + +sal_Int16 SmTextForwarder::GetDepth( sal_uInt16 /*nPara*/ ) const +{ + // math has no outliner... + return -1; +} + +sal_Bool SmTextForwarder::SetDepth( sal_uInt16 /*nPara*/, sal_Int16 nNewDepth ) +{ + // math has no outliner... + return -1 == nNewDepth; // is it the value from 'GetDepth' ? +} + +sal_Bool SmTextForwarder::Delete( const ESelection& rSelection ) +{ + sal_Bool bRes = sal_False; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + { + pEditEngine->QuickDelete( rSelection ); + pEditEngine->QuickFormatDoc(); + bRes = sal_True; + } + return bRes; +} + +sal_Bool SmTextForwarder::InsertText( const String& rStr, const ESelection& rSelection ) +{ + sal_Bool bRes = sal_False; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + { + pEditEngine->QuickInsertText( rStr, rSelection ); + pEditEngine->QuickFormatDoc(); + bRes = sal_True; + } + return bRes; +} + +const SfxItemSet* SmTextForwarder::GetEmptyItemSetPtr() +{ + const SfxItemSet *pItemSet = 0; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + { + pItemSet = &pEditEngine->GetEmptyItemSet(); + } + return pItemSet; +} + +void SmTextForwarder::AppendParagraph() +{ + // append an empty paragraph + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine) + { + sal_uInt16 nParaCount = pEditEngine->GetParagraphCount(); + pEditEngine->InsertParagraph( nParaCount, String() ); + } +} + +xub_StrLen SmTextForwarder::AppendTextPortion( sal_uInt16 nPara, const String &rText, const SfxItemSet &rSet ) +{ + xub_StrLen nRes = 0; + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine && nPara < pEditEngine->GetParagraphCount()) + { + // append text + ESelection aSel( nPara, pEditEngine->GetTextLen( nPara ) ); + pEditEngine->QuickInsertText( rText, aSel ); + + // set attributes for new appended text + nRes = aSel.nEndPos = pEditEngine->GetTextLen( nPara ); + pEditEngine->QuickSetAttribs( rSet, aSel ); + } + return nRes; +} + +void SmTextForwarder::CopyText(const SvxTextForwarder& rSource) +{ + + const SmTextForwarder* pSourceForwarder = dynamic_cast< const SmTextForwarder* >( &rSource ); + if( !pSourceForwarder ) + return; + EditEngine* pSourceEditEngine = pSourceForwarder->rEditAcc.GetEditEngine(); + EditEngine *pEditEngine = rEditAcc.GetEditEngine(); + if (pEditEngine && pSourceEditEngine ) + { + EditTextObject* pNewTextObject = pSourceEditEngine->CreateTextObject(); + pEditEngine->SetText( *pNewTextObject ); + delete pNewTextObject; + } +} + +//------------------------------------------------------------------------ + +SmEditViewForwarder::SmEditViewForwarder( SmEditAccessible& rAcc ) : + rEditAcc( rAcc ) +{ +} + +SmEditViewForwarder::~SmEditViewForwarder() +{ +} + +sal_Bool SmEditViewForwarder::IsValid() const +{ + return rEditAcc.GetEditView() != 0; +} + +Rectangle SmEditViewForwarder::GetVisArea() const +{ + Rectangle aRect(0,0,0,0); + + EditView *pEditView = rEditAcc.GetEditView(); + OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0; + + if( pOutDev && pEditView) + { + Rectangle aVisArea = pEditView->GetVisArea(); + + // figure out map mode from edit engine + EditEngine* pEditEngine = pEditView->GetEditEngine(); + + if( pEditEngine ) + { + MapMode aMapMode(pOutDev->GetMapMode()); + aVisArea = OutputDevice::LogicToLogic( aVisArea, + pEditEngine->GetRefMapMode(), + aMapMode.GetMapUnit() ); + aMapMode.SetOrigin(Point()); + aRect = pOutDev->LogicToPixel( aVisArea, aMapMode ); + } + } + + return aRect; +} + +Point SmEditViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const +{ + EditView *pEditView = rEditAcc.GetEditView(); + OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0; + + if( pOutDev ) + { + MapMode aMapMode(pOutDev->GetMapMode()); + Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode, + aMapMode.GetMapUnit() ) ); + aMapMode.SetOrigin(Point()); + return pOutDev->LogicToPixel( aPoint, aMapMode ); + } + + return Point(); +} + +Point SmEditViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const +{ + EditView *pEditView = rEditAcc.GetEditView(); + OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0; + + if( pOutDev ) + { + MapMode aMapMode(pOutDev->GetMapMode()); + aMapMode.SetOrigin(Point()); + Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) ); + return OutputDevice::LogicToLogic( aPoint, + aMapMode.GetMapUnit(), + rMapMode ); + } + + return Point(); +} + +sal_Bool SmEditViewForwarder::GetSelection( ESelection& rSelection ) const +{ + sal_Bool bRes = sal_False; + EditView *pEditView = rEditAcc.GetEditView(); + if (pEditView) + { + rSelection = pEditView->GetSelection(); + bRes = sal_True; + } + return bRes; +} + +sal_Bool SmEditViewForwarder::SetSelection( const ESelection& rSelection ) +{ + sal_Bool bRes = sal_False; + EditView *pEditView = rEditAcc.GetEditView(); + if (pEditView) + { + pEditView->SetSelection( rSelection ); + bRes = sal_True; + } + return bRes; +} + +sal_Bool SmEditViewForwarder::Copy() +{ + sal_Bool bRes = sal_False; + EditView *pEditView = rEditAcc.GetEditView(); + if (pEditView) + { + pEditView->Copy(); + bRes = sal_True; + } + return bRes; +} + +sal_Bool SmEditViewForwarder::Cut() +{ + sal_Bool bRes = sal_False; + EditView *pEditView = rEditAcc.GetEditView(); + if (pEditView) + { + pEditView->Cut(); + bRes = sal_True; + } + return bRes; +} + +sal_Bool SmEditViewForwarder::Paste() +{ + sal_Bool bRes = sal_False; + EditView *pEditView = rEditAcc.GetEditView(); + if (pEditView) + { + pEditView->Paste(); + bRes = sal_True; + } + return bRes; +} + +//------------------------------------------------------------------------ + +SmEditAccessible::SmEditAccessible( SmEditWindow *pEditWin ) : + aAccName ( String(SmResId(STR_CMDBOXWINDOW)) ), + pTextHelper (0), + pWin (pEditWin) +{ + OSL_ENSURE( pWin, "SmEditAccessible: window missing" ); +} + + +SmEditAccessible::SmEditAccessible( const SmEditAccessible &rSmAcc ) : + SmEditAccessibleBaseClass(), + aAccName ( String(SmResId(STR_CMDBOXWINDOW)) ) +{ + pWin = rSmAcc.pWin; + OSL_ENSURE( pWin, "SmEditAccessible: window missing" ); +} + +SmEditAccessible::~SmEditAccessible() +{ + delete pTextHelper; +} + +void SmEditAccessible::Init() +{ + OSL_ENSURE( pWin, "SmEditAccessible: window missing" ); + if (pWin) + { + EditEngine *pEditEngine = pWin->GetEditEngine(); + EditView *pEditView = pWin->GetEditView(); + if (pEditEngine && pEditView) + { + ::std::auto_ptr< SvxEditSource > pEditSource( + new SmEditSource( pWin, *this ) ); + pTextHelper = new ::accessibility::AccessibleTextHelper( pEditSource ); + pTextHelper->SetEventSource( this ); + } + } +} + +void SmEditAccessible::ClearWin() +{ + // remove handler before current object gets destroyed + // (avoid handler being called for already dead object) + EditEngine *pEditEngine = GetEditEngine(); + if (pEditEngine) + pEditEngine->SetNotifyHdl( Link() ); + + pWin = 0; // implicitly results in AccessibleStateType::DEFUNC set + + //! make TextHelper implicitly release C++ references to some core objects + pTextHelper->SetEditSource( ::std::auto_ptr<SvxEditSource>(NULL) ); + //! make TextHelper release references + //! (e.g. the one set by the 'SetEventSource' call) + pTextHelper->Dispose(); + delete pTextHelper; pTextHelper = 0; +} + +// XAccessible +uno::Reference< XAccessibleContext > SAL_CALL SmEditAccessible::getAccessibleContext( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return this; +} + +// XAccessibleComponent +sal_Bool SAL_CALL SmEditAccessible::containsPoint( const awt::Point& aPoint ) + throw (RuntimeException) +{ + //! the arguments coordinates are relativ to the current window ! + //! Thus the top left-point is (0, 0) + + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + + Size aSz( pWin->GetSizePixel() ); + return aPoint.X >= 0 && aPoint.Y >= 0 && + aPoint.X < aSz.Width() && aPoint.Y < aSz.Height(); +} + +uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleAtPoint( const awt::Point& aPoint ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pTextHelper) + throw RuntimeException(); + return pTextHelper->GetAt( aPoint ); +} + +awt::Rectangle SAL_CALL SmEditAccessible::getBounds( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(), + "mismatch of window parent and accessible parent" ); + return lcl_GetBounds( pWin ); +} + +awt::Point SAL_CALL SmEditAccessible::getLocation( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(), + "mismatch of window parent and accessible parent" ); + awt::Rectangle aRect( lcl_GetBounds( pWin ) ); + return awt::Point( aRect.X, aRect.Y ); +} + +awt::Point SAL_CALL SmEditAccessible::getLocationOnScreen( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(), + "mismatch of window parent and accessible parent" ); + return lcl_GetLocationOnScreen( pWin ); +} + +awt::Size SAL_CALL SmEditAccessible::getSize( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(), + "mismatch of window parent and accessible parent" ); + + Size aSz( pWin->GetSizePixel() ); +#if OSL_DEBUG_LEVEL > 1 + awt::Rectangle aRect( lcl_GetBounds( pWin ) ); + Size aSz2( aRect.Width, aRect.Height ); + OSL_ENSURE( aSz == aSz2, "mismatch in width" ); +#endif + return awt::Size( aSz.Width(), aSz.Height() ); +} + +void SAL_CALL SmEditAccessible::grabFocus( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + + pWin->GrabFocus(); +} + +sal_Int32 SAL_CALL SmEditAccessible::getForeground() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + + if (!pWin) + throw RuntimeException(); + return (sal_Int32) pWin->GetTextColor().GetColor(); +} + +sal_Int32 SAL_CALL SmEditAccessible::getBackground() + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + + if (!pWin) + throw RuntimeException(); + Wallpaper aWall( pWin->GetDisplayBackground() ); + ColorData nCol; + if (aWall.IsBitmap() || aWall.IsGradient()) + nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor().GetColor(); + else + nCol = aWall.GetColor().GetColor(); + return (sal_Int32) nCol; +} + +// XAccessibleContext +sal_Int32 SAL_CALL SmEditAccessible::getAccessibleChildCount( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pTextHelper) + throw RuntimeException(); + return pTextHelper->GetChildCount(); +} + +uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleChild( sal_Int32 i ) + throw (IndexOutOfBoundsException, RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pTextHelper) + throw RuntimeException(); + return pTextHelper->GetChild( i ); +} + +uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleParent( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pWin) + throw RuntimeException(); + + Window *pAccParent = pWin->GetAccessibleParentWindow(); + OSL_ENSURE( pAccParent, "accessible parent missing" ); + return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >(); +} + +sal_Int32 SAL_CALL SmEditAccessible::getAccessibleIndexInParent( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + sal_Int32 nIdx = -1; + Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : 0; + if (pAccParent) + { + sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount(); + for (sal_uInt16 i = 0; i < nCnt && nIdx == -1; ++i) + if (pAccParent->GetAccessibleChildWindow( i ) == pWin) + nIdx = i; + } + return nIdx; +} + +sal_Int16 SAL_CALL SmEditAccessible::getAccessibleRole( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return AccessibleRole::PANEL /*TEXT ?*/; +} + +rtl::OUString SAL_CALL SmEditAccessible::getAccessibleDescription( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + return OUString(); // empty as agreed with product-management +} + +rtl::OUString SAL_CALL SmEditAccessible::getAccessibleName( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + // same name as displayed by the window when not docked + return aAccName; +} + +uno::Reference< XAccessibleRelationSet > SAL_CALL SmEditAccessible::getAccessibleRelationSet( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper(); + return xRelSet; // empty relation set +} + +uno::Reference< XAccessibleStateSet > SAL_CALL SmEditAccessible::getAccessibleStateSet( ) + throw (RuntimeException) +{ + SolarMutexGuard aGuard; + ::utl::AccessibleStateSetHelper *pStateSet = + new ::utl::AccessibleStateSetHelper; + + Reference<XAccessibleStateSet> xStateSet( pStateSet ); + + if (!pWin || !pTextHelper) + pStateSet->AddState( AccessibleStateType::DEFUNC ); + else + { + pStateSet->AddState( AccessibleStateType::MULTI_LINE ); + pStateSet->AddState( AccessibleStateType::ENABLED ); + pStateSet->AddState( AccessibleStateType::FOCUSABLE ); + if (pWin->HasFocus()) + pStateSet->AddState( AccessibleStateType::FOCUSED ); + if (pWin->IsActive()) + pStateSet->AddState( AccessibleStateType::ACTIVE ); + if (pWin->IsVisible()) + pStateSet->AddState( AccessibleStateType::SHOWING ); + if (pWin->IsReallyVisible()) + pStateSet->AddState( AccessibleStateType::VISIBLE ); + if (COL_TRANSPARENT != pWin->GetBackground().GetColor().GetColor()) + pStateSet->AddState( AccessibleStateType::OPAQUE ); + } + + return xStateSet; +} + +Locale SAL_CALL SmEditAccessible::getLocale( ) + throw (IllegalAccessibleComponentStateException, RuntimeException) +{ + SolarMutexGuard aGuard; + // should be the document language... + // We use the language of the localized symbol names here. + return Application::GetSettings().GetUILocale(); +} + + +// XAccessibleEventBroadcaster +void SAL_CALL SmEditAccessible::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) + throw (RuntimeException) +{ + if (pTextHelper) // not disposing (about to destroy view shell) + pTextHelper->AddEventListener( xListener ); +} + +void SAL_CALL SmEditAccessible::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) + throw (RuntimeException) +{ + if (pTextHelper) // not disposing (about to destroy view shell) + pTextHelper->RemoveEventListener( xListener ); +} + +OUString SAL_CALL SmEditAccessible::getImplementationName() + throw (RuntimeException) +{ + return A2OU("SmEditAccessible"); +} + +sal_Bool SAL_CALL SmEditAccessible::supportsService( + const OUString& rServiceName ) + throw (RuntimeException) +{ + return rServiceName == A2OU( "com::sun::star::accessibility::Accessible" ) || + rServiceName == A2OU( "com::sun::star::accessibility::AccessibleComponent" ) || + rServiceName == A2OU( "com::sun::star::accessibility::AccessibleContext" ); +} + +Sequence< OUString > SAL_CALL SmEditAccessible::getSupportedServiceNames() + throw (RuntimeException) +{ + Sequence< OUString > aNames(3); + OUString *pNames = aNames.getArray(); + pNames[0] = A2OU( "com::sun::star::accessibility::Accessible" ); + pNames[1] = A2OU( "com::sun::star::accessibility::AccessibleComponent" ); + pNames[2] = A2OU( "com::sun::star::accessibility::AccessibleContext" ); + return aNames; +} + +////////////////////////////////////////////////////////////////////// + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/accessibility.hxx b/starmath/source/accessibility.hxx new file mode 100644 index 000000000000..8ed6c48465f9 --- /dev/null +++ b/starmath/source/accessibility.hxx @@ -0,0 +1,402 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifdef _MSC_VER +#pragma hdrstop +#endif + +#ifndef _ACCESSIBILITY_HXX_ +#define _ACCESSIBILITY_HXX_ + +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleComponent.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/accessibility/XAccessibleText.hpp> +#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Reference.h> +#include <osl/mutex.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <cppuhelper/implbase5.hxx> +#include <cppuhelper/implbase6.hxx> +#include <svl/brdcst.hxx> + +#include <editeng/editeng.hxx> +#include <editeng/unoedsrc.hxx> // SvxEditSource, SvxTextForwarder, SvxViewForwarder, SvxEditViewForwarder +#include <svx/AccessibleTextHelper.hxx> +#include <edit.hxx> + +class Window; +class SmGraphicWindow; +class SmEditWindow; +class SmDocShell; + +namespace com { namespace sun { namespace star { namespace accessibility { +struct AccessibleEventObject; +}}}} + +////////////////////////////////////////////////////////////////////// +// +// classes and helper-classes used for accessibility in the graphic-window +// + +typedef +cppu::WeakImplHelper6 + < + com::sun::star::lang::XServiceInfo, + com::sun::star::accessibility::XAccessible, + com::sun::star::accessibility::XAccessibleComponent, + com::sun::star::accessibility::XAccessibleContext, + com::sun::star::accessibility::XAccessibleText, + com::sun::star::accessibility::XAccessibleEventBroadcaster + > +SmGraphicAccessibleBaseClass; + +class SmGraphicAccessible : + public SmGraphicAccessibleBaseClass +{ + osl::Mutex aListenerMutex; + String aAccName; + /// client id in the AccessibleEventNotifier queue + sal_uInt32 nClientId; + + SmGraphicWindow *pWin; + + // disallow copy-ctor and assignment-operator for now + SmGraphicAccessible( const SmGraphicAccessible & ); + SmGraphicAccessible & operator = ( const SmGraphicAccessible & ); + +protected: + SmDocShell * GetDoc_Impl(); + String GetAccessibleText_Impl(); + +public: + SmGraphicAccessible( SmGraphicWindow *pGraphicWin ); + virtual ~SmGraphicAccessible(); + + SmGraphicWindow * GetWin() { return pWin; } + void ClearWin(); // to be called when view is destroyed + void LaunchEvent( + const sal_Int16 nAccesibleEventId, + const ::com::sun::star::uno::Any &rOldVal, + const ::com::sun::star::uno::Any &rNewVal); + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleText + virtual sal_Int32 SAL_CALL getCaretPosition( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setCaretPosition ( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Unicode SAL_CALL getCharacter( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getCharacterBounds( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getCharacterCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getIndexAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getSelectedText( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getSelectionStart( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getSelectionEnd( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getText( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); +}; + +////////////////////////////////////////////////////////////////////// +// +// classes and helper-classes used for accessibility in the command-window +// + +class SmEditAccessible; +class SmEditSource; +class EditEngine; +class EditView; +class SvxFieldItem; +struct ESelection; + + +class SmViewForwarder : + public SvxViewForwarder +{ + SmEditAccessible & rEditAcc; + + // disallow copy-ctor and assignment-operator for now + SmViewForwarder( const SmViewForwarder & ); + SmViewForwarder & operator = ( const SmViewForwarder & ); + +public: + SmViewForwarder( SmEditAccessible &rAcc ); + virtual ~SmViewForwarder(); + + virtual sal_Bool IsValid() const; + virtual Rectangle GetVisArea() const; + virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const; + virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const; +}; + + +class SmTextForwarder : /* analog to SvxEditEngineForwarder */ + public SvxTextForwarder +{ + SmEditAccessible & rEditAcc; + SmEditSource & rEditSource; + + DECL_LINK( NotifyHdl, EENotify * ); + + // disallow copy-ctor and assignment-operator for now + SmTextForwarder( const SmTextForwarder & ); + SmTextForwarder & operator = ( const SmTextForwarder & ); + +public: + SmTextForwarder( SmEditAccessible& rAcc, SmEditSource & rSource ); + virtual ~SmTextForwarder(); + + virtual sal_uInt16 GetParagraphCount() const; + virtual sal_uInt16 GetTextLen( sal_uInt16 nParagraph ) const; + virtual String GetText( const ESelection& rSel ) const; + virtual SfxItemSet GetAttribs( const ESelection& rSel, sal_Bool bOnlyHardAttrib = EditEngineAttribs_All ) const; + virtual SfxItemSet GetParaAttribs( sal_uInt16 nPara ) const; + virtual void SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet ); + virtual void RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich ); + virtual void GetPortions( sal_uInt16 nPara, std::vector<sal_uInt16>& rList ) const; + + virtual sal_uInt16 GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const; + virtual sal_uInt16 GetItemState( sal_uInt16 nPara, sal_uInt16 nWhich ) const; + + virtual void QuickInsertText( const String& rText, const ESelection& rSel ); + virtual void QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel ); + virtual void QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel ); + virtual void QuickInsertLineBreak( const ESelection& rSel ); + + virtual SfxItemPool* GetPool() const; + + virtual XubString CalcFieldValue( const SvxFieldItem& rField, sal_uInt16 nPara, sal_uInt16 nPos, Color*& rpTxtColor, Color*& rpFldColor ); + virtual void FieldClicked(const SvxFieldItem&, sal_uInt16, sal_uInt16); + virtual sal_Bool IsValid() const; + + virtual LanguageType GetLanguage( sal_uInt16, sal_uInt16 ) const; + virtual sal_uInt16 GetFieldCount( sal_uInt16 nPara ) const; + virtual EFieldInfo GetFieldInfo( sal_uInt16 nPara, sal_uInt16 nField ) const; + virtual EBulletInfo GetBulletInfo( sal_uInt16 nPara ) const; + virtual Rectangle GetCharBounds( sal_uInt16 nPara, sal_uInt16 nIndex ) const; + virtual Rectangle GetParaBounds( sal_uInt16 nPara ) const; + virtual MapMode GetMapMode() const; + virtual OutputDevice* GetRefDevice() const; + virtual sal_Bool GetIndexAtPoint( const Point&, sal_uInt16& nPara, sal_uInt16& nIndex ) const; + virtual sal_Bool GetWordIndices( sal_uInt16 nPara, sal_uInt16 nIndex, sal_uInt16& nStart, sal_uInt16& nEnd ) const; + virtual sal_Bool GetAttributeRun( sal_uInt16& nStartIndex, sal_uInt16& nEndIndex, sal_uInt16 nPara, sal_uInt16 nIndex ) const; + virtual sal_uInt16 GetLineCount( sal_uInt16 nPara ) const; + virtual sal_uInt16 GetLineLen( sal_uInt16 nPara, sal_uInt16 nLine ) const; + virtual void GetLineBoundaries( /*out*/sal_uInt16 &rStart, /*out*/sal_uInt16 &rEnd, sal_uInt16 nParagraph, sal_uInt16 nLine ) const; + virtual sal_uInt16 GetLineNumberAtIndex( sal_uInt16 nPara, sal_uInt16 nLine ) const; + virtual sal_Bool Delete( const ESelection& ); + virtual sal_Bool InsertText( const String&, const ESelection& ); + virtual sal_Bool QuickFormatDoc( sal_Bool bFull=sal_False ); + + virtual sal_Int16 GetDepth( sal_uInt16 nPara ) const; + virtual sal_Bool SetDepth( sal_uInt16 nPara, sal_Int16 nNewDepth ); + + virtual const SfxItemSet* GetEmptyItemSetPtr(); + // implementation functions for XParagraphAppend and XTextPortionAppend + virtual void AppendParagraph(); + virtual xub_StrLen AppendTextPortion( sal_uInt16 nPara, const String &rText, const SfxItemSet &rSet ); + + virtual void CopyText(const SvxTextForwarder& rSource); +}; + + +class SmEditViewForwarder : /* analog to SvxEditEngineViewForwarder */ + public SvxEditViewForwarder +{ + SmEditAccessible& rEditAcc; + + // disallow copy-ctor and assignment-operator for now + SmEditViewForwarder( const SmEditViewForwarder & ); + SmEditViewForwarder & operator = ( const SmEditViewForwarder & ); + +public: + SmEditViewForwarder( SmEditAccessible& rAcc ); + virtual ~SmEditViewForwarder(); + + virtual sal_Bool IsValid() const; + + virtual Rectangle GetVisArea() const; + virtual Point LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const; + virtual Point PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const; + + virtual sal_Bool GetSelection( ESelection& rSelection ) const; + virtual sal_Bool SetSelection( const ESelection& rSelection ); + virtual sal_Bool Copy(); + virtual sal_Bool Cut(); + virtual sal_Bool Paste(); +}; + + +class SmEditSource : + public SvxEditSource +{ + SfxBroadcaster aBroadCaster; + SmViewForwarder aViewFwd; + SmTextForwarder aTextFwd; + SmEditViewForwarder aEditViewFwd; + + SmEditAccessible& rEditAcc; + + // disallow copy-ctor and assignment-operator for now + SmEditSource( const SmEditSource &rSrc ); + SmEditSource & operator = ( const SmEditSource & ); + +public: + SmEditSource( SmEditWindow *pWin, SmEditAccessible &rAcc ); + virtual ~SmEditSource(); + + virtual SvxEditSource* Clone() const; + virtual SvxTextForwarder* GetTextForwarder(); + virtual SvxViewForwarder* GetViewForwarder(); + virtual SvxEditViewForwarder* GetEditViewForwarder( sal_Bool bCreate = sal_False ); + virtual void UpdateData(); + virtual SfxBroadcaster& GetBroadcaster() const; +}; + + + + +typedef +cppu::WeakImplHelper5 + < + com::sun::star::lang::XServiceInfo, + com::sun::star::accessibility::XAccessible, + com::sun::star::accessibility::XAccessibleComponent, + com::sun::star::accessibility::XAccessibleContext, + com::sun::star::accessibility::XAccessibleEventBroadcaster + > +SmEditAccessibleBaseClass; + +class SmEditAccessible : + public SmEditAccessibleBaseClass +{ + osl::Mutex aListenerMutex; + String aAccName; + ::accessibility::AccessibleTextHelper *pTextHelper; + SmEditWindow *pWin; + + // disallow copy-ctor and assignment-operator for now + SmEditAccessible( const SmEditAccessible & ); + SmEditAccessible & operator = ( const SmEditAccessible & ); + +public: + SmEditAccessible( SmEditWindow *pEditWin ); + virtual ~SmEditAccessible(); + + ::accessibility::AccessibleTextHelper * GetTextHelper() { return pTextHelper; } + + void Init(); + SmEditWindow * GetWin() { return pWin; } + void ClearWin(); // to be called when view is destroyed + + //! access EditEngine and EditView via the functions in the respective window + //! pointers may be 0 (e.g. during reload) + EditEngine * GetEditEngine() { return pWin ? pWin->GetEditEngine() : 0; } + EditView * GetEditView() { return pWin ? pWin->GetEditView() : 0; } + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); +}; + +////////////////////////////////////////////////////////////////////// + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/action.cxx b/starmath/source/action.cxx new file mode 100644 index 000000000000..a7fbbc2a33bf --- /dev/null +++ b/starmath/source/action.cxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include "action.hxx" +#include "smdll.hxx" +#include "document.hxx" +#include "starmath.hrc" + + +SmFormatAction::SmFormatAction(SmDocShell *pDocSh, + const SmFormat& rOldFormat, + const SmFormat& rNewFormat) : + pDoc( pDocSh ), + aOldFormat( rOldFormat ), + aNewFormat( rNewFormat ) +{ +} + +void SmFormatAction::Undo() +{ + pDoc->SetFormat(aOldFormat); +} + +void SmFormatAction::Redo() +{ + pDoc->SetFormat(aNewFormat); +} + +void SmFormatAction::Repeat(SfxRepeatTarget& rDocSh) +{ + dynamic_cast< SmDocShell & >(rDocSh).SetFormat(aNewFormat); +} + +UniString SmFormatAction::GetComment() const +{ + return (SmResId(RID_UNDOFORMATNAME)); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/caret.cxx b/starmath/source/caret.cxx new file mode 100644 index 000000000000..0fd781eb44b7 --- /dev/null +++ b/starmath/source/caret.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Jonas Finnemann Jensen <jopsen@gmail.com> + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jonas Finnemann Jensen <jopsen@gmail.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include "caret.hxx" + +/////////////////////////////// SmCaretPosGraph //////////////////////////////// + +SmCaretPosGraphEntry* SmCaretPosGraphIterator::Next(){ + if(nOffset >= pGraph->nOffset){ + if(pGraph->pNext){ + pGraph = pGraph->pNext; + nOffset = 0; + pEntry = Next(); + }else + pEntry = NULL; + }else + pEntry = pGraph->Graph + nOffset++; + return pEntry; +} + +SmCaretPosGraphEntry* SmCaretPosGraph::Add(SmCaretPosGraphEntry entry){ + if(nOffset >= SmCaretPosGraphSize){ + if(!pNext) + pNext = new SmCaretPosGraph(); + return pNext->Add(entry); + }else{ + //Set Left and Right to point to the entry itself if they are NULL + entry.Left = entry.Left ? entry.Left : Graph + nOffset; + entry.Right = entry.Right ? entry.Right : Graph + nOffset; + //Save the entry + Graph[nOffset] = entry; + return Graph + nOffset++; + } +} + +SmCaretPosGraph::~SmCaretPosGraph(){ + if(pNext) + delete pNext; + pNext = NULL; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/cfgitem.cxx b/starmath/source/cfgitem.cxx new file mode 100644 index 000000000000..cbbfa6d64761 --- /dev/null +++ b/starmath/source/cfgitem.cxx @@ -0,0 +1,1302 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <vcl/svapp.hxx> +#include <sal/macros.h> +#include "cfgitem.hxx" + +#include "starmath.hrc" +#include "smdll.hxx" +#include "format.hxx" + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; + +using ::rtl::OUString; + + +static const char* aRootName = "Office.Math"; + +#define SYMBOL_LIST "SymbolList" +#define FONT_FORMAT_LIST "FontFormatList" + +///////////////////////////////////////////////////////////////// + + +static Sequence< OUString > lcl_GetFontPropertyNames() +{ + static const char * aPropNames[] = + { + "Name", + "CharSet", + "Family", + "Pitch", + "Weight", + "Italic", + 0 + }; + + const char** ppPropName = aPropNames; + + Sequence< OUString > aNames( 6 ); + OUString *pNames = aNames.getArray(); + for( sal_Int32 i = 0; *ppPropName; ++i, ++ppPropName ) + { + pNames[i] = A2OU( *ppPropName ); + } + return aNames; +} + +///////////////////////////////////////////////////////////////// + + +static Sequence< OUString > lcl_GetSymbolPropertyNames() +{ + static const char * aPropNames[] = + { + "Char", + "Set", + "Predefined", + "FontFormatId", + 0 + }; + + const char** ppPropName = aPropNames; + + Sequence< OUString > aNames( 4 ); + OUString *pNames = aNames.getArray(); + for( sal_Int32 i = 0; *ppPropName; ++i, ++ppPropName ) + { + pNames[i] = A2OU( *ppPropName ); + } + return aNames; +} + +///////////////////////////////////////////////////////////////// + +static const char * aMathPropNames[] = +{ + "Print/Title", + "Print/FormulaText", + "Print/Frame", + "Print/Size", + "Print/ZoomFactor", + "LoadSave/IsSaveOnlyUsedSymbols", + //"Misc/NoSymbolsWarning", @deprecated + "Misc/IgnoreSpacesRight", + "View/ToolboxVisible", + "View/AutoRedraw", + "View/FormulaCursor" +}; + + +//! Beware of order according to *_BEGIN *_END defines in format.hxx ! +//! see respective load/save routines here +static const char * aFormatPropNames[] = +{ + "StandardFormat/Textmode", + "StandardFormat/GreekCharStyle", + "StandardFormat/ScaleNormalBracket", + "StandardFormat/HorizontalAlignment", + "StandardFormat/BaseSize", + "StandardFormat/TextSize", + "StandardFormat/IndexSize", + "StandardFormat/FunctionSize", + "StandardFormat/OperatorSize", + "StandardFormat/LimitsSize", + "StandardFormat/Distance/Horizontal", + "StandardFormat/Distance/Vertical", + "StandardFormat/Distance/Root", + "StandardFormat/Distance/SuperScript", + "StandardFormat/Distance/SubScript", + "StandardFormat/Distance/Numerator", + "StandardFormat/Distance/Denominator", + "StandardFormat/Distance/Fraction", + "StandardFormat/Distance/StrokeWidth", + "StandardFormat/Distance/UpperLimit", + "StandardFormat/Distance/LowerLimit", + "StandardFormat/Distance/BracketSize", + "StandardFormat/Distance/BracketSpace", + "StandardFormat/Distance/MatrixRow", + "StandardFormat/Distance/MatrixColumn", + "StandardFormat/Distance/OrnamentSize", + "StandardFormat/Distance/OrnamentSpace", + "StandardFormat/Distance/OperatorSize", + "StandardFormat/Distance/OperatorSpace", + "StandardFormat/Distance/LeftSpace", + "StandardFormat/Distance/RightSpace", + "StandardFormat/Distance/TopSpace", + "StandardFormat/Distance/BottomSpace", + "StandardFormat/Distance/NormalBracketSize", + "StandardFormat/VariableFont", + "StandardFormat/FunctionFont", + "StandardFormat/NumberFont", + "StandardFormat/TextFont", + "StandardFormat/SerifFont", + "StandardFormat/SansFont", + "StandardFormat/FixedFont" +}; + + +static Sequence< OUString > lcl_GetPropertyNames( + const char * aPropNames[], sal_uInt16 nCount ) +{ + + const char** ppPropName = aPropNames; + + Sequence< OUString > aNames( nCount ); + OUString *pNames = aNames.getArray(); + for (sal_Int32 i = 0; i < nCount; ++i, ++ppPropName) + { + pNames[i] = A2OU( *ppPropName ); + } + return aNames; +} + + +static Sequence< OUString > GetFormatPropertyNames() +{ + sal_uInt16 nCnt = SAL_N_ELEMENTS(aFormatPropNames); + return lcl_GetPropertyNames( aFormatPropNames, nCnt ); +} + + +static Sequence< OUString > GetOtherPropertyNames() +{ + sal_uInt16 nCnt = SAL_N_ELEMENTS(aMathPropNames); + return lcl_GetPropertyNames( aMathPropNames, nCnt ); +} + +///////////////////////////////////////////////////////////////// + +struct SmCfgOther +{ + SmPrintSize ePrintSize; + sal_uInt16 nPrintZoomFactor; + bool bPrintTitle; + bool bPrintFormulaText; + bool bPrintFrame; + bool bIsSaveOnlyUsedSymbols; + bool bIgnoreSpacesRight; + bool bToolboxVisible; + bool bAutoRedraw; + bool bFormulaCursor; + //sal_Bool bNoSymbolsWarning; + + SmCfgOther(); +}; + + +SmCfgOther::SmCfgOther() +{ + ePrintSize = PRINT_SIZE_NORMAL; + nPrintZoomFactor = 100; + bPrintTitle = bPrintFormulaText = + bPrintFrame = bIgnoreSpacesRight = + bToolboxVisible = bAutoRedraw = + bFormulaCursor = bIsSaveOnlyUsedSymbols = true; +} + +///////////////////////////////////////////////////////////////// + + +SmFontFormat::SmFontFormat() +{ + aName.AssignAscii( FONTNAME_MATH ); + nCharSet = RTL_TEXTENCODING_UNICODE; + nFamily = FAMILY_DONTKNOW; + nPitch = PITCH_DONTKNOW; + nWeight = WEIGHT_DONTKNOW; + nItalic = ITALIC_NONE; +} + + +SmFontFormat::SmFontFormat( const Font &rFont ) +{ + aName = rFont.GetName(); + nCharSet = (sal_Int16) rFont.GetCharSet(); + nFamily = (sal_Int16) rFont.GetFamily(); + nPitch = (sal_Int16) rFont.GetPitch(); + nWeight = (sal_Int16) rFont.GetWeight(); + nItalic = (sal_Int16) rFont.GetItalic(); +} + + +const Font SmFontFormat::GetFont() const +{ + Font aRes; + aRes.SetName( aName ); + aRes.SetCharSet( (rtl_TextEncoding) nCharSet ); + aRes.SetFamily( (FontFamily) nFamily ); + aRes.SetPitch( (FontPitch) nPitch ); + aRes.SetWeight( (FontWeight) nWeight ); + aRes.SetItalic( (FontItalic) nItalic ); + return aRes; +} + + +bool SmFontFormat::operator == ( const SmFontFormat &rFntFmt ) const +{ + return aName == rFntFmt.aName && + nCharSet == rFntFmt.nCharSet && + nFamily == rFntFmt.nFamily && + nPitch == rFntFmt.nPitch && + nWeight == rFntFmt.nWeight && + nItalic == rFntFmt.nItalic; +} + + +///////////////////////////////////////////////////////////////// + +SmFntFmtListEntry::SmFntFmtListEntry( const String &rId, const SmFontFormat &rFntFmt ) : + aId (rId), + aFntFmt (rFntFmt) +{ +} + + +SmFontFormatList::SmFontFormatList() +{ + bModified = false; +} + + +void SmFontFormatList::Clear() +{ + if (!aEntries.empty()) + { + aEntries.clear(); + SetModified( true ); + } +} + + +void SmFontFormatList::AddFontFormat( const String &rFntFmtId, + const SmFontFormat &rFntFmt ) +{ + const SmFontFormat *pFntFmt = GetFontFormat( rFntFmtId ); + OSL_ENSURE( !pFntFmt, "FontFormatId already exists" ); + if (!pFntFmt) + { + SmFntFmtListEntry aEntry( rFntFmtId, rFntFmt ); + aEntries.push_back( aEntry ); + SetModified( true ); + } +} + + +void SmFontFormatList::RemoveFontFormat( const String &rFntFmtId ) +{ + + // search for entry + for (size_t i = 0; i < aEntries.size(); ++i) + { + if (aEntries[i].aId == rFntFmtId) + { + // remove entry if found + aEntries.erase( aEntries.begin() + i ); + SetModified( true ); + break; + } + } +} + + +const SmFontFormat * SmFontFormatList::GetFontFormat( const String &rFntFmtId ) const +{ + const SmFontFormat *pRes = 0; + + for (size_t i = 0; i < aEntries.size(); ++i) + { + if (aEntries[i].aId == rFntFmtId) + { + pRes = &aEntries[i].aFntFmt; + break; + } + } + + return pRes; +} + + + +const SmFontFormat * SmFontFormatList::GetFontFormat( size_t nPos ) const +{ + const SmFontFormat *pRes = 0; + if (nPos < aEntries.size()) + pRes = &aEntries[nPos].aFntFmt; + return pRes; +} + + +const String SmFontFormatList::GetFontFormatId( const SmFontFormat &rFntFmt ) const +{ + String aRes; + + for (size_t i = 0; i < aEntries.size(); ++i) + { + if (aEntries[i].aFntFmt == rFntFmt) + { + aRes = aEntries[i].aId; + break; + } + } + + return aRes; +} + + +const String SmFontFormatList::GetFontFormatId( const SmFontFormat &rFntFmt, bool bAdd ) +{ + String aRes( GetFontFormatId( rFntFmt) ); + if (0 == aRes.Len() && bAdd) + { + aRes = GetNewFontFormatId(); + AddFontFormat( aRes, rFntFmt ); + } + return aRes; +} + + +const String SmFontFormatList::GetFontFormatId( size_t nPos ) const +{ + String aRes; + if (nPos < aEntries.size()) + aRes = aEntries[nPos].aId; + return aRes; +} + + +const String SmFontFormatList::GetNewFontFormatId() const +{ + // returns first unused FormatId + + String aRes; + + String aPrefix( RTL_CONSTASCII_USTRINGPARAM( "Id" ) ); + sal_Int32 nCnt = GetCount(); + for (sal_Int32 i = 1; i <= nCnt + 1; ++i) + { + String aTmpId( aPrefix ); + aTmpId += String::CreateFromInt32( i ); + if (!GetFontFormat( aTmpId )) + { + aRes = aTmpId; + break; + } + } + OSL_ENSURE( 0 != aRes.Len(), "failed to create new FontFormatId" ); + + return aRes; +} + +///////////////////////////////////////////////////////////////// + +SmMathConfig::SmMathConfig() : + ConfigItem( String::CreateFromAscii( aRootName )) +{ + pFormat = 0; + pOther = 0; + pFontFormatList = 0; + pSymbolMgr = 0; + + bIsOtherModified = bIsFormatModified = false; +} + + +SmMathConfig::~SmMathConfig() +{ + Save(); + delete pFormat; + delete pOther; + delete pFontFormatList; + delete pSymbolMgr; +} + + +void SmMathConfig::SetOtherModified( bool bVal ) +{ + bIsOtherModified = bVal; +} + + +void SmMathConfig::SetFormatModified( bool bVal ) +{ + bIsFormatModified = bVal; +} + + +void SmMathConfig::SetFontFormatListModified( bool bVal ) +{ + if (pFontFormatList) + pFontFormatList->SetModified( bVal ); +} + + +void SmMathConfig::ReadSymbol( SmSym &rSymbol, + const rtl::OUString &rSymbolName, + const rtl::OUString &rBaseNode ) const +{ + Sequence< OUString > aNames = lcl_GetSymbolPropertyNames(); + sal_Int32 nProps = aNames.getLength(); + + OUString aDelim( OUString::valueOf( (sal_Unicode) '/' ) ); + OUString *pName = aNames.getArray(); + for (sal_Int32 i = 0; i < nProps; ++i) + { + OUString &rName = pName[i]; + OUString aTmp( rName ); + rName = rBaseNode; + rName += aDelim; + rName += rSymbolName; + rName += aDelim; + rName += aTmp; + } + + const Sequence< Any > aValues = ((SmMathConfig*) this)->GetProperties( aNames ); + + if (nProps && aValues.getLength() == nProps) + { + const Any * pValue = aValues.getConstArray(); + Font aFont; + sal_UCS4 cChar = '\0'; + String aSet; + bool bPredefined = false; + + OUString aTmpStr; + sal_Int32 nTmp32 = 0; + bool bTmp = false; + + bool bOK = true; + if (pValue->hasValue() && (*pValue >>= nTmp32)) + cChar = static_cast< sal_UCS4 >( nTmp32 ); + else + bOK = false; + ++pValue; + if (pValue->hasValue() && (*pValue >>= aTmpStr)) + aSet = aTmpStr; + else + bOK = false; + ++pValue; + if (pValue->hasValue() && (*pValue >>= bTmp)) + bPredefined = bTmp; + else + bOK = false; + ++pValue; + if (pValue->hasValue() && (*pValue >>= aTmpStr)) + { + const SmFontFormat *pFntFmt = GetFontFormatList().GetFontFormat( aTmpStr ); + OSL_ENSURE( pFntFmt, "unknown FontFormat" ); + if (pFntFmt) + aFont = pFntFmt->GetFont(); + } + else + bOK = false; + ++pValue; + + if (bOK) + { + String aUiName( rSymbolName ); + String aUiSetName( aSet ); + if (bPredefined) + { + String aTmp; + aTmp = GetUiSymbolName( rSymbolName ); + OSL_ENSURE( aTmp.Len(), "localized symbol-name not found" ); + if (aTmp.Len()) + aUiName = aTmp; + aTmp = GetUiSymbolSetName( aSet ); + OSL_ENSURE( aTmp.Len(), "localized symbolset-name not found" ); + if (aTmp.Len()) + aUiSetName = aTmp; + } + + rSymbol = SmSym( aUiName, aFont, cChar, aUiSetName, bPredefined ); + if (aUiName != String(rSymbolName)) + rSymbol.SetExportName( rSymbolName ); + } + else + { + OSL_FAIL( "symbol read error" ); + } + } +} + + +SmSymbolManager & SmMathConfig::GetSymbolManager() +{ + if (!pSymbolMgr) + { + pSymbolMgr = new SmSymbolManager; + pSymbolMgr->Load(); + } + return *pSymbolMgr; +} + + +void SmMathConfig::Commit() +{ + Save(); +} + + +void SmMathConfig::Save() +{ + SaveOther(); + SaveFormat(); + SaveFontFormatList(); +} + + +void SmMathConfig::GetSymbols( std::vector< SmSym > &rSymbols ) const +{ + Sequence< OUString > aNodes( ((SmMathConfig*) this)->GetNodeNames( A2OU( SYMBOL_LIST ) ) ); + const OUString *pNode = aNodes.getConstArray(); + sal_Int32 nNodes = aNodes.getLength(); + + rSymbols.resize( nNodes ); + std::vector< SmSym >::iterator aIt( rSymbols.begin() ); + std::vector< SmSym >::iterator aEnd( rSymbols.end() ); + while (aIt != aEnd) + { + ReadSymbol( *aIt++, *pNode++, A2OU( SYMBOL_LIST ) ); + } +} + + +void SmMathConfig::SetSymbols( const std::vector< SmSym > &rNewSymbols ) +{ + sal_uIntPtr nCount = rNewSymbols.size(); + + Sequence< OUString > aNames = lcl_GetSymbolPropertyNames(); + const OUString *pNames = aNames.getConstArray(); + sal_uIntPtr nSymbolProps = sal::static_int_cast< sal_uInt32 >(aNames.getLength()); + + Sequence< PropertyValue > aValues( nCount * nSymbolProps ); + PropertyValue *pValues = aValues.getArray(); + + PropertyValue *pVal = pValues; + OUString aDelim( OUString::valueOf( (sal_Unicode) '/' ) ); + std::vector< SmSym >::const_iterator aIt( rNewSymbols.begin() ); + std::vector< SmSym >::const_iterator aEnd( rNewSymbols.end() ); + while (aIt != aEnd) + { + const SmSym &rSymbol = *aIt++; + OUString aNodeNameDelim( A2OU( SYMBOL_LIST ) ); + aNodeNameDelim += aDelim; + aNodeNameDelim += rSymbol.GetExportName(); + aNodeNameDelim += aDelim; + + const OUString *pName = pNames; + + // Char + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + pVal->Value <<= static_cast< sal_UCS4 >( rSymbol.GetCharacter() ); + pVal++; + // Set + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + OUString aTmp( rSymbol.GetSymbolSetName() ); + if (rSymbol.IsPredefined()) + aTmp = GetExportSymbolSetName( aTmp ); + pVal->Value <<= aTmp; + pVal++; + // Predefined + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + pVal->Value <<= (sal_Bool) rSymbol.IsPredefined(); + pVal++; + // FontFormatId + SmFontFormat aFntFmt( rSymbol.GetFace() ); + String aFntFmtId( GetFontFormatList().GetFontFormatId( aFntFmt, true ) ); + OSL_ENSURE( aFntFmtId.Len(), "FontFormatId not found" ); + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + pVal->Value <<= OUString( aFntFmtId ); + pVal++; + } + OSL_ENSURE( pVal - pValues == sal::static_int_cast< ptrdiff_t >(nCount * nSymbolProps), "properties missing" ); + ReplaceSetProperties( A2OU( SYMBOL_LIST ) , aValues ); + + StripFontFormatList( rNewSymbols ); + SaveFontFormatList(); +} + + +SmFontFormatList & SmMathConfig::GetFontFormatList() +{ + if (!pFontFormatList) + { + LoadFontFormatList(); + } + return *pFontFormatList; +} + + +void SmMathConfig::LoadFontFormatList() +{ + if (!pFontFormatList) + pFontFormatList = new SmFontFormatList; + else + pFontFormatList->Clear(); + + Sequence< OUString > aNodes( GetNodeNames( A2OU( FONT_FORMAT_LIST ) ) ); + const OUString *pNode = aNodes.getConstArray(); + sal_Int32 nNodes = aNodes.getLength(); + + for (sal_Int32 i = 0; i < nNodes; ++i) + { + SmFontFormat aFntFmt; + ReadFontFormat( aFntFmt, pNode[i], A2OU( FONT_FORMAT_LIST ) ); + if (!pFontFormatList->GetFontFormat( pNode[i] )) + { + OSL_ENSURE( 0 == pFontFormatList->GetFontFormat( pNode[i] ), + "FontFormat ID already exists" ); + pFontFormatList->AddFontFormat( pNode[i], aFntFmt ); + } + } + pFontFormatList->SetModified( false ); +} + + +void SmMathConfig::ReadFontFormat( SmFontFormat &rFontFormat, + const OUString &rSymbolName, const OUString &rBaseNode ) const +{ + Sequence< OUString > aNames = lcl_GetFontPropertyNames(); + sal_Int32 nProps = aNames.getLength(); + + OUString aDelim( OUString::valueOf( (sal_Unicode) '/' ) ); + OUString *pName = aNames.getArray(); + for (sal_Int32 i = 0; i < nProps; ++i) + { + OUString &rName = pName[i]; + OUString aTmp( rName ); + rName = rBaseNode; + rName += aDelim; + rName += rSymbolName; + rName += aDelim; + rName += aTmp; + } + + const Sequence< Any > aValues = ((SmMathConfig*) this)->GetProperties( aNames ); + + if (nProps && aValues.getLength() == nProps) + { + const Any * pValue = aValues.getConstArray(); + + OUString aTmpStr; + sal_Int16 nTmp16 = 0; + + bool bOK = true; + if (pValue->hasValue() && (*pValue >>= aTmpStr)) + rFontFormat.aName = aTmpStr; + else + bOK = false; + ++pValue; + if (pValue->hasValue() && (*pValue >>= nTmp16)) + rFontFormat.nCharSet = nTmp16; // 6.0 file-format GetSOLoadTextEncoding not needed + else + bOK = false; + ++pValue; + if (pValue->hasValue() && (*pValue >>= nTmp16)) + rFontFormat.nFamily = nTmp16; + else + bOK = false; + ++pValue; + if (pValue->hasValue() && (*pValue >>= nTmp16)) + rFontFormat.nPitch = nTmp16; + else + bOK = false; + ++pValue; + if (pValue->hasValue() && (*pValue >>= nTmp16)) + rFontFormat.nWeight = nTmp16; + else + bOK = false; + ++pValue; + if (pValue->hasValue() && (*pValue >>= nTmp16)) + rFontFormat.nItalic = nTmp16; + else + bOK = false; + ++pValue; + + OSL_ENSURE( bOK, "read FontFormat failed" ); + (void)bOK; + } +} + + +void SmMathConfig::SaveFontFormatList() +{ + SmFontFormatList &rFntFmtList = GetFontFormatList(); + + if (!rFntFmtList.IsModified()) + return; + + Sequence< OUString > aNames = lcl_GetFontPropertyNames(); + sal_Int32 nSymbolProps = aNames.getLength(); + + size_t nCount = rFntFmtList.GetCount(); + + Sequence< PropertyValue > aValues( nCount * nSymbolProps ); + PropertyValue *pValues = aValues.getArray(); + + PropertyValue *pVal = pValues; + OUString aDelim( OUString::valueOf( (sal_Unicode) '/' ) ); + for (size_t i = 0; i < nCount; ++i) + { + String aFntFmtId( rFntFmtList.GetFontFormatId( i ) ); + const SmFontFormat aFntFmt( *rFntFmtList.GetFontFormat( aFntFmtId ) ); + + OUString aNodeNameDelim( A2OU( FONT_FORMAT_LIST ) ); + aNodeNameDelim += aDelim; + aNodeNameDelim += aFntFmtId; + aNodeNameDelim += aDelim; + + const OUString *pName = aNames.getConstArray();; + + // Name + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + pVal->Value <<= OUString( aFntFmt.aName ); + pVal++; + // CharSet + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + pVal->Value <<= (sal_Int16) aFntFmt.nCharSet; // 6.0 file-format GetSOStoreTextEncoding not needed + pVal++; + // Family + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + pVal->Value <<= (sal_Int16) aFntFmt.nFamily; + pVal++; + // Pitch + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + pVal->Value <<= (sal_Int16) aFntFmt.nPitch; + pVal++; + // Weight + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + pVal->Value <<= (sal_Int16) aFntFmt.nWeight; + pVal++; + // Italic + pVal->Name = aNodeNameDelim; + pVal->Name += *pName++; + pVal->Value <<= (sal_Int16) aFntFmt.nItalic; + pVal++; + } + OSL_ENSURE( sal::static_int_cast<size_t>(pVal - pValues) == nCount * nSymbolProps, "properties missing" ); + ReplaceSetProperties( A2OU( FONT_FORMAT_LIST ) , aValues ); + + rFntFmtList.SetModified( false ); +} + + +void SmMathConfig::StripFontFormatList( const std::vector< SmSym > &rSymbols ) +{ + size_t i; + + // build list of used font-formats only + //!! font-format IDs may be different !! + SmFontFormatList aUsedList; + for (i = 0; i < rSymbols.size(); ++i) + { + OSL_ENSURE( rSymbols[i].GetName().Len() > 0, "non named symbol" ); + aUsedList.GetFontFormatId( SmFontFormat( rSymbols[i].GetFace() ) , true ); + } + const SmFormat & rStdFmt = GetStandardFormat(); + for (i = FNT_BEGIN; i <= FNT_END; ++i) + { + aUsedList.GetFontFormatId( SmFontFormat( rStdFmt.GetFont( i ) ) , true ); + } + + // remove unused font-formats from list + SmFontFormatList &rFntFmtList = GetFontFormatList(); + size_t nCnt = rFntFmtList.GetCount(); + SmFontFormat *pTmpFormat = new SmFontFormat[ nCnt ]; + String *pId = new String [ nCnt ]; + size_t k; + for (k = 0; k < nCnt; ++k) + { + pTmpFormat[k] = *rFntFmtList.GetFontFormat( k ); + pId[k] = rFntFmtList.GetFontFormatId( k ); + } + for (k = 0; k < nCnt; ++k) + { + if (0 == aUsedList.GetFontFormatId( pTmpFormat[k] ).Len()) + { + rFntFmtList.RemoveFontFormat( pId[k] ); + } + } + delete [] pId; + delete [] pTmpFormat; +} + + +void SmMathConfig::LoadOther() +{ + if (!pOther) + pOther = new SmCfgOther; + + Sequence< OUString > aNames( GetOtherPropertyNames() ); + sal_Int32 nProps = aNames.getLength(); + + Sequence< Any > aValues( GetProperties( aNames ) ); + if (nProps && aValues.getLength() == nProps) + { + const Any *pValues = aValues.getConstArray(); + const Any *pVal = pValues; + + sal_Int16 nTmp16 = 0; + bool bTmp = false; + + // Print/Title + if (pVal->hasValue() && (*pVal >>= bTmp)) + pOther->bPrintTitle = bTmp; + ++pVal; + // Print/FormulaText + if (pVal->hasValue() && (*pVal >>= bTmp)) + pOther->bPrintFormulaText = bTmp; + ++pVal; + // Print/Frame + if (pVal->hasValue() && (*pVal >>= bTmp)) + pOther->bPrintFrame = bTmp; + ++pVal; + // Print/Size + if (pVal->hasValue() && (*pVal >>= nTmp16)) + pOther->ePrintSize = (SmPrintSize) nTmp16; + ++pVal; + // Print/ZoomFactor + if (pVal->hasValue() && (*pVal >>= nTmp16)) + pOther->nPrintZoomFactor = nTmp16; + ++pVal; + // LoadSave/IsSaveOnlyUsedSymbols + if (pVal->hasValue() && (*pVal >>= bTmp)) + pOther->bIsSaveOnlyUsedSymbols = bTmp; + ++pVal; + // Misc/IgnoreSpacesRight + if (pVal->hasValue() && (*pVal >>= bTmp)) + pOther->bIgnoreSpacesRight = bTmp; + ++pVal; + // View/ToolboxVisible + if (pVal->hasValue() && (*pVal >>= bTmp)) + pOther->bToolboxVisible = bTmp; + ++pVal; + // View/AutoRedraw + if (pVal->hasValue() && (*pVal >>= bTmp)) + pOther->bAutoRedraw = bTmp; + ++pVal; + // View/FormulaCursor + if (pVal->hasValue() && (*pVal >>= bTmp)) + pOther->bFormulaCursor = bTmp; + ++pVal; + + OSL_ENSURE( pVal - pValues == nProps, "property mismatch" ); + SetOtherModified( false ); + } +} + + +void SmMathConfig::SaveOther() +{ + if (!pOther || !IsOtherModified()) + return; + + const Sequence< OUString > aNames( GetOtherPropertyNames() ); + sal_Int32 nProps = aNames.getLength(); + + Sequence< Any > aValues( nProps ); + Any *pValues = aValues.getArray(); + Any *pValue = pValues; + + // Print/Title + *pValue++ <<= (sal_Bool) pOther->bPrintTitle; + // Print/FormulaText + *pValue++ <<= (sal_Bool) pOther->bPrintFormulaText; + // Print/Frame + *pValue++ <<= (sal_Bool) pOther->bPrintFrame; + // Print/Size + *pValue++ <<= (sal_Int16) pOther->ePrintSize; + // Print/ZoomFactor + *pValue++ <<= (sal_Int16) pOther->nPrintZoomFactor; + // LoadSave/IsSaveOnlyUsedSymbols + *pValue++ <<= (sal_Bool) pOther->bIsSaveOnlyUsedSymbols; + // Misc/IgnoreSpacesRight + *pValue++ <<= (sal_Bool) pOther->bIgnoreSpacesRight; + // View/ToolboxVisible + *pValue++ <<= (sal_Bool) pOther->bToolboxVisible; + // View/AutoRedraw + *pValue++ <<= (sal_Bool) pOther->bAutoRedraw; + // View/FormulaCursor + *pValue++ <<= (sal_Bool) pOther->bFormulaCursor; + + OSL_ENSURE( pValue - pValues == nProps, "property mismatch" ); + PutProperties( aNames , aValues ); + + SetOtherModified( false ); +} + +void SmMathConfig::LoadFormat() +{ + if (!pFormat) + pFormat = new SmFormat; + + + Sequence< OUString > aNames( GetFormatPropertyNames() ); + sal_Int32 nProps = aNames.getLength(); + + Sequence< Any > aValues( GetProperties( aNames ) ); + if (nProps && aValues.getLength() == nProps) + { + const Any *pValues = aValues.getConstArray(); + const Any *pVal = pValues; + + OUString aTmpStr; + sal_Int16 nTmp16 = 0; + bool bTmp = false; + + // StandardFormat/Textmode + if (pVal->hasValue() && (*pVal >>= bTmp)) + pFormat->SetTextmode( bTmp ); + ++pVal; + // StandardFormat/GreekCharStyle + if (pVal->hasValue() && (*pVal >>= nTmp16)) + pFormat->SetGreekCharStyle( nTmp16 ); + ++pVal; + // StandardFormat/ScaleNormalBracket + if (pVal->hasValue() && (*pVal >>= bTmp)) + pFormat->SetScaleNormalBrackets( bTmp ); + ++pVal; + // StandardFormat/HorizontalAlignment + if (pVal->hasValue() && (*pVal >>= nTmp16)) + pFormat->SetHorAlign( (SmHorAlign) nTmp16 ); + ++pVal; + // StandardFormat/BaseSize + if (pVal->hasValue() && (*pVal >>= nTmp16)) + pFormat->SetBaseSize( Size(0, SmPtsTo100th_mm( nTmp16 )) ); + ++pVal; + + sal_uInt16 i; + for (i = SIZ_BEGIN; i <= SIZ_END; ++i) + { + if (pVal->hasValue() && (*pVal >>= nTmp16)) + pFormat->SetRelSize( i, nTmp16 ); + ++pVal; + } + + for (i = DIS_BEGIN; i <= DIS_END; ++i) + { + if (pVal->hasValue() && (*pVal >>= nTmp16)) + pFormat->SetDistance( i, nTmp16 ); + ++pVal; + } + + LanguageType nLang = Application::GetSettings().GetUILanguage(); + for (i = FNT_BEGIN; i < FNT_END; ++i) + { + Font aFnt; + bool bUseDefaultFont = true; + if (pVal->hasValue() && (*pVal >>= aTmpStr)) + { + bUseDefaultFont = 0 == aTmpStr.getLength(); + if (bUseDefaultFont) + { + aFnt = pFormat->GetFont( i ); + aFnt.SetName( GetDefaultFontName( nLang, i ) ); + } + else + { + const SmFontFormat *pFntFmt = GetFontFormatList().GetFontFormat( aTmpStr ); + OSL_ENSURE( pFntFmt, "unknown FontFormat" ); + if (pFntFmt) + aFnt = pFntFmt->GetFont(); + } + } + ++pVal; + + aFnt.SetSize( pFormat->GetBaseSize() ); + pFormat->SetFont( i, aFnt, bUseDefaultFont ); + } + + OSL_ENSURE( pVal - pValues == nProps, "property mismatch" ); + SetFormatModified( false ); + } +} + + +void SmMathConfig::SaveFormat() +{ + if (!pFormat || !IsFormatModified()) + return; + + const Sequence< OUString > aNames( GetFormatPropertyNames() ); + sal_Int32 nProps = aNames.getLength(); + + Sequence< Any > aValues( nProps ); + Any *pValues = aValues.getArray(); + Any *pValue = pValues; + + // StandardFormat/Textmode + *pValue++ <<= (sal_Bool) pFormat->IsTextmode(); + // StandardFormat/GreekCharStyle + *pValue++ <<= (sal_Int16) pFormat->GetGreekCharStyle(); + // StandardFormat/ScaleNormalBracket + *pValue++ <<= (sal_Bool) pFormat->IsScaleNormalBrackets(); + // StandardFormat/HorizontalAlignment + *pValue++ <<= (sal_Int16) pFormat->GetHorAlign(); + // StandardFormat/BaseSize + *pValue++ <<= (sal_Int16) SmRoundFraction( Sm100th_mmToPts( + pFormat->GetBaseSize().Height() ) ); + + sal_uInt16 i; + for (i = SIZ_BEGIN; i <= SIZ_END; ++i) + *pValue++ <<= (sal_Int16) pFormat->GetRelSize( i ); + + for (i = DIS_BEGIN; i <= DIS_END; ++i) + *pValue++ <<= (sal_Int16) pFormat->GetDistance( i ); + + for (i = FNT_BEGIN; i < FNT_END; ++i) + { + OUString aFntFmtId; + + if (!pFormat->IsDefaultFont( i )) + { + SmFontFormat aFntFmt( pFormat->GetFont( i ) ); + aFntFmtId = GetFontFormatList().GetFontFormatId( aFntFmt, true ); + OSL_ENSURE( aFntFmtId.getLength(), "FontFormatId not found" ); + } + + *pValue++ <<= aFntFmtId; + } + + OSL_ENSURE( pValue - pValues == nProps, "property mismatch" ); + PutProperties( aNames , aValues ); + + SetFormatModified( false ); +} + + +const SmFormat & SmMathConfig::GetStandardFormat() const +{ + if (!pFormat) + ((SmMathConfig *) this)->LoadFormat(); + return *pFormat; +} + + +void SmMathConfig::SetStandardFormat( const SmFormat &rFormat, bool bSaveFontFormatList ) +{ + if (!pFormat) + LoadFormat(); + if (rFormat != *pFormat) + { + *pFormat = rFormat; + SetFormatModified( true ); + SaveFormat(); + + if (bSaveFontFormatList) + { + // needed for SmFontTypeDialog's DefaultButtonClickHdl + SetFontFormatListModified( true ); + SaveFontFormatList(); + } + } +} + + +SmPrintSize SmMathConfig::GetPrintSize() const +{ + if (!pOther) + ((SmMathConfig *) this)->LoadOther(); + return pOther->ePrintSize; +} + + +void SmMathConfig::SetPrintSize( SmPrintSize eSize ) +{ + if (!pOther) + LoadOther(); + if (eSize != pOther->ePrintSize) + { + pOther->ePrintSize = eSize; + SetOtherModified( true ); + } +} + + +sal_uInt16 SmMathConfig::GetPrintZoomFactor() const +{ + if (!pOther) + ((SmMathConfig *) this)->LoadOther(); + return pOther->nPrintZoomFactor; +} + + +void SmMathConfig::SetPrintZoomFactor( sal_uInt16 nVal ) +{ + if (!pOther) + LoadOther(); + if (nVal != pOther->nPrintZoomFactor) + { + pOther->nPrintZoomFactor = nVal; + SetOtherModified( true ); + } +} + + +void SmMathConfig::SetOtherIfNotEqual( bool &rbItem, bool bNewVal ) +{ + if (bNewVal != rbItem) + { + rbItem = bNewVal; + SetOtherModified( true ); + } +} + + +bool SmMathConfig::IsPrintTitle() const +{ + if (!pOther) + ((SmMathConfig *) this)->LoadOther(); + return pOther->bPrintTitle; +} + + +void SmMathConfig::SetPrintTitle( bool bVal ) +{ + if (!pOther) + LoadOther(); + SetOtherIfNotEqual( pOther->bPrintTitle, bVal ); +} + + +bool SmMathConfig::IsPrintFormulaText() const +{ + if (!pOther) + ((SmMathConfig *) this)->LoadOther(); + return pOther->bPrintFormulaText; +} + + +void SmMathConfig::SetPrintFormulaText( bool bVal ) +{ + if (!pOther) + LoadOther(); + SetOtherIfNotEqual( pOther->bPrintFormulaText, bVal ); +} + +bool SmMathConfig::IsSaveOnlyUsedSymbols() const +{ + if (!pOther) + ((SmMathConfig *) this)->LoadOther(); + return pOther->bIsSaveOnlyUsedSymbols; +} + +bool SmMathConfig::IsPrintFrame() const +{ + if (!pOther) + ((SmMathConfig *) this)->LoadOther(); + return pOther->bPrintFrame; +} + + +void SmMathConfig::SetPrintFrame( bool bVal ) +{ + if (!pOther) + LoadOther(); + SetOtherIfNotEqual( pOther->bPrintFrame, bVal ); +} + + +void SmMathConfig::SetSaveOnlyUsedSymbols( bool bVal ) +{ + if (!pOther) + LoadOther(); + SetOtherIfNotEqual( pOther->bIsSaveOnlyUsedSymbols, bVal ); +} + + +bool SmMathConfig::IsIgnoreSpacesRight() const +{ + if (!pOther) + ((SmMathConfig *) this)->LoadOther(); + return pOther->bIgnoreSpacesRight; +} + + +void SmMathConfig::SetIgnoreSpacesRight( bool bVal ) +{ + if (!pOther) + LoadOther(); + SetOtherIfNotEqual( pOther->bIgnoreSpacesRight, bVal ); +} + + +bool SmMathConfig::IsAutoRedraw() const +{ + if (!pOther) + ((SmMathConfig *) this)->LoadOther(); + return pOther->bAutoRedraw; +} + + +void SmMathConfig::SetAutoRedraw( bool bVal ) +{ + if (!pOther) + LoadOther(); + SetOtherIfNotEqual( pOther->bAutoRedraw, bVal ); +} + + +bool SmMathConfig::IsShowFormulaCursor() const +{ + if (!pOther) + ((SmMathConfig *) this)->LoadOther(); + return pOther->bFormulaCursor; +} + + +void SmMathConfig::SetShowFormulaCursor( bool bVal ) +{ + if (!pOther) + LoadOther(); + SetOtherIfNotEqual( pOther->bFormulaCursor, bVal ); +} + +void SmMathConfig::Notify( const com::sun::star::uno::Sequence< rtl::OUString >& ) +{} + +///////////////////////////////////////////////////////////////// + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/cfgitem.hxx b/starmath/source/cfgitem.hxx new file mode 100644 index 000000000000..e3fb818d4c4c --- /dev/null +++ b/starmath/source/cfgitem.hxx @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifdef _MSC_VER +#pragma hdrstop +#endif + +#ifndef _MATH_CFGITEM_HXX_ +#define _MATH_CFGITEM_HXX_ + +#include <deque> +#include <vector> + +#include <com/sun/star/beans/PropertyValues.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Any.h> + +#include <tools/solar.h> +#include <rtl/ustring.hxx> +#include <unotools/configitem.hxx> +#include <vcl/timer.hxx> + +#include <symbol.hxx> +#include <types.hxx> + +using namespace com::sun::star; + +class SmSym; +class SmFormat; +class Font; +struct SmCfgOther; + +///////////////////////////////////////////////////////////////// + + +struct SmFontFormat +{ + String aName; + sal_Int16 nCharSet; + sal_Int16 nFamily; + sal_Int16 nPitch; + sal_Int16 nWeight; + sal_Int16 nItalic; + + SmFontFormat(); + SmFontFormat( const Font &rFont ); + + const Font GetFont() const; + bool operator == ( const SmFontFormat &rFntFmt ) const; +}; + + +struct SmFntFmtListEntry +{ + String aId; + SmFontFormat aFntFmt; + + SmFntFmtListEntry( const String &rId, const SmFontFormat &rFntFmt ); +}; + +class SmFontFormatList +{ + std::deque<SmFntFmtListEntry> aEntries; + bool bModified; + + // disallow copy-constructor and assignment-operator for now + SmFontFormatList( const SmFontFormatList & ); + SmFontFormatList & operator = ( const SmFontFormatList & ); + +public: + SmFontFormatList(); + + void Clear(); + void AddFontFormat( const String &rFntFmtId, const SmFontFormat &rFntFmt ); + void RemoveFontFormat( const String &rFntFmtId ); + + const SmFontFormat * GetFontFormat( const String &rFntFmtId ) const; + const SmFontFormat * GetFontFormat( size_t nPos ) const; + const String GetFontFormatId( const SmFontFormat &rFntFmt ) const; + const String GetFontFormatId( const SmFontFormat &rFntFmt, bool bAdd ); + const String GetFontFormatId( size_t nPos ) const; + const String GetNewFontFormatId() const; + size_t GetCount() const { return aEntries.size(); } + + bool IsModified() const { return bModified; } + void SetModified( bool bVal ) { bModified = bVal; } +}; + + +///////////////////////////////////////////////////////////////// + +class SmMathConfig : public utl::ConfigItem +{ + SmFormat * pFormat; + SmCfgOther * pOther; + SmFontFormatList * pFontFormatList; + SmSymbolManager * pSymbolMgr; + bool bIsOtherModified; + bool bIsFormatModified; + + // disallow copy-constructor and assignment-operator for now + SmMathConfig( const SmMathConfig & ); + SmMathConfig & operator = ( const SmMathConfig & ); + + + void StripFontFormatList( const std::vector< SmSym > &rSymbols ); + + + void Save(); + + void ReadSymbol( SmSym &rSymbol, + const rtl::OUString &rSymbolName, + const rtl::OUString &rBaseNode ) const; + void ReadFontFormat( SmFontFormat &rFontFormat, + const rtl::OUString &rSymbolName, + const rtl::OUString &rBaseNode ) const; + + void SetOtherIfNotEqual( bool &rbItem, bool bNewVal ); + +protected: + void LoadOther(); + void SaveOther(); + void LoadFormat(); + void SaveFormat(); + void LoadFontFormatList(); + void SaveFontFormatList(); + + void SetOtherModified( bool bVal ); + inline bool IsOtherModified() const { return bIsOtherModified; } + void SetFormatModified( bool bVal ); + inline bool IsFormatModified() const { return bIsFormatModified; } + void SetFontFormatListModified( bool bVal ); + inline bool IsFontFormatListModified() const { return pFontFormatList ? pFontFormatList->IsModified(): false; } + + SmFontFormatList & GetFontFormatList(); + const SmFontFormatList & GetFontFormatList() const + { + return ((SmMathConfig *) this)->GetFontFormatList(); + } + +public: + SmMathConfig(); + virtual ~SmMathConfig(); + + // utl::ConfigItem + virtual void Notify( const com::sun::star::uno::Sequence< rtl::OUString > &rPropertyNames ); + virtual void Commit(); + + SmSymbolManager & GetSymbolManager(); + void GetSymbols( std::vector< SmSym > &rSymbols ) const; + void SetSymbols( const std::vector< SmSym > &rNewSymbols ); + + const SmFormat & GetStandardFormat() const; + void SetStandardFormat( const SmFormat &rFormat, bool bSaveFontFormatList = false ); + + bool IsPrintTitle() const; + void SetPrintTitle( bool bVal ); + bool IsPrintFormulaText() const; + void SetPrintFormulaText( bool bVal ); + bool IsPrintFrame() const; + void SetPrintFrame( bool bVal ); + SmPrintSize GetPrintSize() const; + void SetPrintSize( SmPrintSize eSize ); + sal_uInt16 GetPrintZoomFactor() const; + void SetPrintZoomFactor( sal_uInt16 nVal ); + + bool IsSaveOnlyUsedSymbols() const; + void SetSaveOnlyUsedSymbols( bool bVal ); + bool IsIgnoreSpacesRight() const; + void SetIgnoreSpacesRight( bool bVal ); + bool IsAutoRedraw() const; + void SetAutoRedraw( bool bVal ); + bool IsShowFormulaCursor() const; + void SetShowFormulaCursor( bool bVal ); + void SetAutoRedraw( sal_Bool bVal ); +}; + +///////////////////////////////////////////////////////////////// + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/commands.src b/starmath/source/commands.src new file mode 100644 index 000000000000..9d618bbd0cf3 --- /dev/null +++ b/starmath/source/commands.src @@ -0,0 +1,1561 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include <sfx2/sfx.hrc> +#include "starmath.hrc" + + +//////////////////////////////////////////////////////////// + +String RID_PLUSX { Text = "+<?> " ; }; +String RID_MINUSX { Text = "-<?> " ; }; +String RID_PLUSMINUSX { Text = "+-<?> " ; }; +String RID_MINUSPLUSX { Text = "-+<?> " ; }; +String RID_NEGX { Text = "neg <?> " ; }; +String RID_XPLUSY { Text = "<?> + <?> " ; }; +String RID_XMINUSY { Text = "<?> - <?> " ; }; +String RID_XCDOTY { Text = "<?> cdot <?> " ; }; +String RID_XTIMESY { Text = "<?> times <?> " ; }; +String RID_XSYMTIMESY { Text = "<?> * <?> " ; }; +String RID_XSYMDIVIDEY { Text = "<?> / <?> " ; }; +String RID_XDIVY { Text = "<?> div <?> " ; }; +String RID_XOVERY { Text = "{<?>} over {<?>} " ; }; +String RID_XODIVIDEY { Text = "<?> odivide <?> " ; }; +String RID_XODOTY { Text = "<?> odot <?> " ; }; +String RID_XOMINUSY { Text = "<?> ominus <?> " ; }; +String RID_XOPLUSY { Text = "<?> oplus <?> " ; }; +String RID_XOTIMESY { Text = "<?> otimes <?> " ; }; +String RID_XANDY { Text = "<?> and <?> " ; }; +String RID_XORY { Text = "<?> or <?> " ; }; +String RID_XEQY { Text = "<?> = <?> " ; }; +String RID_XNEQY { Text = "<?> <> <?> " ; }; +String RID_XLTY { Text = "<?> < <?> " ; }; +String RID_XGTY { Text = "<?> > <?> " ; }; +String RID_XLEY { Text = "<?> <= <?> " ; }; +String RID_XGEY { Text = "<?> >= <?> " ; }; +String RID_XLESLANTY { Text = "<?> leslant <?> " ; }; +String RID_XGESLANTY { Text = "<?> geslant <?> " ; }; +String RID_XLLY { Text = "<?> << <?> " ; }; +String RID_XGGY { Text = "<?> >> <?> " ; }; +String RID_XDEFY { Text = "<?> def <?> " ; }; +String RID_XEQUIVY { Text = "<?> equiv <?> " ; }; +String RID_XAPPROXY { Text = "<?> approx <?> " ; }; +String RID_XSIMY { Text = "<?> sim <?> " ; }; +String RID_XSIMEQY { Text = "<?> simeq <?> " ; }; +String RID_XPROPY { Text = "<?> prop <?> " ; }; +String RID_XORTHOY { Text = "<?> ortho <?> " ; }; +String RID_XPARALLELY { Text = "<?> parallel <?> " ; }; +String RID_XTOWARDY { Text = "<?> toward <?> " ; }; +String RID_XTRANSLY { Text = "<?> transl <?> " ; }; +String RID_XTRANSRY { Text = "<?> transr <?> " ; }; +String RID_XINY { Text = "<?> in <?> " ; }; +String RID_XNOTINY { Text = "<?> notin <?> " ; }; +String RID_XOWNSY { Text = "<?> owns <?> " ; }; +String RID_XUNIONY { Text = "<?> union <?> " ; }; +String RID_XINTERSECTIONY { Text = "<?> intersection <?> " ; }; +String RID_XSETMINUSY { Text = "<?> setminus <?> " ; }; +String RID_XSLASHY { Text = "<?> slash <?> " ; }; +String RID_XSUBSETY { Text = "<?> subset <?> " ; }; +String RID_XSUBSETEQY { Text = "<?> subseteq <?> " ; }; +String RID_XSUPSETY { Text = "<?> supset <?> " ; }; +String RID_XSUPSETEQY { Text = "<?> supseteq <?> " ; }; +String RID_XNSUBSETY { Text = "<?> nsubset <?> " ; }; +String RID_XNSUBSETEQY { Text = "<?> nsubseteq <?> " ; }; +String RID_XNSUPSETY { Text = "<?> nsupset <?> " ; }; +String RID_XNSUPSETEQY { Text = "<?> nsupseteq <?> " ; }; +String RID_ABSX { Text = "abs{<?>} " ; }; +String RID_FACTX { Text = "fact {<?>} " ; }; +String RID_SQRTX { Text = "sqrt{<?>} " ; }; +String RID_NROOTXY { Text = "nroot{<?>}{<?>} " ; }; +String RID_EX { Text = "func e^{<?>} " ; }; +String RID_EXPX { Text = "exp(<?>) " ; }; +String RID_LNX { Text = "ln(<?>) " ; }; +String RID_LOGX { Text = "log(<?>) " ; }; +String RID_SINX { Text = "sin(<?>) " ; }; +String RID_COSX { Text = "cos(<?>) " ; }; +String RID_TANX { Text = "tan(<?>) " ; }; +String RID_COTX { Text = "cot(<?>) " ; }; +String RID_ARCSINX { Text = "arcsin(<?>) " ; }; +String RID_ARCCOSX { Text = "arccos(<?>) " ; }; +String RID_ARCTANX { Text = "arctan(<?>) " ; }; +String RID_ARCCOTX { Text = "arccot(<?>) " ; }; +String RID_SINHX { Text = "sinh(<?>) " ; }; +String RID_COSHX { Text = "cosh(<?>) " ; }; +String RID_TANHX { Text = "tanh(<?>) " ; }; +String RID_COTHX { Text = "coth(<?>) " ; }; +String RID_ARSINHX { Text = "arsinh(<?>) " ; }; +String RID_ARCOSHX { Text = "arcosh(<?>) " ; }; +String RID_ARTANHX { Text = "artanh(<?>) " ; }; +String RID_ARCOTHX { Text = "arcoth(<?>) " ; }; +String RID_SUMX { Text = "sum <?> " ; }; +String RID_PRODX { Text = "prod <?> " ; }; +String RID_COPRODX { Text = "coprod <?> " ; }; +String RID_LIMX { Text = "lim <?> " ; }; +String RID_LIMINFX { Text = "liminf <?> " ; }; +String RID_LIMSUPX { Text = "limsup <?> " ; }; +String RID_EXISTS { Text = "exists " ; }; +String RID_FORALL { Text = "forall " ; }; +String RID_INTX { Text = "int <?> " ; }; +String RID_IINTX { Text = "iint <?> " ; }; +String RID_IIINTX { Text = "iiint <?> " ; }; +String RID_LINTX { Text = "lint <?> " ; }; +String RID_LLINTX { Text = "llint <?> " ; }; +String RID_LLLINTX { Text = "lllint <?> " ; }; +String RID_FROMX { Text = "from{<?>} <?> " ; }; +String RID_TOX { Text = "to{<?>} <?> " ; }; +String RID_FROMXTOY { Text = "from{<?>} to{<?>} <?> " ; }; +String RID_ACUTEX { Text = "acute <?> " ; }; +String RID_BARX { Text = "bar <?> " ; }; +String RID_BREVEX { Text = "breve <?> " ; }; +String RID_CHECKX { Text = "check <?> " ; }; +String RID_CIRCLEX { Text = "circle <?> " ; }; +String RID_DOTX { Text = "dot <?> " ; }; +String RID_DDOTX { Text = "ddot <?> " ; }; +String RID_DDDOTX { Text = "dddot <?> " ; }; +String RID_GRAVEX { Text = "grave <?> " ; }; +String RID_HATX { Text = "hat <?> " ; }; +String RID_TILDEX { Text = "tilde <?> " ; }; +String RID_VECX { Text = "vec <?> " ; }; +String RID_UNDERLINEX { Text = "underline {<?>} " ; }; +String RID_OVERLINEX { Text = "overline {<?>} " ; }; +String RID_OVERSTRIKEX { Text = "overstrike {<?>} " ; }; +String RID_PHANTOMX { Text = "phantom {<?>} " ; }; +String RID_BOLDX { Text = "bold <?> " ; }; +String RID_ITALX { Text = "ital <?> " ; }; +String RID_SIZEXY { Text = "size <?> {<?>} " ; }; +String RID_FONTXY { Text = "font <?> {<?>} " ; }; +String RID_COLORX { Text = "color <?> {<?>} " ; }; +String RID_LRGROUPX { Text = "{<?>} " ; }; +String RID_LRPARENTX { Text = "(<?>) " ; }; +String RID_LRBRACKETX { Text = "[<?>] " ; }; +String RID_LRDBRACKETX { Text = "ldbracket <?> rdbracket " ; }; +String RID_LRBRACEX { Text = "lbrace <?> rbrace " ; }; +String RID_LRANGLEX { Text = "langle <?> rangle " ; }; +String RID_LRCEILX { Text = "lceil <?> rceil " ; }; +String RID_LRFLOORX { Text = "lfloor <?> rfloor " ; }; +String RID_LRLINEX { Text = "lline <?> rline " ; }; +String RID_LRDLINEX { Text = "ldline <?> rdline " ; }; +String RID_LMRANGLEXY { Text = "langle <?> mline <?> rangle " ; }; +String RID_SLRPARENTX { Text = "left ( <?> right ) " ; }; +String RID_SLRBRACKETX { Text = "left [ <?> right ] " ; }; +String RID_SLRDBRACKETX { Text = "left ldbracket <?> right rdbracket " ; }; +String RID_SLRBRACEX { Text = "left lbrace <?> right rbrace " ; }; +String RID_SLRANGLEX { Text = "left langle <?> right rangle " ; }; +String RID_SLRCEILX { Text = "left lceil <?> right rceil " ; }; +String RID_SLRFLOORX { Text = "left lfloor <?> right rfloor " ; }; +String RID_SLRLINEX { Text = "left lline <?> right rline " ; }; +String RID_SLRDLINEX { Text = "left ldline <?> right rdline " ; }; +String RID_SLMRANGLEXY { Text = "left langle <?> mline <?> right rangle " ; }; +String RID_XOVERBRACEY { Text = "{<?>} overbrace {<?>} " ; }; +String RID_XUNDERBRACEY { Text = "{<?>} underbrace {<?>} " ; }; +String RID_RSUBX { Text = "<?>_{<?>}" ; }; +String RID_RSUPX { Text = "<?>^{<?>}" ; }; +String RID_LSUBX { Text = "<?> lsub{<?>} " ; }; +String RID_LSUPX { Text = "<?> lsup{<?>} " ; }; +String RID_CSUBX { Text = "<?> csub{<?>} " ; }; +String RID_CSUPX { Text = "<?> csup{<?>} " ; }; +String RID_SBLANK { Text = "`" ; }; +String RID_BLANK { Text = "~" ; }; +String RID_NEWLINE { Text = "newline " ; }; +String RID_BINOMXY { Text = "binom{<?>}{<?>} " ; }; +String RID_STACK { Text = "stack{<?> # <?> # <?>} " ; }; +String RID_MATRIX { Text = "matrix{<?> # <?> ## <?> # <?>} " ; }; +String RID_ALIGNLX { Text = "alignl <?> " ; }; +String RID_ALIGNCX { Text = "alignc <?> " ; }; +String RID_ALIGNRX { Text = "alignr <?> " ; }; +String RID_ALEPH { Text = "aleph " ; }; +String RID_EMPTYSET { Text = "emptyset " ; }; +String RID_RE { Text = "Re " ; }; +String RID_IM { Text = "Im " ; }; +String RID_INFINITY { Text = "infinity " ; }; +String RID_PARTIAL { Text = "partial " ; }; +String RID_NABLA { Text = "nabla " ; }; +String RID_WP { Text = "wp " ; }; +String RID_DOTSAXIS { Text = "dotsaxis " ; }; +String RID_DOTSUP { Text = "dotsup " ; }; +String RID_DOTSDOWN { Text = "dotsdown " ; }; +String RID_DOTSLOW { Text = "dotslow " ; }; +String RID_DOTSVERT { Text = "dotsvert " ; }; +String RID_XCIRCY { Text = "<?> circ <?> " ; }; +String RID_XWIDESLASHY { Text = "{<?>} wideslash {<?>} " ; }; +String RID_XWIDEBSLASHY { Text = "<?> widebslash <?> " ; }; +String RID_XDIVIDESY { Text = "<?> divides <?> " ; }; +String RID_XNDIVIDESY { Text = "<?> ndivides <?> " ; }; +String RID_DLARROW { Text = "<?> dlarrow <?> " ; }; +String RID_DLRARROW { Text = "<?> dlrarrow <?> " ; }; +String RID_DRARROW { Text = "<?> drarrow <?> " ; }; +String RID_SETN { Text = "setN " ; }; +String RID_SETZ { Text = "setZ " ; }; +String RID_SETQ { Text = "setQ " ; }; +String RID_SETR { Text = "setR " ; }; +String RID_SETC { Text = "setC " ; }; +String RID_WIDEHATX { Text = "widehat {<?>} " ; }; +String RID_WIDETILDEX { Text = "widetilde {<?>} " ; }; +String RID_WIDEVECX { Text = "widevec {<?>} " ; }; +String RID_HBAR { Text = "hbar " ; }; +String RID_LAMBDABAR { Text = "lambdabar " ; }; +String RID_LEFTARROW { Text = "leftarrow " ; }; +String RID_RIGHTARROW { Text = "rightarrow " ; }; +String RID_UPARROW { Text = "uparrow " ; }; +String RID_DOWNARROW { Text = "downarrow " ; }; +String RID_NOSPACE { Text = "nospace {<?>} " ; }; + + +////////////////////////////////////////// + + +Menu RID_COMMANDMENU +{ + ItemList = + { + MenuItem + { + Identifier = RID_UNBINOPS_MENU ; + HelpId = HID_SMA_UNBINOPS_TBX ; + Text [ en-US ] = "~Unary/Binary Operators" ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_PLUSX; + HelpId = HID_SMA_PLUSX; + Text = "+a"; + }; + MenuItem + { + Identifier = RID_MINUSX; + HelpId = HID_SMA_MINUSX; + Text = "-a"; + }; + MenuItem + { + Identifier = RID_PLUSMINUSX; + HelpId = HID_SMA_PLUSMINUSX; + Text = "+-a"; + }; + MenuItem + { + Identifier = RID_MINUSPLUSX; + HelpId = HID_SMA_MINUSPLUSX; + Text = "-+a"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_XPLUSY; + HelpId = HID_SMA_XPLUSY; + Text = "a + b"; + }; + MenuItem + { + Identifier = RID_XMINUSY; + HelpId = HID_SMA_XMINUSY; + Text = "a - b"; + }; + MenuItem + { + Identifier = RID_XCDOTY; + HelpId = HID_SMA_XCDOTY; + Text = "a cdot b"; + }; + MenuItem + { + Identifier = RID_XTIMESY; + HelpId = HID_SMA_XTIMESY; + Text = "a times b"; + }; + MenuItem + { + Identifier = RID_XSYMTIMESY; + HelpId = HID_SMA_XSYMTIMESY; + Text = "a * b"; + }; + MenuItem + { + Identifier = RID_XOVERY; + HelpId = HID_SMA_XOVERY; + Text = "a over b"; + }; + MenuItem + { + Identifier = RID_XDIVY; + HelpId = HID_SMA_XDIVY; + Text = "a div b"; + }; + MenuItem + { + Identifier = RID_XSYMDIVIDEY; + HelpId = HID_SMA_XSYMDIVIDEY; + Text = "a / b"; + }; + MenuItem + { + Identifier = RID_XCIRCY; + HelpId = HID_SMA_XCIRCY; + Text = "a circ b"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_XWIDESLASHY; + HelpId = HID_SMA_XWIDESLASHY; + Text = "a wideslash b"; + }; + MenuItem + { + Identifier = RID_XWIDEBSLASHY; + HelpId = HID_SMA_XWIDEBSLASHY; + Text = "a widebslash b"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_NEGX; + HelpId = HID_SMA_NEGX; + Text = "neg a"; + }; + MenuItem + { + Identifier = RID_XANDY; + HelpId = HID_SMA_XANDY; + Text = "a and b"; + }; + MenuItem + { + Identifier = RID_XORY; + HelpId = HID_SMA_XORY; + Text = "a or b"; + }; + }; + }; + }; + MenuItem + { + Identifier = RID_RELATIONS_MENU ; + HelpId = HID_SMA_RELATIONS_TBX ; + Text [ en-US ] = "~Relations" ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_XEQY; + HelpId = HID_SMA_XEQY; + Text = "a = b"; + }; + MenuItem + { + Identifier = RID_XNEQY; + HelpId = HID_SMA_XNEQY; + Text = "a <> b"; + }; + MenuItem + { + Identifier = RID_XLTY; + HelpId = HID_SMA_XLTY; + Text = "a < b"; + }; + MenuItem + { + Identifier = RID_XLEY; + HelpId = HID_SMA_XLEY; + Text = "a <= b"; + }; + MenuItem + { + Identifier = RID_XLESLANTY; + HelpId = HID_SMA_XLESLANTY; + Text = "a leslant b"; + }; + MenuItem + { + Identifier = RID_XGTY; + HelpId = HID_SMA_XGTY; + Text = "a > b"; + }; + MenuItem + { + Identifier = RID_XGEY; + HelpId = HID_SMA_XGEY; + Text = "a >= b"; + }; + MenuItem + { + Identifier = RID_XGESLANTY; + HelpId = HID_SMA_XGESLANTY; + Text = "a geslant b"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_XAPPROXY; + HelpId = HID_SMA_XAPPROXY; + Text = "a approx b"; + }; + MenuItem + { + Identifier = RID_XSIMY; + HelpId = HID_SMA_XSIMY; + Text = "a sim b"; + }; + MenuItem + { + Identifier = RID_XSIMEQY; + HelpId = HID_SMA_XSIMEQY; + Text = "a simeq b"; + }; + MenuItem + { + Identifier = RID_XEQUIVY; + HelpId = HID_SMA_XEQUIVY; + Text = "a equiv b"; + }; + MenuItem + { + Identifier = RID_XPROPY; + HelpId = HID_SMA_XPROPY; + Text = "a prop b"; + }; + MenuItem + { + Identifier = RID_XPARALLELY; + HelpId = HID_SMA_XPARALLELY; + Text = "a parallel b"; + }; + MenuItem + { + Identifier = RID_XORTHOY; + HelpId = HID_SMA_XORTHOY; + Text = "a ortho b"; + }; + MenuItem + { + Identifier = RID_XDIVIDESY; + HelpId = HID_SMA_XDIVIDESY; + Text = "a divides b"; + }; + MenuItem + { + Identifier = RID_XNDIVIDESY; + HelpId = HID_SMA_XNDIVIDESY; + Text = "a ndivides b"; + }; + MenuItem + { + Identifier = RID_XTOWARDY; + HelpId = HID_SMA_XTOWARDY; + Text = "a toward b"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_DLARROW; + HelpId = HID_SMA_DLARROW; + Text = "a dlarrow b"; + }; + MenuItem + { + Identifier = RID_DLRARROW; + HelpId = HID_SMA_DLRARROW; + Text = "a dlrarrow b"; + }; + MenuItem + { + Identifier = RID_DRARROW; + HelpId = HID_SMA_DRARROW; + Text = "a drarrow b"; + }; + }; + }; + }; + MenuItem + { + Identifier = RID_SETOPERATIONS_MENU ; + HelpId = HID_SMA_SETOPERATIONS_TBX ; + Text [ en-US ] = "~Set Operations" ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_XINY; + HelpId = HID_SMA_XINY; + Text = "a in A"; + }; + MenuItem + { + Identifier = RID_XNOTINY; + HelpId = HID_SMA_XNOTINY; + Text = "a notin A"; + }; + MenuItem + { + Identifier = RID_XOWNSY; + HelpId = HID_SMA_XOWNSY; + Text = "A owns a"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_XINTERSECTIONY; + HelpId = HID_SMA_XINTERSECTIONY; + Text = "A intersection B"; + }; + MenuItem + { + Identifier = RID_XUNIONY; + HelpId = HID_SMA_XUNIONY; + Text = "A union B"; + }; + MenuItem + { + Identifier = RID_XSETMINUSY; + HelpId = HID_SMA_XSETMINUSY; + Text = "A \\ B"; + }; + MenuItem + { + Identifier = RID_XSLASHY; + HelpId = HID_SMA_XSLASHY; + Text = "A / B"; + }; + MenuItem + { + Identifier = RID_XSUBSETY; + HelpId = HID_SMA_XSUBSETY; + Text = "A subset B"; + }; + MenuItem + { + Identifier = RID_XSUBSETEQY; + HelpId = HID_SMA_XSUBSETEQY; + Text = "A subseteq B"; + }; + MenuItem + { + Identifier = RID_XSUPSETY; + HelpId = HID_SMA_XSUPSETY; + Text = "A supset B"; + }; + MenuItem + { + Identifier = RID_XSUPSETEQY; + HelpId = HID_SMA_XSUPSETEQY; + Text = "A supseteq B"; + }; + MenuItem + { + Identifier = RID_XNSUBSETY; + HelpId = HID_SMA_XNSUBSETY; + Text = "A nsubset B"; + }; + MenuItem + { + Identifier = RID_XNSUBSETEQY; + HelpId = HID_SMA_XNSUBSETEQY; + Text = "A nsubseteq B"; + }; + MenuItem + { + Identifier = RID_XNSUPSETY; + HelpId = HID_SMA_XNSUPSETY; + Text = "A nsupset B"; + }; + MenuItem + { + Identifier = RID_XNSUPSETEQY; + HelpId = HID_SMA_XNSUPSETEQY; + Text = "A nsupseteq B"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_EMPTYSET; + HelpId = HID_SMA_EMPTYSET; + Text = "emptyset"; + }; + MenuItem + { + Identifier = RID_ALEPH; + HelpId = HID_SMA_ALEPH; + Text = "aleph"; + }; + MenuItem + { + Identifier = RID_SETN; + HelpId = HID_SMA_SETN; + Text = "setN"; + }; + MenuItem + { + Identifier = RID_SETZ; + HelpId = HID_SMA_SETZ; + Text = "setZ"; + }; + MenuItem + { + Identifier = RID_SETQ; + HelpId = HID_SMA_SETQ; + Text = "setQ"; + }; + MenuItem + { + Identifier = RID_SETR; + HelpId = HID_SMA_SETR; + Text = "setR"; + }; + MenuItem + { + Identifier = RID_SETC; + HelpId = HID_SMA_SETC; + Text = "setC"; + }; + }; + }; + }; + MenuItem + { + Identifier = RID_FUNCTIONS_MENU ; + HelpId = HID_SMA_FUNCTIONS_TBX ; + Text [ en-US ] = "~Functions" ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_ABSX; + HelpId = HID_SMA_ABSX; + Text = "|x|"; + }; + MenuItem + { + Identifier = RID_FACTX; + HelpId = HID_SMA_FACTX; + Text = "x!"; + }; + MenuItem + { + Identifier = RID_SQRTX; + HelpId = HID_SMA_SQRTX; + Text = "sqrt x"; + }; + MenuItem + { + Identifier = RID_NROOTXY; + HelpId = HID_SMA_NROOTXY; + Text = "nroot x y"; + }; + MenuItem + { + Identifier = RID_RSUPX; + HelpId = HID_SMA_RSUPX; + Text = "x^y"; + }; + MenuItem + { + Identifier = RID_EX; + HelpId = HID_SMA_EX; + Text = "e^x"; + }; + MenuItem + { + Identifier = RID_LNX; + HelpId = HID_SMA_LNX; + Text = "ln(x)"; + }; + MenuItem + { + Identifier = RID_EXPX; + HelpId = HID_SMA_EXPX; + Text = "exp(x)"; + }; + MenuItem + { + Identifier = RID_LOGX; + HelpId = HID_SMA_LOGX; + Text = "log(x)"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_SINX; + HelpId = HID_SMA_SINX; + Text = "sin(x)"; + }; + MenuItem + { + Identifier = RID_COSX; + HelpId = HID_SMA_COSX; + Text = "cos(x)"; + }; + MenuItem + { + Identifier = RID_TANX; + HelpId = HID_SMA_TANX; + Text = "tan(x)"; + }; + MenuItem + { + Identifier = RID_COTX; + HelpId = HID_SMA_COTX; + Text = "cot(x)"; + }; + MenuItem + { + Identifier = RID_SINHX; + HelpId = HID_SMA_SINHX; + Text = "sinh(x)"; + }; + MenuItem + { + Identifier = RID_COSHX; + HelpId = HID_SMA_COSHX; + Text = "cosh(x)"; + }; + MenuItem + { + Identifier = RID_TANHX; + HelpId = HID_SMA_TANHX; + Text = "tanh(x)"; + }; + MenuItem + { + Identifier = RID_COTHX; + HelpId = HID_SMA_COTHX; + Text = "coth(x)"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_FUNCTIONSOTHER1_MENU; + HelpId = HID_SMA_FUNCTIONSOTHER1_MENU; + Text [ en-US ] = "More"; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_ARCSINX; + HelpId = HID_SMA_ARCSINX; + Text = "arcsin(x)"; + }; + MenuItem + { + Identifier = RID_ARCCOSX; + HelpId = HID_SMA_ARCCOSX; + Text = "arccos(x)"; + }; + MenuItem + { + Identifier = RID_ARCTANX; + HelpId = HID_SMA_ARCTANX; + Text = "arctan(x)"; + }; + MenuItem + { + Identifier = RID_ARCCOTX; + HelpId = HID_SMA_ARCCOTX; + Text = "arcot(x)"; + }; + MenuItem + { + Identifier = RID_ARSINHX; + HelpId = HID_SMA_ARSINHX; + Text = "arsinh(x)"; + }; + MenuItem + { + Identifier = RID_ARCOSHX; + HelpId = HID_SMA_ARCOSHX; + Text = "arcosh(x)"; + }; + MenuItem + { + Identifier = RID_ARTANHX; + HelpId = HID_SMA_ARTANHX; + Text = "artanh(x)"; + }; + MenuItem + { + Identifier = RID_ARCOTHX; + HelpId = HID_SMA_ARCOTHX; + Text = "arcoth(x)"; + }; + }; + }; + }; + }; + }; + }; + MenuItem + { + Identifier = RID_OPERATORS_MENU ; + HelpId = HID_SMA_OPERATORS_TBX ; + Text [ en-US ] = "O~perators" ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_LIMX; + HelpId = HID_SMA_LIMX; + Text = "lim x"; + }; + MenuItem + { + Identifier = RID_SUMX; + HelpId = HID_SMA_SUMX; + Text = "sum x"; + }; + MenuItem + { + Identifier = RID_PRODX; + HelpId = HID_SMA_PRODX; + Text = "prod x"; + }; + MenuItem + { + Identifier = RID_COPRODX; + HelpId = HID_SMA_COPRODX; + Text = "coprod x"; + }; + MenuItem + { + Identifier = RID_INTX; + HelpId = HID_SMA_INTX; + Text = "int x"; + }; + MenuItem + { + Identifier = RID_IINTX; + HelpId = HID_SMA_IINTX; + Text = "iint x"; + }; + MenuItem + { + Identifier = RID_IIINTX; + HelpId = HID_SMA_IIINTX; + Text = "iiint x"; + }; + MenuItem + { + Identifier = RID_LINTX; + HelpId = HID_SMA_LINTX; + Text = "lint x"; + }; + MenuItem + { + Identifier = RID_LLINTX; + HelpId = HID_SMA_LLINTX; + Text = "llint x"; + }; + MenuItem + { + Identifier = RID_LLLINTX; + HelpId = HID_SMA_LLLINTX; + Text = "lllint x"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_FROMXTOY; + HelpId = HID_SMA_FROMXTOY; + Text = "... from a to b"; + }; + MenuItem + { + Identifier = RID_FROMX; + HelpId = HID_SMA_FROMX; + Text = "... from a"; + }; + MenuItem + { + Identifier = RID_TOX; + HelpId = HID_SMA_TOX; + Text = "... to b"; + }; + }; + }; + }; + MenuItem + { + Identifier = RID_ATTRIBUTES_MENU ; + HelpId = HID_SMA_ATTRIBUTES_TBX ; + Text [ en-US ] = "~Attributes" ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_ACUTEX; + HelpId = HID_SMA_ACUTEX; + Text = "acute a"; + }; + MenuItem + { + Identifier = RID_GRAVEX; + HelpId = HID_SMA_GRAVEX; + Text = "grave a"; + }; + MenuItem + { + Identifier = RID_CHECKX; + HelpId = HID_SMA_CHECKX; + Text = "check a"; + }; + MenuItem + { + Identifier = RID_BREVEX; + HelpId = HID_SMA_BREVEX; + Text = "breve a"; + }; + MenuItem + { + Identifier = RID_CIRCLEX; + HelpId = HID_SMA_CIRCLEX; + Text = "circle a"; + }; + MenuItem + { + Identifier = RID_DOTX; + HelpId = HID_SMA_DOTX; + Text = "dot a"; + }; + MenuItem + { + Identifier = RID_DDOTX; + HelpId = HID_SMA_DDOTX; + Text = "ddot a"; + }; + MenuItem + { + Identifier = RID_DDDOTX; + HelpId = HID_SMA_DDDOTX; + Text = "dddot a"; + }; + MenuItem + { + Identifier = RID_BARX; + HelpId = HID_SMA_BARX; + Text = "bar a"; + }; + MenuItem + { + Identifier = RID_VECX; + HelpId = HID_SMA_VECX; + Text = "vec a"; + }; + MenuItem + { + Identifier = RID_TILDEX; + HelpId = HID_SMA_TILDEX; + Text = "tilde a"; + }; + MenuItem + { + Identifier = RID_HATX; + HelpId = HID_SMA_HATX; + Text = "hat a"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_WIDEVECX; + HelpId = HID_SMA_WIDEVECX; + Text = "widevec abc"; + }; + MenuItem + { + Identifier = RID_WIDETILDEX; + HelpId = HID_SMA_WIDETILDEX; + Text = "widetilde abc"; + }; + MenuItem + { + Identifier = RID_WIDEHATX; + HelpId = HID_SMA_WIDEHATX; + Text = "widehat abc"; + }; + MenuItem + { + Identifier = RID_OVERLINEX; + HelpId = HID_SMA_OVERLINEX; + Text = "overline abc"; + }; + MenuItem + { + Identifier = RID_UNDERLINEX; + HelpId = HID_SMA_UNDERLINEX; + Text = "underline abc"; + }; + MenuItem + { + Identifier = RID_OVERSTRIKEX; + HelpId = HID_SMA_OVERSTRIKEX; + Text = "overstrike abc"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_PHANTOMX; + HelpId = HID_SMA_PHANTOMX; + Text = "phantom b"; + }; + MenuItem + { + Identifier = RID_BOLDX; + HelpId = HID_SMA_BOLDX; + Text = "bold b"; + }; + MenuItem + { + Identifier = RID_ITALX; + HelpId = HID_SMA_ITALX; + Text = "ital b"; + }; + MenuItem + { + Identifier = RID_SIZEXY; + HelpId = HID_SMA_SIZEXY; + Text = "size s b"; + }; + MenuItem + { + Identifier = RID_FONTXY; + HelpId = HID_SMA_FONTXY; + Text = "font f b"; + }; + }; + }; + }; + MenuItem + { + Identifier = RID_BRACKETS_MENU ; + HelpId = HID_SMA_BRACKETS_TBX ; + Text [ en-US ] = "~Brackets" ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_LRGROUPX; + HelpId = HID_SMA_LRGROUPX; + Text = "{...}"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_LRPARENTX; + HelpId = HID_SMA_LRPARENTX; + Text = "(x)"; + }; + MenuItem + { + Identifier = RID_LRBRACKETX; + HelpId = HID_SMA_LRBRACKETX; + Text = "[x]"; + }; + MenuItem + { + Identifier = RID_LRDBRACKETX; + HelpId = HID_SMA_LRDBRACKETX; + Text = "ldbracket x rdbracket "; + }; + MenuItem + { + Identifier = RID_LRBRACEX; + HelpId = HID_SMA_LRBRACEX; + Text = "{x}"; + }; + MenuItem + { + Identifier = RID_LRANGLEX; + HelpId = HID_SMA_LRANGLEX; + Text = "langle x rangle"; + }; + MenuItem + { + Identifier = RID_LMRANGLEXY; + HelpId = HID_SMA_LMRANGLEXY; + Text = "langle x mline y rangle"; + }; + MenuItem + { + Identifier = RID_LRCEILX; + HelpId = HID_SMA_LRCEILX; + Text = "lceil x rceil"; + }; + MenuItem + { + Identifier = RID_LRFLOORX; + HelpId = HID_SMA_LRFLOORX; + Text = "lfloor x rfloor"; + }; + MenuItem + { + Identifier = RID_LRLINEX; + HelpId = HID_SMA_LRLINEX; + Text = "lline x rline"; + }; + MenuItem + { + Identifier = RID_LRDLINEX; + HelpId = HID_SMA_LRDLINEX; + Text = "ldline x rdline"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_SLRPARENTX; + HelpId = HID_SMA_SLRPARENTX; + Text = "left ( x right )"; + }; + MenuItem + { + Identifier = RID_SLRBRACKETX; + HelpId = HID_SMA_SLRBRACKETX; + Text = "left [ x right ]"; + }; + MenuItem + { + Identifier = RID_SLRDBRACKETX; + HelpId = HID_SMA_SLRDBRACKETX; + Text = "left ldbracket x right rdbracket "; + }; + MenuItem + { + Identifier = RID_SLRBRACEX; + HelpId = HID_SMA_SLRBRACEX; + Text = "left { x right }"; + }; + MenuItem + { + Identifier = RID_SLRANGLEX; + HelpId = HID_SMA_SLRANGLEX; + Text = "left langle x right rangle"; + }; + MenuItem + { + Identifier = RID_SLMRANGLEXY; + HelpId = HID_SMA_SLMRANGLEXY; + Text = "left langle x mline y right rangle"; + }; + MenuItem + { + Identifier = RID_SLRCEILX; + HelpId = HID_SMA_SLRCEILX; + Text = "left lceil x right rceil"; + }; + MenuItem + { + Identifier = RID_SLRFLOORX; + HelpId = HID_SMA_SLRFLOORX; + Text = "left lfloor x right rfloor"; + }; + MenuItem + { + Identifier = RID_SLRLINEX; + HelpId = HID_SMA_SLRLINEX; + Text = "left lline x right rline"; + }; + MenuItem + { + Identifier = RID_SLRDLINEX; + HelpId = HID_SMA_SLRDLINEX; + Text = "left ldline x right rdline"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_XOVERBRACEY; + HelpId = HID_SMA_XOVERBRACEY; + Text = "x overbrace y"; + }; + MenuItem + { + Identifier = RID_XUNDERBRACEY; + HelpId = HID_SMA_XUNDERBRACEY; + Text = "x underbrace y"; + }; + }; + }; + }; + MenuItem + { + Identifier = RID_FORMAT_MENU ; + HelpId = HID_SMA_FORMAT_TBX ; + Text [ en-US ] = "For~mats" ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_RSUPX; + HelpId = HID_SMA_RSUPX; + Text = "^x"; + }; + MenuItem + { + Identifier = RID_RSUBX; + HelpId = HID_SMA_RSUBX; + Text = "_x"; + }; + MenuItem + { + Identifier = RID_LSUPX; + HelpId = HID_SMA_LSUPX; + Text = "lsup x"; + }; + MenuItem + { + Identifier = RID_LSUBX; + HelpId = HID_SMA_LSUBX; + Text = "lsub x"; + }; + MenuItem + { + Identifier = RID_CSUPX; + HelpId = HID_SMA_CSUPX; + Text = "csup x"; + }; + MenuItem + { + Identifier = RID_CSUBX; + HelpId = HID_SMA_CSUBX; + Text = "csub x"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_NEWLINE; + HelpId = HID_SMA_NEWLINE; + Text [ en-US ] = "New Line"; + }; + MenuItem + { + Identifier = RID_SBLANK; + HelpId = HID_SMA_SBLANK; + Text [ en-US ] = "Small Gap"; + }; + MenuItem + { + Identifier = RID_BLANK; + HelpId = HID_SMA_BLANK; + Text [ en-US ] = "Gap"; + }; + MenuItem + { + Identifier = RID_NOSPACE; + HelpId = HID_SMA_NOSPACE; + Text [ en-US ] = "nospace {...}"; + }; + MenuItem + { + Identifier = RID_BINOMXY; + HelpId = HID_SMA_BINOMXY; + Text = "binom x y"; + }; + MenuItem + { + Identifier = RID_STACK; + HelpId = HID_SMA_STACK; + Text = "stack {...}"; + }; + MenuItem + { + Identifier = RID_MATRIX; + HelpId = HID_SMA_MATRIX; + Text = "matrix {...}"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_ALIGNLX; + HelpId = HID_SMA_ALIGNLX; + Text = "alignl x"; + }; + MenuItem + { + Identifier = RID_ALIGNCX; + HelpId = HID_SMA_ALIGNCX; + Text = "alignc x"; + }; + MenuItem + { + Identifier = RID_ALIGNRX; + HelpId = HID_SMA_ALIGNRX; + Text = "alignr x"; + }; + }; + }; + }; + MenuItem + { + Identifier = RID_MISC_MENU ; + HelpId = HID_SMA_MISC_MENU ; + Text [ en-US ] = "~Others" ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = RID_INFINITY; + HelpId = HID_SMA_INFINITY; + Text = "infinity"; + }; + MenuItem + { + Identifier = RID_PARTIAL; + HelpId = HID_SMA_PARTIAL; + Text = "partial"; + }; + MenuItem + { + Identifier = RID_NABLA; + HelpId = HID_SMA_NABLA; + Text = "nabla"; + }; + MenuItem + { + Identifier = RID_EXISTS; + HelpId = HID_SMA_EXISTS; + Text = "exists"; + }; + MenuItem + { + Identifier = RID_FORALL; + HelpId = HID_SMA_FORALL; + Text = "forall"; + }; + MenuItem + { + Identifier = RID_HBAR; + HelpId = HID_SMA_HBAR; + Text = "hbar"; + }; + MenuItem + { + Identifier = RID_LAMBDABAR; + HelpId = HID_SMA_LAMBDABAR; + Text = "lambdabar"; + }; + MenuItem + { + Identifier = RID_RE; + HelpId = HID_SMA_RE; + Text = "Re"; + }; + MenuItem + { + Identifier = RID_IM; + HelpId = HID_SMA_IM; + Text = "Im"; + }; + MenuItem + { + Identifier = RID_WP; + HelpId = HID_SMA_WP; + Text = "wp"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_LEFTARROW; + HelpId = HID_SMA_LEFTARROW; + Text = "leftarrow"; + }; + MenuItem + { + Identifier = RID_RIGHTARROW; + HelpId = HID_SMA_RIGHTARROW; + Text = "rightarrow"; + }; + MenuItem + { + Identifier = RID_UPARROW; + HelpId = HID_SMA_UPARROW; + Text = "uparrow"; + }; + MenuItem + { + Identifier = RID_DOWNARROW; + HelpId = HID_SMA_DOWNARROW; + Text = "downarrow"; + }; + MenuItem + { + Separator = TRUE; + }; + MenuItem + { + Identifier = RID_DOTSLOW; + HelpId = HID_SMA_DOTSLOW; + Text = "dotslow"; + }; + MenuItem + { + Identifier = RID_DOTSAXIS; + HelpId = HID_SMA_DOTSAXIS; + Text = "dotsaxis"; + }; + MenuItem + { + Identifier = RID_DOTSVERT; + HelpId = HID_SMA_DOTSVERT; + Text = "dotsvert"; + }; + MenuItem + { + Identifier = RID_DOTSUP; + HelpId = HID_SMA_DOTSUP; + Text = "dotsup"; + }; + MenuItem + { + Identifier = RID_DOTSDOWN; + HelpId = HID_SMA_DOTSDOWN; + Text = "dotsdown"; + }; + }; + }; + }; + }; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/starmath/source/config.cxx b/starmath/source/config.cxx new file mode 100644 index 000000000000..2bcfb43a0d1f --- /dev/null +++ b/starmath/source/config.cxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <svl/itemset.hxx> +#include <svl/hint.hxx> +#include <svl/smplhint.hxx> +#include <unotools/pathoptions.hxx> +#include <sfx2/sfxsids.hrc> +#include <svl/eitem.hxx> +#include <svl/itempool.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> +#include <tools/stream.hxx> + + +#include "config.hxx" +#include "format.hxx" +#include "smmod.hxx" +#include "starmath.hrc" + +///////////////////////////////////////////////////////////////// + +SmConfig::SmConfig() +{ +} + + +SmConfig::~SmConfig() +{ +} + + +void SmConfig::ItemSetToConfig(const SfxItemSet &rSet) +{ + const SfxPoolItem *pItem = NULL; + + sal_uInt16 nU16; + bool bVal; + if (rSet.GetItemState(SID_PRINTSIZE, sal_True, &pItem) == SFX_ITEM_SET) + { nU16 = ((const SfxUInt16Item *) pItem)->GetValue(); + SetPrintSize( (SmPrintSize) nU16 ); + } + if (rSet.GetItemState(SID_PRINTZOOM, sal_True, &pItem) == SFX_ITEM_SET) + { nU16 = ((const SfxUInt16Item *) pItem)->GetValue(); + SetPrintZoomFactor( nU16 ); + } + if (rSet.GetItemState(SID_PRINTTITLE, sal_True, &pItem) == SFX_ITEM_SET) + { bVal = ((const SfxBoolItem *) pItem)->GetValue(); + SetPrintTitle( bVal ); + } + if (rSet.GetItemState(SID_PRINTTEXT, sal_True, &pItem) == SFX_ITEM_SET) + { bVal = ((const SfxBoolItem *) pItem)->GetValue(); + SetPrintFormulaText( bVal ); + } + if (rSet.GetItemState(SID_PRINTFRAME, sal_True, &pItem) == SFX_ITEM_SET) + { bVal = ((const SfxBoolItem *) pItem)->GetValue(); + SetPrintFrame( bVal ); + } + if (rSet.GetItemState(SID_AUTOREDRAW, sal_True, &pItem) == SFX_ITEM_SET) + { bVal = ((const SfxBoolItem *) pItem)->GetValue(); + SetAutoRedraw( bVal ); + } + if (rSet.GetItemState(SID_NO_RIGHT_SPACES, sal_True, &pItem) == SFX_ITEM_SET) + { bVal = ((const SfxBoolItem *) pItem)->GetValue(); + if (IsIgnoreSpacesRight() != bVal) + { + SetIgnoreSpacesRight( bVal ); + + // (angezeigte) Formeln muessen entsprechen neu formatiert werden. + // Das erreichen wir mit: + Broadcast(SfxSimpleHint(HINT_FORMATCHANGED)); + } + } + if (rSet.GetItemState(SID_SAVE_ONLY_USED_SYMBOLS, sal_True, &pItem) == SFX_ITEM_SET) + { bVal = ((const SfxBoolItem *) pItem)->GetValue(); + SetSaveOnlyUsedSymbols( bVal ); + } + + SaveOther(); +} + + +void SmConfig::ConfigToItemSet(SfxItemSet &rSet) const +{ + const SfxItemPool *pPool = rSet.GetPool(); + + rSet.Put(SfxUInt16Item(pPool->GetWhich(SID_PRINTSIZE), + (sal_uInt16) GetPrintSize())); + rSet.Put(SfxUInt16Item(pPool->GetWhich(SID_PRINTZOOM), + (sal_uInt16) GetPrintZoomFactor())); + + rSet.Put(SfxBoolItem(pPool->GetWhich(SID_PRINTTITLE), IsPrintTitle())); + rSet.Put(SfxBoolItem(pPool->GetWhich(SID_PRINTTEXT), IsPrintFormulaText())); + rSet.Put(SfxBoolItem(pPool->GetWhich(SID_PRINTFRAME), IsPrintFrame())); + rSet.Put(SfxBoolItem(pPool->GetWhich(SID_AUTOREDRAW), IsAutoRedraw())); + rSet.Put(SfxBoolItem(pPool->GetWhich(SID_NO_RIGHT_SPACES), IsIgnoreSpacesRight())); + rSet.Put(SfxBoolItem(pPool->GetWhich(SID_SAVE_ONLY_USED_SYMBOLS), IsSaveOnlyUsedSymbols())); +} + + +///////////////////////////////////////////////////////////////// + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/cursor.cxx b/starmath/source/cursor.cxx new file mode 100644 index 000000000000..3375f18abab2 --- /dev/null +++ b/starmath/source/cursor.cxx @@ -0,0 +1,1646 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Jonas Finnemann Jensen <jopsen@gmail.com> + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jonas Finnemann Jensen <jopsen@gmail.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include "cursor.hxx" +#include "parse.hxx" +#include "visitors.hxx" +#include "document.hxx" +#include "view.hxx" +#include "accessibility.hxx" + +void SmCursor::Move(OutputDevice* pDev, SmMovementDirection direction, bool bMoveAnchor){ + SmCaretPosGraphEntry* NewPos = NULL; + switch(direction){ + case MoveLeft: + { + NewPos = position->Left; + OSL_ENSURE(NewPos, "NewPos shouldn't be NULL here!"); + }break; + case MoveRight: + { + NewPos = position->Right; + OSL_ENSURE(NewPos, "NewPos shouldn't be NULL here!"); + }break; + case MoveUp: + //Implementation is practically identical to MoveDown, except for a single if statement + //so I've implemented them together and added a direction == MoveDown to the if statements. + case MoveDown: + { + SmCaretLine from_line = SmCaretPos2LineVisitor(pDev, position->CaretPos).GetResult(), + best_line, //Best approximated line found so far + curr_line; //Current line + long dbp_sq = 0; //Distance squared to best line + SmCaretPosGraphIterator it = pGraph->GetIterator(); + while(it.Next()){ + //Reject it if it's the current position + if(it->CaretPos == position->CaretPos) continue; + //Compute caret line + curr_line = SmCaretPos2LineVisitor(pDev, it->CaretPos).GetResult(); + //Reject anything above if we're moving down + if(curr_line.GetTop() <= from_line.GetTop() && direction == MoveDown) continue; + //Reject anything below if we're moving up + if(curr_line.GetTop() + curr_line.GetHeight() >= from_line.GetTop() + from_line.GetHeight() + && direction == MoveUp) continue; + //Compare if it to what we have, if we have anything yet + if(NewPos){ + //Compute distance to current line squared, multiplied with a horizontial factor + long dp_sq = curr_line.SquaredDistanceX(from_line) * HORIZONTICAL_DISTANCE_FACTOR + + curr_line.SquaredDistanceY(from_line); + //Discard current line if best line is closer + if(dbp_sq <= dp_sq) continue; + } + //Take current line as the best + best_line = curr_line; + NewPos = it.Current(); + //Update distance to best line + dbp_sq = best_line.SquaredDistanceX(from_line) * HORIZONTICAL_DISTANCE_FACTOR + + best_line.SquaredDistanceY(from_line); + } + }break; + default: + OSL_FAIL("Movement direction not supported!"); + } + if(NewPos){ + position = NewPos; + if(bMoveAnchor) + anchor = NewPos; + RequestRepaint(); + } +} + +void SmCursor::MoveTo(OutputDevice* pDev, Point pos, bool bMoveAnchor){ + SmCaretLine best_line, //Best line found so far, when iterating + curr_line; //Current line, when iterating + SmCaretPosGraphEntry* NewPos = NULL; + long dp_sq = 0, //Distance to current line squared + dbp_sq = 1; //Distance to best line squared + SmCaretPosGraphIterator it = pGraph->GetIterator(); + while(it.Next()){ + OSL_ENSURE(it->CaretPos.IsValid(), "The caret position graph may not have invalid positions!"); + //Compute current line + curr_line = SmCaretPos2LineVisitor(pDev, it->CaretPos).GetResult(); + //If we have a position compare to it + if(NewPos){ + //Compute squared distance to current line + dp_sq = curr_line.SquaredDistanceX(pos) + curr_line.SquaredDistanceY(pos); + //If best line is closer, reject current line + if(dbp_sq <= dp_sq) continue; + } + //Accept current position as the best + best_line = curr_line; + NewPos = it.Current(); + //Update distance to best line + dbp_sq = best_line.SquaredDistanceX(pos) + best_line.SquaredDistanceY(pos); + } + if(NewPos){ + position = NewPos; + if(bMoveAnchor) + anchor = NewPos; + RequestRepaint(); + } +} + +void SmCursor::BuildGraph(){ + //Save the current anchor and position + SmCaretPos _anchor, _position; + //Release pGraph if allocated + if(pGraph){ + if(anchor) + _anchor = anchor->CaretPos; + if(position) + _position = position->CaretPos; + delete pGraph; + //Reset anchor and position as they point into an old graph + anchor = NULL; + position = NULL; + } + pGraph = NULL; + + //Build the new graph + pGraph = SmCaretPosGraphBuildingVisitor(pTree).Graph(); + + //Restore anchor and position pointers + if(_anchor.IsValid() || _position.IsValid()){ + SmCaretPosGraphIterator it = pGraph->GetIterator(); + while(it.Next()){ + if(_anchor == it->CaretPos) + anchor = it.Current(); + if(_position == it->CaretPos) + position = it.Current(); + } + } + //Set position and anchor to first caret position + SmCaretPosGraphIterator it = pGraph->GetIterator(); + if(!position) + position = it.Next(); + if(!anchor) + anchor = position; + + OSL_ENSURE(position->CaretPos.IsValid(), "Position must be valid"); + OSL_ENSURE(anchor->CaretPos.IsValid(), "Anchor must be valid"); +} + +bool SmCursor::SetCaretPosition(SmCaretPos pos, bool moveAnchor){ + SmCaretPosGraphIterator it = pGraph->GetIterator(); + while(it.Next()){ + if(it->CaretPos == pos){ + position = it.Current(); + if(moveAnchor) + anchor = it.Current(); + return true; + } + } + return false; +} + +void SmCursor::AnnotateSelection(){ + //TODO: Manage a state, reset it upon modification and optimize this call + SmSetSelectionVisitor(anchor->CaretPos, position->CaretPos, pTree); +} + +void SmCursor::Draw(OutputDevice& pDev, Point Offset, bool isCaretVisible){ + SmCaretDrawingVisitor(pDev, GetPosition(), Offset, isCaretVisible); +} + +void SmCursor::DeletePrev(OutputDevice* pDev){ + //Delete only a selection if there's a selection + if(HasSelection()){ + Delete(); + return; + } + + SmNode* pLine = FindTopMostNodeInLine(position->CaretPos.pSelectedNode); + SmStructureNode* pLineParent = pLine->GetParent(); + int nLineOffset = pLineParent->IndexOfSubNode(pLine); + + //If we're in front of a node who's parent is a TABLE + if(pLineParent->GetType() == NTABLE && position->CaretPos.Index == 0 && nLineOffset > 0){ + //Now we can merge with nLineOffset - 1 + BeginEdit(); + //Line to merge things into, so we can delete pLine + SmNode* pMergeLine = pLineParent->GetSubNode(nLineOffset-1); + OSL_ENSURE(pMergeLine, "pMergeLine cannot be NULL!"); + //Convert first line to list + SmNodeList *pLineList = NodeToList(pMergeLine); + //Find iterator to patch + SmNodeList::iterator patchPoint = pLineList->end(); + --patchPoint; + //Convert second line to list + NodeToList(pLine, pLineList); + //Patch the line list + ++patchPoint; + SmCaretPos PosAfterDelete = PatchLineList(pLineList, patchPoint); + //Parse the line + pLine = SmNodeListParser().Parse(pLineList); + delete pLineList; + pLineParent->SetSubNode(nLineOffset-1, pLine); + //Delete the removed line slot + SmNodeArray lines(pLineParent->GetNumSubNodes()-1); + for(int i = 0; i < pLineParent->GetNumSubNodes(); i++){ + if(i < nLineOffset) + lines[i] = pLineParent->GetSubNode(i); + else if(i > nLineOffset) + lines[i-1] = pLineParent->GetSubNode(i); + } + pLineParent->SetSubNodes(lines); + //Rebuild graph + anchor = NULL; + position = NULL; + BuildGraph(); + AnnotateSelection(); + //Set caret position + if(!SetCaretPosition(PosAfterDelete, true)) + SetCaretPosition(SmCaretPos(pLine, 0), true); + //Finish editing + EndEdit(); + + //TODO: If we're in an empty (sub/super/*) script + /*}else if(pLineParent->GetType() == NSUBSUP && + nLineOffset != 0 && + pLine->GetType() == NEXPRESSION && + pLine->GetNumSubNodes() == 0){ + //There's a (sub/super) script we can delete + //Consider selecting the entire script if GetNumSubNodes() != 0 or pLine->GetType() != NEXPRESSION + //TODO: Handle case where we delete a limit + */ + + //Else move select, and delete if not complex + }else{ + this->Move(pDev, MoveLeft, false); + if(!this->HasComplexSelection()) + Delete(); + } +} + +void SmCursor::Delete(){ + //Return if we don't have a selection to delete + if(!HasSelection()) + return; + + //Enter edit setion + BeginEdit(); + + //Set selected on nodes + AnnotateSelection(); + + //Find an arbitrary selected node + SmNode* pSNode = FindSelectedNode(pTree); + OSL_ENSURE(pSNode != NULL, "There must be a selection when HasSelection is true!"); + + //Find the topmost node of the line that holds the selection + SmNode* pLine = FindTopMostNodeInLine(pSNode, true); + OSL_ENSURE(pLine != pTree, "Shouldn't be able to select the entire tree"); + + //Get the parent of the line + SmStructureNode* pLineParent = pLine->GetParent(); + //Find line offset in parent + int nLineOffset = pLineParent->IndexOfSubNode(pLine); + OSL_ENSURE(nLineOffset != -1, "pLine must be a child of it's parent!"); + + //Position after delete + SmCaretPos PosAfterDelete; + + SmNodeList* pLineList = NodeToList(pLine); + + //Take the selected nodes and delete them... + SmNodeList::iterator patchIt = TakeSelectedNodesFromList(pLineList); + + //Get teh position to set after delete + PosAfterDelete = PatchLineList(pLineList, patchIt); + + //Finish editing + FinishEdit(pLineList, pLineParent, nLineOffset, PosAfterDelete); +} + +void SmCursor::InsertNodes(SmNodeList* pNewNodes){ + if(pNewNodes->size() == 0){ + delete pNewNodes; + return; + } + + //Begin edit section + BeginEdit(); + + //Position after insert should be after pNewNode + SmCaretPos PosAfterInsert = SmCaretPos(pNewNodes->back(), 1); + + //Get the current position + const SmCaretPos pos = position->CaretPos; + + //Find top most of line that holds position + SmNode* pLine = FindTopMostNodeInLine(pos.pSelectedNode, false); + + //Find line parent and line index in parent + SmStructureNode* pLineParent = pLine->GetParent(); + int nParentIndex = pLineParent->IndexOfSubNode(pLine); + OSL_ENSURE(nParentIndex != -1, "pLine must be a subnode of pLineParent!"); + + //Convert line to list + SmNodeList* pLineList = NodeToList(pLine); + + //Find iterator for place to insert nodes + SmNodeList::iterator it = FindPositionInLineList(pLineList, pos); + + //Insert all new nodes + SmNodeList::iterator newIt, + patchIt = it, // (pointless default value, fixes compiler warnings) + insIt; + for(newIt = pNewNodes->begin(); newIt != pNewNodes->end(); ++newIt){ + insIt = pLineList->insert(it, *newIt); + if(newIt == pNewNodes->begin()) + patchIt = insIt; + if((*newIt)->GetType() == NTEXT) + PosAfterInsert = SmCaretPos(*newIt, ((SmTextNode*)*newIt)->GetText().Len()); + else + PosAfterInsert = SmCaretPos(*newIt, 1); + } + //Patch the places we've changed stuff + PatchLineList(pLineList, patchIt); + PosAfterInsert = PatchLineList(pLineList, it); + //Release list, we've taken the nodes + delete pNewNodes; + pNewNodes = NULL; + + //Finish editing + FinishEdit(pLineList, pLineParent, nParentIndex, PosAfterInsert); +} + +SmNodeList::iterator SmCursor::FindPositionInLineList(SmNodeList* pLineList, SmCaretPos aCaretPos) { + //Find iterator for position + SmNodeList::iterator it; + for(it = pLineList->begin(); it != pLineList->end(); ++it){ + if(*it == aCaretPos.pSelectedNode){ + if((*it)->GetType() == NTEXT){ + //Split textnode if needed + if(aCaretPos.Index > 0){ + SmTextNode* pText = (SmTextNode*)aCaretPos.pSelectedNode; + XubString str1 = pText->GetText().Copy(0, aCaretPos.Index); + XubString str2 = pText->GetText().Copy(aCaretPos.Index); + pText->ChangeText(str1); + ++it; + //Insert str2 as new text node + if(str2.Len() > 0){ + SmTextNode* pNewText = new SmTextNode(pText->GetToken(), pText->GetFontDesc()); + pNewText->ChangeText(str2); + it = pLineList->insert(it, pNewText); + } + } + }else + ++it; + //it now pointer to the node following pos, so pLineList->insert(it, ...) will insert correctly + return it; + + } + } + //If we didn't find pSelectedNode, it must be because the caret is in front of the line + return pLineList->begin(); +} + +SmCaretPos SmCursor::PatchLineList(SmNodeList* pLineList, SmNodeList::iterator aIter) { + //The nodes we should consider merging + SmNode *prev = NULL, + *next = NULL; + if(aIter != pLineList->end()) + next = *aIter; + if(aIter != pLineList->begin()) { + --aIter; + prev = *aIter; + ++aIter; + } + + //Check if there's textnodes to merge + if( prev && + next && + prev->GetType() == NTEXT && + next->GetType() == NTEXT && + ( prev->GetToken().eType != TNUMBER || + next->GetToken().eType == TNUMBER) ){ + SmTextNode *pText = (SmTextNode*)prev, + *pOldN = (SmTextNode*)next; + SmCaretPos retval(pText, pText->GetText().Len()); + String newText; + newText += pText->GetText(); + newText += pOldN->GetText(); + pText->ChangeText(newText); + delete pOldN; + pLineList->erase(aIter); + return retval; + } + + //Check if there's a SmPlaceNode to remove: + if(prev && next && prev->GetType() == NPLACE && !SmNodeListParser::IsOperator(next->GetToken())){ + --aIter; + aIter = pLineList->erase(aIter); + delete prev; + //Return caret pos in front of aIter + if(aIter != pLineList->begin()) + --aIter; //Thus find node before aIter + if(aIter == pLineList->begin()) + return SmCaretPos(); + if((*aIter)->GetType() == NTEXT) + return SmCaretPos(*aIter, ((SmTextNode*)*aIter)->GetText().Len()); + return SmCaretPos(*aIter, 1); + } + if(prev && next && next->GetType() == NPLACE && !SmNodeListParser::IsOperator(prev->GetToken())){ + aIter = pLineList->erase(aIter); + delete next; + if(prev->GetType() == NTEXT) + return SmCaretPos(prev, ((SmTextNode*)prev)->GetText().Len()); + return SmCaretPos(prev, 1); + } + + //If we didn't do anything return + if(!prev) //return an invalid to indicate we're in front of line + return SmCaretPos(); + if(prev->GetType() == NTEXT) + return SmCaretPos(prev, ((SmTextNode*)prev)->GetText().Len()); + return SmCaretPos(prev, 1); +} + +SmNodeList::iterator SmCursor::TakeSelectedNodesFromList(SmNodeList *pLineList, + SmNodeList *pSelectedNodes) { + SmNodeList::iterator retval; + SmNodeList::iterator it = pLineList->begin(); + while(it != pLineList->end()){ + if((*it)->IsSelected()){ + //Split text nodes + if((*it)->GetType() == NTEXT) { + SmTextNode* pText = (SmTextNode*)*it; + String aText = pText->GetText(); + //Start and lengths of the segments, 2 is the selected segment + int start2 = pText->GetSelectionStart(), + start3 = pText->GetSelectionEnd(), + len1 = start2 - 0, + len2 = start3 - start2, + len3 = aText.Len() - start3; + SmToken aToken = pText->GetToken(); + sal_uInt16 eFontDesc = pText->GetFontDesc(); + //If we need make segment 1 + if(len1 > 0) { + int start1 = 0; + String str = aText.Copy(start1, len1); + pText->ChangeText(str); + ++it; + } else {//Remove it if not needed + it = pLineList->erase(it); + delete pText; + } + //Set retval to be right after the selection + retval = it; + //if we need make segment 3 + if(len3 > 0) { + String str = aText.Copy(start3, len3); + SmTextNode* pSeg3 = new SmTextNode(aToken, eFontDesc); + pSeg3->ChangeText(str); + retval = pLineList->insert(it, pSeg3); + } + //If we need to save the selected text + if(pSelectedNodes && len2 > 0) { + String str = aText.Copy(start2, len2); + SmTextNode* pSeg2 = new SmTextNode(aToken, eFontDesc); + pSeg2->ChangeText(str); + pSelectedNodes->push_back(pSeg2); + } + } else { //if it's not textnode + SmNode* pNode = *it; + retval = it = pLineList->erase(it); + if(pSelectedNodes) + pSelectedNodes->push_back(pNode); + else + delete pNode; + } + } else + ++it; + } + return retval; +} + +void SmCursor::InsertSubSup(SmSubSup eSubSup) { + AnnotateSelection(); + + //Find line + SmNode *pLine; + if(HasSelection()) { + SmNode *pSNode = FindSelectedNode(pTree); + OSL_ENSURE(pSNode != NULL, "There must be a selected node when HasSelection is true!"); + pLine = FindTopMostNodeInLine(pSNode, sal_True); + } else + pLine = FindTopMostNodeInLine(position->CaretPos.pSelectedNode, sal_False); + + //Find Parent and offset in parent + SmStructureNode *pLineParent = pLine->GetParent(); + int nParentIndex = pLineParent->IndexOfSubNode(pLine); + OSL_ENSURE(nParentIndex != -1, "pLine must be a subnode of pLineParent!"); + + //TODO: Consider handling special cases where parent is an SmOperNode, + // Maybe this method should be able to add limits to an SmOperNode... + + //We begin modifying the tree here + BeginEdit(); + + //Convert line to list + SmNodeList* pLineList = NodeToList(pLine); + + //Take the selection, and/or find iterator for current position + SmNodeList* pSelectedNodesList = new SmNodeList(); + SmNodeList::iterator it; + if(HasSelection()) + it = TakeSelectedNodesFromList(pLineList, pSelectedNodesList); + else + it = FindPositionInLineList(pLineList, position->CaretPos); + + //Find node that this should be applied to + SmNode* pSubject; + bool bPatchLine = pSelectedNodesList->size() > 0; //If the line should be patched later + if(it != pLineList->begin()) { + --it; + pSubject = *it; + ++it; + } else { + //Create a new place node + pSubject = new SmPlaceNode(); + pSubject->Prepare(pDocShell->GetFormat(), *pDocShell); + it = pLineList->insert(it, pSubject); + ++it; + bPatchLine = true; //We've modified the line it should be patched later. + } + + //Wrap the subject in a SmSubSupNode + SmSubSupNode* pSubSup; + if(pSubject->GetType() != NSUBSUP){ + SmToken token; + token.nGroup = TGPOWER; + pSubSup = new SmSubSupNode(token); + pSubSup->SetBody(pSubject); + *(--it) = pSubSup; + ++it; + }else + pSubSup = (SmSubSupNode*)pSubject; + //pSubject shouldn't be referenced anymore, pSubSup is the SmSubSupNode in pLineList we wish to edit. + //and it pointer to the element following pSubSup in pLineList. + pSubject = NULL; + + //Patch the line if we noted that was needed previously + if(bPatchLine) + PatchLineList(pLineList, it); + + //Convert existing, if any, sub-/superscript line to list + SmNode *pScriptLine = pSubSup->GetSubSup(eSubSup); + SmNodeList* pScriptLineList = NodeToList(pScriptLine); + + //Add selection to pScriptLineList + unsigned int nOldSize = pScriptLineList->size(); + pScriptLineList->insert(pScriptLineList->end(), pSelectedNodesList->begin(), pSelectedNodesList->end()); + delete pSelectedNodesList; + pSelectedNodesList = NULL; + + //Patch pScriptLineList if needed + if(0 < nOldSize && nOldSize < pScriptLineList->size()) { + SmNodeList::iterator iPatchPoint = pScriptLineList->begin(); + std::advance(iPatchPoint, nOldSize); + PatchLineList(pScriptLineList, iPatchPoint); + } + + //Find caret pos, that should be used after sub-/superscription. + SmCaretPos PosAfterScript; //Leave invalid for first position + if(pScriptLineList->size() > 0) + PosAfterScript = SmCaretPos::GetPosAfter(pScriptLineList->back()); + + //Parse pScriptLineList + pScriptLine = SmNodeListParser().Parse(pScriptLineList); + delete pScriptLineList; + pScriptLineList = NULL; + + //Insert pScriptLine back into the tree + pSubSup->SetSubSup(eSubSup, pScriptLine); + + //Finish editing + FinishEdit(pLineList, pLineParent, nParentIndex, PosAfterScript, pScriptLine); +} + +bool SmCursor::InsertLimit(SmSubSup eSubSup, bool bMoveCaret) { + //Find a subject to set limits on + SmOperNode *pSubject = NULL; + //Check if pSelectedNode might be a subject + if(position->CaretPos.pSelectedNode->GetType() == NOPER) + pSubject = (SmOperNode*)position->CaretPos.pSelectedNode; + else { + //If not, check if parent of the current line is a SmOperNode + SmNode *pLineNode = FindTopMostNodeInLine(position->CaretPos.pSelectedNode, sal_False); + if(pLineNode->GetParent() && pLineNode->GetParent()->GetType() == NOPER) + pSubject = (SmOperNode*)pLineNode->GetParent(); + } + + //Abort operation if we're not in the appropriate context + if(!pSubject) + return false; + + BeginEdit(); + + //Find the sub sup node + SmSubSupNode *pSubSup = NULL; + //Check if there's already one there... + if(pSubject->GetSubNode(0)->GetType() == NSUBSUP) + pSubSup = (SmSubSupNode*)pSubject->GetSubNode(0); + else { //if not create a new SmSubSupNode + SmToken token; + token.nGroup = TGLIMIT; + pSubSup = new SmSubSupNode(token); + //Set it's body + pSubSup->SetBody(pSubject->GetSubNode(0)); + //Replace the operation of the SmOperNode + pSubject->SetSubNode(0, pSubSup); + } + + //Create the limit, if needed + SmCaretPos PosAfterLimit; + SmNode *pLine = NULL; + if(!pSubSup->GetSubSup(eSubSup)){ + pLine = new SmPlaceNode(); + pSubSup->SetSubSup(eSubSup, pLine); + PosAfterLimit = SmCaretPos(pLine, 1); + //If it's already there... let's move the caret + } else if(bMoveCaret){ + pLine = pSubSup->GetSubSup(eSubSup); + SmNodeList* pLineList = NodeToList(pLine); + if(pLineList->size() > 0) + PosAfterLimit = SmCaretPos::GetPosAfter(pLineList->back()); + pLine = SmNodeListParser().Parse(pLineList); + delete pLineList; + pSubSup->SetSubSup(eSubSup, pLine); + } + + //Rebuild graph of caret positions + BuildGraph(); + AnnotateSelection(); + + //Set caret position + if(bMoveCaret) + if(!SetCaretPosition(PosAfterLimit, true)) + SetCaretPosition(SmCaretPos(pLine, 0), true); + + EndEdit(); + + return true; +} + +void SmCursor::InsertBrackets(SmBracketType eBracketType) { + BeginEdit(); + + AnnotateSelection(); + + //Find line + SmNode *pLine; + if(HasSelection()) { + SmNode *pSNode = FindSelectedNode(pTree); + OSL_ENSURE(pSNode != NULL, "There must be a selected node if HasSelection()"); + pLine = FindTopMostNodeInLine(pSNode, sal_True); + } else + pLine = FindTopMostNodeInLine(position->CaretPos.pSelectedNode, sal_False); + + //Find parent and offset in parent + SmStructureNode *pLineParent = pLine->GetParent(); + int nParentIndex = pLineParent->IndexOfSubNode(pLine); + OSL_ENSURE( nParentIndex != -1, "pLine must be a subnode of pLineParent!"); + + //Convert line to list + SmNodeList *pLineList = NodeToList(pLine); + + //Take the selection, and/or find iterator for current position + SmNodeList *pSelectedNodesList = new SmNodeList(); + SmNodeList::iterator it; + if(HasSelection()) + it = TakeSelectedNodesFromList(pLineList, pSelectedNodesList); + else + it = FindPositionInLineList(pLineList, position->CaretPos); + + //If there's no selected nodes, create a place node + SmCaretPos PosAfterInsert; + if(pSelectedNodesList->size() == 0) { + SmNode* pPlace = new SmPlaceNode(); + PosAfterInsert = SmCaretPos(pPlace, 1); + pSelectedNodesList->push_front(pPlace); + } + + //Parse body nodes + SmNode *pBodyNode = SmNodeListParser().Parse(pSelectedNodesList); + delete pSelectedNodesList; + + //Create SmBraceNode + SmToken aTok(TLEFT, '\0', "left", 0, 5); + SmBraceNode *pBrace = new SmBraceNode(aTok); + pBrace->SetScaleMode(SCALE_HEIGHT); + SmNode *pLeft = CreateBracket(eBracketType, true), + *pRight = CreateBracket(eBracketType, false); + SmBracebodyNode *pBody = new SmBracebodyNode(SmToken()); + pBody->SetSubNodes(pBodyNode, NULL); + pBrace->SetSubNodes(pLeft, pBody, pRight); + pBrace->Prepare(pDocShell->GetFormat(), *pDocShell); + + //Insert into line + pLineList->insert(it, pBrace); + //Patch line (I think this is good enough) + SmCaretPos pAfter = PatchLineList(pLineList, it); + if( !PosAfterInsert.IsValid() ) + PosAfterInsert = pAfter; + + //Finish editing + FinishEdit(pLineList, pLineParent, nParentIndex, PosAfterInsert); +} + +SmNode *SmCursor::CreateBracket(SmBracketType eBracketType, bool bIsLeft) { + SmToken aTok; + if(bIsLeft){ + switch(eBracketType){ + case NoneBrackets: + aTok = SmToken(TNONE, '\0', "none", TGLBRACES | TGRBRACES, 0); + break; + case RoundBrackets: + aTok = SmToken(TLPARENT, MS_LPARENT, "(", TGLBRACES, 5); + break; + case SquareBrackets: + aTok = SmToken(TLBRACKET, MS_LBRACKET, "[", TGLBRACES, 5); + break; + case DoubleSquareBrackets: + aTok = SmToken(TLDBRACKET, MS_LDBRACKET, "ldbracket", TGLBRACES, 5); + break; + case LineBrackets: + aTok = SmToken(TLLINE, MS_LINE, "lline", TGLBRACES, 5); + break; + case DoubleLineBrackets: + aTok = SmToken(TLDLINE, MS_DLINE, "ldline", TGLBRACES, 5); + break; + case CurlyBrackets: + aTok = SmToken(TLBRACE, MS_LBRACE, "lbrace", TGLBRACES, 5); + break; + case AngleBrackets: + aTok = SmToken(TLANGLE, MS_LANGLE, "langle", TGLBRACES, 5); + break; + case CeilBrackets: + aTok = SmToken(TLCEIL, MS_LCEIL, "lceil", TGLBRACES, 5); + break; + case FloorBrackets: + aTok = SmToken(TLFLOOR, MS_LFLOOR, "lfloor", TGLBRACES, 5); + break; + } + } else { + switch(eBracketType) { + case NoneBrackets: + aTok = SmToken(TNONE, '\0', "none", TGLBRACES | TGRBRACES, 0); + break; + case RoundBrackets: + aTok = SmToken(TRPARENT, MS_RPARENT, ")", TGRBRACES, 5); + break; + case SquareBrackets: + aTok = SmToken(TRBRACKET, MS_RBRACKET, "]", TGRBRACES, 5); + break; + case DoubleSquareBrackets: + aTok = SmToken(TRDBRACKET, MS_RDBRACKET, "rdbracket", TGRBRACES, 5); + break; + case LineBrackets: + aTok = SmToken(TRLINE, MS_LINE, "rline", TGRBRACES, 5); + break; + case DoubleLineBrackets: + aTok = SmToken(TRDLINE, MS_DLINE, "rdline", TGRBRACES, 5); + break; + case CurlyBrackets: + aTok = SmToken(TRBRACE, MS_RBRACE, "rbrace", TGRBRACES, 5); + break; + case AngleBrackets: + aTok = SmToken(TRANGLE, MS_RANGLE, "rangle", TGRBRACES, 5); + break; + case CeilBrackets: + aTok = SmToken(TRCEIL, MS_RCEIL, "rceil", TGRBRACES, 5); + break; + case FloorBrackets: + aTok = SmToken(TRFLOOR, MS_RFLOOR, "rfloor", TGRBRACES, 5); + break; + } + } + SmNode* pRetVal = new SmMathSymbolNode(aTok); + pRetVal->SetScaleMode(SCALE_HEIGHT); + return pRetVal; +} + +bool SmCursor::InsertRow() { + AnnotateSelection(); + + //Find line + SmNode *pLine; + if(HasSelection()) { + SmNode *pSNode = FindSelectedNode(pTree); + OSL_ENSURE(pSNode != NULL, "There must be a selected node if HasSelection()"); + pLine = FindTopMostNodeInLine(pSNode, sal_True); + } else + pLine = FindTopMostNodeInLine(position->CaretPos.pSelectedNode, sal_False); + + //Find parent and offset in parent + SmStructureNode *pLineParent = pLine->GetParent(); + int nParentIndex = pLineParent->IndexOfSubNode(pLine); + OSL_ENSURE( nParentIndex != -1, "pLine must be a subnode of pLineParent!"); + + //Discover the context of this command + SmTableNode *pTable = NULL; + SmMatrixNode *pMatrix = NULL; + int nTableIndex = nParentIndex; + if(pLineParent->GetType() == NTABLE) + pTable = (SmTableNode*)pLineParent; + //If it's warped in a SmLineNode, we can still insert a newline + else if(pLineParent->GetType() == NLINE && + pLineParent->GetParent() && + pLineParent->GetParent()->GetType() == NTABLE) { + //NOTE: This hack might give problems if we stop ignoring SmAlignNode + pTable = (SmTableNode*)pLineParent->GetParent(); + nTableIndex = pTable->IndexOfSubNode(pLineParent); + OSL_ENSURE(nTableIndex != -1, "pLineParent must be a child of its parent!"); + } + if(pLineParent->GetType() == NMATRIX) + pMatrix = (SmMatrixNode*)pLineParent; + + //If we're not in a context that supports InsertRow, return sal_False + if(!pTable && !pMatrix) + return false; + + //Now we start editing + BeginEdit(); + + //Convert line to list + SmNodeList *pLineList = NodeToList(pLine); + + //Find position in line + SmNodeList::iterator it; + if(HasSelection()) { + //Take the selected nodes and delete them... + it = TakeSelectedNodesFromList(pLineList); + } else + it = FindPositionInLineList(pLineList, position->CaretPos); + + //New caret position after inserting the newline/row in whatever context + SmCaretPos PosAfterInsert; + + //If we're in the context of a table + if(pTable) { + SmNodeList *pNewLineList = new SmNodeList(); + //Move elements from pLineList to pNewLineList + pNewLineList->splice(pNewLineList->begin(), *pLineList, it, pLineList->end()); + //Make sure it is valid again + it = pLineList->end(); + if(it != pLineList->begin()) + --it; + if(pNewLineList->size() == 0) + pNewLineList->push_front(new SmPlaceNode()); + //Parse new line + SmNode *pNewLine = SmNodeListParser().Parse(pNewLineList); + delete pNewLineList; + //Wrap pNewLine in SmLineNode if needed + if(pLineParent->GetType() == NLINE) { + SmLineNode *pNewLineNode = new SmLineNode(SmToken(TNEWLINE, '\0', "newline")); + pNewLineNode->SetSubNodes(pNewLine, NULL); + pNewLine = pNewLineNode; + } + //Get position + PosAfterInsert = SmCaretPos(pNewLine, 0); + //Move other nodes if needed + for( int i = pTable->GetNumSubNodes(); i > nTableIndex + 1; i--) + pTable->SetSubNode(i, pTable->GetSubNode(i-1)); + + //Insert new line + pTable->SetSubNode(nTableIndex + 1, pNewLine); + + //Check if we need to change token type: + if(pTable->GetNumSubNodes() > 2 && pTable->GetToken().eType == TBINOM) { + SmToken tok = pTable->GetToken(); + tok.eType = TSTACK; + pTable->SetToken(tok); + } + } + //If we're in the context of a matrix + else if(pMatrix) { + //Find position after insert and patch the list + PosAfterInsert = PatchLineList(pLineList, it); + //Move other children + sal_uInt16 rows = pMatrix->GetNumRows(); + sal_uInt16 cols = pMatrix->GetNumCols(); + int nRowStart = (nParentIndex - nParentIndex % cols) + cols; + for( int i = pMatrix->GetNumSubNodes() + cols - 1; i >= nRowStart + cols; i--) + pMatrix->SetSubNode(i, pMatrix->GetSubNode(i - cols)); + for( int i = nRowStart; i < nRowStart + cols; i++) { + SmPlaceNode *pNewLine = new SmPlaceNode(); + if(i == nParentIndex + cols) + PosAfterInsert = SmCaretPos(pNewLine, 0); + pMatrix->SetSubNode(i, pNewLine); + } + pMatrix->SetRowCol(rows + 1, cols); + } else + OSL_FAIL("We must be either the context of a table or matrix!"); + + //Finish editing + FinishEdit(pLineList, pLineParent, nParentIndex, PosAfterInsert); + //FinishEdit is actually used to handle siturations where parent is an instance of + //SmSubSupNode. In this case parent should always be a table or matrix, however, for + //code reuse we just use FinishEdit() here too. + return true; +} + +void SmCursor::InsertFraction() { + AnnotateSelection(); + + //Find line + SmNode *pLine; + if(HasSelection()) { + SmNode *pSNode = FindSelectedNode(pTree); + OSL_ENSURE(pSNode != NULL, "There must be a selected node when HasSelection is true!"); + pLine = FindTopMostNodeInLine(pSNode, sal_True); + } else + pLine = FindTopMostNodeInLine(position->CaretPos.pSelectedNode, sal_False); + + //Find Parent and offset in parent + SmStructureNode *pLineParent = pLine->GetParent(); + int nParentIndex = pLineParent->IndexOfSubNode(pLine); + OSL_ENSURE(nParentIndex != -1, "pLine must be a subnode of pLineParent!"); + + //We begin modifying the tree here + BeginEdit(); + + //Convert line to list + SmNodeList* pLineList = NodeToList(pLine); + + //Take the selection, and/or find iterator for current position + SmNodeList* pSelectedNodesList = new SmNodeList(); + SmNodeList::iterator it; + if(HasSelection()) + it = TakeSelectedNodesFromList(pLineList, pSelectedNodesList); + else + it = FindPositionInLineList(pLineList, position->CaretPos); + + //Create pNum, and pDenom + if(pSelectedNodesList->size() == 0) + pSelectedNodesList->push_front(new SmPlaceNode()); + SmNode *pNum = SmNodeListParser().Parse(pSelectedNodesList), + *pDenom = new SmPlaceNode(); + delete pSelectedNodesList; + pSelectedNodesList = NULL; + + //Create new fraction + SmBinVerNode *pFrac = new SmBinVerNode(SmToken(TOVER, '\0', "over", TGPRODUCT, 0)); + SmNode *pRect = new SmRectangleNode(SmToken()); + pFrac->SetSubNodes(pNum, pRect, pDenom); + + //Insert in pLineList + SmNodeList::iterator patchIt = pLineList->insert(it, pFrac); + PatchLineList(pLineList, patchIt); + PatchLineList(pLineList, it); + + //Finish editing + FinishEdit(pLineList, pLineParent, nParentIndex, SmCaretPos(pDenom, 1)); +} + +void SmCursor::InsertText(XubString aString){ + BeginEdit(); + + Delete(); + + SmToken token; + token.eType = TIDENT; + token.cMathChar = '\0'; + token.nGroup = 0; + token.nLevel = 5; + token.aText = aString; + + SmTextNode* pText = new SmTextNode(token, FNT_VARIABLE); + + //Prepare the new node + pText->Prepare(pDocShell->GetFormat(), *pDocShell); + pText->AdjustFontDesc(); + + SmNodeList* pList = new SmNodeList(); + pList->push_front(pText); + InsertNodes(pList); + + EndEdit(); +} + +void SmCursor::InsertElement(SmFormulaElement element){ + BeginEdit(); + + Delete(); + + //Create new node + SmNode* pNewNode = NULL; + switch(element){ + case BlankElement: + { + SmToken token; + token.nGroup = TGBLANK; + token.aText.AssignAscii("~"); + pNewNode = new SmBlankNode(token); + }break; + case FactorialElement: + { + SmToken token(TFACT, MS_FACT, "fact", TGUNOPER, 5); + pNewNode = new SmMathSymbolNode(token); + }break; + case PlusElement: + { + SmToken token; + token.eType = TPLUS; + token.cMathChar = MS_PLUS; + token.nGroup = TGUNOPER | TGSUM; + token.nLevel = 5; + token.aText.AssignAscii("+"); + pNewNode = new SmMathSymbolNode(token); + }break; + case MinusElement: + { + SmToken token; + token.eType = TMINUS; + token.cMathChar = MS_MINUS; + token.nGroup = MS_PLUS; + token.nLevel = 5; + token.aText.AssignAscii("-"); + pNewNode = new SmMathSymbolNode(token); + }break; + case CDotElement: + { + SmToken token; + token.eType = TCDOT; + token.cMathChar = MS_CDOT; + token.nGroup = TGPRODUCT; + token.aText.AssignAscii("cdot"); + pNewNode = new SmMathSymbolNode(token); + }break; + case EqualElement: + { + SmToken token; + token.eType = TASSIGN; + token.cMathChar = MS_ASSIGN; + token.nGroup = TGRELATION; + token.aText.AssignAscii("="); + pNewNode = new SmMathSymbolNode(token); + }break; + case LessThanElement: + { + SmToken token; + token.eType = TLT; + token.cMathChar = MS_LT; + token.nGroup = TGRELATION; + token.aText.AssignAscii("<"); + pNewNode = new SmMathSymbolNode(token); + }break; + case GreaterThanElement: + { + SmToken token; + token.eType = TGT; + token.cMathChar = MS_GT; + token.nGroup = TGRELATION; + token.aText.AssignAscii(">"); + pNewNode = new SmMathSymbolNode(token); + }break; + case PercentElement: + { + SmToken token; + token.eType = TTEXT; + token.cMathChar = MS_PERCENT; + token.nGroup = 0; + token.aText.AssignAscii("\"%\""); + pNewNode = new SmMathSymbolNode(token); + }break; + default: + OSL_FAIL("Element unknown!"); + } + OSL_ENSURE(pNewNode != NULL, "No new node was created!"); + if(!pNewNode) + return; + + //Prepare the new node + pNewNode->Prepare(pDocShell->GetFormat(), *pDocShell); + + //Insert new node + SmNodeList* pList = new SmNodeList(); + pList->push_front(pNewNode); + InsertNodes(pList); + + EndEdit(); +} + +void SmCursor::InsertSpecial(XubString aString) { + BeginEdit(); + Delete(); + + aString.EraseLeadingAndTrailingChars(); + aString.EraseLeadingChars('%'); + + //Create instance of special node + SmToken token; + token.eType = TSPECIAL; + token.cMathChar = '\0'; + token.nGroup = 0; + token.nLevel = 5; + token.aText = aString; //Don't know if leading "%" should be removed + SmSpecialNode* pSpecial = new SmSpecialNode(token); + + //Prepare the special node + pSpecial->Prepare(pDocShell->GetFormat(), *pDocShell); + + //Insert the node + SmNodeList* pList = new SmNodeList(); + pList->push_front(pSpecial); + InsertNodes(pList); + + EndEdit(); +} + +void SmCursor::InsertCommand(sal_uInt16 nCommand) { + switch(nCommand){ + case RID_NEWLINE: + InsertRow(); + break; + case RID_FROMX: + InsertLimit(CSUB, true); + break; + case RID_TOX: + InsertLimit(CSUP, true); + break; + case RID_FROMXTOY: + if(InsertLimit(CSUB, true)) + InsertLimit(CSUP, true); + break; + default: + InsertCommandText(SmResId(nCommand)); + break; + } +} + +void SmCursor::InsertCommandText(XubString aCommandText) { + //Parse the the sub expression + SmNode* pSubExpr = SmParser().ParseExpression(aCommandText); + + //Prepare the subtree + pSubExpr->Prepare(pDocShell->GetFormat(), *pDocShell); + + //Convert subtree to list + SmNodeList* pLineList = NodeToList(pSubExpr); + + BeginEdit(); + + //Delete any selection + Delete(); + + //Insert it + InsertNodes(pLineList); + + EndEdit(); +} + +void SmCursor::Copy(){ + if(!HasSelection()) + return; + + //Find selected node + SmNode* pSNode = FindSelectedNode(pTree); + //Find visual line + SmNode* pLine = FindTopMostNodeInLine(pSNode, true); + + //Clone selected nodes + SmNodeList* pList; + if(IsLineCompositionNode(pLine)) + pList = CloneLineToList((SmStructureNode*)pLine, true); + else{ + pList = new SmNodeList(); + //Special care to only clone selected text + if(pLine->GetType() == NTEXT) { + SmTextNode *pText = (SmTextNode*)pLine; + SmTextNode *pClone = new SmTextNode( pText->GetToken(), pText->GetFontDesc() ); + int start = pText->GetSelectionStart(), + length = pText->GetSelectionEnd() - pText->GetSelectionStart(); + pClone->ChangeText(pText->GetText().Copy(start, length)); + pClone->SetScaleMode(pText->GetScaleMode()); + pList->push_front(pClone); + } else { + SmCloningVisitor aCloneFactory; + pList->push_front(aCloneFactory.Clone(pLine)); + } + } + + //Set clipboard + if(pList->size() > 0) + SetClipboard(pList); +} + +void SmCursor::Paste() { + BeginEdit(); + Delete(); + + if(pClipboard && pClipboard->size() > 0) + InsertNodes(CloneList(pClipboard)); + + EndEdit(); +} + +SmNodeList* SmCursor::CloneList(SmNodeList* pList){ + SmCloningVisitor aCloneFactory; + SmNodeList* pClones = new SmNodeList(); + + SmNodeList::iterator it; + for(it = pList->begin(); it != pList->end(); ++it){ + SmNode *pClone = aCloneFactory.Clone(*it); + pClones->push_back(pClone); + } + + return pClones; +} + +void SmCursor::SetClipboard(SmNodeList* pList){ + if(pClipboard){ + //Delete all nodes on the clipboard + SmNodeList::iterator it; + for(it = pClipboard->begin(); it != pClipboard->end(); ++it) + delete (*it); + delete pClipboard; + } + pClipboard = pList; +} + +SmNode* SmCursor::FindTopMostNodeInLine(SmNode* pSNode, bool MoveUpIfSelected){ + //If we haven't got a subnode + if(!pSNode) + return NULL; + + //Move up parent untill we find a node who's + //parent is NULL or isn't selected and not a type of: + // SmExpressionNode + // SmLineNode + // SmBinHorNode + // SmUnHorNode + // SmAlignNode + // SmFontNode + while(pSNode->GetParent() && + ((MoveUpIfSelected && + pSNode->GetParent()->IsSelected()) || + IsLineCompositionNode(pSNode->GetParent()))) + pSNode = pSNode->GetParent(); + //Now we have the selection line node + return pSNode; +} + +SmNode* SmCursor::FindSelectedNode(SmNode* pNode){ + SmNodeIterator it(pNode); + while(it.Next()){ + if(it->IsSelected()) + return it.Current(); + SmNode* pRetVal = FindSelectedNode(it.Current()); + if(pRetVal) + return pRetVal; + } + return NULL; +} + +SmNodeList* SmCursor::LineToList(SmStructureNode* pLine, SmNodeList* list){ + SmNodeIterator it(pLine); + while(it.Next()){ + switch(it->GetType()){ + case NLINE: + case NUNHOR: + case NEXPRESSION: + case NBINHOR: + case NALIGN: + case NFONT: + LineToList((SmStructureNode*)it.Current(), list); + break; + case NERROR: + delete it.Current(); + break; + default: + list->push_back(it.Current()); + } + } + SmNodeArray emptyArray(0); + pLine->SetSubNodes(emptyArray); + delete pLine; + return list; +} + +SmNodeList* SmCursor::CloneLineToList(SmStructureNode* pLine, bool bOnlyIfSelected, SmNodeList* pList){ + SmCloningVisitor aCloneFactory; + SmNodeIterator it(pLine); + while(it.Next()){ + if( IsLineCompositionNode( it.Current() ) ) + CloneLineToList( (SmStructureNode*)it.Current(), bOnlyIfSelected, pList ); + else if( (!bOnlyIfSelected || it->IsSelected()) && it->GetType() != NERROR ) { + //Only clone selected text from SmTextNode + if(it->GetType() == NTEXT) { + SmTextNode *pText = (SmTextNode*)it.Current(); + SmTextNode *pClone = new SmTextNode( it->GetToken(), pText->GetFontDesc() ); + int start = pText->GetSelectionStart(), + length = pText->GetSelectionEnd() - pText->GetSelectionStart(); + pClone->ChangeText(pText->GetText().Copy(start, length)); + pClone->SetScaleMode(pText->GetScaleMode()); + pList->push_back(pClone); + } else + pList->push_back(aCloneFactory.Clone(it.Current())); + } + } + return pList; +} + +bool SmCursor::IsLineCompositionNode(SmNode* pNode){ + switch(pNode->GetType()){ + case NLINE: + case NUNHOR: + case NEXPRESSION: + case NBINHOR: + case NALIGN: + case NFONT: + return true; + default: + return false; + } + return false; +} + +int SmCursor::CountSelectedNodes(SmNode* pNode){ + int nCount = 0; + SmNodeIterator it(pNode); + while(it.Next()){ + if(it->IsSelected() && !IsLineCompositionNode(it.Current())) + nCount++; + nCount += CountSelectedNodes(it.Current()); + } + return nCount; +} + +bool SmCursor::HasComplexSelection(){ + if(!HasSelection()) + return false; + AnnotateSelection(); + + return CountSelectedNodes(pTree) > 1; +} + +void SmCursor::FinishEdit(SmNodeList* pLineList, + SmStructureNode* pParent, + int nParentIndex, + SmCaretPos PosAfterEdit, + SmNode* pStartLine) { + //Store number of nodes in line for later + int entries = pLineList->size(); + + //Parse list of nodes to a tree + SmNodeListParser parser; + SmNode* pLine = parser.Parse(pLineList); + delete pLineList; + + //Check if we're making the body of a subsup node bigger than one + if(pParent->GetType() == NSUBSUP && + nParentIndex == 0 && + entries > 1) { + //Wrap pLine in scalable round brackets + SmToken aTok(TLEFT, '\0', "left", 0, 5); + SmBraceNode *pBrace = new SmBraceNode(aTok); + pBrace->SetScaleMode(SCALE_HEIGHT); + SmNode *pLeft = CreateBracket(RoundBrackets, true), + *pRight = CreateBracket(RoundBrackets, false); + SmBracebodyNode *pBody = new SmBracebodyNode(SmToken()); + pBody->SetSubNodes(pLine, NULL); + pBrace->SetSubNodes(pLeft, pBody, pRight); + pBrace->Prepare(pDocShell->GetFormat(), *pDocShell); + pLine = pBrace; + //TODO: Consider the following alternative behavior: + //Consider the line: A + {B + C}^D lsub E + //Here pLineList is B, + and C and pParent is a subsup node with + //both RSUP and LSUB set. Imagine the user just inserted "B +" in + //the body of the subsup node... + //The most natural thing to do would be to make the line like this: + //A + B lsub E + C ^ D + //E.g. apply LSUB and LSUP to the first element in pLineList and RSUP + //and RSUB to the last eleent in pLineList. But how should this act + //for CSUP and CSUB ??? + //For this reason and because brackets was faster to implement, this solution + //have been choosen. It might be worth working on the other solution later... + } + + //Set pStartLine if NULL + if(!pStartLine) + pStartLine = pLine; + + //Insert it back into the parent + pParent->SetSubNode(nParentIndex, pLine); + + //Rebuild graph of caret position + anchor = NULL; + position = NULL; + BuildGraph(); + AnnotateSelection(); //Update selection annotation! + + //Set caret position + if(!SetCaretPosition(PosAfterEdit, true)) + SetCaretPosition(SmCaretPos(pStartLine, 0), true); + + //End edit section + EndEdit(); +} + +void SmCursor::BeginEdit(){ + if(nEditSections++ > 0) return; + + bIsEnabledSetModifiedSmDocShell = pDocShell->IsEnableSetModified(); + if( bIsEnabledSetModifiedSmDocShell ) + pDocShell->EnableSetModified( sal_False ); +} + +void SmCursor::EndEdit(){ + if(--nEditSections > 0) return; + + pDocShell->SetFormulaArranged(sal_False); + //Okay, I don't know what this does... :) + //It's used in SmDocShell::SetText and with places where everything is modified. + //I think it does some magic, with sfx, but everything is totally undocumented so + //it's kinda hard to tell... + if ( bIsEnabledSetModifiedSmDocShell ) + pDocShell->EnableSetModified( bIsEnabledSetModifiedSmDocShell ); + //I think this notifies people around us that we've modified this document... + pDocShell->SetModified(sal_True); + //I think SmDocShell uses this value when it sends an update graphics event + //Anyway comments elsewhere suggests it need to be updated... + pDocShell->nModifyCount++; + + //TODO: Consider copying the update accessability code from SmDocShell::SetText in here... + //This somehow updates the size of SmGraphicView if it is running in embedded mode + if( pDocShell->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + pDocShell->OnDocumentPrinterChanged(0); + + //Request a replaint... + RequestRepaint(); + + //Update the edit engine and text of the document + String formula; + SmNodeToTextVisitor(pTree, formula); + //pTree->CreateTextFromNode(formula); + pDocShell->aText = formula; + pDocShell->GetEditEngine().QuickInsertText( formula, ESelection( 0, 0, EE_PARA_ALL, EE_PARA_ALL ) ); + pDocShell->GetEditEngine().QuickFormatDoc(); +} + +void SmCursor::RequestRepaint(){ + SmViewShell *pViewSh = SmGetActiveView(); + if( pViewSh ) { + if ( SFX_CREATE_MODE_EMBEDDED == pDocShell->GetCreateMode() ) + pDocShell->Repaint(); + else + pViewSh->GetGraphicWindow().Invalidate(); + } +} + +/////////////////////////////////////// SmNodeListParser /////////////////////////////////////// + +SmNode* SmNodeListParser::Parse(SmNodeList* list, bool bDeleteErrorNodes){ + pList = list; + if(bDeleteErrorNodes){ + //Delete error nodes + SmNodeList::iterator it = pList->begin(); + while(it != pList->end()) { + if((*it)->GetType() == NERROR){ + //Delete and erase + delete *it; + it = pList->erase(it); + }else + ++it; + } + } + SmNode* retval = Expression(); + pList = NULL; + return retval; +} + +SmNode* SmNodeListParser::Expression(){ + SmNodeArray NodeArray; + //Accept as many relations as there is + while(Terminal()) + NodeArray.push_back(Relation()); + + //Create SmExpressionNode, I hope SmToken() will do :) + SmStructureNode* pExpr = new SmExpressionNode(SmToken()); + pExpr->SetSubNodes(NodeArray); + return pExpr; +} + +SmNode* SmNodeListParser::Relation(){ + //Read a sum + SmNode* pLeft = Sum(); + //While we have tokens and the next is a relation + while(Terminal() && IsRelationOperator(Terminal()->GetToken())){ + //Take the operator + SmNode* pOper = Take(); + //Find the right side of the relation + SmNode* pRight = Sum(); + //Create new SmBinHorNode + SmStructureNode* pNewNode = new SmBinHorNode(SmToken()); + pNewNode->SetSubNodes(pLeft, pOper, pRight); + pLeft = pNewNode; + } + return pLeft; +} + +SmNode* SmNodeListParser::Sum(){ + //Read a product + SmNode* pLeft = Product(); + //While we have tokens and the next is a sum + while(Terminal() && IsSumOperator(Terminal()->GetToken())){ + //Take the operator + SmNode* pOper = Take(); + //Find the right side of the sum + SmNode* pRight = Product(); + //Create new SmBinHorNode + SmStructureNode* pNewNode = new SmBinHorNode(SmToken()); + pNewNode->SetSubNodes(pLeft, pOper, pRight); + pLeft = pNewNode; + } + return pLeft; +} + +SmNode* SmNodeListParser::Product(){ + //Read a Factor + SmNode* pLeft = Factor(); + //While we have tokens and the next is a product + while(Terminal() && IsProductOperator(Terminal()->GetToken())){ + //Take the operator + SmNode* pOper = Take(); + //Find the right side of the operation + SmNode* pRight = Factor(); + //Create new SmBinHorNode + SmStructureNode* pNewNode = new SmBinHorNode(SmToken()); + pNewNode->SetSubNodes(pLeft, pOper, pRight); + pLeft = pNewNode; + } + return pLeft; +} + +SmNode* SmNodeListParser::Factor(){ + //Read unary operations + if(!Terminal()) + return Error(); + //Take care of unary operators + else if(IsUnaryOperator(Terminal()->GetToken())) + { + SmStructureNode *pUnary = new SmUnHorNode(SmToken()); + SmNode *pOper = Terminal(), + *pArg; + + if(Next()) + pArg = Factor(); + else + pArg = Error(); + + pUnary->SetSubNodes(pOper, pArg); + return pUnary; + } + return Postfix(); +} + +SmNode* SmNodeListParser::Postfix(){ + if(!Terminal()) + return Error(); + SmNode *pArg = NULL; + if(IsPostfixOperator(Terminal()->GetToken())) + pArg = Error(); + else if(IsOperator(Terminal()->GetToken())) + return Error(); + else + pArg = Take(); + while(Terminal() && IsPostfixOperator(Terminal()->GetToken())) { + SmStructureNode *pUnary = new SmUnHorNode(SmToken()); + SmNode *pOper = Take(); + pUnary->SetSubNodes(pArg, pOper); + pArg = pUnary; + } + return pArg; +} + +SmNode* SmNodeListParser::Error(){ + return new SmErrorNode(PE_UNEXPECTED_TOKEN, SmToken()); +} + +bool SmNodeListParser::IsOperator(const SmToken &token) { + return IsRelationOperator(token) || + IsSumOperator(token) || + IsProductOperator(token) || + IsUnaryOperator(token) || + IsPostfixOperator(token); +} + +bool SmNodeListParser::IsRelationOperator(const SmToken &token) { + return token.nGroup & TGRELATION; +} + +bool SmNodeListParser::IsSumOperator(const SmToken &token) { + return token.nGroup & TGSUM; +} + +bool SmNodeListParser::IsProductOperator(const SmToken &token) { + return token.nGroup & TGPRODUCT && + token.eType != TWIDESLASH && + token.eType != TWIDEBACKSLASH && + token.eType != TUNDERBRACE && + token.eType != TOVERBRACE && + token.eType != TOVER; +} + +bool SmNodeListParser::IsUnaryOperator(const SmToken &token) { + return token.nGroup & TGUNOPER && + (token.eType == TPLUS || + token.eType == TMINUS || + token.eType == TPLUSMINUS || + token.eType == TMINUSPLUS || + token.eType == TNEG || + token.eType == TUOPER); +} + +bool SmNodeListParser::IsPostfixOperator(const SmToken &token) { + return token.eType == TFACT; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/detreg.cxx b/starmath/source/detreg.cxx new file mode 100644 index 000000000000..be0fe1135d49 --- /dev/null +++ b/starmath/source/detreg.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/uno/Sequence.h> +#include <rtl/ustring.hxx> + +#include "smdetect.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +extern "C" { + +SAL_DLLPUBLIC_EXPORT void* SAL_CALL smd_component_getFactory( const sal_Char* pImplementationName, + void* pServiceManager, + void* /*pRegistryKey*/ ) +{ + // Set default return value for this operation - if it failed. + void* pReturn = NULL ; + + if ( + ( pImplementationName != NULL ) && + ( pServiceManager != NULL ) + ) + { + // Define variables which are used in following macros. + Reference< XSingleServiceFactory > xFactory ; + Reference< XMultiServiceFactory > xServiceManager( reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + + if( SmFilterDetect::impl_getStaticImplementationName().equalsAscii( pImplementationName ) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmFilterDetect::impl_getStaticImplementationName(), + SmFilterDetect::impl_createInstance, + SmFilterDetect::impl_getStaticSupportedServiceNames() ); + } + + // Factory is valid - service was found. + if ( xFactory.is() ) + { + xFactory->acquire(); + pReturn = xFactory.get(); + } + } + + // Return with result of this operation. + return pReturn ; +} +} // extern "C" + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/dialog.cxx b/starmath/source/dialog.cxx new file mode 100644 index 000000000000..0daecc2054dd --- /dev/null +++ b/starmath/source/dialog.cxx @@ -0,0 +1,2441 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#define SMDLL 1 +#include "tools/rcid.h" +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <sfx2/app.hxx> +#include <vcl/msgbox.hxx> +#include <svtools/ctrltool.hxx> +#include <sfx2/printer.hxx> +#include <vcl/sound.hxx> +#include <vcl/sndstyle.hxx> +#include <vcl/waitobj.hxx> +#include <vcl/settings.hxx> +#include <vcl/wall.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/sfx.hrc> +#include <tools/string.hxx> +#include <osl/diagnose.h> +#include <svx/ucsubset.hxx> + + +#include "dialog.hxx" +#include "starmath.hrc" +#include "config.hxx" +#include "dialog.hrc" +#include "smmod.hxx" +#include "symbol.hxx" +#include "view.hxx" +#include "document.hxx" +#include "unomodel.hxx" + + +using ::rtl::OUString; + +//////////////////////////////////////// +// +// Da der FontStyle besser ueber die Attribute gesetzt/abgefragt wird als ueber +// den StyleName bauen wir uns hier unsere eigene Uebersetzung +// Attribute <-> StyleName +// + +class SmFontStyles +{ + String aNormal; + String aBold; + String aItalic; + String aBoldItalic; + String aEmpty; + +public: + SmFontStyles(); + + sal_uInt16 GetCount() const { return 4; } + const String & GetStyleName( const Font &rFont ) const; + const String & GetStyleName( sal_uInt16 nIdx ) const; +}; + + +SmFontStyles::SmFontStyles() : + aNormal ( ResId( RID_FONTREGULAR, *SM_MOD()->GetResMgr() ) ), + aBold ( ResId( RID_FONTBOLD, *SM_MOD()->GetResMgr() ) ), + aItalic ( ResId( RID_FONTITALIC, *SM_MOD()->GetResMgr() ) ) +{ + + aBoldItalic = aBold; + aBoldItalic.AppendAscii( ", " ); + aBoldItalic += aItalic; +} + + +const String & SmFontStyles::GetStyleName( const Font &rFont ) const +{ + //! compare also SmSpecialNode::Prepare + bool bBold = IsBold( rFont ), + bItalic = IsItalic( rFont ); + + if (bBold && bItalic) + return aBoldItalic; + else if (bItalic) + return aItalic; + else if (bBold) + return aBold; + else + return aNormal; +} + + +const String & SmFontStyles::GetStyleName( sal_uInt16 nIdx ) const +{ + // 0 = "normal", 1 = "italic", + // 2 = "bold", 3 = "bold italic" + +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE( nIdx < GetCount(), "index out of range" ); +#endif + switch (nIdx) + { + case 0 : return aNormal; + case 1 : return aItalic; + case 2 : return aBold; + case 3 : return aBoldItalic; + } + return aEmpty; +} + + +const SmFontStyles & GetFontStyles() +{ + static const SmFontStyles aImpl; + return aImpl; +} + +///////////////////////////////////////////////////////////////// + +void SetFontStyle(const XubString &rStyleName, Font &rFont) +{ + // finden des Index passend zum StyleName fuer den leeren StyleName wird + // 0 (nicht bold nicht italic) angenommen. + sal_uInt16 nIndex = 0; + if (rStyleName.Len()) + { + sal_uInt16 i; + const SmFontStyles &rStyles = GetFontStyles(); + for (i = 0; i < rStyles.GetCount(); i++) + if (rStyleName.CompareTo( rStyles.GetStyleName(i) ) == COMPARE_EQUAL) + break; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(i < rStyles.GetCount(), "style-name unknown"); +#endif + nIndex = i; + } + + rFont.SetItalic((nIndex & 0x1) ? ITALIC_NORMAL : ITALIC_NONE); + rFont.SetWeight((nIndex & 0x2) ? WEIGHT_BOLD : WEIGHT_NORMAL); +} + + +/**************************************************************************/ + +IMPL_LINK_INLINE_START( SmPrintOptionsTabPage, SizeButtonClickHdl, Button *, EMPTYARG/*pButton*/ ) +{ + aZoom.Enable(aSizeZoomed.IsChecked()); + return 0; +} +IMPL_LINK_INLINE_END( SmPrintOptionsTabPage, SizeButtonClickHdl, Button *, pButton ) + + +SmPrintOptionsTabPage::SmPrintOptionsTabPage(Window *pParent, const SfxItemSet &rOptions) + : SfxTabPage(pParent, SmResId(RID_PRINTOPTIONPAGE), rOptions), + aFixedLine1 (this, SmResId( FL_PRINTOPTIONS )), + aTitle (this, SmResId( CB_TITLEROW )), + aText (this, SmResId( CB_EQUATION_TEXT )), + aFrame (this, SmResId( CB_FRAME )), + aFixedLine2 (this, SmResId( FL_PRINT_FORMAT )), + aSizeNormal (this, SmResId( RB_ORIGINAL_SIZE )), + aSizeScaled (this, SmResId( RB_FIT_TO_PAGE )), + aSizeZoomed (this, SmResId( RB_ZOOM )), + aZoom (this, SmResId( MF_ZOOM )), + aFixedLine3 (this, SmResId( FL_MISC_OPTIONS )), + aNoRightSpaces (this, SmResId( CB_IGNORE_SPACING )), + aSaveOnlyUsedSymbols (this, SmResId( CB_SAVE_ONLY_USED_SYMBOLS )) +{ + FreeResource(); + + aSizeNormal.SetClickHdl(LINK(this, SmPrintOptionsTabPage, SizeButtonClickHdl)); + aSizeScaled.SetClickHdl(LINK(this, SmPrintOptionsTabPage, SizeButtonClickHdl)); + aSizeZoomed.SetClickHdl(LINK(this, SmPrintOptionsTabPage, SizeButtonClickHdl)); + + Reset(rOptions); +} + + +sal_Bool SmPrintOptionsTabPage::FillItemSet(SfxItemSet& rSet) +{ + sal_uInt16 nPrintSize; + if (aSizeNormal.IsChecked()) + nPrintSize = PRINT_SIZE_NORMAL; + else if (aSizeScaled.IsChecked()) + nPrintSize = PRINT_SIZE_SCALED; + else + nPrintSize = PRINT_SIZE_ZOOMED; + + rSet.Put(SfxUInt16Item(GetWhich(SID_PRINTSIZE), (sal_uInt16) nPrintSize)); + rSet.Put(SfxUInt16Item(GetWhich(SID_PRINTZOOM), (sal_uInt16) aZoom.GetValue())); + rSet.Put(SfxBoolItem(GetWhich(SID_PRINTTITLE), aTitle.IsChecked())); + rSet.Put(SfxBoolItem(GetWhich(SID_PRINTTEXT), aText.IsChecked())); + rSet.Put(SfxBoolItem(GetWhich(SID_PRINTFRAME), aFrame.IsChecked())); + rSet.Put(SfxBoolItem(GetWhich(SID_NO_RIGHT_SPACES), aNoRightSpaces.IsChecked())); + rSet.Put(SfxBoolItem(GetWhich(SID_SAVE_ONLY_USED_SYMBOLS), aSaveOnlyUsedSymbols.IsChecked())); + + return true; +} + + +void SmPrintOptionsTabPage::Reset(const SfxItemSet& rSet) +{ + SmPrintSize ePrintSize = (SmPrintSize)((const SfxUInt16Item &)rSet.Get(GetWhich(SID_PRINTSIZE))).GetValue(); + + aSizeNormal.Check(ePrintSize == PRINT_SIZE_NORMAL); + aSizeScaled.Check(ePrintSize == PRINT_SIZE_SCALED); + aSizeZoomed.Check(ePrintSize == PRINT_SIZE_ZOOMED); + + aZoom.Enable(aSizeZoomed.IsChecked()); + + aZoom.SetValue(((const SfxUInt16Item &)rSet.Get(GetWhich(SID_PRINTZOOM))).GetValue()); + + aTitle.Check(((const SfxBoolItem &)rSet.Get(GetWhich(SID_PRINTTITLE))).GetValue()); + aText.Check(((const SfxBoolItem &)rSet.Get(GetWhich(SID_PRINTTEXT))).GetValue()); + aFrame.Check(((const SfxBoolItem &)rSet.Get(GetWhich(SID_PRINTFRAME))).GetValue()); + aNoRightSpaces.Check(((const SfxBoolItem &)rSet.Get(GetWhich(SID_NO_RIGHT_SPACES))).GetValue()); + aSaveOnlyUsedSymbols.Check(((const SfxBoolItem &)rSet.Get(GetWhich(SID_SAVE_ONLY_USED_SYMBOLS))).GetValue()); +} + + +SfxTabPage* SmPrintOptionsTabPage::Create(Window* pWindow, const SfxItemSet& rSet) +{ + return (new SmPrintOptionsTabPage(pWindow, rSet)); +} + +/**************************************************************************/ + + +void SmShowFont::Paint(const Rectangle& rRect ) +{ + Control::Paint( rRect ); + + XubString Text (GetFont().GetName()); + Size TextSize(GetTextWidth(Text), GetTextHeight()); + + DrawText(Point((GetOutputSize().Width() - TextSize.Width()) / 2, + (GetOutputSize().Height() - TextSize.Height()) / 2), Text); +} + + +void SmShowFont::SetFont(const Font& rFont) +{ + Color aTxtColor( GetTextColor() ); + Font aFont (rFont); + + Invalidate(); + aFont.SetSize(Size(0, 24)); + aFont.SetAlign(ALIGN_TOP); + Control::SetFont(aFont); + + // keep old text color (new font may have different color) + SetTextColor( aTxtColor ); +} + + +IMPL_LINK_INLINE_START( SmFontDialog, FontSelectHdl, ComboBox *, pComboBox ) +{ + Face.SetName(pComboBox->GetText()); + aShowFont.SetFont(Face); + return 0; +} +IMPL_LINK_INLINE_END( SmFontDialog, FontSelectHdl, ComboBox *, pComboBox ) + + +IMPL_LINK( SmFontDialog, FontModifyHdl, ComboBox *, pComboBox ) +{ + // if font is available in list then use it + sal_uInt16 nPos = pComboBox->GetEntryPos( pComboBox->GetText() ); + if (COMBOBOX_ENTRY_NOTFOUND != nPos) + { + FontSelectHdl( pComboBox ); + } + return 0; +} + + +IMPL_LINK( SmFontDialog, AttrChangeHdl, CheckBox *, EMPTYARG /*pCheckBox*/ ) +{ + if (aBoldCheckBox.IsChecked()) + Face.SetWeight(FontWeight(WEIGHT_BOLD)); + else + Face.SetWeight(FontWeight(WEIGHT_NORMAL)); + + if (aItalicCheckBox.IsChecked()) + Face.SetItalic(ITALIC_NORMAL); + else + Face.SetItalic(ITALIC_NONE); + + aShowFont.SetFont(Face); + return 0; +} + + +void SmFontDialog::SetFont(const Font &rFont) +{ + Face = rFont; + + aFontBox.SetText( Face.GetName() ); + aBoldCheckBox.Check( IsBold( Face ) ); + aItalicCheckBox.Check( IsItalic( Face ) ); + + aShowFont.SetFont(Face); +} + + +SmFontDialog::SmFontDialog(Window * pParent, + OutputDevice *pFntListDevice, bool bHideCheckboxes, bool bFreeRes) + : ModalDialog(pParent,SmResId(RID_FONTDIALOG)), + aFixedText1 (this, SmResId(1)), + aFontBox (this, SmResId(1)), + aBoldCheckBox (this, SmResId(1)), + aItalicCheckBox (this, SmResId(2)), + aOKButton1 (this, SmResId(1)), + aCancelButton1 (this, SmResId(1)), + aShowFont (this, SmResId(1)), + aFixedText2 (this, SmResId(2)) +{ + if (bFreeRes) + FreeResource(); + + { + WaitObject( this ); + + FontList aFontList( pFntListDevice ); + + sal_uInt16 nCount = aFontList.GetFontNameCount(); + for (sal_uInt16 i = 0; i < nCount; i++) + aFontBox.InsertEntry( aFontList.GetFontName(i).GetName() ); + + Face.SetSize(Size(0, 24)); + Face.SetWeight(WEIGHT_NORMAL); + Face.SetItalic(ITALIC_NONE); + Face.SetFamily(FAMILY_DONTKNOW); + Face.SetPitch(PITCH_DONTKNOW); + Face.SetCharSet(RTL_TEXTENCODING_DONTKNOW); + Face.SetTransparent(true); + + InitColor_Impl(); + + // preview like controls should have a 2D look + aShowFont.SetBorderStyle( WINDOW_BORDER_MONO ); + } + + aFontBox.SetSelectHdl(LINK(this, SmFontDialog, FontSelectHdl)); + aFontBox.SetModifyHdl(LINK(this, SmFontDialog, FontModifyHdl)); + aBoldCheckBox.SetClickHdl(LINK(this, SmFontDialog, AttrChangeHdl)); + aItalicCheckBox.SetClickHdl(LINK(this, SmFontDialog, AttrChangeHdl)); + + if (bHideCheckboxes) + { + aBoldCheckBox.Check( false ); + aBoldCheckBox.Enable( false ); + aBoldCheckBox.Show( false ); + aItalicCheckBox.Check( false ); + aItalicCheckBox.Enable( false ); + aItalicCheckBox.Show( false ); + aFixedText2.Show( false ); + + Size aSize( aFontBox.GetSizePixel() ); + long nComboBoxBottom = aFontBox.GetPosPixel().Y() + aFontBox.GetSizePixel().Height(); + long nCheckBoxBottom = aItalicCheckBox.GetPosPixel().Y() + aItalicCheckBox.GetSizePixel().Height(); + aSize.Height() += nCheckBoxBottom - nComboBoxBottom; + aFontBox.SetSizePixel( aSize ); + } +} + +void SmFontDialog::InitColor_Impl() +{ +#if OSL_DEBUG_LEVEL > 1 + Color aBC( GetDisplayBackground().GetColor() ); +#endif + ColorData nBgCol = COL_WHITE, + nTxtCol = COL_BLACK; + const StyleSettings &rS = GetSettings().GetStyleSettings(); + if (rS.GetHighContrastMode()) + { + nBgCol = rS.GetFieldColor().GetColor(); + nTxtCol = rS.GetFieldTextColor().GetColor(); + } + + Color aTmpColor( nBgCol ); + Wallpaper aWall( aTmpColor ); + Color aTxtColor( nTxtCol ); + aShowFont.SetBackground( aWall ); + aShowFont.SetTextColor( aTxtColor ); +} + + +void SmFontDialog::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( rDCEvt.GetType() == DATACHANGED_SETTINGS && + (rDCEvt.GetFlags() & SETTINGS_STYLE) ) + InitColor_Impl(); + + ModalDialog::DataChanged( rDCEvt ); +} + +/**************************************************************************/ + + +IMPL_LINK( SmFontSizeDialog, DefaultButtonClickHdl, Button *, EMPTYARG /*pButton*/ ) +{ + QueryBox *pQueryBox = new QueryBox(this, SmResId(RID_DEFAULTSAVEQUERY)); + + if (pQueryBox->Execute() == RET_YES) + { + SmModule *pp = SM_MOD(); + SmFormat aFmt( pp->GetConfig()->GetStandardFormat() ); + WriteTo( aFmt ); + pp->GetConfig()->SetStandardFormat( aFmt ); + } + + delete pQueryBox; + return 0; +} + + +SmFontSizeDialog::SmFontSizeDialog(Window * pParent, bool bFreeRes) + : ModalDialog(pParent, SmResId(RID_FONTSIZEDIALOG)), + aFixedText1(this, SmResId(1)), + aBaseSize(this, SmResId(1)), + aFixedText4(this, SmResId(4)), + aTextSize(this, SmResId(4)), + aFixedText5(this, SmResId(5)), + aIndexSize(this, SmResId(5)), + aFixedText6(this, SmResId(6)), + aFunctionSize(this, SmResId(6)), + aFixedText7(this, SmResId(7)), + aOperatorSize(this, SmResId(7)), + aFixedText8(this, SmResId(8)), + aBorderSize(this, SmResId(8)), + aFixedLine1(this, SmResId(1)), + aOKButton1(this, SmResId(1)), + aCancelButton1(this, SmResId(1)), + aDefaultButton(this, SmResId(1)) +{ + if (bFreeRes) + FreeResource(); + + aDefaultButton.SetClickHdl(LINK(this, SmFontSizeDialog, DefaultButtonClickHdl)); +} + + +void SmFontSizeDialog::ReadFrom(const SmFormat &rFormat) +{ + //! aufpassen: richtig runden! + aBaseSize.SetValue( SmRoundFraction( + Sm100th_mmToPts( rFormat.GetBaseSize().Height() ) ) ); + + aTextSize .SetValue( rFormat.GetRelSize(SIZ_TEXT) ); + aIndexSize .SetValue( rFormat.GetRelSize(SIZ_INDEX) ); + aFunctionSize.SetValue( rFormat.GetRelSize(SIZ_FUNCTION) ); + aOperatorSize.SetValue( rFormat.GetRelSize(SIZ_OPERATOR) ); + aBorderSize .SetValue( rFormat.GetRelSize(SIZ_LIMITS) ); +} + + +void SmFontSizeDialog::WriteTo(SmFormat &rFormat) const +{ + rFormat.SetBaseSize( Size(0, SmPtsTo100th_mm( static_cast< long >(aBaseSize.GetValue()))) ); + + rFormat.SetRelSize(SIZ_TEXT, (sal_uInt16) aTextSize .GetValue()); + rFormat.SetRelSize(SIZ_INDEX, (sal_uInt16) aIndexSize .GetValue()); + rFormat.SetRelSize(SIZ_FUNCTION, (sal_uInt16) aFunctionSize.GetValue()); + rFormat.SetRelSize(SIZ_OPERATOR, (sal_uInt16) aOperatorSize.GetValue()); + rFormat.SetRelSize(SIZ_LIMITS, (sal_uInt16) aBorderSize .GetValue()); + + const Size aTmp (rFormat.GetBaseSize()); + for (sal_uInt16 i = FNT_BEGIN; i <= FNT_END; i++) + rFormat.SetFontSize(i, aTmp); + + rFormat.RequestApplyChanges(); +} + + +/**************************************************************************/ + + +IMPL_LINK( SmFontTypeDialog, MenuSelectHdl, Menu *, pMenu ) +{ + SmFontPickListBox *pActiveListBox; + + bool bHideCheckboxes = false; + switch (pMenu->GetCurItemId()) + { + case 1: pActiveListBox = &aVariableFont; break; + case 2: pActiveListBox = &aFunctionFont; break; + case 3: pActiveListBox = &aNumberFont; break; + case 4: pActiveListBox = &aTextFont; break; + case 5: pActiveListBox = &aSerifFont; bHideCheckboxes = true; break; + case 6: pActiveListBox = &aSansFont; bHideCheckboxes = true; break; + case 7: pActiveListBox = &aFixedFont; bHideCheckboxes = true; break; + default:pActiveListBox = NULL; + } + + if (pActiveListBox) + { + SmFontDialog *pFontDialog = new SmFontDialog(this, pFontListDev, bHideCheckboxes); + + pActiveListBox->WriteTo(*pFontDialog); + if (pFontDialog->Execute() == RET_OK) + pActiveListBox->ReadFrom(*pFontDialog); + delete pFontDialog; + } + return 0; +} + + +IMPL_LINK_INLINE_START( SmFontTypeDialog, DefaultButtonClickHdl, Button *, EMPTYARG /*pButton*/ ) +{ + QueryBox *pQueryBox = new QueryBox(this, SmResId(RID_DEFAULTSAVEQUERY)); + if (pQueryBox->Execute() == RET_YES) + { + SmModule *pp = SM_MOD(); + SmFormat aFmt( pp->GetConfig()->GetStandardFormat() ); + WriteTo( aFmt ); + pp->GetConfig()->SetStandardFormat( aFmt, true ); + } + + delete pQueryBox; + return 0; +} +IMPL_LINK_INLINE_END( SmFontTypeDialog, DefaultButtonClickHdl, Button *, pButton ) + + +SmFontTypeDialog::SmFontTypeDialog(Window * pParent, OutputDevice *pFntListDevice, bool bFreeRes) + : ModalDialog(pParent, SmResId(RID_FONTTYPEDIALOG)), + aFixedText1 (this, SmResId(1)), + aVariableFont (this, SmResId(1)), + aFixedText2 (this, SmResId(2)), + aFunctionFont (this, SmResId(2)), + aFixedText3 (this, SmResId(3)), + aNumberFont (this, SmResId(3)), + aFixedText4 (this, SmResId(4)), + aTextFont (this, SmResId(4)), + aFixedText5 (this, SmResId(5)), + aSerifFont (this, SmResId(5)), + aFixedText6 (this, SmResId(6)), + aSansFont (this, SmResId(6)), + aFixedText7 (this, SmResId(7)), + aFixedFont (this, SmResId(7)), + aFixedLine1 (this, SmResId(1)), + aFixedLine2 (this, SmResId(2)), + aOKButton1 (this, SmResId(1)), + aCancelButton1 (this, SmResId(1)), + aMenuButton (this, SmResId(1)), + aDefaultButton (this, SmResId(2)), + pFontListDev (pFntListDevice) +{ + if (bFreeRes) + FreeResource(); + + aDefaultButton.SetClickHdl(LINK(this, SmFontTypeDialog, DefaultButtonClickHdl)); + + aMenuButton.GetPopupMenu()->SetSelectHdl(LINK(this, SmFontTypeDialog, MenuSelectHdl)); +} + +void SmFontTypeDialog::ReadFrom(const SmFormat &rFormat) +{ + SmModule *pp = SM_MOD(); + + aVariableFont = pp->GetConfig()->GetFontPickList(FNT_VARIABLE); + aFunctionFont = pp->GetConfig()->GetFontPickList(FNT_FUNCTION); + aNumberFont = pp->GetConfig()->GetFontPickList(FNT_NUMBER); + aTextFont = pp->GetConfig()->GetFontPickList(FNT_TEXT); + aSerifFont = pp->GetConfig()->GetFontPickList(FNT_SERIF); + aSansFont = pp->GetConfig()->GetFontPickList(FNT_SANS); + aFixedFont = pp->GetConfig()->GetFontPickList(FNT_FIXED); + + aVariableFont.Insert( rFormat.GetFont(FNT_VARIABLE) ); + aFunctionFont.Insert( rFormat.GetFont(FNT_FUNCTION) ); + aNumberFont .Insert( rFormat.GetFont(FNT_NUMBER) ); + aTextFont .Insert( rFormat.GetFont(FNT_TEXT) ); + aSerifFont .Insert( rFormat.GetFont(FNT_SERIF) ); + aSansFont .Insert( rFormat.GetFont(FNT_SANS) ); + aFixedFont .Insert( rFormat.GetFont(FNT_FIXED) ); +} + + +void SmFontTypeDialog::WriteTo(SmFormat &rFormat) const +{ + SmModule *pp = SM_MOD(); + + pp->GetConfig()->GetFontPickList(FNT_VARIABLE) = aVariableFont; + pp->GetConfig()->GetFontPickList(FNT_FUNCTION) = aFunctionFont; + pp->GetConfig()->GetFontPickList(FNT_NUMBER) = aNumberFont; + pp->GetConfig()->GetFontPickList(FNT_TEXT) = aTextFont; + pp->GetConfig()->GetFontPickList(FNT_SERIF) = aSerifFont; + pp->GetConfig()->GetFontPickList(FNT_SANS) = aSansFont; + pp->GetConfig()->GetFontPickList(FNT_FIXED) = aFixedFont; + + rFormat.SetFont( FNT_VARIABLE, aVariableFont.Get(0) ); + rFormat.SetFont( FNT_FUNCTION, aFunctionFont.Get(0) ); + rFormat.SetFont( FNT_NUMBER, aNumberFont .Get(0) ); + rFormat.SetFont( FNT_TEXT, aTextFont .Get(0) ); + rFormat.SetFont( FNT_SERIF, aSerifFont .Get(0) ); + rFormat.SetFont( FNT_SANS, aSansFont .Get(0) ); + rFormat.SetFont( FNT_FIXED, aFixedFont .Get(0) ); + + rFormat.RequestApplyChanges(); +} + +/**************************************************************************/ + +struct FieldMinMax +{ + sal_uInt16 nMin, nMax; +}; + +// Data for min and max values of the 4 metric fields +// for each of the 10 categories +static const FieldMinMax pMinMaxData[10][4] = +{ + // 0 + {{ 0, 200 }, { 0, 200 }, { 0, 100 }, { 0, 0 }}, + // 1 + {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }}, + // 2 + {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }}, + // 3 + {{ 0, 100 }, { 1, 100 }, { 0, 0 }, { 0, 0 }}, + // 4 + {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }}, + // 5 + {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 100 }}, + // 6 + {{ 0, 300 }, { 0, 300 }, { 0, 0 }, { 0, 0 }}, + // 7 + {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }}, + // 8 + {{ 0, 100 }, { 0, 100 }, { 0, 0 }, { 0, 0 }}, + // 9 + {{ 0, 10000 }, { 0, 10000 }, { 0, 10000 }, { 0, 10000 }} +}; + +SmCategoryDesc::SmCategoryDesc(const ResId& rResId, sal_uInt16 nCategoryIdx) : + Resource(rResId) +{ + if (IsAvailableRes(ResId(1,*rResId.GetResMgr()).SetRT(RSC_STRING))) + { + Name = XubString(ResId(1,*rResId.GetResMgr())); + + int i; + for (i = 0; i < 4; i++) + { + int nI2 = i + 2; + + if (IsAvailableRes(ResId(nI2,*rResId.GetResMgr()).SetRT(RSC_STRING))) + { + Strings [i] = new XubString(ResId(nI2,*rResId.GetResMgr())); + Graphics [i] = new Bitmap(ResId(10*nI2,*rResId.GetResMgr())); + } + else + { + Strings [i] = 0; + Graphics [i] = 0; + } + } + + for (i = 0; i < 4; i++) + { + const FieldMinMax &rMinMax = pMinMaxData[ nCategoryIdx ][i]; + Value[i] = Minimum[i] = rMinMax.nMin; + Maximum[i] = rMinMax.nMax; + } + } + + FreeResource(); +} + + +SmCategoryDesc::~SmCategoryDesc() +{ + for (int i = 0; i < 4; i++) + { + delete Strings [i]; + delete Graphics [i]; + } +} + +/**************************************************************************/ + +IMPL_LINK( SmDistanceDialog, GetFocusHdl, Control *, pControl ) +{ + if (Categories[nActiveCategory]) + { + sal_uInt16 i; + + if (pControl == &aMetricField1) + i = 0; + else if (pControl == &aMetricField2) + i = 1; + else if (pControl == &aMetricField3) + i = 2; + else if (pControl == &aMetricField4) + i = 3; + else + return 0; + aBitmap.SetBitmap(*(Categories[nActiveCategory]->GetGraphic(i))); + } + return 0; +} + +IMPL_LINK( SmDistanceDialog, MenuSelectHdl, Menu *, pMenu ) +{ + SetCategory(pMenu->GetCurItemId() - 1); + return 0; +} + + +IMPL_LINK( SmDistanceDialog, DefaultButtonClickHdl, Button *, EMPTYARG /*pButton*/ ) +{ + QueryBox *pQueryBox = new QueryBox(this, SmResId(RID_DEFAULTSAVEQUERY)); + + if (pQueryBox->Execute() == RET_YES) + { + SmModule *pp = SM_MOD(); + SmFormat aFmt( pp->GetConfig()->GetStandardFormat() ); + WriteTo( aFmt ); + pp->GetConfig()->SetStandardFormat( aFmt ); + } + delete pQueryBox; + return 0; +} + + +IMPL_LINK( SmDistanceDialog, CheckBoxClickHdl, CheckBox *, pCheckBox ) +{ + if (pCheckBox == &aCheckBox1) + { + aCheckBox1.Toggle(); + + bool bChecked = aCheckBox1.IsChecked(); + aFixedText4 .Enable( bChecked ); + aMetricField4.Enable( bChecked ); + } + return 0; +} + + +void SmDistanceDialog::SetHelpId(MetricField &rField, const rtl::OString& sHelpId) +{ + //! HelpID's die auf diese Weise explizit gesetzt werden, muessen im + //! util Verzeichnis im File "hidother.src" mit Hilfe von "hidspecial" + //! definiert werden! + + const XubString aEmptyText; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(aEmptyText.Len() == 0, "Sm: Ooops..."); +#endif + + rField.SetHelpId(sHelpId); + rField.SetHelpText(aEmptyText); + + // since MetricField inherits from SpinField which has a sub Edit field + // (which is actually the one we modify) we have to set the help-id + // for it too. + Edit *pSubEdit = rField.GetSubEdit(); + if (pSubEdit) + { + pSubEdit->SetHelpId(sHelpId); + pSubEdit->SetHelpText(aEmptyText); + } +} + + +void SmDistanceDialog::SetCategory(sal_uInt16 nCategory) +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(/*0 <= nCategory &&*/ nCategory < NOCATEGORIES, + "Sm: wrong category number in SmDistanceDialog"); +#endif + + // array to convert category- and metricfield-number in help ids. + // 0 is used in case of unused combinations. +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(NOCATEGORIES == 10, "Sm : array doesn't fit into the number of categories"); +#endif + static const char * aCatMf2Hid[10][4] = + { + { HID_SMA_DEFAULT_DIST, HID_SMA_LINE_DIST, HID_SMA_ROOT_DIST, 0 }, + { HID_SMA_SUP_DIST, HID_SMA_SUB_DIST , 0, 0 }, + { HID_SMA_NUMERATOR_DIST, HID_SMA_DENOMINATOR_DIST, 0, 0 }, + { HID_SMA_FRACLINE_EXCWIDTH, HID_SMA_FRACLINE_LINEWIDTH, 0, 0 }, + { HID_SMA_UPPERLIMIT_DIST, HID_SMA_LOWERLIMIT_DIST, 0, 0 }, + { HID_SMA_BRACKET_EXCHEIGHT, HID_SMA_BRACKET_DIST, 0, HID_SMA_BRACKET_EXCHEIGHT2 }, + { HID_SMA_MATRIXROW_DIST, HID_SMA_MATRIXCOL_DIST, 0, 0 }, + { HID_SMA_ATTRIBUT_DIST, HID_SMA_INTERATTRIBUT_DIST, 0, 0 }, + { HID_SMA_OPERATOR_EXCHEIGHT, HID_SMA_OPERATOR_DIST, 0, 0 }, + { HID_SMA_LEFTBORDER_DIST, HID_SMA_RIGHTBORDER_DIST, HID_SMA_UPPERBORDER_DIST, HID_SMA_LOWERBORDER_DIST } + }; + + // array to help iterate over the controls + Window * const aWin[4][2] = + { + { &aFixedText1, &aMetricField1 }, + { &aFixedText2, &aMetricField2 }, + { &aFixedText3, &aMetricField3 }, + { &aFixedText4, &aMetricField4 } + }; + + SmCategoryDesc *pCat; + + // merken der (evtl neuen) Einstellungen der aktiven SmCategoryDesc + // bevor zu der neuen gewechselt wird. + if (nActiveCategory != CATEGORY_NONE) + { + pCat = Categories[nActiveCategory]; + pCat->SetValue(0, (sal_uInt16) aMetricField1.GetValue()); + pCat->SetValue(1, (sal_uInt16) aMetricField2.GetValue()); + pCat->SetValue(2, (sal_uInt16) aMetricField3.GetValue()); + pCat->SetValue(3, (sal_uInt16) aMetricField4.GetValue()); + + if (nActiveCategory == 5) + bScaleAllBrackets = aCheckBox1.IsChecked(); + + aMenuButton.GetPopupMenu()->CheckItem(nActiveCategory + 1, false); + } + + // aktivieren/deaktivieren der zugehoerigen Controls in Abhaengigkeit von der + // gewaehlten Kategorie. + bool bActive; + for (sal_uInt16 i = 0; i < 4; i++) + { + FixedText *pFT = (FixedText * const) aWin[i][0]; + MetricField *pMF = (MetricField * const) aWin[i][1]; + + // Um feststellen welche Controls aktiv sein sollen wird das + // vorhandensein einer zugehoerigen HelpID ueberprueft. + bActive = aCatMf2Hid[nCategory][i] != 0; + + pFT->Show(bActive); + pFT->Enable(bActive); + pMF->Show(bActive); + pMF->Enable(bActive); + + // setzen von Masseinheit und Anzahl der Nachkommastellen + FieldUnit eUnit; + sal_uInt16 nDigits; + if (nCategory < 9) + { + eUnit = FUNIT_CUSTOM; + nDigits = 0; + pMF->SetCustomUnitText( '%' ); + } + else + { + eUnit = FUNIT_100TH_MM; + nDigits = 2; + } + pMF->SetUnit(eUnit); //! veraendert den Wert + pMF->SetDecimalDigits(nDigits); + + if (bActive) + { + pCat = Categories[nCategory]; + pFT->SetText(*pCat->GetString(i)); + + pMF->SetMin(pCat->GetMinimum(i)); + pMF->SetMax(pCat->GetMaximum(i)); + pMF->SetValue(pCat->GetValue(i)); + + SetHelpId(*pMF, aCatMf2Hid[nCategory][i]); + } + } + // nun noch die CheckBox und das zugehoerige MetricField genau dann aktivieren, + // falls es sich um das Klammer Menu handelt. + bActive = nCategory == 5; + aCheckBox1.Show(bActive); + aCheckBox1.Enable(bActive); + if (bActive) + { + aCheckBox1.Check( bScaleAllBrackets ); + + bool bChecked = aCheckBox1.IsChecked(); + aFixedText4 .Enable( bChecked ); + aMetricField4.Enable( bChecked ); + } + + aMenuButton.GetPopupMenu()->CheckItem(nCategory + 1, true); + aFixedLine.SetText(Categories[nCategory]->GetName()); + + nActiveCategory = nCategory; + + aMetricField1.GrabFocus(); + Invalidate(); + Update(); +} + + +SmDistanceDialog::SmDistanceDialog(Window *pParent, bool bFreeRes) + : ModalDialog(pParent, SmResId(RID_DISTANCEDIALOG)), + aFixedText1 (this, SmResId(1)), + aMetricField1 (this, SmResId(1)), + aFixedText2 (this, SmResId(2)), + aMetricField2 (this, SmResId(2)), + aFixedText3 (this, SmResId(3)), + aMetricField3 (this, SmResId(3)), + aCheckBox1 (this, SmResId(1)), + aFixedText4 (this, SmResId(4)), + aMetricField4 (this, SmResId(4)), + aOKButton1 (this, SmResId(1)), + aCancelButton1 (this, SmResId(1)), + aMenuButton (this, SmResId(1)), + aDefaultButton (this, SmResId(1)), + aBitmap (this, SmResId(1)), + aFixedLine (this, SmResId(1)) +{ + for (sal_uInt16 i = 0; i < NOCATEGORIES; i++) + Categories[i] = new SmCategoryDesc(SmResId(i + 1), i); + nActiveCategory = CATEGORY_NONE; + bScaleAllBrackets = false; + + if (bFreeRes) + FreeResource(); + + // preview like controls should have a 2D look + aBitmap.SetBorderStyle( WINDOW_BORDER_MONO ); + + aMetricField1.SetGetFocusHdl(LINK(this, SmDistanceDialog, GetFocusHdl)); + aMetricField2.SetGetFocusHdl(LINK(this, SmDistanceDialog, GetFocusHdl)); + aMetricField3.SetGetFocusHdl(LINK(this, SmDistanceDialog, GetFocusHdl)); + aMetricField4.SetGetFocusHdl(LINK(this, SmDistanceDialog, GetFocusHdl)); + aCheckBox1.SetClickHdl(LINK(this, SmDistanceDialog, CheckBoxClickHdl)); + + aMenuButton.GetPopupMenu()->SetSelectHdl(LINK(this, SmDistanceDialog, MenuSelectHdl)); + + aDefaultButton.SetClickHdl(LINK(this, SmDistanceDialog, DefaultButtonClickHdl)); +} + + +SmDistanceDialog::~SmDistanceDialog() +{ + for (int i = 0; i < NOCATEGORIES; i++) + DELETEZ(Categories[i]); +} + +void SmDistanceDialog::DataChanged( const DataChangedEvent &rEvt ) +{ + ModalDialog::DataChanged( rEvt ); +} + +void SmDistanceDialog::ReadFrom(const SmFormat &rFormat) +{ + Categories[0]->SetValue(0, rFormat.GetDistance(DIS_HORIZONTAL)); + Categories[0]->SetValue(1, rFormat.GetDistance(DIS_VERTICAL)); + Categories[0]->SetValue(2, rFormat.GetDistance(DIS_ROOT)); + Categories[1]->SetValue(0, rFormat.GetDistance(DIS_SUPERSCRIPT)); + Categories[1]->SetValue(1, rFormat.GetDistance(DIS_SUBSCRIPT)); + Categories[2]->SetValue(0, rFormat.GetDistance(DIS_NUMERATOR)); + Categories[2]->SetValue(1, rFormat.GetDistance(DIS_DENOMINATOR)); + Categories[3]->SetValue(0, rFormat.GetDistance(DIS_FRACTION)); + Categories[3]->SetValue(1, rFormat.GetDistance(DIS_STROKEWIDTH)); + Categories[4]->SetValue(0, rFormat.GetDistance(DIS_UPPERLIMIT)); + Categories[4]->SetValue(1, rFormat.GetDistance(DIS_LOWERLIMIT)); + Categories[5]->SetValue(0, rFormat.GetDistance(DIS_BRACKETSIZE)); + Categories[5]->SetValue(1, rFormat.GetDistance(DIS_BRACKETSPACE)); + Categories[5]->SetValue(3, rFormat.GetDistance(DIS_NORMALBRACKETSIZE)); + Categories[6]->SetValue(0, rFormat.GetDistance(DIS_MATRIXROW)); + Categories[6]->SetValue(1, rFormat.GetDistance(DIS_MATRIXCOL)); + Categories[7]->SetValue(0, rFormat.GetDistance(DIS_ORNAMENTSIZE)); + Categories[7]->SetValue(1, rFormat.GetDistance(DIS_ORNAMENTSPACE)); + Categories[8]->SetValue(0, rFormat.GetDistance(DIS_OPERATORSIZE)); + Categories[8]->SetValue(1, rFormat.GetDistance(DIS_OPERATORSPACE)); + Categories[9]->SetValue(0, rFormat.GetDistance(DIS_LEFTSPACE)); + Categories[9]->SetValue(1, rFormat.GetDistance(DIS_RIGHTSPACE)); + Categories[9]->SetValue(2, rFormat.GetDistance(DIS_TOPSPACE)); + Categories[9]->SetValue(3, rFormat.GetDistance(DIS_BOTTOMSPACE)); + + bScaleAllBrackets = rFormat.IsScaleNormalBrackets(); + + // force update (even of category 0) by setting nActiveCategory to a + // non-existent category number + nActiveCategory = CATEGORY_NONE; + SetCategory(0); +} + + +void SmDistanceDialog::WriteTo(SmFormat &rFormat) /*const*/ +{ + // hmm... koennen die tatsaechlich unterschiedlich sein? + // wenn nicht kann oben naemlich das const stehen! + SetCategory(nActiveCategory); + + rFormat.SetDistance( DIS_HORIZONTAL, Categories[0]->GetValue(0) ); + rFormat.SetDistance( DIS_VERTICAL, Categories[0]->GetValue(1) ); + rFormat.SetDistance( DIS_ROOT, Categories[0]->GetValue(2) ); + rFormat.SetDistance( DIS_SUPERSCRIPT, Categories[1]->GetValue(0) ); + rFormat.SetDistance( DIS_SUBSCRIPT, Categories[1]->GetValue(1) ); + rFormat.SetDistance( DIS_NUMERATOR, Categories[2]->GetValue(0) ); + rFormat.SetDistance( DIS_DENOMINATOR, Categories[2]->GetValue(1) ); + rFormat.SetDistance( DIS_FRACTION, Categories[3]->GetValue(0) ); + rFormat.SetDistance( DIS_STROKEWIDTH, Categories[3]->GetValue(1) ); + rFormat.SetDistance( DIS_UPPERLIMIT, Categories[4]->GetValue(0) ); + rFormat.SetDistance( DIS_LOWERLIMIT, Categories[4]->GetValue(1) ); + rFormat.SetDistance( DIS_BRACKETSIZE, Categories[5]->GetValue(0) ); + rFormat.SetDistance( DIS_BRACKETSPACE, Categories[5]->GetValue(1) ); + rFormat.SetDistance( DIS_MATRIXROW, Categories[6]->GetValue(0) ); + rFormat.SetDistance( DIS_MATRIXCOL, Categories[6]->GetValue(1) ); + rFormat.SetDistance( DIS_ORNAMENTSIZE, Categories[7]->GetValue(0) ); + rFormat.SetDistance( DIS_ORNAMENTSPACE, Categories[7]->GetValue(1) ); + rFormat.SetDistance( DIS_OPERATORSIZE, Categories[8]->GetValue(0) ); + rFormat.SetDistance( DIS_OPERATORSPACE, Categories[8]->GetValue(1) ); + rFormat.SetDistance( DIS_LEFTSPACE, Categories[9]->GetValue(0) ); + rFormat.SetDistance( DIS_RIGHTSPACE, Categories[9]->GetValue(1) ); + rFormat.SetDistance( DIS_TOPSPACE, Categories[9]->GetValue(2) ); + rFormat.SetDistance( DIS_BOTTOMSPACE, Categories[9]->GetValue(3) ); + rFormat.SetDistance( DIS_NORMALBRACKETSIZE, Categories[5]->GetValue(3) ); + + rFormat.SetScaleNormalBrackets( bScaleAllBrackets ); + + rFormat.RequestApplyChanges(); +} + + +/**************************************************************************/ + + +IMPL_LINK( SmAlignDialog, DefaultButtonClickHdl, Button *, EMPTYARG /*pButton*/ ) +{ + QueryBox *pQueryBox = new QueryBox(this, SmResId(RID_DEFAULTSAVEQUERY)); + + if (pQueryBox->Execute() == RET_YES) + { + SmModule *pp = SM_MOD(); + SmFormat aFmt( pp->GetConfig()->GetStandardFormat() ); + WriteTo( aFmt ); + pp->GetConfig()->SetStandardFormat( aFmt ); + } + + delete pQueryBox; + return 0; +} + + +SmAlignDialog::SmAlignDialog(Window * pParent, bool bFreeRes) + : ModalDialog(pParent, SmResId(RID_ALIGNDIALOG)), + aLeft (this, SmResId(1)), + aCenter (this, SmResId(2)), + aRight (this, SmResId(3)), + aFixedLine1 (this, SmResId(1)), + aOKButton1 (this, SmResId(1)), + aCancelButton1 (this, SmResId(1)), + aDefaultButton (this, SmResId(1)) +{ + if (bFreeRes) + FreeResource(); + + aDefaultButton.SetClickHdl(LINK(this, SmAlignDialog, DefaultButtonClickHdl)); +} + + +void SmAlignDialog::ReadFrom(const SmFormat &rFormat) +{ + switch (rFormat.GetHorAlign()) + { + case AlignLeft: + aLeft .Check(true); + aCenter.Check(false); + aRight .Check(false); + break; + + case AlignCenter: + aLeft .Check(false); + aCenter.Check(true); + aRight .Check(false); + break; + + case AlignRight: + aLeft .Check(false); + aCenter.Check(false); + aRight .Check(true); + break; + } +} + + +void SmAlignDialog::WriteTo(SmFormat &rFormat) const +{ + if (aLeft.IsChecked()) + rFormat.SetHorAlign(AlignLeft); + else if (aRight.IsChecked()) + rFormat.SetHorAlign(AlignRight); + else + rFormat.SetHorAlign(AlignCenter); + + rFormat.RequestApplyChanges(); +} + + +/**************************************************************************/ + + +void SmShowSymbolSet::Paint(const Rectangle&) +{ + Push(PUSH_MAPMODE); + + // MapUnit einstellen fuer die 'nLen' berechnet wurde + SetMapMode(MapMode(MAP_PIXEL)); + + sal_uInt16 v = sal::static_int_cast< sal_uInt16 >((aVScrollBar.GetThumbPos() * nColumns)); + size_t nSymbols = aSymbolSet.size(); + + Color aTxtColor( GetTextColor() ); + for (sal_uInt16 i = v; i < nSymbols ; i++) + { + SmSym aSymbol (*aSymbolSet[i]); + Font aFont (aSymbol.GetFace()); + aFont.SetAlign(ALIGN_TOP); + + // etwas kleinere FontSize nehmen (als nLen) um etwas Luft zu haben + // (hoffentlich auch genug fuer links und rechts!) + aFont.SetSize(Size(0, nLen - (nLen / 3))); + SetFont(aFont); + // keep text color + SetTextColor( aTxtColor ); + + int nIV = i - v; + sal_UCS4 cChar = aSymbol.GetCharacter(); + String aText( OUString( &cChar, 1 ) ); + Size aSize( GetTextWidth( aText ), GetTextHeight()); + + DrawText(Point((nIV % nColumns) * nLen + (nLen - aSize.Width()) / 2, + (nIV / nColumns) * nLen + (nLen - aSize.Height()) / 2), + aText); + } + + if (nSelectSymbol != SYMBOL_NONE) + { + Invert(Rectangle(Point(((nSelectSymbol - v) % nColumns) * nLen, + ((nSelectSymbol - v) / nColumns) * nLen), + Size(nLen, nLen))); + } + + Pop(); +} + + +void SmShowSymbolSet::MouseButtonDown(const MouseEvent& rMEvt) +{ + GrabFocus(); + + if (rMEvt.IsLeft() && Rectangle(Point(0, 0), aOutputSize).IsInside(rMEvt.GetPosPixel())) + { + long nPos = (rMEvt.GetPosPixel().Y() / nLen) * nColumns + (rMEvt.GetPosPixel().X() / nLen) + + aVScrollBar.GetThumbPos() * nColumns; + SelectSymbol( sal::static_int_cast< sal_uInt16 >(nPos) ); + + aSelectHdlLink.Call(this); + + if (rMEvt.GetClicks() > 1) aDblClickHdlLink.Call(this); + } + else Control::MouseButtonDown (rMEvt); +} + + +void SmShowSymbolSet::KeyInput(const KeyEvent& rKEvt) +{ + sal_uInt16 n = nSelectSymbol; + + if (n != SYMBOL_NONE) + { + switch (rKEvt.GetKeyCode().GetCode()) + { + case KEY_DOWN: n = n + nColumns; break; + case KEY_UP: n = n - nColumns; break; + case KEY_LEFT: n -= 1; break; + case KEY_RIGHT: n += 1; break; + case KEY_HOME: n = 0; break; + case KEY_END: n = static_cast< sal_uInt16 >(aSymbolSet.size() - 1); break; + case KEY_PAGEUP: n -= nColumns * nRows; break; + case KEY_PAGEDOWN: n += nColumns * nRows; break; + + default: + Control::KeyInput(rKEvt); + return; + } + } + else + n = 0; + + if (n >= aSymbolSet.size()) + n = nSelectSymbol; + + // adjust scrollbar + if ((n < (sal_uInt16) (aVScrollBar.GetThumbPos() * nColumns)) || + (n >= (sal_uInt16) ((aVScrollBar.GetThumbPos() + nRows) * nColumns))) + { + aVScrollBar.SetThumbPos(n / nColumns); + Invalidate(); + Update(); + } + + SelectSymbol(n); + aSelectHdlLink.Call(this); +} + + +SmShowSymbolSet::SmShowSymbolSet(Window *pParent, const ResId& rResId) : + Control(pParent, rResId), + aVScrollBar(this, WinBits(WB_VSCROLL)) +{ + nSelectSymbol = SYMBOL_NONE; + + aOutputSize = GetOutputSizePixel(); + long nScrollBarWidth = aVScrollBar.GetSizePixel().Width(), + nUseableWidth = aOutputSize.Width() - nScrollBarWidth; + + // Hoehe von 16pt in Pixeln (passend zu 'aOutputSize') + nLen = (sal_uInt16) LogicToPixel(Size(0, 16), MapMode(MAP_POINT)).Height(); + + nColumns = sal::static_int_cast< sal_uInt16 >(nUseableWidth / nLen); + if (nColumns > 2 && nColumns % 2 != 0) + nColumns--; + nRows = sal::static_int_cast< sal_uInt16 >(aOutputSize.Height() / nLen); +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(nColumns > 0, "Sm : no columns"); + OSL_ENSURE(nRows > 0, "Sm : no rows"); +#endif + + // genau passend machen + aOutputSize.Width() = nColumns * nLen; + aOutputSize.Height() = nRows * nLen; + + aVScrollBar.SetPosSizePixel(Point(aOutputSize.Width() + 1, -1), + Size(nScrollBarWidth, aOutputSize.Height() + 2)); + aVScrollBar.Enable(false); + aVScrollBar.Show(); + aVScrollBar.SetScrollHdl(LINK(this, SmShowSymbolSet, ScrollHdl)); + + Size WindowSize (aOutputSize); + WindowSize.Width() += nScrollBarWidth; + SetOutputSizePixel(WindowSize); + +} + + +void SmShowSymbolSet::SetSymbolSet(const SymbolPtrVec_t& rSymbolSet) +{ + aSymbolSet = rSymbolSet; + + if (static_cast< sal_uInt16 >(aSymbolSet.size()) > (nColumns * nRows)) + { + aVScrollBar.SetRange(Range(0, ((aSymbolSet.size() + (nColumns - 1)) / nColumns) - nRows)); + aVScrollBar.Enable(true); + } + else + { + aVScrollBar.SetRange(Range(0,0)); + aVScrollBar.Enable (false); + } + + Invalidate(); +} + + +void SmShowSymbolSet::SelectSymbol(sal_uInt16 nSymbol) +{ + int v = (int) (aVScrollBar.GetThumbPos() * nColumns); + + if (nSelectSymbol != SYMBOL_NONE) + Invalidate(Rectangle(Point(((nSelectSymbol - v) % nColumns) * nLen, + ((nSelectSymbol - v) / nColumns) * nLen), + Size(nLen, nLen))); + + if (nSymbol < aSymbolSet.size()) + nSelectSymbol = nSymbol; + + if (aSymbolSet.size() == 0) + nSelectSymbol = SYMBOL_NONE; + + if (nSelectSymbol != SYMBOL_NONE) + Invalidate(Rectangle(Point(((nSelectSymbol - v) % nColumns) * nLen, + ((nSelectSymbol - v) / nColumns) * nLen), + Size(nLen, nLen))); + + Update(); +} + + +IMPL_LINK( SmShowSymbolSet, ScrollHdl, ScrollBar*, EMPTYARG /*pScrollBar*/) +{ + Invalidate(); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// + +void SmShowSymbol::Paint(const Rectangle &rRect) +{ + Control::Paint( rRect ); + + const XubString &rText = GetText(); + Size aTextSize(GetTextWidth(rText), GetTextHeight()); + + DrawText(Point((GetOutputSize().Width() - aTextSize.Width()) / 2, + (GetOutputSize().Height() * 7/10)), rText); +} + + +void SmShowSymbol::MouseButtonDown(const MouseEvent& rMEvt) +{ + if (rMEvt.GetClicks() > 1) + aDblClickHdlLink.Call(this); + else + Control::MouseButtonDown (rMEvt); +} + + +void SmShowSymbol::SetSymbol(const SmSym *pSymbol) +{ + if (pSymbol) + { + Font aFont (pSymbol->GetFace()); + aFont.SetSize(Size(0, GetOutputSize().Height() - GetOutputSize().Height() / 3)); + aFont.SetAlign(ALIGN_BASELINE); + SetFont(aFont); + + sal_UCS4 cChar = pSymbol->GetCharacter(); + String aText( OUString( &cChar, 1 ) ); + SetText( aText ); + } + + // 'Invalidate' fuellt den background mit der background-Farbe. + // Falls der NULL pointer uebergeben wurde reicht dies also zum loeschen + // der Anzeige + Invalidate(); +} + + +//////////////////////////////////////////////////////////////////////////////// + +void SmSymbolDialog::FillSymbolSets(bool bDeleteText) + // fuellt die Eintraege der moeglichen 'SymbolsSet's im Dialog mit den + // aktuellen Werten des SymbolSet Managers, selektiert aber keinen. +{ + aSymbolSets.Clear(); + if (bDeleteText) + aSymbolSets.SetNoSelection(); + + std::set< String > aSybolSetNames( rSymbolMgr.GetSymbolSetNames() ); + std::set< String >::const_iterator aIt( aSybolSetNames.begin() ); + for ( ; aIt != aSybolSetNames.end(); ++aIt) + aSymbolSets.InsertEntry( *aIt ); +} + + +IMPL_LINK( SmSymbolDialog, SymbolSetChangeHdl, ListBox *, EMPTYARG pListBox ) +{ + (void) pListBox; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pListBox == &aSymbolSets, "Sm : wrong argument"); +#endif + + SelectSymbolSet(aSymbolSets.GetSelectEntry()); + return 0; +} + + +IMPL_LINK( SmSymbolDialog, SymbolChangeHdl, SmShowSymbolSet *, EMPTYARG pShowSymbolSet ) +{ + (void) pShowSymbolSet; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pShowSymbolSet == &aSymbolSetDisplay, "Sm : wrong argument"); +#endif + + SelectSymbol(aSymbolSetDisplay.GetSelectSymbol()); + return 0; +} + +IMPL_LINK( SmSymbolDialog, EditClickHdl, Button *, EMPTYARG pButton ) +{ + (void) pButton; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pButton == &aEditBtn, "Sm : wrong argument"); +#endif + + SmSymDefineDialog *pDialog = new SmSymDefineDialog(this, pFontListDev, rSymbolMgr); + + // aktuelles Symbol und SymbolSet am neuen Dialog setzen + const XubString aSymSetName (aSymbolSets.GetSelectEntry()), + aSymName (aSymbolName.GetText()); + pDialog->SelectOldSymbolSet(aSymSetName); + pDialog->SelectOldSymbol(aSymName); + pDialog->SelectSymbolSet(aSymSetName); + pDialog->SelectSymbol(aSymName); + + // altes SymbolSet merken + XubString aOldSymbolSet (aSymbolSets.GetSelectEntry()); + + sal_uInt16 nSymPos = GetSelectedSymbol(); + + // Dialog an evtl geaenderte Daten des SymbolSet Manager anpassen + if (pDialog->Execute() == RET_OK && rSymbolMgr.IsModified()) + { + rSymbolMgr.Save(); + FillSymbolSets(); + } + + // wenn das alte SymbolSet nicht mehr existiert zum ersten gehen + // (soweit eines vorhanden ist) + if (!SelectSymbolSet(aOldSymbolSet) && aSymbolSets.GetEntryCount() > 0) + SelectSymbolSet(aSymbolSets.GetEntry(0)); + else + { + // just update display of current symbol set + OSL_ENSURE( aSymSetName == aSymSetName, "unexpected change in symbol set name" ); + aSymbolSet = rSymbolMgr.GetSymbolSet( aSymbolSetName ); + aSymbolSetDisplay.SetSymbolSet( aSymbolSet ); + } + + if (nSymPos >= aSymbolSet.size()) + nSymPos = static_cast< sal_uInt16 >(aSymbolSet.size()) - 1; + SelectSymbol( nSymPos ); + + delete pDialog; + return 0; +} + + +IMPL_LINK( SmSymbolDialog, SymbolDblClickHdl, SmShowSymbolSet *, EMPTYARG pShowSymbolSet ) +{ + (void) pShowSymbolSet; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pShowSymbolSet == &aSymbolSetDisplay, "Sm : wrong argument"); +#endif + + GetClickHdl(&aGetBtn); + EndDialog(RET_OK); + return 0; +} + + +IMPL_LINK( SmSymbolDialog, GetClickHdl, Button *, EMPTYARG pButton ) +{ + (void) pButton; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pButton == &aGetBtn, "Sm : wrong button"); +#endif + + const SmSym *pSym = GetSymbol(); + if (pSym) + { + String aText ('%'); + aText += pSym->GetName(); + aText += (sal_Unicode)' '; + + rViewSh.GetViewFrame()->GetDispatcher()->Execute( + SID_INSERTSYMBOL, SFX_CALLMODE_STANDARD, + new SfxStringItem(SID_INSERTSYMBOL, aText), 0L); + } + + return 0; +} + + +IMPL_LINK_INLINE_START( SmSymbolDialog, CloseClickHdl, Button *, EMPTYARG pButton ) +{ + (void) pButton; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pButton == &aCloseBtn, "Sm : wrong button"); +#endif + + EndDialog(true); + return 0; +} +IMPL_LINK_INLINE_END( SmSymbolDialog, CloseClickHdl, Button *, pButton ) + + +SmSymbolDialog::SmSymbolDialog(Window *pParent, OutputDevice *pFntListDevice, + SmSymbolManager &rMgr, SmViewShell &rViewShell, bool bFreeRes) : + ModalDialog (pParent, SmResId(RID_SYMBOLDIALOG)), + aSymbolSetText (this, SmResId(1)), + aSymbolSets (this, SmResId(1)), + aSymbolSetDisplay (this, SmResId(1)), + aSymbolName (this, SmResId(2)), + aSymbolDisplay (this, SmResId(2)), + aGetBtn (this, SmResId(2)), + aCloseBtn (this, SmResId(3)), + aEditBtn (this, SmResId(1)), + rViewSh (rViewShell), + rSymbolMgr (rMgr), + pFontListDev (pFntListDevice) +{ + if (bFreeRes) + FreeResource(); + + aSymbolSetName = String(); + aSymbolSet.clear(); + FillSymbolSets(); + if (aSymbolSets.GetEntryCount() > 0) + SelectSymbolSet(aSymbolSets.GetEntry(0)); + + InitColor_Impl(); + + // preview like controls should have a 2D look + aSymbolDisplay.SetBorderStyle( WINDOW_BORDER_MONO ); + + aSymbolSets .SetSelectHdl (LINK(this, SmSymbolDialog, SymbolSetChangeHdl)); + aSymbolSetDisplay.SetSelectHdl (LINK(this, SmSymbolDialog, SymbolChangeHdl)); + aSymbolSetDisplay.SetDblClickHdl(LINK(this, SmSymbolDialog, SymbolDblClickHdl)); + aSymbolDisplay .SetDblClickHdl(LINK(this, SmSymbolDialog, SymbolDblClickHdl)); + aCloseBtn .SetClickHdl (LINK(this, SmSymbolDialog, CloseClickHdl)); + aEditBtn .SetClickHdl (LINK(this, SmSymbolDialog, EditClickHdl)); + aGetBtn .SetClickHdl (LINK(this, SmSymbolDialog, GetClickHdl)); +} + + +SmSymbolDialog::~SmSymbolDialog() +{ +} + + +void SmSymbolDialog::InitColor_Impl() +{ +#if OSL_DEBUG_LEVEL > 1 + Color aBC( GetDisplayBackground().GetColor() ); +#endif + ColorData nBgCol = COL_WHITE, + nTxtCol = COL_BLACK; + const StyleSettings &rS = GetSettings().GetStyleSettings(); + if (rS.GetHighContrastMode()) + { + nBgCol = rS.GetFieldColor().GetColor(); + nTxtCol = rS.GetFieldTextColor().GetColor(); + } + + Color aTmpColor( nBgCol ); + Wallpaper aWall( aTmpColor ); + Color aTxtColor( nTxtCol ); + aSymbolDisplay .SetBackground( aWall ); + aSymbolDisplay .SetTextColor( aTxtColor ); + aSymbolSetDisplay.SetBackground( aWall ); + aSymbolSetDisplay.SetTextColor( aTxtColor ); +} + + +void SmSymbolDialog::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( rDCEvt.GetType() == DATACHANGED_SETTINGS && + (rDCEvt.GetFlags() & SETTINGS_STYLE) ) + InitColor_Impl(); + + ModalDialog::DataChanged( rDCEvt ); +} + + +bool SmSymbolDialog::SelectSymbolSet(const XubString &rSymbolSetName) +{ + bool bRet = false; + sal_uInt16 nPos = aSymbolSets.GetEntryPos(rSymbolSetName); + + aSymbolSetName = String(); + aSymbolSet.clear(); + if (nPos != LISTBOX_ENTRY_NOTFOUND) + { + aSymbolSets.SelectEntryPos(nPos); + + aSymbolSetName = rSymbolSetName; + aSymbolSet = rSymbolMgr.GetSymbolSet( aSymbolSetName ); + + // sort symbols by Unicode position (useful for displaying Greek characters alphabetically) + std::sort( aSymbolSet.begin(), aSymbolSet.end(), lt_SmSymPtr() ); + + aSymbolSetDisplay.SetSymbolSet( aSymbolSet ); + if (aSymbolSet.size() > 0) + SelectSymbol(0); + + bRet = true; + } + else + aSymbolSets.SetNoSelection(); + + return bRet; +} + + +void SmSymbolDialog::SelectSymbol(sal_uInt16 nSymbolNo) +{ + const SmSym *pSym = NULL; + if (aSymbolSetName.Len() > 0 && nSymbolNo < static_cast< sal_uInt16 >(aSymbolSet.size())) + pSym = aSymbolSet[ nSymbolNo ]; + + aSymbolSetDisplay.SelectSymbol(nSymbolNo); + aSymbolDisplay.SetSymbol(pSym); + aSymbolName.SetText(pSym ? pSym->GetName() : XubString()); +} + + +const SmSym * SmSymbolDialog::GetSymbol() const +{ + sal_uInt16 nSymbolNo = aSymbolSetDisplay.GetSelectSymbol(); + bool bValid = aSymbolSetName.Len() > 0 && nSymbolNo < static_cast< sal_uInt16 >(aSymbolSet.size()); + return bValid ? aSymbolSet[ nSymbolNo ] : NULL; +} + + +//////////////////////////////////////////////////////////////////////////////// + + +void SmShowChar::Paint(const Rectangle &rRect) +{ + Control::Paint( rRect ); + + OUString aText( GetText() ); + if (aText.getLength() > 0) + { +#if OSL_DEBUG_LEVEL > 1 + sal_Int32 nPos = 0; + sal_UCS4 cChar = aText.iterateCodePoints( &nPos ); + (void) cChar; +#endif + Size aTextSize(GetTextWidth(aText), GetTextHeight()); + + DrawText(Point((GetOutputSize().Width() - aTextSize.Width()) / 2, + (GetOutputSize().Height() * 7/10)), aText); + } +} + + +void SmShowChar::SetSymbol( const SmSym *pSym ) +{ + if (pSym) + SetSymbol( pSym->GetCharacter(), pSym->GetFace() ); +} + + +void SmShowChar::SetSymbol( sal_UCS4 cChar, const Font &rFont ) +{ + Font aFont( rFont ); + aFont.SetSize( Size(0, GetOutputSize().Height() - GetOutputSize().Height() / 3) ); + aFont.SetAlign(ALIGN_BASELINE); + SetFont(aFont); + aFont.SetTransparent(true); + + String aText( OUString( &cChar, 1) ); + SetText( aText ); + + Invalidate(); +} + + +//////////////////////////////////////////////////////////////////////////////// + +void SmSymDefineDialog::FillSymbols(ComboBox &rComboBox, bool bDeleteText) +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(&rComboBox == &aOldSymbols || &rComboBox == &aSymbols, + "Sm : wrong ComboBox"); +#endif + + rComboBox.Clear(); + if (bDeleteText) + rComboBox.SetText(XubString()); + + ComboBox &rBox = &rComboBox == &aOldSymbols ? aOldSymbolSets : aSymbolSets; + SymbolPtrVec_t aSymSet( aSymbolMgrCopy.GetSymbolSet( rBox.GetText() ) ); + for (size_t i = 0; i < aSymSet.size(); ++i) + rComboBox.InsertEntry( aSymSet[i]->GetName() ); +} + + +void SmSymDefineDialog::FillSymbolSets(ComboBox &rComboBox, bool bDeleteText) +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(&rComboBox == &aOldSymbolSets || &rComboBox == &aSymbolSets, + "Sm : falsche ComboBox"); +#endif + + rComboBox.Clear(); + if (bDeleteText) + rComboBox.SetText(XubString()); + + const std::set< String > aSymbolSetNames( aSymbolMgrCopy.GetSymbolSetNames() ); + std::set< String >::const_iterator aIt( aSymbolSetNames.begin() ); + for ( ; aIt != aSymbolSetNames.end(); ++aIt) + rComboBox.InsertEntry( *aIt ); +} + + +void SmSymDefineDialog::FillFonts(bool bDelete) +{ + aFonts.Clear(); + if (bDelete) + aFonts.SetNoSelection(); + + // alle Fonts der 'FontList' in die Fontliste aufnehmen + // von denen mit gleichen Namen jedoch nur einen (denn der Style wird + // ueber die 'FontStyleBox' gewaehlt und nicht auch noch hier) + if (pFontList) + { + sal_uInt16 nCount = pFontList->GetFontNameCount(); + for (sal_uInt16 i = 0; i < nCount; i++) + aFonts.InsertEntry( pFontList->GetFontName(i).GetName() ); + } +} + + +void SmSymDefineDialog::FillStyles(bool bDeleteText) +{ + aStyles.Clear(); + if (bDeleteText) + aStyles.SetText(XubString()); + + XubString aText (aFonts.GetSelectEntry()); + if (aText.Len() != 0) + { + // eigene StyleName's verwenden + const SmFontStyles &rStyles = GetFontStyles(); + for (sal_uInt16 i = 0; i < rStyles.GetCount(); i++) + aStyles.InsertEntry( rStyles.GetStyleName(i) ); + +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(aStyles.GetEntryCount() > 0, "Sm : no styles available"); +#endif + aStyles.SetText( aStyles.GetEntry(0) ); + } +} + + +SmSym * SmSymDefineDialog::GetSymbol(const ComboBox &rComboBox) +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(&rComboBox == &aOldSymbols || &rComboBox == &aSymbols, + "Sm : wrong combobox"); +#endif + return aSymbolMgrCopy.GetSymbolByName(rComboBox.GetText()); +} + + +IMPL_LINK( SmSymDefineDialog, OldSymbolChangeHdl, ComboBox *, EMPTYARG pComboBox ) +{ + (void) pComboBox; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pComboBox == &aOldSymbols, "Sm : wrong argument"); +#endif + SelectSymbol(aOldSymbols, aOldSymbols.GetText(), false); + return 0; +} + + +IMPL_LINK( SmSymDefineDialog, OldSymbolSetChangeHdl, ComboBox *, EMPTYARG pComboBox ) +{ + (void) pComboBox; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pComboBox == &aOldSymbolSets, "Sm : wrong argument"); +#endif + SelectSymbolSet(aOldSymbolSets, aOldSymbolSets.GetText(), false); + return 0; +} + + +IMPL_LINK( SmSymDefineDialog, ModifyHdl, ComboBox *, pComboBox ) +{ + // merken der Cursorposition zum wiederherstellen derselben + Selection aSelection (pComboBox->GetSelection()); + + if (pComboBox == &aSymbols) + SelectSymbol(aSymbols, aSymbols.GetText(), false); + else if (pComboBox == &aSymbolSets) + SelectSymbolSet(aSymbolSets, aSymbolSets.GetText(), false); + else if (pComboBox == &aOldSymbols) + // nur Namen aus der Liste erlauben + SelectSymbol(aOldSymbols, aOldSymbols.GetText(), true); + else if (pComboBox == &aOldSymbolSets) + // nur Namen aus der Liste erlauben + SelectSymbolSet(aOldSymbolSets, aOldSymbolSets.GetText(), true); + else if (pComboBox == &aStyles) + // nur Namen aus der Liste erlauben (ist hier eh immer der Fall) + SelectStyle(aStyles.GetText(), true); + else + { +#if OSL_DEBUG_LEVEL > 1 + OSL_FAIL("Sm : wrong combobox argument"); +#endif + } + + pComboBox->SetSelection(aSelection); + + UpdateButtons(); + + return 0; +} + + +IMPL_LINK( SmSymDefineDialog, FontChangeHdl, ListBox *, EMPTYARG pListBox ) +{ + (void) pListBox; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pListBox == &aFonts, "Sm : wrong argument"); +#endif + + SelectFont(aFonts.GetSelectEntry()); + return 0; +} + + +IMPL_LINK( SmSymDefineDialog, SubsetChangeHdl, ListBox *, EMPTYARG pListBox ) +{ + (void) pListBox; + sal_uInt16 nPos = aFontsSubsetLB.GetSelectEntryPos(); + if (LISTBOX_ENTRY_NOTFOUND != nPos) + { + const Subset* pSubset = reinterpret_cast<const Subset*> (aFontsSubsetLB.GetEntryData( nPos )); + if (pSubset) + { + aCharsetDisplay.SelectCharacter( pSubset->GetRangeMin() ); + } + } + return 0; +} + + +IMPL_LINK( SmSymDefineDialog, StyleChangeHdl, ComboBox *, EMPTYARG pComboBox ) +{ + (void) pComboBox; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pComboBox == &aStyles, "Sm : falsches Argument"); +#endif + + SelectStyle(aStyles.GetText()); + return 0; +} + + +IMPL_LINK( SmSymDefineDialog, CharHighlightHdl, Control *, EMPTYARG ) +{ + sal_UCS4 cChar = aCharsetDisplay.GetSelectCharacter(); + +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE( pSubsetMap, "SubsetMap missing" ); +#endif + if (pSubsetMap) + { + const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar ); + if (pSubset) + aFontsSubsetLB.SelectEntry( pSubset->GetName() ); + else + aFontsSubsetLB.SetNoSelection(); + } + + aSymbolDisplay.SetSymbol( cChar, aCharsetDisplay.GetFont() ); + + UpdateButtons(); + + // display Unicode position as symbol name while iterating over characters + const String aHex( String::CreateFromInt64( cChar, 16 ).ToUpperAscii() ); + const String aPattern( A2OU( aHex.Len() > 4 ? "Ux000000" : "Ux0000" ) ); + String aUnicodePos( aPattern.Copy( 0, aPattern.Len() - aHex.Len() ) ); + aUnicodePos += aHex; + aSymbols.SetText( aUnicodePos ); + aSymbolName.SetText( aUnicodePos ); + + return 0; +} + + +IMPL_LINK( SmSymDefineDialog, AddClickHdl, Button *, EMPTYARG pButton ) +{ + (void) pButton; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pButton == &aAddBtn, "Sm : wrong argument"); + OSL_ENSURE(aAddBtn.IsEnabled(), "Sm : requirements met ??"); +#endif + + // add symbol + const SmSym aNewSymbol( aSymbols.GetText(), aCharsetDisplay.GetFont(), + aCharsetDisplay.GetSelectCharacter(), aSymbolSets.GetText() ); + //OSL_ENSURE( aSymbolMgrCopy.GetSymbolByName(aTmpSymbolName) == NULL, "symbol already exists" ); + aSymbolMgrCopy.AddOrReplaceSymbol( aNewSymbol ); + + // update display of new symbol + aSymbolDisplay.SetSymbol( &aNewSymbol ); + aSymbolName.SetText( aNewSymbol.GetName() ); + aSymbolSetName.SetText( aNewSymbol.GetSymbolSetName() ); + + // update list box entries + FillSymbolSets(aOldSymbolSets, false); + FillSymbolSets(aSymbolSets, false); + FillSymbols(aOldSymbols ,false); + FillSymbols(aSymbols ,false); + + UpdateButtons(); + + return 0; +} + + +IMPL_LINK( SmSymDefineDialog, ChangeClickHdl, Button *, EMPTYARG pButton ) +{ + (void) pButton; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pButton == &aChangeBtn, "Sm : wrong argument"); + OSL_ENSURE(aChangeBtn.IsEnabled(), "Sm : requirements met ??"); +#endif + + // get new Sybol to use + //! get font from symbol-disp lay since charset-display does not keep + //! the bold attribut. + const SmSym aNewSymbol( aSymbols.GetText(), aCharsetDisplay.GetFont(), + aCharsetDisplay.GetSelectCharacter(), aSymbolSets.GetText() ); + + // remove old symbol if the name was changed then add new one + const bool bNameChanged = aOldSymbols.GetText() != aSymbols.GetText(); + if (bNameChanged) + aSymbolMgrCopy.RemoveSymbol( aOldSymbols.GetText() ); + aSymbolMgrCopy.AddOrReplaceSymbol( aNewSymbol, true ); + + // clear display for original symbol if necessary + if (bNameChanged) + SetOrigSymbol(NULL, XubString()); + + // update display of new symbol + aSymbolDisplay.SetSymbol( &aNewSymbol ); + aSymbolName.SetText( aNewSymbol.GetName() ); + aSymbolSetName.SetText( aNewSymbol.GetSymbolSetName() ); + + // update list box entries + FillSymbolSets(aOldSymbolSets, false); + FillSymbolSets(aSymbolSets, false); + FillSymbols(aOldSymbols ,false); + FillSymbols(aSymbols ,false); + + UpdateButtons(); + + return 0; +} + + +IMPL_LINK( SmSymDefineDialog, DeleteClickHdl, Button *, EMPTYARG pButton ) +{ + (void) pButton; +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(pButton == &aDeleteBtn, "Sm : wrong argument"); + OSL_ENSURE(aDeleteBtn.IsEnabled(), "Sm : requirements met ??"); +#endif + + if (pOrigSymbol) + { + aSymbolMgrCopy.RemoveSymbol( pOrigSymbol->GetName() ); + + // clear display for original symbol + SetOrigSymbol(NULL, XubString()); + + // update list box entries + FillSymbolSets(aOldSymbolSets, false); + FillSymbolSets(aSymbolSets, false); + FillSymbols(aOldSymbols ,false); + FillSymbols(aSymbols ,false); + } + + UpdateButtons(); + + return 0; +} + + +void SmSymDefineDialog::UpdateButtons() +{ + bool bAdd = false, + bChange = false, + bDelete = false; + XubString aTmpSymbolName (aSymbols.GetText()), + aTmpSymbolSetName (aSymbolSets.GetText()); + + if (aTmpSymbolName.Len() > 0 && aTmpSymbolSetName.Len() > 0) + { + // alle Einstellungen gleich? + //! (Font-, Style- und SymbolSet Name werden nicht case sensitiv verglichen) + bool bEqual = pOrigSymbol + && aTmpSymbolSetName.EqualsIgnoreCaseAscii(aOldSymbolSetName.GetText()) + && aTmpSymbolName.Equals(pOrigSymbol->GetName()) + && aFonts.GetSelectEntry().EqualsIgnoreCaseAscii( + pOrigSymbol->GetFace().GetName()) + && aStyles.GetText().EqualsIgnoreCaseAscii( + GetFontStyles().GetStyleName(pOrigSymbol->GetFace())) + && aCharsetDisplay.GetSelectCharacter() == pOrigSymbol->GetCharacter(); + + // hinzufuegen nur wenn es noch kein Symbol desgleichen Namens gibt + bAdd = aSymbolMgrCopy.GetSymbolByName(aTmpSymbolName) == NULL; + + // loeschen nur wenn alle Einstellungen gleich sind + bDelete = pOrigSymbol != NULL; + + // aendern nur falls altes Symbol vorhanden und am neuen etwas anders ist + bChange = pOrigSymbol && !bEqual; + } + + aAddBtn .Enable(bAdd); + aChangeBtn.Enable(bChange); + aDeleteBtn.Enable(bDelete); +} + + +SmSymDefineDialog::SmSymDefineDialog(Window * pParent, + OutputDevice *pFntListDevice, SmSymbolManager &rMgr, bool bFreeRes) : + ModalDialog (pParent, SmResId(RID_SYMDEFINEDIALOG)), + aOldSymbolText (this, SmResId(1)), + aOldSymbols (this, SmResId(1)), + aOldSymbolSetText (this, SmResId(2)), + aOldSymbolSets (this, SmResId(2)), + aCharsetDisplay (this, SmResId(1)), + aSymbolText (this, SmResId(9)), + aSymbols (this, SmResId(4)), + aSymbolSetText (this, SmResId(10)), + aSymbolSets (this, SmResId(5)), + aFontText (this, SmResId(3)), + aFonts (this, SmResId(1)), + aFontsSubsetFT (this, SmResId( FT_FONTS_SUBSET )), + aFontsSubsetLB (this, SmResId( LB_FONTS_SUBSET )), + aStyleText (this, SmResId(4)), + aStyles (this, SmResId(3)), + aOldSymbolName (this, SmResId(7)), + aOldSymbolDisplay (this, SmResId(3)), + aOldSymbolSetName (this, SmResId(8)), + aSymbolName (this, SmResId(5)), + aSymbolDisplay (this, SmResId(2)), + aSymbolSetName (this, SmResId(6)), + aOkBtn (this, SmResId(1)), + aCancelBtn (this, SmResId(1)), + aAddBtn (this, SmResId(1)), + aChangeBtn (this, SmResId(2)), + aDeleteBtn (this, SmResId(3)), + aRightArrow (this, SmResId(1)), + aRigthArrow_Im (SmResId(1)), + rSymbolMgr (rMgr), + pSubsetMap (NULL), + pFontList (NULL) +{ + if (bFreeRes) + FreeResource(); + + pFontList = new FontList( pFntListDevice ); + + pOrigSymbol = 0; + + // auto completion is troublesome since that symbols character also gets automatically selected in the + // display and if the user previously selected a character to define/redefine that one this is bad + aOldSymbols.EnableAutocomplete( false, true ); + aSymbols .EnableAutocomplete( false, true ); + + FillFonts(); + if (aFonts.GetEntryCount() > 0) + SelectFont(aFonts.GetEntry(0)); + + InitColor_Impl(); + + SetSymbolSetManager(rSymbolMgr); + + aOldSymbols .SetSelectHdl(LINK(this, SmSymDefineDialog, OldSymbolChangeHdl)); + aOldSymbolSets .SetSelectHdl(LINK(this, SmSymDefineDialog, OldSymbolSetChangeHdl)); + aSymbolSets .SetModifyHdl(LINK(this, SmSymDefineDialog, ModifyHdl)); + aOldSymbolSets .SetModifyHdl(LINK(this, SmSymDefineDialog, ModifyHdl)); + aSymbols .SetModifyHdl(LINK(this, SmSymDefineDialog, ModifyHdl)); + aOldSymbols .SetModifyHdl(LINK(this, SmSymDefineDialog, ModifyHdl)); + aStyles .SetModifyHdl(LINK(this, SmSymDefineDialog, ModifyHdl)); + aFonts .SetSelectHdl(LINK(this, SmSymDefineDialog, FontChangeHdl)); + aFontsSubsetLB .SetSelectHdl(LINK(this, SmSymDefineDialog, SubsetChangeHdl)); + aStyles .SetSelectHdl(LINK(this, SmSymDefineDialog, StyleChangeHdl)); + aAddBtn .SetClickHdl (LINK(this, SmSymDefineDialog, AddClickHdl)); + aChangeBtn .SetClickHdl (LINK(this, SmSymDefineDialog, ChangeClickHdl)); + aDeleteBtn .SetClickHdl (LINK(this, SmSymDefineDialog, DeleteClickHdl)); + aCharsetDisplay.SetHighlightHdl( LINK( this, SmSymDefineDialog, CharHighlightHdl ) ); + + // preview like controls should have a 2D look + aOldSymbolDisplay.SetBorderStyle( WINDOW_BORDER_MONO ); + aSymbolDisplay .SetBorderStyle( WINDOW_BORDER_MONO ); +} + + +SmSymDefineDialog::~SmSymDefineDialog() +{ + delete pSubsetMap; + delete pOrigSymbol; +} + +void SmSymDefineDialog::InitColor_Impl() +{ +#if OSL_DEBUG_LEVEL > 1 + Color aBC( GetDisplayBackground().GetColor() ); +#endif + ColorData nBgCol = COL_WHITE, + nTxtCol = COL_BLACK; + bool bHighContrast = GetSettings().GetStyleSettings().GetHighContrastMode(); + if (bHighContrast) + { + const StyleSettings &rS = GetSettings().GetStyleSettings(); + nBgCol = rS.GetFieldColor().GetColor(); + nTxtCol = rS.GetFieldTextColor().GetColor(); + } + + Color aTmpColor( nBgCol ); + Wallpaper aWall( aTmpColor ); + Color aTxtColor( nTxtCol ); + aCharsetDisplay .SetBackground( aWall ); + aCharsetDisplay .SetTextColor( aTxtColor ); + aOldSymbolDisplay.SetBackground( aWall ); + aOldSymbolDisplay.SetTextColor( aTxtColor ); + aSymbolDisplay .SetBackground( aWall ); + aSymbolDisplay .SetTextColor( aTxtColor ); + + const Image &rArrowRight = aRigthArrow_Im; + aRightArrow.SetImage( rArrowRight ); +} + + +void SmSymDefineDialog::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( rDCEvt.GetType() == DATACHANGED_SETTINGS && + (rDCEvt.GetFlags() & SETTINGS_STYLE) ) + InitColor_Impl(); + + ModalDialog::DataChanged( rDCEvt ); +} + + +short SmSymDefineDialog::Execute() +{ + short nResult = ModalDialog::Execute(); + + // Aenderungen uebernehmen falls Dialog mit OK beendet wurde + if (aSymbolMgrCopy.IsModified() && nResult == RET_OK) + rSymbolMgr = aSymbolMgrCopy; + + return nResult; +} + + +void SmSymDefineDialog::SetSymbolSetManager(const SmSymbolManager &rMgr) +{ + aSymbolMgrCopy = rMgr; + + // Das modified Flag der Kopie auf false setzen, damit man spaeter damit + // testen kann ob sich was geaendert hat. + aSymbolMgrCopy.SetModified(false); + + FillSymbolSets(aOldSymbolSets); + if (aOldSymbolSets.GetEntryCount() > 0) + SelectSymbolSet(aOldSymbolSets.GetEntry(0)); + FillSymbolSets(aSymbolSets); + if (aSymbolSets.GetEntryCount() > 0) + SelectSymbolSet(aSymbolSets.GetEntry(0)); + FillSymbols(aOldSymbols); + if (aOldSymbols.GetEntryCount() > 0) + SelectSymbol(aOldSymbols.GetEntry(0)); + FillSymbols(aSymbols); + if (aSymbols.GetEntryCount() > 0) + SelectSymbol(aSymbols.GetEntry(0)); + + UpdateButtons(); +} + + +bool SmSymDefineDialog::SelectSymbolSet(ComboBox &rComboBox, + const XubString &rSymbolSetName, bool bDeleteText) +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(&rComboBox == &aOldSymbolSets || &rComboBox == &aSymbolSets, + "Sm : wrong ComboBox"); +#endif + + // 'Normalisieren' des SymbolNamens (ohne leading und trailing Leerzeichen) + XubString aNormName (rSymbolSetName); + aNormName.EraseLeadingChars(' '); + aNormName.EraseTrailingChars(' '); + // und evtl Abweichungen in der Eingabe beseitigen + rComboBox.SetText(aNormName); + + bool bRet = false; + sal_uInt16 nPos = rComboBox.GetEntryPos(aNormName); + + if (nPos != COMBOBOX_ENTRY_NOTFOUND) + { + rComboBox.SetText(rComboBox.GetEntry(nPos)); + bRet = true; + } + else if (bDeleteText) + rComboBox.SetText(XubString()); + + bool bIsOld = &rComboBox == &aOldSymbolSets; + + // setzen des SymbolSet Namens an der zugehoerigen Darstellung + FixedText &rFT = bIsOld ? aOldSymbolSetName : aSymbolSetName; + rFT.SetText(rComboBox.GetText()); + + // setzen der zum SymbolSet gehoerenden Symbol Namen an der zugehoerigen + // Auswahbox + ComboBox &rCB = bIsOld ? aOldSymbols : aSymbols; + FillSymbols(rCB, false); + + // bei Wechsel des SymbolSets fuer das alte Zeichen ein gueltiges + // Symbol bzw keins zur Anzeige bringen + if (bIsOld) + { + XubString aTmpOldSymbolName; + if (aOldSymbols.GetEntryCount() > 0) + aTmpOldSymbolName = aOldSymbols.GetEntry(0); + SelectSymbol(aOldSymbols, aTmpOldSymbolName, true); + } + + UpdateButtons(); + + return bRet; +} + + +void SmSymDefineDialog::SetOrigSymbol(const SmSym *pSymbol, + const XubString &rSymbolSetName) +{ + // clear old symbol + delete pOrigSymbol; + pOrigSymbol = 0; + + XubString aSymName, + aSymSetName; + if (pSymbol) + { + // set new symbol + pOrigSymbol = new SmSym( *pSymbol ); + + aSymName = pSymbol->GetName(); + aSymSetName = rSymbolSetName; + aOldSymbolDisplay.SetSymbol( pSymbol ); + } + else + { // loeschen des angezeigten Symbols + aOldSymbolDisplay.SetText(XubString()); + aOldSymbolDisplay.Invalidate(); + } + aOldSymbolName .SetText(aSymName); + aOldSymbolSetName.SetText(aSymSetName); +} + + +bool SmSymDefineDialog::SelectSymbol(ComboBox &rComboBox, + const XubString &rSymbolName, bool bDeleteText) +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE(&rComboBox == &aOldSymbols || &rComboBox == &aSymbols, + "Sm : wrong ComboBox"); +#endif + + // 'Normalisieren' des SymbolNamens (ohne Leerzeichen) + XubString aNormName (rSymbolName); + aNormName.EraseAllChars(' '); + // und evtl Abweichungen in der Eingabe beseitigen + rComboBox.SetText(aNormName); + + bool bRet = false; + sal_uInt16 nPos = rComboBox.GetEntryPos(aNormName); + + bool bIsOld = &rComboBox == &aOldSymbols; + + if (nPos != COMBOBOX_ENTRY_NOTFOUND) + { + rComboBox.SetText(rComboBox.GetEntry(nPos)); + + if (!bIsOld) + { + const SmSym *pSymbol = GetSymbol(aSymbols); + if (pSymbol) + { + // Font und Style entsprechend waehlen + const Font &rFont = pSymbol->GetFace(); + SelectFont(rFont.GetName(), false); + SelectStyle(GetFontStyles().GetStyleName(rFont), false); + + // da das setzen des Fonts ueber den Style Namen des SymbolsFonts nicht + // so gut klappt (er kann zB leer sein obwohl der Font selbst 'bold' und + // 'italic' ist!). Setzen wir hier den Font wie er zum Symbol gehoert + // zu Fuss. + aCharsetDisplay.SetFont(rFont); + aSymbolDisplay.SetFont(rFont); + + // das zugehoerige Zeichen auswaehlen + SelectChar(pSymbol->GetCharacter()); + + // since SelectChar will also set the unicode point as text in the + // symbols box, we have to set the symbol name again to get that one displayed + aSymbols.SetText( pSymbol->GetName() ); + } + } + + bRet = true; + } + else if (bDeleteText) + rComboBox.SetText(XubString()); + + if (bIsOld) + { + // bei Wechsel des alten Symbols nur vorhandene anzeigen sonst keins + const SmSym *pOldSymbol = NULL; + XubString aTmpOldSymbolSetName; + if (nPos != COMBOBOX_ENTRY_NOTFOUND) + { + pOldSymbol = aSymbolMgrCopy.GetSymbolByName(aNormName); + aTmpOldSymbolSetName = aOldSymbolSets.GetText(); + } + SetOrigSymbol(pOldSymbol, aTmpOldSymbolSetName); + } + else + aSymbolName.SetText(rComboBox.GetText()); + + UpdateButtons(); + + return bRet; +} + + +void SmSymDefineDialog::SetFont(const XubString &rFontName, const XubString &rStyleName) +{ + // Font (FontInfo) passend zu Namen und Style holen + FontInfo aFI; + if (pFontList) + aFI = pFontList->Get(rFontName, WEIGHT_NORMAL, ITALIC_NONE); + SetFontStyle(rStyleName, aFI); + + aCharsetDisplay.SetFont(aFI); + aSymbolDisplay.SetFont(aFI); + + // update subset listbox for new font's unicode subsets + FontCharMap aFontCharMap; + aCharsetDisplay.GetFontCharMap( aFontCharMap ); + if (pSubsetMap) + delete pSubsetMap; + pSubsetMap = new SubsetMap( &aFontCharMap ); + + aFontsSubsetLB.Clear(); + bool bFirst = true; + const Subset* pSubset; + while( NULL != (pSubset = pSubsetMap->GetNextSubset( bFirst )) ) + { + sal_uInt16 nPos = aFontsSubsetLB.InsertEntry( pSubset->GetName()); + aFontsSubsetLB.SetEntryData( nPos, (void *) pSubset ); + // subset must live at least as long as the selected font !!! + if( bFirst ) + aFontsSubsetLB.SelectEntryPos( nPos ); + bFirst = false; + } + if( bFirst ) + aFontsSubsetLB.SetNoSelection(); + aFontsSubsetLB.Enable( !bFirst ); +} + + +bool SmSymDefineDialog::SelectFont(const XubString &rFontName, bool bApplyFont) +{ + bool bRet = false; + sal_uInt16 nPos = aFonts.GetEntryPos(rFontName); + + if (nPos != LISTBOX_ENTRY_NOTFOUND) + { + aFonts.SelectEntryPos(nPos); + if (aStyles.GetEntryCount() > 0) + SelectStyle(aStyles.GetEntry(0)); + if (bApplyFont) + { + SetFont(aFonts.GetSelectEntry(), aStyles.GetText()); + bRet = true; + aSymbolDisplay.SetSymbol( aCharsetDisplay.GetSelectCharacter(), aCharsetDisplay.GetFont() ); + } + bRet = sal_True; + } + else + aFonts.SetNoSelection(); + FillStyles(); + + UpdateButtons(); + + return bRet; +} + + +bool SmSymDefineDialog::SelectStyle(const XubString &rStyleName, bool bApplyFont) +{ + bool bRet = false; + sal_uInt16 nPos = aStyles.GetEntryPos(rStyleName); + + // falls der Style nicht zur Auswahl steht nehmen wir den erst moeglichen + // (sofern vorhanden) + if (nPos == COMBOBOX_ENTRY_NOTFOUND && aStyles.GetEntryCount() > 0) + nPos = 0; + + if (nPos != COMBOBOX_ENTRY_NOTFOUND) + { + aStyles.SetText(aStyles.GetEntry(nPos)); + if (bApplyFont) + { + SetFont(aFonts.GetSelectEntry(), aStyles.GetText()); + bRet = true; + aSymbolDisplay.SetSymbol( aCharsetDisplay.GetSelectCharacter(), aCharsetDisplay.GetFont() ); + } + bRet = sal_True; + } + else + aStyles.SetText(XubString()); + + UpdateButtons(); + + return bRet; +} + + +void SmSymDefineDialog::SelectChar(xub_Unicode cChar) +{ + aCharsetDisplay.SelectCharacter( cChar ); + aSymbolDisplay.SetSymbol( cChar, aCharsetDisplay.GetFont() ); + + UpdateButtons(); +} + + +/**************************************************************************/ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/dialog.hrc b/starmath/source/dialog.hrc new file mode 100755 index 000000000000..9e3e58493ab3 --- /dev/null +++ b/starmath/source/dialog.hrc @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DIALOG_HRC_ +#define _DIALOG_HRC_ + + +#define FL_PRINTOPTIONS 10 +#define CB_TITLEROW 11 +#define CB_EQUATION_TEXT 12 +#define CB_FRAME 13 + +#define FL_PRINT_FORMAT 20 +#define RB_ORIGINAL_SIZE 21 +#define RB_FIT_TO_PAGE 22 +#define RB_ZOOM 23 +#define MF_ZOOM 24 + +#define FL_MISC_OPTIONS 30 +#define CB_IGNORE_SPACING 31 +#define CB_SAVE_ONLY_USED_SYMBOLS 32 + +#define FT_FONTS_SUBSET 110 +#define LB_FONTS_SUBSET 111 + + +#endif + diff --git a/starmath/source/document.cxx b/starmath/source/document.cxx new file mode 100644 index 000000000000..90da132a385a --- /dev/null +++ b/starmath/source/document.cxx @@ -0,0 +1,1449 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/uno/Any.h> + +#include <comphelper/accessibletexthelper.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/storagehelper.hxx> +#include <rtl/logfile.hxx> +#include <rtl/ustring.hxx> +#include <unotools/eventcfg.hxx> +#include <sfx2/event.hxx> +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/fcontnr.hxx> +#include <sfx2/msg.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sot/clsids.hxx> +#include <sot/exchange.hxx> +#include <sot/formats.hxx> +#include <sot/storage.hxx> +#include <svl/eitem.hxx> +#include <svl/fstathelper.hxx> +#include <svl/intitem.hxx> +#include <svl/itempool.hxx> +#include <unotools/lingucfg.hxx> +#include <unotools/linguprops.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/ptitem.hxx> +#include <svtools/sfxecode.hxx> +#include <svl/slstitm.hxx> +#include <svl/smplhint.hxx> +#include <svl/stritem.hxx> +#include <svtools/transfer.hxx> +#include <svl/undo.hxx> +#include <svl/urihelper.hxx> +#include <svl/whiter.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editstat.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/unolingu.hxx> +#include <ucbhelper/content.hxx> +#include <vcl/mapmod.hxx> +#include <tools/mapunit.hxx> +#include <vcl/msgbox.hxx> +#include <sfx2/sfx.hrc> +#include <document.hxx> +#include <action.hxx> +#include <config.hxx> +#include <dialog.hxx> +#include <format.hxx> +#include <smdll.hxx> +#include <starmath.hrc> +#include <symbol.hxx> +#include <toolbox.hxx> +#include <unomodel.hxx> +#include <utility.hxx> +#include <view.hxx> +#include "mathtype.hxx" +#include "ooxml.hxx" +#include "mathmlimport.hxx" +#include "mathmlexport.hxx" +#include <sfx2/sfxsids.hrc> +#include <svx/svxids.hrc> +#include "cursor.hxx" +#include <tools/diagnose_ex.h> +#include "visitors.hxx" +#include "accessibility.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::uno; + + +#define DOCUMENT_BUFFER_SIZE (sal_uInt16)32768 + +static const char pStarMathDoc[] = "StarMathDocument"; + +#define SmDocShell +#include "smslots.hxx" + +//////////////////////////////////////////////////////////// + + +TYPEINIT1( SmDocShell, SfxObjectShell ); + +SFX_IMPL_INTERFACE(SmDocShell, SfxObjectShell, SmResId(0)) +{ + SFX_POPUPMENU_REGISTRATION(SmResId(RID_VIEWMENU)); + SFX_POPUPMENU_REGISTRATION(SmResId(RID_COMMANDMENU)); +} + +SFX_IMPL_OBJECTFACTORY(SmDocShell, SvGlobalName(SO3_SM_CLASSID), SFXOBJECTSHELL_STD_NORMAL, "smath" ) + +void SmDocShell::SFX_NOTIFY(SfxBroadcaster&, const TypeId&, + const SfxHint& rHint, const TypeId&) +{ + switch (((SfxSimpleHint&)rHint).GetId()) + { + case HINT_FORMATCHANGED: + SetFormulaArranged(false); + + nModifyCount++; //! see comment for SID_GAPHIC_SM in SmDocShell::GetState + + Repaint(); + break; + } +} + +void SmDocShell::LoadSymbols() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::LoadSymbols" ); + + SmModule *pp = SM_MOD(); + pp->GetSymbolManager().Load(); +} + + +const String SmDocShell::GetComment() const +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::GetComment" ); + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + const_cast<SmDocShell*>(this)->GetModel(), uno::UNO_QUERY_THROW); + uno::Reference<document::XDocumentProperties> xDocProps( + xDPS->getDocumentProperties()); + return xDocProps->getDescription(); +} + + +void SmDocShell::SetText(const String& rBuffer) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SetText" ); + + if (rBuffer != aText) + { + bool bIsEnabled = IsEnableSetModified(); + if( bIsEnabled ) + EnableSetModified( false ); + + aText = rBuffer; + SetFormulaArranged( false ); + + Parse(); + + SmViewShell *pViewSh = SmGetActiveView(); + if( pViewSh ) + { + pViewSh->GetViewFrame()->GetBindings().Invalidate(SID_TEXT); + if ( SFX_CREATE_MODE_EMBEDDED == GetCreateMode() ) + { + // have SwOleClient::FormatChanged() to align the modified formula properly + // even if the vis area does not change (e.g. when formula text changes from + // "{a over b + c} over d" to "d over {a over b + c}" + SFX_APP()->NotifyEvent(SfxEventHint( SFX_EVENT_VISAREACHANGED, GlobalEventConfig::GetEventName(STR_EVENT_VISAREACHANGED), this)); + + Repaint(); + } + else + pViewSh->GetGraphicWindow().Invalidate(); + } + + if ( bIsEnabled ) + EnableSetModified( bIsEnabled ); + SetModified(true); + + // launch accessible event if necessary + SmGraphicAccessible *pAcc = pViewSh ? pViewSh->GetGraphicWindow().GetAccessible_Impl() : 0; + if (pAcc) + { + Any aOldValue, aNewValue; + if ( comphelper::OCommonAccessibleText::implInitTextChangedEvent( aText, rBuffer, aOldValue, aNewValue ) ) + { + pAcc->LaunchEvent( AccessibleEventId::TEXT_CHANGED, + aOldValue, aNewValue ); + } + } + + if ( GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + OnDocumentPrinterChanged(0); + } +} + +void SmDocShell::SetFormat(SmFormat& rFormat) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SetFormat" ); + + aFormat = rFormat; + SetFormulaArranged( false ); + SetModified( true ); + + nModifyCount++; //! see comment for SID_GAPHIC_SM in SmDocShell::GetState + + // don't use SmGetActiveView since the view shell might not be active (0 pointer) + // if for example the Basic Macro dialog currently has the focus. Thus: + SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this ); + while (pFrm) + { + pFrm->GetBindings().Invalidate(SID_GAPHIC_SM); + pFrm = SfxViewFrame::GetNext( *pFrm, this ); + } +} + +String SmDocShell::GetAccessibleText() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::GetAccessibleText" ); + + if (!IsFormulaArranged()) + ArrangeFormula(); + if (0 == aAccText.Len()) + { + OSL_ENSURE( pTree, "Tree missing" ); + if (pTree) + pTree->GetAccessibleText( aAccText ); + } + return aAccText; +} + +void SmDocShell::Parse() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::Parse" ); + + if (pTree) + delete pTree; + ReplaceBadChars(); + pTree = aInterpreter.Parse(aText); + nModifyCount++; //! see comment for SID_GAPHIC_SM in SmDocShell::GetState + SetFormulaArranged( false ); + InvalidateCursor(); + aUsedSymbols = aInterpreter.GetUsedSymbols(); +} + + +void SmDocShell::ArrangeFormula() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::ArrangeFormula" ); + + if (IsFormulaArranged()) + return; + + //! Nur f�r die Dauer der Existenz dieses Objekts sind am Drucker die + //! richtigen Einstellungen garantiert. + SmPrinterAccess aPrtAcc(*this); + OutputDevice* pOutDev = aPrtAcc.GetRefDev(); + + if (!pOutDev) + { +#if OSL_DEBUG_LEVEL > 1 + OSL_FAIL("!! SmDocShell::ArrangeFormula: reference device missing !!"); +#endif + } + + // falls n�tig ein anderes OutputDevice holen f�r das formatiert wird + if (!pOutDev) + { + SmViewShell *pView = SmGetActiveView(); + if (pView) + pOutDev = &pView->GetGraphicWindow(); + else + { + pOutDev = &SM_MOD()->GetDefaultVirtualDev(); + pOutDev->SetMapMode( MapMode(MAP_100TH_MM) ); + } + } + OSL_ENSURE(pOutDev->GetMapMode().GetMapUnit() == MAP_100TH_MM, + "Sm : falscher MapMode"); + + const SmFormat &rFormat = GetFormat(); + pTree->Prepare(rFormat, *this); + + // format/draw formulas always from left to right, + // and numbers should not be converted + sal_uLong nLayoutMode = pOutDev->GetLayoutMode(); + pOutDev->SetLayoutMode( TEXT_LAYOUT_BIDI_LTR ); + sal_Int16 nDigitLang = pOutDev->GetDigitLanguage(); + pOutDev->SetDigitLanguage( LANGUAGE_ENGLISH ); + // + pTree->Arrange(*pOutDev, rFormat); + // + pOutDev->SetLayoutMode( nLayoutMode ); + pOutDev->SetDigitLanguage( nDigitLang ); + + SetFormulaArranged(true); + + // invalidate accessible text + aAccText = String(); +} + + +void SetEditEngineDefaultFonts(SfxItemPool &rEditEngineItemPool) +{ + // + // set fonts to be used + // + SvtLinguOptions aOpt; + SvtLinguConfig().GetOptions( aOpt ); + // + struct FontDta { + sal_Int16 nFallbackLang; + sal_Int16 nLang; + sal_uInt16 nFontType; + sal_uInt16 nFontInfoId; + } aTable[3] = + { + // info to get western font to be used + { LANGUAGE_ENGLISH_US, LANGUAGE_NONE, + DEFAULTFONT_FIXED, EE_CHAR_FONTINFO }, + // info to get CJK font to be used + { LANGUAGE_JAPANESE, LANGUAGE_NONE, + DEFAULTFONT_CJK_TEXT, EE_CHAR_FONTINFO_CJK }, + // info to get CTL font to be used + { LANGUAGE_ARABIC_SAUDI_ARABIA, LANGUAGE_NONE, + DEFAULTFONT_CTL_TEXT, EE_CHAR_FONTINFO_CTL } + }; + aTable[0].nLang = aOpt.nDefaultLanguage; + aTable[1].nLang = aOpt.nDefaultLanguage_CJK; + aTable[2].nLang = aOpt.nDefaultLanguage_CTL; + // + for (int i = 0; i < 3; ++i) + { + const FontDta &rFntDta = aTable[i]; + LanguageType nLang = (LANGUAGE_NONE == rFntDta.nLang) ? + rFntDta.nFallbackLang : rFntDta.nLang; + Font aFont = Application::GetDefaultDevice()->GetDefaultFont( + rFntDta.nFontType, nLang, DEFAULTFONT_FLAGS_ONLYONE ); + rEditEngineItemPool.SetPoolDefaultItem( + SvxFontItem( aFont.GetFamily(), aFont.GetName(), + aFont.GetStyleName(), aFont.GetPitch(), aFont.GetCharSet(), + rFntDta.nFontInfoId ) ); + } + + // set font heights + SvxFontHeightItem aFontHeigt( + Application::GetDefaultDevice()->LogicToPixel( + Size( 0, 11 ), MapMode( MAP_POINT ) ).Height(), 100, + EE_CHAR_FONTHEIGHT ); + rEditEngineItemPool.SetPoolDefaultItem( aFontHeigt ); + aFontHeigt.SetWhich( EE_CHAR_FONTHEIGHT_CJK ); + rEditEngineItemPool.SetPoolDefaultItem( aFontHeigt ); + aFontHeigt.SetWhich( EE_CHAR_FONTHEIGHT_CTL ); + rEditEngineItemPool.SetPoolDefaultItem( aFontHeigt ); +} + + +EditEngine& SmDocShell::GetEditEngine() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::GetEditEngine" ); + + if (!pEditEngine) + { + //! + //! see also SmEditWindow::DataChanged ! + //! + + pEditEngineItemPool = EditEngine::CreatePool(); + + SetEditEngineDefaultFonts(*pEditEngineItemPool); + + pEditEngine = new EditEngine( pEditEngineItemPool ); + + pEditEngine->EnableUndo( true ); + pEditEngine->SetDefTab( sal_uInt16( + Application::GetDefaultDevice()->GetTextWidth( C2S("XXXX") ) ) ); + + pEditEngine->SetControlWord( + (pEditEngine->GetControlWord() | EE_CNTRL_AUTOINDENTING) & + (~EE_CNTRL_UNDOATTRIBS) & + (~EE_CNTRL_PASTESPECIAL) ); + + pEditEngine->SetWordDelimiters( C2S(" .=+-*/(){}[];\"" ) ); + pEditEngine->SetRefMapMode( MAP_PIXEL ); + + pEditEngine->SetPaperSize( Size( 800, 0 ) ); + + pEditEngine->EraseVirtualDevice(); + + // set initial text if the document already has some... + // (may be the case when reloading a doc) + String aTxt( GetText() ); + if (aTxt.Len()) + pEditEngine->SetText( aTxt ); + + pEditEngine->ClearModifyFlag(); + + } + return *pEditEngine; +} + + +SfxItemPool& SmDocShell::GetEditEngineItemPool() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::GetEditEngineItemPool" ); + + if (!pEditEngineItemPool) + GetEditEngine(); + OSL_ENSURE( pEditEngineItemPool, "EditEngineItemPool missing" ); + return *pEditEngineItemPool; +} + +void SmDocShell::DrawFormula(OutputDevice &rDev, Point &rPosition, bool bDrawSelection) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::Draw" ); + + if (!pTree) + Parse(); + OSL_ENSURE(pTree, "Sm : NULL pointer"); + + if (!IsFormulaArranged()) + ArrangeFormula(); + + //Problem: Was passiert mit dem WYSIWYG? Wir haben waehrend wir inplace aktiv + //sind kein Referenzdevice und sind auch nicht darauf ausgerichtet. Es kann + //also jetzt eine Differenz zwischen der VisArea (spricht die Groesse im Client) + //und der jetzt vorliegenden Groese geben. + //Idee: Die Differenz koennte, zumindest behelfsmaessig, mit SmNod::SetSize + //angepasst werden. + + rPosition.X() += aFormat.GetDistance( DIS_LEFTSPACE ); + rPosition.Y() += aFormat.GetDistance( DIS_TOPSPACE ); + + //! in case of high contrast-mode (accessibility option!) + //! the draw mode needs to be set to default, because when imbedding + //! Math for example in Calc in "a over b" the fraction bar may not + //! be visible else. More generally: the FillColor may have been changed. + sal_uLong nOldDrawMode = DRAWMODE_DEFAULT; + bool bRestoreDrawMode = false; + if (OUTDEV_WINDOW == rDev.GetOutDevType() && + ((Window &) rDev).GetSettings().GetStyleSettings().GetHighContrastMode()) + { + nOldDrawMode = rDev.GetDrawMode(); + rDev.SetDrawMode( DRAWMODE_DEFAULT ); + bRestoreDrawMode = true; + } + + // format/draw formulas always from left to right + // and numbers should not be converted + sal_uLong nLayoutMode = rDev.GetLayoutMode(); + rDev.SetLayoutMode( TEXT_LAYOUT_BIDI_LTR ); + sal_Int16 nDigitLang = rDev.GetDigitLanguage(); + rDev.SetDigitLanguage( LANGUAGE_ENGLISH ); + + //Set selection if any + if(pCursor && bDrawSelection){ + pCursor->AnnotateSelection(); + SmSelectionDrawingVisitor(rDev, pTree, rPosition); + } + + //Drawing using visitor + SmDrawingVisitor(rDev, rPosition, pTree); + + // + rDev.SetLayoutMode( nLayoutMode ); + rDev.SetDigitLanguage( nDigitLang ); + + if (bRestoreDrawMode) + rDev.SetDrawMode( nOldDrawMode ); +} + + + +Size SmDocShell::GetSize() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::GetSize" ); + + Size aRet; + + if (!pTree) + Parse(); + + if (pTree) + { + if (!IsFormulaArranged()) + ArrangeFormula(); + aRet = pTree->GetSize(); + + if ( !aRet.Width() ) + aRet.Width() = 2000; + else + aRet.Width() += aFormat.GetDistance( DIS_LEFTSPACE ) + + aFormat.GetDistance( DIS_RIGHTSPACE ); + if ( !aRet.Height() ) + aRet.Height() = 1000; + else + aRet.Height() += aFormat.GetDistance( DIS_TOPSPACE ) + + aFormat.GetDistance( DIS_BOTTOMSPACE ); + } + + return aRet; +} + +void SmDocShell::InvalidateCursor(){ + delete pCursor; + pCursor = NULL; +} + +SmCursor& SmDocShell::GetCursor(){ + if(!pCursor) + pCursor = new SmCursor(pTree, this); + return *pCursor; +} + +//////////////////////////////////////// + +SmPrinterAccess::SmPrinterAccess( SmDocShell &rDocShell ) +{ + if ( 0 != (pPrinter = rDocShell.GetPrt()) ) + { + pPrinter->Push( PUSH_MAPMODE ); + if ( SFX_CREATE_MODE_EMBEDDED == rDocShell.GetCreateMode() ) + { + // if it is an embedded object (without it's own printer) + // we change the MapMode temporarily. + //!If it is a document with it's own printer the MapMode should + //!be set correct (once) elsewhere(!), in order to avoid numerous + //!superfluous pushing and poping of the MapMode when using + //!this class. + + const MapUnit eOld = pPrinter->GetMapMode().GetMapUnit(); + if ( MAP_100TH_MM != eOld ) + { + MapMode aMap( pPrinter->GetMapMode() ); + aMap.SetMapUnit( MAP_100TH_MM ); + Point aTmp( aMap.GetOrigin() ); + aTmp.X() = OutputDevice::LogicToLogic( aTmp.X(), eOld, MAP_100TH_MM ); + aTmp.Y() = OutputDevice::LogicToLogic( aTmp.Y(), eOld, MAP_100TH_MM ); + aMap.SetOrigin( aTmp ); + pPrinter->SetMapMode( aMap ); + } + } + } + if ( 0 != (pRefDev = rDocShell.GetRefDev()) && pPrinter != pRefDev ) + { + pRefDev->Push( PUSH_MAPMODE ); + if ( SFX_CREATE_MODE_EMBEDDED == rDocShell.GetCreateMode() ) + { + // if it is an embedded object (without it's own printer) + // we change the MapMode temporarily. + //!If it is a document with it's own printer the MapMode should + //!be set correct (once) elsewhere(!), in order to avoid numerous + //!superfluous pushing and poping of the MapMode when using + //!this class. + + const MapUnit eOld = pRefDev->GetMapMode().GetMapUnit(); + if ( MAP_100TH_MM != eOld ) + { + MapMode aMap( pRefDev->GetMapMode() ); + aMap.SetMapUnit( MAP_100TH_MM ); + Point aTmp( aMap.GetOrigin() ); + aTmp.X() = OutputDevice::LogicToLogic( aTmp.X(), eOld, MAP_100TH_MM ); + aTmp.Y() = OutputDevice::LogicToLogic( aTmp.Y(), eOld, MAP_100TH_MM ); + aMap.SetOrigin( aTmp ); + pRefDev->SetMapMode( aMap ); + } + } + } +} + +SmPrinterAccess::~SmPrinterAccess() +{ + if ( pPrinter ) + pPrinter->Pop(); + if ( pRefDev && pRefDev != pPrinter ) + pRefDev->Pop(); +} + +//////////////////////////////////////// + +Printer* SmDocShell::GetPrt() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::GetPrt" ); + + if ( SFX_CREATE_MODE_EMBEDDED == GetCreateMode() ) + { + //Normalerweise wird der Printer vom Server besorgt. Wenn dieser aber + //keinen liefert (weil etwa noch keine connection da ist), kann es + //dennoch sein, dass wir den Printer kennen, denn dieser wird in + //OnDocumentPrinterChanged vom Server durchgereicht und dann temporaer + //festgehalten. + Printer *pPrt = GetDocumentPrinter(); + if ( !pPrt && pTmpPrinter ) + pPrt = pTmpPrinter; + return pPrt; + } + else if ( !pPrinter ) + { + SfxItemSet *pOptions = + new SfxItemSet(GetPool(), + SID_PRINTSIZE, SID_PRINTSIZE, + SID_PRINTZOOM, SID_PRINTZOOM, + SID_PRINTTITLE, SID_PRINTTITLE, + SID_PRINTTEXT, SID_PRINTTEXT, + SID_PRINTFRAME, SID_PRINTFRAME, + SID_NO_RIGHT_SPACES, SID_NO_RIGHT_SPACES, + 0); + + SmModule *pp = SM_MOD(); + pp->GetConfig()->ConfigToItemSet(*pOptions); + pPrinter = new SfxPrinter(pOptions); + pPrinter->SetMapMode( MapMode(MAP_100TH_MM) ); + } + return pPrinter; +} + +OutputDevice* SmDocShell::GetRefDev() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::GetRefDev" ); + + if ( SFX_CREATE_MODE_EMBEDDED == GetCreateMode() ) + { + OutputDevice* pOutDev = GetDocumentRefDev(); + if ( pOutDev ) + return pOutDev; + } + + return GetPrt(); +} + + +void SmDocShell::SetPrinter( SfxPrinter *pNew ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SetPrinter" ); + + delete pPrinter; + pPrinter = pNew; //Eigentumsuebergang! + pPrinter->SetMapMode( MapMode(MAP_100TH_MM) ); + SetFormulaArranged(false); + Repaint(); +} + +void SmDocShell::OnDocumentPrinterChanged( Printer *pPrt ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::OnDocumentPrinterChanged" ); + + pTmpPrinter = pPrt; + SetFormulaArranged(false); + Size aOldSize = GetVisArea().GetSize(); + Repaint(); + if( aOldSize != GetVisArea().GetSize() && aText.Len() ) + SetModified( true ); + pTmpPrinter = 0; +} + +void SmDocShell::Repaint() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::Repaint" ); + + bool bIsEnabled = IsEnableSetModified(); + if ( bIsEnabled ) + EnableSetModified( false ); + + SetFormulaArranged( false ); + + Size aVisSize = GetSize(); + SetVisAreaSize( aVisSize ); + SmViewShell *pViewSh = SmGetActiveView(); + if (pViewSh) + pViewSh->GetGraphicWindow().Invalidate(); + + if ( bIsEnabled ) + EnableSetModified( bIsEnabled ); +} + + +SmDocShell::SmDocShell( const sal_uInt64 i_nSfxCreationFlags ) : + SfxObjectShell( i_nSfxCreationFlags ), + pTree ( 0 ), + pEditEngineItemPool ( 0 ), + pEditEngine ( 0 ), + pPrinter ( 0 ), + pTmpPrinter ( 0 ), + nModifyCount ( 0 ), + bIsFormulaArranged ( false ) +{ + pCursor = NULL; + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SmDocShell" ); + + SetPool(&SFX_APP()->GetPool()); + + SmModule *pp = SM_MOD(); + aFormat = pp->GetConfig()->GetStandardFormat(); + + StartListening(aFormat); + StartListening(*pp->GetConfig()); + + SetBaseModel( new SmModel(this) ); +} + + + +SmDocShell::~SmDocShell() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::~SmDocShell" ); + + SmModule *pp = SM_MOD(); + + EndListening(aFormat); + EndListening(*pp->GetConfig()); + + + if(pCursor) + delete pCursor; + pCursor = NULL; + + delete pEditEngine; + SfxItemPool::Free(pEditEngineItemPool); + delete pTree; + delete pPrinter; +} + + +sal_Bool SmDocShell::SetData( const String& rData ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SetData" ); + + SetText( rData ); + return true; +} + + +sal_Bool SmDocShell::ConvertFrom(SfxMedium &rMedium) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::ConvertFrom" ); + + bool bSuccess = false; + const String& rFltName = rMedium.GetFilter()->GetFilterName(); + + OSL_ENSURE( !rFltName.EqualsAscii( STAROFFICE_XML ), "Wrong filter!"); + + if ( rFltName.EqualsAscii( MATHML_XML ) ) + { + if (pTree) + { + delete pTree; + pTree = 0; + InvalidateCursor(); + } + Reference<com::sun::star::frame::XModel> xModel(GetModel()); + SmXMLImportWrapper aEquation(xModel); + bSuccess = 0 == aEquation.Import(rMedium); + } + else + { + SvStream *pStream = rMedium.GetInStream(); + if ( pStream ) + { + if ( SotStorage::IsStorageFile( pStream ) ) + { + SvStorageRef aStorage = new SotStorage( pStream, false ); + if ( aStorage->IsStream( C2S( "Equation Native" ) ) ) + { + // is this a MathType Storage? + MathType aEquation( aText ); + if ( true == (bSuccess = (1 == aEquation.Parse( aStorage )) )) + Parse(); + } + } + } + } + + if ( GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + { + SetFormulaArranged( false ); + Repaint(); + } + + FinishedLoading( SFX_LOADED_ALL ); + return bSuccess; +} + + +sal_Bool SmDocShell::InitNew( const uno::Reference < embed::XStorage >& xStorage ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::InitNew" ); + + bool bRet = false; + if ( SfxObjectShell::InitNew( xStorage ) ) + { + bRet = true; + SetVisArea(Rectangle(Point(0, 0), Size(2000, 1000))); + } + return bRet; +} + + +sal_Bool SmDocShell::Load( SfxMedium& rMedium ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::Load" ); + + bool bRet = false; + if( SfxObjectShell::Load( rMedium )) + { + uno::Reference < embed::XStorage > xStorage = GetMedium()->GetStorage(); + uno::Reference < container::XNameAccess > xAccess (xStorage, uno::UNO_QUERY); + if ( + ( + xAccess->hasByName( C2S( "content.xml" ) ) && + xStorage->isStreamElement( C2S( "content.xml" ) ) + ) || + ( + xAccess->hasByName( C2S( "Content.xml" ) ) && + xStorage->isStreamElement( C2S( "Content.xml" ) ) + ) + ) + { + // is this a fabulous math package ? + Reference<com::sun::star::frame::XModel> xModel(GetModel()); + SmXMLImportWrapper aEquation(xModel); + sal_uLong nError = aEquation.Import(rMedium); + bRet = 0 == nError; + SetError( nError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); + } + } + + if ( GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + { + SetFormulaArranged( false ); + Repaint(); + } + + FinishedLoading( SFX_LOADED_ALL ); + return bRet; +} + +//------------------------------------------------------------------ + +sal_Bool SmDocShell::Save() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::Save" ); + + //! apply latest changes if necessary + UpdateText(); + + if ( SfxObjectShell::Save() ) + { + if (!pTree) + Parse(); + if( pTree && !IsFormulaArranged() ) + ArrangeFormula(); + + Reference<com::sun::star::frame::XModel> xModel(GetModel()); + SmXMLExportWrapper aEquation(xModel); + aEquation.SetFlat(sal_False); + return aEquation.Export(*GetMedium()); + } + + return false; +} + +/* + * replace bad characters that can not be saved. (#i74144) + * */ +sal_Bool SmDocShell::ReplaceBadChars() +{ + sal_Bool bReplace = sal_False; + if (pEditEngine) + { + String aEngTxt( pEditEngine->GetText( LINEEND_LF ) ); + const sal_Unicode *pEngTxt = aEngTxt.GetBuffer(); + xub_StrLen nLen = aEngTxt.Len(); + for (xub_StrLen i = 0; i < nLen && !bReplace; ++i) + { + const sal_Unicode c = *pEngTxt++; + if (c < ' ' && c != '\r' && c != '\n' && c != '\t') + bReplace = sal_True; + } + if (bReplace) + { + sal_Unicode *pChgTxt = aEngTxt.GetBufferAccess(); + for (xub_StrLen i = 0; i < nLen; ++i) + { + sal_Unicode &rc = *pChgTxt++; + if (rc < ' ' && rc != '\r' && rc != '\n' && rc != '\t') + rc = ' '; + } + aEngTxt.ReleaseBufferAccess( nLen ); + + aText = aEngTxt; + } + } + return bReplace; +} + + +void SmDocShell::UpdateText() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::UpdateText" ); + + if (pEditEngine && pEditEngine->IsModified()) + { + String aEngTxt( pEditEngine->GetText( LINEEND_LF ) ); + if (GetText() != aEngTxt) + SetText( aEngTxt ); + } +} + + +sal_Bool SmDocShell::SaveAs( SfxMedium& rMedium ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SaveAs" ); + + bool bRet = false; + + //! apply latest changes if necessary + UpdateText(); + + if ( SfxObjectShell::SaveAs( rMedium ) ) + { + if (!pTree) + Parse(); + if( pTree && !IsFormulaArranged() ) + ArrangeFormula(); + + Reference<com::sun::star::frame::XModel> xModel(GetModel()); + SmXMLExportWrapper aEquation(xModel); + aEquation.SetFlat(sal_False); + bRet = aEquation.Export(rMedium); + } + return bRet; +} + +sal_Bool SmDocShell::ConvertTo( SfxMedium &rMedium ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::ConvertTo" ); + + bool bRet = false; + const SfxFilter* pFlt = rMedium.GetFilter(); + if( pFlt ) + { + if( !pTree ) + Parse(); + if( pTree && !IsFormulaArranged() ) + ArrangeFormula(); + + const String& rFltName = pFlt->GetFilterName(); + if(rFltName.EqualsAscii( STAROFFICE_XML )) + { + Reference<com::sun::star::frame::XModel> xModel(GetModel()); + SmXMLExportWrapper aEquation(xModel); + aEquation.SetFlat(sal_False); + bRet = aEquation.Export(rMedium); + } + else if(rFltName.EqualsAscii( MATHML_XML )) + { + Reference<com::sun::star::frame::XModel> xModel(GetModel()); + SmXMLExportWrapper aEquation(xModel); + aEquation.SetFlat(sal_True); + bRet = aEquation.Export(rMedium); + } + else if( pFlt->GetFilterName().EqualsAscii("MathType 3.x")) + bRet = WriteAsMathType3( rMedium ); + } + return bRet; +} + +bool SmDocShell::writeFormulaOoxml( ::sax_fastparser::FSHelperPtr m_pSerializer, oox::core::OoxmlVersion version ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::writeFormulaOoxml" ); + + if( !pTree ) + Parse(); + if( pTree && !IsFormulaArranged() ) + ArrangeFormula(); + SmOoxml aEquation( aText, pTree, version ); + return aEquation.ConvertFromStarMath( m_pSerializer ); +} + +sal_Bool SmDocShell::SaveCompleted( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SaveCompleted" ); + + if( SfxObjectShell::SaveCompleted( xStorage )) + return true; + + return false; +} + + +void SmDocShell::Execute(SfxRequest& rReq) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::Execute" ); + + switch (rReq.GetSlot()) + { + case SID_TEXTMODE: + { + SmFormat aOldFormat = GetFormat(); + SmFormat aNewFormat( aOldFormat ); + aNewFormat.SetTextmode(!aOldFormat.IsTextmode()); + + ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager(); + if (pTmpUndoMgr) + pTmpUndoMgr->AddUndoAction( + new SmFormatAction(this, aOldFormat, aNewFormat)); + + SetFormat( aNewFormat ); + Repaint(); + } + break; + + case SID_AUTO_REDRAW : + { + SmModule *pp = SM_MOD(); + bool bRedraw = pp->GetConfig()->IsAutoRedraw(); + pp->GetConfig()->SetAutoRedraw(!bRedraw); + } + break; + + case SID_LOADSYMBOLS: + LoadSymbols(); + break; + + case SID_SAVESYMBOLS: + SaveSymbols(); + break; + + case SID_FONT: + { + // get device used to retrieve the FontList + OutputDevice *pDev = GetPrinter(); + if (!pDev || pDev->GetDevFontCount() == 0) + pDev = &SM_MOD()->GetDefaultVirtualDev(); + OSL_ENSURE (pDev, "device for font list missing" ); + + SmFontTypeDialog *pFontTypeDialog = new SmFontTypeDialog( NULL, pDev ); + + SmFormat aOldFormat = GetFormat(); + pFontTypeDialog->ReadFrom( aOldFormat ); + if (pFontTypeDialog->Execute() == RET_OK) + { + SmFormat aNewFormat( aOldFormat ); + + pFontTypeDialog->WriteTo(aNewFormat); + ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager(); + if (pTmpUndoMgr) + pTmpUndoMgr->AddUndoAction( + new SmFormatAction(this, aOldFormat, aNewFormat)); + + SetFormat( aNewFormat ); + Repaint(); + } + delete pFontTypeDialog; + } + break; + + case SID_FONTSIZE: + { + SmFontSizeDialog *pFontSizeDialog = new SmFontSizeDialog(NULL); + + SmFormat aOldFormat = GetFormat(); + pFontSizeDialog->ReadFrom( aOldFormat ); + if (pFontSizeDialog->Execute() == RET_OK) + { + SmFormat aNewFormat( aOldFormat ); + + pFontSizeDialog->WriteTo(aNewFormat); + + ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager(); + if (pTmpUndoMgr) + pTmpUndoMgr->AddUndoAction( + new SmFormatAction(this, aOldFormat, aNewFormat)); + + SetFormat( aNewFormat ); + Repaint(); + } + delete pFontSizeDialog; + } + break; + + case SID_DISTANCE: + { + SmDistanceDialog *pDistanceDialog = new SmDistanceDialog(NULL); + + SmFormat aOldFormat = GetFormat(); + pDistanceDialog->ReadFrom( aOldFormat ); + if (pDistanceDialog->Execute() == RET_OK) + { + SmFormat aNewFormat( aOldFormat ); + + pDistanceDialog->WriteTo(aNewFormat); + + ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager(); + if (pTmpUndoMgr) + pTmpUndoMgr->AddUndoAction( + new SmFormatAction(this, aOldFormat, aNewFormat)); + + SetFormat( aNewFormat ); + Repaint(); + } + delete pDistanceDialog; + } + break; + + case SID_ALIGN: + { + SmAlignDialog *pAlignDialog = new SmAlignDialog(NULL); + + SmFormat aOldFormat = GetFormat(); + pAlignDialog->ReadFrom( aOldFormat ); + if (pAlignDialog->Execute() == RET_OK) + { + SmFormat aNewFormat( aOldFormat ); + + pAlignDialog->WriteTo(aNewFormat); + + SmModule *pp = SM_MOD(); + SmFormat aFmt( pp->GetConfig()->GetStandardFormat() ); + pAlignDialog->WriteTo( aFmt ); + pp->GetConfig()->SetStandardFormat( aFmt ); + + ::svl::IUndoManager *pTmpUndoMgr = GetUndoManager(); + if (pTmpUndoMgr) + pTmpUndoMgr->AddUndoAction( + new SmFormatAction(this, aOldFormat, aNewFormat)); + + SetFormat( aNewFormat ); + Repaint(); + } + delete pAlignDialog; + } + break; + + case SID_TEXT: + { + const SfxStringItem& rItem = (const SfxStringItem&)rReq.GetArgs()->Get(SID_TEXT); + if (GetText() != rItem.GetValue()) + SetText(rItem.GetValue()); + } + break; + + case SID_UNDO: + case SID_REDO: + { + ::svl::IUndoManager* pTmpUndoMgr = GetUndoManager(); + if( pTmpUndoMgr ) + { + sal_uInt16 nId = rReq.GetSlot(), nCnt = 1; + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + if( pArgs && SFX_ITEM_SET == pArgs->GetItemState( nId, false, &pItem )) + nCnt = ((SfxUInt16Item*)pItem)->GetValue(); + + sal_Bool (::svl::IUndoManager:: *fnDo)(); + + sal_uInt16 nCount; + if( SID_UNDO == rReq.GetSlot() ) + { + nCount = pTmpUndoMgr->GetUndoActionCount(); + fnDo = &::svl::IUndoManager::Undo; + } + else + { + nCount = pTmpUndoMgr->GetRedoActionCount(); + fnDo = &::svl::IUndoManager::Redo; + } + + try + { + for( ; nCnt && nCount; --nCnt, --nCount ) + (pTmpUndoMgr->*fnDo)(); + } + catch( const Exception& e ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + Repaint(); + UpdateText(); + SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this ); + while( pFrm ) + { + SfxBindings& rBind = pFrm->GetBindings(); + rBind.Invalidate(SID_UNDO); + rBind.Invalidate(SID_REDO); + rBind.Invalidate(SID_REPEAT); + rBind.Invalidate(SID_CLEARHISTORY); + pFrm = SfxViewFrame::GetNext( *pFrm, this ); + } + } + break; + } + + rReq.Done(); +} + + +void SmDocShell::GetState(SfxItemSet &rSet) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::GetState" ); + + SfxWhichIter aIter(rSet); + + for (sal_uInt16 nWh = aIter.FirstWhich(); 0 != nWh; nWh = aIter.NextWhich()) + { + switch (nWh) + { + case SID_TEXTMODE: + rSet.Put(SfxBoolItem(SID_TEXTMODE, GetFormat().IsTextmode())); + break; + + case SID_DOCTEMPLATE : + rSet.DisableItem(SID_DOCTEMPLATE); + break; + + case SID_AUTO_REDRAW : + { + SmModule *pp = SM_MOD(); + bool bRedraw = pp->GetConfig()->IsAutoRedraw(); + + rSet.Put(SfxBoolItem(SID_AUTO_REDRAW, bRedraw)); + } + break; + + case SID_MODIFYSTATUS: + { + sal_Unicode cMod = ' '; + if (IsModified()) + cMod = '*'; + rSet.Put(SfxStringItem(SID_MODIFYSTATUS, String(cMod))); + } + break; + + case SID_TEXT: + rSet.Put(SfxStringItem(SID_TEXT, GetText())); + break; + + case SID_GAPHIC_SM: + //! very old (pre UNO) and ugly hack to invalidate the SmGraphicWindow. + //! If nModifyCount gets changed then the call below will implicitly notify + //! SmGraphicController::StateChanged and there the window gets invalidated. + //! Thus all the 'nModifyCount++' before invalidating this slot. + rSet.Put(SfxInt16Item(SID_GAPHIC_SM, nModifyCount)); + break; + + case SID_UNDO: + case SID_REDO: + { + SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this ); + if( pFrm ) + pFrm->GetSlotState( nWh, NULL, &rSet ); + else + rSet.DisableItem( nWh ); + } + break; + + case SID_GETUNDOSTRINGS: + case SID_GETREDOSTRINGS: + { + ::svl::IUndoManager* pTmpUndoMgr = GetUndoManager(); + if( pTmpUndoMgr ) + { + UniString(::svl::IUndoManager:: *fnGetComment)( size_t, bool const ) const; + + sal_uInt16 nCount; + if( SID_GETUNDOSTRINGS == nWh ) + { + nCount = pTmpUndoMgr->GetUndoActionCount(); + fnGetComment = &::svl::IUndoManager::GetUndoActionComment; + } + else + { + nCount = pTmpUndoMgr->GetRedoActionCount(); + fnGetComment = &::svl::IUndoManager::GetRedoActionComment; + } + if( nCount ) + { + String sList; + for( sal_uInt16 n = 0; n < nCount; ++n ) + ( sList += (pTmpUndoMgr->*fnGetComment)( n, ::svl::IUndoManager::TopLevel ) ) + += '\n'; + + SfxStringListItem aItem( nWh ); + aItem.SetString( sList ); + rSet.Put( aItem ); + } + } + else + rSet.DisableItem( nWh ); + } + break; + } + } +} + + +::svl::IUndoManager *SmDocShell::GetUndoManager() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::GetUndoManager" ); + + if (!pEditEngine) + GetEditEngine(); + return &pEditEngine->GetUndoManager(); +} + + +void SmDocShell::SaveSymbols() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SaveSymbols" ); + + SmModule *pp = SM_MOD(); + pp->GetSymbolManager().Save(); +} + + +void SmDocShell::Draw(OutputDevice *pDevice, + const JobSetup &, + sal_uInt16 /*nAspect*/) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::Draw" ); + + pDevice->IntersectClipRegion(GetVisArea()); + Point atmppoint; + DrawFormula(*pDevice, atmppoint); +} + +SfxItemPool& SmDocShell::GetPool() const +{ + return SFX_APP()->GetPool(); +} + +void SmDocShell::SetVisArea(const Rectangle & rVisArea) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SetVisArea" ); + + Rectangle aNewRect(rVisArea); + + aNewRect.SetPos(Point()); + + if (! aNewRect.Right()) aNewRect.Right() = 2000; + if (! aNewRect.Bottom()) aNewRect.Bottom() = 1000; + + bool bIsEnabled = IsEnableSetModified(); + if ( bIsEnabled ) + EnableSetModified( false ); + + //TODO/LATER: it's unclear how this interacts with the SFX code + // If outplace editing, then dont resize the OutplaceWindow. But the + // ObjectShell has to resize. Bug 56470 + bool bUnLockFrame; + if( GetCreateMode() == SFX_CREATE_MODE_EMBEDDED && !IsInPlaceActive() && GetFrame() ) + { + GetFrame()->LockAdjustPosSizePixel(); + bUnLockFrame = true; + } + else + bUnLockFrame = false; + + SfxObjectShell::SetVisArea( aNewRect ); + + if( bUnLockFrame ) + GetFrame()->UnlockAdjustPosSizePixel(); + + if ( bIsEnabled ) + EnableSetModified( bIsEnabled ); +} + + +void SmDocShell::FillClass(SvGlobalName* pClassName, + sal_uInt32* pFormat, + String* /*pAppName*/, + String* pFullTypeName, + String* pShortTypeName, + sal_Int32 nFileFormat, + sal_Bool bTemplate /* = sal_False */) const +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::FillClass" ); + + if (nFileFormat == SOFFICE_FILEFORMAT_60 ) + { + *pClassName = SvGlobalName(SO3_SM_CLASSID_60); + *pFormat = SOT_FORMATSTR_ID_STARMATH_60; + *pFullTypeName = String(SmResId(STR_MATH_DOCUMENT_FULLTYPE_CURRENT)); + *pShortTypeName = String(SmResId(RID_DOCUMENTSTR)); + } + else if (nFileFormat == SOFFICE_FILEFORMAT_8 ) + { + *pClassName = SvGlobalName(SO3_SM_CLASSID_60); + *pFormat = bTemplate ? SOT_FORMATSTR_ID_STARMATH_8_TEMPLATE : SOT_FORMATSTR_ID_STARMATH_8; + *pFullTypeName = String(SmResId(STR_MATH_DOCUMENT_FULLTYPE_CURRENT)); + *pShortTypeName = String(SmResId(RID_DOCUMENTSTR)); + } +} + +sal_uLong SmDocShell::GetMiscStatus() const +{ + return SfxObjectShell::GetMiscStatus() | SVOBJ_MISCSTATUS_NOTRESIZEABLE + | SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE; +} + +void SmDocShell::SetModified(sal_Bool bModified) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::SetModified" ); + + if( IsEnableSetModified() ) + { + SfxObjectShell::SetModified( bModified ); + Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED)); + } +} + +bool SmDocShell::WriteAsMathType3( SfxMedium& rMedium ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmDocShell::WriteAsMathType3" ); + + MathType aEquation( aText, pTree ); + + bool bRet = 0 != aEquation.ConvertFromStarMath( rMedium ); + return bRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/edit.cxx b/starmath/source/edit.cxx new file mode 100644 index 000000000000..0779c823052c --- /dev/null +++ b/starmath/source/edit.cxx @@ -0,0 +1,995 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/AccessibleEventObject.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <toolkit/helper/vclunohelper.hxx> + + +#include "starmath.hrc" +#define ITEMID_FONT 1 +#define ITEMID_FONTHEIGHT 2 +#define ITEMID_LRSPACE 3 +#define ITEMID_WEIGHT 4 + + +#include <vcl/menu.hxx> +#include <editeng/editview.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editstat.hxx> +#include <editeng/eeitem.hxx> +#include <sfx2/dispatch.hxx> +#include <svl/intitem.hxx> +#include <svl/itempool.hxx> +#include <svl/stritem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/lrspitem.hxx> +#include <svl/itemset.hxx> +#include <editeng/fontitem.hxx> +#include <sfx2/viewfrm.hxx> + +#include "edit.hxx" +#include "view.hxx" +#include "document.hxx" +#include "config.hxx" +#include "accessibility.hxx" + +#define SCROLL_LINE 24 + +#define MINWIDTH 200 +#define MINHEIGHT 200 +#define MINSPLIT 40 +#define SPLITTERWIDTH 2 + + +using namespace com::sun::star::accessibility; +using namespace com::sun::star; +using namespace com::sun::star::uno; + +//////////////////////////////////////// + + +void SmGetLeftSelectionPart(const ESelection &rSel, + sal_uInt16 &nPara, sal_uInt16 &nPos) + // returns paragraph number and position of the selections left part +{ + // compare start and end of selection and use the one that comes first + if ( rSel.nStartPara < rSel.nEndPara + || (rSel.nStartPara == rSel.nEndPara && rSel.nStartPos < rSel.nEndPos) ) + { nPara = rSel.nStartPara; + nPos = rSel.nStartPos; + } + else + { nPara = rSel.nEndPara; + nPos = rSel.nEndPos; + } +} + +bool SmEditWindow::IsInlineEditEnabled() +{ + SmViewShell *pView = GetView(); + return pView ? pView->IsInlineEditEnabled() : false; +} + +//////////////////////////////////////// + +SmEditWindow::SmEditWindow( SmCmdBoxWindow &rMyCmdBoxWin ) : + Window (&rMyCmdBoxWin), + DropTargetHelper ( this ), + pAccessible (0), + rCmdBox (rMyCmdBoxWin), + pEditView (0), + pHScrollBar (0), + pVScrollBar (0), + pScrollBox (0) +{ + SetHelpId(HID_SMA_COMMAND_WIN_EDIT); + SetMapMode(MAP_PIXEL); + + // Even RTL languages don't use RTL for math + rCmdBox.GetEditWindow()->EnableRTL( false ); + + ApplyColorConfigValues( SM_MOD()->GetColorConfig() ); + + // compare DataChanged + SetBackground( GetSettings().GetStyleSettings().GetWindowColor() ); + + aModifyTimer.SetTimeoutHdl(LINK(this, SmEditWindow, ModifyTimerHdl)); + aModifyTimer.SetTimeout(500); + + if (!IsInlineEditEnabled()) + { + aCursorMoveTimer.SetTimeoutHdl(LINK(this, SmEditWindow, CursorMoveTimerHdl)); + aCursorMoveTimer.SetTimeout(500); + } + + // if not called explicitly the this edit window within the + // command window will just show an empty gray panel. + Show(); +} + + +SmEditWindow::~SmEditWindow() +{ + aModifyTimer.Stop(); + + StartCursorMove(); + + // clean up of classes used for accessibility + // must be done before EditView (and thus EditEngine) is no longer + // available for those classes. + if (pAccessible) + pAccessible->ClearWin(); // make Accessible defunctional + // Note: memory for pAccessible will be freed when the reference + // xAccessible is released. + + if (pEditView) + { + EditEngine *pEditEngine = pEditView->GetEditEngine(); + if (pEditEngine) + { + pEditEngine->SetStatusEventHdl( Link() ); + pEditEngine->RemoveView( pEditView ); + } + } + delete pEditView; + delete pHScrollBar; + delete pVScrollBar; + delete pScrollBox; +} + +void SmEditWindow::StartCursorMove() +{ + if (!IsInlineEditEnabled()) + aCursorMoveTimer.Stop(); +} + +void SmEditWindow::InvalidateSlots() +{ + SfxBindings& rBind = GetView()->GetViewFrame()->GetBindings(); + rBind.Invalidate(SID_COPY); + rBind.Invalidate(SID_CUT); + rBind.Invalidate(SID_DELETE); +} + +SmViewShell * SmEditWindow::GetView() +{ + return rCmdBox.GetView(); +} + + +SmDocShell * SmEditWindow::GetDoc() +{ + SmViewShell *pView = rCmdBox.GetView(); + return pView ? pView->GetDoc() : 0; +} + + +EditEngine * SmEditWindow::GetEditEngine() +{ + EditEngine *pEditEng = 0; + if (pEditView) + pEditEng = pEditView->GetEditEngine(); + else + { + SmDocShell *pDoc = GetDoc(); + if (pDoc) + pEditEng = &pDoc->GetEditEngine(); + } + return pEditEng; +} + + +SfxItemPool * SmEditWindow::GetEditEngineItemPool() +{ + SmDocShell *pDoc = GetDoc(); + return pDoc ? &pDoc->GetEditEngineItemPool() : 0; +} + +void SmEditWindow::ApplyColorConfigValues( const svtools::ColorConfig &rColorCfg ) +{ + // Note: SetBackground still done in SmEditWindow::DataChanged +#if OSL_DEBUG_LEVEL > 1 +// ColorData nVal = rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor; +#endif + SetTextColor( rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor ); + Invalidate(); +} + +void SmEditWindow::DataChanged( const DataChangedEvent& ) +{ + const StyleSettings aSettings( GetSettings().GetStyleSettings() ); + + ApplyColorConfigValues( SM_MOD()->GetColorConfig() ); + SetBackground( aSettings.GetWindowColor() ); + + // edit fields in other Applications use this font instead of + // the application font thus we use this one too + SetPointFont( aSettings.GetFieldFont() /*aSettings.GetAppFont()*/ ); + + EditEngine *pEditEngine = GetEditEngine(); + SfxItemPool *pEditEngineItemPool = GetEditEngineItemPool(); + + if (pEditEngine && pEditEngineItemPool) + { + //! + //! see also SmDocShell::GetEditEngine() ! + //! + + pEditEngine->SetDefTab( sal_uInt16( GetTextWidth( C2S("XXXX") ) ) ); + + SetEditEngineDefaultFonts(*pEditEngineItemPool); + + // forces new settings to be used + // unfortunately this resets the whole edit engine + // thus we need to save at least the text + String aTxt( pEditEngine->GetText( LINEEND_LF ) ); + pEditEngine->Clear(); //incorrect font size + pEditEngine->SetText( aTxt ); + } + + AdjustScrollBars(); + Resize(); +} + +IMPL_LINK( SmEditWindow, ModifyTimerHdl, Timer *, EMPTYARG /*pTimer*/ ) +{ + SmModule *pp = SM_MOD(); + if (pp->GetConfig()->IsAutoRedraw()) + Flush(); + aModifyTimer.Stop(); + return 0; +} + +IMPL_LINK(SmEditWindow, CursorMoveTimerHdl, Timer *, EMPTYARG /*pTimer*/) + // every once in a while check cursor position (selection) of edit + // window and if it has changed (try to) set the formula-cursor + // according to that. +{ + if (IsInlineEditEnabled()) + return 0; + + ESelection aNewSelection(GetSelection()); + + if (!aNewSelection.IsEqual(aOldSelection)) + { + SmViewShell *pView = rCmdBox.GetView(); + if (pView) + { + // get row and column to look for + sal_uInt16 nRow, nCol; + SmGetLeftSelectionPart(aNewSelection, nRow, nCol); + nRow++; + nCol++; + pView->GetGraphicWindow().SetCursorPos(nRow, nCol); + aOldSelection = aNewSelection; + } + } + aCursorMoveTimer.Stop(); + + return 0; +} + +void SmEditWindow::Resize() +{ + if (!pEditView) + CreateEditView(); + + if (pEditView) + { + pEditView->SetOutputArea(AdjustScrollBars()); + pEditView->ShowCursor(); + + OSL_ENSURE( pEditView->GetEditEngine(), "EditEngine missing" ); + const long nMaxVisAreaStart = pEditView->GetEditEngine()->GetTextHeight() - + pEditView->GetOutputArea().GetHeight(); + if (pEditView->GetVisArea().Top() > nMaxVisAreaStart) + { + Rectangle aVisArea(pEditView->GetVisArea() ); + aVisArea.Top() = (nMaxVisAreaStart > 0 ) ? nMaxVisAreaStart : 0; + aVisArea.SetSize(pEditView->GetOutputArea().GetSize()); + pEditView->SetVisArea(aVisArea); + pEditView->ShowCursor(); + } + InitScrollBars(); + } + Invalidate(); +} + +void SmEditWindow::MouseButtonUp(const MouseEvent &rEvt) +{ + if (pEditView) + pEditView->MouseButtonUp(rEvt); + else + Window::MouseButtonUp (rEvt); + + if (!IsInlineEditEnabled()) + CursorMoveTimerHdl(&aCursorMoveTimer); + InvalidateSlots(); +} + +void SmEditWindow::MouseButtonDown(const MouseEvent &rEvt) +{ + if (pEditView) + pEditView->MouseButtonDown(rEvt); + else + Window::MouseButtonDown (rEvt); + + GrabFocus(); +} + +void SmEditWindow::Command(const CommandEvent& rCEvt) +{ + bool bForwardEvt = true; + if (rCEvt.GetCommand() == COMMAND_CONTEXTMENU) + { + GetParent()->ToTop(); + + Point aPoint = rCEvt.GetMousePosPixel(); + PopupMenu* pPopupMenu = new PopupMenu(SmResId(RID_COMMANDMENU)); + + // added for replaceability of context menus + Menu* pMenu = NULL; + ::com::sun::star::ui::ContextMenuExecuteEvent aEvent; + aEvent.SourceWindow = VCLUnoHelper::GetInterface( this ); + aEvent.ExecutePosition.X = aPoint.X(); + aEvent.ExecutePosition.Y = aPoint.Y(); + ::rtl::OUString sDummy; + if ( GetView()->TryContextMenuInterception( *pPopupMenu, sDummy, pMenu, aEvent ) ) + { + if ( pMenu ) + { + delete pPopupMenu; + pPopupMenu = (PopupMenu*) pMenu; + } + } + + pPopupMenu->SetSelectHdl(LINK(this, SmEditWindow, MenuSelectHdl)); + + pPopupMenu->Execute( this, aPoint ); + delete pPopupMenu; + bForwardEvt = false; + } + else if (rCEvt.GetCommand() == COMMAND_WHEEL) + bForwardEvt = !HandleWheelCommands( rCEvt ); + + if (bForwardEvt) + { + if (pEditView) + pEditView->Command( rCEvt ); + else + Window::Command (rCEvt); + } +} + + +bool SmEditWindow::HandleWheelCommands( const CommandEvent &rCEvt ) +{ + bool bCommandHandled = false; // true if the CommandEvent needs not + // to be passed on (because it has fully + // been taken care of). + + const CommandWheelData* pWData = rCEvt.GetWheelData(); + if (pWData) + { + if (COMMAND_WHEEL_ZOOM == pWData->GetMode()) + bCommandHandled = true; // no zooming in Command window + else + bCommandHandled = HandleScrollCommand( rCEvt, pHScrollBar, pVScrollBar); + } + + return bCommandHandled; +} + + +IMPL_LINK_INLINE_START( SmEditWindow, MenuSelectHdl, Menu *, pMenu ) +{ + SmViewShell *pViewSh = rCmdBox.GetView(); + if (pViewSh) + pViewSh->GetViewFrame()->GetDispatcher()->Execute( + SID_INSERTCOMMAND, SFX_CALLMODE_STANDARD, + new SfxInt16Item(SID_INSERTCOMMAND, pMenu->GetCurItemId()), 0L); + return 0; +} +IMPL_LINK_INLINE_END( SmEditWindow, MenuSelectHdl, Menu *, pMenu ) + +void SmEditWindow::KeyInput(const KeyEvent& rKEvt) +{ + if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE) + { + bool bCallBase = true; + SfxViewShell* pViewShell = GetView(); + if ( pViewShell && pViewShell->ISA(SmViewShell) ) + { + // Terminate possible InPlace mode + bCallBase = !pViewShell->Escape(); + } + if ( bCallBase ) + Window::KeyInput( rKEvt ); + } + else + { + StartCursorMove(); + + if (!pEditView) + CreateEditView(); + if ( !pEditView->PostKeyEvent(rKEvt) ) + { + SmViewShell *pView = GetView(); + if ( pView && !pView->KeyInput(rKEvt) ) + { + /* fuert bei F1 (Hilfe) zum Zerstoeren von this! */ + Flush(); + if ( aModifyTimer.IsActive() ) + aModifyTimer.Stop(); + Window::KeyInput(rKEvt); + } + else + { + //SFX hat evtl. Slot an der View gecallt und dabei (wg. Hack + //im SFX) den Focus auf die View gesetzt + SfxViewShell* pVShell = GetView(); + if ( pVShell && pVShell->ISA(SmViewShell) && + ((SmViewShell*)pVShell)->GetGraphicWindow().HasFocus() ) + { + GrabFocus(); + } + } + } + else + { + // have doc-shell modified only for formula input/change and not + // cursor travelling and such things... + SmDocShell *pDocShell = GetDoc(); + if (pDocShell) + pDocShell->SetModified( GetEditEngine()->IsModified() ); + + aModifyTimer.Start(); + } + + InvalidateSlots(); + } +} + +void SmEditWindow::Paint(const Rectangle& rRect) +{ + if (!pEditView) + CreateEditView(); + pEditView->Paint(rRect); +} + +void SmEditWindow::CreateEditView() +{ + EditEngine *pEditEngine = GetEditEngine(); + + //! pEditEngine and pEditView may be 0. + //! For example when the program is used by the document-converter + if (!pEditView && pEditEngine) + { + pEditView = new EditView( pEditEngine, this ); + pEditEngine->InsertView( pEditView ); + + if (!pVScrollBar) + pVScrollBar = new ScrollBar(this, WinBits(WB_VSCROLL)); + if (!pHScrollBar) + pHScrollBar = new ScrollBar(this, WinBits(WB_HSCROLL)); + if (!pScrollBox) + pScrollBox = new ScrollBarBox(this); + pVScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl)); + pHScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl)); + pVScrollBar->EnableDrag( true ); + pHScrollBar->EnableDrag( true ); + + pEditView->SetOutputArea(AdjustScrollBars()); + + ESelection eSelection; + + pEditView->SetSelection(eSelection); + Update(); + pEditView->ShowCursor(true, true); + + pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) ); + SetPointer(pEditView->GetPointer()); + + SetScrollBarRanges(); + } +} + + +IMPL_LINK( SmEditWindow, EditStatusHdl, EditStatus *, EMPTYARG /*pStat*/ ) +{ + if (!pEditView) + return 1; + else + { + Resize(); + return 0; + } +} + +IMPL_LINK_INLINE_START( SmEditWindow, ScrollHdl, ScrollBar *, EMPTYARG /*pScrollBar*/ ) +{ + OSL_ENSURE(pEditView, "EditView missing"); + if (pEditView) + { + pEditView->SetVisArea(Rectangle(Point(pHScrollBar->GetThumbPos(), + pVScrollBar->GetThumbPos()), + pEditView->GetVisArea().GetSize())); + pEditView->Invalidate(); + } + return 0; +} +IMPL_LINK_INLINE_END( SmEditWindow, ScrollHdl, ScrollBar *, pScrollBar ) + +Rectangle SmEditWindow::AdjustScrollBars() +{ + const Size aOut( GetOutputSizePixel() ); + Point aPoint; + Rectangle aRect( aPoint, aOut ); + + if (pVScrollBar && pHScrollBar && pScrollBox) + { + const long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize(); + Point aPt( aRect.TopRight() ); aPt.X() -= nTmp -1L; + pVScrollBar->SetPosSizePixel( aPt, Size(nTmp, aOut.Height() - nTmp)); + + aPt = aRect.BottomLeft(); aPt.Y() -= nTmp - 1L; + pHScrollBar->SetPosSizePixel( aPt, Size(aOut.Width() - nTmp, nTmp)); + + aPt.X() = pHScrollBar->GetSizePixel().Width(); + aPt.Y() = pVScrollBar->GetSizePixel().Height(); + pScrollBox->SetPosSizePixel(aPt, Size(nTmp, nTmp )); + + aRect.Right() = aPt.X() - 2; + aRect.Bottom() = aPt.Y() - 2; + } + return aRect; +} + +void SmEditWindow::SetScrollBarRanges() +{ + // Extra-Methode, nicht InitScrollBars, da auch fuer EditEngine-Events. + EditEngine *pEditEngine = GetEditEngine(); + if (pVScrollBar && pHScrollBar && pEditEngine && pEditView) + { + long nTmp = pEditEngine->GetTextHeight(); + pVScrollBar->SetRange(Range(0, nTmp)); + pVScrollBar->SetThumbPos(pEditView->GetVisArea().Top()); + + nTmp = pEditEngine->GetPaperSize().Width(); + pHScrollBar->SetRange(Range(0,nTmp)); + pHScrollBar->SetThumbPos(pEditView->GetVisArea().Left()); + } +} + +void SmEditWindow::InitScrollBars() +{ + if (pVScrollBar && pHScrollBar && pScrollBox && pEditView) + { + const Size aOut( pEditView->GetOutputArea().GetSize() ); + pVScrollBar->SetVisibleSize(aOut.Height()); + pVScrollBar->SetPageSize(aOut.Height() * 8 / 10); + pVScrollBar->SetLineSize(aOut.Height() * 2 / 10); + + pHScrollBar->SetVisibleSize(aOut.Width()); + pHScrollBar->SetPageSize(aOut.Width() * 8 / 10); + pHScrollBar->SetLineSize(SCROLL_LINE ); + + SetScrollBarRanges(); + + pVScrollBar->Show(); + pHScrollBar->Show(); + pScrollBox->Show(); + } +} + + +String SmEditWindow::GetText() const +{ + String aText; + EditEngine *pEditEngine = const_cast< SmEditWindow* >(this)->GetEditEngine(); + OSL_ENSURE( pEditEngine, "EditEngine missing" ); + if (pEditEngine) + aText = pEditEngine->GetText( LINEEND_LF ); + return aText; +} + + +void SmEditWindow::SetText(const XubString& rText) +{ + EditEngine *pEditEngine = GetEditEngine(); + OSL_ENSURE( pEditEngine, "EditEngine missing" ); + if (pEditEngine && !pEditEngine->IsModified()) + { + if (!pEditView) + CreateEditView(); + + ESelection eSelection = pEditView->GetSelection(); + + pEditEngine->SetText(rText); + pEditEngine->ClearModifyFlag(); + + //! Hier die Timer neu zu starten verhindert, dass die Handler fuer andere + //! (im Augenblick nicht mehr aktive) Math Tasks aufgerufen werden. + aModifyTimer.Start(); + + pEditView->SetSelection(eSelection); + } +} + + +void SmEditWindow::GetFocus() +{ + Window::GetFocus(); + + if (xAccessible.is()) + { + // Note: will implicitly send the AccessibleStateType::FOCUSED event + ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper(); + if (pHelper) + pHelper->SetFocus( sal_True ); + } + + if (!pEditView) + CreateEditView(); + EditEngine *pEditEngine = GetEditEngine(); + if (pEditEngine) + pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) ); + + //Let SmViewShell know we got focus + if(GetView() && IsInlineEditEnabled()) + GetView()->SetInsertIntoEditWindow(true); +} + + +void SmEditWindow::LoseFocus() +{ + EditEngine *pEditEngine = GetEditEngine(); + if (pEditEngine) + pEditEngine->SetStatusEventHdl( Link() ); + + Window::LoseFocus(); + + if (xAccessible.is()) + { + // Note: will implicitly send the AccessibleStateType::FOCUSED event + ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper(); + if (pHelper) + pHelper->SetFocus( sal_False ); + } +} + + +bool SmEditWindow::IsAllSelected() const +{ + bool bRes = false; + EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine(); + OSL_ENSURE( pEditView, "NULL pointer" ); + OSL_ENSURE( pEditEngine, "NULL pointer" ); + if (pEditEngine && pEditView) + { + ESelection eSelection( pEditView->GetSelection() ); + sal_Int32 nParaCnt = pEditEngine->GetParagraphCount(); + if (!(nParaCnt - 1)) + { + String Text( pEditEngine->GetText( LINEEND_LF ) ); + bRes = !eSelection.nStartPos && (eSelection.nEndPos == Text.Len () - 1); + } + else + { + bRes = !eSelection.nStartPara && (eSelection.nEndPara == nParaCnt - 1); + } + } + return bRes; +} + +void SmEditWindow::SelectAll() +{ + OSL_ENSURE( pEditView, "NULL pointer" ); + if (pEditView) + { + // 0xFFFF as last two parameters refers to the end of the text + pEditView->SetSelection( ESelection( 0, 0, 0xFFFF, 0xFFFF ) ); + } +} + +void SmEditWindow::InsertCommand(sal_uInt16 nCommand) +{ + OSL_ENSURE( pEditView, "EditView missing" ); + if (pEditView) + { + //Anfang der Selektion merken und hinterher den Cursor daraufsetzen. Nur so + //macht das SelNextMark() Sinn. + ESelection aSelection = pEditView->GetSelection(); + aSelection.nEndPos = aSelection.nStartPos; + aSelection.nEndPara = aSelection.nStartPara; + + OSL_ENSURE( pEditView, "NULL pointer" ); + String aText = String(SmResId(nCommand)); + pEditView->InsertText(aText); + + if (HasMark(aText)) + { // set selection to next mark + pEditView->SetSelection(aSelection); + SelNextMark(); + } + else + { // set selection after inserted text + aSelection.nEndPos = aSelection.nEndPos + sal::static_int_cast< xub_StrLen >(aText.Len()); + aSelection.nStartPos = aSelection.nEndPos; + pEditView->SetSelection(aSelection); + } + + aModifyTimer.Start(); + StartCursorMove(); + GrabFocus(); + } +} + +void SmEditWindow::MarkError(const Point &rPos) +{ + OSL_ENSURE( pEditView, "EditView missing" ); + if (pEditView) + { + const xub_StrLen nCol = sal::static_int_cast< xub_StrLen >(rPos.X()); + const sal_uInt16 nRow = sal::static_int_cast< sal_uInt16 >(rPos.Y() - 1); + + pEditView->SetSelection(ESelection(nRow, nCol - 1, nRow, nCol)); + GrabFocus(); + } +} + +void SmEditWindow::SelNextMark() +{ + EditEngine *pEditEngine = GetEditEngine(); + OSL_ENSURE( pEditView, "NULL pointer" ); + OSL_ENSURE( pEditEngine, "NULL pointer" ); + if (pEditEngine && pEditView) + { + ESelection eSelection = pEditView->GetSelection(); + sal_uInt16 Pos = eSelection.nEndPos; + String aMark (C2S("<?>")); + String aText; + sal_uInt16 nCounts = pEditEngine->GetParagraphCount(); + + while (eSelection.nEndPara < nCounts) + { + aText = pEditEngine->GetText( eSelection.nEndPara ); + Pos = aText.Search(aMark, Pos); + + if (Pos != STRING_NOTFOUND) + { + pEditView->SetSelection(ESelection (eSelection.nEndPara, Pos, eSelection.nEndPara, Pos + 3)); + break; + } + + Pos = 0; + eSelection.nEndPara++; + } + } +} + +void SmEditWindow::SelPrevMark() +{ + EditEngine *pEditEngine = GetEditEngine(); + OSL_ENSURE( pEditEngine, "NULL pointer" ); + OSL_ENSURE( pEditView, "NULL pointer" ); + if (pEditEngine && pEditView) + { + ESelection eSelection = pEditView->GetSelection(); + sal_uInt16 Pos = STRING_NOTFOUND; + xub_StrLen Max = eSelection.nStartPos; + String Text( pEditEngine->GetText( eSelection.nStartPara ) ); + String aMark (C2S("<?>")); + sal_uInt16 nCounts = pEditEngine->GetParagraphCount(); + + do + { + sal_uInt16 Fnd = Text.Search(aMark, 0); + + while ((Fnd < Max) && (Fnd != STRING_NOTFOUND)) + { + Pos = Fnd; + Fnd = Text.Search(aMark, Fnd + 1); + } + + if (Pos == STRING_NOTFOUND) + { + eSelection.nStartPara--; + Text = pEditEngine->GetText( eSelection.nStartPara ); + Max = Text.Len(); + } + } + while ((eSelection.nStartPara < nCounts) && + (Pos == STRING_NOTFOUND)); + + if (Pos != STRING_NOTFOUND) + { + pEditView->SetSelection(ESelection (eSelection.nStartPara, Pos, eSelection.nStartPara, Pos + 3)); + } + } +} + +bool SmEditWindow::HasMark(const String& rText) const + // returns true iff 'rText' contains a mark +{ + return rText.SearchAscii("<?>", 0) != STRING_NOTFOUND; +} + +void SmEditWindow::MouseMove(const MouseEvent &rEvt) +{ + if (pEditView) + pEditView->MouseMove(rEvt); +} + +sal_Int8 SmEditWindow::AcceptDrop( const AcceptDropEvent& /*rEvt*/ ) +{ + return pEditView ? /*pEditView->QueryDrop( rEvt )*/DND_ACTION_NONE: DND_ACTION_NONE; +} + +sal_Int8 SmEditWindow::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ ) +{ + return pEditView ? /*pEditView->Drop( rEvt )*/DND_ACTION_NONE : DND_ACTION_NONE; +} + +ESelection SmEditWindow::GetSelection() const +{ + // pointer may be 0 when reloading a document and the old view + // was already destroyed + //(OSL_ENSURE( pEditView, "NULL pointer" ); + ESelection eSel; + if (pEditView) + eSel = pEditView->GetSelection(); + return eSel; +} + +void SmEditWindow::SetSelection(const ESelection &rSel) +{ + OSL_ENSURE( pEditView, "NULL pointer" ); + if (pEditView) + pEditView->SetSelection(rSel); + InvalidateSlots(); +} + +bool SmEditWindow::IsEmpty() const +{ + EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine(); + bool bEmpty = ( pEditEngine ? pEditEngine->GetTextLen() == 0 : false); + return bEmpty; +} + +bool SmEditWindow::IsSelected() const +{ + return pEditView ? pEditView->HasSelection() : false; +} + +void SmEditWindow::Cut() +{ + OSL_ENSURE( pEditView, "EditView missing" ); + if (pEditView) + { + pEditView->Cut(); + GetDoc()->SetModified( true ); + } +} + +void SmEditWindow::Copy() +{ + OSL_ENSURE( pEditView, "EditView missing" ); + if (pEditView) + pEditView->Copy(); +} + +void SmEditWindow::Paste() +{ + OSL_ENSURE( pEditView, "EditView missing" ); + if (pEditView) + { + pEditView->Paste(); + GetDoc()->SetModified( true ); + } +} + +void SmEditWindow::Delete() +{ + OSL_ENSURE( pEditView, "EditView missing" ); + if (pEditView) + { + pEditView->DeleteSelected(); + GetDoc()->SetModified( true ); + } +} + +void SmEditWindow::InsertText(const String& Text) +{ + OSL_ENSURE( pEditView, "EditView missing" ); + if (pEditView) + { + pEditView->InsertText(Text); + aModifyTimer.Start(); + StartCursorMove(); + } +} + +void SmEditWindow::Flush() +{ + EditEngine *pEditEngine = GetEditEngine(); + if (pEditEngine && pEditEngine->IsModified()) + { + pEditEngine->ClearModifyFlag(); + SmViewShell *pViewSh = rCmdBox.GetView(); + if (pViewSh) + { + pViewSh->GetViewFrame()->GetDispatcher()->Execute( + SID_TEXT, SFX_CALLMODE_STANDARD, + new SfxStringItem(SID_TEXT, GetText()), 0L); + } + } + if (aCursorMoveTimer.IsActive()) + { + aCursorMoveTimer.Stop(); + CursorMoveTimerHdl(&aCursorMoveTimer); + } +} + + +void SmEditWindow::DeleteEditView( SmViewShell & /*rView*/ ) +{ + if (pEditView) + { + EditEngine *pEditEngine = pEditView->GetEditEngine(); + if (pEditEngine) + { + pEditEngine->SetStatusEventHdl( Link() ); + pEditEngine->RemoveView( pEditView ); + } + delete pEditView; + pEditView = 0; + } +} + + +uno::Reference< XAccessible > SmEditWindow::CreateAccessible() +{ + if (!pAccessible) + { + pAccessible = new SmEditAccessible( this ); + xAccessible = pAccessible; + pAccessible->Init(); + } + return xAccessible; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/eqnolefilehdr.cxx b/starmath/source/eqnolefilehdr.cxx new file mode 100644 index 000000000000..3e7fa57c665a --- /dev/null +++ b/starmath/source/eqnolefilehdr.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" +#include "eqnolefilehdr.hxx" +#include <sot/storage.hxx> + +////////////////////////////////////////////////////////////////////// + + + +sal_Bool GetMathTypeVersion( SotStorage* pStor, sal_uInt8 &nVersion ) +{ + sal_uInt8 nVer = 0; + sal_Bool bSuccess = sal_False; + + // + // code snippet copied from MathType::Parse + // + SvStorageStreamRef xSrc = pStor->OpenSotStream( + String::CreateFromAscii("Equation Native"), + STREAM_STD_READ | STREAM_NOCREATE); + if ( (!xSrc.Is()) || (SVSTREAM_OK != xSrc->GetError())) + return bSuccess; + SvStorageStream *pS = &xSrc; + pS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + // + EQNOLEFILEHDR aHdr; + aHdr.Read(pS); + *pS >> nVer; + + if (!pS->GetError()) + { + nVersion = nVer; + bSuccess = sal_True; + } + return bSuccess; +} + +////////////////////////////////////////////////////////////////////// + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/eqnolefilehdr.hxx b/starmath/source/eqnolefilehdr.hxx new file mode 100644 index 000000000000..669511a0d6a4 --- /dev/null +++ b/starmath/source/eqnolefilehdr.hxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __EQNOLEFILEHDR_HXX__ +#define __EQNOLEFILEHDR_HXX__ + +#include <sal/types.h> +#include <sot/storage.hxx> + +class SvStorageStream; +class SotStorage; + +#define EQNOLEFILEHDR_SIZE 28 + +class EQNOLEFILEHDR +{ +public: + EQNOLEFILEHDR() {} + EQNOLEFILEHDR(sal_uInt32 nLenMTEF) : nCBHdr(0x1c),nVersion(0x20000), + nCf(0xc1c6),nCBObject(nLenMTEF),nReserved1(0),nReserved2(0x0014F690), + nReserved3(0x0014EBB4), nReserved4(0) {} + + sal_uInt16 nCBHdr; // length of header, sizeof(EQNOLEFILEHDR) = 28 + sal_uInt32 nVersion; // hiword = 2, loword = 0 + sal_uInt16 nCf; // clipboard format ("MathType EF") + sal_uInt32 nCBObject; // length of MTEF data following this header + sal_uInt32 nReserved1; // not used + sal_uInt32 nReserved2; // not used + sal_uInt32 nReserved3; // not used + sal_uInt32 nReserved4; // not used + + inline void Read(SvStorageStream *pS) + { + *pS >> nCBHdr; + *pS >> nVersion; + *pS >> nCf; + *pS >> nCBObject; + *pS >> nReserved1; + *pS >> nReserved2; + *pS >> nReserved3; + *pS >> nReserved4; + } + inline void Write(SvStorageStream *pS) + { + *pS << nCBHdr; + *pS << nVersion; + *pS << nCf; + *pS << nCBObject; + *pS << nReserved1; + *pS << nReserved2; + *pS << nReserved3; + *pS << nReserved4; + } +}; + +SAL_DLLPUBLIC_EXPORT sal_Bool GetMathTypeVersion( SotStorage* pStor, sal_uInt8 &nVersion ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/format.cxx b/starmath/source/format.cxx new file mode 100644 index 000000000000..0e612126b00f --- /dev/null +++ b/starmath/source/format.cxx @@ -0,0 +1,244 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <tools/stream.hxx> +#include <vcl/svapp.hxx> +#include <editeng/scripttypeitem.hxx> +#include "format.hxx" + +///////////////////////////////////////////////////////////////// + +// Latin default-fonts +static const sal_uInt16 aLatinDefFnts[FNT_END] = +{ + DEFAULTFONT_SERIF, // FNT_VARIABLE + DEFAULTFONT_SERIF, // FNT_FUNCTION + DEFAULTFONT_SERIF, // FNT_NUMBER + DEFAULTFONT_SERIF, // FNT_TEXT + DEFAULTFONT_SERIF, // FNT_SERIF + DEFAULTFONT_SANS, // FNT_SANS + DEFAULTFONT_FIXED // FNT_FIXED + //OpenSymbol, // FNT_MATH +}; + +// CJK default-fonts +//! we use non-asian fonts for variables, functions and numbers since they +//! look better and even in asia only latin letters will be used for those. +//! At least that's what I was told... +static const sal_uInt16 aCJKDefFnts[FNT_END] = +{ + DEFAULTFONT_SERIF, // FNT_VARIABLE + DEFAULTFONT_SERIF, // FNT_FUNCTION + DEFAULTFONT_SERIF, // FNT_NUMBER + DEFAULTFONT_CJK_TEXT, // FNT_TEXT + DEFAULTFONT_CJK_TEXT, // FNT_SERIF + DEFAULTFONT_CJK_DISPLAY, // FNT_SANS + DEFAULTFONT_CJK_TEXT // FNT_FIXED + //OpenSymbol, // FNT_MATH +}; + +// CTL default-fonts +static const sal_uInt16 aCTLDefFnts[FNT_END] = +{ + DEFAULTFONT_CTL_TEXT, // FNT_VARIABLE + DEFAULTFONT_CTL_TEXT, // FNT_FUNCTION + DEFAULTFONT_CTL_TEXT, // FNT_NUMBER + DEFAULTFONT_CTL_TEXT, // FNT_TEXT + DEFAULTFONT_CTL_TEXT, // FNT_SERIF + DEFAULTFONT_CTL_TEXT, // FNT_SANS + DEFAULTFONT_CTL_TEXT // FNT_FIXED + //OpenSymbol, // FNT_MATH +}; + + +String GetDefaultFontName( LanguageType nLang, sal_uInt16 nIdent ) +{ + OSL_ENSURE( /*FNT_BEGIN <= nIdent &&*/ nIdent <= FNT_END, + "index out opd range" ); + + if (FNT_MATH == nIdent) + return String::CreateFromAscii( FNTNAME_MATH ); + else + { + const sal_uInt16 *pTable; + switch ( SvtLanguageOptions::GetScriptTypeOfLanguage( nLang ) ) + { + case SCRIPTTYPE_LATIN : pTable = aLatinDefFnts; break; + case SCRIPTTYPE_ASIAN : pTable = aCJKDefFnts; break; + case SCRIPTTYPE_COMPLEX : pTable = aCTLDefFnts; break; + default : + pTable = aLatinDefFnts; + OSL_FAIL( "unknown script-type" ); + } + + return Application::GetDefaultDevice()->GetDefaultFont( + pTable[ nIdent ], nLang, + DEFAULTFONT_FLAGS_ONLYONE ).GetName(); + } +} + +///////////////////////////////////////////////////////////////// + +SmFormat::SmFormat() +: aBaseSize(0, SmPtsTo100th_mm(12)) +{ + nVersion = SM_FMT_VERSION_NOW; + + eHorAlign = AlignCenter; + nGreekCharStyle = 0; + bIsTextmode = bScaleNormalBrackets = false; + + vSize[SIZ_TEXT] = 100; + vSize[SIZ_INDEX] = 60; + vSize[SIZ_FUNCTION] = + vSize[SIZ_OPERATOR] = 100; + vSize[SIZ_LIMITS] = 60; + + vDist[DIS_HORIZONTAL] = 10; + vDist[DIS_VERTICAL] = 5; + vDist[DIS_ROOT] = 0; + vDist[DIS_SUPERSCRIPT] = + vDist[DIS_SUBSCRIPT] = 20; + vDist[DIS_NUMERATOR] = + vDist[DIS_DENOMINATOR] = 0; + vDist[DIS_FRACTION] = 10; + vDist[DIS_STROKEWIDTH] = 5; + vDist[DIS_UPPERLIMIT] = + vDist[DIS_LOWERLIMIT] = 0; + vDist[DIS_BRACKETSIZE] = + vDist[DIS_BRACKETSPACE] = 5; + vDist[DIS_MATRIXROW] = 3; + vDist[DIS_MATRIXCOL] = 30; + vDist[DIS_ORNAMENTSIZE] = + vDist[DIS_ORNAMENTSPACE] = 0; + vDist[DIS_OPERATORSIZE] = 50; + vDist[DIS_OPERATORSPACE] = 20; + vDist[DIS_LEFTSPACE] = + vDist[DIS_RIGHTSPACE] = 100; + vDist[DIS_TOPSPACE] = + vDist[DIS_BOTTOMSPACE] = + vDist[DIS_NORMALBRACKETSIZE] = 0; + + vFont[FNT_VARIABLE] = + vFont[FNT_FUNCTION] = + vFont[FNT_NUMBER] = + vFont[FNT_TEXT] = + vFont[FNT_SERIF] = SmFace(C2S(FNTNAME_TIMES), aBaseSize); + vFont[FNT_SANS] = SmFace(C2S(FNTNAME_HELV), aBaseSize); + vFont[FNT_FIXED] = SmFace(C2S(FNTNAME_COUR), aBaseSize); + vFont[FNT_MATH] = SmFace(C2S(FNTNAME_MATH), aBaseSize); + + vFont[FNT_MATH].SetCharSet( RTL_TEXTENCODING_UNICODE ); + + vFont[FNT_VARIABLE].SetItalic(ITALIC_NORMAL); + vFont[FNT_FUNCTION].SetItalic(ITALIC_NONE); + vFont[FNT_NUMBER] .SetItalic(ITALIC_NONE); + vFont[FNT_TEXT] .SetItalic(ITALIC_NONE); + vFont[FNT_SERIF] .SetItalic(ITALIC_NONE); + vFont[FNT_SANS] .SetItalic(ITALIC_NONE); + vFont[FNT_FIXED] .SetItalic(ITALIC_NONE); + + for ( sal_uInt16 i = FNT_BEGIN; i <= FNT_END; i++ ) + { + SmFace &rFace = vFont[i]; + rFace.SetTransparent( true ); + rFace.SetAlign( ALIGN_BASELINE ); + rFace.SetColor( COL_AUTO ); + bDefaultFont[i] = false; + } +} + + +void SmFormat::SetFont(sal_uInt16 nIdent, const SmFace &rFont, bool bDefault ) +{ + vFont[nIdent] = rFont; + vFont[nIdent].SetTransparent( true ); + vFont[nIdent].SetAlign( ALIGN_BASELINE ); + + bDefaultFont[nIdent] = bDefault; +} + +SmFormat & SmFormat::operator = (const SmFormat &rFormat) +{ + SetBaseSize(rFormat.GetBaseSize()); + SetVersion (rFormat.GetVersion()); + SetHorAlign(rFormat.GetHorAlign()); + SetTextmode(rFormat.IsTextmode()); + SetGreekCharStyle(rFormat.GetGreekCharStyle()); + SetScaleNormalBrackets(rFormat.IsScaleNormalBrackets()); + + sal_uInt16 i; + for (i = FNT_BEGIN; i <= FNT_END; i++) + { + SetFont(i, rFormat.GetFont(i)); + SetDefaultFont(i, rFormat.IsDefaultFont(i)); + } + for (i = SIZ_BEGIN; i <= SIZ_END; i++) + SetRelSize(i, rFormat.GetRelSize(i)); + for (i = DIS_BEGIN; i <= DIS_END; i++) + SetDistance(i, rFormat.GetDistance(i)); + + return *this; +} + + +bool SmFormat::operator == (const SmFormat &rFormat) const +{ + bool bRes = aBaseSize == rFormat.aBaseSize && + eHorAlign == rFormat.eHorAlign && + nGreekCharStyle == rFormat.nGreekCharStyle && + bIsTextmode == rFormat.bIsTextmode && + bScaleNormalBrackets == rFormat.bScaleNormalBrackets; + + sal_uInt16 i; + for (i = 0; i <= SIZ_END && bRes; ++i) + { + if (vSize[i] != rFormat.vSize[i]) + bRes = false; + } + for (i = 0; i <= DIS_END && bRes; ++i) + { + if (vDist[i] != rFormat.vDist[i]) + bRes = false; + } + for (i = 0; i <= FNT_END && bRes; ++i) + { + if (vFont[i] != rFormat.vFont[i] || + bDefaultFont[i] != rFormat.bDefaultFont[i]) + bRes = false; + } + + return bRes; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/math_pch.cxx b/starmath/source/math_pch.cxx new file mode 100644 index 000000000000..312868097731 --- /dev/null +++ b/starmath/source/math_pch.cxx @@ -0,0 +1,430 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + +#define SMDLL 1 + +#include "starmath.hrc" + +#define ITEMID_FONT 1 +#define ITEMID_FONTHEIGHT 2 +#define ITEMID_LRSPACE 3 +#define ITEMID_WEIGHT 4 + +//--------- ab hier die "generierten" +#include <tools/string.hxx> +#include <tools/solar.h> +#include <tools/contnr.hxx> +#include <tools/rtti.hxx> +#include <tools/ref.hxx> +#include <tools/link.hxx> +#include <svl/brdcst.hxx> +#include <svl/svarray.hxx> +#include <osl/diagnose.h> +#include <svl/hint.hxx> +#include <svl/smplhint.hxx> +#include <sot/sotref.hxx> +#include <tools/globname.hxx> +#include <sot/factory.hxx> +#include <vcl/sv.h> +#include <basic/sbxdef.hxx> +#include <tools/time.hxx> +#include <tools/gen.hxx> +#include <tools/stream.hxx> +#include <tools/errinf.hxx> +#include <tools/errcode.hxx> +#include <sot/object.hxx> +#include <sot/sotdata.hxx> +#include <sfx2/shell.hxx> +#include <sal/types.h> +#include <sal/config.h> +#include <tools/date.hxx> +#include <vcl/accel.hxx> +#include <tools/resid.hxx> +#include <tools/rc.hxx> +#include <i18npool/lang.h> +#include <tools/resmgr.hxx> +#include <vcl/keycod.hxx> +#include <vcl/keycodes.hxx> +#include <vcl/vclenum.hxx> +#include <vcl/cmdevt.hxx> +#include <vcl/font.hxx> +#include <tools/color.hxx> +#include <vcl/region.hxx> +#include <vcl/mapmod.hxx> +#include <tools/fract.hxx> +#include <vcl/wall.hxx> +#include <vcl/settings.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/pointr.hxx> +#include <vcl/ptrstyle.hxx> +#include <vcl/wintypes.hxx> +#include <vcl/inputctx.hxx> +#include <vcl/event.hxx> +#include <format.hxx> +#include <utility.hxx> +#include <vcl/fixed.hxx> +#include <vcl/ctrl.hxx> +#include <vcl/window.hxx> +#include <sfx2/minarray.hxx> +#include <vcl/combobox.hxx> +#include <vcl/combobox.h> +#include <vcl/menu.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/lstbox.hxx> +#include <vcl/lstbox.h> +#include <usr/guid.hxx> +#include <usr/sequ.hxx> +#include <uno/types.h> +#include <uno/macros.h> +#include <osl/mutex.h> +#include <tools/shl.hxx> +#include <sfx2/module.hxx> +#include <sfx2/imgdef.hxx> +#include <usr/uno.hxx> +#include <usr/xiface.hxx> +#include <usr/ustring.hxx> +#include <salhelper/simplereferenceobject.hxx> +#include <osl/types.h> +#include <osl/interlck.h> +#include <smdll.hxx> +#include <sfx2/sfxsids.hrc> +#include <chaos/cntids.hrc> +#include <svl/cntwids.hrc> +#include <svl/solar.hrc> +#include <svl/lstner.hxx> +#include <starmath.hrc> +#include <basic/sbx.hxx> +#include <basic/sbxform.hxx> +#include <basic/sbxobj.hxx> +#include <basic/sbxvar.hxx> +#include <basic/sbxcore.hxx> +#include <basic/sbxprop.hxx> +#include <basic/sbxmeth.hxx> +#include <tools/unqid.hxx> +#include <svl/poolitem.hxx> +#include <svtools/args.hxx> +#include <smmod.hxx> +#include <osl/thread.hxx> +#include <osl/thread.h> +#include <vcl/apptypes.hxx> +#include <tools/dynary.hxx> +#include <vcl/svapp.hxx> +#include <vcl/timer.hxx> +#include <sfx2/app.hxx> +#include <sfx2/sfx.hrc> +#include <svl/memberid.hrc> +#include <vcl/syswin.hxx> +#include <tools/datetime.hxx> +#include <tools/wldcrd.hxx> +#include <parse.hxx> +#include <tools/stack.hxx> +#include <types.hxx> +#include <config.hxx> +#include <svtools/confitem.hxx> +#include <tools/poly.hxx> +#include <svx/xpoly.hxx> +#include <rect.hxx> +#include <vcl/outdev.hxx> +#include <smart/com/sun/star/frame/XDispatchProviderInterceptor.hxx> +#include <smart/com/sun/star/frame/XDispatch.hxx> +#include <smart/com/sun/star/frame/XDispatchProvider.hxx> +#include <smart/com/sun/star/frame/XStatusListener.hxx> +#include <smart/com/sun/star/frame/FrameSearchFlag.hxx> +#include <smart/com/sun/star/frame/XDispatchProviderInterception.hxx> +#include <smart/com/sun/star/frame/FeatureStateEvent.hxx> +#include <smart/com/sun/star/frame/DispatchDescriptor.hxx> +#include <smart/com/sun/star/frame/XFrameActionListener.hxx> +#include <smart/com/sun/star/frame/XComponentLoader.hxx> +#include <smart/com/sun/star/frame/XFrame.hxx> +#include <smart/com/sun/star/frame/FrameActionEvent.hxx> +#include <smart/com/sun/star/frame/FrameAction.hxx> +#include <smart/com/sun/star/util/XURLTransformer.hxx> +#include <smart/com/sun/star/task/XStatusIndicatorFactory.hxx> +#include <smart/com/sun/star/task/XStatusIndicatorSupplier.hxx> +#include <smart/com/sun/star/task/XStatusIndicator.hxx> +#include <smart/com/sun/star/frame/XBrowseHistoryRegistry.hxx> +#include <smart/com/sun/star/io/BufferSizeExceededException.hxx> +#include <smart/com/sun/star/io/NotConnectedException.hxx> +#include <smart/com/sun/star/io/IOException.hxx> +#include <smart/com/sun/star/io/UnexpectedEOFException.hxx> +#include <smart/com/sun/star/io/WrongFormatException.hxx> +#include <smart/com/sun/star/lang/ServiceNotRegisteredException.hxx> +#include <smart/com/sun/star/lang/NullPointerException.hxx> +#include <smart/com/sun/star/lang/ClassNotFoundException.hxx> +#include <smart/com/sun/star/lang/NoSuchMethodException.hxx> +#include <smart/com/sun/star/lang/SecurityException.hxx> +#include <smart/com/sun/star/lang/NoSuchFieldException.hxx> +#include <smart/com/sun/star/lang/DisposedException.hxx> +#include <smart/com/sun/star/lang/ArrayIndexOutOfBoundsException.hxx> +#include <smart/com/sun/star/lang/IllegalAccessException.hxx> +#include <smart/com/sun/star/lang/IndexOutOfBoundsException.hxx> +#include <smart/com/sun/star/lang/IllegalArgumentException.hxx> +#include <smart/com/sun/star/lang/NoSupportException.hxx> +#include <smart/com/sun/star/lang/WrappedTargetException.hxx> +#include <smart/com/sun/star/reflection/ParamInfo.hxx> +#include <smart/com/sun/star/reflection/XIdlArray.hxx> +#include <smart/com/sun/star/reflection/XIdlClassProvider.hxx> +#include <smart/com/sun/star/reflection/FieldAccessMode.hxx> +#include <smart/com/sun/star/reflection/XIdlClass.hxx> +#include <smart/com/sun/star/reflection/XIdlField.hxx> +#include <smart/com/sun/star/reflection/ParamMode.hxx> +#include <smart/com/sun/star/reflection/MethodMode.hxx> +#include <smart/com/sun/star/reflection/XIdlMember.hxx> +#include <smart/com/sun/star/reflection/XIdlReflection.hxx> +#include <smart/com/sun/star/reflection/XIdlMethod.hxx> +#include <smart/com/sun/star/reflection/InvocationTargetException.hxx> +#include <smart/com/sun/star/beans/PropertyValues.hxx> +#include <smart/com/sun/star/beans/XPropertySet.hxx> +#include <smart/com/sun/star/beans/PropertyValue.hxx> +#include <smart/com/sun/star/beans/PropertyState.hxx> +#include <smart/com/sun/star/beans/XPropertySetInfo.hxx> +#include <smart/com/sun/star/beans/XMultiPropertySet.hxx> +#include <smart/com/sun/star/beans/XFastPropertySet.hxx> +#include <smart/com/sun/star/beans/XVetoableChangeListener.hxx> +#include <smart/com/sun/star/beans/XPropertyState.hxx> +#include <smart/com/sun/star/beans/XPropertyStateChangeListener.hxx> +#include <smart/com/sun/star/beans/PropertyAttribute.hxx> +#include <smart/com/sun/star/beans/XPropertiesChangeListener.hxx> +#include <smart/com/sun/star/beans/XPropertyChangeListener.hxx> +#include <smart/com/sun/star/beans/XPropertyAccess.hxx> +#include <smart/com/sun/star/beans/XPropertyContainer.hxx> +#include <smart/com/sun/star/beans/PropertyStateChangeEvent.hxx> +#include <smart/com/sun/star/beans/PropertyChangeEvent.hxx> +#include <smart/com/sun/star/beans/UnknownPropertyException.hxx> +#include <smart/com/sun/star/beans/IntrospectionException.hxx> +#include <smart/com/sun/star/beans/PropertyExistException.hxx> +#include <smart/com/sun/star/beans/IllegalTypeException.hxx> +#include <smart/com/sun/star/beans/PropertyVetoException.hxx> +#include <smart/com/sun/star/container/XEnumerationAccess.hxx> +#include <smart/com/sun/star/container/XHierarchicalNameAccess.hxx> +#include <smart/com/sun/star/container/XNameAccess.hxx> +#include <smart/com/sun/star/container/XContentEnumerationAccess.hxx> +#include <smart/com/sun/star/container/XEnumeration.hxx> +#include <smart/com/sun/star/container/XElementAccess.hxx> +#include <smart/com/sun/star/container/XIndexAccess.hxx> +#include <smart/com/sun/star/lang/XEventListener.hxx> +#include <smart/com/sun/star/lang/EventObject.hxx> +#include <smart/com/sun/star/script/XAllListenerAdapterService.hxx> +#include <smart/com/sun/star/script/XAllListener.hxx> +#include <smart/com/sun/star/script/AllEventObject.hxx> +#include <smart/com/sun/star/container/XComponentEnumeration.hxx> +#include <smart/com/sun/star/lang/XComponent.hxx> +#include <smart/com/sun/star/container/XComponentEnumerationAccess.hxx> +#include <smart/com/sun/star/lang/ListenerExistException.hxx> +#include <smart/com/sun/star/container/ElementExistException.hxx> +#include <smart/com/sun/star/lang/InvalidListenerException.hxx> +#include <smart/com/sun/star/container/NoSuchElementException.hxx> +#include <smart/com/sun/star/awt/XKeyListener.hxx> +#include <smart/com/sun/star/awt/XPaintListener.hxx> +#include <smart/com/sun/star/awt/KeyEvent.hxx> +#include <smart/com/sun/star/awt/KeyModifier.hxx> +#include <smart/com/sun/star/awt/XMouseMotionListener.hxx> +#include <smart/com/sun/star/awt/FocusEvent.hxx> +#include <smart/com/sun/star/awt/XWindowListener.hxx> +#include <smart/com/sun/star/awt/XActivateListener.hxx> +#include <smart/com/sun/star/awt/MouseEvent.hxx> +#include <smart/com/sun/star/awt/XTopWindowListener.hxx> +#include <smart/com/sun/star/awt/PaintEvent.hxx> +#include <smart/com/sun/star/awt/InputEvent.hxx> +#include <smart/com/sun/star/awt/KeyGroup.hxx> +#include <smart/com/sun/star/awt/Key.hxx> +#include <smart/com/sun/star/awt/WindowEvent.hxx> +#include <smart/com/sun/star/awt/XMouseListener.hxx> +#include <smart/com/sun/star/awt/KeyFunction.hxx> +#include <smart/com/sun/star/awt/FocusChangeReason.hxx> +#include <smart/com/sun/star/awt/MouseButton.hxx> +#include <smart/com/sun/star/awt/XFocusListener.hxx> +#include <smart/com/sun/star/awt/XAdjustmentListener.hxx> +#include <smart/com/sun/star/awt/XActionListener.hxx> +#include <smart/com/sun/star/awt/XTextListener.hxx> +#include <smart/com/sun/star/awt/XSpinListener.hxx> +#include <smart/com/sun/star/awt/XItemListener.hxx> +#include <smart/com/sun/star/awt/XVclContainerListener.hxx> +#include <smart/com/sun/star/awt/XFileDialog.hxx> +#include <smart/com/sun/star/awt/XTextComponent.hxx> +#include <smart/com/sun/star/awt/XListBox.hxx> +#include <smart/com/sun/star/awt/XProgressMonitor.hxx> +#include <smart/com/sun/star/awt/TextAlign.hxx> +#include <smart/com/sun/star/awt/XScrollBar.hxx> +#include <smart/com/sun/star/awt/XVclContainerPeer.hxx> +#include <smart/com/sun/star/awt/XTabControllerModel.hxx> +#include <smart/com/sun/star/awt/XMessageBox.hxx> +#include <smart/com/sun/star/awt/XTextEditField.hxx> +#include <smart/com/sun/star/awt/Style.hxx> +#include <smart/com/sun/star/awt/XTimeField.hxx> +#include <smart/com/sun/star/awt/XVclWindowPeer.hxx> +#include <smart/com/sun/star/awt/XControlModel.hxx> +#include <smart/com/sun/star/awt/XSpinField.hxx> +#include <smart/com/sun/star/awt/XUnoControlContainer.hxx> +#include <smart/com/sun/star/awt/XTextLayoutConstrains.hxx> +#include <smart/com/sun/star/awt/XNumericField.hxx> +#include <smart/com/sun/star/awt/XButton.hxx> +#include <smart/com/sun/star/awt/XTextArea.hxx> +#include <smart/com/sun/star/awt/XImageButton.hxx> +#include <smart/com/sun/star/awt/XFixedText.hxx> +#include <smart/com/sun/star/awt/XControlContainer.hxx> +#include <smart/com/sun/star/awt/XDialog.hxx> +#include <smart/com/sun/star/awt/ScrollBarOrientation.hxx> +#include <smart/com/sun/star/awt/XRadioButton.hxx> +#include <smart/com/sun/star/awt/XCurrencyField.hxx> +#include <smart/com/sun/star/awt/XPatternField.hxx> +#include <smart/com/sun/star/awt/VclWindowPeerAttribute.hxx> +#include <smart/com/sun/star/awt/XTabController.hxx> +#include <smart/com/sun/star/awt/XVclContainer.hxx> +#include <smart/com/sun/star/awt/XDateField.hxx> +#include <smart/com/sun/star/awt/XComboBox.hxx> +#include <smart/com/sun/star/awt/XControl.hxx> +#include <smart/com/sun/star/awt/XCheckBox.hxx> +#include <smart/com/sun/star/awt/MessageBoxCommand.hxx> +#include <smart/com/sun/star/awt/XLayoutConstrains.hxx> +#include <smart/com/sun/star/awt/XProgressBar.hxx> +#include <smart/com/sun/star/awt/SimpleFontMetric.hxx> +#include <smart/com/sun/star/awt/FontWeight.hxx> +#include <smart/com/sun/star/awt/FontSlant.hxx> +#include <smart/com/sun/star/awt/CharSet.hxx> +#include <smart/com/sun/star/awt/FontDescriptor.hxx> +#include <smart/com/sun/star/awt/FontWidth.hxx> +#include <smart/com/sun/star/awt/XFont.hxx> +#include <smart/com/sun/star/awt/FontType.hxx> +#include <smart/com/sun/star/awt/FontUnderline.hxx> +#include <smart/com/sun/star/awt/FontStrikeout.hxx> +#include <smart/com/sun/star/awt/FontFamily.hxx> +#include <smart/com/sun/star/awt/FontPitch.hxx> +#include <smart/com/sun/star/awt/XTopWindow.hxx> +#include <smart/com/sun/star/awt/XWindow.hxx> +#include <smart/com/sun/star/awt/PosSize.hxx> +#include <smart/com/sun/star/awt/VclContainerEvent.hxx> +#include <smart/com/sun/star/awt/ItemEvent.hxx> +#include <smart/com/sun/star/awt/SpinEvent.hxx> +#include <smart/com/sun/star/awt/TextEvent.hxx> +#include <smart/com/sun/star/awt/AdjustmentType.hxx> +#include <smart/com/sun/star/awt/ActionEvent.hxx> +#include <smart/com/sun/star/awt/AdjustmentEvent.hxx> +#include <smart/com/sun/star/awt/Rectangle.hxx> +#include <smart/com/sun/star/awt/Selection.hxx> +#include <smart/com/sun/star/awt/Size.hxx> +#include <smart/com/sun/star/awt/WindowDescriptor.hxx> +#include <smart/com/sun/star/awt/InvalidateStyle.hxx> +#include <smart/com/sun/star/awt/XToolkit.hxx> +#include <smart/com/sun/star/awt/XWindowPeer.hxx> +#include <smart/com/sun/star/awt/WindowClass.hxx> +#include <smart/com/sun/star/awt/XSystemDependentWindowPeer.hxx> +#include <smart/com/sun/star/awt/WindowAttribute.hxx> +#include <smart/com/sun/star/awt/XPointer.hxx> +#include <smart/com/sun/star/awt/SystemPointer.hxx> +#include <smart/com/sun/star/awt/XView.hxx> +#include <usr/refl.hxx> +#include <sfx2/msg.hxx> +#include <svl/itemset.hxx> +#include <sfx2/basedlgs.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/objface.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <symbol.hxx> +#include <svl/itempool.hxx> +#include <vcl/image.hxx> +#include <vcl/metric.hxx> +#include <sfx2/inimgr.hxx> +#include <node.hxx> +#include <tools/table.hxx> +#include <sfx2/docfac.hxx> +#include <svl/ownlist.hxx> +#include <sfx2/objsh.hxx> +#include <svl/stritem.hxx> +#include <sfx2/ipfrm.hxx> +#include <vcl/dialog.hxx> +#include <sfx2/dispatch.hxx> +#include <svl/svstdarr.hxx> +#include <sfx2/bindings.hxx> +#include <dialog.hxx> +#include <vcl/symbol.hxx> +#include <sfx2/tabdlg.hxx> +#include <vcl/button.hxx> +#include <vcl/tabdlg.hxx> +#include <vcl/tabpage.hxx> +#include <vcl/tabctrl.hxx> +#include <svx/optgenrl.hxx> +#include <vcl/edit.hxx> +#include <vcl/group.hxx> +#include <document.hxx> +#include <vcl/spinfld.hxx> +#include <vcl/menubtn.hxx> +#include <svtools/ctrlbox.hxx> +#include <vcl/virdev.hxx> +#include <vcl/field.hxx> +#include <svtools/ctrltool.hxx> +#include <sfx2/interno.hxx> +#include <sfx2/sfxdefs.hxx> +#include <sfx2/childwin.hxx> +#include <sfx2/chalign.hxx> +#include <vcl/floatwin.hxx> +#include <sot/storage.hxx> +#include <rsc/rscsfx.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/btndlg.hxx> +#include <uno/uno.h> +#include <uno/string.h> +#include <uno/sequence.h> +#include <uno/any.h> +#include <uno/exceptn.h> +#include <uno/intrface.h> +#include <uno/factory.h> +#include <uno/api.h> +#include <svx/svxids.hrc> +#include <view.hxx> +#include <sfx2/dockwin.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/clientsh.hxx> +#include <svtools/scrwin.hxx> +#include <vcl/scrbar.hxx> +#include <sfx2/ctrlitem.hxx> +#include <sfx2/viewfac.hxx> +#include <edit.hxx> +#include <editeng/editdata.hxx> +#include <toolbox.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/dockwin.hxx> +#include <smslots.hxx> +#include <svl/undo.hxx> +#include <sfx2/request.hxx> +#include <svl/whiter.hxx> +#include <vcl/prntypes.hxx> +#include <vcl/jobset.hxx> +#include <vcl/gdimtf.hxx> +#include <sot/exchange.hxx> +#include <vcl/wrkwin.hxx> +#include <action.hxx> +#include <sfx2/filedlg.hxx> +#include <sfx2/iodlg.hxx> + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathmlexport.cxx b/starmath/source/mathmlexport.cxx new file mode 100644 index 000000000000..fe8f77f93918 --- /dev/null +++ b/starmath/source/mathmlexport.cxx @@ -0,0 +1,1503 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + +/* + Warning: The SvXMLElementExport helper class creates the beginning and + closing tags of xml elements in its constructor and destructor, so theres + hidden stuff going on, on occasion the ordering of these classes declarations + may be significant +*/ + + +#include <com/sun/star/xml/sax/XErrorHandler.hpp> +#include <com/sun/star/xml/sax/XEntityResolver.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XDTDHandler.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XActiveDataControl.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <com/sun/star/task/XStatusIndicatorFactory.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/uno/Any.h> + +#include <rtl/math.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/docfile.hxx> +#include <osl/diagnose.h> +#include <tools/urlobj.hxx> +#include <svtools/sfxecode.hxx> +#include <unotools/saveopt.hxx> +#include <svl/stritem.hxx> +#include <svl/itemprop.hxx> +#include <unotools/processfactory.hxx> +#include <unotools/streamwrap.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/nmspmap.hxx> +#include <xmloff/attrlist.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/xmlmetai.hxx> +#include <osl/mutex.hxx> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/servicehelper.hxx> + +#include <memory> + +#include "mathmlexport.hxx" +#include <starmath.hrc> +#include <unomodel.hxx> +#include <document.hxx> +#include <utility.hxx> +#include <config.hxx> + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; +using namespace ::xmloff::token; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +#define EXPORT_SVC_NAME RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.XMLExportFilter") + +#undef WANTEXCEPT + + +//////////////////////////////////////////////////////////// + +sal_Bool SmXMLExportWrapper::Export(SfxMedium &rMedium) +{ + sal_Bool bRet=sal_True; + uno::Reference<lang::XMultiServiceFactory> + xServiceFactory(utl::getProcessServiceFactory()); + OSL_ENSURE(xServiceFactory.is(),"got no service manager"); + + //Get model + uno::Reference< lang::XComponent > xModelComp(xModel, uno::UNO_QUERY ); + + sal_Bool bEmbedded = sal_False; + uno::Reference <lang::XUnoTunnel> xTunnel; + xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY); + SmModel *pModel = reinterpret_cast<SmModel *> + (xTunnel->getSomething(SmModel::getUnoTunnelId())); + + SmDocShell *pDocShell = pModel ? + static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0; + if ( pDocShell && + SFX_CREATE_MODE_EMBEDDED == pDocShell->GetCreateMode() ) + bEmbedded = sal_True; + + uno::Reference<task::XStatusIndicator> xStatusIndicator; + if (!bEmbedded) + { + if (pDocShell /*&& pDocShell->GetMedium()*/) + { + OSL_ENSURE( pDocShell->GetMedium() == &rMedium, + "different SfxMedium found" ); + + SfxItemSet* pSet = rMedium.GetItemSet(); + if (pSet) + { + const SfxUnoAnyItem* pItem = static_cast<const SfxUnoAnyItem*>( + pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) ); + if (pItem) + pItem->GetValue() >>= xStatusIndicator; + } + } + + // set progress range and start status indicator + if (xStatusIndicator.is()) + { + sal_Int32 nProgressRange = bFlat ? 1 : 3; + xStatusIndicator->start(String(SmResId(STR_STATSTR_WRITING)), + nProgressRange); + } + } + + + // create XPropertySet with three properties for status indicator + comphelper::PropertyMapEntry aInfoMap[] = + { + { "UsePrettyPrinting", sizeof("UsePrettyPrinting")-1, 0, + &::getBooleanCppuType(), + beans::PropertyAttribute::MAYBEVOID, 0}, + { "BaseURI", sizeof("BaseURI")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StreamRelPath", sizeof("StreamRelPath")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StreamName", sizeof("StreamName")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { NULL, 0, 0, NULL, 0, 0 } + }; + uno::Reference< beans::XPropertySet > xInfoSet( + comphelper::GenericPropertySet_CreateInstance( + new comphelper::PropertySetInfo( aInfoMap ) ) ); + + SvtSaveOptions aSaveOpt; + OUString sUsePrettyPrinting(RTL_CONSTASCII_USTRINGPARAM("UsePrettyPrinting")); + sal_Bool bUsePrettyPrinting( bFlat || aSaveOpt.IsPrettyPrinting() ); + Any aAny; + aAny.setValue( &bUsePrettyPrinting, ::getBooleanCppuType() ); + xInfoSet->setPropertyValue( sUsePrettyPrinting, aAny ); + + // Set base URI + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("BaseURI") ); + xInfoSet->setPropertyValue( sPropName, makeAny( rMedium.GetBaseURL( true ) ) ); + + sal_Int32 nSteps=0; + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + if (!bFlat) //Storage (Package) of Stream + { + uno::Reference < embed::XStorage > xStg = rMedium.GetOutputStorage(); + sal_Bool bOASIS = ( SotStorage::GetVersion( xStg ) > SOFFICE_FILEFORMAT_60 ); + + // TODO/LATER: handle the case of embedded links gracefully + if ( bEmbedded ) //&& !pStg->IsRoot() ) + { + OUString aName; + if ( rMedium.GetItemSet() ) + { + const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>( + rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) ); + if ( pDocHierarchItem ) + aName = pDocHierarchItem->GetValue(); + } + + if ( aName.getLength() ) + { + sPropName = OUString(RTL_CONSTASCII_USTRINGPARAM("StreamRelPath")); + xInfoSet->setPropertyValue( sPropName, makeAny( aName ) ); + } + } + + if ( !bEmbedded ) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + bRet = WriteThroughComponent( + xStg, xModelComp, "meta.xml", xServiceFactory, xInfoSet, + (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaExporter" + : "com.sun.star.comp.Math.XMLMetaExporter"), + sal_False); + } + if ( bRet ) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + bRet = WriteThroughComponent( + xStg, xModelComp, "content.xml", xServiceFactory, xInfoSet, + "com.sun.star.comp.Math.XMLContentExporter"); + } + + if ( bRet ) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + bRet = WriteThroughComponent( + xStg, xModelComp, "settings.xml", xServiceFactory, xInfoSet, + (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsExporter" + : "com.sun.star.comp.Math.XMLSettingsExporter") ); + } + } + else + { + SvStream *pStream = rMedium.GetOutStream(); + uno::Reference<io::XOutputStream> xOut( + new utl::OOutputStreamWrapper(*pStream) ); + + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + bRet = WriteThroughComponent( + xOut, xModelComp, xServiceFactory, xInfoSet, + "com.sun.star.comp.Math.XMLContentExporter"); + } + + if (xStatusIndicator.is()) + xStatusIndicator->end(); + + return bRet; +} + + +/// export through an XML exporter component (output stream version) +sal_Bool SmXMLExportWrapper::WriteThroughComponent( + Reference<io::XOutputStream> xOutputStream, + Reference<XComponent> xComponent, + Reference<lang::XMultiServiceFactory> & rFactory, + Reference<beans::XPropertySet> & rPropSet, + const sal_Char* pComponentName ) +{ + OSL_ENSURE(xOutputStream.is(), "I really need an output stream!"); + OSL_ENSURE(xComponent.is(), "Need component!"); + OSL_ENSURE(NULL != pComponentName, "Need component name!"); + + // get component + Reference< io::XActiveDataSource > xSaxWriter( + rFactory->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer") )), + UNO_QUERY ); + OSL_ENSURE( xSaxWriter.is(), "can't instantiate XML writer" ); + if (!xSaxWriter.is()) + return sal_False; + + // connect XML writer to output stream + xSaxWriter->setOutputStream( xOutputStream ); + + // prepare arguments (prepend doc handler to given arguments) + Reference<xml::sax::XDocumentHandler> xDocHandler( xSaxWriter,UNO_QUERY); + + Sequence<Any> aArgs( 2 ); + aArgs[0] <<= xDocHandler; + aArgs[1] <<= rPropSet; + + // get filter component + Reference< document::XExporter > xExporter( + rFactory->createInstanceWithArguments( + OUString::createFromAscii(pComponentName), aArgs), UNO_QUERY); + OSL_ENSURE( xExporter.is(), + "can't instantiate export filter component" ); + if ( !xExporter.is() ) + return sal_False; + + + // connect model and filter + xExporter->setSourceDocument( xComponent ); + + // filter! + Reference < XFilter > xFilter( xExporter, UNO_QUERY ); + uno::Sequence< PropertyValue > aProps(0); + xFilter->filter( aProps ); + + uno::Reference<lang::XUnoTunnel> xFilterTunnel; + xFilterTunnel = uno::Reference<lang::XUnoTunnel> + ( xFilter, uno::UNO_QUERY ); + SmXMLExport *pFilter = reinterpret_cast< SmXMLExport * >( + sal::static_int_cast< sal_uIntPtr >( + xFilterTunnel->getSomething( SmXMLExport::getUnoTunnelId() ))); + return pFilter ? pFilter->GetSuccess() : sal_True; +} + + +/// export through an XML exporter component (storage version) +sal_Bool SmXMLExportWrapper::WriteThroughComponent( + const Reference < embed::XStorage >& xStorage, + Reference<XComponent> xComponent, + const sal_Char* pStreamName, + Reference<lang::XMultiServiceFactory> & rFactory, + Reference<beans::XPropertySet> & rPropSet, + const sal_Char* pComponentName, + sal_Bool bCompress + ) +{ + OSL_ENSURE(xStorage.is(), "Need storage!"); + OSL_ENSURE(NULL != pStreamName, "Need stream name!"); + + // open stream + Reference < io::XStream > xStream; + OUString sStreamName = OUString::createFromAscii(pStreamName); + try + { + xStream = xStorage->openStreamElement( sStreamName, + embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); + } + catch ( uno::Exception& ) + { + OSL_FAIL( "Can't create output stream in package!" ); + return sal_False; + } + + String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) ); + OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") ); + uno::Any aAny; + aAny <<= aMime; + + uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY ); + xSet->setPropertyValue( aPropName, aAny ); + + if ( !bCompress ) + { + aPropName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("Compressed") ); + sal_Bool bFalse = sal_False; + aAny.setValue( &bFalse, ::getBooleanCppuType() ); + xSet->setPropertyValue( aPropName, aAny ); + } + + // even plain stream must be encrypted in encrypted document + OUString aTmpPropName( RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption") ); + sal_Bool bTrue = sal_True; + aAny.setValue( &bTrue, ::getBooleanCppuType() ); + xSet->setPropertyValue( aTmpPropName, aAny ); + + // set Base URL + if ( rPropSet.is() ) + { + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("StreamName") ); + rPropSet->setPropertyValue( sPropName, makeAny( sStreamName ) ); + } + + // write the stuff + sal_Bool bRet = WriteThroughComponent( xStream->getOutputStream(), xComponent, rFactory, + rPropSet, pComponentName ); + + return bRet; +} + +//////////////////////////////////////////////////////////// + +SmXMLExport::SmXMLExport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + sal_uInt16 nExportFlags) +: SvXMLExport( xServiceFactory, MAP_INCH, XML_MATH, nExportFlags ) , + pTree(0) , + bSuccess(sal_False) +{ +} + +sal_Int64 SAL_CALL SmXMLExport::getSomething( + const uno::Sequence< sal_Int8 >& rId ) +throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + return sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_uIntPtr >(this)); + + return SvXMLExport::getSomething( rId ); +} + +namespace +{ + class theSmXMLExportUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSmXMLExportUnoTunnelId> {}; +} + +const uno::Sequence< sal_Int8 > & SmXMLExport::getUnoTunnelId() throw() +{ + return theSmXMLExportUnoTunnelId::get().getSeq(); +} + +OUString SAL_CALL SmXMLExport_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLExporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SmXMLExport_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( EXPORT_SVC_NAME ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmXMLExport_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) + throw( uno::Exception ) +{ + // EXPORT_OASIS is required here allthough there is no differrence between + // OOo and OASIS, because without the flag, a transformation to OOo would + // be chained in. + return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_ALL ); +} + +//////////////////////////////////////////////////////////// + +OUString SAL_CALL SmXMLExportMetaOOO_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLMetaExporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SmXMLExportMetaOOO_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( EXPORT_SVC_NAME ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmXMLExportMetaOOO_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) +throw( uno::Exception ) +{ + return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_META ); +} + +//////////////////////////////////////////////////////////// + +OUString SAL_CALL SmXMLExportMeta_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisMetaExporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SmXMLExportMeta_getSupportedServiceNames() +throw() +{ + const OUString aServiceName( EXPORT_SVC_NAME ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmXMLExportMeta_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) +throw( uno::Exception ) +{ + return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_META ); +} + +//////////////////////////////////////////////////////////// + +OUString SAL_CALL SmXMLExportSettingsOOO_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLSettingsExporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SmXMLExportSettingsOOO_getSupportedServiceNames() +throw() +{ + const OUString aServiceName( EXPORT_SVC_NAME ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmXMLExportSettingsOOO_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) +throw( uno::Exception ) +{ + return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_SETTINGS ); +} + +//////////////////////////////////////////////////////////// + +OUString SAL_CALL SmXMLExportSettings_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisSettingsExporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SmXMLExportSettings_getSupportedServiceNames() +throw() +{ + const OUString aServiceName( EXPORT_SVC_NAME ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmXMLExportSettings_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) +throw( uno::Exception ) +{ + return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_SETTINGS ); +} + +//////////////////////////////////////////////////////////// + +OUString SAL_CALL SmXMLExportContent_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLContentExporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SmXMLExportContent_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( EXPORT_SVC_NAME ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmXMLExportContent_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) +throw( uno::Exception ) +{ + // The EXPORT_OASIS flag is only required to avoid that a transformer is + // chanied in + return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_CONTENT ); +} + +//////////////////////////////////////////////////////////// + +// XServiceInfo +// override empty method from parent class +rtl::OUString SAL_CALL SmXMLExport::getImplementationName() +throw(uno::RuntimeException) +{ + OUString aTxt; + switch( getExportFlags() ) + { + case EXPORT_META: + aTxt = SmXMLExportMeta_getImplementationName(); + break; + case EXPORT_SETTINGS: + aTxt = SmXMLExportSettings_getImplementationName(); + break; + case EXPORT_CONTENT: + aTxt = SmXMLExportContent_getImplementationName(); + break; + case EXPORT_ALL: + default: + aTxt = SmXMLExport_getImplementationName(); + break; + } + return aTxt; +} + +sal_uInt32 SmXMLExport::exportDoc(enum XMLTokenEnum eClass) +{ + if ( (getExportFlags() & EXPORT_CONTENT) == 0 ) + { + SvXMLExport::exportDoc( eClass ); + } + else + { + uno::Reference <frame::XModel> xModel = GetModel(); + uno::Reference <lang::XUnoTunnel> xTunnel; + xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY); + SmModel *pModel = reinterpret_cast<SmModel *> + (xTunnel->getSomething(SmModel::getUnoTunnelId())); + + if (pModel) + { + SmDocShell *pDocShell = + static_cast<SmDocShell*>(pModel->GetObjectShell()); + pTree = pDocShell->GetFormulaTree(); + aText = pDocShell->GetText(); + } + + GetDocHandler()->startDocument(); + + /*Add xmlns line*/ + SvXMLAttributeList &rList = GetAttrList(); + + // make use of a default namespace + ResetNamespaceMap(); // Math doesn't need namespaces from xmloff, since it now uses default namespaces (because that is common with current MathML usage in the web) + _GetNamespaceMap().Add( OUString(), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH ); + + rList.AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH_IDX), + GetNamespaceMap().GetNameByKey( XML_NAMESPACE_MATH_IDX)); + + //I think we need something like ImplExportEntities(); + _ExportContent(); + GetDocHandler()->endDocument(); + } + + bSuccess=sal_True; + return 0; +} + +void SmXMLExport::_ExportContent() +{ + SvXMLElementExport aEquation(*this, XML_NAMESPACE_MATH, XML_MATH, sal_True, sal_True); + SvXMLElementExport *pSemantics=0; + + if (aText.Len()) + { + pSemantics = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, + XML_SEMANTICS, sal_True, sal_True); + } + + ExportNodes(pTree, 0); + + if (aText.Len()) + { + // Convert symbol names + uno::Reference <frame::XModel> xModel = GetModel(); + uno::Reference <lang::XUnoTunnel> xTunnel; + xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY); + SmModel *pModel = reinterpret_cast<SmModel *> + (xTunnel->getSomething(SmModel::getUnoTunnelId())); + SmDocShell *pDocShell = pModel ? + static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0; + OSL_ENSURE( pDocShell, "doc shell missing" ); + if (pDocShell) + { + SmParser &rParser = pDocShell->GetParser(); + bool bVal = rParser.IsExportSymbolNames(); + rParser.SetExportSymbolNames( true ); + SmNode *pTmpTree = rParser.Parse( aText ); + aText = rParser.GetText(); + delete pTmpTree; + rParser.SetExportSymbolNames( bVal ); + } + + AddAttribute(XML_NAMESPACE_MATH, XML_ENCODING, + OUString(RTL_CONSTASCII_USTRINGPARAM("StarMath 5.0"))); + SvXMLElementExport aAnnotation(*this, XML_NAMESPACE_MATH, + XML_ANNOTATION, sal_True, sal_False); + GetDocHandler()->characters(OUString( aText )); + } + delete pSemantics; +} + +void SmXMLExport::GetViewSettings( Sequence < PropertyValue >& aProps) +{ + uno::Reference <frame::XModel> xModel = GetModel(); + if ( !xModel.is() ) + return; + + uno::Reference <lang::XUnoTunnel> xTunnel; + xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY); + SmModel *pModel = reinterpret_cast<SmModel *> + (xTunnel->getSomething(SmModel::getUnoTunnelId())); + + if ( !pModel ) + return; + + SmDocShell *pDocShell = + static_cast<SmDocShell*>(pModel->GetObjectShell()); + if ( !pDocShell ) + return; + + aProps.realloc( 4 ); + PropertyValue *pValue = aProps.getArray(); + sal_Int32 nIndex = 0; + + Rectangle aRect( pDocShell->GetVisArea() ); + + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaTop") ); + pValue[nIndex++].Value <<= aRect.Top(); + + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaLeft") ); + pValue[nIndex++].Value <<= aRect.Left(); + + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaWidth") ); + pValue[nIndex++].Value <<= aRect.GetWidth(); + + pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaHeight") ); + pValue[nIndex++].Value <<= aRect.GetHeight(); +} + +void SmXMLExport::GetConfigurationSettings( Sequence < PropertyValue > & rProps) +{ + Reference < XPropertySet > xProps ( GetModel(), UNO_QUERY ); + if ( xProps.is() ) + { + Reference< XPropertySetInfo > xPropertySetInfo = xProps->getPropertySetInfo(); + if (xPropertySetInfo.is()) + { + Sequence< Property > aProps = xPropertySetInfo->getProperties(); + sal_Int32 nCount(aProps.getLength()); + if (nCount > 0) + { + rProps.realloc(nCount); + PropertyValue* pProps = rProps.getArray(); + if (pProps) + { + SmConfig *pConfig = SM_MOD()->GetConfig(); + const bool bUsedSymbolsOnly = pConfig ? pConfig->IsSaveOnlyUsedSymbols() : false; + + const OUString sFormula ( RTL_CONSTASCII_USTRINGPARAM ( "Formula" ) ); + const OUString sBasicLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "BasicLibraries" ) ); + const OUString sDialogLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "DialogLibraries" ) ); + const OUString sRuntimeUID ( RTL_CONSTASCII_USTRINGPARAM ( "RuntimeUID" ) ); + for (sal_Int32 i = 0; i < nCount; i++, pProps++) + { + const OUString &rPropName = aProps[i].Name; + if (rPropName != sFormula && + rPropName != sBasicLibraries && + rPropName != sDialogLibraries && + rPropName != sRuntimeUID) + { + pProps->Name = rPropName; + + rtl::OUString aActualName( rPropName ); + + // handle 'save used symbols only' + if (bUsedSymbolsOnly && rPropName.equalsAscii("Symbols")) + aActualName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "UserDefinedSymbolsInUse" ) ); + + pProps->Value = xProps->getPropertyValue( aActualName ); + } + } + } + } + } + } +} + +void SmXMLExport::ExportLine(const SmNode *pNode, int nLevel) +{ + ExportExpression(pNode, nLevel); +} + +void SmXMLExport::ExportBinaryHorizontal(const SmNode *pNode, int nLevel) +{ + ExportExpression(pNode, nLevel); +} + +void SmXMLExport::ExportUnaryHorizontal(const SmNode *pNode, int nLevel) +{ + ExportExpression(pNode, nLevel); +} + +void SmXMLExport::ExportExpression(const SmNode *pNode, int nLevel) +{ + SvXMLElementExport *pRow=0; + sal_uLong nSize = pNode->GetNumSubNodes(); + + // #i115443: nodes of type expression always need to be grouped with mrow statement + if (nSize > 1 || (pNode && pNode->GetType() == NEXPRESSION)) + pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW, sal_True, sal_True); + + for (sal_uInt16 i = 0; i < nSize; i++) + if (const SmNode *pTemp = pNode->GetSubNode(i)) + ExportNodes(pTemp, nLevel+1); + + delete pRow; +} + +void SmXMLExport::ExportBinaryVertical(const SmNode *pNode, int nLevel) +{ + OSL_ENSURE(pNode->GetNumSubNodes()==3,"Bad Fraction"); + SvXMLElementExport aFraction(*this, XML_NAMESPACE_MATH, XML_MFRAC, sal_True, sal_True); + ExportNodes(pNode->GetSubNode(0), nLevel); + ExportNodes(pNode->GetSubNode(2), nLevel); +} + +void SmXMLExport::ExportTable(const SmNode *pNode, int nLevel) +{ + SvXMLElementExport *pTable=0; + + sal_uInt16 nSize = pNode->GetNumSubNodes(); + + //If the list ends in newline then the last entry has + //no subnodes, the newline is superfulous so we just drop + //the last node, inclusion would create a bad MathML + //table + if (nSize >= 1 && pNode->GetSubNode(nSize-1)->GetNumSubNodes() == 0) + --nSize; + + // try to avoid creating a mtable element when the formula consists only + // of a single output line + if (nLevel || (nSize >1)) + pTable = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTABLE, sal_True, sal_True); + + for (sal_uInt16 i = 0; i < nSize; i++) + if (const SmNode *pTemp = pNode->GetSubNode(i)) + { + SvXMLElementExport *pRow=0; + SvXMLElementExport *pCell=0; + if (pTable) + { + pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTR, sal_True, sal_True); + pCell = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTD, sal_True, sal_True); + } + ExportNodes(pTemp, nLevel+1); + delete pCell; + delete pRow; + } + + delete pTable; +} + +void SmXMLExport::ExportMath(const SmNode *pNode, int /*nLevel*/) +{ + const SmMathSymbolNode *pTemp = static_cast<const SmMathSymbolNode *>(pNode); + SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, sal_True, sal_False); + sal_Unicode nArse[2]; + nArse[0] = pTemp->GetText().GetChar(0); + sal_Unicode cTmp = ConvertMathToMathML( nArse[0] ); + if (cTmp != 0) + nArse[0] = cTmp; + OSL_ENSURE(nArse[0] != 0xffff,"Non existent symbol"); + nArse[1] = 0; + GetDocHandler()->characters(nArse); +} + +void SmXMLExport::ExportText(const SmNode *pNode, int /*nLevel*/) +{ + SvXMLElementExport *pText; + const SmTextNode *pTemp = static_cast<const SmTextNode *>(pNode); + switch (pNode->GetToken().eType) + { + default: + case TIDENT: + { + //Note that we change the fontstyle to italic for strings that + //are italic and longer than a single character. + sal_Bool bIsItalic = IsItalic( pTemp->GetFont() ); + if ((pTemp->GetText().Len() > 1) && bIsItalic) + AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_ITALIC); + else if ((pTemp->GetText().Len() == 1) && !bIsItalic) + AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL); + pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI,sal_True,sal_False); + break; + } + case TNUMBER: + pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MN,sal_True,sal_False); + break; + case TTEXT: + pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTEXT,sal_True,sal_False); + break; + } + GetDocHandler()->characters(OUString(pTemp->GetText().GetBuffer())); + delete pText; +} + +void SmXMLExport::ExportBlank(const SmNode * /*pNode*/, int /*nLevel*/) +{ + //!! exports an empty <mi> tag since for example "~_~" is allowed in + //!! Math (so it has no sense at all) but must not result in an empty + //!! <msub> tag in MathML !! + + SvXMLElementExport *pText; + + pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, sal_True, sal_False); + + GetDocHandler()->characters( OUString() ); + delete pText; +} + +void SmXMLExport::ExportSubSupScript(const SmNode *pNode, int nLevel) +{ + const SmNode *pSub = 0; + const SmNode *pSup = 0; + const SmNode *pCSub = 0; + const SmNode *pCSup = 0; + const SmNode *pLSub = 0; + const SmNode *pLSup = 0; + SvXMLElementExport *pThing = 0, *pThing2 = 0; + + //if we have prescripts at all then we must use the tensor notation + + //This is one of those excellent locations where scope is vital to + //arrange the construction and destruction of the element helper + //classes correctly + pLSub = pNode->GetSubNode(LSUB+1); + pLSup = pNode->GetSubNode(LSUP+1); + if (pLSub || pLSup) + { + SvXMLElementExport aMultiScripts(*this, XML_NAMESPACE_MATH, + XML_MMULTISCRIPTS, sal_True, sal_True); + + + if (NULL != (pCSub = pNode->GetSubNode(CSUB+1)) + && NULL != (pCSup = pNode->GetSubNode(CSUP+1))) + { + pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, + XML_MUNDEROVER, sal_True,sal_True); + } + else if (NULL != (pCSub = pNode->GetSubNode(CSUB+1))) + { + pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, + XML_MUNDER, sal_True,sal_True); + } + else if (NULL != (pCSup = pNode->GetSubNode(CSUP+1))) + { + pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, + XML_MOVER, sal_True,sal_True); + } + + ExportNodes(pNode->GetSubNode(0), nLevel+1); //Main Term + + if (pCSub) + ExportNodes(pCSub, nLevel+1); + if (pCSup) + ExportNodes(pCSup, nLevel+1); + delete pThing2; + + pSub = pNode->GetSubNode(RSUB+1); + pSup = pNode->GetSubNode(RSUP+1); + if (pSub || pSup) + { + if (pSub) + ExportNodes(pSub, nLevel+1); + else + { + SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,sal_True,sal_True); + } + if (pSup) + ExportNodes(pSup, nLevel+1); + else + { + SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,sal_True,sal_True); + } + } + + //Seperator element between suffix and prefix sub/sup pairs + { + SvXMLElementExport aPrescripts(*this, XML_NAMESPACE_MATH, + XML_MPRESCRIPTS, sal_True,sal_True); + } + + if (pLSub) + ExportNodes(pLSub, nLevel+1); + else + { + SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, + sal_True,sal_True); + + } + if (pLSup) + ExportNodes(pLSup, nLevel+1); + else + { + SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE, + sal_True,sal_True); + + } + } + else + { + if (NULL != (pSub = pNode->GetSubNode(RSUB+1)) && + NULL != (pSup = pNode->GetSubNode(RSUP+1))) + { + pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, + XML_MSUBSUP, sal_True,sal_True); + } + else if (NULL != (pSub = pNode->GetSubNode(RSUB+1))) + { + pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUB, + sal_True,sal_True); + } + else if (NULL != (pSup = pNode->GetSubNode(RSUP+1))) + { + pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUP, + sal_True,sal_True); + } + + if (NULL != (pCSub = pNode->GetSubNode(CSUB+1)) + && NULL != (pCSup=pNode->GetSubNode(CSUP+1))) + { + pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, + XML_MUNDEROVER, sal_True,sal_True); + } + else if (NULL != (pCSub = pNode->GetSubNode(CSUB+1))) + { + pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, + XML_MUNDER, sal_True,sal_True); + } + else if (NULL != (pCSup = pNode->GetSubNode(CSUP+1))) + { + pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, + XML_MOVER, sal_True,sal_True); + } + ExportNodes(pNode->GetSubNode(0), nLevel+1); //Main Term + + if (pCSub) + ExportNodes(pCSub, nLevel+1); + if (pCSup) + ExportNodes(pCSup, nLevel+1); + delete pThing2; + + if (pSub) + ExportNodes(pSub, nLevel+1); + if (pSup) + ExportNodes(pSup, nLevel+1); + delete pThing; + } +} + +void SmXMLExport::ExportBrace(const SmNode *pNode, int nLevel) +{ + const SmNode *pTemp; + const SmNode *pLeft=pNode->GetSubNode(0); + const SmNode *pRight=pNode->GetSubNode(2); + SvXMLElementExport *pFences=0,*pRow=0; + if ( ((pLeft) && (pLeft->GetToken().eType != TNONE)) && + ((pRight) && (pRight->GetToken().eType != TNONE)) && + (pNode->GetScaleMode() == SCALE_HEIGHT)) + { + sal_Unicode nArse[2]; + nArse[1] = 0; + nArse[0] = static_cast< + const SmMathSymbolNode* >(pLeft)->GetText().GetChar(0); + OSL_ENSURE(nArse[0] != 0xffff,"Non existent symbol"); + AddAttribute(XML_NAMESPACE_MATH, XML_OPEN,nArse); + nArse[0] = static_cast< + const SmMathSymbolNode* >(pRight)->GetText().GetChar(0); + OSL_ENSURE(nArse[0] != 0xffff,"Non existent symbol"); + AddAttribute(XML_NAMESPACE_MATH, XML_CLOSE,nArse); + pFences = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MFENCED, + sal_True,sal_True); + } + else if (pLeft && (pLeft->GetToken().eType != TNONE)) + { + pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW, + sal_True, sal_True); + if (pNode->GetScaleMode() == SCALE_HEIGHT) + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE); + else + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE); + ExportNodes(pLeft, nLevel+1); + } + else + pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW, + sal_True, sal_True); + + if (NULL != (pTemp = pNode->GetSubNode(1))) + ExportNodes(pTemp, nLevel+1); + if (pFences) + delete pFences; + else if (pRight && (pRight->GetToken().eType != TNONE)) + { + if (pNode->GetScaleMode() == SCALE_HEIGHT) + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE); + else + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE); + ExportNodes(pRight, nLevel+1); + } + delete pRow; +} + +void SmXMLExport::ExportRoot(const SmNode *pNode, int nLevel) +{ + if (pNode->GetSubNode(0)) + { + SvXMLElementExport aRoot(*this, XML_NAMESPACE_MATH, XML_MROOT,sal_True, + sal_True); + ExportNodes(pNode->GetSubNode(2), nLevel+1); + ExportNodes(pNode->GetSubNode(0), nLevel+1); + } + else + { + SvXMLElementExport aSqrt(*this, XML_NAMESPACE_MATH, XML_MSQRT,sal_True, + sal_True); + ExportNodes(pNode->GetSubNode(2), nLevel+1); + } +} + +void SmXMLExport::ExportOperator(const SmNode *pNode, int nLevel) +{ + /*we need to either use content or font and size attributes + *here*/ + SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW, + sal_True, sal_True); + ExportNodes(pNode->GetSubNode(0), nLevel+1); + ExportNodes(pNode->GetSubNode(1), nLevel+1); +} + +void SmXMLExport::ExportAttributes(const SmNode *pNode, int nLevel) +{ + SvXMLElementExport *pElement=0; + + if (pNode->GetToken().eType == TUNDERLINE) + { + AddAttribute(XML_NAMESPACE_MATH, XML_ACCENTUNDER, + XML_TRUE); + pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER, + sal_True,sal_True); + } + else if (pNode->GetToken().eType != TOVERSTRIKE) + { + AddAttribute(XML_NAMESPACE_MATH, XML_ACCENT, + XML_TRUE); + pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER, + sal_True,sal_True); + } + + ExportNodes(pNode->GetSubNode(1), nLevel+1); + switch (pNode->GetToken().eType) + { + case TOVERLINE: + { + //proper entity support required + SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, + sal_True,sal_True); + sal_Unicode nArse[2] = {0xAF,0x00}; + GetDocHandler()->characters(nArse); + } + break; + case TUNDERLINE: + { + //proper entity support required + SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, + sal_True,sal_True); + sal_Unicode nArse[2] = {0x0332,0x00}; + GetDocHandler()->characters(nArse); + } + break; + case TOVERSTRIKE: + break; + default: + ExportNodes(pNode->GetSubNode(0), nLevel+1); + break; + } + delete pElement; +} + +static bool lcl_HasEffectOnMathvariant( const SmTokenType eType ) +{ + return eType == TBOLD || eType == TNBOLD || + eType == TITALIC || eType == TNBOLD || + eType == TSANS || eType == TSERIF || eType == TFIXED; +} + +void SmXMLExport::ExportFont(const SmNode *pNode, int nLevel) +{ + SvXMLElementExport *pElement = 0; + + // + // gather the mathvariant attribut relevant data from all + // successively following SmFontNodes... + // + int nBold = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true; + int nItalic = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true; + int nSansSerifFixed = -1; + SmTokenType eNodeType = TUNKNOWN; + while (lcl_HasEffectOnMathvariant( (eNodeType = pNode->GetToken().eType) )) + { + switch (eNodeType) + { + case TBOLD : nBold = 1; break; + case TNBOLD : nBold = 0; break; + case TITALIC : nItalic = 1; break; + case TNITALIC : nItalic = 0; break; + case TSANS : nSansSerifFixed = 0; break; + case TSERIF : nSansSerifFixed = 1; break; + case TFIXED : nSansSerifFixed = 2; break; + default: + OSL_FAIL( "unexpected case" ); + } + // According to the parser every node that is to be evaluated heres + // has a single non-zero subnode at index 1!! Thus we only need to check + // that single node for follow-up nodes that have an effect on the attribute. + if (pNode->GetNumSubNodes() > 1 && pNode->GetSubNode(1) && + lcl_HasEffectOnMathvariant( pNode->GetSubNode(1)->GetToken().eType)) + { + pNode = pNode->GetSubNode(1); + } + else + break; + } + + switch (pNode->GetToken().eType) + { + //wrap a phantom element around everything*/ + case TPHANTOM: + pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, + XML_MPHANTOM, sal_True,sal_True); + break; + case TBLACK: + AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_BLACK); + break; + case TWHITE: + AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_WHITE); + break; + case TRED: + AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_RED); + break; + case TGREEN: + AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_GREEN); + break; + case TBLUE: + AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_BLUE); + break; + case TCYAN: + AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_AQUA); + break; + case TMAGENTA: + AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_FUCHSIA); + break; + case TYELLOW: + AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_YELLOW); + break; + case TSIZE: + { + const SmFontNode *pFontNode = static_cast<const SmFontNode *>(pNode); + const Fraction &aFrac = pFontNode->GetSizeParameter(); + + OUStringBuffer sStrBuf; + switch(pFontNode->GetSizeType()) + { + case FNTSIZ_MULTIPLY: + SvXMLUnitConverter::convertDouble(sStrBuf, + static_cast<double>(aFrac*Fraction(100.00))); + sStrBuf.append(static_cast<sal_Unicode>('%')); + break; + case FNTSIZ_DIVIDE: + SvXMLUnitConverter::convertDouble(sStrBuf, + static_cast<double>(Fraction(100.00)/aFrac)); + sStrBuf.append(static_cast<sal_Unicode>('%')); + break; + case FNTSIZ_ABSOLUT: + SvXMLUnitConverter::convertDouble(sStrBuf, + static_cast<double>(aFrac)); + sStrBuf.append( + GetXMLToken(XML_UNIT_PT)); + break; + default: + { + //The problem here is that the wheels fall off because + //font size is stored in 100th's of a mm not pts, and + //rounding errors take their toll on the original + //value specified in points. + + //Must fix StarMath to retain the original pt values + Fraction aTemp = Sm100th_mmToPts(pFontNode->GetFont(). + GetSize().Height()); + + if (pFontNode->GetSizeType() == FNTSIZ_MINUS) + aTemp-=aFrac; + else + aTemp+=aFrac; + + double mytest = static_cast<double>(aTemp); + + mytest = ::rtl::math::round(mytest,1); + SvXMLUnitConverter::convertDouble(sStrBuf,mytest); + sStrBuf.append(GetXMLToken(XML_UNIT_PT)); + } + break; + } + + OUString sStr(sStrBuf.makeStringAndClear()); + AddAttribute(XML_NAMESPACE_MATH, XML_MATHSIZE, sStr); + } + break; + case TBOLD: + case TITALIC: + case TNBOLD: + case TNITALIC: + case TFIXED: + case TSANS: + case TSERIF: + { + // nBold: -1 = yet undefined; 0 = false; 1 = true; + // nItalic: -1 = yet undefined; 0 = false; 1 = true; + // nSansSerifFixed: -1 = undefined; 0 = sans; 1 = serif; 2 = fixed; + const sal_Char *pText = "normal"; + if (nSansSerifFixed == -1 || nSansSerifFixed == 1) + { + pText = "normal"; + if (nBold == 1 && nItalic != 1) + pText = "bold"; + else if (nBold != 1 && nItalic == 1) + pText = "italic"; + else if (nBold == 1 && nItalic == 1) + pText = "bold-italic"; + } + else if (nSansSerifFixed == 0) + { + pText = "sans-serif"; + if (nBold == 1 && nItalic != 1) + pText = "bold-sans-serif"; + else if (nBold != 1 && nItalic == 1) + pText = "sans-serif-italic"; + else if (nBold == 1 && nItalic == 1) + pText = "sans-serif-bold-italic"; + } + else if (nSansSerifFixed == 2) + pText = "monospace"; // no modifiers allowed for monospace ... + else + { + OSL_FAIL( "unexpected case" ); + } + AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, A2OU(pText)); + } + break; + default: + break; + + } + //for now we will just always export with a style and not worry about + //anyone else for the moment. + { + //wrap a style around it + SvXMLElementExport aStyle(*this, XML_NAMESPACE_MATH, XML_MSTYLE, sal_True,sal_True); + ExportExpression(pNode, nLevel); + } + + delete pElement; +} + + +void SmXMLExport::ExportVerticalBrace(const SmNode *pNode, int nLevel) +{ + //Place the overbrace value OVER a vertical brace and then place that + //expression OVER the overbrace value, If someone can find a + //dedicated term in MathML to handle this overbrace/underbrace concept + //let me know. C. + XMLTokenEnum which; + + switch (pNode->GetToken().eType) + { + case TOVERBRACE: + default: + which = XML_MOVER; + break; + case TUNDERBRACE: + which = XML_MUNDER; + break; + } + + OSL_ENSURE(pNode->GetNumSubNodes()==3,"Bad Vertical Brace"); + SvXMLElementExport aOver1(*this, XML_NAMESPACE_MATH,which, sal_True, sal_True); + {//Scoping + // using accents will draw the over-/underbraces too close to the base + // see http://www.w3.org/TR/MathML2/chapter3.html#id.3.4.5.2 + // also XML_ACCENT is illegal with XML_MUNDER. Thus no XML_ACCENT attribut here! + SvXMLElementExport aOver2(*this, XML_NAMESPACE_MATH,which, sal_True, sal_True); + ExportNodes(pNode->GetSubNode(0), nLevel); + ExportNodes(pNode->GetSubNode(1), nLevel); + } + ExportNodes(pNode->GetSubNode(2), nLevel); +} + +void SmXMLExport::ExportMatrix(const SmNode *pNode, int nLevel) +{ + SvXMLElementExport aTable(*this, XML_NAMESPACE_MATH, XML_MTABLE, sal_True, sal_True); + const SmMatrixNode *pMatrix = static_cast<const SmMatrixNode *>(pNode); + sal_uInt16 i=0; + for (sal_uLong y = 0; y < pMatrix->GetNumRows(); y++) + { + SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MTR, sal_True, sal_True); + for (sal_uLong x = 0; x < pMatrix->GetNumCols(); x++) + if (const SmNode *pTemp = pNode->GetSubNode(i++)) + { + SvXMLElementExport aCell(*this, XML_NAMESPACE_MATH, XML_MTD, sal_True, sal_True); + ExportNodes(pTemp, nLevel+1); + } + } +} + +void SmXMLExport::ExportNodes(const SmNode *pNode, int nLevel) +{ + if (!pNode) + return; + switch(pNode->GetType()) + { + case NTABLE: + ExportTable(pNode, nLevel); + break; + case NALIGN: + case NBRACEBODY: + case NEXPRESSION: + ExportExpression(pNode, nLevel); + break; + case NLINE: + ExportLine(pNode, nLevel); + break; + case NTEXT: + ExportText(pNode, nLevel); + break; + case NSPECIAL: //NSPECIAL requires some sort of Entity preservation in the XML engine. + case NGLYPH_SPECIAL: + case NMATH: + { + sal_Unicode cTmp = 0; + const SmTextNode *pTemp = static_cast< const SmTextNode * >(pNode); + if (pTemp->GetText().Len() > 0) + cTmp = ConvertMathToMathML( pTemp->GetText().GetChar(0) ); + if (cTmp == 0) + { + // no conversion to MathML implemented -> export it as text + // thus at least it will not vanish into nothing + ExportText(pNode, nLevel); + } + else + { + //To fully handle generic MathML we need to implement the full + //operator dictionary, we will generate MathML with explicit + //stretchiness for now. + sal_Int16 nLength = GetAttrList().getLength(); + sal_Bool bAddStretch=sal_True; + for ( sal_Int16 i = 0; i < nLength; i++ ) + { + OUString sLocalName; + sal_uInt16 nPrefix = GetNamespaceMap().GetKeyByAttrName( + GetAttrList().getNameByIndex(i), &sLocalName ); + + if ( ( XML_NAMESPACE_MATH == nPrefix ) && + IsXMLToken(sLocalName, XML_STRETCHY) ) + { + bAddStretch = sal_False; + break; + } + } + if (bAddStretch) + { + AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE); + } + ExportMath(pNode, nLevel); + } + } + break; + case NPLACE: + ExportMath(pNode, nLevel); + break; + case NBINHOR: + ExportBinaryHorizontal(pNode, nLevel); + break; + case NUNHOR: + ExportUnaryHorizontal(pNode, nLevel); + break; + case NBRACE: + ExportBrace(pNode, nLevel); + break; + case NBINVER: + ExportBinaryVertical(pNode, nLevel); + break; + case NSUBSUP: + ExportSubSupScript(pNode, nLevel); + break; + case NROOT: + ExportRoot(pNode, nLevel); + break; + case NOPER: + ExportOperator(pNode, nLevel); + break; + case NATTRIBUT: + ExportAttributes(pNode, nLevel); + break; + case NFONT: + ExportFont(pNode, nLevel); + break; + case NVERTICAL_BRACE: + ExportVerticalBrace(pNode, nLevel); + break; + case NMATRIX: + ExportMatrix(pNode, nLevel); + break; + case NBLANK: + ExportBlank(pNode, nLevel); + break; + default: + OSL_FAIL( "Warning: failed to export a node?" ); + break; + + } +} + +//////////////////////////////////////////////////////////// + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathmlexport.hxx b/starmath/source/mathmlexport.hxx new file mode 100644 index 000000000000..4ab602bad8b3 --- /dev/null +++ b/starmath/source/mathmlexport.hxx @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _MATHMLEXPORT_HXX_ +#define _MATHMLEXPORT_HXX_ + +#include <xmloff/xmlimp.hxx> +#include <xmloff/xmlexp.hxx> +#include <xmloff/DocumentSettingsContext.hxx> +#include <xmloff/xmltoken.hxx> + +#include <node.hxx> + +class SfxMedium; +namespace com { namespace sun { namespace star { + namespace io { + class XInputStream; + class XOutputStream; } + namespace beans { + class XPropertySet; } +} } } + + +//////////////////////////////////////////////////////////// + +class SmXMLExportWrapper +{ + com::sun::star::uno::Reference<com::sun::star::frame::XModel> xModel; + sal_Bool bFlat; //set true for export to flat .mml, set false for + //export to a .sxm (or whatever) package +public: + SmXMLExportWrapper(com::sun::star::uno::Reference<com::sun::star::frame::XModel> &rRef) + : xModel(rRef), bFlat(sal_True) {} + + sal_Bool Export(SfxMedium &rMedium); + void SetFlat(sal_Bool bIn) {bFlat = bIn;} + + sal_Bool WriteThroughComponent( + ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > + xOutputStream, + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > + xComponent, + ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > & rFactory, + ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet > & rPropSet, + const sal_Char* pComponentName ); + + sal_Bool WriteThroughComponent( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor, + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > + xComponent, + const sal_Char* pStreamName, + ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory > & rFactory, + ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet > & rPropSet, + const sal_Char* pComponentName, + sal_Bool bCompress=sal_True ); +}; + +//////////////////////////////////////////////////////////// + +class SmXMLExport : public SvXMLExport +{ + const SmNode * pTree; + String aText; + sal_Bool bSuccess; + +protected: + void ExportNodes(const SmNode *pNode, int nLevel); + void ExportTable(const SmNode *pNode, int nLevel); + void ExportLine(const SmNode *pNode, int nLevel); + void ExportExpression(const SmNode *pNode, int nLevel); + void ExportText(const SmNode *pNode, int nLevel); + void ExportMath(const SmNode *pNode, int nLevel); + void ExportPolygon(const SmNode *pNode, int nLevel); + void ExportBinaryHorizontal(const SmNode *pNode, int nLevel); + void ExportUnaryHorizontal(const SmNode *pNode, int nLevel); + void ExportBrace(const SmNode *pNode, int nLevel); + void ExportBinaryVertical(const SmNode *pNode, int nLevel); + void ExportSubSupScript(const SmNode *pNode, int nLevel); + void ExportRoot(const SmNode *pNode, int nLevel); + void ExportOperator(const SmNode *pNode, int nLevel); + void ExportAttributes(const SmNode *pNode, int nLevel); + void ExportFont(const SmNode *pNode, int nLevel); + void ExportVerticalBrace(const SmNode *pNode, int nLevel); + void ExportMatrix(const SmNode *pNode, int nLevel); + void ExportBlank(const SmNode *pNode, int nLevel); + +public: + SmXMLExport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + sal_uInt16 nExportFlags=EXPORT_ALL); + virtual ~SmXMLExport() {}; + + // XServiceInfo (override parent method) + ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + + // XUnoTunnel + sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw(::com::sun::star::uno::RuntimeException); + static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId() throw(); + + void _ExportAutoStyles() {} + void _ExportMasterStyles() {} + void _ExportContent(); + sal_uInt32 exportDoc(enum ::xmloff::token::XMLTokenEnum eClass); + + virtual void GetViewSettings(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps); + virtual void GetConfigurationSettings(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps); + + sal_Bool GetSuccess() {return bSuccess;} +}; + +//////////////////////////////////////////////////////////// + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathmlimport.cxx b/starmath/source/mathmlimport.cxx new file mode 100644 index 000000000000..a70f3fe31096 --- /dev/null +++ b/starmath/source/mathmlimport.cxx @@ -0,0 +1,3037 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + +/*todo: Change characters and tcharacters to accumulate the characters together +into one string, xml parser hands them to us line by line rather than all in +one go*/ + +#include <com/sun/star/xml/sax/XErrorHandler.hpp> +#include <com/sun/star/xml/sax/XEntityResolver.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XDTDHandler.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XActiveDataControl.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <com/sun/star/task/XStatusIndicatorFactory.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/uno/Any.h> + +#include <rtl/math.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/docfile.hxx> +#include <osl/diagnose.h> +#include <tools/urlobj.hxx> +#include <svtools/sfxecode.hxx> +#include <unotools/saveopt.hxx> +#include <svl/stritem.hxx> +#include <svl/itemprop.hxx> +#include <unotools/processfactory.hxx> +#include <unotools/streamwrap.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/nmspmap.hxx> +#include <xmloff/attrlist.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/xmlmetai.hxx> +#include <osl/mutex.hxx> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/servicehelper.hxx> + +#include <memory> + +#include "mathmlimport.hxx" +#include <starmath.hrc> +#include <unomodel.hxx> +#include <document.hxx> +#include <utility.hxx> + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; +using namespace ::xmloff::token; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +#define IMPORT_SVC_NAME RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.XMLImportFilter") + +#undef WANTEXCEPT + +//////////////////////////////////////////////////////////// + +sal_uLong SmXMLImportWrapper::Import(SfxMedium &rMedium) +{ + sal_uLong nError = ERRCODE_SFX_DOLOADFAILED; + + uno::Reference<lang::XMultiServiceFactory> xServiceFactory( + utl::getProcessServiceFactory()); + OSL_ENSURE(xServiceFactory.is(), "XMLReader::Read: got no service manager"); + if ( !xServiceFactory.is() ) + return nError; + + //Make a model component from our SmModel + uno::Reference< lang::XComponent > xModelComp( xModel, uno::UNO_QUERY ); + OSL_ENSURE( xModelComp.is(), "XMLReader::Read: got no model" ); + + // try to get an XStatusIndicator from the Medium + uno::Reference<task::XStatusIndicator> xStatusIndicator; + + sal_Bool bEmbedded = sal_False; + uno::Reference <lang::XUnoTunnel> xTunnel; + xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY); + SmModel *pModel = reinterpret_cast<SmModel *> + (xTunnel->getSomething(SmModel::getUnoTunnelId())); + + SmDocShell *pDocShell = pModel ? + static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0; + if (pDocShell) + { + OSL_ENSURE( pDocShell->GetMedium() == &rMedium, + "different SfxMedium found" ); + + SfxItemSet* pSet = rMedium.GetItemSet(); + if (pSet) + { + const SfxUnoAnyItem* pItem = static_cast<const SfxUnoAnyItem*>( + pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) ); + if (pItem) + pItem->GetValue() >>= xStatusIndicator; + } + + if ( SFX_CREATE_MODE_EMBEDDED == pDocShell->GetCreateMode() ) + bEmbedded = sal_True; + } + + comphelper::PropertyMapEntry aInfoMap[] = + { + { "PrivateData", sizeof("PrivateData")-1, 0, + &::getCppuType( (Reference<XInterface> *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "BaseURI", sizeof("BaseURI")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StreamRelPath", sizeof("StreamRelPath")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { "StreamName", sizeof("StreamName")-1, 0, + &::getCppuType( (OUString *)0 ), + beans::PropertyAttribute::MAYBEVOID, 0 }, + { NULL, 0, 0, NULL, 0, 0 } + }; + uno::Reference< beans::XPropertySet > xInfoSet( + comphelper::GenericPropertySet_CreateInstance( + new comphelper::PropertySetInfo( aInfoMap ) ) ); + + // Set base URI + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("BaseURI") ); + xInfoSet->setPropertyValue( sPropName, makeAny( rMedium.GetBaseURL() ) ); + + sal_Int32 nSteps=3; + if ( !(rMedium.IsStorage())) + nSteps = 1; + + sal_Int32 nProgressRange(nSteps); + if (xStatusIndicator.is()) + { + xStatusIndicator->start(String(SmResId(STR_STATSTR_READING)), + nProgressRange); + } + + nSteps=0; + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + if ( rMedium.IsStorage()) + { + // TODO/LATER: handle the case of embedded links gracefully + if ( bEmbedded ) // && !rMedium.GetStorage()->IsRoot() ) + { + OUString aName( RTL_CONSTASCII_USTRINGPARAM( "dummyObjName" ) ); + if ( rMedium.GetItemSet() ) + { + const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>( + rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) ); + if ( pDocHierarchItem ) + aName = pDocHierarchItem->GetValue(); + } + + if ( aName.getLength() ) + { + sPropName = OUString(RTL_CONSTASCII_USTRINGPARAM("StreamRelPath")); + xInfoSet->setPropertyValue( sPropName, makeAny( aName ) ); + } + } + + sal_Bool bOASIS = ( SotStorage::GetVersion( rMedium.GetStorage() ) > SOFFICE_FILEFORMAT_60 ); + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + sal_uLong nWarn = ReadThroughComponent( + rMedium.GetStorage(), xModelComp, "meta.xml", "Meta.xml", + xServiceFactory, xInfoSet, + (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaImporter" + : "com.sun.star.comp.Math.XMLMetaImporter") ); + + if ( nWarn != ERRCODE_IO_BROKENPACKAGE ) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + nWarn = ReadThroughComponent( + rMedium.GetStorage(), xModelComp, "settings.xml", 0, + xServiceFactory, xInfoSet, + (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsImporter" + : "com.sun.star.comp.Math.XMLSettingsImporter" ) ); + + if ( nWarn != ERRCODE_IO_BROKENPACKAGE ) + { + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + nError = ReadThroughComponent( + rMedium.GetStorage(), xModelComp, "content.xml", "Content.xml", + xServiceFactory, xInfoSet, "com.sun.star.comp.Math.XMLImporter" ); + } + else + nError = ERRCODE_IO_BROKENPACKAGE; + } + else + nError = ERRCODE_IO_BROKENPACKAGE; + } + else + { + Reference<io::XInputStream> xInputStream = + new utl::OInputStreamWrapper(rMedium.GetInStream()); + + if (xStatusIndicator.is()) + xStatusIndicator->setValue(nSteps++); + + nError = ReadThroughComponent( xInputStream, xModelComp, + xServiceFactory, xInfoSet, "com.sun.star.comp.Math.XMLImporter", false ); + } + + if (xStatusIndicator.is()) + xStatusIndicator->end(); + return nError; +} + + +/// read a component (file + filter version) +sal_uLong SmXMLImportWrapper::ReadThroughComponent( + Reference<io::XInputStream> xInputStream, + Reference<XComponent> xModelComponent, + Reference<lang::XMultiServiceFactory> & rFactory, + Reference<beans::XPropertySet> & rPropSet, + const sal_Char* pFilterName, + sal_Bool bEncrypted ) +{ + sal_uLong nError = ERRCODE_SFX_DOLOADFAILED; + OSL_ENSURE(xInputStream.is(), "input stream missing"); + OSL_ENSURE(xModelComponent.is(), "document missing"); + OSL_ENSURE(rFactory.is(), "factory missing"); + OSL_ENSURE(NULL != pFilterName,"I need a service name for the component!"); + + // prepare ParserInputSrouce + xml::sax::InputSource aParserInput; + aParserInput.aInputStream = xInputStream; + + // get parser + Reference< xml::sax::XParser > xParser( + rFactory->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")) ), + UNO_QUERY ); + OSL_ENSURE( xParser.is(), "Can't create parser" ); + if ( !xParser.is() ) + return nError; + + Sequence<Any> aArgs( 1 ); + aArgs[0] <<= rPropSet; + + // get filter + Reference< xml::sax::XDocumentHandler > xFilter( + rFactory->createInstanceWithArguments( + OUString::createFromAscii(pFilterName), aArgs ), + UNO_QUERY ); + OSL_ENSURE( xFilter.is(), "Can't instantiate filter component." ); + if ( !xFilter.is() ) + return nError; + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + // connect model and filter + Reference < XImporter > xImporter( xFilter, UNO_QUERY ); + xImporter->setTargetDocument( xModelComponent ); + + // finally, parser the stream + try + { + xParser->parseStream( aParserInput ); + + uno::Reference<lang::XUnoTunnel> xFilterTunnel; + xFilterTunnel = uno::Reference<lang::XUnoTunnel> + ( xFilter, uno::UNO_QUERY ); + SmXMLImport *pFilter = reinterpret_cast< SmXMLImport * >( + sal::static_int_cast< sal_uIntPtr >( + xFilterTunnel->getSomething( SmXMLImport::getUnoTunnelId() ))); + if ( pFilter && pFilter->GetSuccess() ) + nError = 0; + } + catch( xml::sax::SAXParseException& r ) + { + // sax parser sends wrapped exceptions, + // try to find the original one + xml::sax::SAXException aSaxEx = *(xml::sax::SAXException*)(&r); + sal_Bool bTryChild = sal_True; + + while( bTryChild ) + { + xml::sax::SAXException aTmp; + if ( aSaxEx.WrappedException >>= aTmp ) + aSaxEx = aTmp; + else + bTryChild = sal_False; + } + + packages::zip::ZipIOException aBrokenPackage; + if ( aSaxEx.WrappedException >>= aBrokenPackage ) + return ERRCODE_IO_BROKENPACKAGE; + + if ( bEncrypted ) + nError = ERRCODE_SFX_WRONGPASSWORD; + } + catch( xml::sax::SAXException& r ) + { + packages::zip::ZipIOException aBrokenPackage; + if ( r.WrappedException >>= aBrokenPackage ) + return ERRCODE_IO_BROKENPACKAGE; + + if ( bEncrypted ) + nError = ERRCODE_SFX_WRONGPASSWORD; + } + catch( packages::zip::ZipIOException& ) + { + nError = ERRCODE_IO_BROKENPACKAGE; + } + catch( io::IOException& ) + { + } + + return nError; +} + + +sal_uLong SmXMLImportWrapper::ReadThroughComponent( + const uno::Reference< embed::XStorage >& xStorage, + Reference<XComponent> xModelComponent, + const sal_Char* pStreamName, + const sal_Char* pCompatibilityStreamName, + Reference<lang::XMultiServiceFactory> & rFactory, + Reference<beans::XPropertySet> & rPropSet, + const sal_Char* pFilterName ) +{ + OSL_ENSURE(xStorage.is(), "Need storage!"); + OSL_ENSURE(NULL != pStreamName, "Please, please, give me a name!"); + + // open stream (and set parser input) + OUString sStreamName = OUString::createFromAscii(pStreamName); + uno::Reference < container::XNameAccess > xAccess( xStorage, uno::UNO_QUERY ); + if ( !xAccess->hasByName(sStreamName) || !xStorage->isStreamElement(sStreamName) ) + { + // stream name not found! Then try the compatibility name. + // do we even have an alternative name? + if ( pCompatibilityStreamName ) + sStreamName = OUString::createFromAscii(pCompatibilityStreamName); + } + + // get input stream + try + { + uno::Reference < io::XStream > xEventsStream = xStorage->openStreamElement( sStreamName, embed::ElementModes::READ ); + + // determine if stream is encrypted or not + uno::Reference < beans::XPropertySet > xProps( xEventsStream, uno::UNO_QUERY ); + Any aAny = xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Encrypted") ) ); + sal_Bool bEncrypted = sal_False; + if ( aAny.getValueType() == ::getBooleanCppuType() ) + aAny >>= bEncrypted; + + // set Base URL + if ( rPropSet.is() ) + { + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("StreamName") ); + rPropSet->setPropertyValue( sPropName, makeAny( sStreamName ) ); + } + + + Reference < io::XInputStream > xStream = xEventsStream->getInputStream(); + return ReadThroughComponent( xStream, xModelComponent, rFactory, rPropSet, pFilterName, bEncrypted ); + } + catch ( packages::WrongPasswordException& ) + { + return ERRCODE_SFX_WRONGPASSWORD; + } + catch( packages::zip::ZipIOException& ) + { + return ERRCODE_IO_BROKENPACKAGE; + } + catch ( uno::Exception& ) + { + } + + return ERRCODE_SFX_DOLOADFAILED; +} + +//////////////////////////////////////////////////////////// + +SmXMLImport::SmXMLImport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + sal_uInt16 nImportFlags) +: SvXMLImport( xServiceFactory, nImportFlags ), + pPresLayoutElemTokenMap(0), + pPresLayoutAttrTokenMap(0), + pFencedAttrTokenMap(0), + pOperatorAttrTokenMap(0), + pAnnotationAttrTokenMap(0), + pPresElemTokenMap(0), + pPresScriptEmptyElemTokenMap(0), + pPresTableElemTokenMap(0), + pColorTokenMap(0), + bSuccess(sal_False) +{ +} + +namespace +{ + class theSmXMLImportUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSmXMLImportUnoTunnelId> {}; +} + +const uno::Sequence< sal_Int8 > & SmXMLImport::getUnoTunnelId() throw() +{ + return theSmXMLImportUnoTunnelId::get().getSeq(); +} + +OUString SAL_CALL SmXMLImport_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLImporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SmXMLImport_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( IMPORT_SVC_NAME ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmXMLImport_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) + throw( uno::Exception ) +{ + return (cppu::OWeakObject*)new SmXMLImport(rSMgr, IMPORT_ALL); +} + +//////////////////////////////////////////////////////////// + +OUString SAL_CALL SmXMLImportMeta_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisMetaImporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SmXMLImportMeta_getSupportedServiceNames() +throw() +{ + const OUString aServiceName( IMPORT_SVC_NAME ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmXMLImportMeta_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) +throw( uno::Exception ) +{ + return (cppu::OWeakObject*)new SmXMLImport( rSMgr, IMPORT_META ); +} + +//////////////////////////////////////////////////////////// + +OUString SAL_CALL SmXMLImportSettings_getImplementationName() throw() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisSettingsImporter" ) ); +} + +uno::Sequence< OUString > SAL_CALL SmXMLImportSettings_getSupportedServiceNames() + throw() +{ + const OUString aServiceName( IMPORT_SVC_NAME ); + const uno::Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmXMLImportSettings_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr) + throw( uno::Exception ) +{ + return (cppu::OWeakObject*)new SmXMLImport( rSMgr, IMPORT_SETTINGS ); +} + +//////////////////////////////////////////////////////////// + +// XServiceInfo +// override empty method from parent class +rtl::OUString SAL_CALL SmXMLImport::getImplementationName() + throw(uno::RuntimeException) +{ + OUString aTxt; + switch( getImportFlags() ) + { + case IMPORT_META: + aTxt = SmXMLImportMeta_getImplementationName(); + break; + case IMPORT_SETTINGS: + aTxt = SmXMLImportSettings_getImplementationName(); + break; + case IMPORT_ALL: + default: + aTxt = SmXMLImport_getImplementationName(); + break; + } + return aTxt; +} + + +sal_Int64 SAL_CALL SmXMLImport::getSomething( + const uno::Sequence< sal_Int8 >&rId ) +throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + return sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_uIntPtr >(this)); + + return SvXMLImport::getSomething( rId ); +} + +void SmXMLImport::endDocument(void) + throw(xml::sax::SAXException, uno::RuntimeException) +{ + //Set the resulted tree into the SmDocShell where it belongs + SmNode *pTree; + if (NULL != (pTree = GetTree())) + { + uno::Reference <frame::XModel> xModel = GetModel(); + uno::Reference <lang::XUnoTunnel> xTunnel; + xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY); + SmModel *pModel = reinterpret_cast<SmModel *> + (xTunnel->getSomething(SmModel::getUnoTunnelId())); + + if (pModel) + { + SmDocShell *pDocShell = + static_cast<SmDocShell*>(pModel->GetObjectShell()); + pDocShell->SetFormulaTree(pTree); + if (0 == aText.Len()) //If we picked up no annotation text + { + //Make up some editable text + aText = pDocShell->GetText(); + pTree->CreateTextFromNode(aText); + aText.EraseTrailingChars(); + if ((aText.GetChar(0) == '{') && + (aText.GetChar(aText.Len()-1) == '}')) + { + aText.Erase(0,1); + aText.Erase(aText.Len()-1,1); + } + } + pDocShell->SetText( String() ); + + // Convert symbol names + SmParser &rParser = pDocShell->GetParser(); + bool bVal = rParser.IsImportSymbolNames(); + rParser.SetImportSymbolNames( true ); + SmNode *pTmpTree = rParser.Parse( aText ); + aText = rParser.GetText(); + delete pTmpTree; + rParser.SetImportSymbolNames( bVal ); + + pDocShell->SetText( aText ); + } + OSL_ENSURE(pModel,"So there *was* a uno problem after all"); + + bSuccess = sal_True; + } + + SvXMLImport::endDocument(); +} + +//////////////////////////////////////////////////////////// + +class SmXMLImportContext: public SvXMLImportContext +{ +public: + SmXMLImportContext( SmXMLImport &rImport, sal_uInt16 nPrfx, + const OUString& rLName) + : SvXMLImportContext(rImport, nPrfx, rLName) {} + + const SmXMLImport& GetSmImport() const + { + return (const SmXMLImport&)GetImport(); + } + + SmXMLImport& GetSmImport() + { + return (SmXMLImport&)GetImport(); + } + + virtual void TCharacters(const OUString & /*rChars*/); + virtual void Characters(const OUString &rChars); + virtual SvXMLImportContext *CreateChildContext(sal_uInt16 /*nPrefix*/, const OUString& /*rLocalName*/, const uno::Reference< xml::sax::XAttributeList > & /*xAttrList*/); +}; + +void SmXMLImportContext::TCharacters(const OUString & /*rChars*/) +{ +} + +void SmXMLImportContext::Characters(const OUString &rChars) +{ + /* + Whitespace occurring within the content of token elements is "trimmed" + from the ends (i.e. all whitespace at the beginning and end of the + content is removed), and "collapsed" internally (i.e. each sequence of + 1 or more whitespace characters is replaced with one blank character). + */ + //collapsing not done yet! + const OUString &rChars2 = rChars.trim(); + if (rChars2.getLength()) + TCharacters(rChars2/*.collapse()*/); +} + +SvXMLImportContext * SmXMLImportContext::CreateChildContext(sal_uInt16 /*nPrefix*/, + const OUString& /*rLocalName*/, + const uno::Reference< xml::sax::XAttributeList > & /*xAttrList*/) +{ + return 0; +} + +//////////////////////////////////////////////////////////// + +struct SmXMLContext_Helper +{ + sal_Int8 nIsBold; + sal_Int8 nIsItalic; + double nFontSize; + sal_Bool bFontNodeNeeded; + OUString sFontFamily; + OUString sColor; + + SmXMLImportContext rContext; + + SmXMLContext_Helper(SmXMLImportContext &rImport) : + nIsBold(-1), nIsItalic(-1), nFontSize(0.0), rContext(rImport) {} + + void RetrieveAttrs(const uno::Reference< xml::sax::XAttributeList > &xAttrList ); + void ApplyAttrs(); +}; + +void SmXMLContext_Helper::RetrieveAttrs(const uno::Reference< + xml::sax::XAttributeList > & xAttrList ) +{ + sal_Int8 nOldIsBold=nIsBold; + sal_Int8 nOldIsItalic=nIsItalic; + double nOldFontSize=nFontSize; + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + OUString sOldFontFamily = sFontFamily; + for (sal_Int16 i=0;i<nAttrCount;i++) + { + OUString sAttrName = xAttrList->getNameByIndex(i); + OUString aLocalName; + sal_uInt16 nPrefix = rContext.GetSmImport().GetNamespaceMap(). + GetKeyByAttrName(sAttrName,&aLocalName); + OUString sValue = xAttrList->getValueByIndex(i); + const SvXMLTokenMap &rAttrTokenMap = + rContext.GetSmImport().GetPresLayoutAttrTokenMap(); + switch(rAttrTokenMap.Get(nPrefix,aLocalName)) + { + case XML_TOK_FONTWEIGHT: + nIsBold = sValue.equals(GetXMLToken(XML_BOLD)); + break; + case XML_TOK_FONTSTYLE: + nIsItalic = sValue.equals(GetXMLToken(XML_ITALIC)); + break; + case XML_TOK_FONTSIZE: + SvXMLUnitConverter::convertDouble(nFontSize,sValue); + rContext.GetSmImport().GetMM100UnitConverter(). + setXMLMeasureUnit(MAP_POINT); + if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT))) + { + if (-1 == sValue.indexOf('%')) + nFontSize=0.0; + else + { + rContext.GetSmImport().GetMM100UnitConverter(). + setXMLMeasureUnit(MAP_RELATIVE); + } + } + break; + case XML_TOK_FONTFAMILY: + sFontFamily = sValue; + break; + case XML_TOK_COLOR: + sColor = sValue; + break; + default: + break; + } + } + + if ((nOldIsBold!=nIsBold) || (nOldIsItalic!=nIsItalic) || + (nOldFontSize!=nFontSize) || (sOldFontFamily!=sFontFamily) + || sColor.getLength()) + bFontNodeNeeded=sal_True; + else + bFontNodeNeeded=sal_False; +} + +void SmXMLContext_Helper::ApplyAttrs() +{ + SmNodeStack &rNodeStack = rContext.GetSmImport().GetNodeStack(); + + if (bFontNodeNeeded) + { + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 5; + + if (nIsBold != -1) + { + if (nIsBold) + aToken.eType = TBOLD; + else + aToken.eType = TNBOLD; + SmStructureNode *pFontNode = static_cast<SmStructureNode *> + (new SmFontNode(aToken)); + pFontNode->SetSubNodes(0,rNodeStack.Pop()); + rNodeStack.Push(pFontNode); + } + if (nIsItalic != -1) + { + if (nIsItalic) + aToken.eType = TITALIC; + else + aToken.eType = TNITALIC; + SmStructureNode *pFontNode = static_cast<SmStructureNode *> + (new SmFontNode(aToken)); + pFontNode->SetSubNodes(0,rNodeStack.Pop()); + rNodeStack.Push(pFontNode); + } + if (nFontSize != 0.0) + { + aToken.eType = TSIZE; + SmFontNode *pFontNode = new SmFontNode(aToken); + + if (MAP_RELATIVE == rContext.GetSmImport().GetMM100UnitConverter(). + getXMLMeasureUnit()) + { + if (nFontSize < 100.00) + pFontNode->SetSizeParameter(Fraction(100.00/nFontSize), + FNTSIZ_DIVIDE); + else + pFontNode->SetSizeParameter(Fraction(nFontSize/100.00), + FNTSIZ_MULTIPLY); + } + else + pFontNode->SetSizeParameter(Fraction(nFontSize),FNTSIZ_ABSOLUT); + + pFontNode->SetSubNodes(0,rNodeStack.Pop()); + rNodeStack.Push(pFontNode); + } + if (sFontFamily.getLength()) + { + if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED))) + aToken.eType = TFIXED; + else if (sFontFamily.equalsIgnoreAsciiCase(OUString( + RTL_CONSTASCII_USTRINGPARAM("sans")))) + aToken.eType = TSANS; + else if (sFontFamily.equalsIgnoreAsciiCase(OUString( + RTL_CONSTASCII_USTRINGPARAM("serif")))) + aToken.eType = TSERIF; + else //Just give up, we need to extend our font mechanism to be + //more general + return; + + aToken.aText = sFontFamily; + SmFontNode *pFontNode = new SmFontNode(aToken); + pFontNode->SetSubNodes(0,rNodeStack.Pop()); + rNodeStack.Push(pFontNode); + } + if (sColor.getLength()) + { + //Again we can only handle a small set of colours in + //StarMath for now. + const SvXMLTokenMap& rTokenMap = + rContext.GetSmImport().GetColorTokenMap(); + aToken.eType = static_cast<SmTokenType>(rTokenMap.Get( + XML_NAMESPACE_MATH, sColor)); + if (aToken.eType != -1) + { + SmFontNode *pFontNode = new SmFontNode(aToken); + pFontNode->SetSubNodes(0,rNodeStack.Pop()); + rNodeStack.Push(pFontNode); + } + } + + } +} + +//////////////////////////////////////////////////////////// + +class SmXMLDocContext_Impl : public SmXMLImportContext +{ +public: + SmXMLDocContext_Impl( SmXMLImport &rImport, sal_uInt16 nPrfx, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrfx,rLName) {} + + virtual SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList); + + void EndElement(); +}; + +//////////////////////////////////////////////////////////// + +/*avert thy gaze from the proginator*/ +class SmXMLRowContext_Impl : public SmXMLDocContext_Impl +{ +protected: + sal_uLong nElementCount; + +public: + SmXMLRowContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLDocContext_Impl(rImport,nPrefix,rLName) + { nElementCount = GetSmImport().GetNodeStack().Count(); } + + virtual SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList); + + SvXMLImportContext *StrictCreateChildContext(sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > &xAttrList); + + void EndElement(); +}; + +//////////////////////////////////////////////////////////// + +class SmXMLFracContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLFracContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement(); +}; + +//////////////////////////////////////////////////////////// + +class SmXMLSqrtContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLSqrtContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement(); +}; + +//////////////////////////////////////////////////////////// + +class SmXMLRootContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLRootContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement(); +}; + +//////////////////////////////////////////////////////////// + +class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl +{ +protected: + SmXMLContext_Helper aStyleHelper; + +public: + /*Right now the style tag is completely ignored*/ + SmXMLStyleContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) : SmXMLRowContext_Impl(rImport,nPrefix,rLName), + aStyleHelper(*this) {} + + void EndElement(); + void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList ); +}; + +void SmXMLStyleContext_Impl::StartElement(const uno::Reference< + xml::sax::XAttributeList > & xAttrList ) +{ + aStyleHelper.RetrieveAttrs(xAttrList); +} + + +void SmXMLStyleContext_Impl::EndElement() +{ + /* + <mstyle> accepts any number of arguments; if this number is not 1, its + contents are treated as a single "inferred <mrow>" containing its + arguments + */ + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + if (rNodeStack.Count() - nElementCount > 1) + SmXMLRowContext_Impl::EndElement(); + aStyleHelper.ApplyAttrs(); +} + +//////////////////////////////////////////////////////////// + +class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl +{ +public: + /*Right now the style tag is completely ignored*/ + SmXMLPaddedContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement(); +}; + +void SmXMLPaddedContext_Impl::EndElement() +{ + /* + <mpadded> accepts any number of arguments; if this number is not 1, its + contents are treated as a single "inferred <mrow>" containing its + arguments + */ + if (GetSmImport().GetNodeStack().Count() - nElementCount > 1) + SmXMLRowContext_Impl::EndElement(); +} + +//////////////////////////////////////////////////////////// + +class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl +{ +public: + /*Right now the style tag is completely ignored*/ + SmXMLPhantomContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement(); +}; + +void SmXMLPhantomContext_Impl::EndElement() +{ + /* + <mphantom> accepts any number of arguments; if this number is not 1, its + contents are treated as a single "inferred <mrow>" containing its + arguments + */ + if (GetSmImport().GetNodeStack().Count() - nElementCount > 1) + SmXMLRowContext_Impl::EndElement(); + + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 5; + aToken.eType = TPHANTOM; + + SmStructureNode *pPhantom = static_cast<SmStructureNode *> + (new SmFontNode(aToken)); + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + pPhantom->SetSubNodes(0,rNodeStack.Pop()); + rNodeStack.Push(pPhantom); +} + +//////////////////////////////////////////////////////////// + +class SmXMLFencedContext_Impl : public SmXMLRowContext_Impl +{ +protected: + sal_Unicode cBegin; + sal_Unicode cEnd; + +public: + SmXMLFencedContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLRowContext_Impl(rImport,nPrefix,rLName), + cBegin('('), cEnd(')') {} + + void StartElement(const uno::Reference< xml::sax::XAttributeList > & xAttrList ); + void EndElement(); +}; + + +void SmXMLFencedContext_Impl::StartElement(const uno::Reference< + xml::sax::XAttributeList > & xAttrList ) +{ + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for (sal_Int16 i=0;i<nAttrCount;i++) + { + OUString sAttrName = xAttrList->getNameByIndex(i); + OUString aLocalName; + sal_uInt16 nPrefix = GetImport().GetNamespaceMap(). + GetKeyByAttrName(sAttrName,&aLocalName); + OUString sValue = xAttrList->getValueByIndex(i); + const SvXMLTokenMap &rAttrTokenMap = + GetSmImport().GetFencedAttrTokenMap(); + switch(rAttrTokenMap.Get(nPrefix,aLocalName)) + { + //temp, starmath cannot handle multichar brackets (I think) + case XML_TOK_OPEN: + cBegin = sValue[0]; + break; + case XML_TOK_CLOSE: + cEnd = sValue[0]; + break; + default: + /*Go to superclass*/ + break; + } + } +} + + +void SmXMLFencedContext_Impl::EndElement() +{ + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.aText = ','; + aToken.eType = TLEFT; + aToken.nLevel = 5; + + aToken.eType = TLPARENT; + aToken.cMathChar = cBegin; + SmStructureNode *pSNode = new SmBraceNode(aToken); + SmNode *pLeft = new SmMathSymbolNode(aToken); + + aToken.cMathChar = cEnd; + aToken.eType = TRPARENT; + SmNode *pRight = new SmMathSymbolNode(aToken); + + SmNodeArray aRelationArray; + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + + aToken.cMathChar = '\0'; + aToken.aText = ','; + aToken.eType = TIDENT; + + sal_uLong i = rNodeStack.Count() - nElementCount; + if (rNodeStack.Count() - nElementCount > 1) + i += rNodeStack.Count() - 1 - nElementCount; + aRelationArray.resize(i); + while (rNodeStack.Count() > nElementCount) + { + aRelationArray[--i] = rNodeStack.Pop(); + if (i > 1 && rNodeStack.Count() > 1) + aRelationArray[--i] = new SmGlyphSpecialNode(aToken); + } + + SmToken aDummy; + SmStructureNode *pBody = new SmExpressionNode(aDummy); + pBody->SetSubNodes(aRelationArray); + + + pSNode->SetSubNodes(pLeft,pBody,pRight); + pSNode->SetScaleMode(SCALE_HEIGHT); + GetSmImport().GetNodeStack().Push(pSNode); +} + + +//////////////////////////////////////////////////////////// + +class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLErrorContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement(); +}; + +void SmXMLErrorContext_Impl::EndElement() +{ + /*Right now the error tag is completely ignored, what + can I do with it in starmath, ?, maybe we need a + report window ourselves, do a test for validity of + the xml input, use merrors, and then generate + the markup inside the merror with a big red colour + of something. For now just throw them all away. + */ + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + while (rNodeStack.Count() > nElementCount) + { + SmNode *pNode = rNodeStack.Pop(); + delete pNode; + } +} + +//////////////////////////////////////////////////////////// + +class SmXMLNumberContext_Impl : public SmXMLImportContext +{ +protected: + SmToken aToken; + +public: + SmXMLNumberContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrefix,rLName) + { + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 5; + aToken.eType = TNUMBER; + } + + virtual void TCharacters(const OUString &rChars); + + void EndElement(); +}; + +void SmXMLNumberContext_Impl::TCharacters(const OUString &rChars) +{ + aToken.aText = rChars; +} + +void SmXMLNumberContext_Impl::EndElement() +{ + GetSmImport().GetNodeStack().Push(new SmTextNode(aToken,FNT_NUMBER)); +} + +//////////////////////////////////////////////////////////// + +class SmXMLAnnotationContext_Impl : public SmXMLImportContext +{ + sal_Bool bIsStarMath; + +public: + SmXMLAnnotationContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrefix,rLName), bIsStarMath(sal_False) {} + + virtual void Characters(const OUString &rChars); + + void StartElement(const uno::Reference<xml::sax::XAttributeList > & xAttrList ); +}; + +void SmXMLAnnotationContext_Impl::StartElement(const uno::Reference< + xml::sax::XAttributeList > & xAttrList ) +{ + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for (sal_Int16 i=0;i<nAttrCount;i++) + { + OUString sAttrName = xAttrList->getNameByIndex(i); + OUString aLocalName; + sal_uInt16 nPrefix = GetImport().GetNamespaceMap(). + GetKeyByAttrName(sAttrName,&aLocalName); + + OUString sValue = xAttrList->getValueByIndex(i); + const SvXMLTokenMap &rAttrTokenMap = + GetSmImport().GetAnnotationAttrTokenMap(); + switch(rAttrTokenMap.Get(nPrefix,aLocalName)) + { + case XML_TOK_ENCODING: + bIsStarMath= sValue.equals( + OUString(RTL_CONSTASCII_USTRINGPARAM("StarMath 5.0"))); + break; + default: + break; + } + } +} + +void SmXMLAnnotationContext_Impl::Characters(const OUString &rChars) +{ + if (bIsStarMath) + GetSmImport().GetText().Append(String(rChars)); +} + +//////////////////////////////////////////////////////////// + +class SmXMLTextContext_Impl : public SmXMLImportContext +{ +protected: + SmToken aToken; + +public: + SmXMLTextContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrefix,rLName) + { + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 5; + aToken.eType = TTEXT; + } + + virtual void TCharacters(const OUString &rChars); + + void EndElement(); +}; + +void SmXMLTextContext_Impl::TCharacters(const OUString &rChars) +{ + aToken.aText = rChars; +} + +void SmXMLTextContext_Impl::EndElement() +{ + GetSmImport().GetNodeStack().Push(new SmTextNode(aToken,FNT_TEXT)); +} + +//////////////////////////////////////////////////////////// + +class SmXMLStringContext_Impl : public SmXMLImportContext +{ +protected: + SmToken aToken; + +public: + SmXMLStringContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrefix,rLName) + { + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 5; + aToken.eType = TTEXT; + } + + virtual void TCharacters(const OUString &rChars); + + void EndElement(); +}; + +void SmXMLStringContext_Impl::TCharacters(const OUString &rChars) +{ + /* + The content of <ms> elements should be rendered with visible "escaping" of + certain characters in the content, including at least "double quote" + itself, and preferably whitespace other than individual blanks. The intent + is for the viewer to see that the expression is a string literal, and to + see exactly which characters form its content. For example, <ms>double + quote is "</ms> might be rendered as "double quote is \"". + + Obviously this isn't fully done here. + */ + aToken.aText.Erase(); + aToken.aText += '\"'; + aToken.aText += String(rChars); + aToken.aText += '\"'; +} + +void SmXMLStringContext_Impl::EndElement() +{ + GetSmImport().GetNodeStack().Push(new SmTextNode(aToken,FNT_FIXED)); +} + +//////////////////////////////////////////////////////////// + +class SmXMLIdentifierContext_Impl : public SmXMLImportContext +{ +protected: + SmXMLContext_Helper aStyleHelper; + SmToken aToken; + +public: + SmXMLIdentifierContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrefix,rLName),aStyleHelper(*this) + { + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 5; + aToken.eType = TIDENT; + } + + void TCharacters(const OUString &rChars); + void StartElement(const uno::Reference< xml::sax::XAttributeList > & xAttrList ) + { + aStyleHelper.RetrieveAttrs(xAttrList); + }; + void EndElement(); +}; + +void SmXMLIdentifierContext_Impl::EndElement() +{ + SmTextNode *pNode = 0; + //we will handle identifier italic/normal here instead of with a standalone + //font node + if (((aStyleHelper.nIsItalic == -1) && (aToken.aText.Len() > 1)) + || ((aStyleHelper.nIsItalic == 0) && (aToken.aText.Len() == 1))) + { + pNode = new SmTextNode(aToken,FNT_FUNCTION); + pNode->GetFont().SetItalic(ITALIC_NONE); + aStyleHelper.nIsItalic = -1; + } + else + pNode = new SmTextNode(aToken,FNT_VARIABLE); + if (aStyleHelper.bFontNodeNeeded && aStyleHelper.nIsItalic != -1) + { + if (aStyleHelper.nIsItalic) + pNode->GetFont().SetItalic(ITALIC_NORMAL); + else + pNode->GetFont().SetItalic(ITALIC_NONE); + } + + if ((-1!=aStyleHelper.nIsBold) || (0.0!=aStyleHelper.nFontSize) || + (aStyleHelper.sFontFamily.getLength()) || + aStyleHelper.sColor.getLength()) + aStyleHelper.bFontNodeNeeded=sal_True; + else + aStyleHelper.bFontNodeNeeded=sal_False; + if (aStyleHelper.bFontNodeNeeded) + aStyleHelper.ApplyAttrs(); + GetSmImport().GetNodeStack().Push(pNode); +} + +void SmXMLIdentifierContext_Impl::TCharacters(const OUString &rChars) +{ + aToken.aText = rChars; +} + +//////////////////////////////////////////////////////////// + +class SmXMLOperatorContext_Impl : public SmXMLImportContext +{ + sal_Bool bIsStretchy; + +protected: + SmToken aToken; + +public: + SmXMLOperatorContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrefix,rLName), bIsStretchy(sal_False) + { + aToken.nGroup = 0; + aToken.eType = TSPECIAL; + aToken.nLevel = 5; + } + + void TCharacters(const OUString &rChars); + void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList ); + void EndElement(); +}; + +void SmXMLOperatorContext_Impl::TCharacters(const OUString &rChars) +{ + aToken.cMathChar = rChars[0]; +} + +void SmXMLOperatorContext_Impl::EndElement() +{ + SmMathSymbolNode *pNode = new SmMathSymbolNode(aToken); + //For stretchy scaling the scaling must be retrieved from this node + //and applied to the expression itself so as to get the expression + //to scale the operator to the height of the expression itself + if (bIsStretchy) + pNode->SetScaleMode(SCALE_HEIGHT); + GetSmImport().GetNodeStack().Push(pNode); +} + + + +void SmXMLOperatorContext_Impl::StartElement(const uno::Reference< + xml::sax::XAttributeList > & xAttrList ) +{ + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for (sal_Int16 i=0;i<nAttrCount;i++) + { + OUString sAttrName = xAttrList->getNameByIndex(i); + OUString aLocalName; + sal_uInt16 nPrefix = GetImport().GetNamespaceMap(). + GetKeyByAttrName(sAttrName,&aLocalName); + + OUString sValue = xAttrList->getValueByIndex(i); + const SvXMLTokenMap &rAttrTokenMap = + GetSmImport().GetOperatorAttrTokenMap(); + switch(rAttrTokenMap.Get(nPrefix,aLocalName)) + { + case XML_TOK_STRETCHY: + bIsStretchy = sValue.equals( + GetXMLToken(XML_TRUE)); + break; + default: + break; + } + } +} + + +//////////////////////////////////////////////////////////// + +class SmXMLSpaceContext_Impl : public SmXMLImportContext +{ +public: + SmXMLSpaceContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrefix,rLName) {} + + void StartElement(const uno::Reference< xml::sax::XAttributeList >& xAttrList ); +}; + +void SmXMLSpaceContext_Impl::StartElement( + const uno::Reference<xml::sax::XAttributeList > & /*xAttrList*/ ) +{ + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.eType = TBLANK; + aToken.nLevel = 5; + SmBlankNode *pBlank = new SmBlankNode(aToken); + pBlank->IncreaseBy(aToken); + GetSmImport().GetNodeStack().Push(pBlank); +} + +//////////////////////////////////////////////////////////// + +class SmXMLSubContext_Impl : public SmXMLRowContext_Impl +{ +protected: + void GenericEndElement(SmTokenType eType,SmSubSup aSubSup); + +public: + SmXMLSubContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement() + { + GenericEndElement(TRSUB,RSUB); + } +}; + + +void SmXMLSubContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup eSubSup) +{ + /*The <msub> element requires exactly 2 arguments.*/ + const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2; + OSL_ENSURE( bNodeCheck, "Sub has not two arguments" ); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 0; + aToken.eType = eType; + SmSubSupNode *pNode = new SmSubSupNode(aToken); + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + + // initialize subnodes array + SmNodeArray aSubNodes; + aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES); + for (sal_uLong i = 1; i < aSubNodes.size(); i++) + aSubNodes[i] = NULL; + + aSubNodes[eSubSup+1] = rNodeStack.Pop(); + aSubNodes[0] = rNodeStack.Pop(); + pNode->SetSubNodes(aSubNodes); + rNodeStack.Push(pNode); +} + +//////////////////////////////////////////////////////////// + +class SmXMLSupContext_Impl : public SmXMLSubContext_Impl +{ +public: + SmXMLSupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLSubContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement() + { + GenericEndElement(TRSUP,RSUP); + } +}; + +//////////////////////////////////////////////////////////// + +class SmXMLSubSupContext_Impl : public SmXMLRowContext_Impl +{ +protected: + void GenericEndElement(SmTokenType eType, SmSubSup aSub,SmSubSup aSup); + +public: + SmXMLSubSupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement() + { + GenericEndElement(TRSUB,RSUB,RSUP); + } +}; + +void SmXMLSubSupContext_Impl::GenericEndElement(SmTokenType eType, + SmSubSup aSub,SmSubSup aSup) +{ + /*The <msub> element requires exactly 3 arguments.*/ + const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 3; + OSL_ENSURE( bNodeCheck, "SubSup has not three arguments" ); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 0; + aToken.eType = eType; + SmSubSupNode *pNode = new SmSubSupNode(aToken); + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + + // initialize subnodes array + SmNodeArray aSubNodes; + aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES); + for (sal_uLong i = 1; i < aSubNodes.size(); i++) + aSubNodes[i] = NULL; + + aSubNodes[aSup+1] = rNodeStack.Pop(); + aSubNodes[aSub+1] = rNodeStack.Pop(); + aSubNodes[0] = rNodeStack.Pop(); + pNode->SetSubNodes(aSubNodes); + rNodeStack.Push(pNode); +} + +//////////////////////////////////////////////////////////// + +class SmXMLUnderContext_Impl : public SmXMLSubContext_Impl +{ +protected: + sal_Int16 nAttrCount; + +public: + SmXMLUnderContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLSubContext_Impl(rImport,nPrefix,rLName) {} + + void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList ); + void EndElement(); + void HandleAccent(); +}; + +void SmXMLUnderContext_Impl::StartElement(const uno::Reference< + xml::sax::XAttributeList > & xAttrList ) +{ + nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; +} + +void SmXMLUnderContext_Impl::HandleAccent() +{ + const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2; + OSL_ENSURE( bNodeCheck, "Sub has not two arguments" ); + if (!bNodeCheck) + return; + + /*Just one special case for the underline thing*/ + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + SmNode *pTest = rNodeStack.Pop(); + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 0; + aToken.eType = TUNDERLINE; + + + SmNodeArray aSubNodes; + aSubNodes.resize(2); + + SmStructureNode *pNode = new SmAttributNode(aToken); + if ((pTest->GetToken().cMathChar & 0x0FFF) == 0x0332) + { + aSubNodes[0] = new SmRectangleNode(aToken); + delete pTest; + } + else + aSubNodes[0] = pTest; + + aSubNodes[1] = rNodeStack.Pop(); + pNode->SetSubNodes(aSubNodes); + pNode->SetScaleMode(SCALE_WIDTH); + rNodeStack.Push(pNode); +} + + +void SmXMLUnderContext_Impl::EndElement() +{ + if (!nAttrCount) + GenericEndElement(TCSUB,CSUB); + else + HandleAccent(); +} + +//////////////////////////////////////////////////////////// + +class SmXMLOverContext_Impl : public SmXMLSubContext_Impl +{ +protected: + sal_Int16 nAttrCount; + +public: + SmXMLOverContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLSubContext_Impl(rImport,nPrefix,rLName), nAttrCount(0) {} + + void EndElement(); + void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList ); + void HandleAccent(); +}; + + +void SmXMLOverContext_Impl::StartElement(const uno::Reference< + xml::sax::XAttributeList > & xAttrList ) +{ + nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; +} + + +void SmXMLOverContext_Impl::EndElement() +{ + if (!nAttrCount) + GenericEndElement(TCSUP,CSUP); + else + HandleAccent(); +} + + +void SmXMLOverContext_Impl::HandleAccent() +{ + const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2; + OSL_ENSURE (bNodeCheck, "Sub has not two arguments"); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 0; + aToken.eType = TACUTE; + + SmAttributNode *pNode = new SmAttributNode(aToken); + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + + SmNodeArray aSubNodes; + aSubNodes.resize(2); + aSubNodes[0] = rNodeStack.Pop(); + aSubNodes[1] = rNodeStack.Pop(); + pNode->SetSubNodes(aSubNodes); + pNode->SetScaleMode(SCALE_WIDTH); + rNodeStack.Push(pNode); + +} + +//////////////////////////////////////////////////////////// + +class SmXMLUnderOverContext_Impl : public SmXMLSubSupContext_Impl +{ +public: + SmXMLUnderOverContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLSubSupContext_Impl(rImport,nPrefix,rLName) {} + + void EndElement() + { + GenericEndElement(TCSUB,CSUB,CSUP); + } +}; + +//////////////////////////////////////////////////////////// + +class SmXMLMultiScriptsContext_Impl : public SmXMLSubSupContext_Impl +{ + bool bHasPrescripts; + +public: + SmXMLMultiScriptsContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) : + SmXMLSubSupContext_Impl(rImport,nPrefix,rLName), + bHasPrescripts(false) {} + + void EndElement(); + void MiddleElement(); + SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > &xAttrList); +}; + +//////////////////////////////////////////////////////////// + +class SmXMLNoneContext_Impl : public SmXMLImportContext +{ +public: + SmXMLNoneContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrefix,rLName) {} + + void EndElement(); +}; + + +void SmXMLNoneContext_Impl::EndElement(void) +{ + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.aText.Erase(); + aToken.nLevel = 5; + aToken.eType = TIDENT; + GetSmImport().GetNodeStack().Push( + new SmTextNode(aToken,FNT_VARIABLE)); +} + +//////////////////////////////////////////////////////////// + +class SmXMLPrescriptsContext_Impl : public SmXMLImportContext +{ +public: + SmXMLPrescriptsContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) + : SmXMLImportContext(rImport,nPrefix,rLName) {} +}; + +//////////////////////////////////////////////////////////// + +class SmXMLTableRowContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLTableRowContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) : + SmXMLRowContext_Impl(rImport,nPrefix,rLName) + {} + + SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > &xAttrList); +}; + + +//////////////////////////////////////////////////////////// + +class SmXMLTableContext_Impl : public SmXMLTableRowContext_Impl +{ +public: + SmXMLTableContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) : + SmXMLTableRowContext_Impl(rImport,nPrefix,rLName) + {} + + void EndElement(); + SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > &xAttrList); +}; + + +//////////////////////////////////////////////////////////// + +class SmXMLTableCellContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLTableCellContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) : + SmXMLRowContext_Impl(rImport,nPrefix,rLName) + {} +}; + +//////////////////////////////////////////////////////////// + +class SmXMLAlignGroupContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLAlignGroupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) : + SmXMLRowContext_Impl(rImport,nPrefix,rLName) + {} + + /*Don't do anything with alignment for now*/ + void EndElement() + { + } +}; + +//////////////////////////////////////////////////////////// + +class SmXMLActionContext_Impl : public SmXMLRowContext_Impl +{ +public: + SmXMLActionContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix, + const OUString& rLName) : + SmXMLRowContext_Impl(rImport,nPrefix,rLName) + {} + + void EndElement(); +}; + +//////////////////////////////////////////////////////////// + +// NB: virtually inherit so we can multiply inherit properly +// in SmXMLFlatDocContext_Impl +class SmXMLOfficeContext_Impl : public virtual SvXMLImportContext +{ +public: + SmXMLOfficeContext_Impl( SmXMLImport &rImport, sal_uInt16 nPrfx, + const OUString& rLName) + : SvXMLImportContext(rImport,nPrfx,rLName) {} + + virtual SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList); +}; + +SvXMLImportContext *SmXMLOfficeContext_Impl::CreateChildContext(sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference< xml::sax::XAttributeList > &xAttrList) +{ + SvXMLImportContext *pContext = 0; + if ( XML_NAMESPACE_OFFICE == nPrefix && + rLocalName == GetXMLToken(XML_META) ) + { + OSL_FAIL("XML_TOK_DOC_META: should not have come here, maybe document is invalid?"); + } + else if ( XML_NAMESPACE_OFFICE == nPrefix && + rLocalName == GetXMLToken(XML_SETTINGS) ) + { + pContext = new XMLDocumentSettingsContext( GetImport(), + XML_NAMESPACE_OFFICE, rLocalName, + xAttrList ); + } + else + pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); + + return pContext; +} + +//////////////////////////////////////////////////////////// + +// context for flat file xml format +class SmXMLFlatDocContext_Impl + : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext +{ +public: + SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport, + sal_uInt16 i_nPrefix, const OUString & i_rLName, + const uno::Reference<document::XDocumentProperties>& i_xDocProps, + const uno::Reference<xml::sax::XDocumentHandler>& i_xDocBuilder); + + virtual ~SmXMLFlatDocContext_Impl(); + + virtual SvXMLImportContext *CreateChildContext(sal_uInt16 i_nPrefix, const OUString& i_rLocalName, const uno::Reference<xml::sax::XAttributeList>& i_xAttrList); +}; + +SmXMLFlatDocContext_Impl::SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport, + sal_uInt16 i_nPrefix, const OUString & i_rLName, + const uno::Reference<document::XDocumentProperties>& i_xDocProps, + const uno::Reference<xml::sax::XDocumentHandler>& i_xDocBuilder) : + SvXMLImportContext(i_rImport, i_nPrefix, i_rLName), + SmXMLOfficeContext_Impl(i_rImport, i_nPrefix, i_rLName), + SvXMLMetaDocumentContext(i_rImport, i_nPrefix, i_rLName, + i_xDocProps, i_xDocBuilder) +{ +} + +SmXMLFlatDocContext_Impl::~SmXMLFlatDocContext_Impl() +{ +} + +SvXMLImportContext *SmXMLFlatDocContext_Impl::CreateChildContext( + sal_uInt16 i_nPrefix, const OUString& i_rLocalName, + const uno::Reference<xml::sax::XAttributeList>& i_xAttrList) +{ + // behave like meta base class iff we encounter office:meta + if ( XML_NAMESPACE_OFFICE == i_nPrefix && + i_rLocalName == GetXMLToken(XML_META) ) + { + return SvXMLMetaDocumentContext::CreateChildContext( + i_nPrefix, i_rLocalName, i_xAttrList ); + } + else + { + return SmXMLOfficeContext_Impl::CreateChildContext( + i_nPrefix, i_rLocalName, i_xAttrList ); + } +} + +//////////////////////////////////////////////////////////// + +static SvXMLTokenMapEntry aPresLayoutElemTokenMap[] = +{ + { XML_NAMESPACE_MATH, XML_SEMANTICS, XML_TOK_SEMANTICS }, + { XML_NAMESPACE_MATH, XML_MATH, XML_TOK_MATH }, + { XML_NAMESPACE_MATH, XML_MSTYLE, XML_TOK_MSTYLE }, + { XML_NAMESPACE_MATH, XML_MERROR, XML_TOK_MERROR }, + { XML_NAMESPACE_MATH, XML_MPHANTOM, XML_TOK_MPHANTOM }, + { XML_NAMESPACE_MATH, XML_MROW, XML_TOK_MROW }, + { XML_NAMESPACE_MATH, XML_MFRAC, XML_TOK_MFRAC }, + { XML_NAMESPACE_MATH, XML_MSQRT, XML_TOK_MSQRT }, + { XML_NAMESPACE_MATH, XML_MROOT, XML_TOK_MROOT }, + { XML_NAMESPACE_MATH, XML_MSUB, XML_TOK_MSUB }, + { XML_NAMESPACE_MATH, XML_MSUP, XML_TOK_MSUP }, + { XML_NAMESPACE_MATH, XML_MSUBSUP, XML_TOK_MSUBSUP }, + { XML_NAMESPACE_MATH, XML_MUNDER, XML_TOK_MUNDER }, + { XML_NAMESPACE_MATH, XML_MOVER, XML_TOK_MOVER }, + { XML_NAMESPACE_MATH, XML_MUNDEROVER, XML_TOK_MUNDEROVER }, + { XML_NAMESPACE_MATH, XML_MMULTISCRIPTS, XML_TOK_MMULTISCRIPTS }, + { XML_NAMESPACE_MATH, XML_MTABLE, XML_TOK_MTABLE }, + { XML_NAMESPACE_MATH, XML_MACTION, XML_TOK_MACTION }, + { XML_NAMESPACE_MATH, XML_MFENCED, XML_TOK_MFENCED }, + { XML_NAMESPACE_MATH, XML_MPADDED, XML_TOK_MPADDED }, + XML_TOKEN_MAP_END +}; + +static SvXMLTokenMapEntry aPresLayoutAttrTokenMap[] = +{ + { XML_NAMESPACE_MATH, XML_FONTWEIGHT, XML_TOK_FONTWEIGHT }, + { XML_NAMESPACE_MATH, XML_FONTSTYLE, XML_TOK_FONTSTYLE }, + { XML_NAMESPACE_MATH, XML_FONTSIZE, XML_TOK_FONTSIZE }, + { XML_NAMESPACE_MATH, XML_FONTFAMILY, XML_TOK_FONTFAMILY }, + { XML_NAMESPACE_MATH, XML_COLOR, XML_TOK_COLOR }, + XML_TOKEN_MAP_END +}; + +static SvXMLTokenMapEntry aFencedAttrTokenMap[] = +{ + { XML_NAMESPACE_MATH, XML_OPEN, XML_TOK_OPEN }, + { XML_NAMESPACE_MATH, XML_CLOSE, XML_TOK_CLOSE }, + XML_TOKEN_MAP_END +}; + +static SvXMLTokenMapEntry aOperatorAttrTokenMap[] = +{ + { XML_NAMESPACE_MATH, XML_STRETCHY, XML_TOK_STRETCHY }, + XML_TOKEN_MAP_END +}; + +static SvXMLTokenMapEntry aAnnotationAttrTokenMap[] = +{ + { XML_NAMESPACE_MATH, XML_ENCODING, XML_TOK_ENCODING }, + XML_TOKEN_MAP_END +}; + + +static SvXMLTokenMapEntry aPresElemTokenMap[] = +{ + { XML_NAMESPACE_MATH, XML_ANNOTATION, XML_TOK_ANNOTATION }, + { XML_NAMESPACE_MATH, XML_MI, XML_TOK_MI }, + { XML_NAMESPACE_MATH, XML_MN, XML_TOK_MN }, + { XML_NAMESPACE_MATH, XML_MO, XML_TOK_MO }, + { XML_NAMESPACE_MATH, XML_MTEXT, XML_TOK_MTEXT }, + { XML_NAMESPACE_MATH, XML_MSPACE,XML_TOK_MSPACE }, + { XML_NAMESPACE_MATH, XML_MS, XML_TOK_MS }, + { XML_NAMESPACE_MATH, XML_MALIGNGROUP, XML_TOK_MALIGNGROUP }, + XML_TOKEN_MAP_END +}; + +static SvXMLTokenMapEntry aPresScriptEmptyElemTokenMap[] = +{ + { XML_NAMESPACE_MATH, XML_MPRESCRIPTS, XML_TOK_MPRESCRIPTS }, + { XML_NAMESPACE_MATH, XML_NONE, XML_TOK_NONE }, + XML_TOKEN_MAP_END +}; + +static SvXMLTokenMapEntry aPresTableElemTokenMap[] = +{ + { XML_NAMESPACE_MATH, XML_MTR, XML_TOK_MTR }, + { XML_NAMESPACE_MATH, XML_MTD, XML_TOK_MTD }, + XML_TOKEN_MAP_END +}; + +static SvXMLTokenMapEntry aColorTokenMap[] = +{ + { XML_NAMESPACE_MATH, XML_BLACK, TBLACK}, + { XML_NAMESPACE_MATH, XML_WHITE, TWHITE}, + { XML_NAMESPACE_MATH, XML_RED, TRED}, + { XML_NAMESPACE_MATH, XML_GREEN, TGREEN}, + { XML_NAMESPACE_MATH, XML_BLUE, TBLUE}, + { XML_NAMESPACE_MATH, XML_AQUA, TCYAN}, + { XML_NAMESPACE_MATH, XML_FUCHSIA, TMAGENTA}, + { XML_NAMESPACE_MATH, XML_YELLOW, TYELLOW}, + XML_TOKEN_MAP_END +}; + + +//////////////////////////////////////////////////////////// + +const SvXMLTokenMap& SmXMLImport::GetPresLayoutElemTokenMap() +{ + if (!pPresLayoutElemTokenMap) + pPresLayoutElemTokenMap = new SvXMLTokenMap(aPresLayoutElemTokenMap); + return *pPresLayoutElemTokenMap; +} + +const SvXMLTokenMap& SmXMLImport::GetPresLayoutAttrTokenMap() +{ + if (!pPresLayoutAttrTokenMap) + pPresLayoutAttrTokenMap = new SvXMLTokenMap(aPresLayoutAttrTokenMap); + return *pPresLayoutAttrTokenMap; +} + + +const SvXMLTokenMap& SmXMLImport::GetFencedAttrTokenMap() +{ + if (!pFencedAttrTokenMap) + pFencedAttrTokenMap = new SvXMLTokenMap(aFencedAttrTokenMap); + return *pFencedAttrTokenMap; +} + +const SvXMLTokenMap& SmXMLImport::GetOperatorAttrTokenMap() +{ + if (!pOperatorAttrTokenMap) + pOperatorAttrTokenMap = new SvXMLTokenMap(aOperatorAttrTokenMap); + return *pOperatorAttrTokenMap; +} + +const SvXMLTokenMap& SmXMLImport::GetAnnotationAttrTokenMap() +{ + if (!pAnnotationAttrTokenMap) + pAnnotationAttrTokenMap = new SvXMLTokenMap(aAnnotationAttrTokenMap); + return *pAnnotationAttrTokenMap; +} + +const SvXMLTokenMap& SmXMLImport::GetPresElemTokenMap() +{ + if (!pPresElemTokenMap) + pPresElemTokenMap = new SvXMLTokenMap(aPresElemTokenMap); + return *pPresElemTokenMap; +} + +const SvXMLTokenMap& SmXMLImport::GetPresScriptEmptyElemTokenMap() +{ + if (!pPresScriptEmptyElemTokenMap) + pPresScriptEmptyElemTokenMap = new + SvXMLTokenMap(aPresScriptEmptyElemTokenMap); + return *pPresScriptEmptyElemTokenMap; +} + +const SvXMLTokenMap& SmXMLImport::GetPresTableElemTokenMap() +{ + if (!pPresTableElemTokenMap) + pPresTableElemTokenMap = new SvXMLTokenMap(aPresTableElemTokenMap); + return *pPresTableElemTokenMap; +} + +const SvXMLTokenMap& SmXMLImport::GetColorTokenMap() +{ + if (!pColorTokenMap) + pColorTokenMap = new SvXMLTokenMap(aColorTokenMap); + return *pColorTokenMap; +} + +//////////////////////////////////////////////////////////// + +SvXMLImportContext *SmXMLDocContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference<xml::sax::XAttributeList>& xAttrList) +{ + SvXMLImportContext* pContext = 0L; + + const SvXMLTokenMap& rTokenMap = GetSmImport().GetPresLayoutElemTokenMap(); + + switch(rTokenMap.Get(nPrefix, rLocalName)) + { + //Consider semantics a dummy except for any starmath annotations + case XML_TOK_SEMANTICS: + pContext = GetSmImport().CreateRowContext(nPrefix,rLocalName, + xAttrList); + break; + /*General Layout Schemata*/ + case XML_TOK_MROW: + pContext = GetSmImport().CreateRowContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MFRAC: + pContext = GetSmImport().CreateFracContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MSQRT: + pContext = GetSmImport().CreateSqrtContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MROOT: + pContext = GetSmImport().CreateRootContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MSTYLE: + pContext = GetSmImport().CreateStyleContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MERROR: + pContext = GetSmImport().CreateErrorContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MPADDED: + pContext = GetSmImport().CreatePaddedContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MPHANTOM: + pContext = GetSmImport().CreatePhantomContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MFENCED: + pContext = GetSmImport().CreateFencedContext(nPrefix,rLocalName, + xAttrList); + break; + /*Script and Limit Schemata*/ + case XML_TOK_MSUB: + pContext = GetSmImport().CreateSubContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MSUP: + pContext = GetSmImport().CreateSupContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MSUBSUP: + pContext = GetSmImport().CreateSubSupContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MUNDER: + pContext = GetSmImport().CreateUnderContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MOVER: + pContext = GetSmImport().CreateOverContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MUNDEROVER: + pContext = GetSmImport().CreateUnderOverContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MMULTISCRIPTS: + pContext = GetSmImport().CreateMultiScriptsContext(nPrefix, + rLocalName, xAttrList); + break; + case XML_TOK_MTABLE: + pContext = GetSmImport().CreateTableContext(nPrefix, + rLocalName, xAttrList); + break; + case XML_TOK_MACTION: + pContext = GetSmImport().CreateActionContext(nPrefix, + rLocalName, xAttrList); + break; + default: + /*Basically theres an implicit mrow around certain bare + *elements, use a RowContext to see if this is one of + *those ones*/ + SmXMLRowContext_Impl aTempContext(GetSmImport(),nPrefix, + GetXMLToken(XML_MROW)); + + pContext = aTempContext.StrictCreateChildContext(nPrefix, + rLocalName, xAttrList); + break; + } + return pContext; +} + +void SmXMLDocContext_Impl::EndElement() +{ + SmNodeArray ContextArray; + ContextArray.resize(1); + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + + for (sal_uLong i=0;i< 1;i++) + ContextArray[i] = rNodeStack.Pop(); + + SmToken aDummy; + SmStructureNode *pSNode = new SmLineNode(aDummy); + pSNode->SetSubNodes(ContextArray); + rNodeStack.Push(pSNode); + + SmNodeArray LineArray; + sal_uLong n = rNodeStack.Count(); + LineArray.resize(n); + for (sal_uLong j = 0; j < n; j++) + LineArray[n - (j + 1)] = rNodeStack.Pop(); + SmStructureNode *pSNode2 = new SmTableNode(aDummy); + pSNode2->SetSubNodes(LineArray); + rNodeStack.Push(pSNode2); +} + +void SmXMLFracContext_Impl::EndElement() +{ + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + const bool bNodeCheck = rNodeStack.Count() - nElementCount == 2; + OSL_ENSURE( bNodeCheck, "Fraction (mfrac) tag is missing component" ); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 0; + aToken.eType = TOVER; + SmStructureNode *pSNode = new SmBinVerNode(aToken); + SmNode *pOper = new SmRectangleNode(aToken); + SmNode *pSecond = rNodeStack.Pop(); + SmNode *pFirst = rNodeStack.Pop(); + pSNode->SetSubNodes(pFirst,pOper,pSecond); + rNodeStack.Push(pSNode); +} + +void SmXMLRootContext_Impl::EndElement() +{ + /*The <mroot> element requires exactly 2 arguments.*/ + const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2; + OSL_ENSURE( bNodeCheck, "Root tag is missing component"); + if (!bNodeCheck) + return; + + SmToken aToken; + aToken.cMathChar = MS_SQRT; //Temporary: alert, based on StarSymbol font + aToken.nGroup = 0; + aToken.nLevel = 0; + aToken.eType = TNROOT; + SmStructureNode *pSNode = new SmRootNode(aToken); + SmNode *pOper = new SmRootSymbolNode(aToken); + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + SmNode *pIndex = rNodeStack.Pop(); + SmNode *pBase = rNodeStack.Pop(); + pSNode->SetSubNodes(pIndex,pOper,pBase); + rNodeStack.Push(pSNode); +} + +void SmXMLSqrtContext_Impl::EndElement() +{ + /* + <msqrt> accepts any number of arguments; if this number is not 1, its + contents are treated as a single "inferred <mrow>" containing its + arguments + */ + if (GetSmImport().GetNodeStack().Count() - nElementCount > 1) + SmXMLRowContext_Impl::EndElement(); + + SmToken aToken; + aToken.cMathChar = MS_SQRT; //Temporary: alert, based on StarSymbol font + aToken.nGroup = 0; + aToken.nLevel = 0; + aToken.eType = TSQRT; + SmStructureNode *pSNode = new SmRootNode(aToken); + SmNode *pOper = new SmRootSymbolNode(aToken); + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + pSNode->SetSubNodes(0,pOper,rNodeStack.Pop()); + rNodeStack.Push(pSNode); +} + +void SmXMLRowContext_Impl::EndElement() +{ + SmNodeArray aRelationArray; + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + sal_uLong nSize = rNodeStack.Count()-nElementCount; + + if (nSize > 0) + { + aRelationArray.resize(nSize); + for (sal_uLong j=rNodeStack.Count()-nElementCount;j > 0;j--) + aRelationArray[j-1] = rNodeStack.Pop(); + + + //If the first or last element is an operator with stretchyness + //set then we must create a brace node here from those elements, + //removing the stretchness from the operators and applying it to + //ourselves, and creating the appropiate dummy StarMath none bracket + //to balance the arrangement + if (((aRelationArray[0]->GetScaleMode() == SCALE_HEIGHT) + && (aRelationArray[0]->GetType() == NMATH)) + || ((aRelationArray[nSize-1]->GetScaleMode() == SCALE_HEIGHT) + && (aRelationArray[nSize-1]->GetType() == NMATH))) + { + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 5; + + int nLeft=0,nRight=0; + if ((aRelationArray[0]->GetScaleMode() == SCALE_HEIGHT) + && (aRelationArray[0]->GetType() == NMATH)) + { + aToken = aRelationArray[0]->GetToken(); + nLeft=1; + } + else + aToken.cMathChar = '\0'; + + aToken.eType = TLPARENT; + SmNode *pLeft = new SmMathSymbolNode(aToken); + + if ((aRelationArray[nSize-1]->GetScaleMode() == SCALE_HEIGHT) + && (aRelationArray[nSize-1]->GetType() == NMATH)) + { + aToken = aRelationArray[nSize-1]->GetToken(); + nRight=1; + } + else + aToken.cMathChar = '\0'; + + aToken.eType = TRPARENT; + SmNode *pRight = new SmMathSymbolNode(aToken); + + SmNodeArray aRelationArray2; + + //!! nSize-nLeft-nRight may be < 0 !! + int nRelArrSize = nSize-nLeft-nRight; + if (nRelArrSize > 0) + { + aRelationArray2.resize(nRelArrSize); + for (int i=0;i < nRelArrSize;i++) + aRelationArray2[i] = aRelationArray[i+nLeft]; + } + + SmToken aDummy; + SmStructureNode *pSNode = new SmBraceNode(aToken); + SmStructureNode *pBody = new SmExpressionNode(aDummy); + pBody->SetSubNodes(aRelationArray2); + + pSNode->SetSubNodes(pLeft,pBody,pRight); + pSNode->SetScaleMode(SCALE_HEIGHT); + rNodeStack.Push(pSNode); + return; + } + } + else //Multiple newlines result in empty row elements + { + aRelationArray.resize(1); + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 5; + aToken.eType = TNEWLINE; + aRelationArray[0] = new SmLineNode(aToken); + } + + SmToken aDummy; + SmStructureNode *pSNode = new SmExpressionNode(aDummy); + pSNode->SetSubNodes(aRelationArray); + rNodeStack.Push(pSNode); +} + + +SvXMLImportContext *SmXMLRowContext_Impl::StrictCreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference<xml::sax::XAttributeList>& xAttrList) +{ + SvXMLImportContext* pContext = 0L; + + const SvXMLTokenMap& rTokenMap = GetSmImport().GetPresElemTokenMap(); + switch(rTokenMap.Get(nPrefix, rLocalName)) + { + /*Note that these should accept malignmark subelements, but do not*/ + case XML_TOK_MN: + pContext = GetSmImport().CreateNumberContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MI: + pContext = GetSmImport().CreateIdentifierContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MO: + pContext = GetSmImport().CreateOperatorContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MTEXT: + pContext = GetSmImport().CreateTextContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MSPACE: + pContext = GetSmImport().CreateSpaceContext(nPrefix,rLocalName, + xAttrList); + break; + case XML_TOK_MS: + pContext = GetSmImport().CreateStringContext(nPrefix,rLocalName, + xAttrList); + break; + + /*Note: The maligngroup should only be seen when the row + * (or decendants) are in a table*/ + case XML_TOK_MALIGNGROUP: + pContext = GetSmImport().CreateAlignGroupContext(nPrefix,rLocalName, + xAttrList); + break; + + case XML_TOK_ANNOTATION: + pContext = GetSmImport().CreateAnnotationContext(nPrefix,rLocalName, + xAttrList); + break; + + default: + break; + } + return pContext; +} + + +SvXMLImportContext *SmXMLRowContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference<xml::sax::XAttributeList>& xAttrList) +{ + SvXMLImportContext* pContext = StrictCreateChildContext(nPrefix, + rLocalName, xAttrList); + + if (!pContext) + { + //Hmm, unrecognized for this level, check to see if its + //an element that can have an implicit schema around it + pContext = SmXMLDocContext_Impl::CreateChildContext(nPrefix, + rLocalName,xAttrList); + } + return pContext; +} + + +SvXMLImportContext *SmXMLMultiScriptsContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference<xml::sax::XAttributeList>& xAttrList) +{ + SvXMLImportContext* pContext = 0L; + + const SvXMLTokenMap& rTokenMap = GetSmImport(). + GetPresScriptEmptyElemTokenMap(); + switch(rTokenMap.Get(nPrefix, rLocalName)) + { + case XML_TOK_MPRESCRIPTS: + MiddleElement(); + pContext = GetSmImport().CreatePrescriptsContext(nPrefix, + rLocalName, xAttrList); + break; + case XML_TOK_NONE: + pContext = GetSmImport().CreateNoneContext(nPrefix,rLocalName, + xAttrList); + break; + default: + pContext = SmXMLRowContext_Impl::CreateChildContext(nPrefix, + rLocalName,xAttrList); + break; + } + return pContext; +} + +void SmXMLMultiScriptsContext_Impl::MiddleElement() +{ + bHasPrescripts=true; + + OSL_ENSURE( GetSmImport().GetNodeStack().Count() - nElementCount > 0, + "Sub has no arguments"); + + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + if (rNodeStack.Count()-nElementCount > 1) + { + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 0; + aToken.eType = TRSUB; + sal_uLong nFinalCount = rNodeStack.Count()-nElementCount-1; + + SmNodeStack aReverseStack; + while (rNodeStack.Count()-nElementCount) + { + SmNode *pThing = rNodeStack.Pop(); + aReverseStack.Push(pThing); + } + + for (sal_uLong nCount=0;nCount < nFinalCount;nCount+=2) + { + SmSubSupNode *pNode = new SmSubSupNode(aToken); + + // initialize subnodes array + SmNodeArray aSubNodes; + aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES); + for (sal_uLong i = 1; i < aSubNodes.size(); i++) + aSubNodes[i] = NULL; + + /*On each loop the base and its sub sup pair becomes the + base for the next loop to which the next sub sup pair is + attached, i.e. wheels within wheels*/ + aSubNodes[0] = aReverseStack.Pop(); + + SmNode *pScriptNode = aReverseStack.Pop(); + + if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) || + (pScriptNode->GetToken().aText.Len()))) + aSubNodes[RSUB+1] = pScriptNode; + pScriptNode = aReverseStack.Pop(); + if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) || + (pScriptNode->GetToken().aText.Len()))) + aSubNodes[RSUP+1] = pScriptNode; + + pNode->SetSubNodes(aSubNodes); + aReverseStack.Push(pNode); + } + rNodeStack.Push(aReverseStack.Pop()); + } +} + + +void SmXMLTableContext_Impl::EndElement() +{ + SmNodeArray aExpressionArray; + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + SmNodeStack aReverseStack; + aExpressionArray.resize(rNodeStack.Count()-nElementCount); + + sal_uLong nRows = rNodeStack.Count()-nElementCount; + sal_uInt16 nCols = 0; + + SmStructureNode *pArray; + for (sal_uLong i=rNodeStack.Count()-nElementCount;i > 0;i--) + { + pArray = (SmStructureNode *)rNodeStack.Pop(); + if (pArray->GetNumSubNodes() == 0) + { + //This is a little tricky, it is possible that there was + //be elements that were not inside a <mtd> pair, in which + //case they will not be in a row, i.e. they will not have + //SubNodes, so we have to wait until here before we can + //resolve the situation. Implicitsurrounding tags are + //surprisingly difficult to get right within this + //architecture + + SmNodeArray aRelationArray; + aRelationArray.resize(1); + aRelationArray[0] = pArray; + SmToken aDummy; + pArray = new SmExpressionNode(aDummy); + pArray->SetSubNodes(aRelationArray); + } + + if (pArray->GetNumSubNodes() > nCols) + nCols = pArray->GetNumSubNodes(); + aReverseStack.Push(pArray); + } + aExpressionArray.resize(nCols*nRows); + sal_uLong j=0; + while (aReverseStack.Count()) + { + pArray = (SmStructureNode *)aReverseStack.Pop(); + for (sal_uInt16 i=0;i<pArray->GetNumSubNodes();i++) + aExpressionArray[j++] = pArray->GetSubNode(i); + } + + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = TRGROUP; + aToken.nLevel = 0; + aToken.eType = TMATRIX; + SmMatrixNode *pSNode = new SmMatrixNode(aToken); + pSNode->SetSubNodes(aExpressionArray); + pSNode->SetRowCol(static_cast<sal_uInt16>(nRows),nCols); + rNodeStack.Push(pSNode); +} + +SvXMLImportContext *SmXMLTableRowContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference<xml::sax::XAttributeList>& xAttrList) +{ + SvXMLImportContext* pContext = 0L; + + const SvXMLTokenMap& rTokenMap = GetSmImport(). + GetPresTableElemTokenMap(); + switch(rTokenMap.Get(nPrefix, rLocalName)) + { + case XML_TOK_MTD: + pContext = GetSmImport().CreateTableCellContext(nPrefix, + rLocalName, xAttrList); + break; + default: + pContext = SmXMLRowContext_Impl::CreateChildContext(nPrefix, + rLocalName,xAttrList); + break; + } + return pContext; +} + +SvXMLImportContext *SmXMLTableContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const uno::Reference<xml::sax::XAttributeList>& xAttrList) +{ + SvXMLImportContext* pContext = 0L; + + const SvXMLTokenMap& rTokenMap = GetSmImport(). + GetPresTableElemTokenMap(); + switch(rTokenMap.Get(nPrefix, rLocalName)) + { + case XML_TOK_MTR: + pContext = GetSmImport().CreateTableRowContext(nPrefix,rLocalName, + xAttrList); + break; + default: + pContext = SmXMLTableRowContext_Impl::CreateChildContext(nPrefix, + rLocalName,xAttrList); + break; + } + return pContext; +} + +void SmXMLMultiScriptsContext_Impl::EndElement() +{ + if (!bHasPrescripts) + MiddleElement(); + + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + if (rNodeStack.Count()-nElementCount > 1) + { + SmToken aToken; + aToken.cMathChar = '\0'; + aToken.nGroup = 0; + aToken.nLevel = 0; + aToken.eType = TLSUB; + sal_uLong nFinalCount = rNodeStack.Count()-nElementCount-1; + + SmNodeStack aReverseStack; + while (rNodeStack.Count()-nElementCount) + aReverseStack.Push(rNodeStack.Pop()); + for (sal_uLong nCount=0;nCount < nFinalCount;nCount+=2) + { + SmSubSupNode *pNode = new SmSubSupNode(aToken); + + // initialize subnodes array + SmNodeArray aSubNodes; + aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES); + for (sal_uLong i = 1; i < aSubNodes.size(); i++) + aSubNodes[i] = NULL; + + /*On each loop the base and its sub sup pair becomes the + base for the next loop to which the next sub sup pair is + attached, i.e. wheels within wheels*/ + aSubNodes[0] = aReverseStack.Pop(); + + SmNode *pScriptNode = aReverseStack.Pop(); + if (pScriptNode->GetToken().aText.Len()) + aSubNodes[LSUB+1] = pScriptNode; + pScriptNode = aReverseStack.Pop(); + if (pScriptNode->GetToken().aText.Len()) + aSubNodes[LSUP+1] = pScriptNode; + + pNode->SetSubNodes(aSubNodes); + aReverseStack.Push(pNode); + } + rNodeStack.Push(aReverseStack.Pop()); + } + +} +void SmXMLActionContext_Impl::EndElement() +{ + /*For now we will just assume that the + selected attribute is one, and then just display + that expression alone, i.e. remove all expect the + first pushed one*/ + + SmNodeStack &rNodeStack = GetSmImport().GetNodeStack(); + for (sal_uLong i=rNodeStack.Count()-nElementCount;i > 1;i--) + { + delete rNodeStack.Pop(); + } +} + +SvXMLImportContext *SmXMLImport::CreateContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + if ( XML_NAMESPACE_OFFICE == nPrefix ) + { + if ( (IsXMLToken(rLocalName, XML_DOCUMENT) || + IsXMLToken(rLocalName, XML_DOCUMENT_META))) + { + uno::Reference<xml::sax::XDocumentHandler> xDocBuilder( + mxServiceFactory->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.dom.SAXDocumentBuilder"))), + uno::UNO_QUERY_THROW); + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + GetModel(), uno::UNO_QUERY_THROW); + return IsXMLToken(rLocalName, XML_DOCUMENT_META) + ? new SvXMLMetaDocumentContext(*this, + XML_NAMESPACE_OFFICE, rLocalName, + xDPS->getDocumentProperties(), xDocBuilder) + // flat OpenDocument file format -- this has not been tested... + : new SmXMLFlatDocContext_Impl( *this, nPrefix, rLocalName, + xDPS->getDocumentProperties(), xDocBuilder); + } + else + { + return new SmXMLOfficeContext_Impl( *this,nPrefix,rLocalName); + } + } + else + return new SmXMLDocContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateRowContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLRowContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateTextContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLTextContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateAnnotationContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLAnnotationContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateStringContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLStringContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateNumberContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLNumberContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateIdentifierContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLIdentifierContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateOperatorContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLOperatorContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateSpaceContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLSpaceContext_Impl(*this,nPrefix,rLocalName); +} + + +SvXMLImportContext *SmXMLImport::CreateFracContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLFracContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateSqrtContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLSqrtContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateRootContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLRootContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateStyleContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLStyleContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreatePaddedContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLPaddedContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreatePhantomContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLPhantomContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateFencedContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLFencedContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateErrorContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLErrorContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateSubContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLSubContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateSubSupContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLSubSupContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateSupContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLSupContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateUnderContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLUnderContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateOverContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLOverContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateUnderOverContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLUnderOverContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateMultiScriptsContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLMultiScriptsContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateTableContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLTableContext_Impl(*this,nPrefix,rLocalName); +} +SvXMLImportContext *SmXMLImport::CreateTableRowContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLTableRowContext_Impl(*this,nPrefix,rLocalName); +} +SvXMLImportContext *SmXMLImport::CreateTableCellContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLTableCellContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateNoneContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLNoneContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreatePrescriptsContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLPrescriptsContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateAlignGroupContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLAlignGroupContext_Impl(*this,nPrefix,rLocalName); +} + +SvXMLImportContext *SmXMLImport::CreateActionContext(sal_uInt16 nPrefix, + const OUString &rLocalName, + const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/) +{ + return new SmXMLActionContext_Impl(*this,nPrefix,rLocalName); +} + +SmXMLImport::~SmXMLImport() throw () +{ + delete pPresLayoutElemTokenMap; + delete pPresElemTokenMap; + delete pPresScriptEmptyElemTokenMap; + delete pPresTableElemTokenMap; + delete pPresLayoutAttrTokenMap; + delete pFencedAttrTokenMap; + delete pColorTokenMap; + delete pOperatorAttrTokenMap; + delete pAnnotationAttrTokenMap; +} + +void SmXMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps) +{ + uno::Reference <frame::XModel> xModel = GetModel(); + if ( !xModel.is() ) + return; + + uno::Reference <lang::XUnoTunnel> xTunnel; + xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY); + SmModel *pModel = reinterpret_cast<SmModel *> + (xTunnel->getSomething(SmModel::getUnoTunnelId())); + + if ( !pModel ) + return; + + SmDocShell *pDocShell = + static_cast<SmDocShell*>(pModel->GetObjectShell()); + if ( !pDocShell ) + return; + + Rectangle aRect( pDocShell->GetVisArea() ); + + sal_Int32 nCount = aViewProps.getLength(); + const PropertyValue *pValue = aViewProps.getConstArray(); + + long nTmp = 0; + + for (sal_Int32 i = 0; i < nCount ; i++) + { + if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaTop" ) ) ) + { + pValue->Value >>= nTmp; + aRect.setY( nTmp ); + } + else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaLeft" ) ) ) + { + pValue->Value >>= nTmp; + aRect.setX( nTmp ); + } + else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaWidth" ) ) ) + { + pValue->Value >>= nTmp; + Size aSize( aRect.GetSize() ); + aSize.Width() = nTmp; + aRect.SetSize( aSize ); + } + else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaHeight" ) ) ) + { + pValue->Value >>= nTmp; + Size aSize( aRect.GetSize() ); + aSize.Height() = nTmp; + aRect.SetSize( aSize ); + } + pValue++; + } + + pDocShell->SetVisArea ( aRect ); +} + +void SmXMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps) +{ + uno::Reference < XPropertySet > xProps ( GetModel(), UNO_QUERY ); + if ( xProps.is() ) + { + Reference < XPropertySetInfo > xInfo ( xProps->getPropertySetInfo() ); + if (xInfo.is() ) + { + sal_Int32 nCount = aConfProps.getLength(); + const PropertyValue* pValues = aConfProps.getConstArray(); + + const OUString sFormula ( RTL_CONSTASCII_USTRINGPARAM ( "Formula" ) ); + const OUString sBasicLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "BasicLibraries" ) ); + const OUString sDialogLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "DialogLibraries" ) ); + while ( nCount-- ) + { + if (pValues->Name != sFormula && + pValues->Name != sBasicLibraries && + pValues->Name != sDialogLibraries) + { + try + { + if ( xInfo->hasPropertyByName( pValues->Name ) ) + xProps->setPropertyValue( pValues->Name, pValues->Value ); + } + catch (beans::PropertyVetoException &e) + { + (void) e; + // dealing with read-only properties here. Nothing to do... + } + catch( Exception& e) + { + OSL_FAIL( "SmXMLImport::SetConfigurationSettings: Exception!" ); + } + } + + pValues++; + } + } + } +} + + +//////////////////////////////////////////////////////////// + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathmlimport.hxx b/starmath/source/mathmlimport.hxx new file mode 100644 index 000000000000..db44e4a336ea --- /dev/null +++ b/starmath/source/mathmlimport.hxx @@ -0,0 +1,348 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _MATHMLIMPORT_HXX_ +#define _MATHMLIMPORT_HXX_ + +#include <xmloff/xmlimp.hxx> +#include <xmloff/xmlexp.hxx> +#include <xmloff/DocumentSettingsContext.hxx> +#include <xmloff/xmltoken.hxx> + +#include <node.hxx> + +class SfxMedium; +namespace com { namespace sun { namespace star { + namespace io { + class XInputStream; + class XOutputStream; } + namespace beans { + class XPropertySet; } +} } } + +//////////////////////////////////////////////////////////// + +class SmXMLImportWrapper +{ + com::sun::star::uno::Reference<com::sun::star::frame::XModel> xModel; + +public: + SmXMLImportWrapper(com::sun::star::uno::Reference<com::sun::star::frame::XModel> &rRef) + : xModel(rRef) {} + + sal_uLong Import(SfxMedium &rMedium); + + sal_uLong ReadThroughComponent( + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xInputStream, + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > xModelComponent, + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rFactory, + ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet > & rPropSet, + const sal_Char* pFilterName, + sal_Bool bEncrypted ); + + sal_uLong ReadThroughComponent( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > xModelComponent, + const sal_Char* pStreamName, + const sal_Char* pCompatibilityStreamName, + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rFactory, + ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySet > & rPropSet, + const sal_Char* pFilterName ); +}; + +//////////////////////////////////////////////////////////// + +class SmXMLImport : public SvXMLImport +{ + SvXMLTokenMap *pPresLayoutElemTokenMap; + SvXMLTokenMap *pPresLayoutAttrTokenMap; + SvXMLTokenMap *pFencedAttrTokenMap; + SvXMLTokenMap *pOperatorAttrTokenMap; + SvXMLTokenMap *pAnnotationAttrTokenMap; + SvXMLTokenMap *pPresElemTokenMap; + SvXMLTokenMap *pPresScriptEmptyElemTokenMap; + SvXMLTokenMap *pPresTableElemTokenMap; + SvXMLTokenMap *pColorTokenMap; + + SmNodeStack aNodeStack; + sal_Bool bSuccess; + String aText; + +public: + SmXMLImport( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory, + sal_uInt16 nImportFlags=IMPORT_ALL); + virtual ~SmXMLImport() throw (); + + // XServiceInfo (override parent method) + ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + + // XUnoTunnel + sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw(::com::sun::star::uno::RuntimeException); + static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId() throw(); + + void SAL_CALL endDocument(void) + throw( ::com::sun::star::xml::sax::SAXException, + ::com::sun::star::uno::RuntimeException ); + + SvXMLImportContext *CreateContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateMathContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateRowContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateFracContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateNumberContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateTextContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateAnnotationContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateStringContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateIdentifierContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateOperatorContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateSpaceContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateSqrtContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateRootContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateStyleContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreatePaddedContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreatePhantomContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateFencedContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateErrorContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateSubContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateSupContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateSubSupContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateUnderContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateOverContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateUnderOverContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateMultiScriptsContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateNoneContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreatePrescriptsContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateTableContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateTableRowContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateTableCellContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateAlignGroupContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + SvXMLImportContext *CreateActionContext(sal_uInt16 nPrefix, + const rtl::OUString &rLocalName, + const com::sun::star::uno::Reference < + com::sun::star::xml::sax::XAttributeList> &xAttrList); + + const SvXMLTokenMap &GetPresLayoutElemTokenMap(); + const SvXMLTokenMap &GetPresLayoutAttrTokenMap(); + const SvXMLTokenMap &GetFencedAttrTokenMap(); + const SvXMLTokenMap &GetOperatorAttrTokenMap(); + const SvXMLTokenMap &GetAnnotationAttrTokenMap(); + const SvXMLTokenMap &GetPresElemTokenMap(); + const SvXMLTokenMap &GetPresScriptEmptyElemTokenMap(); + const SvXMLTokenMap &GetPresTableElemTokenMap(); + const SvXMLTokenMap &GetColorTokenMap(); + + SmNodeStack & GetNodeStack() { return aNodeStack; } + SmNode *GetTree() { return aNodeStack.Pop(); } + sal_Bool GetSuccess() { return bSuccess; } + String &GetText() { return aText; } + + virtual void SetViewSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aViewProps); + virtual void SetConfigurationSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aViewProps); +}; + +//////////////////////////////////////////////////////////// + +enum SmXMLMathElemTokenMap +{ + XML_TOK_MATH +}; + +enum SmXMLPresLayoutElemTokenMap +{ + XML_TOK_SEMANTICS, + XML_TOK_MSTYLE, + XML_TOK_MERROR, + XML_TOK_MPHANTOM, + XML_TOK_MROW, + XML_TOK_MFRAC, + XML_TOK_MSQRT, + XML_TOK_MROOT, + XML_TOK_MSUB, + XML_TOK_MSUP, + XML_TOK_MSUBSUP, + XML_TOK_MMULTISCRIPTS, + XML_TOK_MUNDER, + XML_TOK_MOVER, + XML_TOK_MUNDEROVER, + XML_TOK_MTABLE, + XML_TOK_MACTION, + XML_TOK_MFENCED, + XML_TOK_MPADDED +}; + +enum SmXMLPresLayoutAttrTokenMap +{ + XML_TOK_FONTWEIGHT, + XML_TOK_FONTSTYLE, + XML_TOK_FONTSIZE, + XML_TOK_FONTFAMILY, + XML_TOK_COLOR +}; + + +enum SmXMLFencedAttrTokenMap +{ + XML_TOK_OPEN, + XML_TOK_CLOSE +}; + + +enum SmXMLPresTableElemTokenMap +{ + XML_TOK_MTR, + XML_TOK_MTD +}; + +enum SmXMLPresElemTokenMap +{ + XML_TOK_ANNOTATION, + XML_TOK_MI, + XML_TOK_MN, + XML_TOK_MO, + XML_TOK_MTEXT, + XML_TOK_MSPACE, + XML_TOK_MS, + XML_TOK_MALIGNGROUP +}; + +enum SmXMLPresScriptEmptyElemTokenMap +{ + XML_TOK_MPRESCRIPTS, + XML_TOK_NONE +}; + +enum SmXMLOperatorAttrTokenMap +{ + XML_TOK_STRETCHY +}; + +enum SmXMLAnnotationAttrTokenMap +{ + XML_TOK_ENCODING +}; + +//////////////////////////////////////////////////////////// + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathtype.cxx b/starmath/source/mathtype.cxx new file mode 100644 index 000000000000..c332bbec489b --- /dev/null +++ b/starmath/source/mathtype.cxx @@ -0,0 +1,3374 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + +#include <mathtype.hxx> +#include <osl/diagnose.h> +#include <sfx2/docfile.hxx> + +#define APPEND(str,ascii) str.AppendAscii(RTL_CONSTASCII_STRINGPARAM(ascii)) + +static sal_Unicode Convert(sal_Unicode nIn) +{ + //Find the best match in accepted unicode for our private area symbols + static sal_Unicode aStarMathPrivateToUnicode[] = + { + 0x2030, 0xF613, 0xF612, 0x002B, 0x003C, 0x003E, 0xE425, 0xE421, 0xE088, 0x2208, + 0x0192, 0x2026, 0x2192, 0x221A, 0x221A, 0x221A, 0xE090, 0x005E, 0x02C7, 0x02D8, + 0x00B4, 0x0060, 0x02DC, 0x00AF, 0x0362, 0xE099, 0xE09A, 0x20DB, 0xE09C, 0xE09D, + 0x0028, 0x0029, 0x2220, 0x22AF, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, + 0x002F, 0x005C, 0x274F, 0xE0AB, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03A0, + 0x03a3, 0x03a5, 0x03a6, 0x03a8, 0x03A9, 0x03B1, 0x03B2, 0x03b3, 0x03b4, 0x03b5, + 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03b5, + 0x03d1, 0x03d6, 0xE0D2, 0x03db, 0x2118, 0x2202, 0x2129, 0xE0D7, 0xE0D8, 0x22A4, + 0xE0DA, 0x2190, 0x2191, 0x2193 + }; + if ((nIn >= 0xE080) && (nIn <= 0xE0DD)) + nIn = aStarMathPrivateToUnicode[nIn-0xE080]; + + //For whatever unicode glyph that equation editor doesn't ship with that + //we have a possible match we can munge it to. + switch (nIn) + { + case 0x2223: + nIn = '|'; + break; + default: + break; + } + + return nIn; +} + +void MathType::Init() +{ + //These are the default MathType sizes + aSizeTable[0]=12; + aSizeTable[1]=8; + aSizeTable[2]=6; + aSizeTable[3]=24; + aSizeTable[4]=10; + aSizeTable[5]=12; + aSizeTable[6]=12; + + /* + These are the default MathType italic/bold settings If mathtype is changed + from its defaults, there is nothing we can do, as this information is not + stored in the document + */ + MathTypeFont aFont; + for(sal_uInt8 i=1;i<=11;i++) + { + aFont.nTface = i+128; + switch (i) + { + default: + aFont.nStyle=0; + break; + case 3: + case 4: + aFont.nStyle=1; + break; + case 7: + aFont.nStyle=2; + break; + } + aUserStyles.insert(aFont); + } +} + + +/*ToDo replace with table rather than switch, returns + sal_True in the case that the char is just a char, and + sal_False if the character is an operator which must not be + placed inside the quote sequence designed to protect + against being parsed as a keyword + + General solution required to force starmath to handle + unicode math chars the way it handles its own math + chars rathar than handle them as text as it will do + for the default case below, i.e. incorrect spacing + between math symbols and ordinary text e.g. 1=2 rather + than 1 = 2 + */ +sal_Bool MathType::LookupChar(sal_Unicode nChar,String &rRet,sal_uInt8 nVersion, + sal_uInt8 nTypeFace) +{ + bool bRet=false; + const char *pC = NULL; + switch(nChar) + { + case 0x0000: + pC = " none "; + break; + case 0x00ac: + pC = " neg "; + break; + case 0x00b1: + pC = " +- "; + break; + case '(': + pC = " \\( "; + break; + case ')': + pC = " \\) "; + break; + case '[': + pC = " \\[ "; + break; + case ']': + pC = " \\] "; + break; + case '.': + pC = " \".\" "; + break; + case 0xae: + if ((nVersion < 3) && (nTypeFace == 0x86)) + pC = " rightarrow "; + else + { + rRet.Append(nChar); + bRet=true; + } + break; + case 0x00fb: + if ((nVersion < 3) && (nTypeFace == 0x81)) + nChar = 0xDF; + rRet.Append(nChar); + bRet=true; + break; + case 'a': + if ((nVersion < 3) && (nTypeFace == 0x84)) + nChar = 0x3b1; + rRet.Append(nChar); + bRet=true; + break; + case 'b': + if ((nVersion < 3) && (nTypeFace == 0x84)) + nChar = 0x3b2; + rRet.Append(nChar); + bRet=true; + break; + case 'l': + if ((nVersion < 3) && (nTypeFace == 0x84)) + nChar = 0x3bb; + rRet.Append(nChar); + bRet=true; + break; + case 'n': + if ((nVersion < 3) && (nTypeFace == 0x84)) + nChar = 0x3bd; + rRet.Append(nChar); + bRet=true; + break; + case 'r': + if ((nVersion < 3) && (nTypeFace == 0x84)) + nChar = 0x3c1; + rRet.Append(nChar); + bRet=true; + break; + case 'D': + if ((nVersion < 3) && (nTypeFace == 0x84)) + nChar = 0x394; + rRet.Append(nChar); + bRet=true; + break; + case 0xa9: + if ((nVersion < 3) && (nTypeFace == 0x82)) + nChar = '\''; + rRet.Append(nChar); + bRet=true; + break; + case 0x00f1: + if ((nVersion < 3) && (nTypeFace == 0x86)) + pC = " \\rangle "; + else + { + rRet.Append(nChar); + bRet=true; + } + break; + case 0x00a3: + if ((nVersion < 3) && (nTypeFace == 0x86)) + pC = " <= "; + else + { + rRet.Append(nChar); + bRet=true; + } + break; + case 0x00de: + if ((nVersion < 3) && (nTypeFace == 0x86)) + pC = " drarrow "; + else + { + rRet.Append(nChar); + bRet=true; + } + break; + case 0x0057: + if ((nVersion < 3) && (nTypeFace == 0x85)) + pC = " %OMEGA "; + else + { + rRet.Append(nChar); + bRet=true; + } + break; + case 0x007b: + pC = " lbrace "; + break; + case 0x007c: + pC = " \\lline "; + break; + case 0x007d: + pC = " rbrace "; + break; + case 0x007e: + pC = " \"~\" "; + break; + case 0x2224: + pC = " ndivides "; + break; + case 0x2225: + pC = " parallel "; + break; + case 0x00d7: + if (nVersion < 3) + pC = " cdot "; + else + pC = " times "; + break; + case 0x00f7: + pC = " div "; + break; + case 0x019b: + pC = " lambdabar "; + break; + case 0x2026: + pC = " dotslow "; + break; + case 0x2022: + pC = " cdot "; + break; + case 0x2102: + pC = " setC "; + break; + case 0x210f: + pC = " hbar "; + break; + case 0x2111: + pC = " Im "; + break; + case 0x2115: + pC = " setN "; + break; + case 0x2118: + pC = " wp "; + break; + case 0x211a: + pC = " setQ "; + break; + case 0x211c: + pC = " Re "; + break; + case 0x211d: + pC = " setR "; + break; + case 0x2124: + pC = " setZ "; + break; + case 0x2135: + pC = " aleph "; + break; + case 0x2190: + pC = " leftarrow "; + break; + case 0x2191: + pC = " uparrow "; + break; + case 0x2192: + pC = " rightarrow "; + break; + case 0x0362: + pC = " widevec "; + break; + case 0x2193: + pC = " downarrow "; + break; + case 0x21d0: + pC = " dlarrow "; + break; + case 0x21d2: + pC = " drarrow "; + break; + case 0x21d4: + pC = " dlrarrow "; + break; + case 0x2200: + pC = " forall "; + break; + case 0x2202: + pC = " partial "; + break; + case 0x2203: + pC = " exists "; + break; + case 0x2205: + pC = " emptyset "; + break; + case 0x2207: + pC = " nabla "; + break; + case 0x2208: + pC = " in "; + break; + case 0x2209: + pC = " notin "; + break; + case 0x220d: + pC = " owns "; + break; + case 0x220f: + pC = " prod "; + break; + case 0x2210: + pC = " coprod "; + break; + case 0x2211: + pC = " sum "; + break; + case 0x2212: + pC = " - "; + break; + case 0x2213: + pC = " -+ "; + break; + case 0x2217: + pC = " * "; + break; + case 0x2218: + pC = " circ "; + break; + case 0x221d: + pC = " prop "; + break; + case 0x221e: + pC = " infinity "; + break; + case 0x2227: + pC = " and "; + break; + case 0x2228: + pC = " or "; + break; + case 0x2229: + pC = " intersection "; + break; + case 0x222a: + pC = " union "; + break; + case 0x222b: + pC = " int "; + break; + case 0x222c: + pC = " iint "; + break; + case 0x222d: + pC = " iiint "; + break; + case 0x222e: + pC = " lint "; + break; + case 0x222f: + pC = " llint "; + break; + case 0x2230: + pC = " lllint "; + break; + case 0x2245: + pC = " simeq "; + break; + case 0x2248: + pC = " approx "; + break; + case 0x2260: + pC = " <> "; + break; + case 0x2261: + pC = " equiv "; + break; + case 0x2264: + pC = " <= "; + break; + case 0x2265: + pC = " >= "; + break; + case 0x2282: + pC = " subset "; + break; + case 0x2283: + pC = " supset "; + break; + case 0x2284: + pC = " nsubset "; + break; + case 0x2285: + pC = " nsupset "; + break; + case 0x2286: + pC = " subseteq "; + break; + case 0x2287: + pC = " supseteq "; + break; + case 0x2288: + pC = " nsubseteq "; + break; + case 0x2289: + pC = " nsupseteq "; + break; + case 0x227a: + case 0x227b: + case 0x22b2: + case 0x22b3: + rRet += ' '; + rRet.Append(nChar); + rRet += ' '; + break; + case 0x22a5: + pC = " ortho "; + break; + case 0x22c5: + pC = " cdot "; + break; + case 0x22ee: + pC = " dotsvert "; + break; + case 0x22ef: + pC = " dotsaxis "; + break; + case 0x22f0: + pC = " dotsup "; + break; + case 0x22f1: + pC = " dotsdown "; + break; + case 0x2329: + pC = " langle "; + break; + case 0x232a: + pC = " rangle "; + break; + case 0x301a: + pC = " ldbracket "; + break; + case 0x301b: + pC = " rdbracket "; + break; + case 0xe083: + rRet.Append('+'); + bRet=true; + break; + case '^': + case 0xe091: + pC = " widehat "; + break; + case 0xe096: + pC = " widetilde "; + break; + case 0xe098: + pC = " widevec "; + break; + case 0xE421: + pC = " geslant "; + break; + case 0xE425: + pC = " leslant "; + break; + case 0xeb01: //no space + case 0xeb08: //normal space + bRet=true; + break; + case 0xef04: //tiny space + case 0xef05: //tiny space + case 0xeb02: //small space + case 0xeb04: //medium space + rRet.Append('`'); + break; + case 0xeb05: //large space + rRet.Append('~'); + break; + case 0x3a9: + pC = " %OMEGA "; + break; + default: + rRet.Append(nChar); + bRet=true; + break; + } + if (pC) + rRet.AppendAscii(pC); + return bRet; +} + +void MathTypeFont::AppendStyleToText(String &rRet) +{ + const char *pC = NULL; + switch (nStyle) + { + default: + case 0: + break; + case 1: + pC = " ital "; + break; + case 2: + pC = " bold "; + break; + case 3: + pC = " bold italic"; + break; + } + if (pC) + rRet.AppendAscii(pC); +} + +void MathType::TypeFaceToString(String &rTxt,sal_uInt8 nFace) +{ + MathTypeFont aFont(nFace); + MathTypeFontSet::iterator aItr = aUserStyles.find(aFont); + if (aItr != aUserStyles.end()) + aFont.nStyle = aItr->nStyle; + aFont.AppendStyleToText(rTxt); +} + +int MathType::Parse(SotStorage *pStor) +{ + SvStorageStreamRef xSrc = pStor->OpenSotStream( + String::CreateFromAscii("Equation Native"), + STREAM_STD_READ | STREAM_NOCREATE); + if ( (!xSrc.Is()) || (SVSTREAM_OK != xSrc->GetError())) + return 0; + pS = &xSrc; + pS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + + EQNOLEFILEHDR aHdr; + aHdr.Read(pS); + *pS >> nVersion; + *pS >> nPlatform; + *pS >> nProduct; + *pS >> nProdVersion; + *pS >> nProdSubVersion; + + if (nVersion > 3) // allow only supported versions of MathType to be parsed + return 0; + +#ifdef STANDALONE + *pOut << "Format Version is " << int(nVersion) << endl; + *pOut << "Generating Platform is " << (nPlatform ? "Windows" + : "Mac") << endl; + *pOut << "Generating Product is " << (nPlatform ? "Equation Editor" + : "Equation Editor") << endl; + *pOut << "Prod Version is " << int(nProdVersion) << "." << + int(nProdSubVersion) << endl << endl; +#endif + + int nRet = HandleRecords(); + //little crude hack to close ocassionally open expressions + //a sophisticated system to determine what expressions are + //opened is required, but this is as much work as rewriting + //starmaths internals. + APPEND(rRet,"{}"); + +#if OSL_DEBUG_LEVEL > 1 +# ifdef CAOLAN + //sanity check + + //sigh, theres no point! MathType (in some bizarre subvarient) pads + //the end of the formula with ENDs (0)'s + sal_uLong nEnd = pS->Tell(); + OSL_ENSURE(nEnd == pS->Seek(STREAM_SEEK_TO_END), + "Possibly unfully parsed formula"); +# endif +#endif + return nRet; +} + +static void lcl_PrependDummyTerm(String &rRet, xub_StrLen &rTextStart) +{ + if ((rRet.GetChar(rTextStart) == '=') && + ((rTextStart == 0) || + (rRet.GetChar(rTextStart-1) == '{')) + ) + { + rRet.InsertAscii(" {}",rTextStart); + rTextStart+=3; + } +} + +static void lcl_AppendDummyTerm(String &rRet) +{ + bool bOk=false; + for(int nI=rRet.Len()-1;nI >= 0; nI--) + { + xub_StrLen nIdx = sal::static_int_cast< xub_StrLen >(nI); + sal_Unicode nChar = rRet.GetChar(nIdx); + if (nChar == ' ') + continue; + if (rRet.GetChar(nIdx) != '{') + bOk=true; + break; + } + if (!bOk) //No term, use dummy + APPEND(rRet," {}"); +} + +void MathType::HandleNudge() +{ + sal_uInt8 nXNudge; + *pS >> nXNudge; + sal_uInt8 nYNudge; + *pS >> nYNudge; + if (nXNudge == 128 && nYNudge == 128) + { + sal_uInt16 nXLongNudge; + sal_uInt16 nYLongNudge; + *pS >> nXLongNudge; + *pS >> nYLongNudge; + } +} +/*Fabously complicated as many tokens have to be reordered and generally + *moved around from mathtypes paradigm to starmaths.*/ +int MathType::HandleRecords(int nLevel,sal_uInt8 nSelector, + sal_uInt8 nVariation, int nMatrixRows,int nMatrixCols) +{ + sal_uInt8 nTag,nRecord; + sal_uInt8 nTabType,nTabStops; + sal_uInt16 nTabOffset; + String sFontName; + int i,nRet=1,newline=0; + bool bSilent=false; + int nPart=0; + String sPush,sMainTerm; + int nSetSize=0,nSetAlign=0; + int nCurRow=0,nCurCol=0; + bool bOpenString=false; + xub_StrLen nTextStart = 0; + xub_StrLen nSubSupStartPos = 0; + xub_StrLen nLastTemplateBracket=STRING_NOTFOUND; + + do + { + *pS >> nTag; + nRecord = nTag&0x0F; + + /*MathType strings can of course include words which + *are StarMath keywords, the simplest solution is + to escape strings of greater than len 1 with double + quotes to avoid scanning the TokenTable for matches + + Unfortunately it may turn out that the string gets + split during the handling of a character emblishment + so this special case must be handled in the + character handler case 2: + */ + if ((nRecord == CHAR) && (!bIsSilent) && (!bOpenString)) + { + bOpenString=true; + nTextStart = rRet.Len(); + } + else if ((nRecord != CHAR) && (bOpenString)) + { + bOpenString=false; + if ((rRet.Len() - nTextStart) > 1) + { + String aStr; + TypeFaceToString(aStr,nTypeFace); + aStr += '\"'; + rRet.Insert(aStr,nTextStart); + rRet += '\"'; + } + else + { + if (nRecord == END) + { + sal_Unicode cChar = 0; + xub_StrLen nI = rRet.Len()-1; + while (nI && ((cChar = rRet.GetChar(nI)) == ' ')) + --nI; + if ((cChar == '=') || (cChar == '+') || (cChar == '-')) + APPEND(rRet,"{}"); + } + } + } + + switch(nRecord) + { + case LINE: + { + if (xfLMOVE(nTag)) + HandleNudge(); + + if (newline>0) + APPEND(rRet,"\nnewline\n"); + if (!(xfNULL(nTag))) + { + switch (nSelector) + { + case 0x0: + if (nVariation==0) + APPEND(rRet," langle "); + else if (nVariation==1) + APPEND(rRet," \\langle "); + break; + case 0x1: + if (nVariation==0) + APPEND(rRet," left ("); + else if (nVariation==1) + APPEND(rRet,"\\("); + break; + case 0x2: + if ((nVariation==0) || (nVariation==1)) + APPEND(rRet," left lbrace "); + else + APPEND(rRet," left none "); + break; + case 0x3: + if (nVariation==0) + APPEND(rRet," left ["); + else if (nVariation==1) + APPEND(rRet,"\\["); + break; + case 0x8: + case 0xb: + APPEND(rRet," \\["); + break; + case 0x4: + if (nVariation==0) + APPEND(rRet," lline "); + else if (nVariation==1) + APPEND(rRet," \\lline "); + break; + case 0x5: + if (nVariation==0) + APPEND(rRet," ldline "); + else if (nVariation==1) + APPEND(rRet," \\ldline "); + break; + case 0x6: + if (nVariation == 0 || nVariation == 1) + APPEND(rRet," left lfloor "); + else if (nVariation==1) + APPEND(rRet," left none "); + break; + case 0x7: + if (nVariation==0) + APPEND(rRet," lceil "); + else if (nVariation==1) + APPEND(rRet," \\lceil "); + break; + case 0x9: + case 0xa: + APPEND(rRet," \\]"); + break; + case 0xc: + APPEND(rRet," \\("); + break; + case 0xd: + if (nPart == 0) + { + if (nVariation == 0) + APPEND(rRet," sqrt"); + else + { + APPEND(rRet," nroot"); + sPush = rRet; + rRet.Erase(); + } + } + APPEND(rRet," {"); + break; + case 0xe: + if (nPart == 0) + APPEND(rRet," { "); + + + if (nPart == 1) + APPEND(rRet," over "); + APPEND(rRet," {"); + break; + case 0xf: + nSubSupStartPos = rRet.Len(); + if ((nVariation == 0) || + ((nVariation == 2) && (nPart==1))) + { + lcl_AppendDummyTerm(rRet); + APPEND(rRet," rSup"); + } + else if ((nVariation == 1) || + ((nVariation == 2) && (nPart==0))) + { + lcl_AppendDummyTerm(rRet); + APPEND(rRet," rSub"); + } + APPEND(rRet," {"); + break; + case 0x10: + if (nVariation == 0) + APPEND(rRet," {underline "); + else if (nVariation == 1) + APPEND(rRet," {underline underline "); + APPEND(rRet," {"); + break; + case 0x11: + if (nVariation == 0) + APPEND(rRet," {overline "); + else if (nVariation == 1) + APPEND(rRet," {overline overline "); + APPEND(rRet," {"); + break; + case 0x12: + if (nPart == 0) + { + if (nVariation == 0) + APPEND(rRet," widevec ");//left arrow above + else if (nVariation == 1) + APPEND(rRet," widevec ");//left arrow below + APPEND(rRet," {"); + } + break; + case 0x13: + if (nPart == 0) + { + if (nVariation == 0) + APPEND(rRet," widevec ");//right arrow above + else if (nVariation == 1) + APPEND(rRet," widevec ");//right arrow below + APPEND(rRet," {"); + } + break; + case 0x14: + if (nPart == 0) + { + if (nVariation == 0) + APPEND(rRet," widevec ");//double arrow above + else if (nVariation == 1) + APPEND(rRet," widevec ");//double arrow below + APPEND(rRet," {"); + } + break; + case 0x15: + if (nPart == 0) + { + if ((nVariation == 3) || (nVariation == 4)) + APPEND(rRet," lInt"); + else + APPEND(rRet," Int"); + if ( (nVariation != 0) && (nVariation != 3)) + { + sPush = rRet; + rRet.Erase(); + } + } + if (((nVariation == 1) || + (nVariation == 4)) && (nPart==1)) + APPEND(rRet," rSub"); + else if ((nVariation == 2) && (nPart==2)) + APPEND(rRet," rSup"); + else if ((nVariation == 2) && (nPart==1)) + APPEND(rRet," rSub"); + APPEND(rRet," {"); + break; + case 0x16: + if (nPart == 0) + { + if ((nVariation == 2) || (nVariation == 3)) + APPEND(rRet," llInt"); + else + APPEND(rRet," iInt"); + if ( (nVariation != 0) && (nVariation != 2)) + { + sPush = rRet; + rRet.Erase(); + } + } + if (((nVariation == 1) || + (nVariation == 3)) && (nPart==1)) + APPEND(rRet," rSub"); + APPEND(rRet," {"); + break; + case 0x17: + if (nPart == 0) + { + if ((nVariation == 2) || (nVariation == 3)) + APPEND(rRet," lllInt"); + else + APPEND(rRet," iiInt"); + if ( (nVariation != 0) && (nVariation != 2)) + { + sPush = rRet; + rRet.Erase(); + } + } + if (((nVariation == 1) || + (nVariation == 3)) && (nPart==1)) + APPEND(rRet," rSub"); + APPEND(rRet," {"); + break; + case 0x18: + if (nPart == 0) + { + if (nVariation == 2) + APPEND(rRet," lInt"); + else + APPEND(rRet," Int"); + sPush = rRet; + rRet.Erase(); + } + if (((nVariation == 1) || + (nVariation == 2)) && (nPart==1)) + APPEND(rRet," cSub"); + else if ((nVariation == 0) && (nPart==2)) + APPEND(rRet," cSup"); + else if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," cSub"); + APPEND(rRet," {"); + break; + case 0x19: + if (nPart == 0) + { + if (nVariation == 0) + APPEND(rRet," llInt"); + else + APPEND(rRet," iInt"); + sPush = rRet; + rRet.Erase(); + } + if (nPart==1) + APPEND(rRet," cSub"); + APPEND(rRet," {"); + break; + case 0x1a: + if (nPart == 0) + { + if (nVariation == 0) + APPEND(rRet," lllInt"); + else + APPEND(rRet," iiInt"); + sPush = rRet; + rRet.Erase(); + } + if (nPart==1) + APPEND(rRet," cSub"); + APPEND(rRet," {"); + break; + case 0x1b: + case 0x1c: + APPEND(rRet," {"); + break; + case 0x1d: + if (nPart == 0) + { + APPEND(rRet," Sum"); + if (nVariation != 2) + { + sPush = rRet; + rRet.Erase(); + } + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," cSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," cSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," cSub"); + APPEND(rRet," {"); + break; + case 0x1e: + if (nPart == 0) + { + APPEND(rRet," Sum"); + sPush = rRet; + rRet.Erase(); + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," rSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," rSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," rSub"); + APPEND(rRet," {"); + break; + case 0x1f: + if (nPart == 0) + { + APPEND(rRet," Prod"); + if (nVariation != 2) + { + sPush = rRet; + rRet.Erase(); + } + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," cSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," cSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," cSub"); + APPEND(rRet," {"); + break; + case 0x20: + if (nPart == 0) + { + APPEND(rRet," Prod"); + sPush = rRet; + rRet.Erase(); + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," rSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," rSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," rSub"); + APPEND(rRet," {"); + break; + case 0x21: + if (nPart == 0) + { + APPEND(rRet," coProd"); + if (nVariation != 2) + { + sPush = rRet; + rRet.Erase(); + } + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," cSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," cSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," cSub"); + APPEND(rRet," {"); + break; + case 0x22: + if (nPart == 0) + { + APPEND(rRet," coProd"); + sPush = rRet; + rRet.Erase(); + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," rSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," rSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," rSub"); + APPEND(rRet," {"); + break; + case 0x23: + if (nPart == 0) + { + APPEND(rRet," union"); //union + if (nVariation != 2) + { + sPush = rRet; + rRet.Erase(); + } + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," cSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," cSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," cSub"); + APPEND(rRet," {"); + break; + case 0x24: + if (nPart == 0) + { + APPEND(rRet," union"); //union + sPush = rRet; + rRet.Erase(); + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," rSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," rSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," rSub"); + APPEND(rRet," {"); + break; + case 0x25: + if (nPart == 0) + { + APPEND(rRet," intersect"); //intersect + if (nVariation != 2) + { + sPush = rRet; + rRet.Erase(); + } + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," cSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," cSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," cSub"); + APPEND(rRet," {"); + break; + case 0x26: + if (nPart == 0) + { + APPEND(rRet," intersect"); //intersect + sPush = rRet; + rRet.Erase(); + } + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," rSub"); + else if ((nVariation == 1) && (nPart==2)) + APPEND(rRet," rSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," rSub"); + APPEND(rRet," {"); + break; + case 0x27: + if ((nVariation == 0) && (nPart==1)) + APPEND(rRet," cSup"); + else if ((nVariation == 1) && (nPart==1)) + APPEND(rRet," cSub"); + else if ((nVariation == 2) && (nPart==1)) + APPEND(rRet," cSub"); + else if ((nVariation == 2) && (nPart==2)) + APPEND(rRet," cSup"); + APPEND(rRet," {"); + break; + case 0x28: + if (nVariation == 0) + { + if (nPart == 0) + { + sPush = rRet; + rRet.Erase(); + } + } + APPEND(rRet," {"); + if (nVariation == 0) + { + if (nPart == 1) + APPEND(rRet,"alignr "); + } + if (nPart == 0) + APPEND(rRet,"\\lline "); + if (nVariation == 1) + APPEND(rRet,"overline "); + break; + case 0x29: + APPEND(rRet," {"); + break; + case 0x2a: + if (nPart == 0) + { + sPush = rRet; + rRet.Erase(); + } + if ((nVariation == 0) && (nPart==0)) + APPEND(rRet," rSup"); + else if ((nVariation == 2) && (nPart==1)) + APPEND(rRet," rSup"); + else if ((nVariation == 1) && (nPart==0)) + APPEND(rRet," rSub"); + else if ((nVariation == 2) && (nPart==0)) + APPEND(rRet," rSub"); + APPEND(rRet," {"); + break; + case 0x2b: + if (nPart == 0) + { + sPush = rRet; + rRet.Erase(); + } + if ((nVariation == 0) && (nPart==0)) + APPEND(rRet," cSup"); + else if ((nVariation == 2) && (nPart==1)) + APPEND(rRet," cSup"); + else if ((nVariation == 1) && (nPart==0)) + APPEND(rRet," cSub"); + else if ((nVariation == 2) && (nPart==0)) + APPEND(rRet," cSub"); + APPEND(rRet," {"); + break; + case 0x2c: + if (nPart == 0) + APPEND(rRet,"\"\""); + if ((nVariation == 0) + || ((nVariation == 2) && (nPart==1))) + APPEND(rRet," lSup"); + else if ((nVariation == 1) + || ((nVariation == 2) && (nPart==0))) + APPEND(rRet," lSub"); + APPEND(rRet," {"); + break; + case 0x2d: + if (nVariation==0) + { + if (nPart == 0) + APPEND(rRet," langle "); + } + else if (nVariation==1) + { + APPEND(rRet," \\langle "); + newline--; + } + else if (nVariation==2) + { + APPEND(rRet," \\lline "); + newline--; + } + break; + case 0x2e: + if (nVariation == 0) + APPEND(rRet," widevec ");//left below + else if (nVariation == 1) + APPEND(rRet," widevec ");//right below + else if (nVariation == 2) + APPEND(rRet," widevec ");//double headed below + APPEND(rRet," {"); + break; + case 0x2f: + if (nVariation == 0) + APPEND(rRet," widevec ");//left above + else if (nVariation == 1) + APPEND(rRet," widevec ");//right above + else if (nVariation == 2) + APPEND(rRet," widevec ");//double headed above + APPEND(rRet," {"); + break; + default: + break; + } + sal_Int16 nOldCurSize=nCurSize; + xub_StrLen nSizeStartPos = rRet.Len(); + HandleSize(nLSize,nDSize,nSetSize); + nRet = HandleRecords(nLevel+1); + while (nSetSize) + { + bool bOk=false; + xub_StrLen nI = rRet.SearchBackward('{'); + if (nI != STRING_NOTFOUND) + { + for(nI=nI+1;nI<rRet.Len();nI++) + if (rRet.GetChar(nI) != ' ') + { + bOk=true; + break; + } + } + else + bOk=true; + + if (bOk) + APPEND(rRet,"} "); + else + rRet.Erase(nSizeStartPos); + nSetSize--; + nCurSize=nOldCurSize; + } + + + HandleMatrixSeperator(nMatrixRows,nMatrixCols, + nCurCol,nCurRow); + + switch (nSelector) + { + case 0x0: + if (nVariation==0) + APPEND(rRet," rangle "); + else if (nVariation==2) + APPEND(rRet," \\rangle "); + break; + case 0x1: + if (nVariation==0) + APPEND(rRet," right )"); + else if (nVariation==2) + APPEND(rRet,"\\)"); + break; + case 0x2: + if ((nVariation==0) || (nVariation==2)) + APPEND(rRet," right rbrace "); + else + APPEND(rRet," right none "); + break; + case 0x3: + if (nVariation==0) + APPEND(rRet," right ]"); + else if (nVariation==2) + APPEND(rRet,"\\]"); + break; + case 0x4: + if (nVariation==0) + APPEND(rRet," rline "); + else if (nVariation==2) + APPEND(rRet," \\rline "); + break; + case 0x5: + if (nVariation==0) + APPEND(rRet," rdline "); + else if (nVariation==2) + APPEND(rRet," \\rdline "); + break; + case 0x6: + if (nVariation == 0 || nVariation == 2) + APPEND(rRet," right rfloor "); + else if (nVariation==2) + APPEND(rRet," right none "); + break; + case 0x7: + if (nVariation==0) + APPEND(rRet," rceil "); + else if (nVariation==2) + APPEND(rRet," \\rceil "); + break; + case 0x8: + case 0xa: + APPEND(rRet,"\\["); + break; + case 0x9: + case 0xc: + APPEND(rRet,"\\]"); + break; + case 0xd: + APPEND(rRet,"} "); + if (nVariation == 1) + { + if (nPart == 0) + { + newline--; + sMainTerm = rRet; + rRet.Erase(); + } + else + { + sPush += rRet; + rRet = sPush; + rRet += sMainTerm; + } + } + else + { + if (nPart == 0) + newline--; + } + nPart++; + break; + case 0xb: + APPEND(rRet,"\\)"); + break; + case 0xe: + APPEND(rRet,"} "); + if (nPart == 0) + newline--; + else + APPEND(rRet,"} "); + nPart++; + break; + case 0xf: + { + if ((nPart == 0) && + ((nVariation == 2) || (nVariation == 1))) + newline--; + + bool bOk=false; + xub_StrLen nI = rRet.SearchBackward('{'); + if (nI != STRING_NOTFOUND) + { + for(nI=nI+1;nI<rRet.Len();nI++) + if (rRet.GetChar(nI) != ' ') + { + bOk=true; + break; + } + } + else + bOk=true; + + if (bOk) + APPEND(rRet,"} "); + else + rRet.Erase(nSubSupStartPos); + nPart++; + } + break; + case 0x2c: + if ((nPart == 0) && + ((nVariation == 2) || (nVariation == 1))) + newline--; + APPEND(rRet,"} "); + nPart++; + break; + case 0x2e: + case 0x2f: + APPEND(rRet,"} "); + break; + case 0x10: + case 0x11: + APPEND(rRet,"}} "); + break; + case 0x12: + case 0x13: + case 0x14: + if (nPart == 0) + { + newline--; + APPEND(rRet,"} "); + } + nPart++; + break; + case 0x1b: + APPEND(rRet,"} "); + if (nPart == 0) + { + newline--; + APPEND(rRet,"overbrace"); + } + nPart++; + break; + case 0x1c: + APPEND(rRet,"} "); + if (nPart == 0) + { + newline--; + APPEND(rRet,"underbrace"); + } + nPart++; + break; + case 0x27: + if (nPart==0) + newline--; + else if ((nPart==1) && + ((nVariation == 2) || (nVariation == 1))) + newline--; + APPEND(rRet,"} "); + nPart++; + break; + case 0x28: + APPEND(rRet,"} "); + if (nVariation == 0) + { + if (nPart == 0) + { + sMainTerm = rRet; + rRet.Erase(); + } + else + { + sPush += rRet; + rRet = sPush; + APPEND(rRet," over "); + rRet += sMainTerm; + } + } + if (nPart == 0) + newline--; + nPart++; + break; + case 0x29: + APPEND(rRet,"} "); + if (nPart == 0) + { + newline--; + switch (nVariation) + { + case 1: + APPEND(rRet,"slash"); + break; + default: + APPEND(rRet,"wideslash"); + break; + } + } + nPart++; + break; + case 0x1d: + case 0x1e: + case 0x1f: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + APPEND(rRet,"} "); + if (nPart == 0) + { + if (nVariation != 2) + { + sMainTerm = rRet; + rRet.Erase(); + } + newline--; + } + else if ((nPart == 1) && (nVariation == 0)) + { + sPush += rRet; + rRet = sPush; + rRet += sMainTerm; + newline--; + } + else if ((nPart == 1) && (nVariation == 1)) + newline--; + else if ((nPart == 2) && (nVariation == 1)) + { + sPush += rRet; + rRet = sPush; + rRet += sMainTerm; + newline--; + } + nPart++; + break; + case 0x15: + APPEND(rRet,"} "); + if (nPart == 0) + { + if ((nVariation != 0) && (nVariation != 3)) + { + sMainTerm = rRet; + rRet.Erase(); + } + newline--; + } + else if ((nPart == 1) && + ((nVariation == 1) || (nVariation==4))) + { + sPush += rRet; + rRet = sPush; + rRet += sMainTerm; + newline--; + } + else if ((nPart == 1) && (nVariation == 2)) + newline--; + else if ((nPart == 2) && (nVariation == 2)) + { + sPush += rRet; + rRet = sPush; + rRet += sMainTerm; + newline--; + } + nPart++; + break; + case 0x16: + case 0x17: + APPEND(rRet,"} "); + if (nPart == 0) + { + if ((nVariation != 0) && (nVariation != 2)) + { + sMainTerm = rRet; + rRet.Erase(); + } + newline--; + } + else if ((nPart == 1) && + ((nVariation == 1) || (nVariation==3))) + { + sPush += rRet; + rRet = sPush; + rRet += sMainTerm; + newline--; + } + nPart++; + break; + case 0x18: + APPEND(rRet,"} "); + if (nPart == 0) + { + sMainTerm = rRet; + rRet.Erase(); + newline--; + } + else if ((nPart == 1) && + ((nVariation == 1) || (nVariation==2))) + { + sPush += rRet; + rRet = sPush; + rRet += sMainTerm; + newline--; + } + else if ((nPart == 1) && (nVariation == 0)) + newline--; + else if ((nPart == 2) && (nVariation == 0)) + { + sPush += rRet; + rRet = sPush; + rRet += sMainTerm; + newline--; + } + nPart++; + break; + case 0x19: + case 0x1a: + APPEND(rRet,"} "); + if (nPart == 0) + { + sMainTerm = rRet; + rRet.Erase(); + newline--; + } + else if (nPart == 1) + { + sPush += rRet; + rRet = sPush; + rRet += sMainTerm; + newline--; + } + nPart++; + break; + case 0x2a: + case 0x2b: + APPEND(rRet,"} "); + + if ((nPart == 0) && + ((nVariation == 0) || (nVariation == 1))) + { + sMainTerm = rRet; + rRet.Erase(); + newline--; + } + else if ((nPart == 0) && (nVariation == 2)) + newline--; + else if ((nPart == 1) && (nVariation == 2)) + { + sMainTerm = rRet; + rRet.Erase(); + newline--; + } + else if ((nPart == 2) || ((((nPart == 1) && + (nVariation == 0)) || (nVariation == 1)))) + { + sPush+=rRet; + rRet = sPush; + rRet += sMainTerm; + } + nPart++; + break; + case 0x2d: + if (nVariation==0) + { + if (nPart == 0) + { + newline--; //there is another term to arrive + APPEND(rRet," mline "); + } + else + APPEND(rRet," rangle "); + } + else if (nVariation==1) + APPEND(rRet," \\lline "); + else if (nVariation==2) + APPEND(rRet," \\rangle "); + nPart++; + break; + default: + break; + } + bSilent = true; //Skip the optional brackets and/or + //symbols that follow some of these + //records. Foo Data. + + /*In matrices and piles we cannot seperate equation + *lines with the newline keyword*/ + if (nMatrixCols==0) + newline++; + } + } + break; + case CHAR: + if (xfLMOVE(nTag)) + HandleNudge(); + nRet = HandleChar(nTextStart,nSetSize,nLevel,nTag,nSelector, + nVariation,bSilent); + break; + case TMPL: + if (xfLMOVE(nTag)) + HandleNudge(); + nRet = HandleTemplate(nLevel,nSelector,nVariation, + nLastTemplateBracket); + break; + case PILE: + if (xfLMOVE(nTag)) + HandleNudge(); + nRet = HandlePile(nSetAlign,nLevel,nSelector,nVariation); + HandleMatrixSeperator(nMatrixRows,nMatrixCols,nCurCol,nCurRow); + break; + case MATRIX: + if (xfLMOVE(nTag)) + HandleNudge(); + nRet = HandleMatrix(nLevel,nSelector,nVariation); + HandleMatrixSeperator(nMatrixRows,nMatrixCols,nCurCol,nCurRow); + break; + case EMBEL: + if (xfLMOVE(nTag)) + HandleNudge(); + HandleEmblishments(); + break; + case RULER: + *pS >> nTabStops; + for (i=0;i<nTabStops;i++) + { + *pS >> nTabType; + *pS >> nTabOffset; + } + OSL_FAIL("Not seen in the wild Equation Ruler Field"); + break; + case FONT: + { + MathTypeFont aFont; + *pS >> aFont.nTface; + /* + The typeface number is the negative (which makes it + positive) of the typeface value (unbiased) that appears in + CHAR records that might follow a given FONT record + */ + aFont.nTface = 128-aFont.nTface; + *pS >> aFont.nStyle; + aUserStyles.insert(aFont); + std::vector<sal_Char> aSeq; + while(1) + { + sal_Char nChar8(0); + *pS >> nChar8; + if (nChar8 == 0) + break; + aSeq.push_back(nChar8); + } + sFontName = rtl::OUString(&aSeq[0], aSeq.size(), + RTL_TEXTENCODING_MS_1252); + } + break; + case SIZE: + HandleSetSize(); + break; + case 10: + case 11: + case 12: + case 13: + case 14: + nLSize=nRecord-10; + break; + case END: + default: + break; + } + } + while (nRecord != END && !pS->IsEof()); + while (nSetSize) + { + rRet += '}'; + nSetSize--; + } + return nRet; +} + +/*Simply determine if we are at the end of a record or the end of a line, + *with fiddley logic to see if we are in a matrix or a pile or neither + + Note we cannot tell until after the event that this is the last entry + of a pile, so we must strip the last seperator of a pile after this + is detected in the PILE handler + */ +void MathType::HandleMatrixSeperator(int nMatrixRows,int nMatrixCols, + int &rCurCol,int &rCurRow) +{ + if (nMatrixRows!=0) + { + if (rCurCol == nMatrixCols-1) + { + if (rCurRow != nMatrixRows-1) + APPEND(rRet," {} ##\n"); + if (nMatrixRows!=-1) + { + rCurCol=0; + rCurRow++; + } + } + else + { + APPEND(rRet," {} # "); + if (nMatrixRows!=-1) + rCurCol++; + else + rRet += '\n'; + } + } +} + +/* set the alignment of the following term, but starmath currently + * cannot handle vertical alignment */ +void MathType::HandleAlign(sal_uInt8 nHorAlign, sal_uInt8 /*nVAlign*/, int &rSetAlign) +{ + switch(nHorAlign) + { + case 1: + default: + APPEND(rRet,"alignl {"); + break; + case 2: + APPEND(rRet,"alignc {"); + break; + case 3: + APPEND(rRet,"alignr {"); + break; + } + rSetAlign++; +} + +/* set size of text, complexity due to overuse of signedness as a flag + * indicator by mathtype file format*/ +sal_Bool MathType::HandleSize(sal_Int16 nLstSize,sal_Int16 nDefSize, int &rSetSize) +{ + bool bRet=false; + if (nLstSize < 0) + { + if ((-nLstSize/32 != nDefaultSize) && (-nLstSize/32 != nCurSize)) + { + if (rSetSize) + { + rSetSize--; + rRet += '}'; + bRet=true; + } + if (-nLstSize/32 != nLastSize) + { + nLastSize = nCurSize; + APPEND(rRet," size "); + rRet += String::CreateFromInt32(-nLstSize/32); + rRet += '{'; + bRet=true; + rSetSize++; + } + nCurSize = -nLstSize/32; + } + } + else + { + /*sizetable should theoreticaly be filled with the default sizes + *of the various font groupings matching starmaths equivalents + in aTypeFaces, and a test would be done to see if the new font + size would be the same as what starmath would have chosen for + itself anyway in which case the size setting could be ignored*/ + nLstSize = aSizeTable[nLstSize]; + nLstSize = nLstSize + nDefSize; + if (nLstSize != nCurSize) + { + if (rSetSize) + { + rSetSize--; + rRet += '}'; + bRet=true; + } + if (nLstSize != nLastSize) + { + nLastSize = nCurSize; + APPEND(rRet," size "); + rRet += String::CreateFromInt32(nLstSize); + rRet += '{'; + bRet=true; + rSetSize++; + } + nCurSize = nLstSize; + } + } + return bRet; +} + +int MathType::ConvertFromStarMath( SfxMedium& rMedium ) +{ + if (!pTree) + return 0; + + SvStream *pStream = rMedium.GetOutStream(); + if ( pStream ) + { + SvStorageRef pStor = new SotStorage( pStream, false ); + + SvGlobalName aGName(0x0002ce02L, 0x0000, 0x0000,0xc0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x46 ); + pStor->SetClass( aGName, 0, C2S("Microsoft Equation 3.0")); + + static sal_uInt8 const aCompObj[] = { + 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71, + 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B, + 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74, + 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39, + 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + SvStorageStreamRef xStor( pStor->OpenSotStream( C2S("\1CompObj"))); + xStor->Write(aCompObj,sizeof(aCompObj)); + + static sal_uInt8 const aOle[] = { + 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + SvStorageStreamRef xStor2( pStor->OpenSotStream( C2S("\1Ole"))); + xStor2->Write(aOle,sizeof(aOle)); + xStor.Clear(); + xStor2.Clear(); + + SvStorageStreamRef xSrc = pStor->OpenSotStream(C2S("Equation Native")); + if ( (!xSrc.Is()) || (SVSTREAM_OK != xSrc->GetError())) + return 0; + + pS = &xSrc; + pS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + + pS->SeekRel(EQNOLEFILEHDR_SIZE); //Skip 28byte Header and fill it in later + *pS << sal_uInt8(0x03); + *pS << sal_uInt8(0x01); + *pS << sal_uInt8(0x01); + *pS << sal_uInt8(0x03); + *pS << sal_uInt8(0x00); + sal_uInt32 nSize = pS->Tell(); + nPendingAttributes=0; + + HandleNodes(pTree); + *pS << sal_uInt8(END); + + nSize = pS->Tell()-nSize; + pS->Seek(0); + EQNOLEFILEHDR aHdr(nSize+4+1); + aHdr.Write(pS); + + pStor->Commit(); + } + + return 1; +} + + +sal_uInt8 MathType::HandleNodes(SmNode *pNode,int nLevel) +{ + bool bRet=false; + switch(pNode->GetType()) + { + case NATTRIBUT: + HandleAttributes(pNode,nLevel); + break; + case NTEXT: + HandleText(pNode,nLevel); + break; + case NVERTICAL_BRACE: + HandleVerticalBrace(pNode,nLevel); + break; + case NBRACE: + HandleBrace(pNode,nLevel); + break; + case NOPER: + HandleOperator(pNode,nLevel); + break; + case NBINVER: + HandleFractions(pNode,nLevel); + break; + case NROOT: + HandleRoot(pNode,nLevel); + break; + case NSPECIAL: + { + SmTextNode *pText=(SmTextNode *)pNode; + //if the token str and the result text are the same then this + //is to be seen as text, else assume its a mathchar + if (pText->GetText() == pText->GetToken().aText) + HandleText(pText,nLevel); + else + HandleMath(pText,nLevel); + } + break; + case NMATH: + HandleMath(pNode,nLevel); + break; + case NSUBSUP: + HandleSubSupScript(pNode,nLevel); + break; + case NEXPRESSION: + { + sal_uInt16 nSize = pNode->GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pNode->GetSubNode(i)) + HandleNodes(pTemp,nLevel+1); + } + break; + case NTABLE: + //Root Node, PILE equivalent, i.e. vertical stack + HandleTable(pNode,nLevel); + break; + case NMATRIX: + HandleSmMatrix((SmMatrixNode *)pNode,nLevel); + break; + case NLINE: + { + *pS << sal_uInt8(0x0a); + *pS << sal_uInt8(LINE); + sal_uInt16 nSize = pNode->GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pNode->GetSubNode(i)) + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); + } + break; + case NALIGN: + HandleMAlign(pNode,nLevel); + break; + case NBLANK: + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x98); + if (pNode->GetToken().eType == TSBLANK) + *pS << sal_uInt16(0xEB04); + else + *pS << sal_uInt16(0xEB05); + break; + default: + { + sal_uInt16 nSize = pNode->GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pNode->GetSubNode(i)) + HandleNodes(pTemp,nLevel+1); + } + break; + } + return bRet; +} + + +int MathType::StartTemplate(sal_uInt16 nSelector,sal_uInt16 nVariation) +{ + int nOldPending=nPendingAttributes; + *pS << sal_uInt8(TMPL); //Template + *pS << sal_uInt8(nSelector); //selector + *pS << sal_uInt8(nVariation); //variation + *pS << sal_uInt8(0x00); //options + *pS << sal_uInt8(LINE); + //theres just no way we can now handle any character + //attributes (from mathtypes perspective) centered + //over an expression but above template attribute + //such as widevec and similiar constructs + //we have to drop them + nPendingAttributes=0; + return nOldPending; +} + +void MathType::EndTemplate(int nOldPendingAttributes) +{ + *pS << sal_uInt8(END); //end line + *pS << sal_uInt8(END); //end template + nPendingAttributes=nOldPendingAttributes; +} + + +void MathType::HandleSmMatrix(SmMatrixNode *pMatrix,int nLevel) +{ + *pS << sal_uInt8(MATRIX); + *pS << sal_uInt8(0x00); //vAlign ? + *pS << sal_uInt8(0x00); //h_just + *pS << sal_uInt8(0x00); //v_just + *pS << sal_uInt8(pMatrix->GetNumRows()); //v_just + *pS << sal_uInt8(pMatrix->GetNumCols()); //v_just + int nBytes=(pMatrix->GetNumRows()+1)*2/8; + if (((pMatrix->GetNumRows()+1)*2)%8) + nBytes++; + for (sal_uInt16 j = 0; j < nBytes; j++) + *pS << sal_uInt8(0x00); //row_parts + nBytes=(pMatrix->GetNumCols()+1)*2/8; + if (((pMatrix->GetNumCols()+1)*2)%8) + nBytes++; + for (sal_uInt16 k = 0; k < nBytes; k++) + *pS << sal_uInt8(0x00); //col_parts + sal_uInt16 nSize = pMatrix->GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pMatrix->GetSubNode(i)) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //end line + } + *pS << sal_uInt8(END); +} + + +//Root Node, PILE equivalent, i.e. vertical stack +void MathType::HandleTable(SmNode *pNode,int nLevel) +{ + sal_uInt16 nSize = pNode->GetNumSubNodes(); + //The root of the starmath is a table, if + //we convert this them each iteration of + //conversion from starmath to mathtype will + //add an extra unnecessary level to the + //mathtype output stack which would grow + //without bound in a multi step conversion + + if (nLevel == 0) + *pS << sal_uInt8(0x0A); //initial size + + if ( nLevel || (nSize >1)) + { + *pS << sal_uInt8(PILE); + *pS << sal_uInt8(nHAlign); //vAlign ? + *pS << sal_uInt8(0x01); //hAlign + } + + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pNode->GetSubNode(i)) + { + *pS << sal_uInt8(LINE); + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); + } + if (nLevel || (nSize>1)) + *pS << sal_uInt8(END); +} + + +void MathType::HandleRoot(SmNode *pNode,int nLevel) +{ + SmNode *pTemp; + *pS << sal_uInt8(TMPL); //Template + *pS << sal_uInt8(0x0D); //selector + if (pNode->GetSubNode(0)) + *pS << sal_uInt8(0x01); //variation + else + *pS << sal_uInt8(0x00); //variation + *pS << sal_uInt8(0x00); //options + + if (NULL != (pTemp = pNode->GetSubNode(2))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); + } + + if (NULL != (pTemp = pNode->GetSubNode(0))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); + } + else + *pS << sal_uInt8(LINE|0x10); //dummy line + + + + *pS << sal_uInt8(END); +} + +sal_uInt8 MathType::HandleCScript(SmNode *pNode,SmNode *pContent,int nLevel, + sal_uLong *pPos,sal_Bool bTest) +{ + sal_uInt8 nVariation2=0xff; + + if (bTest && pNode->GetSubNode(CSUP+1)) + { + nVariation2=0; + if (pNode->GetSubNode(CSUB+1)) + nVariation2=2; + } + else if (pNode->GetSubNode(CSUB+1)) + nVariation2=1; + + if (nVariation2!=0xff) + { + if (pPos) + *pPos = pS->Tell(); + *pS << sal_uInt8(TMPL); //Template + *pS << sal_uInt8(0x2B); //selector + *pS << nVariation2; + *pS << sal_uInt8(0x00); //options + + if (pContent) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pContent,nLevel+1); + *pS << sal_uInt8(END); //line + } + else + *pS << sal_uInt8(LINE|0x10); + + *pS << sal_uInt8(0x0B); + + SmNode *pTemp; + if (NULL != (pTemp = pNode->GetSubNode(CSUB+1))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //line + } + else + *pS << sal_uInt8(LINE|0x10); + if (bTest && NULL != (pTemp = pNode->GetSubNode(CSUP+1))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //line + } + else + *pS << sal_uInt8(LINE|0x10); + } + return nVariation2; +} + + + +/* + Sub and Sup scripts and another problem area, StarMath + can have all possible options used at the same time, whereas + Mathtype cannot. The ordering of the nodes for each system + is quite different as well leading to some complexity + */ +void MathType::HandleSubSupScript(SmNode *pNode,int nLevel) +{ + SmNode *pTemp; + + sal_uInt8 nVariation=0xff; + if (pNode->GetSubNode(LSUP+1)) + { + nVariation=0; + if (pNode->GetSubNode(LSUB+1)) + nVariation=2; + } + else if (NULL != (pTemp = pNode->GetSubNode(LSUB+1))) + nVariation=1; + + if (nVariation!=0xff) + { + *pS << sal_uInt8(TMPL); //Template + *pS << sal_uInt8(0x2c); //selector + *pS << nVariation; + *pS << sal_uInt8(0x00); //options + *pS << sal_uInt8(0x0B); + + if (NULL != (pTemp = pNode->GetSubNode(LSUB+1))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //line + } + else + *pS << sal_uInt8(LINE|0x10); + if (NULL != (pTemp = pNode->GetSubNode(LSUP+1))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //line + } + else + *pS << sal_uInt8(LINE|0x10); + *pS << sal_uInt8(END); + nVariation=0xff; + } + + + sal_uInt8 nVariation2=HandleCScript(pNode,NULL,nLevel); + + if (NULL != (pTemp = pNode->GetSubNode(0))) + { + HandleNodes(pTemp,nLevel+1); + } + + if (nVariation2 != 0xff) + *pS << sal_uInt8(END); + + if (NULL != (pNode->GetSubNode(RSUP+1))) + { + nVariation=0; + if (pNode->GetSubNode(RSUB+1)) + nVariation=2; + } + else if (NULL != (pTemp = pNode->GetSubNode(RSUB+1))) + nVariation=1; + + if (nVariation!=0xff) + { + *pS << sal_uInt8(TMPL); //Template + *pS << sal_uInt8(0x0F); //selector + *pS << nVariation; + *pS << sal_uInt8(0x00); //options + *pS << sal_uInt8(0x0B); + + if (NULL != (pTemp = pNode->GetSubNode(RSUB+1))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //line + } + else + *pS << sal_uInt8(LINE|0x10); + if (NULL != (pTemp = pNode->GetSubNode(RSUP+1))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //line + } + else + *pS << sal_uInt8(LINE|0x10); + *pS << sal_uInt8(END); //line + } + + //After subscript mathtype will keep the size of + //normal text at the subscript size, sigh. + *pS << sal_uInt8(0x0A); +} + + +void MathType::HandleFractions(SmNode *pNode,int nLevel) +{ + SmNode *pTemp; + *pS << sal_uInt8(TMPL); //Template + *pS << sal_uInt8(0x0E); //selector + *pS << sal_uInt8(0x00); //variation + *pS << sal_uInt8(0x00); //options + + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(LINE); //line + if (NULL != (pTemp = pNode->GetSubNode(0))) + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); + + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(LINE); //line + if (NULL != (pTemp = pNode->GetSubNode(2))) + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); + + *pS << sal_uInt8(END); +} + + +void MathType::HandleBrace(SmNode *pNode,int nLevel) +{ + SmNode *pTemp; + SmNode *pLeft=pNode->GetSubNode(0); + SmNode *pRight=pNode->GetSubNode(2); + + *pS << sal_uInt8(TMPL); //Template + bIsReInterpBrace=0; + sal_uInt8 nBSpec=0x10; + sal_uLong nLoc = pS->Tell(); + if (pLeft) + { + switch (pLeft->GetToken().eType) + { + case TLANGLE: + *pS << sal_uInt8(tmANGLE); //selector + *pS << sal_uInt8(0x00); //variation + *pS << sal_uInt8(0x00); //options + break; + case TLBRACE: + *pS << sal_uInt8(tmBRACE); //selector + *pS << sal_uInt8(0x00); //variation + *pS << sal_uInt8(0x00); //options + nBSpec+=3; + break; + case TLBRACKET: + *pS << sal_uInt8(tmBRACK); //selector + *pS << sal_uInt8(0x00); //variation + *pS << sal_uInt8(0x00); //options + nBSpec+=3; + break; + case TLFLOOR: + *pS << sal_uInt8(tmFLOOR); //selector + *pS << sal_uInt8(0x00); //variation + *pS << sal_uInt8(0x00); //options + break; + case TLLINE: + *pS << sal_uInt8(tmBAR); //selector + *pS << sal_uInt8(0x00); //variation + *pS << sal_uInt8(0x00); //options + nBSpec+=3; + break; + case TLDLINE: + *pS << sal_uInt8(tmDBAR); //selector + *pS << sal_uInt8(0x00); //variation + *pS << sal_uInt8(0x00); //options + break; + default: + *pS << sal_uInt8(tmPAREN); //selector + *pS << sal_uInt8(0x00); //variation + *pS << sal_uInt8(0x00); //options + nBSpec+=3; + break; + } + } + + if (NULL != (pTemp = pNode->GetSubNode(1))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //options + } + nSpec=nBSpec; + if (pLeft) + HandleNodes(pLeft,nLevel+1); + if (bIsReInterpBrace) + { + sal_uLong nLoc2 = pS->Tell(); + pS->Seek(nLoc); + *pS << sal_uInt8(0x2D); + pS->Seek(nLoc2); + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x96); + *pS << sal_uInt16(0xEC07); + bIsReInterpBrace=0; + } + if (pRight) + HandleNodes(pRight,nLevel+1); + nSpec=0x0; + *pS << sal_uInt8(END); +} + + +void MathType::HandleVerticalBrace(SmNode *pNode,int nLevel) +{ + SmNode *pTemp; + *pS << sal_uInt8(TMPL); //Template + if (pNode->GetToken().eType == TUNDERBRACE) + *pS << sal_uInt8(tmLHBRACE); //selector + else + *pS << sal_uInt8(tmUHBRACE); //selector + *pS << sal_uInt8(0x01); //variation + *pS << sal_uInt8(0x00); //options + + if (NULL != (pTemp = pNode->GetSubNode(0))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //options + } + + if (NULL != (pTemp = pNode->GetSubNode(2))) + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pTemp,nLevel+1); + *pS << sal_uInt8(END); //options + } + *pS << sal_uInt8(END); +} + +void MathType::HandleOperator(SmNode *pNode,int nLevel) +{ + if (HandleLim(pNode,nLevel)) + return; + + sal_uLong nPos; + sal_uInt8 nVariation; + + switch (pNode->GetToken().eType) + { + case TIINT: + case TIIINT: + case TLINT: + case TLLINT: + case TLLLINT: + nVariation=HandleCScript(pNode->GetSubNode(0), + pNode->GetSubNode(1),nLevel,&nPos,0); + break; + default: + nVariation=HandleCScript(pNode->GetSubNode(0), + pNode->GetSubNode(1),nLevel,&nPos); + break; + } + + sal_uInt8 nOldVariation=nVariation; + sal_uInt8 nIntVariation=nVariation; + + sal_uLong nPos2=0; + if (nVariation != 0xff) + { + nPos2 = pS->Tell(); + pS->Seek(nPos); + if (nVariation == 2) + { + nIntVariation=0; + nVariation = 1; + } + else if (nVariation == 0) + nVariation = 1; + else if (nVariation == 1) + nVariation = 0; + } + else + { + nVariation = 2; + nIntVariation=0; + } + *pS << sal_uInt8(TMPL); + switch(pNode->GetToken().eType) + { + case TINT: + if (nOldVariation != 0xff) + *pS << sal_uInt8(0x18); //selector + else + *pS << sal_uInt8(0x15); //selector + *pS << nIntVariation; //variation + break; + case TIINT: + if (nOldVariation != 0xff) + { + *pS << sal_uInt8(0x19); + *pS << sal_uInt8(0x01); + } + else + { + *pS << sal_uInt8(0x16); + *pS << sal_uInt8(0x00); + } + break; + case TIIINT: + if (nOldVariation != 0xff) + { + *pS << sal_uInt8(0x1a); + *pS << sal_uInt8(0x01); + } + else + { + *pS << sal_uInt8(0x17); + *pS << sal_uInt8(0x00); + } + break; + case TLINT: + if (nOldVariation != 0xff) + { + *pS << sal_uInt8(0x18); + *pS << sal_uInt8(0x02); + } + else + { + *pS << sal_uInt8(0x15); + *pS << sal_uInt8(0x03); + } + break; + case TLLINT: + if (nOldVariation != 0xff) + { + *pS << sal_uInt8(0x19); + *pS << sal_uInt8(0x00); + } + else + { + *pS << sal_uInt8(0x16); + *pS << sal_uInt8(0x02); + } + break; + case TLLLINT: + if (nOldVariation != 0xff) + { + *pS << sal_uInt8(0x1a); + *pS << sal_uInt8(0x00); + } + else + { + *pS << sal_uInt8(0x17); + *pS << sal_uInt8(0x02); + } + break; + case TSUM: + default: + *pS << sal_uInt8(0x1d); + *pS << nVariation; + break; + case TPROD: + *pS << sal_uInt8(0x1f); + *pS << nVariation; + break; + case TCOPROD: + *pS << sal_uInt8(0x21); + *pS << nVariation; + break; + } + *pS << sal_uInt8(0x00); //options + + if (nPos2) + pS->Seek(nPos2); + else + { + *pS << sal_uInt8(LINE); //line + HandleNodes(pNode->GetSubNode(1),nLevel+1); + *pS << sal_uInt8(END); //line + *pS << sal_uInt8(LINE|0x10); + *pS << sal_uInt8(LINE|0x10); + } + + + *pS << sal_uInt8(0x0D); + switch(pNode->GetToken().eType) + { + case TSUM: + default: + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x86); + *pS << sal_uInt16(0x2211); + break; + case TPROD: + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x86); + *pS << sal_uInt16(0x220F); + break; + case TCOPROD: + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x8B); + *pS << sal_uInt16(0x2210); + break; + case TIIINT: + case TLLLINT: + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x86); + *pS << sal_uInt16(0x222B); + case TIINT: + case TLLINT: + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x86); + *pS << sal_uInt16(0x222B); + case TINT: + case TLINT: + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x86); + *pS << sal_uInt16(0x222B); + break; + } + *pS << sal_uInt8(END); + *pS << sal_uInt8(0x0A); +} + + +int MathType::HandlePile(int &rSetAlign,int nLevel,sal_uInt8 nSelector, + sal_uInt8 nVariation) +{ + *pS >> nHAlign; + *pS >> nVAlign; + + HandleAlign(nHAlign,nVAlign,rSetAlign); + + APPEND(rRet," stack {\n"); + int nRet = HandleRecords(nLevel+1,nSelector,nVariation,-1,-1); + rRet.Erase(rRet.Len()-3,2); + APPEND(rRet,"} "); + + while (rSetAlign) + { + APPEND(rRet,"} "); + rSetAlign--; + } + return nRet; +} + +int MathType::HandleMatrix(int nLevel,sal_uInt8 nSelector, + sal_uInt8 nVariation) +{ + sal_uInt8 nH_just,nV_just,nRows,nCols; + *pS >> nVAlign; + *pS >> nH_just; + *pS >> nV_just; + *pS >> nRows; + *pS >> nCols; + int nBytes = ((nRows+1)*2)/8; + if (((nRows+1)*2)%8) + nBytes++; + pS->SeekRel(nBytes); + nBytes = ((nCols+1)*2)/8; + if (((nCols+1)*2)%8) + nBytes++; + pS->SeekRel(nBytes); + APPEND(rRet," matrix {\n"); + int nRet = HandleRecords(nLevel+1,nSelector,nVariation,nRows,nCols); + + xub_StrLen nI = rRet.SearchBackward('#'); + if ((nI != STRING_NOTFOUND) && (nI > 0)) + if (rRet.GetChar(nI-1) != '#') //missing column + APPEND(rRet,"{}"); + + APPEND(rRet,"\n} "); + return nRet; +} + +int MathType::HandleTemplate(int nLevel,sal_uInt8 &rSelector, + sal_uInt8 &rVariation, xub_StrLen &rLastTemplateBracket) +{ + sal_uInt8 nOption; //This appears utterly unused + *pS >> rSelector; + *pS >> rVariation; + *pS >> nOption; + OSL_ENSURE(rSelector < 48,"Selector out of range"); + if ((rSelector >= 21) && (rSelector <=26)) + { + OSL_ENSURE(nOption < 2,"Option out of range"); + } + else if (/*(rSelector >= 0) &&*/ (rSelector <=12)) + { + OSL_ENSURE(nOption < 3,"Option out of range"); + } + + //For the (broken) case where one subscript template ends, and there is + //another one after it, mathtype handles it as if the second one was + //inside the first one and renders it as sub of sub + bool bRemove=false; + if ( (rSelector == 0xf) && (rLastTemplateBracket != STRING_NOTFOUND) ) + { + bRemove=true; + for (xub_StrLen nI = rLastTemplateBracket+1; nI < rRet.Len(); nI++ ) + if (rRet.GetChar(nI) != ' ') + { + bRemove=false; + break; + } + } + + //suborderlist + int nRet = HandleRecords(nLevel+1,rSelector,rVariation); + + if (bRemove) + { + rRet.Erase(rLastTemplateBracket,1); + APPEND(rRet,"} "); + rLastTemplateBracket = STRING_NOTFOUND; + } + if (rSelector == 0xf) + rLastTemplateBracket = rRet.SearchBackward('}'); + else + rLastTemplateBracket = STRING_NOTFOUND; + + rSelector = sal::static_int_cast< sal_uInt8 >(-1); + return nRet; +} + +void MathType::HandleEmblishments() +{ + sal_uInt8 nEmbel; + do + { + *pS >> nEmbel; + switch (nEmbel) + { + case 0x02: + APPEND(rRet," dot "); + break; + case 0x03: + APPEND(rRet," ddot "); + break; + case 0x04: + APPEND(rRet," dddot "); + break; + case 0x05: + if (nPostSup == 0) + { + APPEND(sPost," sup {}"); + nPostSup = sPost.Len(); + } + sPost.InsertAscii(" ' ",nPostSup-1); + nPostSup += 3; + break; + case 0x06: + if (nPostSup == 0) + { + APPEND(sPost," sup {}"); + nPostSup = sPost.Len(); + } + sPost.InsertAscii(" '' ",nPostSup-1); + nPostSup += 4; + break; + case 0x07: + if (nPostlSup == 0) + { + APPEND(sPost," lsup {}"); + nPostlSup = sPost.Len(); + } + sPost.InsertAscii(" ' ",nPostlSup-1); + nPostlSup += 3; + break; + case 0x08: + APPEND(rRet," tilde "); + break; + case 0x09: + APPEND(rRet," hat "); + break; + case 0x0b: + APPEND(rRet," vec "); + break; + case 0x10: + APPEND(rRet," overstrike "); + break; + case 0x11: + APPEND(rRet," bar "); + break; + case 0x12: + if (nPostSup == 0) + { + APPEND(sPost," sup {}"); + nPostSup = sPost.Len(); + } + sPost.InsertAscii(" ''' ",nPostSup-1); + nPostSup += 5; + break; + case 0x14: + APPEND(rRet," breve "); + break; + default: + OSL_ENSURE(nEmbel < 21,"Embel out of range"); + break; + } + if (nVersion < 3) + break; + }while (nEmbel); +} + +void MathType::HandleSetSize() +{ + sal_uInt8 nTemp; + *pS >> nTemp; + switch (nTemp) + { + case 101: + *pS >> nLSize; + nLSize = -nLSize; + break; + case 100: + *pS >> nTemp; + nLSize = nTemp; + *pS >> nDSize; + break; + default: + nLSize = nTemp; + *pS >> nTemp; + nDSize = nTemp-128; + break; + } +} + +int MathType::HandleChar(xub_StrLen &rTextStart,int &rSetSize,int nLevel, + sal_uInt8 nTag,sal_uInt8 nSelector,sal_uInt8 nVariation, sal_Bool bSilent) +{ + sal_Unicode nChar; + int nRet=1; + + if (xfAUTO(nTag)) + { + //This is a candidate for function recognition, whatever + //that is! + } + + sal_uInt8 nOldTypeFace = nTypeFace; + *pS >> nTypeFace; + if (nVersion < 3) + { + sal_uInt8 nChar8; + *pS >> nChar8; + nChar = nChar8; + } + else + *pS >> nChar; + + /* + bad character, old mathtype < 3 has these + */ + if (nChar < 0x20) + return nRet; + + if (xfEMBELL(nTag)) + { + //A bit tricky, the character emblishments for + //mathtype can all be listed after eachother, in + //starmath some must go before the character and some + //must go after. In addition some of the emblishments + //may repeated and in starmath some of these groups + //must be gathered together. sPost is the portion that + //follows the char and nPostSup and nPostlSup are the + //indexes at which this class of emblishment is + //collated together + sPost.Erase(); + nPostSup = nPostlSup = 0; + int nOriglen=rRet.Len()-rTextStart; + APPEND(rRet," {"); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n" + if ((!bSilent) && ((nOriglen) > 1)) + rRet += '\"'; + nRet = HandleRecords(nLevel+1,nSelector,nVariation); + if (!bSilent) + { + if (nOriglen > 1) + { + String aStr; + TypeFaceToString(aStr,nOldTypeFace); + aStr += '\"'; + rRet.Insert(aStr,rTextStart); + + aStr.Erase(); + TypeFaceToString(aStr,nTypeFace); + rRet.Append(aStr); + rRet += '{'; + } + else + APPEND(rRet," {"); + rTextStart = rRet.Len(); + } + } + + if (!bSilent) + { + xub_StrLen nOldLen = rRet.Len(); + if ( + HandleSize(nLSize,nDSize,rSetSize) || + (nOldTypeFace != nTypeFace) + ) + { + if ((nOldLen - rTextStart) > 1) + { + rRet.InsertAscii("\"",nOldLen); + String aStr; + TypeFaceToString(aStr,nOldTypeFace); + aStr += '\"'; + rRet.Insert(aStr,rTextStart); + } + rTextStart = rRet.Len(); + } + nOldLen = rRet.Len(); + if (!LookupChar(nChar,rRet,nVersion,nTypeFace)) + { + if (nOldLen - rTextStart > 1) + { + rRet.InsertAscii("\"",nOldLen); + String aStr; + TypeFaceToString(aStr,nOldTypeFace); + aStr += '\"'; + rRet.Insert(aStr,rTextStart); + } + rTextStart = rRet.Len(); + } + lcl_PrependDummyTerm(rRet, rTextStart); + } + + if ((xfEMBELL(nTag)) && (!bSilent)) + { + rRet += '}'; // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n" + rRet += '}'; + rRet += sPost; + rTextStart = rRet.Len(); + } + return nRet; +} + +sal_Bool MathType::HandleLim(SmNode *pNode,int nLevel) +{ + bool bRet=false; + //Special case for the "lim" option in StarMath + if ((pNode->GetToken().eType == TLIM) + || (pNode->GetToken().eType == TLIMSUP) + || (pNode->GetToken().eType == TLIMINF) + ) + { + if (pNode->GetSubNode(1)) + { + sal_uInt8 nVariation2=HandleCScript(pNode->GetSubNode(0),NULL, + nLevel); + + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(LINE); //line + *pS << sal_uInt8(CHAR|0x10); + *pS << sal_uInt8(0x82); + *pS << sal_uInt16('l'); + *pS << sal_uInt8(CHAR|0x10); + *pS << sal_uInt8(0x82); + *pS << sal_uInt16('i'); + *pS << sal_uInt8(CHAR|0x10); + *pS << sal_uInt8(0x82); + *pS << sal_uInt16('m'); + + if (pNode->GetToken().eType == TLIMSUP) + { + *pS << sal_uInt8(CHAR); //some space + *pS << sal_uInt8(0x98); + *pS << sal_uInt16(0xEB04); + + *pS << sal_uInt8(CHAR|0x10); + *pS << sal_uInt8(0x82); + *pS << sal_uInt16('s'); + *pS << sal_uInt8(CHAR|0x10); + *pS << sal_uInt8(0x82); + *pS << sal_uInt16('u'); + *pS << sal_uInt8(CHAR|0x10); + *pS << sal_uInt8(0x82); + *pS << sal_uInt16('p'); + } + else if (pNode->GetToken().eType == TLIMINF) + { + *pS << sal_uInt8(CHAR); //some space + *pS << sal_uInt8(0x98); + *pS << sal_uInt16(0xEB04); + + *pS << sal_uInt8(CHAR|0x10); + *pS << sal_uInt8(0x82); + *pS << sal_uInt16('i'); + *pS << sal_uInt8(CHAR|0x10); + *pS << sal_uInt8(0x82); + *pS << sal_uInt16('n'); + *pS << sal_uInt8(CHAR|0x10); + *pS << sal_uInt8(0x82); + *pS << sal_uInt16('f'); + } + + + *pS << sal_uInt8(CHAR); //some space + *pS << sal_uInt8(0x98); + *pS << sal_uInt16(0xEB04); + + if (nVariation2 != 0xff) + { + *pS << sal_uInt8(END); + *pS << sal_uInt8(END); + } + HandleNodes(pNode->GetSubNode(1),nLevel+1); + //*pS << sal_uInt8(END); //options + bRet = true; + } + } + return bRet; +} + +void MathType::HandleMAlign(SmNode *pNode,int nLevel) +{ + sal_uInt8 nPushedHAlign=nHAlign; + switch(pNode->GetToken().eType) + { + case TALIGNC: + nHAlign=2; + break; + case TALIGNR: + nHAlign=3; + break; + default: + nHAlign=1; + break; + } + sal_uInt16 nSize = pNode->GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (SmNode *pTemp = pNode->GetSubNode(i)) + HandleNodes(pTemp,nLevel+1); + nHAlign=nPushedHAlign; +} + +void MathType::HandleMath(SmNode *pNode, int /*nLevel*/) +{ + if (pNode->GetToken().eType == TMLINE) + { + *pS << sal_uInt8(END); + *pS << sal_uInt8(LINE); + bIsReInterpBrace=1; + return; + } + SmMathSymbolNode *pTemp=(SmMathSymbolNode *)pNode; + for(xub_StrLen i=0;i<pTemp->GetText().Len();i++) + { + sal_Unicode nArse = Convert(pTemp->GetText().GetChar(i)); + if ((nArse == 0x2224) || (nArse == 0x2288) || (nArse == 0x2285) || + (nArse == 0x2289)) + { + *pS << sal_uInt8(CHAR|0x20); + } + else if ((nPendingAttributes) && + (i == ((pTemp->GetText().Len()+1)/2)-1)) + { + *pS << sal_uInt8(0x22); + } + else + *pS << sal_uInt8(CHAR); //char without formula recognition + //The typeface seems to be MTEXTRA for unicode characters, + //though how to determine when mathtype chooses one over + //the other is unknown. This should do the trick + //nevertheless. + sal_uInt8 nBias; + if ( (nArse == 0x2213) || (nArse == 0x2218) || + (nArse == 0x210F) || ( + (nArse >= 0x22EE) && (nArse <= 0x22FF) + )) + { + nBias = 0xB; //typeface + } + else if ((nArse > 0x2000) || (nArse == 0x00D7)) + nBias = 0x6; //typeface + else if (nArse == 0x3d1) + nBias = 0x4; + else if ((nArse > 0xFF) && ((nArse < 0x393) || (nArse > 0x3c9))) + nBias = 0xB; //typeface + else if ((nArse == 0x2F) || (nArse == 0x2225)) + nBias = 0x2; //typeface + else + nBias = 0x3; //typeface + + *pS << sal_uInt8(nSpec+nBias+128); //typeface + + if (nArse == 0x2224) + { + *pS << sal_uInt16(0x7C); + *pS << sal_uInt8(EMBEL); + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } + else if (nArse == 0x2225) + *pS << sal_uInt16(0xEC09); + else if (nArse == 0xE421) + *pS << sal_uInt16(0x2265); + else if (nArse == 0x230A) + *pS << sal_uInt16(0xF8F0); + else if (nArse == 0x230B) + *pS << sal_uInt16(0xF8FB); + else if (nArse == 0xE425) + *pS << sal_uInt16(0x2264); + else if (nArse == 0x226A) + { + *pS << sal_uInt16(0x3C); + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x98); + *pS << sal_uInt16(0xEB01); + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x86); + *pS << sal_uInt16(0x3c); + } + else if (nArse == 0x2288) + { + *pS << sal_uInt16(0x2286); + *pS << sal_uInt8(EMBEL); + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } + else if (nArse == 0x2289) + { + *pS << sal_uInt16(0x2287); + *pS << sal_uInt8(EMBEL); + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } + else if (nArse == 0x2285) + { + *pS << sal_uInt16(0x2283); + *pS << sal_uInt8(EMBEL); + *pS << sal_uInt8(0x0A); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } + else + *pS << nArse; + } + nPendingAttributes = 0; +} + +void MathType::HandleAttributes(SmNode *pNode,int nLevel) +{ + int nOldPending = 0; + SmNode *pTemp = 0; + SmTextNode *pIsText = 0; + + if (NULL != (pTemp = pNode->GetSubNode(0))) + { + pIsText = (SmTextNode *)pNode->GetSubNode(1); + + switch (pTemp->GetToken().eType) + { + case TWIDEVEC: + //theres just no way we can now handle any character + //attributes (from mathtypes perspective) centered + //over an expression but above template attributes + //such as widevec and similiar constructs + //we have to drop them + nOldPending = StartTemplate(0x2f,0x01); + break; + case TCHECK: //Not Exportable + case TACUTE: //Not Exportable + case TGRAVE: //Not Exportable + case TCIRCLE: //Not Exportable + case TWIDETILDE: //Not Exportable + case TWIDEHAT: //Not Exportable + break; + case TUNDERLINE: + nOldPending = StartTemplate(0x10); + break; + case TOVERLINE: //If the next node is not text + //or text with more than one char + if ((pIsText->GetToken().eType != TTEXT) || + (pIsText->GetText().Len() > 1)) + nOldPending = StartTemplate(0x11); + break; + default: + nPendingAttributes++; + break; + } + } + + if (pIsText) + HandleNodes(pIsText,nLevel+1); + + switch (pTemp->GetToken().eType) + { + case TWIDEVEC: + case TUNDERLINE: + EndTemplate(nOldPending); + break; + case TOVERLINE: + if ((pIsText->GetToken().eType != TTEXT) || + (pIsText->GetText().Len() > 1)) + EndTemplate(nOldPending); + break; + default: + break; + } + + //if there was no suitable place to put the attribute, + //then we have to just give up on it + if (nPendingAttributes) + nPendingAttributes--; + else + { + if ((nInsertion != 0) && NULL != (pTemp = pNode->GetSubNode(0))) + { + sal_uLong nPos = pS->Tell(); + nInsertion--; + pS->Seek(nInsertion); + switch(pTemp->GetToken().eType) + { + case TACUTE: //Not Exportable + case TGRAVE: //Not Exportable + case TCIRCLE: //Not Exportable + break; + case TCDOT: + *pS << sal_uInt8(2); + break; + case TDDOT: + *pS << sal_uInt8(3); + break; + case TDDDOT: + *pS << sal_uInt8(4); + break; + case TTILDE: + *pS << sal_uInt8(8); + break; + case THAT: + *pS << sal_uInt8(9); + break; + case TVEC: + *pS << sal_uInt8(11); + break; + case TOVERSTRIKE: + *pS << sal_uInt8(16); + break; + case TOVERLINE: + if ((pIsText->GetToken().eType == TTEXT) && + (pIsText->GetText().Len() == 1)) + *pS << sal_uInt8(17); + break; + case TBREVE: + *pS << sal_uInt8(20); + break; + case TWIDEVEC: + case TUNDERLINE: + case TWIDETILDE: + case TWIDEHAT: + break; + case TBAR: + *pS << sal_uInt8(17); + break; + default: + *pS << sal_uInt8(0x2); + break; + } + pS->Seek(nPos); + } + } +} + +void MathType::HandleText(SmNode *pNode, int /*nLevel*/) +{ + SmTextNode *pTemp=(SmTextNode *)pNode; + for(xub_StrLen i=0;i<pTemp->GetText().Len();i++) + { + if ((nPendingAttributes) && + (i == ((pTemp->GetText().Len()+1)/2)-1)) + { + *pS << sal_uInt8(0x22); //char, with attributes right + //after the character + } + else + *pS << sal_uInt8(CHAR); + + sal_uInt8 nFace = 0x1; + if (pNode->GetFont().GetItalic() == ITALIC_NORMAL) + nFace = 0x3; + else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD) + nFace = 0x7; + *pS << sal_uInt8(nFace+128); //typeface + sal_uInt16 nChar = pTemp->GetText().GetChar(i); + *pS << Convert(nChar); + + //Mathtype can only have these sort of character + //attributes on a single character, starmath can put them + //anywhere, when the entity involved is a text run this is + //a large effort to place the character attribute on the + //central mathtype character so that it does pretty much + //what the user probably has in mind. The attributes + //filled in here are dummy ones which are replaced in the + //ATTRIBUT handler if a suitable location for the + //attributes was found here. Unfortunately it is + //possible for starmath to place character attributes on + //entities which cannot occur in mathtype e.g. a Summation + //symbol so these attributes may be lost + if ((nPendingAttributes) && + (i == ((pTemp->GetText().Len()+1)/2)-1)) + { + *pS << sal_uInt8(EMBEL); + while (nPendingAttributes) + { + *pS << sal_uInt8(2); + //wedge the attributes in here and clear + //the pending stack + nPendingAttributes--; + } + nInsertion=pS->Tell(); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/mathtype.hxx b/starmath/source/mathtype.hxx new file mode 100644 index 000000000000..e37d388f8e8a --- /dev/null +++ b/starmath/source/mathtype.hxx @@ -0,0 +1,179 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + #ifndef MATHTYPE_HXX +#define MATHTYPE_HXX + +#include "node.hxx" +#include "eqnolefilehdr.hxx" + +#include <sot/storage.hxx> + +#include <set> + +class SfxMedium; + +class MathTypeFont +{ +public: + sal_uInt8 nTface; + sal_uInt8 nStyle; + MathTypeFont() : nTface(0),nStyle(0) {} + MathTypeFont(sal_uInt8 nFace) : nTface(nFace),nStyle(0) {} + void AppendStyleToText(String &rS); +}; + +struct LessMathTypeFont +{ + sal_Bool operator() (const MathTypeFont &rValue1, + const MathTypeFont &rValue2) const + { + return rValue1.nTface < rValue2.nTface; + } +}; + +typedef ::std::set< MathTypeFont, LessMathTypeFont > MathTypeFontSet; + +class MathType +{ +public: + MathType(String &rIn) : + rRet(rIn), nHAlign(0), nVAlign(0), nDefaultSize(12), + nLSize(0), nDSize(0), nCurSize(0), nLastSize(0), bIsSilent(sal_False), + nTypeFace(0) + { + Init(); + } + + MathType(String &rIn,SmNode *pIn) : + rRet(rIn), pTree(pIn), nHAlign(2), nVAlign(0), nInsertion(0), nDefaultSize(12), + nLSize(0), nDSize(0), nCurSize(0), nLastSize(0), nSpec(0), bIsSilent(sal_False), + nTypeFace(0) + { + Init(); + } + + int Parse( SotStorage* pStor ); + int ConvertFromStarMath( SfxMedium& rMedium ); + +private: +/*Ver 2 Header*/ + sal_uInt8 nVersion; + sal_uInt8 nPlatform; + sal_uInt8 nProduct; + sal_uInt8 nProdVersion; + sal_uInt8 nProdSubVersion; + + SvStorageStream *pS; + + void Init(); + + int HandleRecords(int nLevel=0,sal_uInt8 nSelector=0xFF, + sal_uInt8 nVariation=0xFF,int nRows=0,int nCols=0); + sal_Bool HandleSize(sal_Int16 nLSize,sal_Int16 nDSize, int &rSetSize); + void HandleAlign(sal_uInt8 nHAlign,sal_uInt8 nVAlign, int &rSetAlign); + int HandlePile(int &rSetAlign,int nLevel,sal_uInt8 nSelector, + sal_uInt8 nVariation); + int HandleMatrix(int nLevel,sal_uInt8 nSelector,sal_uInt8 nVariarion); + void HandleMatrixSeperator(int nMatrixRows,int nMatrixCols,int &rCurCol, + int &rCurRow); + int HandleTemplate(int nLevel,sal_uInt8 &rSelector,sal_uInt8 &rVariation, + xub_StrLen &rLastTemplateBracket); + void HandleEmblishments(); + void HandleSetSize(); + int HandleChar(xub_StrLen &rTextStart,int &rSetSize,int nLevel, + sal_uInt8 nTag,sal_uInt8 nSelector,sal_uInt8 nVariation, + sal_Bool bSilent); + void HandleNudge(); + int xfLMOVE(sal_uInt8 nTest) const {return nTest&0x80;} + int xfAUTO(sal_uInt8 nTest) const {return nTest&0x10;} + int xfEMBELL(sal_uInt8 nTest) const {return nTest&0x20;} + int xfNULL(sal_uInt8 nTest) const {return nTest&0x10;} + int xfLSPACE(sal_uInt8 nTest) const {return nTest&0x40;} + int xfRULER(sal_uInt8 nTest) const {return nTest&0x20;} + + sal_uInt8 HandleNodes(SmNode *pNode,int nLevel=0); + int StartTemplate(sal_uInt16 nSelector,sal_uInt16 nVariation=0); + void EndTemplate(int nOldPendingAttributes); + void HandleSmMatrix(SmMatrixNode *pMatrix,int nLevel); + void HandleTable(SmNode *pNode,int nLevel); + void HandleRoot(SmNode *pNode,int nLevel); + void HandleSubSupScript(SmNode *pNode,int nLevel); + sal_uInt8 HandleCScript(SmNode *pNode,SmNode *pContent,int nLevel, + sal_uLong *pPos=NULL,sal_Bool bTest=sal_True); + void HandleFractions(SmNode *pNode,int nLevel); + void HandleBrace(SmNode *pNode,int nLevel); + void HandleVerticalBrace(SmNode *pNode,int nLevel); + void HandleOperator(SmNode *pNode,int nLevel); + sal_Bool HandleLim(SmNode *pNode,int nLevel); + void HandleMAlign(SmNode *pNode,int nLevel); + void HandleMath(SmNode *pNode,int nLevel); + void HandleText(SmNode *pNode,int nLevel); + void HandleAttributes(SmNode *pNode,int nLevel); + void TypeFaceToString(String &rRet,sal_uInt8 nFace); + + String &rRet; + SmNode *pTree; + + sal_uInt8 nHAlign; + sal_uInt8 nVAlign; + + int nPendingAttributes; + sal_uLong nInsertion; + + sal_Int16 aSizeTable[7]; + sal_Int16 nDefaultSize; + sal_Int16 nLSize; + sal_Int16 nDSize; + sal_Int16 nCurSize; + sal_Int16 nLastSize; + sal_uInt8 nSpec; + sal_Bool bIsSilent, bIsReInterpBrace; + String sPost; + xub_StrLen nPostSup; + xub_StrLen nPostlSup; + sal_uInt8 nTypeFace; + MathTypeFontSet aUserStyles; + + enum MTOKENS {END,LINE,CHAR,TMPL,PILE,MATRIX,EMBEL,RULER,FONT,SIZE}; + enum MTEMPLATES + { + tmANGLE,tmPAREN,tmBRACE,tmBRACK,tmBAR,tmDBAR,tmFLOOR,tmCEILING, + tmLBLB,tmRBRB,tmRBLB,tmLBRP,tmLPRB,tmROOT,tmFRACT,tmSCRIPT,tmUBAR, + tmOBAR,tmLARROW,tmRARROW,tmBARROW,tmSINT,tmDINT,tmTINT,tmSSINT, + tmDSINT,tmTSINT,tmUHBRACE,tmLHBRACE,tmSUM + }; +public: + static sal_Bool LookupChar(sal_Unicode nChar,String &rRet, + sal_uInt8 nVersion=3,sal_uInt8 nTypeFace=0); +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/node.cxx b/starmath/source/node.cxx new file mode 100644 index 000000000000..93dbedf73ea5 --- /dev/null +++ b/starmath/source/node.cxx @@ -0,0 +1,3151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + +#include "node.hxx" +#include "rect.hxx" +#include "symbol.hxx" +#include "smmod.hxx" +#include "document.hxx" +#include "view.hxx" +#include "mathtype.hxx" +#include "visitors.hxx" + +#include <tools/gen.hxx> +#include <tools/fract.hxx> +#include <rtl/math.hxx> +#include <tools/color.hxx> +#include <vcl/metric.hxx> +#include <vcl/lineinfo.hxx> +#include <vcl/outdev.hxx> +#include <sfx2/module.hxx> + +#include <math.h> +#include <float.h> + + +#define APPEND(str,ascii) str.AppendAscii(RTL_CONSTASCII_STRINGPARAM(ascii)) + + +using ::rtl::OUString; + + +//////////////////////////////////////// +// SmTmpDevice +// Allows for font and color changes. The original settings will be restored +// in the destructor. +// It's main purpose is to allow for the "const" in the 'OutputDevice' +// argument in the 'Arrange' functions and restore changes made in the 'Draw' +// functions. +// Usually a MapMode of 1/100th mm will be used. +// + +class SmTmpDevice +{ + OutputDevice &rOutDev; + + // disallow use of copy-constructor and assignment-operator + SmTmpDevice(const SmTmpDevice &rTmpDev); + SmTmpDevice & operator = (const SmTmpDevice &rTmpDev); + + Color Impl_GetColor( const Color& rColor ); + +public: + SmTmpDevice(OutputDevice &rTheDev, bool bUseMap100th_mm); + ~SmTmpDevice() { rOutDev.Pop(); } + + void SetFont(const Font &rNewFont); + + void SetLineColor( const Color& rColor ) { rOutDev.SetLineColor( Impl_GetColor(rColor) ); } + void SetFillColor( const Color& rColor ) { rOutDev.SetFillColor( Impl_GetColor(rColor) ); } + void SetTextColor( const Color& rColor ) { rOutDev.SetTextColor( Impl_GetColor(rColor) ); } + + operator OutputDevice & () { return rOutDev; } +}; + + +SmTmpDevice::SmTmpDevice(OutputDevice &rTheDev, bool bUseMap100th_mm) : + rOutDev(rTheDev) +{ + rOutDev.Push( PUSH_FONT | PUSH_MAPMODE | + PUSH_LINECOLOR | PUSH_FILLCOLOR | PUSH_TEXTCOLOR ); + if (bUseMap100th_mm && MAP_100TH_MM != rOutDev.GetMapMode().GetMapUnit()) + { + OSL_FAIL( "incorrect MapMode?" ); + rOutDev.SetMapMode( MAP_100TH_MM ); //Immer fuer 100% fomatieren + } +} + + +Color SmTmpDevice::Impl_GetColor( const Color& rColor ) +{ + ColorData nNewCol = rColor.GetColor(); + if (COL_AUTO == nNewCol) + { + if (OUTDEV_PRINTER == rOutDev.GetOutDevType()) + nNewCol = COL_BLACK; + else + { + Color aBgCol( rOutDev.GetBackground().GetColor() ); + if (OUTDEV_WINDOW == rOutDev.GetOutDevType()) + aBgCol = ((Window &) rOutDev).GetDisplayBackground().GetColor(); + + nNewCol = SM_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor; + + Color aTmpColor( nNewCol ); + if (aBgCol.IsDark() && aTmpColor.IsDark()) + nNewCol = COL_WHITE; + else if (aBgCol.IsBright() && aTmpColor.IsBright()) + nNewCol = COL_BLACK; + } + } + return Color( nNewCol ); +} + + +void SmTmpDevice::SetFont(const Font &rNewFont) +{ + rOutDev.SetFont( rNewFont ); + rOutDev.SetTextColor( Impl_GetColor( rNewFont.GetColor() ) ); +} + + +/////////////////////////////////////////////////////////////////////////// + + +SmNode::SmNode(SmNodeType eNodeType, const SmToken &rNodeToken) +{ + eType = eNodeType; + eScaleMode = SCALE_NONE; + aNodeToken = rNodeToken; + nAccIndex = -1; + SetSelected(false); + aParentNode = NULL; +} + + +SmNode::~SmNode() +{ +} + + +bool SmNode::IsVisible() const +{ + return false; +} + + +sal_uInt16 SmNode::GetNumSubNodes() const +{ + return 0; +} + + +SmNode * SmNode::GetSubNode(sal_uInt16 /*nIndex*/) +{ + return NULL; +} + + +SmNode * SmNode::GetLeftMost() + // returns leftmost node of current subtree. + //! (this assumes the one with index 0 is always the leftmost subnode + //! for the current node). +{ + SmNode *pNode = GetNumSubNodes() > 0 ? + GetSubNode(0) : NULL; + + return pNode ? pNode->GetLeftMost() : this; +} + + +void SmNode::SetPhantom(bool bIsPhantomP) +{ + if (! (Flags() & FLG_VISIBLE)) + bIsPhantom = bIsPhantomP; + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->SetPhantom(bIsPhantom); +} + + +void SmNode::SetColor(const Color& rColor) +{ + if (! (Flags() & FLG_COLOR)) + GetFont().SetColor(rColor); + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->SetColor(rColor); +} + + +void SmNode::SetAttribut(sal_uInt16 nAttrib) +{ + if ( + (nAttrib == ATTR_BOLD && !(Flags() & FLG_BOLD)) || + (nAttrib == ATTR_ITALIC && !(Flags() & FLG_ITALIC)) + ) + { + nAttributes |= nAttrib; + } + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->SetAttribut(nAttrib); +} + + +void SmNode::ClearAttribut(sal_uInt16 nAttrib) +{ + if ( + (nAttrib == ATTR_BOLD && !(Flags() & FLG_BOLD)) || + (nAttrib == ATTR_ITALIC && !(Flags() & FLG_ITALIC)) + ) + { + nAttributes &= ~nAttrib; + } + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->ClearAttribut(nAttrib); +} + + +void SmNode::SetFont(const SmFace &rFace) +{ + if (!(Flags() & FLG_FONT)) + GetFont() = rFace; + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->SetFont(rFace); +} + + +void SmNode::SetFontSize(const Fraction &rSize, sal_uInt16 nType) + //! 'rSize' is in units of pts +{ + Size aFntSize; + + if (!(Flags() & FLG_SIZE)) + { + Fraction aVal (SmPtsTo100th_mm(rSize.GetNumerator()), + rSize.GetDenominator()); + long nHeight = (long)aVal; + + aFntSize = GetFont().GetSize(); + aFntSize.Width() = 0; + switch(nType) + { + case FNTSIZ_ABSOLUT: + aFntSize.Height() = nHeight; + break; + + case FNTSIZ_PLUS: + aFntSize.Height() += nHeight; + break; + + case FNTSIZ_MINUS: + aFntSize.Height() -= nHeight; + break; + + case FNTSIZ_MULTIPLY: + aFntSize.Height() = (long) (Fraction(aFntSize.Height()) * rSize); + break; + + case FNTSIZ_DIVIDE: + if (rSize != Fraction(0L)) + aFntSize.Height() = (long) (Fraction(aFntSize.Height()) / rSize); + break; + default: + break; + } + + // check the requested size against maximum value + static int const nMaxVal = SmPtsTo100th_mm(128); + if (aFntSize.Height() > nMaxVal) + aFntSize.Height() = nMaxVal; + + GetFont().SetSize(aFntSize); + } + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->SetFontSize(rSize, nType); +} + + +void SmNode::SetSize(const Fraction &rSize) +{ + GetFont() *= rSize; + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->SetSize(rSize); +} + + +void SmNode::SetRectHorAlign(RectHorAlign eHorAlign, bool bApplyToSubTree ) +{ + if (!(Flags() & FLG_HORALIGN)) + eRectHorAlign = eHorAlign; + + if (bApplyToSubTree) + { + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->SetRectHorAlign(eHorAlign); + } +} + + +void SmNode::PrepareAttributes() +{ + GetFont().SetWeight((Attributes() & ATTR_BOLD) ? WEIGHT_BOLD : WEIGHT_NORMAL); + GetFont().SetItalic((Attributes() & ATTR_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE); +} + + +void SmNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) +{ +#if OSL_DEBUG_LEVEL > 1 + bIsDebug = true; +#else + bIsDebug = false; +#endif + bIsPhantom = false; + nFlags = 0; + nAttributes = 0; + + switch (rFormat.GetHorAlign()) + { case AlignLeft: eRectHorAlign = RHA_LEFT; break; + case AlignCenter: eRectHorAlign = RHA_CENTER; break; + case AlignRight: eRectHorAlign = RHA_RIGHT; break; + } + + GetFont() = rFormat.GetFont(FNT_MATH); + OSL_ENSURE( GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE, + "unexpected CharSet" ); + GetFont().SetWeight(WEIGHT_NORMAL); + GetFont().SetItalic(ITALIC_NONE); + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->Prepare(rFormat, rDocShell); +} + + +#if OSL_DEBUG_LEVEL > 1 +void SmNode::ToggleDebug() const + // toggle 'bIsDebug' in current subtree +{ + SmNode *pThis = (SmNode *) this; + + pThis->bIsDebug = bIsDebug ? false : true; + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = pThis->GetSubNode(i))) + pNode->ToggleDebug(); +} +#endif + + +void SmNode::Move(const Point& rPosition) +{ + if (rPosition.X() == 0 && rPosition.Y() == 0) + return; + + SmRect::Move(rPosition); + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->Move(rPosition); +} + + +void SmNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->Arrange(rDev, rFormat); +} + +void SmNode::CreateTextFromNode(String &rText) +{ + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + if (nSize > 1) + rText.Append('{'); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->CreateTextFromNode(rText); + if (nSize > 1) + { + rText.EraseTrailingChars(); + APPEND(rText,"} "); + } +} + + +void SmNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong /*nWidth*/) +{ +} + + +void SmNode::AdaptToY(const OutputDevice &/*rDev*/, sal_uLong /*nHeight*/) +{ +} + + +const SmNode * SmNode::FindTokenAt(sal_uInt16 nRow, sal_uInt16 nCol) const + // returns (first) ** visible ** (sub)node with the tokens text at + // position 'nRow', 'nCol'. + //! (there should be exactly one such node if any) +{ + if ( IsVisible() + && nRow == GetToken().nRow + && nCol >= GetToken().nCol && nCol < GetToken().nCol + GetToken().aText.Len()) + return this; + else + { + sal_uInt16 nNumSubNodes = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nNumSubNodes; i++) + { const SmNode *pNode = GetSubNode(i); + + if (!pNode) + continue; + + const SmNode *pResult = pNode->FindTokenAt(nRow, nCol); + if (pResult) + return pResult; + } + } + + return 0; +} + + +const SmNode * SmNode::FindRectClosestTo(const Point &rPoint) const +{ + long nDist = LONG_MAX; + const SmNode *pResult = 0; + + if (IsVisible()) + pResult = this; + else + { + sal_uInt16 nNumSubNodes = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nNumSubNodes; i++) + { const SmNode *pNode = GetSubNode(i); + + if (!pNode) + continue; + + long nTmp; + const SmNode *pFound = pNode->FindRectClosestTo(rPoint); + if (pFound && (nTmp = pFound->OrientedDist(rPoint)) < nDist) + { nDist = nTmp; + pResult = pFound; + + // quit immediately if 'rPoint' is inside the *should not + // overlap with other rectangles* part. + // This (partly) serves for getting the attributes in eg + // "bar overstrike a". + // ('nDist < 0' is used as *quick shot* to avoid evaluation of + // the following expression, where the result is already determined) + if (nDist < 0 && pFound->IsInsideRect(rPoint)) + break; + } + } + } + + return pResult; +} + +void SmNode::GetAccessibleText( String &/*rText*/ ) const +{ + OSL_FAIL( "SmNode: GetAccessibleText not overloaded" ); +} + +const SmNode * SmNode::FindNodeWithAccessibleIndex(xub_StrLen nAccIdx) const +{ + const SmNode *pResult = 0; + + sal_Int32 nIdx = GetAccessibleIndex(); + String aTxt; + if (nIdx >= 0) + GetAccessibleText( aTxt ); // get text if used in following 'if' statement + + if (nIdx >= 0 + && nIdx <= nAccIdx && nAccIdx < nIdx + aTxt.Len()) + pResult = this; + else + { + sal_uInt16 nNumSubNodes = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nNumSubNodes; i++) + { + const SmNode *pNode = GetSubNode(i); + if (!pNode) + continue; + + pResult = pNode->FindNodeWithAccessibleIndex(nAccIdx); + if (pResult) + return pResult; + } + } + + return pResult; +} + +#ifdef DEBUG_ENABLE_DUMPASDOT +void SmNode::DumpAsDot(std::ostream &out, String* label, int number, int& id, int parent) const +{ + //If this is the root start the file + if(number == -1){ + out<<"digraph {"<<std::endl; + if(label){ + out<<"labelloc = \"t\";"<<std::endl; + String eq(*label); + //CreateTextFromNode(eq); + eq.SearchAndReplaceAll(String::CreateFromAscii("\n"), String::CreateFromAscii(" ")); + eq.SearchAndReplaceAll(String::CreateFromAscii("\\"), String::CreateFromAscii("\\\\")); + eq.SearchAndReplaceAll(String::CreateFromAscii("\""), String::CreateFromAscii("\\\"")); + out<<"label= \"Equation: \\\""; + out<< rtl::OUStringToOString(eq, RTL_TEXTENCODING_UTF8).getStr(); + out<<"\\\"\";"<<std::endl; + } + } + + //Some how out<<(int)this; doesn't work... So we do this nasty workaround... + char strid[100]; + sprintf(strid, "%i", id); + + char strnr[100]; + sprintf(strnr, "%i", number); + + //Dump connection to this node + if( parent != -1 ){ + char pid[100]; + sprintf(pid, "%i", parent); + out<<"n"<<pid<<" -> n"<<strid<<" [label=\""<<strnr<<"\"];"<<std::endl; + //If doesn't have parent and isn't a rootnode: + } else if(number != -1) { + out<<"orphaned -> n"<<strid<<" [label=\""<<strnr<<"\"];"<<std::endl; + } + + //Dump this node + out<<"n"<< strid<<" [label=\""; + switch( GetType() ) { + case NTABLE: out<<"SmTableNode"; break; + case NBRACE: out<<"SmBraceNode"; break; + case NBRACEBODY: out<<"SmBracebodyNode"; break; + case NOPER: out<<"SmOperNode"; break; + case NALIGN: out<<"SmAlignNode"; break; + case NATTRIBUT: out<<"SmAttributNode"; break; + case NFONT: out<<"SmFontNode"; break; + case NUNHOR: out<<"SmUnHorNode"; break; + case NBINHOR: out<<"SmBinHorNode"; break; + case NBINVER: out<<"SmBinVerNode"; break; + case NBINDIAGONAL: out<<"SmBinDiagonalNode"; break; + case NSUBSUP: out<<"SmSubSupNode"; break; + case NMATRIX: out<<"SmMatrixNode"; break; + case NPLACE: out<<"SmPlaceNode"; break; + case NTEXT: + out<<"SmTextNode: "; + out<< rtl::OUStringToOString(((SmTextNode*)this)->GetText(), RTL_TEXTENCODING_UTF8).getStr(); + break; + case NSPECIAL: out<<"SmSpecialNode"; break; + case NGLYPH_SPECIAL: out<<"SmGlyphSpecialNode"; break; + case NMATH: + out<<"SmMathSymbolNode: "; + out<< rtl::OUStringToOString(((SmMathSymbolNode*)this)->GetText(), RTL_TEXTENCODING_UTF8).getStr(); + break; + case NBLANK: out<<"SmBlankNode"; break; + case NERROR: out<<"SmErrorNode"; break; + case NLINE: out<<"SmLineNode"; break; + case NEXPRESSION: out<<"SmExpressionNode"; break; + case NPOLYLINE: out<<"SmPolyLineNode"; break; + case NROOT: out<<"SmRootNode"; break; + case NROOTSYMBOL: out<<"SmRootSymbolNode"; break; + case NRECTANGLE: out<<"SmRectangleNode"; break; + case NVERTICAL_BRACE: out<<"SmVerticalBraceNode"; break; + default: + out<<"Unknown Node"; + } + out<<"\""; + if(IsSelected()) + out<<", style=dashed"; + out<<"];"<<std::endl; + + //Dump subnodes + int myid = id; + const SmNode *pNode; + USHORT nSize = GetNumSubNodes(); + for (USHORT i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->DumpAsDot(out, NULL, i, ++id, myid); + + //If this is the root end the file + if( number == -1 ) + out<<"}"<<std::endl; +} +#endif /* DEBUG_ENABLE_DUMPASDOT */ + +long SmNode::GetFormulaBaseline() const +{ + OSL_FAIL( "This dummy implementation should not have been called." ); + return 0; +} + +/////////////////////////////////////////////////////////////////////////// + +SmStructureNode::SmStructureNode( const SmStructureNode &rNode ) : + SmNode( rNode.GetType(), rNode.GetToken() ) +{ + sal_uLong i; + for (i = 0; i < aSubNodes.size(); i++) + delete aSubNodes[i]; + aSubNodes.resize(0); + + sal_uLong nSize = rNode.aSubNodes.size(); + aSubNodes.resize( nSize ); + for (i = 0; i < nSize; ++i) + { + SmNode *pNode = rNode.aSubNodes[i]; + aSubNodes[i] = pNode ? new SmNode( *pNode ) : 0; + } + ClaimPaternity(); +} + + +SmStructureNode::~SmStructureNode() +{ + SmNode *pNode; + + for (sal_uInt16 i = 0; i < GetNumSubNodes(); i++) + if (NULL != (pNode = GetSubNode(i))) + delete pNode; +} + + +SmStructureNode & SmStructureNode::operator = ( const SmStructureNode &rNode ) +{ + SmNode::operator = ( rNode ); + + sal_uLong i; + for (i = 0; i < aSubNodes.size(); i++) + delete aSubNodes[i]; + aSubNodes.resize(0); + + sal_uLong nSize = rNode.aSubNodes.size(); + aSubNodes.resize( nSize ); + for (i = 0; i < nSize; ++i) + { + SmNode *pNode = rNode.aSubNodes[i]; + aSubNodes[i] = pNode ? new SmNode( *pNode ) : 0; + } + + ClaimPaternity(); + + return *this; +} + + +void SmStructureNode::SetSubNodes(SmNode *pFirst, SmNode *pSecond, SmNode *pThird) +{ + size_t nSize = pThird ? 3 : (pSecond ? 2 : (pFirst ? 1 : 0)); + aSubNodes.resize( nSize ); + if (pFirst) + aSubNodes[0] = pFirst; + if (pSecond) + aSubNodes[1] = pSecond; + if (pThird) + aSubNodes[2] = pThird; + + ClaimPaternity(); +} + + +void SmStructureNode::SetSubNodes(const SmNodeArray &rNodeArray) +{ + aSubNodes = rNodeArray; + ClaimPaternity(); +} + + +bool SmStructureNode::IsVisible() const +{ + return false; +} + + +sal_uInt16 SmStructureNode::GetNumSubNodes() const +{ + return (sal_uInt16) aSubNodes.size(); +} + + +SmNode * SmStructureNode::GetSubNode(sal_uInt16 nIndex) +{ + return aSubNodes[nIndex]; +} + + +void SmStructureNode::GetAccessibleText( String &rText ) const +{ + sal_uInt16 nNodes = GetNumSubNodes(); + for (sal_uInt16 i = 0; i < nNodes; ++i) + { + const SmNode *pNode = ((SmStructureNode *) this)->GetSubNode(i); + if (pNode) + { + if (pNode->IsVisible()) + ((SmStructureNode *) pNode)->nAccIndex = rText.Len(); + pNode->GetAccessibleText( rText ); + } + } +} + +/////////////////////////////////////////////////////////////////////////// + + +bool SmVisibleNode::IsVisible() const +{ + return true; +} + + +sal_uInt16 SmVisibleNode::GetNumSubNodes() const +{ + return 0; +} + + +SmNode * SmVisibleNode::GetSubNode(sal_uInt16 /*nIndex*/) +{ + return NULL; +} + + +/////////////////////////////////////////////////////////////////////////// + +void SmGraphicNode::GetAccessibleText( String &rText ) const +{ + rText += GetToken().aText; +} + +/////////////////////////////////////////////////////////////////////////// + + +void SmExpressionNode::CreateTextFromNode(String &rText) +{ + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + if (nSize > 1) + rText.Append('{'); + for (sal_uInt16 i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + { + pNode->CreateTextFromNode(rText); + //Just a bit of foo to make unary +asd -asd +-asd -+asd look nice + if (pNode->GetType() == NMATH) + if ((nSize != 2) || ((rText.GetChar(rText.Len()-1) != '+') && + (rText.GetChar(rText.Len()-1) != '-'))) + rText.Append(' '); + } + + if (nSize > 1) + { + rText.EraseTrailingChars(); + APPEND(rText,"} "); + } +} + + +/////////////////////////////////////////////////////////////////////////// + +void SmTableNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) + // arranges all subnodes in one column +{ + Point rPosition; + + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + + // make distance depend on font size + long nDist = +(rFormat.GetDistance(DIS_VERTICAL) + * GetFont().GetSize().Height()) / 100L; + + if (nSize < 1) + return; + + // arrange subnodes and get maximum width of them + long nMaxWidth = 0, + nTmp; + sal_uInt16 i; + for (i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + { pNode->Arrange(rDev, rFormat); + if ((nTmp = pNode->GetItalicWidth()) > nMaxWidth) + nMaxWidth = nTmp; + } + + Point aPos; + SmRect::operator = (SmRect(nMaxWidth, 1)); + for (i = 0; i < nSize; i++) + { if (NULL != (pNode = GetSubNode(i))) + { const SmRect &rNodeRect = pNode->GetRect(); + const SmNode *pCoNode = pNode->GetLeftMost(); + RectHorAlign eHorAlign = pCoNode->GetRectHorAlign(); + + aPos = rNodeRect.AlignTo(*this, RP_BOTTOM, + eHorAlign, RVA_BASELINE); + if (i) + aPos.Y() += nDist; + pNode->MoveTo(aPos); + ExtendBy(rNodeRect, nSize > 1 ? RCP_NONE : RCP_ARG); + } + } + // #i972# + if (HasBaseline()) + nFormulaBaseline = GetBaseline(); + else + { + SmTmpDevice aTmpDev ((OutputDevice &) rDev, sal_True); + aTmpDev.SetFont(GetFont()); + + SmRect aRect = (SmRect(aTmpDev, &rFormat, C2S("a"), + GetFont().GetBorderWidth())); + nFormulaBaseline = GetAlignM(); + // move from middle position by constant - distance + // between middle and baseline for single letter + nFormulaBaseline += aRect.GetBaseline() - aRect.GetAlignM(); + } +} + + +SmNode * SmTableNode::GetLeftMost() +{ + return this; +} + + +long SmTableNode::GetFormulaBaseline() const +{ + return nFormulaBaseline; +} + + +/**************************************************************************/ + + +void SmLineNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) +{ + SmNode::Prepare(rFormat, rDocShell); + + //! wir verwenden hier den 'FNT_VARIABLE' Font, da er vom Ascent und Descent + //! ia besser zum Rest der Formel passt als der 'FNT_MATH' Font. + GetFont() = rFormat.GetFont(FNT_VARIABLE); + Flags() |= FLG_FONT; +} + + +/**************************************************************************/ + + +void SmLineNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) + // arranges all subnodes in one row with some extra space between +{ + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + sal_uInt16 i; + for (i = 0; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + pNode->Arrange(rDev, rFormat); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + if (nSize < 1) + { + // provide an empty rectangle with alignment parameters for the "current" + // font (in order to make "a^1 {}_2^3 a_4" work correct, that is, have the + // same sub-/supscript positions.) + //! be sure to use a character that has explicitly defined HiAttribut + //! line in rect.cxx such as 'a' in order to make 'vec a' look same to + //! 'vec {a}'. + SmRect::operator = (SmRect(aTmpDev, &rFormat, C2S("a"), + GetFont().GetBorderWidth())); + // make sure that the rectangle occupies (almost) no space + SetWidth(1); + SetItalicSpaces(0, 0); + return; + } + + // make distance depend on font size + long nDist = (rFormat.GetDistance(DIS_HORIZONTAL) * GetFont().GetSize().Height()) / 100L; + if (!IsUseExtraSpaces()) + nDist = 0; + + Point aPos; + // copy the first node into LineNode and extend by the others + if (NULL != (pNode = GetSubNode(0))) + SmRect::operator = (pNode->GetRect()); + + for (i = 1; i < nSize; i++) + if (NULL != (pNode = GetSubNode(i))) + { + aPos = pNode->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE); + + // add horizontal space to the left for each but the first sub node + aPos.X() += nDist; + + pNode->MoveTo(aPos); + ExtendBy( *pNode, RCP_XOR ); + } +} + + +/**************************************************************************/ + + +void SmExpressionNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) + // as 'SmLineNode::Arrange' but keeps alignment of leftmost subnode +{ + SmLineNode::Arrange(rDev, rFormat); + + // copy alignment of leftmost subnode if any + SmNode *pNode = GetLeftMost(); + if (pNode) + SetRectHorAlign(pNode->GetRectHorAlign(), false); +} + + +/**************************************************************************/ + + +void SmUnHorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + bool bIsPostfix = GetToken().eType == TFACT; + + SmNode *pOper = GetSubNode(bIsPostfix ? 1 : 0), + *pBody = GetSubNode(bIsPostfix ? 0 : 1); + OSL_ENSURE(pOper, "Sm: NULL pointer"); + OSL_ENSURE(pBody, "Sm: NULL pointer"); + + pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100)); + pOper->Arrange(rDev, rFormat); + pBody->Arrange(rDev, rFormat); + + Point aPos = pOper->AlignTo(*pBody, bIsPostfix ? RP_RIGHT : RP_LEFT, + RHA_CENTER, RVA_BASELINE); + // add a bit space between operator and argument + // (worst case -{1 over 2} where - and over have almost no space inbetween) + long nDelta = pOper->GetFont().GetSize().Height() / 20; + if (bIsPostfix) + aPos.X() += nDelta; + else + aPos.X() -= nDelta; + pOper->MoveTo(aPos); + + SmRect::operator = (*pBody); + long nOldBot = GetBottom(); + + ExtendBy(*pOper, RCP_XOR); + + // workaround for Bug 50865: "a^2 a^+2" have different baselines + // for exponents (if size of exponent is large enough) + SetBottom(nOldBot); +} + + +/**************************************************************************/ + + +void SmRootNode::GetHeightVerOffset(const SmRect &rRect, + long &rHeight, long &rVerOffset) const + // calculate height and vertical offset of root sign suitable for 'rRect' +{ + rVerOffset = (rRect.GetBottom() - rRect.GetAlignB()) / 2; + rHeight = rRect.GetHeight() - rVerOffset; + + OSL_ENSURE(rHeight >= 0, "Sm : Ooops..."); + OSL_ENSURE(rVerOffset >= 0, "Sm : Ooops..."); +} + + +Point SmRootNode::GetExtraPos(const SmRect &rRootSymbol, + const SmRect &rExtra) const +{ + const Size &rSymSize = rRootSymbol.GetSize(); + + Point aPos = rRootSymbol.GetTopLeft() + + Point((rSymSize.Width() * 70) / 100, + (rSymSize.Height() * 52) / 100); + + // from this calculate topleft edge of 'rExtra' + aPos.X() -= rExtra.GetWidth() + rExtra.GetItalicRightSpace(); + aPos.Y() -= rExtra.GetHeight(); + // if there's enough space move a bit less to the right + // examples: "nroot i a", "nroot j a" + // (it looks better if we don't use italic-spaces here) + long nX = rRootSymbol.GetLeft() + (rSymSize.Width() * 30) / 100; + if (aPos.X() > nX) + aPos.X() = nX; + + return aPos; +} + + +void SmRootNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + //! pExtra needs to have the smaller index than pRootSym in order to + //! not to get the root symbol but the pExtra when clicking on it in the + //! GraphicWindow. (That is because of the simplicity of the algorithm + //! that finds the node corresponding to a mouseclick in the window.) + SmNode *pExtra = GetSubNode(0), + *pRootSym = GetSubNode(1), + *pBody = GetSubNode(2); + OSL_ENSURE(pRootSym, "Sm: NULL pointer"); + OSL_ENSURE(pBody, "Sm: NULL pointer"); + + pBody->Arrange(rDev, rFormat); + + long nHeight, + nVerOffset; + GetHeightVerOffset(*pBody, nHeight, nVerOffset); + nHeight += rFormat.GetDistance(DIS_ROOT) + * GetFont().GetSize().Height() / 100L; + + // font specialist advised to change the width first + pRootSym->AdaptToY(rDev, nHeight); + pRootSym->AdaptToX(rDev, pBody->GetItalicWidth()); + + pRootSym->Arrange(rDev, rFormat); + + Point aPos = pRootSym->AlignTo(*pBody, RP_LEFT, RHA_CENTER, RVA_BASELINE); + //! overrride calulated vertical position + aPos.Y() = pRootSym->GetTop() + pBody->GetBottom() - pRootSym->GetBottom(); + aPos.Y() -= nVerOffset; + pRootSym->MoveTo(aPos); + + if (pExtra) + { pExtra->SetSize(Fraction(rFormat.GetRelSize(SIZ_INDEX), 100)); + pExtra->Arrange(rDev, rFormat); + + aPos = GetExtraPos(*pRootSym, *pExtra); + pExtra->MoveTo(aPos); + } + + SmRect::operator = (*pBody); + ExtendBy(*pRootSym, RCP_THIS); + if (pExtra) + ExtendBy(*pExtra, RCP_THIS, true); +} + + +void SmRootNode::CreateTextFromNode(String &rText) +{ + SmNode *pExtra = GetSubNode(0); + if (pExtra) + { + APPEND(rText,"nroot "); + pExtra->CreateTextFromNode(rText); + } + else + APPEND(rText,"sqrt "); + GetSubNode(2)->CreateTextFromNode(rText); +} + + +/**************************************************************************/ + + +void SmBinHorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + SmNode *pLeft = GetSubNode(0), + *pOper = GetSubNode(1), + *pRight = GetSubNode(2); + OSL_ENSURE(pLeft != NULL, "Sm: NULL pointer"); + OSL_ENSURE(pOper != NULL, "Sm: NULL pointer"); + OSL_ENSURE(pRight != NULL, "Sm: NULL pointer"); + + pOper->SetSize(Fraction (rFormat.GetRelSize(SIZ_OPERATOR), 100)); + + pLeft ->Arrange(rDev, rFormat); + pOper ->Arrange(rDev, rFormat); + pRight->Arrange(rDev, rFormat); + + const SmRect &rOpRect = pOper->GetRect(); + + long nDist = (rOpRect.GetWidth() * + rFormat.GetDistance(DIS_HORIZONTAL)) / 100L; + + SmRect::operator = (*pLeft); + + Point aPos; + aPos = pOper->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE); + aPos.X() += nDist; + pOper->MoveTo(aPos); + ExtendBy(*pOper, RCP_XOR); + + aPos = pRight->AlignTo(*this, RP_RIGHT, RHA_CENTER, RVA_BASELINE); + aPos.X() += nDist; + + pRight->MoveTo(aPos); + ExtendBy(*pRight, RCP_XOR); +} + + +/**************************************************************************/ + + +void SmBinVerNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + SmNode *pNum = GetSubNode(0), + *pLine = GetSubNode(1), + *pDenom = GetSubNode(2); + OSL_ENSURE(pNum, "Sm : NULL pointer"); + OSL_ENSURE(pLine, "Sm : NULL pointer"); + OSL_ENSURE(pDenom, "Sm : NULL pointer"); + + bool bIsTextmode = rFormat.IsTextmode(); + if (bIsTextmode) + { + Fraction aFraction(rFormat.GetRelSize(SIZ_INDEX), 100); + pNum ->SetSize(aFraction); + pLine ->SetSize(aFraction); + pDenom->SetSize(aFraction); + } + + pNum ->Arrange(rDev, rFormat); + pDenom->Arrange(rDev, rFormat); + + long nFontHeight = GetFont().GetSize().Height(), + nExtLen = nFontHeight * rFormat.GetDistance(DIS_FRACTION) / 100L, + nThick = nFontHeight * rFormat.GetDistance(DIS_STROKEWIDTH) / 100L, + nWidth = Max(pNum->GetItalicWidth(), pDenom->GetItalicWidth()), + nNumDist = bIsTextmode ? 0 : + nFontHeight * rFormat.GetDistance(DIS_NUMERATOR) / 100L, + nDenomDist = bIsTextmode ? 0 : + nFontHeight * rFormat.GetDistance(DIS_DENOMINATOR) / 100L; + + // font specialist advised to change the width first + pLine->AdaptToY(rDev, nThick); + pLine->AdaptToX(rDev, nWidth + 2 * nExtLen); + pLine->Arrange(rDev, rFormat); + + // get horizontal alignment for numerator + const SmNode *pLM = pNum->GetLeftMost(); + RectHorAlign eHorAlign = pLM->GetRectHorAlign(); + + // move numerator to its position + Point aPos = pNum->AlignTo(*pLine, RP_TOP, eHorAlign, RVA_BASELINE); + aPos.Y() -= nNumDist; + pNum->MoveTo(aPos); + + // get horizontal alignment for denominator + pLM = pDenom->GetLeftMost(); + eHorAlign = pLM->GetRectHorAlign(); + + // move denominator to its position + aPos = pDenom->AlignTo(*pLine, RP_BOTTOM, eHorAlign, RVA_BASELINE); + aPos.Y() += nDenomDist; + pDenom->MoveTo(aPos); + + SmRect::operator = (*pNum); + ExtendBy(*pDenom, RCP_NONE).ExtendBy(*pLine, RCP_NONE, pLine->GetCenterY()); +} + +void SmBinVerNode::CreateTextFromNode(String &rText) +{ + SmNode *pNum = GetSubNode(0), + *pDenom = GetSubNode(2); + pNum->CreateTextFromNode(rText); + APPEND(rText,"over "); + pDenom->CreateTextFromNode(rText); +} + + +SmNode * SmBinVerNode::GetLeftMost() +{ + return this; +} + + +/**************************************************************************/ + + +double Det(const Point &rHeading1, const Point &rHeading2) + // gibt den Wert der durch die beiden Punkte gebildeten Determinante + // zurueck +{ + return rHeading1.X() * rHeading2.Y() - rHeading1.Y() * rHeading2.X(); +} + + +bool IsPointInLine(const Point &rPoint1, + const Point &rPoint2, const Point &rHeading2) + // ergibt true genau dann, wenn der Punkt 'rPoint1' zu der Gerade gehoert die + // durch den Punkt 'rPoint2' geht und den Richtungsvektor 'rHeading2' hat +{ + OSL_ENSURE(rHeading2 != Point(), "Sm : 0 vector"); + + bool bRes = false; + const double eps = 5.0 * DBL_EPSILON; + + double fLambda; + if (labs(rHeading2.X()) > labs(rHeading2.Y())) + { + fLambda = (rPoint1.X() - rPoint2.X()) / (double) rHeading2.X(); + bRes = fabs(rPoint1.Y() - (rPoint2.Y() + fLambda * rHeading2.Y())) < eps; + } + else + { + fLambda = (rPoint1.Y() - rPoint2.Y()) / (double) rHeading2.Y(); + bRes = fabs(rPoint1.X() - (rPoint2.X() + fLambda * rHeading2.X())) < eps; + } + + return bRes; +} + + +sal_uInt16 GetLineIntersectionPoint(Point &rResult, + const Point& rPoint1, const Point &rHeading1, + const Point& rPoint2, const Point &rHeading2) +{ + OSL_ENSURE(rHeading1 != Point(), "Sm : 0 vector"); + OSL_ENSURE(rHeading2 != Point(), "Sm : 0 vector"); + + sal_uInt16 nRes = 1; + const double eps = 5.0 * DBL_EPSILON; + + // sind die Richtumgsvektoren linear abhaengig ? + double fDet = Det(rHeading1, rHeading2); + if (fabs(fDet) < eps) + { + nRes = IsPointInLine(rPoint1, rPoint2, rHeading2) ? USHRT_MAX : 0; + rResult = nRes ? rPoint1 : Point(); + } + else + { + // hier achten wir nicht auf Rechengenauigkeit + // (das wuerde aufwendiger und lohnt sich hier kaum) + double fLambda = ( (rPoint1.Y() - rPoint2.Y()) * rHeading2.X() + - (rPoint1.X() - rPoint2.X()) * rHeading2.Y()) + / fDet; + rResult = Point(rPoint1.X() + (long) (fLambda * rHeading1.X()), + rPoint1.Y() + (long) (fLambda * rHeading1.Y())); + } + + return nRes; +} + + + +SmBinDiagonalNode::SmBinDiagonalNode(const SmToken &rNodeToken) +: SmStructureNode(NBINDIAGONAL, rNodeToken) +{ + bAscending = false; + SetNumSubNodes(3); +} + + +void SmBinDiagonalNode::GetOperPosSize(Point &rPos, Size &rSize, + const Point &rDiagPoint, double fAngleDeg) const + // gibt die Position und Groesse fuer den Diagonalstrich zurueck. + // Vor.: das SmRect des Nodes gibt die Begrenzung vor(!), muss also selbst + // bereits bekannt sein. + +{ + const double fPi = 3.1415926535897932384626433; + double fAngleRad = fAngleDeg / 180.0 * fPi; + long nRectLeft = GetItalicLeft(), + nRectRight = GetItalicRight(), + nRectTop = GetTop(), + nRectBottom = GetBottom(); + Point aRightHdg (100, 0), + aDownHdg (0, 100), + aDiagHdg ( (long)(100.0 * cos(fAngleRad)), + (long)(-100.0 * sin(fAngleRad)) ); + + long nLeft, nRight, nTop, nBottom; // Raender des Rechtecks fuer die + // Diagonale + Point aPoint; + if (IsAscending()) + { + // + // obere rechte Ecke bestimmen + // + GetLineIntersectionPoint(aPoint, + Point(nRectLeft, nRectTop), aRightHdg, + rDiagPoint, aDiagHdg); + // + // gibt es einen Schnittpunkt mit dem oberen Rand ? + if (aPoint.X() <= nRectRight) + { + nRight = aPoint.X(); + nTop = nRectTop; + } + else + { + // es muss einen Schnittpunkt mit dem rechten Rand geben! + GetLineIntersectionPoint(aPoint, + Point(nRectRight, nRectTop), aDownHdg, + rDiagPoint, aDiagHdg); + + nRight = nRectRight; + nTop = aPoint.Y(); + } + + // + // untere linke Ecke bestimmen + // + GetLineIntersectionPoint(aPoint, + Point(nRectLeft, nRectBottom), aRightHdg, + rDiagPoint, aDiagHdg); + // + // gibt es einen Schnittpunkt mit dem unteren Rand ? + if (aPoint.X() >= nRectLeft) + { + nLeft = aPoint.X(); + nBottom = nRectBottom; + } + else + { + // es muss einen Schnittpunkt mit dem linken Rand geben! + GetLineIntersectionPoint(aPoint, + Point(nRectLeft, nRectTop), aDownHdg, + rDiagPoint, aDiagHdg); + + nLeft = nRectLeft; + nBottom = aPoint.Y(); + } + } + else + { + // + // obere linke Ecke bestimmen + // + GetLineIntersectionPoint(aPoint, + Point(nRectLeft, nRectTop), aRightHdg, + rDiagPoint, aDiagHdg); + // + // gibt es einen Schnittpunkt mit dem oberen Rand ? + if (aPoint.X() >= nRectLeft) + { + nLeft = aPoint.X(); + nTop = nRectTop; + } + else + { + // es muss einen Schnittpunkt mit dem linken Rand geben! + GetLineIntersectionPoint(aPoint, + Point(nRectLeft, nRectTop), aDownHdg, + rDiagPoint, aDiagHdg); + + nLeft = nRectLeft; + nTop = aPoint.Y(); + } + + // + // untere rechte Ecke bestimmen + // + GetLineIntersectionPoint(aPoint, + Point(nRectLeft, nRectBottom), aRightHdg, + rDiagPoint, aDiagHdg); + // + // gibt es einen Schnittpunkt mit dem unteren Rand ? + if (aPoint.X() <= nRectRight) + { + nRight = aPoint.X(); + nBottom = nRectBottom; + } + else + { + // es muss einen Schnittpunkt mit dem rechten Rand geben! + GetLineIntersectionPoint(aPoint, + Point(nRectRight, nRectTop), aDownHdg, + rDiagPoint, aDiagHdg); + + nRight = nRectRight; + nBottom = aPoint.Y(); + } + } + + rSize = Size(nRight - nLeft + 1, nBottom - nTop + 1); + rPos.X() = nLeft; + rPos.Y() = nTop; +} + + +void SmBinDiagonalNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + //! die beiden Argumente muessen in den Subnodes vor dem Operator kommen, + //! damit das anklicken im GraphicWindow den FormulaCursor richtig setzt + //! (vgl SmRootNode) + SmNode *pLeft = GetSubNode(0), + *pRight = GetSubNode(1); + OSL_ENSURE(pLeft, "Sm : NULL pointer"); + OSL_ENSURE(pRight, "Sm : NULL pointer"); + + OSL_ENSURE(GetSubNode(2)->GetType() == NPOLYLINE, "Sm : wrong node type"); + SmPolyLineNode *pOper = (SmPolyLineNode *) GetSubNode(2); + OSL_ENSURE(pOper, "Sm : NULL pointer"); + + //! some routines being called extract some info from the OutputDevice's + //! font (eg the space to be used for borders OR the font name(!!)). + //! Thus the font should reflect the needs and has to be set! + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + pLeft->Arrange(aTmpDev, rFormat); + pRight->Arrange(aTmpDev, rFormat); + + // implizit die Weite (incl Rand) des Diagonalstrichs ermitteln + pOper->Arrange(aTmpDev, rFormat); + + long nDelta = pOper->GetWidth() * 8 / 10; + + // TopLeft Position vom rechten Argument ermitteln + Point aPos; + aPos.X() = pLeft->GetItalicRight() + nDelta + pRight->GetItalicLeftSpace(); + if (IsAscending()) + aPos.Y() = pLeft->GetBottom() + nDelta; + else + aPos.Y() = pLeft->GetTop() - nDelta - pRight->GetHeight(); + + pRight->MoveTo(aPos); + + // neue Baseline bestimmen + long nTmpBaseline = IsAscending() ? (pLeft->GetBottom() + pRight->GetTop()) / 2 + : (pLeft->GetTop() + pRight->GetBottom()) / 2; + Point aLogCenter ((pLeft->GetItalicRight() + pRight->GetItalicLeft()) / 2, + nTmpBaseline); + + SmRect::operator = (*pLeft); + ExtendBy(*pRight, RCP_NONE); + + + // Position und Groesse des Diagonalstrich ermitteln + Size aTmpSize; + GetOperPosSize(aPos, aTmpSize, aLogCenter, IsAscending() ? 60.0 : -60.0); + + // font specialist advised to change the width first + pOper->AdaptToY(aTmpDev, aTmpSize.Height()); + pOper->AdaptToX(aTmpDev, aTmpSize.Width()); + // und diese wirksam machen + pOper->Arrange(aTmpDev, rFormat); + + pOper->MoveTo(aPos); + + ExtendBy(*pOper, RCP_NONE, nTmpBaseline); +} + + +/**************************************************************************/ + + +void SmSubSupNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + OSL_ENSURE(GetNumSubNodes() == 1 + SUBSUP_NUM_ENTRIES, + "Sm: wrong number of subnodes"); + + SmNode *pBody = GetBody(); + OSL_ENSURE(pBody, "Sm: NULL pointer"); + + long nOrigHeight = pBody->GetFont().GetSize().Height(); + + pBody->Arrange(rDev, rFormat); + + const SmRect &rBodyRect = pBody->GetRect(); + SmRect::operator = (rBodyRect); + + // line that separates sub- and supscript rectangles + long nDelimLine = SmFromTo(GetAlignB(), GetAlignT(), 0.4); + + Point aPos; + long nDelta, nDist; + + // iterate over all possible sub-/supscripts + SmRect aTmpRect (rBodyRect); + for (int i = 0; i < SUBSUP_NUM_ENTRIES; i++) + { SmSubSup eSubSup = (SmSubSup) i; // cast + SmNode *pSubSup = GetSubSup(eSubSup); + + if (!pSubSup) + continue; + + // switch position of limits if we are in textmode + if (rFormat.IsTextmode() && (GetToken().nGroup & TGLIMIT)) + switch (eSubSup) + { case CSUB: eSubSup = RSUB; break; + case CSUP: eSubSup = RSUP; break; + default: + break; + } + + // prevent sub-/supscripts from diminishing in size + // (as would be in "a_{1_{2_{3_4}}}") + if (GetFont().GetSize().Height() > rFormat.GetBaseSize().Height() / 3) + { + sal_uInt16 nIndex = (eSubSup == CSUB || eSubSup == CSUP) ? + SIZ_LIMITS : SIZ_INDEX; + Fraction aFraction ( rFormat.GetRelSize(nIndex), 100 ); + pSubSup->SetSize(aFraction); + } + + pSubSup->Arrange(rDev, rFormat); + + bool bIsTextmode = rFormat.IsTextmode(); + nDist = 0; + + //! be sure that CSUB, CSUP are handled before the other cases! + switch (eSubSup) + { case RSUB : + case LSUB : + if (!bIsTextmode) + nDist = nOrigHeight + * rFormat.GetDistance(DIS_SUBSCRIPT) / 100L; + aPos = pSubSup->GetRect().AlignTo(aTmpRect, + eSubSup == LSUB ? RP_LEFT : RP_RIGHT, + RHA_CENTER, RVA_BOTTOM); + aPos.Y() += nDist; + nDelta = nDelimLine - aPos.Y(); + if (nDelta > 0) + aPos.Y() += nDelta; + break; + case RSUP : + case LSUP : + if (!bIsTextmode) + nDist = nOrigHeight + * rFormat.GetDistance(DIS_SUPERSCRIPT) / 100L; + aPos = pSubSup->GetRect().AlignTo(aTmpRect, + eSubSup == LSUP ? RP_LEFT : RP_RIGHT, + RHA_CENTER, RVA_TOP); + aPos.Y() -= nDist; + nDelta = aPos.Y() + pSubSup->GetHeight() - nDelimLine; + if (nDelta > 0) + aPos.Y() -= nDelta; + break; + case CSUB : + if (!bIsTextmode) + nDist = nOrigHeight + * rFormat.GetDistance(DIS_LOWERLIMIT) / 100L; + aPos = pSubSup->GetRect().AlignTo(rBodyRect, RP_BOTTOM, + RHA_CENTER, RVA_BASELINE); + aPos.Y() += nDist; + break; + case CSUP : + if (!bIsTextmode) + nDist = nOrigHeight + * rFormat.GetDistance(DIS_UPPERLIMIT) / 100L; + aPos = pSubSup->GetRect().AlignTo(rBodyRect, RP_TOP, + RHA_CENTER, RVA_BASELINE); + aPos.Y() -= nDist; + break; + default : + OSL_FAIL("Sm: unknown case"); + break; + } + + pSubSup->MoveTo(aPos); + ExtendBy(*pSubSup, RCP_THIS, true); + + // update rectangle to which RSUB, RSUP, LSUB, LSUP + // will be aligned to + if (eSubSup == CSUB || eSubSup == CSUP) + aTmpRect = *this; + } +} + +void SmSubSupNode::CreateTextFromNode(String &rText) +{ + SmNode *pNode; + GetSubNode(0)->CreateTextFromNode(rText); + + if (NULL != (pNode = GetSubNode(LSUB+1))) + { + APPEND(rText,"lsub "); + pNode->CreateTextFromNode(rText); + } + if (NULL != (pNode = GetSubNode(LSUP+1))) + { + APPEND(rText,"lsup "); + pNode->CreateTextFromNode(rText); + } + if (NULL != (pNode = GetSubNode(CSUB+1))) + { + APPEND(rText,"csub "); + pNode->CreateTextFromNode(rText); + } + if (NULL != (pNode = GetSubNode(CSUP+1))) + { + APPEND(rText,"csup "); + pNode->CreateTextFromNode(rText); + } + if (NULL != (pNode = GetSubNode(RSUB+1))) + { + rText.EraseTrailingChars(); + rText.Append('_'); + pNode->CreateTextFromNode(rText); + } + if (NULL != (pNode = GetSubNode(RSUP+1))) + { + rText.EraseTrailingChars(); + rText.Append('^'); + pNode->CreateTextFromNode(rText); + } +} + + +/**************************************************************************/ + +void SmBraceNode::CreateTextFromNode(String &rText) +{ + if (GetScaleMode() == SCALE_HEIGHT) + APPEND(rText,"left "); + { + String aStr; + GetSubNode(0)->CreateTextFromNode(aStr); + aStr.EraseLeadingAndTrailingChars(); + aStr.EraseLeadingChars('\\'); + if (aStr.Len()) + { + if (aStr.EqualsAscii("divides")) + APPEND(rText,"lline"); + else if (aStr.EqualsAscii("parallel")) + APPEND(rText,"ldline"); + else if (aStr.EqualsAscii("<")) + APPEND(rText,"langle"); + else + rText.Append(aStr); + rText.Append(' '); + } + else + APPEND(rText,"none "); + } + GetSubNode(1)->CreateTextFromNode(rText); + if (GetScaleMode() == SCALE_HEIGHT) + APPEND(rText,"right "); + { + String aStr; + GetSubNode(2)->CreateTextFromNode(aStr); + aStr.EraseLeadingAndTrailingChars(); + aStr.EraseLeadingChars('\\'); + if (aStr.Len()) + { + if (aStr.EqualsAscii("divides")) + APPEND(rText,"rline"); + else if (aStr.EqualsAscii("parallel")) + APPEND(rText,"rdline"); + else if (aStr.EqualsAscii(">")) + APPEND(rText,"rangle"); + else + rText.Append(aStr); + rText.Append(' '); + } + else + APPEND(rText,"none "); + } + rText.Append(' '); + +} + +void SmBraceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + SmNode *pLeft = GetSubNode(0), + *pBody = GetSubNode(1), + *pRight = GetSubNode(2); + OSL_ENSURE(pLeft, "Sm: NULL pointer"); + OSL_ENSURE(pBody, "Sm: NULL pointer"); + OSL_ENSURE(pRight, "Sm: NULL pointer"); + + pBody->Arrange(rDev, rFormat); + + bool bIsScaleNormal = rFormat.IsScaleNormalBrackets(), + bScale = pBody->GetHeight() > 0 && + (GetScaleMode() == SCALE_HEIGHT || bIsScaleNormal), + bIsABS = GetToken().eType == TABS; + + long nFaceHeight = GetFont().GetSize().Height(); + + // Uebergroesse in % ermitteln + sal_uInt16 nPerc = 0; + if (!bIsABS && bScale) + { // im Fall von Klammern mit Uebergroesse... + sal_uInt16 nIndex = GetScaleMode() == SCALE_HEIGHT ? + DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE; + nPerc = rFormat.GetDistance(nIndex); + } + + // ermitteln der Hoehe fuer die Klammern + long nBraceHeight; + if (bScale) + { + nBraceHeight = pBody->GetType() == NBRACEBODY ? + ((SmBracebodyNode *) pBody)->GetBodyHeight() + : pBody->GetHeight(); + nBraceHeight += 2 * (nBraceHeight * nPerc / 100L); + } + else + nBraceHeight = nFaceHeight; + + // Abstand zum Argument + nPerc = bIsABS ? 0 : rFormat.GetDistance(DIS_BRACKETSPACE); + long nDist = nFaceHeight * nPerc / 100L; + + // sofern erwuenscht skalieren der Klammern auf die gewuenschte Groesse + if (bScale) + { + Size aTmpSize (pLeft->GetFont().GetSize()); + OSL_ENSURE(pRight->GetFont().GetSize() == aTmpSize, + "Sm : different font sizes"); + aTmpSize.Width() = Min((long) nBraceHeight * 60L / 100L, + rFormat.GetBaseSize().Height() * 3L / 2L); + // correction factor since change from StarMath to OpenSymbol font + // because of the different font width in the FontMetric + aTmpSize.Width() *= 182; + aTmpSize.Width() /= 267; + + xub_Unicode cChar = pLeft->GetToken().cMathChar; + if (cChar != MS_LINE && cChar != MS_DLINE) + pLeft ->GetFont().SetSize(aTmpSize); + + cChar = pRight->GetToken().cMathChar; + if (cChar != MS_LINE && cChar != MS_DLINE) + pRight->GetFont().SetSize(aTmpSize); + + pLeft ->AdaptToY(rDev, nBraceHeight); + pRight->AdaptToY(rDev, nBraceHeight); + } + + pLeft ->Arrange(rDev, rFormat); + pRight->Arrange(rDev, rFormat); + + // damit auch "\(a\) - (a) - left ( a right )" vernuenftig aussieht + RectVerAlign eVerAlign = bScale ? RVA_CENTERY : RVA_BASELINE; + + Point aPos; + aPos = pLeft->AlignTo(*pBody, RP_LEFT, RHA_CENTER, eVerAlign); + aPos.X() -= nDist; + pLeft->MoveTo(aPos); + + aPos = pRight->AlignTo(*pBody, RP_RIGHT, RHA_CENTER, eVerAlign); + aPos.X() += nDist; + pRight->MoveTo(aPos); + + SmRect::operator = (*pBody); + ExtendBy(*pLeft, RCP_THIS).ExtendBy(*pRight, RCP_THIS); +} + + +/**************************************************************************/ + + +void SmBracebodyNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + sal_uInt16 nNumSubNodes = GetNumSubNodes(); + if (nNumSubNodes == 0) + return; + + // arrange arguments + sal_uInt16 i; + for (i = 0; i < nNumSubNodes; i += 2) + GetSubNode(i)->Arrange(rDev, rFormat); + + // build reference rectangle with necessary info for vertical alignment + SmRect aRefRect (*GetSubNode(0)); + for (i = 0; i < nNumSubNodes; i += 2) + { + SmRect aTmpRect (*GetSubNode(i)); + Point aPos = aTmpRect.AlignTo(aRefRect, RP_RIGHT, RHA_CENTER, RVA_BASELINE); + aTmpRect.MoveTo(aPos); + aRefRect.ExtendBy(aTmpRect, RCP_XOR); + } + + nBodyHeight = aRefRect.GetHeight(); + + // scale separators to required height and arrange them + bool bScale = GetScaleMode() == SCALE_HEIGHT || rFormat.IsScaleNormalBrackets(); + long nHeight = bScale ? aRefRect.GetHeight() : GetFont().GetSize().Height(); + sal_uInt16 nIndex = GetScaleMode() == SCALE_HEIGHT ? + DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE; + sal_uInt16 nPerc = rFormat.GetDistance(nIndex); + if (bScale) + nHeight += 2 * (nHeight * nPerc / 100L); + for (i = 1; i < nNumSubNodes; i += 2) + { + SmNode *pNode = GetSubNode(i); + pNode->AdaptToY(rDev, nHeight); + pNode->Arrange(rDev, rFormat); + } + + // horizontal distance between argument and brackets or separators + long nDist = GetFont().GetSize().Height() + * rFormat.GetDistance(DIS_BRACKETSPACE) / 100L; + + SmNode *pLeft = GetSubNode(0); + SmRect::operator = (*pLeft); + for (i = 1; i < nNumSubNodes; i++) + { + bool bIsSeparator = i % 2 != 0; + RectVerAlign eVerAlign = bIsSeparator ? RVA_CENTERY : RVA_BASELINE; + + SmNode *pRight = GetSubNode(i); + Point aPosX = pRight->AlignTo(*pLeft, RP_RIGHT, RHA_CENTER, eVerAlign), + aPosY = pRight->AlignTo(aRefRect, RP_RIGHT, RHA_CENTER, eVerAlign); + aPosX.X() += nDist; + + pRight->MoveTo(Point(aPosX.X(), aPosY.Y())); + ExtendBy(*pRight, bIsSeparator ? RCP_THIS : RCP_XOR); + + pLeft = pRight; + } +} + + +/**************************************************************************/ + + +void SmVerticalBraceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + SmNode *pBody = GetSubNode(0), + *pBrace = GetSubNode(1), + *pScript = GetSubNode(2); + OSL_ENSURE(pBody, "Sm: NULL pointer!"); + OSL_ENSURE(pBrace, "Sm: NULL pointer!"); + OSL_ENSURE(pScript, "Sm: NULL pointer!"); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + pBody->Arrange(aTmpDev, rFormat); + + // Groesse wie bei Grenzen fuer diesen Teil + pScript->SetSize( Fraction( rFormat.GetRelSize(SIZ_LIMITS), 100 ) ); + // etwas hoehere Klammern als normal + pBrace ->SetSize( Fraction(3, 2) ); + + long nItalicWidth = pBody->GetItalicWidth(); + if (nItalicWidth > 0) + pBrace->AdaptToX(aTmpDev, nItalicWidth); + + pBrace ->Arrange(aTmpDev, rFormat); + pScript->Arrange(aTmpDev, rFormat); + + // die relativen Position und die Abstaende zueinander bestimmen + RectPos eRectPos; + long nFontHeight = pBody->GetFont().GetSize().Height(); + long nDistBody = nFontHeight * rFormat.GetDistance(DIS_ORNAMENTSIZE), + nDistScript = nFontHeight; + if (GetToken().eType == TOVERBRACE) + { + eRectPos = RP_TOP; + nDistBody = - nDistBody; + nDistScript *= - rFormat.GetDistance(DIS_UPPERLIMIT); + } + else // TUNDERBRACE + { + eRectPos = RP_BOTTOM; + nDistScript *= + rFormat.GetDistance(DIS_LOWERLIMIT); + } + nDistBody /= 100L; + nDistScript /= 100L; + + Point aPos = pBrace->AlignTo(*pBody, eRectPos, RHA_CENTER, RVA_BASELINE); + aPos.Y() += nDistBody; + pBrace->MoveTo(aPos); + + aPos = pScript->AlignTo(*pBrace, eRectPos, RHA_CENTER, RVA_BASELINE); + aPos.Y() += nDistScript; + pScript->MoveTo(aPos); + + SmRect::operator = (*pBody); + ExtendBy(*pBrace, RCP_THIS).ExtendBy(*pScript, RCP_THIS); +} + + +/**************************************************************************/ + + +SmNode * SmOperNode::GetSymbol() +{ + SmNode *pNode = GetSubNode(0); + OSL_ENSURE(pNode, "Sm: NULL pointer!"); + + if (pNode->GetType() == NSUBSUP) + pNode = ((SmSubSupNode *) pNode)->GetBody(); + + OSL_ENSURE(pNode, "Sm: NULL pointer!"); + return pNode; +} + + +long SmOperNode::CalcSymbolHeight(const SmNode &rSymbol, + const SmFormat &rFormat) const + // returns the font height to be used for operator-symbol +{ + long nHeight = GetFont().GetSize().Height(); + + SmTokenType eTmpType = GetToken().eType; + if (eTmpType == TLIM || eTmpType == TLIMINF || eTmpType == TLIMSUP) + return nHeight; + + if (!rFormat.IsTextmode()) + { + // set minimum size () + nHeight += (nHeight * 20L) / 100L; + + nHeight += nHeight + * rFormat.GetDistance(DIS_OPERATORSIZE) / 100L; + nHeight = nHeight * 686L / 845L; + } + + // correct user-defined symbols to match height of sum from used font + if (rSymbol.GetToken().eType == TSPECIAL) + nHeight = nHeight * 845L / 686L; + + return nHeight; +} + + +void SmOperNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + SmNode *pOper = GetSubNode(0); + SmNode *pBody = GetSubNode(1); + + OSL_ENSURE(pOper, "Sm: missing subnode"); + OSL_ENSURE(pBody, "Sm: missing subnode"); + + SmNode *pSymbol = GetSymbol(); + pSymbol->SetSize(Fraction(CalcSymbolHeight(*pSymbol, rFormat), + pSymbol->GetFont().GetSize().Height())); + + pBody->Arrange(rDev, rFormat); + pOper->Arrange(rDev, rFormat); + + long nOrigHeight = GetFont().GetSize().Height(), + nDist = nOrigHeight + * rFormat.GetDistance(DIS_OPERATORSPACE) / 100L; + + Point aPos = pOper->AlignTo(*pBody, RP_LEFT, RHA_CENTER, /*RVA_CENTERY*/RVA_MID); + aPos.X() -= nDist; + pOper->MoveTo(aPos); + + SmRect::operator = (*pBody); + ExtendBy(*pOper, RCP_THIS); +} + + +/**************************************************************************/ + + +void SmAlignNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) + // setzt im ganzen subtree (incl aktuellem node) das alignment +{ + OSL_ENSURE(GetNumSubNodes() > 0, "Sm: missing subnode"); + + SmNode *pNode = GetSubNode(0); + + RectHorAlign eHorAlign = RHA_CENTER; + switch (GetToken().eType) + { + case TALIGNL: eHorAlign = RHA_LEFT; break; + case TALIGNC: eHorAlign = RHA_CENTER; break; + case TALIGNR: eHorAlign = RHA_RIGHT; break; + default: + break; + } + SetRectHorAlign(eHorAlign); + + pNode->Arrange(rDev, rFormat); + + SmRect::operator = (pNode->GetRect()); +} + + +/**************************************************************************/ + + +void SmAttributNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + SmNode *pAttr = GetSubNode(0), + *pBody = GetSubNode(1); + OSL_ENSURE(pBody, "Sm: body missing"); + OSL_ENSURE(pAttr, "Sm: attribute missing"); + + pBody->Arrange(rDev, rFormat); + + if (GetScaleMode() == SCALE_WIDTH) + pAttr->AdaptToX(rDev, pBody->GetItalicWidth()); + pAttr->Arrange(rDev, rFormat); + + // get relative position of attribut + RectVerAlign eVerAlign; + long nDist = 0; + switch (GetToken().eType) + { case TUNDERLINE : + eVerAlign = RVA_ATTRIBUT_LO; + break; + case TOVERSTRIKE : + eVerAlign = RVA_ATTRIBUT_MID; + break; + default : + eVerAlign = RVA_ATTRIBUT_HI; + if (pBody->GetType() == NATTRIBUT) + nDist = GetFont().GetSize().Height() + * rFormat.GetDistance(DIS_ORNAMENTSPACE) / 100L; + } + Point aPos = pAttr->AlignTo(*pBody, RP_ATTRIBUT, RHA_CENTER, eVerAlign); + aPos.Y() -= nDist; + pAttr->MoveTo(aPos); + + SmRect::operator = (*pBody); + ExtendBy(*pAttr, RCP_THIS, true); +} + + +/**************************************************************************/ + + + + +void SmFontNode::CreateTextFromNode(String &rText) +{ + switch (GetToken().eType) + { + case TBOLD: + APPEND(rText,"bold "); + break; + case TNBOLD: + APPEND(rText,"nbold "); + break; + case TITALIC: + APPEND(rText,"italic "); + break; + case TNITALIC: + APPEND(rText,"nitalic "); + break; + case TPHANTOM: + APPEND(rText,"phantom "); + break; + case TSIZE: + { + APPEND(rText,"size "); + switch (nSizeType) + { + case FNTSIZ_PLUS: + rText.Append('+'); + break; + case FNTSIZ_MINUS: + rText.Append('-'); + break; + case FNTSIZ_MULTIPLY: + rText.Append('*'); + break; + case FNTSIZ_DIVIDE: + rText.Append('/'); + break; + case FNTSIZ_ABSOLUT: + default: + break; + } + rText += String( ::rtl::math::doubleToUString( + static_cast<double>(aFontSize), + rtl_math_StringFormat_Automatic, + rtl_math_DecimalPlaces_Max, '.', sal_True)); + rText.Append(' '); + } + break; + case TBLACK: + APPEND(rText,"color black "); + break; + case TWHITE: + APPEND(rText,"color white "); + break; + case TRED: + APPEND(rText,"color red "); + break; + case TGREEN: + APPEND(rText,"color green "); + break; + case TBLUE: + APPEND(rText,"color blue "); + break; + case TCYAN: + APPEND(rText,"color cyan "); + break; + case TMAGENTA: + APPEND(rText,"color magenta "); + break; + case TYELLOW: + APPEND(rText,"color yellow "); + break; + case TSANS: + APPEND(rText,"font sans "); + break; + case TSERIF: + APPEND(rText,"font serif "); + break; + case TFIXED: + APPEND(rText,"font fixed "); + break; + default: + break; + } + GetSubNode(1)->CreateTextFromNode(rText); +} + + +void SmFontNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) +{ + //! prepare subnodes first + SmNode::Prepare(rFormat, rDocShell); + + int nFnt = -1; + switch (GetToken().eType) + { + case TFIXED: nFnt = FNT_FIXED; break; + case TSANS: nFnt = FNT_SANS; break; + case TSERIF: nFnt = FNT_SERIF; break; + default: + break; + } + if (nFnt != -1) + { GetFont() = rFormat.GetFont( sal::static_int_cast< sal_uInt16 >(nFnt) ); + SetFont(GetFont()); + } + + //! prevent overwrites of this font by 'Arrange' or 'SetFont' calls of + //! other font nodes (those with lower depth in the tree) + Flags() |= FLG_FONT; +} + + +void SmFontNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + SmNode *pNode = GetSubNode(1); + OSL_ENSURE(pNode, "Sm: missing subnode"); + + switch (GetToken().eType) + { case TSIZE : + pNode->SetFontSize(aFontSize, nSizeType); + break; + case TSANS : + case TSERIF : + case TFIXED : + pNode->SetFont(GetFont()); + break; + case TUNKNOWN : break; // no assertion on "font <?> <?>" + + case TPHANTOM : SetPhantom(true); break; + case TBOLD : SetAttribut(ATTR_BOLD); break; + case TITALIC : SetAttribut(ATTR_ITALIC); break; + case TNBOLD : ClearAttribut(ATTR_BOLD); break; + case TNITALIC : ClearAttribut(ATTR_ITALIC); break; + + case TBLACK : SetColor(Color(COL_BLACK)); break; + case TWHITE : SetColor(Color(COL_WHITE)); break; + case TRED : SetColor(Color(COL_RED)); break; + case TGREEN : SetColor(Color(COL_GREEN)); break; + case TBLUE : SetColor(Color(COL_BLUE)); break; + case TCYAN : SetColor(Color(COL_CYAN)); break; + case TMAGENTA : SetColor(Color(COL_MAGENTA)); break; + case TYELLOW : SetColor(Color(COL_YELLOW)); break; + + default: + OSL_FAIL("Sm: unknown case"); + } + + pNode->Arrange(rDev, rFormat); + + SmRect::operator = (pNode->GetRect()); +} + + +void SmFontNode::SetSizeParameter(const Fraction& rValue, sal_uInt16 Type) +{ + nSizeType = Type; + aFontSize = rValue; +} + + +/**************************************************************************/ + + +SmPolyLineNode::SmPolyLineNode(const SmToken &rNodeToken) +: SmGraphicNode(NPOLYLINE, rNodeToken) +{ + aPoly.SetSize(2); + nWidth = 0; +} + + +void SmPolyLineNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nNewWidth) +{ + aToSize.Width() = nNewWidth; +} + + +void SmPolyLineNode::AdaptToY(const OutputDevice &/*rDev*/, sal_uLong nNewHeight) +{ + GetFont().FreezeBorderWidth(); + aToSize.Height() = nNewHeight; +} + + +void SmPolyLineNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + //! some routines being called extract some info from the OutputDevice's + //! font (eg the space to be used for borders OR the font name(!!)). + //! Thus the font should reflect the needs and has to be set! + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + long nBorderwidth = GetFont().GetBorderWidth(); + + // + // Das Polygon mit den beiden Endpunkten bilden + // + OSL_ENSURE(aPoly.GetSize() == 2, "Sm : wrong number of points"); + Point aPointA, aPointB; + if (GetToken().eType == TWIDESLASH) + { + aPointA.X() = nBorderwidth; + aPointA.Y() = aToSize.Height() - nBorderwidth; + aPointB.X() = aToSize.Width() - nBorderwidth; + aPointB.Y() = nBorderwidth; + } + else + { + OSL_ENSURE(GetToken().eType == TWIDEBACKSLASH, "Sm : unexpected token"); + aPointA.X() = + aPointA.Y() = nBorderwidth; + aPointB.X() = aToSize.Width() - nBorderwidth; + aPointB.Y() = aToSize.Height() - nBorderwidth; + } + aPoly.SetPoint(aPointA, 0); + aPoly.SetPoint(aPointB, 1); + + long nThick = GetFont().GetSize().Height() + * rFormat.GetDistance(DIS_STROKEWIDTH) / 100L; + nWidth = nThick + 2 * nBorderwidth; + + SmRect::operator = (SmRect(aToSize.Width(), aToSize.Height())); +} + + +/**************************************************************************/ + +void SmRootSymbolNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nWidth) +{ + nBodyWidth = nWidth; +} + + +void SmRootSymbolNode::AdaptToY(const OutputDevice &rDev, sal_uLong nHeight) +{ + // etwas extra Laenge damit der horizontale Balken spaeter ueber dem + // Argument positioniert ist + SmMathSymbolNode::AdaptToY(rDev, nHeight + nHeight / 10L); +} + + +/**************************************************************************/ + + +void SmRectangleNode::AdaptToX(const OutputDevice &/*rDev*/, sal_uLong nWidth) +{ + aToSize.Width() = nWidth; +} + + +void SmRectangleNode::AdaptToY(const OutputDevice &/*rDev*/, sal_uLong nHeight) +{ + GetFont().FreezeBorderWidth(); + aToSize.Height() = nHeight; +} + + +void SmRectangleNode::Arrange(const OutputDevice &rDev, const SmFormat &/*rFormat*/) +{ + long nFontHeight = GetFont().GetSize().Height(); + long nWidth = aToSize.Width(), + nHeight = aToSize.Height(); + if (nHeight == 0) + nHeight = nFontHeight / 30; + if (nWidth == 0) + nWidth = nFontHeight / 3; + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + // add some borderspace + sal_uLong nTmpBorderWidth = GetFont().GetBorderWidth(); + nHeight += 2 * nTmpBorderWidth; + + //! use this method in order to have 'SmRect::HasAlignInfo() == true' + //! and thus having the attribut-fences updated in 'SmRect::ExtendBy' + SmRect::operator = (SmRect(nWidth, nHeight)); +} + + +/**************************************************************************/ + + +SmTextNode::SmTextNode( SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 nFontDescP ) : + SmVisibleNode(eNodeType, rNodeToken) +{ + nFontDesc = nFontDescP; +} + + +SmTextNode::SmTextNode( const SmToken &rNodeToken, sal_uInt16 nFontDescP ) : + SmVisibleNode(NTEXT, rNodeToken) +{ + nFontDesc = nFontDescP; +} + + +void SmTextNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) +{ + SmNode::Prepare(rFormat, rDocShell); + + // default setting for horizontal alignment of nodes with TTEXT + // content is as alignl (cannot be done in Arrange since it would + // override the settings made by an SmAlignNode before) + if (TTEXT == GetToken().eType) + SetRectHorAlign( RHA_LEFT ); + + aText = GetToken().aText; + GetFont() = rFormat.GetFont(GetFontDesc()); + + if (IsItalic( GetFont() )) + Attributes() |= ATTR_ITALIC; + if (IsBold( GetFont() )) + Attributes() |= ATTR_BOLD; + + // special handling for ':' where it is a token on it's own and is likely + // to be used for mathematical notations. (E.g. a:b = 2:3) + // In that case it should not be displayed in italic. + if (GetToken().aText.Len() == 1 && GetToken().aText.GetChar(0) == ':') + Attributes() &= ~ATTR_ITALIC; +}; + + +void SmTextNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + PrepareAttributes(); + + sal_uInt16 nSizeDesc = GetFontDesc() == FNT_FUNCTION ? + SIZ_FUNCTION : SIZ_TEXT; + GetFont() *= Fraction (rFormat.GetRelSize(nSizeDesc), 100); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + SmRect::operator = (SmRect(aTmpDev, &rFormat, aText, GetFont().GetBorderWidth())); +} + +void SmTextNode::CreateTextFromNode(String &rText) +{ + bool bQuoted=false; + if (GetToken().eType == TTEXT) + { + rText.Append('\"'); + bQuoted=true; + } + else + { + SmParser aParseTest; + SmNode *pTable = aParseTest.Parse(GetToken().aText); + bQuoted=true; + if ( (pTable->GetType() == NTABLE) && (pTable->GetNumSubNodes() == 1) ) + { + SmNode *pResult = pTable->GetSubNode(0); + if ( (pResult->GetType() == NLINE) && + (pResult->GetNumSubNodes() == 1) ) + { + pResult = pResult->GetSubNode(0); + if ( (pResult->GetType() == NEXPRESSION) && + (pResult->GetNumSubNodes() == 1) ) + { + pResult = pResult->GetSubNode(0); + if (pResult->GetType() == NTEXT) + bQuoted=false; + } + } + } + delete pTable; + + if ((GetToken().eType == TIDENT) && (GetFontDesc() == FNT_FUNCTION)) + { + //Search for existing functions and remove extraenous keyword + APPEND(rText,"func "); + } + else if (bQuoted) + APPEND(rText,"italic "); + + if (bQuoted) + rText.Append('\"'); + + } + + rText.Append(GetToken().aText); + + if (bQuoted) + rText.Append('\"'); + rText.Append(' '); +} + + +void SmTextNode::GetAccessibleText( String &rText ) const +{ + rText += aText; +} + +void SmTextNode::AdjustFontDesc() +{ + if (GetToken().eType == TTEXT) + nFontDesc = FNT_TEXT; + else if(GetToken().eType == TFUNC) + nFontDesc = FNT_FUNCTION; + else { + SmTokenType nTok; + const SmTokenTableEntry *pEntry = SmParser::GetTokenTableEntry( aText ); + if (pEntry && pEntry->nGroup == TGFUNCTION) { + nTok = pEntry->eType; + nFontDesc = FNT_FUNCTION; + } else { + sal_Unicode firstChar = aText.GetChar(0); + if( ('0' <= firstChar && firstChar <= '9') || firstChar == '.' || firstChar == ',') { + nFontDesc = FNT_NUMBER; + nTok = TNUMBER; + } else if (aText.Len() > 1) { + nFontDesc = FNT_VARIABLE; + nTok = TIDENT; + } else { + nFontDesc = FNT_VARIABLE; + nTok = TCHARACTER; + } + } + SmToken tok = GetToken(); + tok.eType = nTok; + SetToken(tok); + } +} + +/**************************************************************************/ + +void SmMatrixNode::CreateTextFromNode(String &rText) +{ + APPEND(rText,"matrix {"); + for (sal_uInt16 i = 0; i < nNumRows; i++) + { + for (sal_uInt16 j = 0; j < nNumCols; j++) + { + SmNode *pNode = GetSubNode(i * nNumCols + j); + pNode->CreateTextFromNode(rText); + if (j != nNumCols-1) + APPEND(rText,"# "); + } + if (i != nNumRows-1) + APPEND(rText,"## "); + } + rText.EraseTrailingChars(); + APPEND(rText,"} "); +} + + +void SmMatrixNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + Point aPosition, + aOffset; + SmNode *pNode; + sal_uInt16 i, j; + + // initialize array that is to hold the maximum widhts of all + // elements (subnodes) in that column. + long *pColWidth = new long[nNumCols]; + for (j = 0; j < nNumCols; j++) + pColWidth[j] = 0; + + // arrange subnodes and calculate the aboves arrays contents + sal_uInt16 nNodes = GetNumSubNodes(); + for (i = 0; i < nNodes; i++) + { + sal_uInt16 nIdx = nNodes - 1 - i; + if (NULL != (pNode = GetSubNode(nIdx))) + { + pNode->Arrange(rDev, rFormat); + int nCol = nIdx % nNumCols; + pColWidth[nCol] = Max(pColWidth[nCol], pNode->GetItalicWidth()); + } + } + + // norm distance from which the following two are calcutated + const int nNormDist = 3 * GetFont().GetSize().Height(); + + // define horizontal and vertical minimal distances that seperate + // the elements + long nHorDist = nNormDist * rFormat.GetDistance(DIS_MATRIXCOL) / 100L, + nVerDist = nNormDist * rFormat.GetDistance(DIS_MATRIXROW) / 100L; + + // build array that holds the leftmost position for each column + long *pColLeft = new long[nNumCols]; + long nX = 0; + for (j = 0; j < nNumCols; j++) + { pColLeft[j] = nX; + nX += pColWidth[j] + nHorDist; + } + + Point aPos, aDelta; + SmRect aLineRect; + SmRect::operator = (SmRect()); + for (i = 0; i < nNumRows; i++) + { aLineRect = SmRect(); + for (j = 0; j < nNumCols; j++) + { SmNode *pTmpNode = GetSubNode(i * nNumCols + j); + OSL_ENSURE(pTmpNode, "Sm: NULL pointer"); + + const SmRect &rNodeRect = pTmpNode->GetRect(); + + // align all baselines in that row if possible + aPos = rNodeRect.AlignTo(aLineRect, RP_RIGHT, RHA_CENTER, RVA_BASELINE); + aPos.X() += nHorDist; + + // get horizontal alignment + const SmNode *pCoNode = pTmpNode->GetLeftMost(); + RectHorAlign eHorAlign = pCoNode->GetRectHorAlign(); + + // caculate horizontal position of element depending on column + // and horizontal alignment + switch (eHorAlign) + { case RHA_LEFT: + aPos.X() = rNodeRect.GetLeft() + pColLeft[j]; + break; + case RHA_CENTER: + aPos.X() = rNodeRect.GetLeft() + pColLeft[j] + + pColWidth[j] / 2 + - rNodeRect.GetItalicCenterX(); + break; + case RHA_RIGHT: + aPos.X() = rNodeRect.GetLeft() + pColLeft[j] + + pColWidth[j] - rNodeRect.GetItalicWidth(); + break; + } + + pTmpNode->MoveTo(aPos); + aLineRect.ExtendBy(rNodeRect, RCP_XOR); + } + + aPos = aLineRect.AlignTo(*this, RP_BOTTOM, RHA_CENTER, RVA_BASELINE); + aPos.Y() += nVerDist; + + // move 'aLineRect' and rectangles in that line to final position + aDelta.X() = 0; // since horizontal alignment is already done + aDelta.Y() = aPos.Y() - aLineRect.GetTop(); + aLineRect.Move(aDelta); + for (j = 0; j < nNumCols; j++) + if (NULL != (pNode = GetSubNode(i * nNumCols + j))) + pNode->Move(aDelta); + + ExtendBy(aLineRect, RCP_NONE); + } + + delete [] pColLeft; + delete [] pColWidth; +} + + +void SmMatrixNode::SetRowCol(sal_uInt16 nMatrixRows, sal_uInt16 nMatrixCols) +{ + nNumRows = nMatrixRows; + nNumCols = nMatrixCols; +} + + +SmNode * SmMatrixNode::GetLeftMost() +{ + return this; +} + + +/**************************************************************************/ + + +SmMathSymbolNode::SmMathSymbolNode(const SmToken &rNodeToken) +: SmSpecialNode(NMATH, rNodeToken, FNT_MATH) +{ + xub_Unicode cChar = GetToken().cMathChar; + if ((xub_Unicode) '\0' != cChar) + SetText( cChar ); +} + +void SmMathSymbolNode::AdaptToX(const OutputDevice &rDev, sal_uLong nWidth) +{ + // Since there is no function to do this, we try to approximate it: + Size aFntSize (GetFont().GetSize()); + + //! however the result is a bit better with 'nWidth' as initial font width + aFntSize.Width() = nWidth; + GetFont().SetSize(aFntSize); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + // get denominator of error factor for width + long nTmpBorderWidth = GetFont().GetBorderWidth(); + long nDenom = SmRect(aTmpDev, NULL, GetText(), nTmpBorderWidth).GetItalicWidth(); + + // scale fontwidth with this error factor + aFntSize.Width() *= nWidth; + aFntSize.Width() /= nDenom ? nDenom : 1; + + GetFont().SetSize(aFntSize); +} + +void SmMathSymbolNode::AdaptToY(const OutputDevice &rDev, sal_uLong nHeight) +{ + GetFont().FreezeBorderWidth(); + Size aFntSize (GetFont().GetSize()); + + // da wir nur die Hoehe skalieren wollen muesen wir hier ggf die Fontweite + // ermitteln um diese beizubehalten. + if (aFntSize.Width() == 0) + { + OutputDevice &rDevNC = (OutputDevice &) rDev; + rDevNC.Push(PUSH_FONT | PUSH_MAPMODE); + rDevNC.SetFont(GetFont()); + aFntSize.Width() = rDev.GetFontMetric().GetSize().Width(); + rDevNC.Pop(); + } + OSL_ENSURE(aFntSize.Width() != 0, "Sm: "); + + //! however the result is a bit better with 'nHeight' as initial + //! font height + aFntSize.Height() = nHeight; + GetFont().SetSize(aFntSize); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + // get denominator of error factor for height + long nTmpBorderWidth = GetFont().GetBorderWidth(); + long nDenom = SmRect(aTmpDev, NULL, GetText(), nTmpBorderWidth).GetHeight(); + + // scale fontwidth with this error factor + aFntSize.Height() *= nHeight; + aFntSize.Height() /= nDenom ? nDenom : 1; + + GetFont().SetSize(aFntSize); +} + + +void SmMathSymbolNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) +{ + SmNode::Prepare(rFormat, rDocShell); + + GetFont() = rFormat.GetFont(GetFontDesc()); + // use same font size as is used for variables + GetFont().SetSize( rFormat.GetFont( FNT_VARIABLE ).GetSize() ); + + OSL_ENSURE(GetFont().GetCharSet() == RTL_TEXTENCODING_SYMBOL || + GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE, + "wrong charset for character from StarMath/OpenSymbol font"); + + Flags() |= FLG_FONT | FLG_ITALIC; +}; + + +void SmMathSymbolNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + const XubString &rText = GetText(); + + if (rText.Len() == 0 || rText.GetChar(0) == xub_Unicode('\0')) + { SmRect::operator = (SmRect()); + return; + } + + PrepareAttributes(); + + GetFont() *= Fraction (rFormat.GetRelSize(SIZ_TEXT), 100); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth())); +} + +void SmMathSymbolNode::CreateTextFromNode(String &rText) +{ + String sStr; + MathType::LookupChar(GetToken().cMathChar, sStr); + rText.Append(sStr); +} + +void SmRectangleNode::CreateTextFromNode(String &rText) +{ + switch (GetToken().eType) + { + case TUNDERLINE: + APPEND(rText,"underline "); + break; + case TOVERLINE: + APPEND(rText,"overline "); + break; + case TOVERSTRIKE: + APPEND(rText,"overstrike "); + break; + default: + break; + } +} + +void SmAttributNode::CreateTextFromNode(String &rText) +{ + SmNode *pNode; + sal_uInt16 nSize = GetNumSubNodes(); + OSL_ENSURE(nSize == 2, "Node missing members"); + rText.Append('{'); + sal_Unicode nLast=0; + if (NULL != (pNode = GetSubNode(0))) + { + String aStr; + pNode->CreateTextFromNode(aStr); + if (aStr.Len() > 1) + rText.Append(aStr); + else + { + nLast = aStr.GetChar(0); + switch (nLast) + { + case 0xAF: + APPEND(rText,"overline "); + break; + case 0x2d9: + APPEND(rText,"dot "); + break; + case 0x2dc: + APPEND(rText,"widetilde "); + break; + case 0xA8: + APPEND(rText,"ddot "); + break; + case 0xE082: + break; + case 0xE09B: + APPEND(rText,"dddot "); + break; + default: + rText.Append(nLast); + break; + } + } + } + + if (nSize == 2) + if (NULL != (pNode = GetSubNode(1))) + pNode->CreateTextFromNode(rText); + + rText.EraseTrailingChars(); + + if (nLast == 0xE082) + APPEND(rText," overbrace {}"); + + APPEND(rText,"} "); +} + +/**************************************************************************/ + +bool lcl_IsFromGreekSymbolSet( const String &rTokenText ) +{ + bool bRes = false; + + // valid symbol name needs to have a '%' at pos 0 and at least an additonal char + if (rTokenText.Len() > 2 && rTokenText.GetBuffer()[0] == (sal_Unicode)'%') + { + String aName( rTokenText.Copy(1) ); + SmSym *pSymbol = SM_MOD()->GetSymbolManager().GetSymbolByName( aName ); + if (pSymbol && GetExportSymbolSetName( pSymbol->GetSymbolSetName() ).EqualsAscii( "Greek" ) ) + bRes = true; + } + + return bRes; +} + + +SmSpecialNode::SmSpecialNode(SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 _nFontDesc) : + SmTextNode(eNodeType, rNodeToken, _nFontDesc) +{ + bIsFromGreekSymbolSet = lcl_IsFromGreekSymbolSet( rNodeToken.aText ); +} + + +SmSpecialNode::SmSpecialNode(const SmToken &rNodeToken) : + SmTextNode(NSPECIAL, rNodeToken, FNT_MATH) //! default Font nicht immer richtig +{ + bIsFromGreekSymbolSet = lcl_IsFromGreekSymbolSet( rNodeToken.aText ); +} + + +void SmSpecialNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) +{ + SmNode::Prepare(rFormat, rDocShell); + + const SmSym *pSym; + SmModule *pp = SM_MOD(); + + String aName( GetToken().aText.Copy(1) ); + if (NULL != (pSym = pp->GetSymbolManager().GetSymbolByName( aName ))) + { + sal_UCS4 cChar = pSym->GetCharacter(); + String aTmp( OUString( &cChar, 1 ) ); + SetText( aTmp ); + GetFont() = pSym->GetFace(); + } + else + { + SetText( GetToken().aText ); + GetFont() = rFormat.GetFont(FNT_VARIABLE); + } + // use same font size as is used for variables + GetFont().SetSize( rFormat.GetFont( FNT_VARIABLE ).GetSize() ); + + //! eigentlich sollten nur WEIGHT_NORMAL und WEIGHT_BOLD vorkommen... + //! In der sms-Datei gibt es jedoch zB auch 'WEIGHT_ULTRALIGHT' + //! daher vergleichen wir hier mit > statt mit != . + //! (Langfristig sollte die Notwendigkeit fuer 'PrepareAttribut', und damit + //! fuer dieses hier, mal entfallen.) + // + //! see also SmFontStyles::GetStyleName + if (IsItalic( GetFont() )) + SetAttribut(ATTR_ITALIC); + if (IsBold( GetFont() )) + SetAttribut(ATTR_BOLD); + + Flags() |= FLG_FONT; + + if (bIsFromGreekSymbolSet) + { + OSL_ENSURE( GetText().Len() == 1, "a symbol should only consist of 1 char!" ); + bool bItalic = false; + sal_Int16 nStyle = rFormat.GetGreekCharStyle(); + OSL_ENSURE( nStyle >= 0 && nStyle <= 2, "unexpected value for GreekCharStyle" ); + if (nStyle == 1) + bItalic = true; + else if (nStyle == 2) + { + String aTmp( GetText() ); + if (aTmp.Len() > 0) + { + const sal_Unicode cUppercaseAlpha = 0x0391; + const sal_Unicode cUppercaseOmega = 0x03A9; + sal_Unicode cChar = aTmp.GetBuffer()[0]; + // uppercase letters should be straight and lowercase letters italic + bItalic = !(cUppercaseAlpha <= cChar && cChar <= cUppercaseOmega); + } + } + + if (bItalic) + Attributes() |= ATTR_ITALIC; + else + Attributes() &= ~ATTR_ITALIC;; + } +}; + + +void SmSpecialNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + PrepareAttributes(); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth())); +} + +/**************************************************************************/ + + +void SmGlyphSpecialNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + PrepareAttributes(); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), + GetFont().GetBorderWidth()).AsGlyphRect()); +} + + +/**************************************************************************/ + + +void SmPlaceNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) +{ + SmNode::Prepare(rFormat, rDocShell); + + GetFont().SetColor(COL_GRAY); + Flags() |= FLG_COLOR | FLG_FONT | FLG_ITALIC; +}; + + +void SmPlaceNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + PrepareAttributes(); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + SmRect::operator = (SmRect(aTmpDev, &rFormat, GetText(), GetFont().GetBorderWidth())); +} + + +/**************************************************************************/ + + +void SmErrorNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) +{ + SmNode::Prepare(rFormat, rDocShell); + + GetFont().SetColor(COL_RED); + Flags() |= FLG_VISIBLE | FLG_BOLD | FLG_ITALIC + | FLG_COLOR | FLG_FONT | FLG_SIZE; +} + + +void SmErrorNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + PrepareAttributes(); + + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + const XubString &rText = GetText(); + SmRect::operator = (SmRect(aTmpDev, &rFormat, rText, GetFont().GetBorderWidth())); +} + + +/**************************************************************************/ + + +void SmBlankNode::IncreaseBy(const SmToken &rToken) +{ + switch(rToken.eType) + { + case TBLANK: nNum += 4; break; + case TSBLANK: nNum += 1; break; + default: + break; + } +} + + +void SmBlankNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) +{ + SmNode::Prepare(rFormat, rDocShell); + + //! hier muss/sollte es lediglich nicht der StarMath Font sein, + //! damit fuer das in Arrange verwendete Zeichen ein "normales" + //! (ungecliptes) Rechteck erzeugt wird. + GetFont() = rFormat.GetFont(FNT_VARIABLE); + + Flags() |= FLG_FONT | FLG_BOLD | FLG_ITALIC; +} + + +void SmBlankNode::Arrange(const OutputDevice &rDev, const SmFormat &rFormat) +{ + SmTmpDevice aTmpDev ((OutputDevice &) rDev, true); + aTmpDev.SetFont(GetFont()); + + // Abstand von der Fonthoehe abhaengig machen + // (damit er beim skalieren (zB size *2 {a ~ b}) mitwaechst) + long nDist = GetFont().GetSize().Height() / 10L, + nSpace = nNum * nDist; + + // ein SmRect mit Baseline und allem drum und dran besorgen + SmRect::operator = (SmRect(aTmpDev, &rFormat, XubString(xub_Unicode(' ')), + GetFont().GetBorderWidth())); + + // und dieses auf die gewuenschte Breite bringen + SetItalicSpaces(0, 0); + SetWidth(nSpace); +} + +/**************************************************************************/ +//Implementation of all accept methods for SmVisitor + +void SmNode::Accept(SmVisitor*){ + //This method is only implemented to avoid making SmNode abstract because an + //obscure copy constructor is used... I can't find it's implementation, and + //don't want to figure out how to fix it... If you want to, just delete this + //method, making SmNode abstract, and see where you can an problem with that. + OSL_FAIL("SmNode should not be visitable!"); +} + +void SmTableNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmBraceNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmBracebodyNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmOperNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmAlignNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmAttributNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmFontNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmUnHorNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmBinHorNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmBinVerNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmBinDiagonalNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmSubSupNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmMatrixNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmPlaceNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmTextNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmSpecialNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmGlyphSpecialNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmMathSymbolNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmBlankNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmErrorNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmLineNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmExpressionNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmPolyLineNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmRootNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmRootSymbolNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmRectangleNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +void SmVerticalBraceNode::Accept(SmVisitor* pVisitor) { + pVisitor->Visit(this); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/ooxml.cxx b/starmath/source/ooxml.cxx new file mode 100644 index 000000000000..aea6e09c64be --- /dev/null +++ b/starmath/source/ooxml.cxx @@ -0,0 +1,499 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Lubos Lunak <l.lunak@suse.cz> (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + +#include "ooxml.hxx" + +#include <oox/token/tokens.hxx> + +using namespace oox; +using namespace oox::core; + +// TODO duped from MathType + +static sal_Unicode Convert(sal_Unicode nIn) +{ + //Find the best match in accepted unicode for our private area symbols + static sal_Unicode aStarMathPrivateToUnicode[] = + { + 0x2030, 0xF613, 0xF612, 0x002B, 0x003C, 0x003E, 0xE425, 0xE421, 0xE088, 0x2208, + 0x0192, 0x2026, 0x2192, 0x221A, 0x221A, 0x221A, 0xE090, 0x005E, 0x02C7, 0x02D8, + 0x00B4, 0x0060, 0x02DC, 0x00AF, 0x0362, 0xE099, 0xE09A, 0x20DB, 0xE09C, 0xE09D, + 0x0028, 0x0029, 0x2220, 0x22AF, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, + 0x002F, 0x005C, 0x274F, 0xE0AB, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03A0, + 0x03a3, 0x03a5, 0x03a6, 0x03a8, 0x03A9, 0x03B1, 0x03B2, 0x03b3, 0x03b4, 0x03b5, + 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03b5, + 0x03d1, 0x03d6, 0xE0D2, 0x03db, 0x2118, 0x2202, 0x2129, 0xE0D7, 0xE0D8, 0x22A4, + 0xE0DA, 0x2190, 0x2191, 0x2193 + }; + if ((nIn >= 0xE080) && (nIn <= 0xE0DD)) + nIn = aStarMathPrivateToUnicode[nIn-0xE080]; + + //For whatever unicode glyph that equation editor doesn't ship with that + //we have a possible match we can munge it to. + switch (nIn) + { + case 0x2223: + nIn = '|'; + break; + default: + break; + } + + return nIn; +} + +SmOoxml::SmOoxml( const String &rIn, const SmNode* pIn, OoxmlVersion v ) +: str( rIn ) +, pTree( pIn ) +, version( v ) +{ +} + +bool SmOoxml::ConvertFromStarMath( ::sax_fastparser::FSHelperPtr serializer ) +{ + if( pTree == NULL ) + return false; + m_pSerializer = serializer; + m_pSerializer->startElementNS( XML_m, XML_oMath, + FSNS( XML_xmlns, XML_m ), "http://schemas.openxmlformats.org/officeDocument/2006/math", FSEND ); + HandleNode( pTree, 0 ); + m_pSerializer->endElementNS( XML_m, XML_oMath ); + return true; +} + +// NOTE: This is still work in progress and unfinished, but it already covers a good +// part of the ooxml math stuff. + +void SmOoxml::HandleNode( const SmNode* pNode, int nLevel ) +{ +// fprintf(stderr,"XX %d %d %d\n", nLevel, pNode->GetType(), pNode->GetNumSubNodes()); + switch(pNode->GetType()) + { + case NATTRIBUT: + HandleAttribute( static_cast< const SmAttributNode* >( pNode ), nLevel ); + break; + case NTEXT: + HandleText(pNode,nLevel); + break; +#if 0 + case NVERTICAL_BRACE: + HandleVerticalBrace(pNode,nLevel); + break; + case NBRACE: + HandleBrace(pNode,nLevel); + break; + case NOPER: + HandleOperator(pNode,nLevel); + break; +#endif + case NUNHOR: + HandleUnaryOperation( static_cast< const SmUnHorNode* >( pNode ), nLevel ); + break; + case NBINHOR: + HandleBinaryOperation( static_cast< const SmBinHorNode* >( pNode ), nLevel ); + break; + case NBINVER: + HandleFractions(pNode,nLevel); + break; + case NROOT: + HandleRoot( static_cast< const SmRootNode* >( pNode ), nLevel ); + break; +#if 0 + case NSPECIAL: + { + const SmTextNode* pText= static_cast< const SmTextNode* >( pNode ); + //if the token str and the result text are the same then this + //is to be seen as text, else assume its a mathchar + if (pText->GetText() == pText->GetToken().aText) + HandleText(pText,nLevel); + else + HandleMath(pText,nLevel); + } + break; +#endif + case NMATH: + HandleMath(pNode,nLevel); + break; + case NSUBSUP: + HandleSubSupScript( static_cast< const SmSubSupNode* >( pNode ), nLevel ); + break; + case NEXPRESSION: + HandleAllSubNodes( pNode, nLevel ); + break; + case NTABLE: + //Root Node, PILE equivalent, i.e. vertical stack + HandleTable(pNode,nLevel); + break; +#if 0 + case NMATRIX: + HandleSmMatrix( static_cast< const SmMatrixNode* >( pNode ), nLevel ); + break; +#endif + case NLINE: + { +// TODO + HandleAllSubNodes( pNode, nLevel ); + } + break; +#if 0 + case NALIGN: + HandleMAlign(pNode,nLevel); + break; + case NPLACE: + // explicitly do nothing, MSOffice treats that as a placeholder if item is missing + break; + case NBLANK: + *pS << sal_uInt8(CHAR); + *pS << sal_uInt8(0x98); + if (pNode->GetToken().eType == TSBLANK) + *pS << sal_uInt16(0xEB04); + else + *pS << sal_uInt16(0xEB05); + break; +#endif + default: + HandleAllSubNodes( pNode, nLevel ); + break; + } +} + +//Root Node, PILE equivalent, i.e. vertical stack +void SmOoxml::HandleTable( const SmNode* pNode, int nLevel ) +{ + //The root of the starmath is a table, if + //we convert this them each iteration of + //conversion from starmath to OOXML will + //add an extra unnecessary level to the + //OOXML output stack which would grow + //without bound in a multi step conversion + if( nLevel || pNode->GetNumSubNodes() > 1 ) + HandleVerticalStack( pNode, nLevel, 0 ); + else + HandleAllSubNodes( pNode, nLevel ); +} + +void SmOoxml::HandleAllSubNodes( const SmNode* pNode, int nLevel ) +{ + int size = pNode->GetNumSubNodes(); + for( int i = 0; + i < size; + ++i ) + { +// TODO remove when all types of nodes are handled properly + if( pNode->GetSubNode( i ) == NULL ) + { + OSL_FAIL( "Subnode is NULL, parent node not handled properly" ); + continue; + } + HandleNode( pNode->GetSubNode( i ), nLevel + 1 ); + } +} + +// output vertical stack, firstItem says which child to use as first (if there +// are more than two children, OOXML can have only a vertical stack of two items, +// so create a bigger vertical stack recursively) +void SmOoxml::HandleVerticalStack( const SmNode* pNode, int nLevel, int firstItem ) +{ + if( firstItem == pNode->GetNumSubNodes() - 1 ) // only one item, just output the item + { + HandleNode( pNode->GetSubNode( firstItem ), nLevel + 1 ); + return; + } + m_pSerializer->startElementNS( XML_m, XML_f, FSEND ); + m_pSerializer->startElementNS( XML_m, XML_fPr, FSEND ); + m_pSerializer->singleElementNS( XML_m, XML_type, FSNS( XML_m, XML_val ), "noBar", FSEND ); + m_pSerializer->endElementNS( XML_m, XML_fPr ); + m_pSerializer->startElementNS( XML_m, XML_num, FSEND ); + HandleNode( pNode->GetSubNode( firstItem ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_num ); + // TODO this nesting means MSOffice will use smaller fonts for nested items, + // not sure if there's another way to represent a bigger stack than 2 items + m_pSerializer->startElementNS( XML_m, XML_den, FSEND ); + HandleVerticalStack( pNode, nLevel, firstItem + 1 ); + m_pSerializer->endElementNS( XML_m, XML_den ); + m_pSerializer->endElementNS( XML_m, XML_f ); +} + +void SmOoxml::HandleText( const SmNode* pNode, int /*nLevel*/) +{ + m_pSerializer->startElementNS( XML_m, XML_r, FSEND ); + + if( version == ECMA_DIALECT ) + { // HACK: MSOffice2007 does not import characters properly unless this font is explicitly given + m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND ); + m_pSerializer->singleElementNS( XML_w, XML_rFonts, FSNS( XML_w, XML_ascii ), "Cambria Math", + FSNS( XML_w, XML_hAnsi ), "Cambria Math", FSEND ); + m_pSerializer->endElementNS( XML_w, XML_rPr ); + } + m_pSerializer->startElementNS( XML_m, XML_t, FSEND ); + SmTextNode* pTemp=(SmTextNode* )pNode; +// fprintf(stderr, "T %s\n", rtl::OUStringToOString( pTemp->GetText(), RTL_TEXTENCODING_UTF8 ).getStr()); + for(xub_StrLen i=0;i<pTemp->GetText().Len();i++) + { +#if 0 + if ((nPendingAttributes) && + (i == ((pTemp->GetText().Len()+1)/2)-1)) + { + *pS << sal_uInt8(0x22); //char, with attributes right + //after the character + } + else + *pS << sal_uInt8(CHAR); + + sal_uInt8 nFace = 0x1; + if (pNode->GetFont().GetItalic() == ITALIC_NORMAL) + nFace = 0x3; + else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD) + nFace = 0x7; + *pS << sal_uInt8(nFace+128); //typeface +#endif + sal_uInt16 nChar = pTemp->GetText().GetChar(i); + m_pSerializer->write( rtl::OUString( Convert(nChar))); + +#if 0 + //Mathtype can only have these sort of character + //attributes on a single character, starmath can put them + //anywhere, when the entity involved is a text run this is + //a large effort to place the character attribute on the + //central mathtype character so that it does pretty much + //what the user probably has in mind. The attributes + //filled in here are dummy ones which are replaced in the + //ATTRIBUT handler if a suitable location for the + //attributes was found here. Unfortunately it is + //possible for starmath to place character attributes on + //entities which cannot occur in mathtype e.g. a Summation + //symbol so these attributes may be lost + if ((nPendingAttributes) && + (i == ((pTemp->GetText().Len()+1)/2)-1)) + { + *pS << sal_uInt8(EMBEL); + while (nPendingAttributes) + { + *pS << sal_uInt8(2); + //wedge the attributes in here and clear + //the pending stack + nPendingAttributes--; + } + nInsertion=pS->Tell(); + *pS << sal_uInt8(END); //end embel + *pS << sal_uInt8(END); //end embel + } +#endif + } + m_pSerializer->endElementNS( XML_m, XML_t ); + m_pSerializer->endElementNS( XML_m, XML_r ); +} + +void SmOoxml::HandleFractions( const SmNode* pNode, int nLevel, const char* type ) +{ + m_pSerializer->startElementNS( XML_m, XML_f, FSEND ); + if( type != NULL ) + { + m_pSerializer->startElementNS( XML_m, XML_fPr, FSEND ); + m_pSerializer->singleElementNS( XML_m, XML_type, FSNS( XML_m, XML_val ), type, FSEND ); + m_pSerializer->endElementNS( XML_m, XML_fPr ); + } + OSL_ASSERT( pNode->GetNumSubNodes() == 3 ); + m_pSerializer->startElementNS( XML_m, XML_num, FSEND ); + HandleNode( pNode->GetSubNode( 0 ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_num ); + m_pSerializer->startElementNS( XML_m, XML_den, FSEND ); + HandleNode( pNode->GetSubNode( 2 ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_den ); + m_pSerializer->endElementNS( XML_m, XML_f ); +} + +void SmOoxml::HandleUnaryOperation( const SmUnHorNode* pNode, int nLevel ) +{ + // update HandleMath() when adding new items +// fprintf(stderr,"UNARY %d\n", pNode->Symbol()->GetToken().eType ); + switch( pNode->Symbol()->GetToken().eType ) + { + default: + HandleAllSubNodes( pNode, nLevel ); + break; + } +} + +void SmOoxml::HandleBinaryOperation( const SmBinHorNode* pNode, int nLevel ) +{ +// fprintf(stderr,"BINARY %d\n", pNode->Symbol()->GetToken().eType ); + // update HandleMath() when adding new items + switch( pNode->Symbol()->GetToken().eType ) + { + case TDIVIDEBY: + return HandleFractions( pNode, nLevel, "lin" ); + default: + HandleAllSubNodes( pNode, nLevel ); + break; + } +} + +void SmOoxml::HandleAttribute( const SmAttributNode* pNode, int nLevel ) +{ + switch( pNode->Attribute()->GetToken().eType ) + { + case TCHECK: // TODO check these all are really accents + case TACUTE: + case TGRAVE: + case TCIRCLE: + case TWIDETILDE: + case TWIDEHAT: + { + m_pSerializer->startElementNS( XML_m, XML_acc, FSEND ); + m_pSerializer->startElementNS( XML_m, XML_accPr, FSEND ); + rtl::OString value = rtl::OUStringToOString( + rtl::OUString( pNode->Attribute()->GetToken().cMathChar ), RTL_TEXTENCODING_UTF8 ); + m_pSerializer->singleElementNS( XML_m, XML_chr, FSNS( XML_m, XML_val ), value.getStr(), FSEND ); + m_pSerializer->endElementNS( XML_m, XML_accPr ); + m_pSerializer->startElementNS( XML_m, XML_e, FSEND ); + HandleNode( pNode->Body(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_acc ); + break; + } + default: + HandleAllSubNodes( pNode, nLevel ); + break; + } +} + +void SmOoxml::HandleMath( const SmNode* pNode, int nLevel ) +{ +// fprintf(stderr,"MATH %d\n", pNode->GetToken().eType); + switch( pNode->GetToken().eType ) + { + case TDIVIDEBY: + case TACUTE: + // these are handled elsewhere, e.g. when handling BINHOR + OSL_ASSERT( false ); + default: + HandleText( pNode, nLevel ); + break; + } +} + +void SmOoxml::HandleRoot( const SmRootNode* pNode, int nLevel ) +{ + m_pSerializer->startElementNS( XML_m, XML_rad, FSEND ); + if( const SmNode* argument = pNode->Argument()) + { + m_pSerializer->startElementNS( XML_m, XML_deg, FSEND ); + HandleNode( argument, nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_deg ); + } + else + { + m_pSerializer->startElementNS( XML_m, XML_radPr, FSEND ); + m_pSerializer->singleElementNS( XML_m, XML_degHide, FSNS( XML_m, XML_val ), "1", FSEND ); + m_pSerializer->endElementNS( XML_m, XML_radPr ); + m_pSerializer->singleElementNS( XML_m, XML_deg, FSEND ); // empty but present + } + m_pSerializer->startElementNS( XML_m, XML_e, FSEND ); + HandleNode( pNode->Body(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_rad ); +} + +void SmOoxml::HandleSubSupScript( const SmSubSupNode* pNode, int nLevel ) +{ + // set flags to a bitfield of which sub/sup items exists + int flags = ( pNode->GetSubSup( CSUB ) != NULL ? ( 1 << CSUB ) : 0 ) + | ( pNode->GetSubSup( CSUP ) != NULL ? ( 1 << CSUP ) : 0 ) + | ( pNode->GetSubSup( RSUB ) != NULL ? ( 1 << RSUB ) : 0 ) + | ( pNode->GetSubSup( RSUP ) != NULL ? ( 1 << RSUP ) : 0 ) + | ( pNode->GetSubSup( LSUB ) != NULL ? ( 1 << RSUB ) : 0 ) + | ( pNode->GetSubSup( LSUP ) != NULL ? ( 1 << LSUP ) : 0 ); + if( flags == 0 ) // none + return; + HandleSubSupScriptInternal( pNode, nLevel, flags ); +} + +void SmOoxml::HandleSubSupScriptInternal( const SmSubSupNode* pNode, int nLevel, int flags ) +{ + if( flags == ( 1 << RSUP | 1 << RSUB )) + { // m:sSubSup + m_pSerializer->startElementNS( XML_m, XML_sSubSup, FSEND ); + m_pSerializer->startElementNS( XML_m, XML_e, FSEND ); + HandleNode( pNode->GetBody(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS( XML_m, XML_sub, FSEND ); + HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sub ); + m_pSerializer->startElementNS( XML_m, XML_sup, FSEND ); + HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sup ); + m_pSerializer->endElementNS( XML_m, XML_sSubSup ); + } + else if( flags == 1 << RSUB ) + { // m:sSub + m_pSerializer->startElementNS( XML_m, XML_sSub, FSEND ); + m_pSerializer->startElementNS( XML_m, XML_e, FSEND ); + HandleNode( pNode->GetBody(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS( XML_m, XML_sub, FSEND ); + HandleNode( pNode->GetSubSup( RSUB ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sub ); + m_pSerializer->endElementNS( XML_m, XML_sSub ); + } + else if( flags == 1 << RSUP ) + { // m:sSup + m_pSerializer->startElementNS( XML_m, XML_sSup, FSEND ); + m_pSerializer->startElementNS( XML_m, XML_e, FSEND ); + HandleNode( pNode->GetBody(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->startElementNS( XML_m, XML_sup, FSEND ); + HandleNode( pNode->GetSubSup( RSUP ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sup ); + m_pSerializer->endElementNS( XML_m, XML_sSup ); + } + else if( flags == ( 1 << LSUP | 1 << LSUB )) + { // m:sPre + m_pSerializer->startElementNS( XML_m, XML_sPre, FSEND ); + m_pSerializer->startElementNS( XML_m, XML_sub, FSEND ); + HandleNode( pNode->GetSubSup( LSUB ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sub ); + m_pSerializer->startElementNS( XML_m, XML_sup, FSEND ); + HandleNode( pNode->GetSubSup( LSUP ), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_sup ); + m_pSerializer->startElementNS( XML_m, XML_e, FSEND ); + HandleNode( pNode->GetBody(), nLevel + 1 ); + m_pSerializer->endElementNS( XML_m, XML_e ); + m_pSerializer->endElementNS( XML_m, XML_sSubSup ); + } + else + { + OSL_FAIL( "Unhandled sub/sup combination" ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/ooxml.hxx b/starmath/source/ooxml.hxx new file mode 100644 index 000000000000..7246a8c78fa3 --- /dev/null +++ b/starmath/source/ooxml.hxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Lubos Lunak <l.lunak@suse.cz> (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef SM_OOXML_HXX +#define SM_OOXML_HXX + +#include "node.hxx" + +#include <sax/fshelper.hxx> +#include <oox/core/filterbase.hxx> + +/** + Class implementing writing of formulas to OOXML. + */ +class SmOoxml +{ +public: + SmOoxml( const String &rIn,const SmNode* pIn, oox::core::OoxmlVersion version ); + bool ConvertFromStarMath( ::sax_fastparser::FSHelperPtr m_pSerializer ); +private: + void HandleNode( const SmNode* pNode, int nLevel ); + void HandleAllSubNodes( const SmNode* pNode, int nLevel ); + void HandleTable( const SmNode* pNode, int nLevel ); + void HandleVerticalStack( const SmNode* pNode, int nLevel, int firstItem ); + void HandleText( const SmNode* pNode, int nLevel ); + void HandleMath( const SmNode* pNode, int nLevel ); + void HandleFractions( const SmNode* pNode, int nLevel, const char* type = NULL ); + void HandleUnaryOperation( const SmUnHorNode* pNode, int nLevel ); + void HandleBinaryOperation( const SmBinHorNode* pNode, int nLevel ); + void HandleRoot( const SmRootNode* pNode,int nLevel ); + void HandleAttribute( const SmAttributNode* pNode,int nLevel ); + void HandleSubSupScript( const SmSubSupNode* pNode, int nLevel ); + void HandleSubSupScriptInternal( const SmSubSupNode* pNode, int nLevel, int flags ); + String str; + const SmNode* const pTree; + ::sax_fastparser::FSHelperPtr m_pSerializer; + oox::core::OoxmlVersion version; +}; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/parse.cxx b/starmath/source/parse.cxx new file mode 100644 index 000000000000..06859cec4a6b --- /dev/null +++ b/starmath/source/parse.cxx @@ -0,0 +1,2525 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <stdio.h> + +#define SMDLL 1 + +#include <com/sun/star/i18n/UnicodeType.hpp> +#include <i18npool/lang.h> +#include <unotools/charclass.hxx> +#include <editeng/unolingu.hxx> +#include <unotools/syslocale.hxx> +#include <sal/macros.h> +#include "parse.hxx" +#include "starmath.hrc" +#include "smdll.hxx" +#include "smmod.hxx" +#include "config.hxx" + +#include "node.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::i18n; + +/////////////////////////////////////////////////////////////////////////// + +static inline bool strnccmp(const String &u1, xub_StrLen nIdx, + const sal_Char *s2, xub_StrLen nLen) +{ + return u1.EqualsIgnoreCaseAscii( s2, nIdx, nLen ); +} + +static const sal_Unicode aDelimiterTable[] = +{ + ' ', '\t', '\n', '\r', '+', '-', '*', '/', '=', '#', + '%', '\\', '"', '~', '`', '>', '<', '&', '|', '(', + ')', '{', '}', '[', ']', '^', '_', + '\0' // end of list symbol +}; + + +static inline bool IsDigit( sal_Unicode cChar ) +{ + return '0' <= cChar && cChar <= '9'; +} + +/////////////////////////////////////////////////////////////////////////// + +SmToken::SmToken() : + eType (TUNKNOWN), + cMathChar ('\0') +{ + nGroup = nCol = nRow = nLevel = 0; +} + +SmToken::SmToken(SmTokenType eTokenType, + sal_Unicode cMath, + const sal_Char* pText, + sal_uLong nTokenGroup, + sal_uInt16 nTokenLevel) { + eType = eTokenType; + cMathChar = cMath; + aText.AssignAscii(pText); + nGroup = nTokenGroup; + nLevel = nTokenLevel; + nCol = nRow = 0; +} + +/////////////////////////////////////////////////////////////////////////// + + +static const SmTokenTableEntry aTokenTable[] = +{ + { "Im" , TIM, MS_IM, TGSTANDALONE, 5 }, + { "MZ23", TDEBUG, '\0', TGATTRIBUT, 0 }, + { "Re" , TRE, MS_RE, TGSTANDALONE, 5 }, + { "abs", TABS, '\0', TGUNOPER, 13 }, + { "arcosh", TACOSH, '\0', TGFUNCTION, 5 }, + { "arcoth", TACOTH, '\0', TGFUNCTION, 5 }, + { "acute", TACUTE, MS_ACUTE, TGATTRIBUT, 5 }, + { "aleph" , TALEPH, MS_ALEPH, TGSTANDALONE, 5 }, + { "alignb", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0}, + { "alignc", TALIGNC, '\0', TGALIGN, 0}, + { "alignl", TALIGNL, '\0', TGALIGN, 0}, + { "alignm", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0}, + { "alignr", TALIGNR, '\0', TGALIGN, 0}, + { "alignt", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0}, + { "and", TAND, MS_AND, TGPRODUCT, 0}, + { "approx", TAPPROX, MS_APPROX, TGRELATION, 0}, + { "arccos", TACOS, '\0', TGFUNCTION, 5}, + { "arccot", TACOT, '\0', TGFUNCTION, 5}, + { "arcsin", TASIN, '\0', TGFUNCTION, 5}, + { "arctan", TATAN, '\0', TGFUNCTION, 5}, + { "arsinh", TASINH, '\0', TGFUNCTION, 5}, + { "artanh", TATANH, '\0', TGFUNCTION, 5}, + { "backepsilon" , TBACKEPSILON, MS_BACKEPSILON, TGSTANDALONE, 5}, + { "bar", TBAR, MS_BAR, TGATTRIBUT, 5}, + { "binom", TBINOM, '\0', 0, 5 }, + { "black", TBLACK, '\0', TGCOLOR, 0}, + { "blue", TBLUE, '\0', TGCOLOR, 0}, + { "bold", TBOLD, '\0', TGFONTATTR, 5}, + { "boper", TBOPER, '\0', TGPRODUCT, 0}, + { "breve", TBREVE, MS_BREVE, TGATTRIBUT, 5}, + { "bslash", TBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 }, + { "cdot", TCDOT, MS_CDOT, TGPRODUCT, 0}, + { "check", TCHECK, MS_CHECK, TGATTRIBUT, 5}, + { "circ" , TCIRC, MS_CIRC, TGSTANDALONE, 5}, + { "circle", TCIRCLE, MS_CIRCLE, TGATTRIBUT, 5}, + { "color", TCOLOR, '\0', TGFONTATTR, 5}, + { "coprod", TCOPROD, MS_COPROD, TGOPER, 5}, + { "cos", TCOS, '\0', TGFUNCTION, 5}, + { "cosh", TCOSH, '\0', TGFUNCTION, 5}, + { "cot", TCOT, '\0', TGFUNCTION, 5}, + { "coth", TCOTH, '\0', TGFUNCTION, 5}, + { "csub", TCSUB, '\0', TGPOWER, 0}, + { "csup", TCSUP, '\0', TGPOWER, 0}, + { "cyan", TCYAN, '\0', TGCOLOR, 0}, + { "dddot", TDDDOT, MS_DDDOT, TGATTRIBUT, 5}, + { "ddot", TDDOT, MS_DDOT, TGATTRIBUT, 5}, + { "def", TDEF, MS_DEF, TGRELATION, 0}, + { "div", TDIV, MS_DIV, TGPRODUCT, 0}, + { "divides", TDIVIDES, MS_LINE, TGRELATION, 0}, + { "dlarrow" , TDLARROW, MS_DLARROW, TGSTANDALONE, 5}, + { "dlrarrow" , TDLRARROW, MS_DLRARROW, TGSTANDALONE, 5}, + { "dot", TDOT, MS_DOT, TGATTRIBUT, 5}, + { "dotsaxis", TDOTSAXIS, MS_DOTSAXIS, TGSTANDALONE, 5}, // 5 to continue expression + { "dotsdiag", TDOTSDIAG, MS_DOTSUP, TGSTANDALONE, 5}, // + { "dotsdown", TDOTSDOWN, MS_DOTSDOWN, TGSTANDALONE, 5}, // + { "dotslow", TDOTSLOW, MS_DOTSLOW, TGSTANDALONE, 5}, // + { "dotsup", TDOTSUP, MS_DOTSUP, TGSTANDALONE, 5}, // + { "dotsvert", TDOTSVERT, MS_DOTSVERT, TGSTANDALONE, 5}, // + { "downarrow" , TDOWNARROW, MS_DOWNARROW, TGSTANDALONE, 5}, + { "drarrow" , TDRARROW, MS_DRARROW, TGSTANDALONE, 5}, + { "emptyset" , TEMPTYSET, MS_EMPTYSET, TGSTANDALONE, 5}, + { "equiv", TEQUIV, MS_EQUIV, TGRELATION, 0}, + { "exists", TEXISTS, MS_EXISTS, TGSTANDALONE, 5}, + { "exp", TEXP, '\0', TGFUNCTION, 5}, + { "fact", TFACT, MS_FACT, TGUNOPER, 5}, + { "fixed", TFIXED, '\0', TGFONT, 0}, + { "font", TFONT, '\0', TGFONTATTR, 5}, + { "forall", TFORALL, MS_FORALL, TGSTANDALONE, 5}, + { "from", TFROM, '\0', TGLIMIT, 0}, + { "func", TFUNC, '\0', TGFUNCTION, 5}, + { "ge", TGE, MS_GE, TGRELATION, 0}, + { "geslant", TGESLANT, MS_GESLANT, TGRELATION, 0 }, + { "gg", TGG, MS_GG, TGRELATION, 0}, + { "grave", TGRAVE, MS_GRAVE, TGATTRIBUT, 5}, + { "green", TGREEN, '\0', TGCOLOR, 0}, + { "gt", TGT, MS_GT, TGRELATION, 0}, + { "hat", THAT, MS_HAT, TGATTRIBUT, 5}, + { "hbar" , THBAR, MS_HBAR, TGSTANDALONE, 5}, + { "iiint", TIIINT, MS_IIINT, TGOPER, 5}, + { "iint", TIINT, MS_IINT, TGOPER, 5}, + { "in", TIN, MS_IN, TGRELATION, 0}, + { "infinity" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5}, + { "infty" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5}, + { "int", TINT, MS_INT, TGOPER, 5}, + { "intersection", TINTERSECT, MS_INTERSECT, TGPRODUCT, 0}, + { "ital", TITALIC, '\0', TGFONTATTR, 5}, + { "italic", TITALIC, '\0', TGFONTATTR, 5}, + { "lambdabar" , TLAMBDABAR, MS_LAMBDABAR, TGSTANDALONE, 5}, + { "langle", TLANGLE, MS_LANGLE, TGLBRACES, 5}, + { "lbrace", TLBRACE, MS_LBRACE, TGLBRACES, 5}, + { "lceil", TLCEIL, MS_LCEIL, TGLBRACES, 5}, + { "ldbracket", TLDBRACKET, MS_LDBRACKET, TGLBRACES, 5}, + { "ldline", TLDLINE, MS_DLINE, TGLBRACES, 5}, + { "le", TLE, MS_LE, TGRELATION, 0}, + { "left", TLEFT, '\0', 0, 5}, + { "leftarrow" , TLEFTARROW, MS_LEFTARROW, TGSTANDALONE, 5}, + { "leslant", TLESLANT, MS_LESLANT, TGRELATION, 0 }, + { "lfloor", TLFLOOR, MS_LFLOOR, TGLBRACES, 5}, + { "lim", TLIM, '\0', TGOPER, 5}, + { "liminf", TLIMINF, '\0', TGOPER, 5}, + { "limsup", TLIMSUP, '\0', TGOPER, 5}, + { "lint", TLINT, MS_LINT, TGOPER, 5}, + { "ll", TLL, MS_LL, TGRELATION, 0}, + { "lline", TLLINE, MS_LINE, TGLBRACES, 5}, + { "llint", TLLINT, MS_LLINT, TGOPER, 5}, + { "lllint", TLLLINT, MS_LLLINT, TGOPER, 5}, + { "ln", TLN, '\0', TGFUNCTION, 5}, + { "log", TLOG, '\0', TGFUNCTION, 5}, + { "lsub", TLSUB, '\0', TGPOWER, 0}, + { "lsup", TLSUP, '\0', TGPOWER, 0}, + { "lt", TLT, MS_LT, TGRELATION, 0}, + { "magenta", TMAGENTA, '\0', TGCOLOR, 0}, + { "matrix", TMATRIX, '\0', 0, 5}, + { "minusplus", TMINUSPLUS, MS_MINUSPLUS, TGUNOPER | TGSUM, 5}, + { "mline", TMLINE, MS_LINE, 0, 0}, //! nicht in TGRBRACES, Level 0 + { "nabla", TNABLA, MS_NABLA, TGSTANDALONE, 5}, + { "nbold", TNBOLD, '\0', TGFONTATTR, 5}, + { "ndivides", TNDIVIDES, MS_NDIVIDES, TGRELATION, 0}, + { "neg", TNEG, MS_NEG, TGUNOPER, 5 }, + { "neq", TNEQ, MS_NEQ, TGRELATION, 0}, + { "newline", TNEWLINE, '\0', 0, 0}, + { "ni", TNI, MS_NI, TGRELATION, 0}, + { "nitalic", TNITALIC, '\0', TGFONTATTR, 5}, + { "none", TNONE, '\0', TGLBRACES | TGRBRACES, 0}, + { "nospace", TNOSPACE, '\0', TGSTANDALONE, 5}, + { "notin", TNOTIN, MS_NOTIN, TGRELATION, 0}, + { "nroot", TNROOT, MS_SQRT, TGUNOPER, 5}, + { "nsubset", TNSUBSET, MS_NSUBSET, TGRELATION, 0 }, + { "nsupset", TNSUPSET, MS_NSUPSET, TGRELATION, 0 }, + { "nsubseteq", TNSUBSETEQ, MS_NSUBSETEQ, TGRELATION, 0 }, + { "nsupseteq", TNSUPSETEQ, MS_NSUPSETEQ, TGRELATION, 0 }, + { "odivide", TODIVIDE, MS_ODIVIDE, TGPRODUCT, 0}, + { "odot", TODOT, MS_ODOT, TGPRODUCT, 0}, + { "ominus", TOMINUS, MS_OMINUS, TGSUM, 0}, + { "oper", TOPER, '\0', TGOPER, 5}, + { "oplus", TOPLUS, MS_OPLUS, TGSUM, 0}, + { "or", TOR, MS_OR, TGSUM, 0}, + { "ortho", TORTHO, MS_ORTHO, TGRELATION, 0}, + { "otimes", TOTIMES, MS_OTIMES, TGPRODUCT, 0}, + { "over", TOVER, '\0', TGPRODUCT, 0}, + { "overbrace", TOVERBRACE, MS_OVERBRACE, TGPRODUCT, 5}, + { "overline", TOVERLINE, '\0', TGATTRIBUT, 5}, + { "overstrike", TOVERSTRIKE, '\0', TGATTRIBUT, 5}, + { "owns", TNI, MS_NI, TGRELATION, 0}, + { "parallel", TPARALLEL, MS_DLINE, TGRELATION, 0}, + { "partial", TPARTIAL, MS_PARTIAL, TGSTANDALONE, 5 }, + { "phantom", TPHANTOM, '\0', TGFONTATTR, 5}, + { "plusminus", TPLUSMINUS, MS_PLUSMINUS, TGUNOPER | TGSUM, 5}, + { "prod", TPROD, MS_PROD, TGOPER, 5}, + { "prop", TPROP, MS_PROP, TGRELATION, 0}, + { "rangle", TRANGLE, MS_RANGLE, TGRBRACES, 0}, //! 0 to terminate expression + { "rbrace", TRBRACE, MS_RBRACE, TGRBRACES, 0}, // + { "rceil", TRCEIL, MS_RCEIL, TGRBRACES, 0}, // + { "rdbracket", TRDBRACKET, MS_RDBRACKET, TGRBRACES, 0}, // + { "rdline", TRDLINE, MS_DLINE, TGRBRACES, 0}, // + { "red", TRED, '\0', TGCOLOR, 0}, + { "rfloor", TRFLOOR, MS_RFLOOR, TGRBRACES, 0}, //! 0 to terminate expression + { "right", TRIGHT, '\0', 0, 0}, + { "rightarrow" , TRIGHTARROW, MS_RIGHTARROW, TGSTANDALONE, 5}, + { "rline", TRLINE, MS_LINE, TGRBRACES, 0}, //! 0 to terminate expression + { "rsub", TRSUB, '\0', TGPOWER, 0}, + { "rsup", TRSUP, '\0', TGPOWER, 0}, + { "sans", TSANS, '\0', TGFONT, 0}, + { "serif", TSERIF, '\0', TGFONT, 0}, + { "setC" , TSETC, MS_SETC, TGSTANDALONE, 5}, + { "setN" , TSETN, MS_SETN, TGSTANDALONE, 5}, + { "setQ" , TSETQ, MS_SETQ, TGSTANDALONE, 5}, + { "setR" , TSETR, MS_SETR, TGSTANDALONE, 5}, + { "setZ" , TSETZ, MS_SETZ, TGSTANDALONE, 5}, + { "setminus", TBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 }, + { "sim", TSIM, MS_SIM, TGRELATION, 0}, + { "simeq", TSIMEQ, MS_SIMEQ, TGRELATION, 0}, + { "sin", TSIN, '\0', TGFUNCTION, 5}, + { "sinh", TSINH, '\0', TGFUNCTION, 5}, + { "size", TSIZE, '\0', TGFONTATTR, 5}, + { "slash", TSLASH, MS_SLASH, TGPRODUCT, 0 }, + { "sqrt", TSQRT, MS_SQRT, TGUNOPER, 5}, + { "stack", TSTACK, '\0', 0, 5}, + { "sub", TRSUB, '\0', TGPOWER, 0}, + { "subset", TSUBSET, MS_SUBSET, TGRELATION, 0}, + { "subseteq", TSUBSETEQ, MS_SUBSETEQ, TGRELATION, 0}, + { "sum", TSUM, MS_SUM, TGOPER, 5}, + { "sup", TRSUP, '\0', TGPOWER, 0}, + { "supset", TSUPSET, MS_SUPSET, TGRELATION, 0}, + { "supseteq", TSUPSETEQ, MS_SUPSETEQ, TGRELATION, 0}, + { "tan", TTAN, '\0', TGFUNCTION, 5}, + { "tanh", TTANH, '\0', TGFUNCTION, 5}, + { "tilde", TTILDE, MS_TILDE, TGATTRIBUT, 5}, + { "times", TTIMES, MS_TIMES, TGPRODUCT, 0}, + { "to", TTO, '\0', TGLIMIT, 0}, + { "toward", TTOWARD, MS_RIGHTARROW, TGRELATION, 0}, + { "transl", TTRANSL, MS_TRANSL, TGRELATION, 0}, + { "transr", TTRANSR, MS_TRANSR, TGRELATION, 0}, + { "underbrace", TUNDERBRACE, MS_UNDERBRACE, TGPRODUCT, 5}, + { "underline", TUNDERLINE, '\0', TGATTRIBUT, 5}, + { "union", TUNION, MS_UNION, TGSUM, 0}, + { "uoper", TUOPER, '\0', TGUNOPER, 5}, + { "uparrow" , TUPARROW, MS_UPARROW, TGSTANDALONE, 5}, + { "vec", TVEC, MS_VEC, TGATTRIBUT, 5}, + { "white", TWHITE, '\0', TGCOLOR, 0}, + { "widebslash", TWIDEBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 }, + { "widehat", TWIDEHAT, MS_HAT, TGATTRIBUT, 5}, + { "widetilde", TWIDETILDE, MS_TILDE, TGATTRIBUT, 5}, + { "wideslash", TWIDESLASH, MS_SLASH, TGPRODUCT, 0 }, + { "widevec", TWIDEVEC, MS_VEC, TGATTRIBUT, 5}, + { "wp" , TWP, MS_WP, TGSTANDALONE, 5}, + { "yellow", TYELLOW, '\0', TGCOLOR, 0}, + { "", TEND, '\0', 0, 0} +}; + +const SmTokenTableEntry * SmParser::GetTokenTableEntry( const String &rName ) +{ + const SmTokenTableEntry * pRes = 0; + if (rName.Len()) + { + sal_Int32 nEntries = SAL_N_ELEMENTS(aTokenTable); + for (sal_Int32 i = 0; i < nEntries; ++i) + { + if (rName.EqualsIgnoreCaseAscii( aTokenTable[i].pIdent )) + { + pRes = &aTokenTable[i]; + break; + } + } + + } + + return pRes; +} + + +/////////////////////////////////////////////////////////////////////////// + +#if OSL_DEBUG_LEVEL > 1 + +bool SmParser::IsDelimiter( const String &rTxt, xub_StrLen nPos ) + // returns 'true' iff cChar is '\0' or a delimeter +{ + OSL_ENSURE( nPos <= rTxt.Len(), "index out of range" ); + + sal_Unicode cChar = rTxt.GetChar( nPos ); + if(!cChar) + return true; + + // check if 'cChar' is in the delimeter table + const sal_Unicode *pDelim = &aDelimiterTable[0]; + for ( ; *pDelim != 0; pDelim++) + if (*pDelim == cChar) + break; + + + sal_Int16 nTypJp = SM_MOD()->GetSysLocale().GetCharClass().getType( rTxt, nPos ); + bool bIsDelim = (*pDelim != 0 || + nTypJp == com::sun::star::i18n::UnicodeType::SPACE_SEPARATOR || + nTypJp == com::sun::star::i18n::UnicodeType::CONTROL); + + return bIsDelim; +} + +#endif + +void SmParser::Insert(const String &rText, sal_uInt16 nPos) +{ + m_aBufferString.Insert(rText, nPos); + + xub_StrLen nLen = rText.Len(); + m_nBufferIndex = m_nBufferIndex + nLen; + m_nTokenIndex = m_nTokenIndex + nLen; +} + + +void SmParser::Replace( sal_uInt16 nPos, sal_uInt16 nLen, const String &rText ) +{ + OSL_ENSURE( nPos + nLen <= m_aBufferString.Len(), "argument mismatch" ); + + m_aBufferString.Replace( nPos, nLen, rText ); + sal_Int16 nChg = rText.Len() - nLen; + m_nBufferIndex = m_nBufferIndex + nChg; + m_nTokenIndex = m_nTokenIndex + nChg; +} + + +// First character may be any alphabetic +const sal_Int32 coStartFlags = + KParseTokens::ANY_LETTER_OR_NUMBER | + KParseTokens::IGNORE_LEADING_WS; + +// Continuing characters may be any alphanumeric or dot. +const sal_Int32 coContFlags = + ((coStartFlags | KParseTokens::ASC_DOT) & ~KParseTokens::IGNORE_LEADING_WS) + | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING; + +// First character for numbers, may be any numeric or dot +const sal_Int32 coNumStartFlags = + KParseTokens::ASC_DIGIT | + KParseTokens::ASC_DOT | + KParseTokens::IGNORE_LEADING_WS; +// Continuing characters for numbers, may be any numeric or dot. +const sal_Int32 coNumContFlags = + (coNumStartFlags | KParseTokens::ASC_DOT) & ~KParseTokens::IGNORE_LEADING_WS; + +void SmParser::NextToken() +{ + static const String aEmptyStr; + + xub_StrLen nBufLen = m_aBufferString.Len(); + ParseResult aRes; + xub_StrLen nRealStart; + bool bCont; + bool bNumStart = false; + CharClass aCC(SM_MOD()->GetSysLocale().GetCharClass().getLocale()); + do + { + // skip white spaces + while (UnicodeType::SPACE_SEPARATOR == + aCC.getType( m_aBufferString, m_nBufferIndex )) + ++m_nBufferIndex; + + sal_Int32 nStartFlags = coStartFlags; + sal_Int32 nContFlags = coContFlags; + sal_Unicode cFirstChar = m_aBufferString.GetChar( m_nBufferIndex ); + aRes = aCC.parseAnyToken( m_aBufferString, m_nBufferIndex, + nStartFlags, aEmptyStr, + nContFlags, aEmptyStr ); + + // #i45779# parse numbers correctly + // i.e. independent from the locale setting. + // (note that #i11752# remains fixed) + if ((aRes.TokenType & KParseType::IDENTNAME) && IsDigit( cFirstChar )) + { + ParseResult aTmpRes; + lang::Locale aOldLoc( aCC.getLocale() ); + aCC.setLocale( m_aDotLoc ); + aTmpRes = aCC.parsePredefinedToken( + KParseType::ASC_NUMBER, + m_aBufferString, m_nBufferIndex, + KParseTokens::ASC_DIGIT, aEmptyStr, + KParseTokens::ASC_DIGIT | KParseTokens::ASC_DOT, aEmptyStr ); + aCC.setLocale( aOldLoc ); + if (aTmpRes.TokenType & KParseType::ASC_NUMBER) + aRes.TokenType = aTmpRes.TokenType; + } + + nRealStart = m_nBufferIndex + sal::static_int_cast< xub_StrLen >(aRes.LeadingWhiteSpace); + m_nBufferIndex = nRealStart; + + bCont = false; + if ( aRes.TokenType == 0 && + nRealStart < nBufLen && + '\n' == m_aBufferString.GetChar( nRealStart ) ) + { + // keep data needed for tokens row and col entry up to date + ++m_Row; + m_nBufferIndex = m_nColOff = nRealStart + 1; + bCont = true; + } + else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR) + { + String aName( m_aBufferString.Copy( nRealStart, 2 )); + if ( aName.EqualsAscii( "%%" )) + { + //SkipComment + m_nBufferIndex = nRealStart + 2; + while (m_nBufferIndex < nBufLen && + '\n' != m_aBufferString.GetChar( m_nBufferIndex )) + ++m_nBufferIndex; + bCont = true; + } + } + + } while (bCont); + + // set index of current token + m_nTokenIndex = m_nBufferIndex; + + m_aCurToken.nRow = m_Row; + m_aCurToken.nCol = nRealStart - m_nColOff + 1; + + bool bHandled = true; + if (nRealStart >= nBufLen) + { + m_aCurToken.eType = TEND; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.Erase(); + } + else if ((aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER)) + || (bNumStart && (aRes.TokenType & KParseType::IDENTNAME))) + { + sal_Int32 n = aRes.EndPos - nRealStart; + OSL_ENSURE( n >= 0, "length < 0" ); + m_aCurToken.eType = TNUMBER; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 5; + m_aCurToken.aText = m_aBufferString.Copy( nRealStart, sal::static_int_cast< xub_StrLen >(n) ); + +#if OSL_DEBUG_LEVEL > 1 + if (!IsDelimiter( m_aBufferString, static_cast< xub_StrLen >(aRes.EndPos) )) + { + OSL_FAIL( "identifier really finished? (compatibility!)" ); + } +#endif + } + else if (aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING) + { + m_aCurToken.eType = TTEXT; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 5; + m_aCurToken.aText = aRes.DequotedNameOrString; + m_aCurToken.nRow = m_Row; + m_aCurToken.nCol = nRealStart - m_nColOff + 2; + } + else if (aRes.TokenType & KParseType::IDENTNAME) + { + sal_Int32 n = aRes.EndPos - nRealStart; + OSL_ENSURE( n >= 0, "length < 0" ); + String aName( m_aBufferString.Copy( nRealStart, sal::static_int_cast< xub_StrLen >(n) ) ); + const SmTokenTableEntry *pEntry = GetTokenTableEntry( aName ); + + if (pEntry) + { + m_aCurToken.eType = pEntry->eType; + m_aCurToken.cMathChar = pEntry->cMathChar; + m_aCurToken.nGroup = pEntry->nGroup; + m_aCurToken.nLevel = pEntry->nLevel; + m_aCurToken.aText.AssignAscii( pEntry->pIdent ); + } + else + { + m_aCurToken.eType = TIDENT; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 5; + m_aCurToken.aText = aName; + +#if OSL_DEBUG_LEVEL > 1 + if (!IsDelimiter( m_aBufferString, static_cast< xub_StrLen >(aRes.EndPos) )) + { + OSL_FAIL( "identifier really finished? (compatibility!)" ); + } +#endif + } + } + else if (aRes.TokenType == 0 && '_' == m_aBufferString.GetChar( nRealStart )) + { + m_aCurToken.eType = TRSUB; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = TGPOWER; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "_" ); + + aRes.EndPos = nRealStart + 1; + } + else if (aRes.TokenType & KParseType::BOOLEAN) + { + sal_Int32 &rnEndPos = aRes.EndPos; + String aName( m_aBufferString.Copy( nRealStart, + sal::static_int_cast< xub_StrLen >(rnEndPos - nRealStart) )); + if (2 >= aName.Len()) + { + sal_Unicode ch = aName.GetChar( 0 ); + switch (ch) + { + case '<': + { + if (m_aBufferString.Copy( nRealStart, 2 ). + EqualsAscii( "<<" )) + { + m_aCurToken.eType = TLL; + m_aCurToken.cMathChar = MS_LL; + m_aCurToken.nGroup = TGRELATION; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "<<" ); + + rnEndPos = nRealStart + 2; + } + else if (m_aBufferString.Copy( nRealStart, 2 ). + EqualsAscii( "<=" )) + { + m_aCurToken.eType = TLE; + m_aCurToken.cMathChar = MS_LE; + m_aCurToken.nGroup = TGRELATION; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "<=" ); + + rnEndPos = nRealStart + 2; + } + else if (m_aBufferString.Copy( nRealStart, 2 ). + EqualsAscii( "<>" )) + { + m_aCurToken.eType = TNEQ; + m_aCurToken.cMathChar = MS_NEQ; + m_aCurToken.nGroup = TGRELATION; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "<>" ); + + rnEndPos = nRealStart + 2; + } + else if (m_aBufferString.Copy( nRealStart, 3 ). + EqualsAscii( "<?>" )) + { + m_aCurToken.eType = TPLACE; + m_aCurToken.cMathChar = MS_PLACE; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "<?>" ); + + rnEndPos = nRealStart + 3; + } + else + { + m_aCurToken.eType = TLT; + m_aCurToken.cMathChar = MS_LT; + m_aCurToken.nGroup = TGRELATION; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "<" ); + } + } + break; + case '>': + { + if (m_aBufferString.Copy( nRealStart, 2 ). + EqualsAscii( ">=" )) + { + m_aCurToken.eType = TGE; + m_aCurToken.cMathChar = MS_GE; + m_aCurToken.nGroup = TGRELATION; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( ">=" ); + + rnEndPos = nRealStart + 2; + } + else if (m_aBufferString.Copy( nRealStart, 2 ). + EqualsAscii( ">>" )) + { + m_aCurToken.eType = TGG; + m_aCurToken.cMathChar = MS_GG; + m_aCurToken.nGroup = TGRELATION; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( ">>" ); + + rnEndPos = nRealStart + 2; + } + else + { + m_aCurToken.eType = TGT; + m_aCurToken.cMathChar = MS_GT; + m_aCurToken.nGroup = TGRELATION; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( ">" ); + } + } + break; + default: + bHandled = false; + } + } + } + else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR) + { + sal_Int32 &rnEndPos = aRes.EndPos; + String aName( m_aBufferString.Copy( nRealStart, + sal::static_int_cast< xub_StrLen >(rnEndPos - nRealStart) ) ); + + if (1 == aName.Len()) + { + sal_Unicode ch = aName.GetChar( 0 ); + switch (ch) + { + case '%': + { + //! modifies aRes.EndPos + + OSL_ENSURE( rnEndPos >= nBufLen || + '%' != m_aBufferString.GetChar( sal::static_int_cast< xub_StrLen >(rnEndPos) ), + "unexpected comment start" ); + + // get identifier of user-defined character + ParseResult aTmpRes = aCC.parseAnyToken( + m_aBufferString, rnEndPos, + KParseTokens::ANY_LETTER, + aEmptyStr, + coContFlags, + aEmptyStr ); + + xub_StrLen nTmpStart = sal::static_int_cast< xub_StrLen >(rnEndPos + + aTmpRes.LeadingWhiteSpace); + + // default setting for the case that no identifier + // i.e. a valid symbol-name is following the '%' + // character + m_aCurToken.eType = TTEXT; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 5; + m_aCurToken.aText = String(); + m_aCurToken.nRow = sal::static_int_cast< xub_StrLen >(m_Row); + m_aCurToken.nCol = nTmpStart - m_nColOff; + + if (aTmpRes.TokenType & KParseType::IDENTNAME) + { + + xub_StrLen n = sal::static_int_cast< xub_StrLen >(aTmpRes.EndPos - nTmpStart); + m_aCurToken.eType = TSPECIAL; + m_aCurToken.aText = m_aBufferString.Copy( sal::static_int_cast< xub_StrLen >(nTmpStart-1), n+1 ); + + OSL_ENSURE( aTmpRes.EndPos > rnEndPos, + "empty identifier" ); + if (aTmpRes.EndPos > rnEndPos) + rnEndPos = aTmpRes.EndPos; + else + ++rnEndPos; + } + + // if no symbol-name was found we start-over with + // finding the next token right afer the '%' sign. + // I.e. we leave rnEndPos unmodified. + } + break; + case '[': + { + m_aCurToken.eType = TLBRACKET; + m_aCurToken.cMathChar = MS_LBRACKET; + m_aCurToken.nGroup = TGLBRACES; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "[" ); + } + break; + case '\\': + { + m_aCurToken.eType = TESCAPE; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "\\" ); + } + break; + case ']': + { + m_aCurToken.eType = TRBRACKET; + m_aCurToken.cMathChar = MS_RBRACKET; + m_aCurToken.nGroup = TGRBRACES; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "]" ); + } + break; + case '^': + { + m_aCurToken.eType = TRSUP; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = TGPOWER; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "^" ); + } + break; + case '`': + { + m_aCurToken.eType = TSBLANK; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = TGBLANK; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "`" ); + } + break; + case '{': + { + m_aCurToken.eType = TLGROUP; + m_aCurToken.cMathChar = MS_LBRACE; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "{" ); + } + break; + case '|': + { + m_aCurToken.eType = TOR; + m_aCurToken.cMathChar = MS_OR; + m_aCurToken.nGroup = TGSUM; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "|" ); + } + break; + case '}': + { + m_aCurToken.eType = TRGROUP; + m_aCurToken.cMathChar = MS_RBRACE; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "}" ); + } + break; + case '~': + { + m_aCurToken.eType = TBLANK; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = TGBLANK; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "~" ); + } + break; + case '#': + { + if (m_aBufferString.Copy( nRealStart, 2 ). + EqualsAscii( "##" )) + { + m_aCurToken.eType = TDPOUND; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "##" ); + + rnEndPos = nRealStart + 2; + } + else + { + m_aCurToken.eType = TPOUND; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "#" ); + } + } + break; + case '&': + { + m_aCurToken.eType = TAND; + m_aCurToken.cMathChar = MS_AND; + m_aCurToken.nGroup = TGPRODUCT; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "&" ); + } + break; + case '(': + { + m_aCurToken.eType = TLPARENT; + m_aCurToken.cMathChar = MS_LPARENT; + m_aCurToken.nGroup = TGLBRACES; + m_aCurToken.nLevel = 5; //! 0 to continue expression + m_aCurToken.aText.AssignAscii( "(" ); + } + break; + case ')': + { + m_aCurToken.eType = TRPARENT; + m_aCurToken.cMathChar = MS_RPARENT; + m_aCurToken.nGroup = TGRBRACES; + m_aCurToken.nLevel = 0; //! 0 to terminate expression + m_aCurToken.aText.AssignAscii( ")" ); + } + break; + case '*': + { + m_aCurToken.eType = TMULTIPLY; + m_aCurToken.cMathChar = MS_MULTIPLY; + m_aCurToken.nGroup = TGPRODUCT; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "*" ); + } + break; + case '+': + { + if (m_aBufferString.Copy( nRealStart, 2 ). + EqualsAscii( "+-" )) + { + m_aCurToken.eType = TPLUSMINUS; + m_aCurToken.cMathChar = MS_PLUSMINUS; + m_aCurToken.nGroup = TGUNOPER | TGSUM; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "+-" ); + + rnEndPos = nRealStart + 2; + } + else + { + m_aCurToken.eType = TPLUS; + m_aCurToken.cMathChar = MS_PLUS; + m_aCurToken.nGroup = TGUNOPER | TGSUM; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "+" ); + } + } + break; + case '-': + { + if (m_aBufferString.Copy( nRealStart, 2 ). + EqualsAscii( "-+" )) + { + m_aCurToken.eType = TMINUSPLUS; + m_aCurToken.cMathChar = MS_MINUSPLUS; + m_aCurToken.nGroup = TGUNOPER | TGSUM; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "-+" ); + + rnEndPos = nRealStart + 2; + } + else + { + m_aCurToken.eType = TMINUS; + m_aCurToken.cMathChar = MS_MINUS; + m_aCurToken.nGroup = TGUNOPER | TGSUM; + m_aCurToken.nLevel = 5; + m_aCurToken.aText.AssignAscii( "-" ); + } + } + break; + case '.': + { + // for compatibility with SO5.2 + // texts like .34 ...56 ... h ...78..90 + // will be treated as numbers + m_aCurToken.eType = TNUMBER; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 5; + + xub_StrLen nTxtStart = m_nBufferIndex; + sal_Unicode cChar; + do + { + cChar = m_aBufferString.GetChar( ++m_nBufferIndex ); + } + while ( cChar == '.' || IsDigit( cChar ) ); + + m_aCurToken.aText = m_aBufferString.Copy( sal::static_int_cast< xub_StrLen >(nTxtStart), + sal::static_int_cast< xub_StrLen >(m_nBufferIndex - nTxtStart) ); + aRes.EndPos = m_nBufferIndex; + } + break; + case '/': + { + m_aCurToken.eType = TDIVIDEBY; + m_aCurToken.cMathChar = MS_SLASH; + m_aCurToken.nGroup = TGPRODUCT; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "/" ); + } + break; + case '=': + { + m_aCurToken.eType = TASSIGN; + m_aCurToken.cMathChar = MS_ASSIGN; + m_aCurToken.nGroup = TGRELATION; + m_aCurToken.nLevel = 0; + m_aCurToken.aText.AssignAscii( "=" ); + } + break; + default: + bHandled = false; + } + } + } + else + bHandled = false; + + if (!bHandled) + { + m_aCurToken.eType = TCHARACTER; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = 0; + m_aCurToken.nLevel = 5; + m_aCurToken.aText = m_aBufferString.Copy( nRealStart, 1 ); + + aRes.EndPos = nRealStart + 1; + } + + if (TEND != m_aCurToken.eType) + m_nBufferIndex = sal::static_int_cast< xub_StrLen >(aRes.EndPos); +} + + +//////////////////////////////////////// +// grammar +// + + +void SmParser::Table() +{ + SmNodeArray LineArray; + + Line(); + while (m_aCurToken.eType == TNEWLINE) + { + NextToken(); + Line(); + } + + if (m_aCurToken.eType != TEND) + Error(PE_UNEXPECTED_CHAR); + + sal_uLong n = m_aNodeStack.Count(); + + LineArray.resize(n); + + for (sal_uLong i = 0; i < n; i++) + LineArray[n - (i + 1)] = m_aNodeStack.Pop(); + + SmStructureNode *pSNode = new SmTableNode(m_aCurToken); + pSNode->SetSubNodes(LineArray); + m_aNodeStack.Push(pSNode); +} + + +void SmParser::Align() + // parse alignment info (if any), then go on with rest of expression +{ + SmStructureNode *pSNode = 0; + bool bNeedGroupClose = false; + + if (TokenInGroup(TGALIGN)) + { + if (CONVERT_40_TO_50 == GetConversion()) + // encapsulate expression to be aligned in group braces + // (here group-open brace) + { Insert('{', GetTokenIndex()); + bNeedGroupClose = true; + + // get first valid align statement in sequence + // (the dominant one in 4.0) and erase all others (especially old + // discarded tokens) from command string. + while (TokenInGroup(TGALIGN)) + { + if (TokenInGroup(TGDISCARDED) || pSNode) + { + m_nBufferIndex = GetTokenIndex(); + m_aBufferString.Erase(m_nBufferIndex, m_aCurToken.aText.Len()); + } + else + pSNode = new SmAlignNode(m_aCurToken); + + NextToken(); + } + } + else + { + pSNode = new SmAlignNode(m_aCurToken); + + NextToken(); + + // allow for just one align statement in 5.0 + if (CONVERT_40_TO_50 != GetConversion() && TokenInGroup(TGALIGN)) + { Error(PE_DOUBLE_ALIGN); + return; + } + } + } + + Expression(); + + if (bNeedGroupClose) + Insert('}', GetTokenIndex()); + + if (pSNode) + { pSNode->SetSubNodes(m_aNodeStack.Pop(), 0); + m_aNodeStack.Push(pSNode); + } +} + + +void SmParser::Line() +{ + sal_uInt16 n = 0; + SmNodeArray ExpressionArray; + + ExpressionArray.resize(n); + + // start with single expression that may have an alignment statement + // (and go on with expressions that must not have alignment + // statements in 'while' loop below. See also 'Expression()'.) + if (m_aCurToken.eType != TEND && m_aCurToken.eType != TNEWLINE) + { Align(); + ExpressionArray.resize(++n); + ExpressionArray[n - 1] = m_aNodeStack.Pop(); + } + + while (m_aCurToken.eType != TEND && m_aCurToken.eType != TNEWLINE) + { if (CONVERT_40_TO_50 != GetConversion()) + Expression(); + else + Align(); + ExpressionArray.resize(++n); + ExpressionArray[n - 1] = m_aNodeStack.Pop(); + } + + //If there's no expression, add an empty one. + //this is to avoid a formula tree without any caret + //positions, in visual formula editor. + if(ExpressionArray.size() == 0) + ExpressionArray.push_back(new SmExpressionNode(SmToken())); + + SmStructureNode *pSNode = new SmLineNode(m_aCurToken); + pSNode->SetSubNodes(ExpressionArray); + m_aNodeStack.Push(pSNode); +} + + +void SmParser::Expression() +{ + bool bUseExtraSpaces = true; + SmNode *pNode = m_aNodeStack.Pop(); + if (pNode) + { + if (pNode->GetToken().eType == TNOSPACE) + bUseExtraSpaces = false; + else + m_aNodeStack.Push(pNode); // push the node from above again (now to be used as argument to this current 'nospace' node) + } + + sal_uInt16 n = 0; + SmNodeArray RelationArray; + + RelationArray.resize(n); + + Relation(); + RelationArray.resize(++n); + RelationArray[n - 1] = m_aNodeStack.Pop(); + + while (m_aCurToken.nLevel >= 4) + { Relation(); + RelationArray.resize(++n); + RelationArray[n - 1] = m_aNodeStack.Pop(); + } + + SmExpressionNode *pSNode = new SmExpressionNode(m_aCurToken); + pSNode->SetSubNodes(RelationArray); + pSNode->SetUseExtraSpaces(bUseExtraSpaces); + m_aNodeStack.Push(pSNode); +} + + +void SmParser::Relation() +{ + Sum(); + while (TokenInGroup(TGRELATION)) + { + SmStructureNode *pSNode = new SmBinHorNode(m_aCurToken); + SmNode *pFirst = m_aNodeStack.Pop(); + + OpSubSup(); + SmNode *pSecond = m_aNodeStack.Pop(); + + Sum(); + + pSNode->SetSubNodes(pFirst, pSecond, m_aNodeStack.Pop()); + m_aNodeStack.Push(pSNode); + } +} + + +void SmParser::Sum() +{ + Product(); + while (TokenInGroup(TGSUM)) + { + SmStructureNode *pSNode = new SmBinHorNode(m_aCurToken); + SmNode *pFirst = m_aNodeStack.Pop(); + + OpSubSup(); + SmNode *pSecond = m_aNodeStack.Pop(); + + Product(); + + pSNode->SetSubNodes(pFirst, pSecond, m_aNodeStack.Pop()); + m_aNodeStack.Push(pSNode); + } +} + + +void SmParser::Product() +{ + Power(); + + while (TokenInGroup(TGPRODUCT)) + { SmStructureNode *pSNode; + SmNode *pFirst = m_aNodeStack.Pop(), + *pOper; + bool bSwitchArgs = false; + + SmTokenType eType = m_aCurToken.eType; + switch (eType) + { + case TOVER: + pSNode = new SmBinVerNode(m_aCurToken); + pOper = new SmRectangleNode(m_aCurToken); + NextToken(); + break; + + case TBOPER: + pSNode = new SmBinHorNode(m_aCurToken); + + NextToken(); + + //Let the glyph node know it's a binary operation + m_aCurToken.eType = TBOPER; + m_aCurToken.nGroup = TGPRODUCT; + + GlyphSpecial(); + pOper = m_aNodeStack.Pop(); + break; + + case TOVERBRACE : + case TUNDERBRACE : + pSNode = new SmVerticalBraceNode(m_aCurToken); + pOper = new SmMathSymbolNode(m_aCurToken); + + NextToken(); + break; + + case TWIDEBACKSLASH: + case TWIDESLASH: + { + SmBinDiagonalNode *pSTmp = new SmBinDiagonalNode(m_aCurToken); + pSTmp->SetAscending(eType == TWIDESLASH); + pSNode = pSTmp; + + pOper = new SmPolyLineNode(m_aCurToken); + NextToken(); + + bSwitchArgs = true; + break; + } + + default: + pSNode = new SmBinHorNode(m_aCurToken); + + OpSubSup(); + pOper = m_aNodeStack.Pop(); + } + + Power(); + + if (bSwitchArgs) + //! vgl siehe SmBinDiagonalNode::Arrange + pSNode->SetSubNodes(pFirst, m_aNodeStack.Pop(), pOper); + else + pSNode->SetSubNodes(pFirst, pOper, m_aNodeStack.Pop()); + m_aNodeStack.Push(pSNode); + } +} + + +void SmParser::SubSup(sal_uLong nActiveGroup) +{ + OSL_ENSURE(nActiveGroup == TGPOWER || nActiveGroup == TGLIMIT, + "Sm: wrong token group"); + + if (!TokenInGroup(nActiveGroup)) + // already finish + return; + + SmSubSupNode *pNode = new SmSubSupNode(m_aCurToken); + //! Of course 'm_aCurToken' is just the first sub-/supscript token. + //! It should be of no further interest. The positions of the + //! sub-/supscripts will be identified by the corresponding subnodes + //! index in the 'aSubNodes' array (enum value from 'SmSubSup'). + + pNode->SetUseLimits(nActiveGroup == TGLIMIT); + + // initialize subnodes array + SmNodeArray aSubNodes; + aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES); + aSubNodes[0] = m_aNodeStack.Pop(); + for (sal_uInt16 i = 1; i < aSubNodes.size(); i++) + aSubNodes[i] = NULL; + + // process all sub-/supscripts + int nIndex = 0; + while (TokenInGroup(nActiveGroup)) + { SmTokenType eType (m_aCurToken.eType); + + // skip sub-/supscript token + NextToken(); + + // get sub-/supscript node on top of stack + if (eType == TFROM || eType == TTO) + { + // parse limits in old 4.0 and 5.0 style + Relation(); + } + else + Term(); + + switch (eType) + { case TRSUB : nIndex = (int) RSUB; break; + case TRSUP : nIndex = (int) RSUP; break; + case TFROM : + case TCSUB : nIndex = (int) CSUB; break; + case TTO : + case TCSUP : nIndex = (int) CSUP; break; + case TLSUB : nIndex = (int) LSUB; break; + case TLSUP : nIndex = (int) LSUP; break; + default : + OSL_FAIL("Sm: unknown case"); + } + nIndex++; + OSL_ENSURE(1 <= nIndex && nIndex <= 1 + SUBSUP_NUM_ENTRIES, + "SmParser::Power() : sub-/supscript index falsch"); + + // set sub-/supscript if not already done + if (aSubNodes[nIndex] != NULL) + Error(PE_DOUBLE_SUBSUPSCRIPT); + aSubNodes[nIndex] = m_aNodeStack.Pop(); + } + + pNode->SetSubNodes(aSubNodes); + m_aNodeStack.Push(pNode); +} + + +void SmParser::OpSubSup() +{ + // push operator symbol + m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken)); + // skip operator token + NextToken(); + // get sub- supscripts if any + if (TokenInGroup(TGPOWER)) + SubSup(TGPOWER); +} + + +void SmParser::Power() +{ + // get body for sub- supscripts on top of stack + Term(); + + SubSup(TGPOWER); +} + + +void SmParser::Blank() +{ + OSL_ENSURE(TokenInGroup(TGBLANK), "Sm : wrong token"); + SmBlankNode *pBlankNode = new SmBlankNode(m_aCurToken); + + while (TokenInGroup(TGBLANK)) + { + pBlankNode->IncreaseBy(m_aCurToken); + NextToken(); + } + + // Blanks am Zeilenende ignorieren wenn die entsprechende Option gesetzt ist + if ( m_aCurToken.eType == TNEWLINE || + (m_aCurToken.eType == TEND && SM_MOD()->GetConfig()->IsIgnoreSpacesRight()) ) + { + pBlankNode->Clear(); + } + + m_aNodeStack.Push(pBlankNode); +} + + +void SmParser::Term() +{ + switch (m_aCurToken.eType) + { + case TESCAPE : + Escape(); + break; + + case TNOSPACE : + case TLGROUP : + { + bool bNoSpace = m_aCurToken.eType == TNOSPACE; + if (bNoSpace) // push 'no space' node and continue to parse expression + { + m_aNodeStack.Push(new SmExpressionNode(m_aCurToken)); + NextToken(); + } + if (m_aCurToken.eType != TLGROUP) + { + m_aNodeStack.Pop(); // get rid of the 'no space' node pushed above + Term(); + } + else + { + NextToken(); + + // allow for empty group + if (m_aCurToken.eType == TRGROUP) + { + if (bNoSpace) // get rid of the 'no space' node pushed above + m_aNodeStack.Pop(); + SmStructureNode *pSNode = new SmExpressionNode(m_aCurToken); + pSNode->SetSubNodes(NULL, NULL); + m_aNodeStack.Push(pSNode); + + NextToken(); + } + else // go as usual + { + Align(); + if (m_aCurToken.eType != TRGROUP) + Error(PE_RGROUP_EXPECTED); + else + NextToken(); + } + } + } + break; + + case TLEFT : + Brace(); + break; + + case TBLANK : + case TSBLANK : + Blank(); + break; + + case TTEXT : + m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_TEXT)); + NextToken(); + break; + case TIDENT : + case TCHARACTER : + m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_VARIABLE)); + NextToken(); + break; + case TNUMBER : + m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_NUMBER)); + NextToken(); + break; + + case TLEFTARROW : + case TRIGHTARROW : + case TUPARROW : + case TDOWNARROW : + case TSETN : + case TSETZ : + case TSETQ : + case TSETR : + case TSETC : + case THBAR : + case TLAMBDABAR : + case TCIRC : + case TDRARROW : + case TDLARROW : + case TDLRARROW : + case TBACKEPSILON : + case TALEPH : + case TIM : + case TRE : + case TWP : + case TEMPTYSET : + case TINFINITY : + case TEXISTS : + case TFORALL : + case TPARTIAL : + case TNABLA : + case TTOWARD : + case TDOTSAXIS : + case TDOTSDIAG : + case TDOTSDOWN : + case TDOTSLOW : + case TDOTSUP : + case TDOTSVERT : + m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken)); + NextToken(); + break; + + case TPLACE: + m_aNodeStack.Push(new SmPlaceNode(m_aCurToken)); + NextToken(); + break; + + case TSPECIAL: + Special(); + break; + + case TBINOM: + Binom(); + break; + + case TSTACK: + Stack(); + break; + + case TMATRIX: + Matrix(); + break; + + default: + if (TokenInGroup(TGLBRACES)) + { Brace(); + } + else if (TokenInGroup(TGOPER)) + { Operator(); + } + else if (TokenInGroup(TGUNOPER)) + { UnOper(); + } + else if ( TokenInGroup(TGATTRIBUT) + || TokenInGroup(TGFONTATTR)) + { SmStructureNodeArray aArray; + + bool bIsAttr; + sal_uInt16 n = 0; + while (true == (bIsAttr = TokenInGroup(TGATTRIBUT)) + || TokenInGroup(TGFONTATTR)) + { aArray.resize(n + 1); + + if (bIsAttr) + Attribut(); + else + FontAttribut(); + + // check if casting in following line is ok + OSL_ENSURE(!m_aNodeStack.Top()->IsVisible(), "Sm : Ooops..."); + + aArray[n] = (SmStructureNode *) m_aNodeStack.Pop(); + n++; + } + + Power(); + + SmNode *pFirstNode = m_aNodeStack.Pop(); + while (n > 0) + { aArray[n - 1]->SetSubNodes(0, pFirstNode); + pFirstNode = aArray[n - 1]; + n--; + } + m_aNodeStack.Push(pFirstNode); + } + else if (TokenInGroup(TGFUNCTION)) + { if (CONVERT_40_TO_50 != GetConversion()) + { Function(); + } + else // encapsulate old 4.0 style parsing in braces + { + // insert opening brace + Insert('{', GetTokenIndex()); + + // + // parse in 4.0 style + // + Function(); + + SmNode *pFunc = m_aNodeStack.Pop(); + + if (m_aCurToken.eType == TLPARENT) + { Term(); + } + else + { Align(); + } + + // insert closing brace + Insert('}', GetTokenIndex()); + + SmStructureNode *pSNode = new SmExpressionNode(pFunc->GetToken()); + pSNode->SetSubNodes(pFunc, m_aNodeStack.Pop()); + m_aNodeStack.Push(pSNode); + } + } + else + Error(PE_UNEXPECTED_CHAR); + } +} + + +void SmParser::Escape() +{ + NextToken(); + + switch (m_aCurToken.eType) + { + case TLPARENT : + case TRPARENT : + case TLBRACKET : + case TRBRACKET : + case TLDBRACKET : + case TRDBRACKET : + case TLBRACE : + case TLGROUP : + case TRBRACE : + case TRGROUP : + case TLANGLE : + case TRANGLE : + case TLCEIL : + case TRCEIL : + case TLFLOOR : + case TRFLOOR : + case TLLINE : + case TRLINE : + case TLDLINE : + case TRDLINE : + break; + default: + Error(PE_UNEXPECTED_TOKEN); + } + + SmNode *pNode = new SmMathSymbolNode(m_aCurToken); + m_aNodeStack.Push(pNode); + + NextToken(); +} + + +void SmParser::Operator() +{ + if (TokenInGroup(TGOPER)) + { SmStructureNode *pSNode = new SmOperNode(m_aCurToken); + + // put operator on top of stack + Oper(); + + if (TokenInGroup(TGLIMIT) || TokenInGroup(TGPOWER)) + SubSup(m_aCurToken.nGroup); + SmNode *pOperator = m_aNodeStack.Pop(); + + // get argument + Power(); + + pSNode->SetSubNodes(pOperator, m_aNodeStack.Pop()); + m_aNodeStack.Push(pSNode); + } +} + + +void SmParser::Oper() +{ + SmTokenType eType (m_aCurToken.eType); + SmNode *pNode = NULL; + + switch (eType) + { + case TSUM : + case TPROD : + case TCOPROD : + case TINT : + case TIINT : + case TIIINT : + case TLINT : + case TLLINT : + case TLLLINT : + pNode = new SmMathSymbolNode(m_aCurToken); + break; + + case TLIM : + case TLIMSUP : + case TLIMINF : + { + const sal_Char* pLim = 0; + switch (eType) + { + case TLIM : pLim = "lim"; break; + case TLIMSUP : pLim = "lim sup"; break; + case TLIMINF : pLim = "lim inf"; break; + default: + break; + } + if( pLim ) + m_aCurToken.aText.AssignAscii( pLim ); + pNode = new SmTextNode(m_aCurToken, FNT_TEXT); + } + break; + + case TOVERBRACE : + case TUNDERBRACE : + pNode = new SmMathSymbolNode(m_aCurToken); + break; + + case TOPER : + NextToken(); + + OSL_ENSURE(m_aCurToken.eType == TSPECIAL, "Sm: wrong token"); + pNode = new SmGlyphSpecialNode(m_aCurToken); + break; + + default : + OSL_FAIL("Sm: unknown case"); + } + m_aNodeStack.Push(pNode); + + NextToken(); +} + + +void SmParser::UnOper() +{ + OSL_ENSURE(TokenInGroup(TGUNOPER), "Sm: wrong token"); + + SmToken aNodeToken = m_aCurToken; + SmTokenType eType = m_aCurToken.eType; + bool bIsPostfix = eType == TFACT; + + SmStructureNode *pSNode; + SmNode *pOper = 0, + *pExtra = 0, + *pArg; + + switch (eType) + { + case TABS : + case TSQRT : + NextToken(); + break; + + case TNROOT : + NextToken(); + Power(); + pExtra = m_aNodeStack.Pop(); + break; + + case TUOPER : + NextToken(); + //Let the glyph know what it is... + m_aCurToken.eType = TUOPER; + m_aCurToken.nGroup = TGUNOPER; + GlyphSpecial(); + pOper = m_aNodeStack.Pop(); + break; + + case TPLUS : + case TMINUS : + case TPLUSMINUS : + case TMINUSPLUS : + case TNEG : + case TFACT : + OpSubSup(); + pOper = m_aNodeStack.Pop(); + break; + + default : + Error(PE_UNOPER_EXPECTED); + } + + // get argument + Power(); + pArg = m_aNodeStack.Pop(); + + if (eType == TABS) + { pSNode = new SmBraceNode(aNodeToken); + pSNode->SetScaleMode(SCALE_HEIGHT); + + // build nodes for left & right lines + // (text, group, level of the used token are of no interrest here) + // we'll use row & column of the keyword for abs + aNodeToken.eType = TABS; + // + aNodeToken.cMathChar = MS_LINE; + SmNode* pLeft = new SmMathSymbolNode(aNodeToken); + // + aNodeToken.cMathChar = MS_LINE; + SmNode* pRight = new SmMathSymbolNode(aNodeToken); + + pSNode->SetSubNodes(pLeft, pArg, pRight); + } + else if (eType == TSQRT || eType == TNROOT) + { pSNode = new SmRootNode(aNodeToken); + pOper = new SmRootSymbolNode(aNodeToken); + pSNode->SetSubNodes(pExtra, pOper, pArg); + } + else + { pSNode = new SmUnHorNode(aNodeToken); + + if (bIsPostfix) + pSNode->SetSubNodes(pArg, pOper); + else + // prefix operator + pSNode->SetSubNodes(pOper, pArg); + } + + m_aNodeStack.Push(pSNode); +} + + +void SmParser::Attribut() +{ + OSL_ENSURE(TokenInGroup(TGATTRIBUT), "Sm: wrong token group"); + + SmStructureNode *pSNode = new SmAttributNode(m_aCurToken); + SmNode *pAttr; + SmScaleMode eScaleMode = SCALE_NONE; + + // get appropriate node for the attribut itself + switch (m_aCurToken.eType) + { case TUNDERLINE : + case TOVERLINE : + case TOVERSTRIKE : + pAttr = new SmRectangleNode(m_aCurToken); + eScaleMode = SCALE_WIDTH; + break; + + case TWIDEVEC : + case TWIDEHAT : + case TWIDETILDE : + pAttr = new SmMathSymbolNode(m_aCurToken); + eScaleMode = SCALE_WIDTH; + break; + + default : + pAttr = new SmMathSymbolNode(m_aCurToken); + } + + NextToken(); + + pSNode->SetSubNodes(pAttr, 0); + pSNode->SetScaleMode(eScaleMode); + m_aNodeStack.Push(pSNode); +} + + +void SmParser::FontAttribut() +{ + OSL_ENSURE(TokenInGroup(TGFONTATTR), "Sm: wrong token group"); + + switch (m_aCurToken.eType) + { + case TITALIC : + case TNITALIC : + case TBOLD : + case TNBOLD : + case TPHANTOM : + m_aNodeStack.Push(new SmFontNode(m_aCurToken)); + NextToken(); + break; + + case TSIZE : + FontSize(); + break; + + case TFONT : + Font(); + break; + + case TCOLOR : + Color(); + break; + + default : + OSL_FAIL("Sm: unknown case"); + } +} + + +void SmParser::Color() +{ + OSL_ENSURE(m_aCurToken.eType == TCOLOR, "Sm : Ooops..."); + + // last color rules, get that one + SmToken aToken; + do + { NextToken(); + + if (TokenInGroup(TGCOLOR)) + { aToken = m_aCurToken; + NextToken(); + } + else + Error(PE_COLOR_EXPECTED); + } while (m_aCurToken.eType == TCOLOR); + + m_aNodeStack.Push(new SmFontNode(aToken)); +} + + +void SmParser::Font() +{ + OSL_ENSURE(m_aCurToken.eType == TFONT, "Sm : Ooops..."); + + // last font rules, get that one + SmToken aToken; + do + { NextToken(); + + if (TokenInGroup(TGFONT)) + { aToken = m_aCurToken; + NextToken(); + } + else + Error(PE_FONT_EXPECTED); + } while (m_aCurToken.eType == TFONT); + + m_aNodeStack.Push(new SmFontNode(aToken)); +} + + +// gets number used as arguments in Math formulas (e.g. 'size' command) +// Format: no negative numbers, must start with a digit, no exponent notation, ... +bool lcl_IsNumber(const UniString& rText) +{ + bool bPoint = false; + const sal_Unicode* pBuffer = rText.GetBuffer(); + for(xub_StrLen nPos = 0; nPos < rText.Len(); nPos++, pBuffer++) + { + const sal_Unicode cChar = *pBuffer; + if(cChar == '.') + { + if(bPoint) + return false; + else + bPoint = true; + } + else if ( !IsDigit( cChar ) ) + return false; + } + return true; +} + +void SmParser::FontSize() +{ + OSL_ENSURE(m_aCurToken.eType == TSIZE, "Sm : Ooops..."); + + sal_uInt16 Type; + SmFontNode *pFontNode = new SmFontNode(m_aCurToken); + + NextToken(); + + switch (m_aCurToken.eType) + { + case TNUMBER: Type = FNTSIZ_ABSOLUT; break; + case TPLUS: Type = FNTSIZ_PLUS; break; + case TMINUS: Type = FNTSIZ_MINUS; break; + case TMULTIPLY: Type = FNTSIZ_MULTIPLY; break; + case TDIVIDEBY: Type = FNTSIZ_DIVIDE; break; + + default: + delete pFontNode; + Error(PE_SIZE_EXPECTED); + return; + } + + if (Type != FNTSIZ_ABSOLUT) + { + NextToken(); + if (m_aCurToken.eType != TNUMBER) + { + delete pFontNode; + Error(PE_SIZE_EXPECTED); + return; + } + } + + // get number argument + Fraction aValue( 1L ); + if (lcl_IsNumber( m_aCurToken.aText )) + { + double fTmp; + if ((fTmp = m_aCurToken.aText.ToDouble()) != 0.0) + { + aValue = fTmp; + + //!! keep the numerator and denominator from being to large + //!! otherwise ongoing multiplications may result in overflows + //!! (for example in SmNode::SetFontSize the font size calculated + //!! may become 0 because of this!!! Happens e.g. for ftmp = 2.9 with Linux + //!! or ftmp = 1.11111111111111111... (11/9) on every platform.) + if (aValue.GetDenominator() > 1000) + { + long nNum = aValue.GetNumerator(); + long nDenom = aValue.GetDenominator(); + while (nDenom > 1000) + { + nNum /= 10; + nDenom /= 10; + } + aValue = Fraction( nNum, nDenom ); + } + } + } + + NextToken(); + + pFontNode->SetSizeParameter(aValue, Type); + m_aNodeStack.Push(pFontNode); +} + + +void SmParser::Brace() +{ + OSL_ENSURE(m_aCurToken.eType == TLEFT || TokenInGroup(TGLBRACES), + "Sm: kein Klammer Ausdruck"); + + SmStructureNode *pSNode = new SmBraceNode(m_aCurToken); + SmNode *pBody = 0, + *pLeft = 0, + *pRight = 0; + SmScaleMode eScaleMode = SCALE_NONE; + SmParseError eError = PE_NONE; + + if (m_aCurToken.eType == TLEFT) + { NextToken(); + + eScaleMode = SCALE_HEIGHT; + + // check for left bracket + if (TokenInGroup(TGLBRACES) || TokenInGroup(TGRBRACES)) + { + pLeft = new SmMathSymbolNode(m_aCurToken); + + NextToken(); + Bracebody(true); + pBody = m_aNodeStack.Pop(); + + if (m_aCurToken.eType == TRIGHT) + { NextToken(); + + // check for right bracket + if (TokenInGroup(TGLBRACES) || TokenInGroup(TGRBRACES)) + { + pRight = new SmMathSymbolNode(m_aCurToken); + NextToken(); + } + else + eError = PE_RBRACE_EXPECTED; + } + else + eError = PE_RIGHT_EXPECTED; + } + else + eError = PE_LBRACE_EXPECTED; + } + else + { + if (TokenInGroup(TGLBRACES)) + { + pLeft = new SmMathSymbolNode(m_aCurToken); + + NextToken(); + Bracebody(false); + pBody = m_aNodeStack.Pop(); + + SmTokenType eExpectedType = TUNKNOWN; + switch (pLeft->GetToken().eType) + { case TLPARENT : eExpectedType = TRPARENT; break; + case TLBRACKET : eExpectedType = TRBRACKET; break; + case TLBRACE : eExpectedType = TRBRACE; break; + case TLDBRACKET : eExpectedType = TRDBRACKET; break; + case TLLINE : eExpectedType = TRLINE; break; + case TLDLINE : eExpectedType = TRDLINE; break; + case TLANGLE : eExpectedType = TRANGLE; break; + case TLFLOOR : eExpectedType = TRFLOOR; break; + case TLCEIL : eExpectedType = TRCEIL; break; + default : + OSL_FAIL("Sm: unknown case"); + } + + if (m_aCurToken.eType == eExpectedType) + { + pRight = new SmMathSymbolNode(m_aCurToken); + NextToken(); + } + else + eError = PE_PARENT_MISMATCH; + } + else + eError = PE_LBRACE_EXPECTED; + } + + if (eError == PE_NONE) + { OSL_ENSURE(pLeft, "Sm: NULL pointer"); + OSL_ENSURE(pRight, "Sm: NULL pointer"); + pSNode->SetSubNodes(pLeft, pBody, pRight); + pSNode->SetScaleMode(eScaleMode); + m_aNodeStack.Push(pSNode); + } + else + { delete pSNode; + delete pBody; + delete pLeft; + delete pRight; + + Error(eError); + } +} + + +void SmParser::Bracebody(bool bIsLeftRight) +{ + SmStructureNode *pBody = new SmBracebodyNode(m_aCurToken); + SmNodeArray aNodes; + sal_uInt16 nNum = 0; + + // get body if any + if (bIsLeftRight) + { + do + { + if (m_aCurToken.eType == TMLINE) + { + m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken)); + NextToken(); + nNum++; + } + else if (m_aCurToken.eType != TRIGHT) + { Align(); + nNum++; + + if (m_aCurToken.eType != TMLINE && m_aCurToken.eType != TRIGHT) + Error(PE_RIGHT_EXPECTED); + } + } while (m_aCurToken.eType != TEND && m_aCurToken.eType != TRIGHT); + } + else + { + do + { + if (m_aCurToken.eType == TMLINE) + { + m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken)); + NextToken(); + nNum++; + } + else if (!TokenInGroup(TGRBRACES)) + { Align(); + nNum++; + + if (m_aCurToken.eType != TMLINE && !TokenInGroup(TGRBRACES)) + Error(PE_RBRACE_EXPECTED); + } + } while (m_aCurToken.eType != TEND && !TokenInGroup(TGRBRACES)); + } + + // build argument vector in parsing order + aNodes.resize(nNum); + for (sal_uInt16 i = 0; i < nNum; i++) + aNodes[nNum - 1 - i] = m_aNodeStack.Pop(); + + pBody->SetSubNodes(aNodes); + pBody->SetScaleMode(bIsLeftRight ? SCALE_HEIGHT : SCALE_NONE); + m_aNodeStack.Push(pBody); +} + + +void SmParser::Function() +{ + switch (m_aCurToken.eType) + { + case TFUNC: + NextToken(); // skip "FUNC"-statement + // fall through + + case TSIN : + case TCOS : + case TTAN : + case TCOT : + case TASIN : + case TACOS : + case TATAN : + case TACOT : + case TSINH : + case TCOSH : + case TTANH : + case TCOTH : + case TASINH : + case TACOSH : + case TATANH : + case TACOTH : + case TLN : + case TLOG : + case TEXP : + m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_FUNCTION)); + NextToken(); + break; + + default: + Error(PE_FUNC_EXPECTED); + } +} + + +void SmParser::Binom() +{ + SmNodeArray ExpressionArray; + SmStructureNode *pSNode = new SmTableNode(m_aCurToken); + + NextToken(); + + Sum(); + Sum(); + + ExpressionArray.resize(2); + + for (int i = 0; i < 2; i++) + ExpressionArray[2 - (i + 1)] = m_aNodeStack.Pop(); + + pSNode->SetSubNodes(ExpressionArray); + m_aNodeStack.Push(pSNode); +} + + +void SmParser::Stack() +{ + SmNodeArray ExpressionArray; + NextToken(); + if (m_aCurToken.eType == TLGROUP) + { + sal_uInt16 n = 0; + + do + { + NextToken(); + Align(); + n++; + } + while (m_aCurToken.eType == TPOUND); + + ExpressionArray.resize(n); + + for (sal_uInt16 i = 0; i < n; i++) + ExpressionArray[n - (i + 1)] = m_aNodeStack.Pop(); + + if (m_aCurToken.eType != TRGROUP) + Error(PE_RGROUP_EXPECTED); + + NextToken(); + + //We need to let the table node know it context + //it's used in SmNodeToTextVisitor + SmToken aTok = m_aCurToken; + aTok.eType = TSTACK; + SmStructureNode *pSNode = new SmTableNode(aTok); + pSNode->SetSubNodes(ExpressionArray); + m_aNodeStack.Push(pSNode); + } + else + Error(PE_LGROUP_EXPECTED); +} + + +void SmParser::Matrix() +{ + SmNodeArray ExpressionArray; + + NextToken(); + if (m_aCurToken.eType == TLGROUP) + { + sal_uInt16 c = 0; + + do + { + NextToken(); + Align(); + c++; + } + while (m_aCurToken.eType == TPOUND); + + sal_uInt16 r = 1; + + while (m_aCurToken.eType == TDPOUND) + { + NextToken(); + for (sal_uInt16 i = 0; i < c; i++) + { + Align(); + if (i < (c - 1)) + { + if (m_aCurToken.eType == TPOUND) + { + NextToken(); + } + else + Error(PE_POUND_EXPECTED); + } + } + + r++; + } + + long nRC = r * c; + + ExpressionArray.resize(nRC); + + for (sal_uInt16 i = 0; i < (nRC); i++) + ExpressionArray[(nRC) - (i + 1)] = m_aNodeStack.Pop(); + + if (m_aCurToken.eType != TRGROUP) + Error(PE_RGROUP_EXPECTED); + + NextToken(); + + SmMatrixNode *pMNode = new SmMatrixNode(m_aCurToken); + pMNode->SetSubNodes(ExpressionArray); + pMNode->SetRowCol(r, c); + m_aNodeStack.Push(pMNode); + } + else + Error(PE_LGROUP_EXPECTED); +} + + +void SmParser::Special() +{ + bool bReplace = false; + String &rName = m_aCurToken.aText; + String aNewName; + + if (CONVERT_NONE == GetConversion()) + { + // conversion of symbol names for 6.0 (XML) file format + // (name change on import / export. + // UI uses localized names XML file format does not.) + if( rName.Len() && rName.GetChar( 0 ) == sal_Unicode( '%' ) ) + { + if (IsImportSymbolNames()) + { + const SmLocalizedSymbolData &rLSD = SM_MOD()->GetLocSymbolData(); + aNewName = rLSD.GetUiSymbolName( rName.Copy( 1 ) ); + bReplace = true; + } + else if (IsExportSymbolNames()) + { + const SmLocalizedSymbolData &rLSD = SM_MOD()->GetLocSymbolData(); + aNewName = rLSD.GetExportSymbolName( rName.Copy( 1 ) ); + bReplace = true; + } + } + if( aNewName.Len() ) + aNewName.Insert( '%', 0 ); + } + else // 5.0 <-> 6.0 formula text (symbol name) conversion + { + LanguageType nLanguage = GetLanguage(); + SmLocalizedSymbolData &rData = SM_MOD()->GetLocSymbolData(); + const ResStringArray *pFrom = 0; + const ResStringArray *pTo = 0; + if (CONVERT_50_TO_60 == GetConversion()) + { + pFrom = rData.Get50NamesArray( nLanguage ); + pTo = rData.Get60NamesArray( nLanguage ); + } + else if (CONVERT_60_TO_50 == GetConversion()) + { + pFrom = rData.Get60NamesArray( nLanguage ); + pTo = rData.Get50NamesArray( nLanguage ); + } + if (pFrom && pTo) + { + OSL_ENSURE( pFrom->Count() == pTo->Count(), + "array length mismatch" ); + sal_uInt16 nCount = sal::static_int_cast< sal_uInt16 >(pFrom->Count()); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + if (pFrom->GetString(i) == rName) + { + aNewName = pTo->GetString(i); + bReplace = true; + } + } + } + // else: + // conversion arrays not found or (usually) + // conversion not necessary + } + + if (bReplace && aNewName.Len() && rName != aNewName) + { + Replace( GetTokenIndex(), rName.Len(), aNewName ); + rName = aNewName; + } + + // add symbol name to list of used symbols + const String aSymbolName( m_aCurToken.aText.Copy( 1 ) ); + if (aSymbolName.Len() > 0 ) + AddToUsedSymbols( aSymbolName ); + + m_aNodeStack.Push(new SmSpecialNode(m_aCurToken)); + NextToken(); +} + + +void SmParser::GlyphSpecial() +{ + m_aNodeStack.Push(new SmGlyphSpecialNode(m_aCurToken)); + NextToken(); +} + + +void SmParser::Error(SmParseError eError) +{ + SmStructureNode *pSNode = new SmExpressionNode(m_aCurToken); + SmErrorNode *pErr = new SmErrorNode(eError, m_aCurToken); + pSNode->SetSubNodes(pErr, 0); + + //! put a structure node on the stack (instead of the error node itself) + //! because sometimes such a node is expected in order to attach some + //! subnodes + m_aNodeStack.Push(pSNode); + + AddError(eError, pSNode); + + NextToken(); +} + + +// end gramar + + +SmParser::SmParser() + : m_aDotLoc( SvxCreateLocale( LANGUAGE_ENGLISH_US ) ) +{ + m_eConversion = CONVERT_NONE; + bImportSymNames = m_bExportSymNames = false; + m_nLang = Application::GetSettings().GetUILanguage(); +} + +SmNode *SmParser::Parse(const String &rBuffer) +{ + ClearUsedSymbols(); + + m_aBufferString = rBuffer; + m_aBufferString.ConvertLineEnd( LINEEND_LF ); + m_nBufferIndex = 0; + m_nTokenIndex = 0; + m_Row = 1; + m_nColOff = 0; + m_nCurError = -1; + + for ( size_t i = 0, n = m_aErrDescList.size(); i < n; ++i ) + delete m_aErrDescList[ i ]; + m_aErrDescList.clear(); + + m_aNodeStack.Clear(); + + SetLanguage( Application::GetSettings().GetUILanguage() ); + NextToken(); + Table(); + + return m_aNodeStack.Pop(); +} + +SmNode *SmParser::ParseExpression(const String &rBuffer) +{ + m_aBufferString = rBuffer; + m_aBufferString.ConvertLineEnd( LINEEND_LF ); + m_nBufferIndex = 0; + m_nTokenIndex = 0; + m_Row = 1; + m_nColOff = 0; + m_nCurError = -1; + + for ( size_t i = 0, n = m_aErrDescList.size(); i < n; ++i ) + delete m_aErrDescList[ i ]; + m_aErrDescList.clear(); + + m_aNodeStack.Clear(); + + SetLanguage( Application::GetSettings().GetUILanguage() ); + NextToken(); + Expression(); + + return m_aNodeStack.Pop(); +} + + +size_t SmParser::AddError(SmParseError Type, SmNode *pNode) +{ + SmErrorDesc *pErrDesc = new SmErrorDesc; + + pErrDesc->Type = Type; + pErrDesc->pNode = pNode; + pErrDesc->Text = String(SmResId(RID_ERR_IDENT)); + + sal_uInt16 nRID; + switch (Type) + { + case PE_UNEXPECTED_CHAR: nRID = RID_ERR_UNEXPECTEDCHARACTER; break; + case PE_LGROUP_EXPECTED: nRID = RID_ERR_LGROUPEXPECTED; break; + case PE_RGROUP_EXPECTED: nRID = RID_ERR_RGROUPEXPECTED; break; + case PE_LBRACE_EXPECTED: nRID = RID_ERR_LBRACEEXPECTED; break; + case PE_RBRACE_EXPECTED: nRID = RID_ERR_RBRACEEXPECTED; break; + case PE_FUNC_EXPECTED: nRID = RID_ERR_FUNCEXPECTED; break; + case PE_UNOPER_EXPECTED: nRID = RID_ERR_UNOPEREXPECTED; break; + case PE_BINOPER_EXPECTED: nRID = RID_ERR_BINOPEREXPECTED; break; + case PE_SYMBOL_EXPECTED: nRID = RID_ERR_SYMBOLEXPECTED; break; + case PE_IDENTIFIER_EXPECTED: nRID = RID_ERR_IDENTEXPECTED; break; + case PE_POUND_EXPECTED: nRID = RID_ERR_POUNDEXPECTED; break; + case PE_COLOR_EXPECTED: nRID = RID_ERR_COLOREXPECTED; break; + case PE_RIGHT_EXPECTED: nRID = RID_ERR_RIGHTEXPECTED; break; + + default: + nRID = RID_ERR_UNKOWN; + } + pErrDesc->Text += SmResId(nRID); + + m_aErrDescList.push_back( pErrDesc ); + + return m_aErrDescList.size()-1; +} + + +const SmErrorDesc *SmParser::NextError() +{ + if ( !m_aErrDescList.empty() ) + if (m_nCurError > 0) return m_aErrDescList[ --m_nCurError ]; + else + { + m_nCurError = 0; + return m_aErrDescList[ m_nCurError ]; + } + else return NULL; +} + + +const SmErrorDesc *SmParser::PrevError() +{ + if ( !m_aErrDescList.empty() ) + if (m_nCurError < (int) (m_aErrDescList.size() - 1)) return m_aErrDescList[ ++m_nCurError ]; + else + { + m_nCurError = (int) (m_aErrDescList.size() - 1); + return m_aErrDescList[ m_nCurError ]; + } + else return NULL; +} + + +const SmErrorDesc *SmParser::GetError(size_t i) +{ + if ( i < m_aErrDescList.size() ) + return m_aErrDescList[ i ]; + + if ( (size_t)m_nCurError < m_aErrDescList.size() ) + return m_aErrDescList[ m_nCurError ]; + + return NULL; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/rect.cxx b/starmath/source/rect.cxx new file mode 100644 index 000000000000..b69abbd455c6 --- /dev/null +++ b/starmath/source/rect.cxx @@ -0,0 +1,696 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <tools/string.hxx> +#include <osl/diagnose.h> +#include <vcl/svapp.hxx> +#include <vcl/wrkwin.hxx> +#include <vcl/virdev.hxx> + + +#include "rect.hxx" +#include "types.hxx" +#include "utility.hxx" +#include "smmod.hxx" + + +//////////////////////////////////////////////////////////////////////////////// + + +// '\0' terminated Array with symbol, which should be treat as letters in +// StarMath Font, (to get a normal (non-clipped) SmRect in contrast to the +// other operators and symbols). +static xub_Unicode const aMathAlpha[] = +{ + MS_ALEPH, MS_IM, MS_RE, + MS_WP, xub_Unicode(0xE070), MS_EMPTYSET, + xub_Unicode(0x2113), xub_Unicode(0xE0D6), xub_Unicode(0x2107), + xub_Unicode(0x2127), xub_Unicode(0x210A), MS_HBAR, + MS_LAMBDABAR, MS_SETN, MS_SETZ, + MS_SETQ, MS_SETR, MS_SETC, + xub_Unicode(0x2373), xub_Unicode(0xE0A5), xub_Unicode(0x2112), + xub_Unicode(0x2130), xub_Unicode(0x2131), + xub_Unicode('\0') +}; + +bool SmIsMathAlpha(const XubString &rText) + // true iff symbol (from StarMath Font) should be treated as letter +{ + if (rText.Len() == 0) + return false; + + OSL_ENSURE(rText.Len() == 1, "Sm : string must be exactly one character long"); + xub_Unicode cChar = rText.GetChar(0); + + // is it a greek symbol? + if (xub_Unicode(0xE0AC) <= cChar && cChar <= xub_Unicode(0xE0D4)) + return true; + else + { + // appears it in 'aMathAlpha'? + const xub_Unicode *pChar = aMathAlpha; + while (*pChar && *pChar != cChar) + pChar++; + return *pChar != xub_Unicode('\0'); + } +} + + +//////////////////////////////////////// +// +// SmRect members +// + + +SmRect::SmRect() + // constructs empty rectangle at (0, 0) with width and height 0. +{ + OSL_ENSURE(aTopLeft == Point(0, 0), "Sm: ooops..."); + OSL_ENSURE(aSize == Size(0, 0), "Sm: ooops..."); + + bHasBaseline = bHasAlignInfo = false; + nBaseline = nAlignT = nAlignM = nAlignB = + nGlyphTop = nGlyphBottom = + nItalicLeftSpace = nItalicRightSpace = + nLoAttrFence = nHiAttrFence = 0; + nBorderWidth = 0; +} + + +SmRect::SmRect(const SmRect &rRect) +: aTopLeft(rRect.aTopLeft), + aSize(rRect.aSize) +{ + bHasBaseline = rRect.bHasBaseline; + nBaseline = rRect.nBaseline; + nAlignT = rRect.nAlignT; + nAlignM = rRect.nAlignM; + nAlignB = rRect.nAlignB; + nGlyphTop = rRect.nGlyphTop; + nGlyphBottom = rRect.nGlyphBottom; + nHiAttrFence = rRect.nHiAttrFence; + nLoAttrFence = rRect.nLoAttrFence; + bHasAlignInfo = rRect.bHasAlignInfo; + nItalicLeftSpace = rRect.nItalicLeftSpace; + nItalicRightSpace = rRect.nItalicRightSpace; + nBorderWidth = rRect.nBorderWidth; +} + + +void SmRect::CopyAlignInfo(const SmRect &rRect) +{ + nBaseline = rRect.nBaseline; + bHasBaseline = rRect.bHasBaseline; + nAlignT = rRect.nAlignT; + nAlignM = rRect.nAlignM; + nAlignB = rRect.nAlignB; + bHasAlignInfo = rRect.bHasAlignInfo; + nLoAttrFence = rRect.nLoAttrFence; + nHiAttrFence = rRect.nHiAttrFence; +} + + +void SmRect::BuildRect(const OutputDevice &rDev, const SmFormat *pFormat, + const XubString &rText, sal_uInt16 nBorder) +{ + OSL_ENSURE(aTopLeft == Point(0, 0), "Sm: Ooops..."); + + aSize = Size(rDev.GetTextWidth(rText), rDev.GetTextHeight()); + + const FontMetric aFM (rDev.GetFontMetric()); + bool bIsMath = aFM.GetName().EqualsIgnoreCaseAscii( FONTNAME_MATH ); + bool bAllowSmaller = bIsMath && !SmIsMathAlpha(rText); + const long nFontHeight = rDev.GetFont().GetSize().Height(); + + nBorderWidth = nBorder; + bHasAlignInfo = true; + bHasBaseline = true; + nBaseline = aFM.GetAscent(); + nAlignT = nBaseline - nFontHeight * 750L / 1000L; + nAlignM = nBaseline - nFontHeight * 121L / 422L; + // that's where the horizontal bars of '+', '-', ... are + // (1/3 of ascent over baseline) + // (121 = 1/3 of 12pt ascent, 422 = 12pt fontheight) + nAlignB = nBaseline; + + // workaround for printer fonts with very small (possible 0 or even + // negative(!)) leading + if (aFM.GetIntLeading() < 5 && rDev.GetOutDevType() == OUTDEV_PRINTER) + { + OutputDevice *pWindow = Application::GetDefaultDevice(); + + pWindow->Push(PUSH_MAPMODE | PUSH_FONT); + + pWindow->SetMapMode(rDev.GetMapMode()); + pWindow->SetFont(rDev.GetFontMetric()); + + long nDelta = pWindow->GetFontMetric().GetIntLeading(); + if (nDelta == 0) + { // this value approx. fits a Leading of 80 at a + // Fontheight of 422 (12pt) + nDelta = nFontHeight * 8L / 43; + } + SetTop(GetTop() - nDelta); + + pWindow->Pop(); + } + + // get GlyphBoundRect + Rectangle aGlyphRect; +#if OSL_DEBUG_LEVEL > 1 + bool bSuccess = +#endif + SmGetGlyphBoundRect(rDev, rText, aGlyphRect); +#if OSL_DEBUG_LEVEL > 1 + if (!bSuccess) + { + OSL_FAIL( "Sm : Ooops... (fehlt evtl. der Font?)"); + } +#endif + + nItalicLeftSpace = GetLeft() - aGlyphRect.Left() + nBorderWidth; + nItalicRightSpace = aGlyphRect.Right() - GetRight() + nBorderWidth; + if (nItalicLeftSpace < 0 && !bAllowSmaller) + nItalicLeftSpace = 0; + if (nItalicRightSpace < 0 && !bAllowSmaller) + nItalicRightSpace = 0; + + long nDist = 0; + if (pFormat) + nDist = (rDev.GetFont().GetSize().Height() + * pFormat->GetDistance(DIS_ORNAMENTSIZE)) / 100L; + + nHiAttrFence = aGlyphRect.TopLeft().Y() - 1 - nBorderWidth - nDist; + nLoAttrFence = SmFromTo(GetAlignB(), GetBottom(), 0.0); + + nGlyphTop = aGlyphRect.Top() - nBorderWidth; + nGlyphBottom = aGlyphRect.Bottom() + nBorderWidth; + + if (bAllowSmaller) + { + // for symbols and operators from the StarMath Font + // we adjust upper and lower margin of the symbol + SetTop(nGlyphTop); + SetBottom(nGlyphBottom); + } + + if (nHiAttrFence < GetTop()) + nHiAttrFence = GetTop(); + + if (nLoAttrFence > GetBottom()) + nLoAttrFence = GetBottom(); + + OSL_ENSURE(rText.Len() == 0 || !IsEmpty(), + "Sm: empty rectangle created"); +} + + +void SmRect::Init(const OutputDevice &rDev, const SmFormat *pFormat, + const XubString &rText, sal_uInt16 nEBorderWidth) + // get rectangle fitting for drawing 'rText' on OutputDevice 'rDev' +{ + BuildRect(rDev, pFormat, rText, nEBorderWidth); +} + + +SmRect::SmRect(const OutputDevice &rDev, const SmFormat *pFormat, + const XubString &rText, long nEBorderWidth) +{ + OSL_ENSURE( nEBorderWidth >= 0, "BorderWidth is negative" ); + if (nEBorderWidth < 0) + nEBorderWidth = 0; + Init(rDev, pFormat, rText, (sal_uInt16) nEBorderWidth); +} + + +SmRect::SmRect(long nWidth, long nHeight) + // this constructor should never be used for anything textlike because + // it will not provide useful values for baseline, AlignT and AlignB! + // It's purpose is to get a 'SmRect' for the horizontal line in fractions + // as used in 'SmBinVerNode'. +: aSize(nWidth, nHeight) +{ + OSL_ENSURE(aTopLeft == Point(0, 0), "Sm: ooops..."); + + bHasBaseline = false; + bHasAlignInfo = true; + nBaseline = 0; + nAlignT = GetTop(); + nAlignB = GetBottom(); + nAlignM = (nAlignT + nAlignB) / 2; // this is the default + nItalicLeftSpace = nItalicRightSpace = 0; + nGlyphTop = nHiAttrFence = GetTop(); + nGlyphBottom = nLoAttrFence = GetBottom(); + nBorderWidth = 0; +} + + +void SmRect::SetLeft(long nLeft) +{ + if (nLeft <= GetRight()) + { aSize.Width() = GetRight() - nLeft + 1; + aTopLeft.X() = nLeft; + } +} + + +void SmRect::SetRight(long nRight) +{ + if (nRight >= GetLeft()) + aSize.Width() = nRight - GetLeft() + 1; +} + + +void SmRect::SetBottom(long nBottom) +{ + if (nBottom >= GetTop()) + aSize.Height() = nBottom - GetTop() + 1; +} + + +void SmRect::SetTop(long nTop) +{ + if (nTop <= GetBottom()) + { aSize.Height() = GetBottom() - nTop + 1; + aTopLeft.Y() = nTop; + } +} + + +void SmRect::Move(const Point &rPosition) + // move rectangle by position 'rPosition'. +{ + aTopLeft += rPosition; + + long nDelta = rPosition.Y(); + nBaseline += nDelta; + nAlignT += nDelta; + nAlignM += nDelta; + nAlignB += nDelta; + nGlyphTop += nDelta; + nGlyphBottom += nDelta; + nHiAttrFence += nDelta; + nLoAttrFence += nDelta; +} + + +const Point SmRect::AlignTo(const SmRect &rRect, RectPos ePos, + RectHorAlign eHor, RectVerAlign eVer) const +{ Point aPos (GetTopLeft()); + // will become the topleft point of the new rectangle position + + // set horizontal or vertical new rectangle position depending on + // 'ePos' is one of 'RP_LEFT', 'RP_RIGHT' or 'RP_TOP', 'RP_BOTTOM' + switch (ePos) + { case RP_LEFT : + aPos.X() = rRect.GetItalicLeft() - GetItalicRightSpace() + - GetWidth(); + break; + case RP_RIGHT : + aPos.X() = rRect.GetItalicRight() + 1 + GetItalicLeftSpace(); + break; + case RP_TOP : + aPos.Y() = rRect.GetTop() - GetHeight(); + break; + case RP_BOTTOM : + aPos.Y() = rRect.GetBottom() + 1; + break; + case RP_ATTRIBUT : + aPos.X() = rRect.GetItalicCenterX() - GetItalicWidth() / 2 + + GetItalicLeftSpace(); + break; + default : + OSL_FAIL("Sm: unknown case"); + } + + // check if horizontal position is already set + if (ePos == RP_LEFT || ePos == RP_RIGHT || ePos == RP_ATTRIBUT) + // correct error in current vertical position + switch (eVer) + { case RVA_TOP : + aPos.Y() += rRect.GetAlignT() - GetAlignT(); + break; + case RVA_MID : + aPos.Y() += rRect.GetAlignM() - GetAlignM(); + break; + case RVA_BASELINE : + // align baselines if possible else align mid's + if (HasBaseline() && rRect.HasBaseline()) + aPos.Y() += rRect.GetBaseline() - GetBaseline(); + else + aPos.Y() += rRect.GetAlignM() - GetAlignM(); + break; + case RVA_BOTTOM : + aPos.Y() += rRect.GetAlignB() - GetAlignB(); + break; + case RVA_CENTERY : + aPos.Y() += rRect.GetCenterY() - GetCenterY(); + break; + case RVA_ATTRIBUT_HI: + aPos.Y() += rRect.GetHiAttrFence() - GetBottom(); + break; + case RVA_ATTRIBUT_MID : + aPos.Y() += SmFromTo(rRect.GetAlignB(), rRect.GetAlignT(), 0.4) + - GetCenterY(); + break; + case RVA_ATTRIBUT_LO : + aPos.Y() += rRect.GetLoAttrFence() - GetTop(); + break; + default : + OSL_FAIL("Sm: unknown case"); + } + + // check if vertical position is already set + if (ePos == RP_TOP || ePos == RP_BOTTOM) + // correct error in current horizontal position + switch (eHor) + { case RHA_LEFT : + aPos.X() += rRect.GetItalicLeft() - GetItalicLeft(); + break; + case RHA_CENTER : + aPos.X() += rRect.GetItalicCenterX() - GetItalicCenterX(); + break; + case RHA_RIGHT : + aPos.X() += rRect.GetItalicRight() - GetItalicRight(); + break; + default : + OSL_FAIL("Sm: unknown case"); + } + + return aPos; +} + + +SmRect & SmRect::Union(const SmRect &rRect) + // rectangle union of current one with 'rRect'. The result is to be the + // smallest rectangles that covers the space of both rectangles. + // (empty rectangles cover no space) + //! Italic correction is NOT taken into account here! +{ + if (rRect.IsEmpty()) + return *this; + + long nL = rRect.GetLeft(), + nR = rRect.GetRight(), + nT = rRect.GetTop(), + nB = rRect.GetBottom(), + nGT = rRect.nGlyphTop, + nGB = rRect.nGlyphBottom; + if (!IsEmpty()) + { long nTmp; + + if ((nTmp = GetLeft()) < nL) + nL = nTmp; + if ((nTmp = GetRight()) > nR) + nR = nTmp; + if ((nTmp = GetTop()) < nT) + nT = nTmp; + if ((nTmp = GetBottom()) > nB) + nB = nTmp; + if ((nTmp = nGlyphTop) < nGT) + nGT = nTmp; + if ((nTmp = nGlyphBottom) > nGB) + nGB = nTmp; + } + + SetLeft(nL); + SetRight(nR); + SetTop(nT); + SetBottom(nB); + nGlyphTop = nGT; + nGlyphBottom = nGB; + + return *this; +} + + +SmRect & SmRect::ExtendBy(const SmRect &rRect, RectCopyMBL eCopyMode) + // let current rectangle be the union of itself and 'rRect' + // (the smallest rectangle surrounding both). Also adapt values for + // 'AlignT', 'AlignM', 'AlignB', baseline and italic-spaces. + // The baseline is set according to 'eCopyMode'. + // If one of the rectangles has no relevant info the other one is copied. +{ + // get some values used for (italic) spaces adaption + // ! (need to be done before changing current SmRect) ! + long nL = Min(GetItalicLeft(), rRect.GetItalicLeft()), + nR = Max(GetItalicRight(), rRect.GetItalicRight()); + + Union(rRect); + + SetItalicSpaces(GetLeft() - nL, nR - GetRight()); + + if (!HasAlignInfo()) + CopyAlignInfo(rRect); + else if (rRect.HasAlignInfo()) + { nAlignT = Min(GetAlignT(), rRect.GetAlignT()); + nAlignB = Max(GetAlignB(), rRect.GetAlignB()); + nHiAttrFence = Min(GetHiAttrFence(), rRect.GetHiAttrFence()); + nLoAttrFence = Max(GetLoAttrFence(), rRect.GetLoAttrFence()); + OSL_ENSURE(HasAlignInfo(), "Sm: ooops..."); + + switch (eCopyMode) + { case RCP_THIS: + // already done + break; + case RCP_ARG: + CopyMBL(rRect); + break; + case RCP_NONE: + ClearBaseline(); + nAlignM = (nAlignT + nAlignB) / 2; + break; + case RCP_XOR: + if (!HasBaseline()) + CopyMBL(rRect); + break; + default : + OSL_FAIL("Sm: unknown case"); + } + } + + return *this; +} + + +SmRect & SmRect::ExtendBy(const SmRect &rRect, RectCopyMBL eCopyMode, + long nNewAlignM) + // as 'ExtendBy' but sets AlignM value to 'nNewAlignM'. + // (this version will be used in 'SmBinVerNode' to provide means to + // align eg "{a over b} over c" correctly where AlignM should not + // be (AlignT + AlignB) / 2) +{ + OSL_ENSURE(HasAlignInfo(), "Sm: no align info"); + + ExtendBy(rRect, eCopyMode); + nAlignM = nNewAlignM; + + return *this; +} + + +SmRect & SmRect::ExtendBy(const SmRect &rRect, RectCopyMBL eCopyMode, + bool bKeepVerAlignParams) + // as 'ExtendBy' but keeps original values for AlignT, -M and -B and + // baseline. + // (this is used in 'SmSupSubNode' where the sub-/supscripts shouldn't + // be allowed to modify these values.) +{ + long nOldAlignT = GetAlignT(), + nOldAlignM = GetAlignM(), + nOldAlignB = GetAlignB(), + nOldBaseline = nBaseline; //! depends not on 'HasBaseline' + bool bOldHasAlignInfo = HasAlignInfo(); + + ExtendBy(rRect, eCopyMode); + + if (bKeepVerAlignParams) + { nAlignT = nOldAlignT; + nAlignM = nOldAlignM; + nAlignB = nOldAlignB; + nBaseline = nOldBaseline; + bHasAlignInfo = bOldHasAlignInfo; + } + + return *this; +} + + +long SmRect::OrientedDist(const Point &rPoint) const + // return oriented distance of rPoint to the current rectangle, + // especially the return value is <= 0 iff the point is inside the + // rectangle. + // For simplicity the maximum-norm is used. +{ + bool bIsInside = IsInsideItalicRect(rPoint); + + // build reference point to define the distance + Point aRef; + if (bIsInside) + { Point aIC (GetItalicCenterX(), GetCenterY()); + + aRef.X() = rPoint.X() >= aIC.X() ? GetItalicRight() : GetItalicLeft(); + aRef.Y() = rPoint.Y() >= aIC.Y() ? GetBottom() : GetTop(); + } + else + { + // x-coordinate + if (rPoint.X() > GetItalicRight()) + aRef.X() = GetItalicRight(); + else if (rPoint.X() < GetItalicLeft()) + aRef.X() = GetItalicLeft(); + else + aRef.X() = rPoint.X(); + // y-coordinate + if (rPoint.Y() > GetBottom()) + aRef.Y() = GetBottom(); + else if (rPoint.Y() < GetTop()) + aRef.Y() = GetTop(); + else + aRef.Y() = rPoint.Y(); + } + + // build distance vector + Point aDist (aRef - rPoint); + + long nAbsX = labs(aDist.X()), + nAbsY = labs(aDist.Y()); + + return bIsInside ? - Min(nAbsX, nAbsY) : Max (nAbsX, nAbsY); +} + + +bool SmRect::IsInsideRect(const Point &rPoint) const +{ + return rPoint.Y() >= GetTop() + && rPoint.Y() <= GetBottom() + && rPoint.X() >= GetLeft() + && rPoint.X() <= GetRight(); +} + + +bool SmRect::IsInsideItalicRect(const Point &rPoint) const +{ + return rPoint.Y() >= GetTop() + && rPoint.Y() <= GetBottom() + && rPoint.X() >= GetItalicLeft() + && rPoint.X() <= GetItalicRight(); +} + +SmRect SmRect::AsGlyphRect() const +{ + SmRect aRect (*this); + aRect.SetTop(nGlyphTop); + aRect.SetBottom(nGlyphBottom); + return aRect; +} + +bool SmGetGlyphBoundRect(const OutputDevice &rDev, + const XubString &rText, Rectangle &rRect) + // basically the same as 'GetTextBoundRect' (in class 'OutputDevice') + // but with a string as argument. +{ + // handle special case first + xub_StrLen nLen = rText.Len(); + if (nLen == 0) + { rRect.SetEmpty(); + return true; + } + + // get a device where 'OutputDevice::GetTextBoundRect' will be successful + OutputDevice *pGlyphDev; + if (rDev.GetOutDevType() != OUTDEV_PRINTER) + pGlyphDev = (OutputDevice *) &rDev; + else + { + // since we format for the printer (where GetTextBoundRect will fail) + // we need a virtual device here. + pGlyphDev = &SM_MOD()->GetDefaultVirtualDev(); + } + + const FontMetric aDevFM (rDev.GetFontMetric()); + + pGlyphDev->Push(PUSH_FONT | PUSH_MAPMODE); + Font aFnt(rDev.GetFont()); + aFnt.SetAlign(ALIGN_TOP); + + // use scale factor when calling GetTextBoundRect to counter + // negative effects from antialiasing which may otherwise result + // in significant incorrect bounding rectangles for some charcters. + Size aFntSize = aFnt.GetSize(); + + // Workaround to avoid HUGE font sizes and resulting problems + long nScaleFactor = 1; + while( aFntSize.Height() > 2000 * nScaleFactor ) + nScaleFactor *= 2; + + aFnt.SetSize( Size( aFntSize.Width() / nScaleFactor, aFntSize.Height() / nScaleFactor ) ); + pGlyphDev->SetFont(aFnt); + + long nTextWidth = rDev.GetTextWidth(rText); + Point aPoint; + Rectangle aResult (aPoint, Size(nTextWidth, rDev.GetTextHeight())), + aTmp; + + bool bSuccess = pGlyphDev->GetTextBoundRect(aTmp, rText, 0, 0); + OSL_ENSURE( bSuccess, "GetTextBoundRect failed" ); + + + if (!aTmp.IsEmpty()) + { + aResult = Rectangle(aTmp.Left() * nScaleFactor, aTmp.Top() * nScaleFactor, + aTmp.Right() * nScaleFactor, aTmp.Bottom() * nScaleFactor); + if (&rDev != pGlyphDev) /* only when rDev is a printer... */ + { + long nGDTextWidth = pGlyphDev->GetTextWidth(rText); + if (nGDTextWidth != 0 && + nTextWidth != nGDTextWidth) + { + aResult.Right() *= nTextWidth; + aResult.Right() /= nGDTextWidth * nScaleFactor; + } + } + } + + // move rectangle to match possibly different baselines + // (because of different devices) + long nDelta = aDevFM.GetAscent() - pGlyphDev->GetFontMetric().GetAscent() * nScaleFactor; + aResult.Move(0, nDelta); + + pGlyphDev->Pop(); + + rRect = aResult; + return bSuccess; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/register.cxx b/starmath/source/register.cxx new file mode 100644 index 000000000000..ef921342ba07 --- /dev/null +++ b/starmath/source/register.cxx @@ -0,0 +1,228 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/uno/Sequence.h> +#include <rtl/ustring.hxx> + +#include <sfx2/sfxmodelfactory.hxx> + +#include "smdll.hxx" +#include "document.hxx" +#include "unomodel.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +//Math document +extern Sequence< OUString > SAL_CALL + SmDocument_getSupportedServiceNames() throw(); +extern OUString SAL_CALL + SmDocument_getImplementationName() throw(); +extern Reference< XInterface >SAL_CALL + SmDocument_createInstance(const Reference< XMultiServiceFactory > & rSMgr, const sal_uInt64 _nCreationFlags) throw( Exception ); + +//MathML import +extern Sequence< OUString > SAL_CALL + SmXMLImport_getSupportedServiceNames() throw(); +extern OUString SAL_CALL + SmXMLImport_getImplementationName() throw(); +extern Reference< XInterface > SAL_CALL + SmXMLImport_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ); +extern Sequence< OUString > SAL_CALL + SmXMLImportMeta_getSupportedServiceNames() throw(); +extern OUString SAL_CALL + SmXMLImportMeta_getImplementationName() throw(); +extern Reference< XInterface > SAL_CALL + SmXMLImportMeta_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ); +extern Sequence< OUString > SAL_CALL + SmXMLImportSettings_getSupportedServiceNames() throw(); +extern OUString SAL_CALL SmXMLImportSettings_getImplementationName() throw(); +extern Reference< XInterface > SAL_CALL + SmXMLImportSettings_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ); + +//MathML export +extern Sequence< OUString > SAL_CALL + SmXMLExport_getSupportedServiceNames() throw(); +extern OUString SAL_CALL + SmXMLExport_getImplementationName() throw(); +extern Reference< XInterface > SAL_CALL + SmXMLExport_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ); +extern Sequence< OUString > SAL_CALL + SmXMLExportMetaOOO_getSupportedServiceNames() throw(); +extern OUString SAL_CALL + SmXMLExportMetaOOO_getImplementationName() throw(); +extern Reference< XInterface > SAL_CALL + SmXMLExportMetaOOO_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ); +extern Sequence< OUString > SAL_CALL + SmXMLExportMeta_getSupportedServiceNames() throw(); +extern OUString SAL_CALL + SmXMLExportMeta_getImplementationName() throw(); +extern Reference< XInterface > SAL_CALL + SmXMLExportMeta_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ); +extern Sequence< OUString > SAL_CALL + SmXMLExportSettingsOOO_getSupportedServiceNames() throw(); +extern OUString SAL_CALL + SmXMLExportSettingsOOO_getImplementationName() throw(); +extern Reference< XInterface > SAL_CALL + SmXMLExportSettingsOOO_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ); +extern Sequence< OUString > SAL_CALL + SmXMLExportSettings_getSupportedServiceNames() throw(); +extern OUString SAL_CALL + SmXMLExportSettings_getImplementationName() throw(); +extern Reference< XInterface > SAL_CALL + SmXMLExportSettings_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ); +extern Sequence< OUString > SAL_CALL + SmXMLExportContent_getSupportedServiceNames() throw(); +extern OUString SAL_CALL + SmXMLExportContent_getImplementationName() throw(); +extern Reference< XInterface > SAL_CALL + SmXMLExportContent_createInstance(const Reference< XMultiServiceFactory > & rSMgr) throw( Exception ); + + +extern "C" { + +SAL_DLLPUBLIC_EXPORT void* SAL_CALL sm_component_getFactory( const sal_Char* pImplementationName, + void* pServiceManager, + void* /*pRegistryKey*/ ) +{ + // Set default return value for this operation - if it failed. + void* pReturn = NULL ; + + if ( + ( pImplementationName != NULL ) && + ( pServiceManager != NULL ) + ) + { + // Define variables which are used in following macros. + Reference< XSingleServiceFactory > xFactory ; + Reference< XMultiServiceFactory > xServiceManager( reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + + if( SmXMLImport_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmXMLImport_getImplementationName(), + SmXMLImport_createInstance, + SmXMLImport_getSupportedServiceNames() ); + } + else if( SmXMLExport_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmXMLExport_getImplementationName(), + SmXMLExport_createInstance, + SmXMLExport_getSupportedServiceNames() ); + } + else if( SmXMLImportMeta_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmXMLImportMeta_getImplementationName(), + SmXMLImportMeta_createInstance, + SmXMLImportMeta_getSupportedServiceNames() ); + } + else if( SmXMLExportMetaOOO_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmXMLExportMetaOOO_getImplementationName(), + SmXMLExportMetaOOO_createInstance, + SmXMLExportMetaOOO_getSupportedServiceNames() ); + } + else if( SmXMLExportMeta_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmXMLExportMeta_getImplementationName(), + SmXMLExportMeta_createInstance, + SmXMLExportMeta_getSupportedServiceNames() ); + } + else if( SmXMLImportSettings_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmXMLImportSettings_getImplementationName(), + SmXMLImportSettings_createInstance, + SmXMLImportSettings_getSupportedServiceNames() ); + } + else if( SmXMLExportSettingsOOO_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmXMLExportSettingsOOO_getImplementationName(), + SmXMLExportSettingsOOO_createInstance, + SmXMLExportSettingsOOO_getSupportedServiceNames() ); + } + else if( SmXMLExportSettings_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmXMLExportSettings_getImplementationName(), + SmXMLExportSettings_createInstance, + SmXMLExportSettings_getSupportedServiceNames() ); + } + else if( SmXMLExportContent_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::cppu::createSingleFactory( xServiceManager, + SmXMLExportContent_getImplementationName(), + SmXMLExportContent_createInstance, + SmXMLExportContent_getSupportedServiceNames() ); + } + else if( SmDocument_getImplementationName().equalsAsciiL( + pImplementationName, strlen(pImplementationName)) ) + { + xFactory = ::sfx2::createSfxModelFactory( xServiceManager, + SmDocument_getImplementationName(), + SmDocument_createInstance, + SmDocument_getSupportedServiceNames() ); + } + + + // Factory is valid - service was found. + if ( xFactory.is() ) + { + xFactory->acquire(); + pReturn = xFactory.get(); + } + } + + // Return with result of this operation. + return pReturn ; +} +} // extern "C" + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/smdetect.cxx b/starmath/source/smdetect.cxx new file mode 100644 index 000000000000..dfab23448a09 --- /dev/null +++ b/starmath/source/smdetect.cxx @@ -0,0 +1,471 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + +#include "smdetect.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/ucb/CommandAbortedException.hpp> +#include <com/sun/star/ucb/InteractiveAppException.hpp> +#include <com/sun/star/ucb/XContent.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <toolkit/helper/vclunohelper.hxx> +#include <ucbhelper/simpleinteractionrequest.hxx> +#include <rtl/ustring.h> +#include <rtl/logfile.hxx> +#include <svl/itemset.hxx> +#include <vcl/window.hxx> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <tools/urlobj.hxx> +#include <osl/mutex.hxx> +#include <svtools/sfxecode.hxx> +#include <svtools/ehdl.hxx> +#include <sot/storinfo.hxx> +#include <vcl/svapp.hxx> +#include <sfx2/app.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/request.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/fcontnr.hxx> +#include <sfx2/brokenpackageint.hxx> + +#include "document.hxx" + +extern sal_Bool GetMathTypeVersion( SotStorage* pStor, sal_uInt8 &nVersion ); + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; +using namespace ::rtl; + +SmFilterDetect::SmFilterDetect( const REFERENCE < ::com::sun::star::lang::XMultiServiceFactory >& /*xFactory*/ ) +{ +} + +SmFilterDetect::~SmFilterDetect() +{ +} + +::rtl::OUString SAL_CALL SmFilterDetect::detect( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lDescriptor ) throw( ::com::sun::star::uno::RuntimeException ) +{ + REFERENCE< XInputStream > xStream; + REFERENCE< XContent > xContent; + REFERENCE< XInteractionHandler > xInteraction; + String aURL; + ::rtl::OUString sTemp; + String aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection) + String aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action) + + ::rtl::OUString aDocumentTitle; // interesting only if set in this method + + // opening as template is done when a parameter tells to do so and a template filter can be detected + // (otherwise no valid filter would be found) or if the detected filter is a template filter and + // there is no parameter that forbids to open as template + sal_Bool bOpenAsTemplate = sal_False; + sal_Bool bWasReadOnly = sal_False, bReadOnly = sal_False; + + sal_Bool bRepairPackage = sal_False; + sal_Bool bRepairAllowed = sal_False; + + // now some parameters that can already be in the array, but may be overwritten or new inserted here + // remember their indices in the case new values must be added to the array + sal_Int32 nPropertyCount = lDescriptor.getLength(); + sal_Int32 nIndexOfInputStream = -1; + sal_Int32 nIndexOfContent = -1; + sal_Int32 nIndexOfReadOnlyFlag = -1; + sal_Int32 nIndexOfTemplateFlag = -1; + sal_Int32 nIndexOfDocumentTitle = -1; + + for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty ) + { + // extract properties + if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("URL")) ) + { + lDescriptor[nProperty].Value >>= sTemp; + aURL = sTemp; + } + else if( !aURL.Len() && lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("FileName")) ) + { + lDescriptor[nProperty].Value >>= sTemp; + aURL = sTemp; + } + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")) ) + { + lDescriptor[nProperty].Value >>= sTemp; + aTypeName = sTemp; + } + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("FilterName")) ) + { + lDescriptor[nProperty].Value >>= sTemp; + aPreselectedFilterName = sTemp; + } + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream")) ) + nIndexOfInputStream = nProperty; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")) ) + nIndexOfReadOnlyFlag = nProperty; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("UCBContent")) ) + nIndexOfContent = nProperty; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("AsTemplate")) ) + { + lDescriptor[nProperty].Value >>= bOpenAsTemplate; + nIndexOfTemplateFlag = nProperty; + } + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("InteractionHandler")) ) + lDescriptor[nProperty].Value >>= xInteraction; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("RepairPackage")) ) + lDescriptor[nProperty].Value >>= bRepairPackage; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentTitle")) ) + nIndexOfDocumentTitle = nProperty; + } + + // can't check the type for external filters, so set the "dont" flag accordingly + SolarMutexGuard aGuard; + + SfxApplication* pApp = SFX_APP(); + SfxAllItemSet *pSet = new SfxAllItemSet( pApp->GetPool() ); + TransformParameters( SID_OPENDOC, lDescriptor, *pSet ); + SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, sal_False ); + + bWasReadOnly = pItem && pItem->GetValue(); + + String aFilterName; + String aPrefix = String::CreateFromAscii( "private:factory/" ); + if( aURL.Match( aPrefix ) == aPrefix.Len() ) + { + const SfxFilter* pFilter = 0; + String aPattern( aPrefix ); + aPattern += String::CreateFromAscii("smath"); + if ( aURL.Match( aPattern ) >= aPattern.Len() ) + { + pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL ); + aTypeName = pFilter->GetTypeName(); + aFilterName = pFilter->GetName(); + } + } + else + { + // ctor of SfxMedium uses owner transition of ItemSet + SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, sal_False, NULL, pSet ); + aMedium.UseInteractionHandler( true ); + + bool bIsStorage = aMedium.IsStorage(); + if ( aMedium.GetErrorCode() == ERRCODE_NONE ) + { + // remember input stream and content and put them into the descriptor later + // should be done here since later the medium can switch to a version + xStream = aMedium.GetInputStream(); + xContent = aMedium.GetContent(); + bReadOnly = aMedium.IsReadOnly(); + + if ( bIsStorage ) + { + //TODO/LATER: factor this out! + uno::Reference < embed::XStorage > xStorage = aMedium.GetStorage( sal_False ); + if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE ) + { + // error during storage creation means _here_ that the medium + // is broken, but we can not handle it in medium since unpossibility + // to create a storage does not _always_ means that the medium is broken + aMedium.SetError( aMedium.GetLastStorageCreationState(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); + if ( xInteraction.is() ) + { + OUString empty; + try + { + InteractiveAppException xException( empty, + REFERENCE< XInterface >(), + InteractionClassification_ERROR, + aMedium.GetError() ); + + REFERENCE< XInteractionRequest > xRequest( + new ucbhelper::SimpleInteractionRequest( makeAny( xException ), + ucbhelper::CONTINUATION_APPROVE ) ); + xInteraction->handle( xRequest ); + } + catch ( Exception & ) {}; + } + } + else + { + aFilterName.Erase(); + + try + { + const SfxFilter* pFilter = aPreselectedFilterName.Len() ? + SfxFilterMatcher().GetFilter4FilterName( aPreselectedFilterName ) : aTypeName.Len() ? + SfxFilterMatcher(String::CreateFromAscii("smath")).GetFilter4EA( aTypeName ) : 0; + String aTmpFilterName; + if ( pFilter ) + aTmpFilterName = pFilter->GetName(); + aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter ? pFilter->IsAllowedAsTemplate() : sal_False, &aTmpFilterName ); + } + catch( lang::WrappedTargetException& aWrap ) + { + packages::zip::ZipIOException aZipException; + + // repairing is done only if this type is requested from outside + if ( ( aWrap.TargetException >>= aZipException ) && aTypeName.Len() ) + { + if ( xInteraction.is() ) + { + // the package is broken one + aDocumentTitle = aMedium.GetURLObject().getName( + INetURLObject::LAST_SEGMENT, + true, + INetURLObject::DECODE_WITH_CHARSET ); + + if ( !bRepairPackage ) + { + // ask the user whether he wants to try to repair + RequestPackageReparation aRequest( aDocumentTitle ); + xInteraction->handle( aRequest.GetRequest() ); + bRepairAllowed = aRequest.isApproved(); + } + + if ( !bRepairAllowed ) + { + // repair either not allowed or not successful + NotifyBrokenPackage aNotifyRequest( aDocumentTitle ); + xInteraction->handle( aNotifyRequest.GetRequest() ); + } + } + + if ( !bRepairAllowed ) + aTypeName.Erase(); + } + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + aTypeName.Erase(); + } + + if ( aTypeName.Len() ) + { + const SfxFilter* pFilter = + SfxFilterMatcher( String::CreateFromAscii("smath") ).GetFilter4EA( aTypeName ); + if ( pFilter ) + aFilterName = pFilter->GetName(); + } + } + } + else + { + //Test to see if this begins with xml and if so run it through + //the MathML filter. There are all sorts of things wrong with + //this approach, to be fixed at a better level than here + SvStream *pStrm = aMedium.GetInStream(); + aTypeName.Erase(); + if (pStrm && !pStrm->GetError()) + { + SotStorageRef aStorage = new SotStorage ( pStrm, sal_False ); + if ( !aStorage->GetError() ) + { + if ( aStorage->IsStream( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Equation Native" ) ) ) ) + { + sal_uInt8 nVersion; + if (GetMathTypeVersion( aStorage, nVersion ) && nVersion <=3) + aTypeName.AssignAscii( "math_MathType_3x" ); + } + } + else + { + const sal_uInt16 nSize = 5; + sal_Char aBuffer[nSize+1]; + aBuffer[nSize] = 0; + pStrm->Seek( STREAM_SEEK_TO_BEGIN ); + sal_uLong nBytesRead = pStrm->Read( aBuffer, nSize ); + if (nBytesRead == nSize) + { + if (0 == strncmp( "<?xml",aBuffer,nSize)) + { + static const sal_Char sFltrNm_2[] = MATHML_XML; + static const sal_Char sTypeNm_2[] = "math_MathML_XML_Math"; + aFilterName.AssignAscii( sFltrNm_2 ); + aTypeName.AssignAscii( sTypeNm_2 ); + } + } + } + + if ( aTypeName.Len() ) + { + const SfxFilter* pFilt = SfxFilterMatcher( String::CreateFromAscii("smath") ).GetFilter4EA( aTypeName ); + if ( pFilt ) + aFilterName = pFilt->GetName(); + } + } + } + } + } + + if ( nIndexOfInputStream == -1 && xStream.is() ) + { + // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream")); + lDescriptor[nPropertyCount].Value <<= xStream; + nPropertyCount++; + } + + if ( nIndexOfContent == -1 && xContent.is() ) + { + // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UCBContent")); + lDescriptor[nPropertyCount].Value <<= xContent; + nPropertyCount++; + } + + if ( bReadOnly != bWasReadOnly ) + { + if ( nIndexOfReadOnlyFlag == -1 ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")); + lDescriptor[nPropertyCount].Value <<= bReadOnly; + nPropertyCount++; + } + else + lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly; + } + + if ( !bRepairPackage && bRepairAllowed ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RepairPackage")); + lDescriptor[nPropertyCount].Value <<= bRepairAllowed; + nPropertyCount++; + + bOpenAsTemplate = sal_True; + + // TODO/LATER: set progress bar that should be used + } + + if ( bOpenAsTemplate ) + { + if ( nIndexOfTemplateFlag == -1 ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AsTemplate")); + lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate; + nPropertyCount++; + } + else + lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate; + } + + if ( aDocumentTitle.getLength() ) + { + // the title was set here + if ( nIndexOfDocumentTitle == -1 ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentTitle")); + lDescriptor[nPropertyCount].Value <<= aDocumentTitle; + nPropertyCount++; + } + else + lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle; + } + + if ( !aFilterName.Len() ) + aTypeName.Erase(); + + return aTypeName; +} + +SFX_IMPL_SINGLEFACTORY( SmFilterDetect ) + +/* XServiceInfo */ +UNOOUSTRING SAL_CALL SmFilterDetect::getImplementationName() throw( UNORUNTIMEEXCEPTION ) +{ + return impl_getStaticImplementationName(); +} + \ +/* XServiceInfo */ +sal_Bool SAL_CALL SmFilterDetect::supportsService( const UNOOUSTRING& sServiceName ) throw( UNORUNTIMEEXCEPTION ) +{ + UNOSEQUENCE< UNOOUSTRING > seqServiceNames = getSupportedServiceNames(); + const UNOOUSTRING* pArray = seqServiceNames.getConstArray(); + for ( sal_Int32 nCounter=0; nCounter<seqServiceNames.getLength(); nCounter++ ) + { + if ( pArray[nCounter] == sServiceName ) + { + return sal_True ; + } + } + return sal_False ; +} + +/* XServiceInfo */ +UNOSEQUENCE< UNOOUSTRING > SAL_CALL SmFilterDetect::getSupportedServiceNames() throw( UNORUNTIMEEXCEPTION ) +{ + return impl_getStaticSupportedServiceNames(); +} + +/* Helper for XServiceInfo */ +UNOSEQUENCE< UNOOUSTRING > SmFilterDetect::impl_getStaticSupportedServiceNames() +{ + UNOSEQUENCE< UNOOUSTRING > seqServiceNames( 1 ); + seqServiceNames.getArray() [0] = UNOOUSTRING(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ExtendedTypeDetection" )); + return seqServiceNames ; +} + +/* Helper for XServiceInfo */ +UNOOUSTRING SmFilterDetect::impl_getStaticImplementationName() +{ + return UNOOUSTRING(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.math.FormatDetector" )); +} + +/* Helper for registry */ +UNOREFERENCE< UNOXINTERFACE > SAL_CALL SmFilterDetect::impl_createInstance( const UNOREFERENCE< UNOXMULTISERVICEFACTORY >& xServiceManager ) throw( UNOEXCEPTION ) +{ + return UNOREFERENCE< UNOXINTERFACE >( *new SmFilterDetect( xServiceManager ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/smdetect.hxx b/starmath/source/smdetect.hxx new file mode 100644 index 000000000000..ae5fc38852ce --- /dev/null +++ b/starmath/source/smdetect.hxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SM_TYPEDETECT_HXX +#define _SM_TYPEDETECT_HXX + +#include <rtl/ustring.hxx> +#include <osl/diagnose.h> +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <cppuhelper/implbase2.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <cppuhelper/factory.hxx> +#include <tools/link.hxx> +#include <tools/string.hxx> + +class SfxObjectFactory; +class SfxFilterMatcher; +class LoadEnvironment_Impl; +class SfxMedium; + +namespace com +{ + namespace sun + { + namespace star + { + namespace uno + { + class Any; + } + namespace lang + { + class XMultiServiceFactory; + } + namespace frame + { + class XFrame; + } + namespace beans + { + struct PropertyValue; + } + } + } +} + +#include <sfx2/sfxuno.hxx> + +#define REFERENCE ::com::sun::star::uno::Reference +#define SEQUENCE ::com::sun::star::uno::Sequence +#define RUNTIME_EXCEPTION ::com::sun::star::uno::RuntimeException + +class SmFilterDetect : public ::cppu::WeakImplHelper2< ::com::sun::star::document::XExtendedFilterDetection, ::com::sun::star::lang::XServiceInfo > +{ +public: + SmFilterDetect( const REFERENCE < ::com::sun::star::lang::XMultiServiceFactory >& xFactory ); + virtual ~SmFilterDetect(); + + SFX_DECL_XSERVICEINFO + + //---------------------------------------------------------------------------------- + // XExtendedFilterDetect + //---------------------------------------------------------------------------------- + virtual ::rtl::OUString SAL_CALL detect( SEQUENCE< ::com::sun::star::beans::PropertyValue >& lDescriptor ) throw( RUNTIME_EXCEPTION ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/smdll.cxx b/starmath/source/smdll.cxx new file mode 100644 index 000000000000..7c4a19b49439 --- /dev/null +++ b/starmath/source/smdll.cxx @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <sot/factory.hxx> +#include <svx/svxids.hrc> +#include <svx/modctrl.hxx> +#include <svx/zoomctrl.hxx> +#include <sfx2/docfac.hxx> +#include <svx/lboxctrl.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/app.hxx> +#include <sfx2/taskpane.hxx> + +#include <smdll.hxx> +#include <document.hxx> +#include <toolbox.hxx> +#include <view.hxx> + +#include <starmath.hrc> + +#include <svx/xmlsecctrl.hxx> + +namespace +{ + class SmDLL + { + public: + SmDLL(); + ~SmDLL(); + }; + + SmDLL::SmDLL() + { + SmModule** ppShlPtr = (SmModule**) GetAppData(SHL_SM); + if ( *ppShlPtr ) + return; + + SfxObjectFactory& rFactory = SmDocShell::Factory(); + SmModule *pModule = new SmModule( &rFactory ); + *ppShlPtr = pModule; + + rFactory.SetDocumentServiceName( String::CreateFromAscii("com.sun.star.formula.FormulaProperties") ); + + SmModule::RegisterInterface(pModule); + SmDocShell::RegisterInterface(pModule); + SmViewShell::RegisterInterface(pModule); + + SmViewShell::RegisterFactory(1); + + SvxZoomStatusBarControl::RegisterControl(SID_ATTR_ZOOM, pModule); + SvxModifyControl::RegisterControl(SID_TEXTSTATUS, pModule); + SvxUndoRedoControl::RegisterControl(SID_UNDO, pModule); + SvxUndoRedoControl::RegisterControl(SID_REDO, pModule); + XmlSecStatusBarControl::RegisterControl(SID_SIGNATURE, pModule); + + SmToolBoxWrapper::RegisterChildWindow(true); + SmCmdBoxWrapper::RegisterChildWindow(true); + + ::sfx2::TaskPaneWrapper::RegisterChildWindow(false, pModule); + } + + SmDLL::~SmDLL() + { +#if 0 + // the SdModule must be destroyed + SmModule** ppShlPtr = (SmModule**) GetAppData(SHL_SM); + delete (*ppShlPtr); + (*ppShlPtr) = NULL; + *GetAppData(SHL_SM) = 0; +#endif + } + + struct theSmDLLInstance : public rtl::Static<SmDLL, theSmDLLInstance> {}; +} + +namespace SmGlobals +{ + void ensure() + { + theSmDLLInstance::get(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/smmod.cxx b/starmath/source/smmod.cxx new file mode 100644 index 000000000000..669a26ab39ef --- /dev/null +++ b/starmath/source/smmod.cxx @@ -0,0 +1,375 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <tools/globname.hxx> +#include <vcl/status.hxx> +#include <sfx2/msg.hxx> +#include <sfx2/app.hxx> +#include <sfx2/objface.hxx> +#include <svl/whiter.hxx> +#include <sfx2/request.hxx> +#include <sfx2/sfx.hrc> +#include <sfx2/viewsh.hxx> +#include <vcl/wrkwin.hxx> +#include <svx/svxids.hrc> +#include <vcl/msgbox.hxx> +#include <vcl/virdev.hxx> +#include <unotools/syslocale.hxx> +#include <tools/rtti.hxx> +#include "smmod.hxx" +#include "symbol.hxx" +#include "config.hxx" +#include "dialog.hxx" +#include "edit.hxx" +#include "view.hxx" +#include "starmath.hrc" +#include "svx/modctrl.hxx" + +TYPEINIT1( SmModule, SfxModule ); + +#define SmModule +#include "smslots.hxx" + +#include <svx/xmlsecctrl.hxx> + + + +SmResId::SmResId( sal_uInt16 nId ) + : ResId(nId, *SM_MOD()->GetResMgr()) +{ +} + +///////////////////////////////////////////////////////////////// + +SmLocalizedSymbolData::SmLocalizedSymbolData() : + Resource( SmResId(RID_LOCALIZED_NAMES) ), + aUiSymbolNamesAry ( SmResId(RID_UI_SYMBOL_NAMES) ), + aExportSymbolNamesAry ( SmResId(RID_EXPORT_SYMBOL_NAMES) ), + aUiSymbolSetNamesAry ( SmResId(RID_UI_SYMBOLSET_NAMES) ), + aExportSymbolSetNamesAry( SmResId(RID_EXPORT_SYMBOLSET_NAMES) ), + p50NamesAry ( 0 ), + p60NamesAry ( 0 ), + n50NamesLang ( LANGUAGE_NONE ), + n60NamesLang ( LANGUAGE_NONE ) +{ + FreeResource(); +} + + +SmLocalizedSymbolData::~SmLocalizedSymbolData() +{ + delete p50NamesAry; + delete p60NamesAry; +} + + +const String SmLocalizedSymbolData::GetUiSymbolName( const String &rExportName ) const +{ + String aRes; + + const SmLocalizedSymbolData &rData = SM_MOD()->GetLocSymbolData(); + const ResStringArray &rUiNames = rData.GetUiSymbolNamesArray(); + const ResStringArray &rExportNames = rData.GetExportSymbolNamesArray(); + sal_uInt16 nCount = sal::static_int_cast< xub_StrLen >(rExportNames.Count()); + for (sal_uInt16 i = 0; i < nCount && !aRes.Len(); ++i) + { + if (rExportName == rExportNames.GetString(i)) + { + aRes = rUiNames.GetString(i); + break; + } + } + + return aRes; +} + + +const String SmLocalizedSymbolData::GetExportSymbolName( const String &rUiName ) const +{ + String aRes; + + const SmLocalizedSymbolData &rData = SM_MOD()->GetLocSymbolData(); + const ResStringArray &rUiNames = rData.GetUiSymbolNamesArray(); + const ResStringArray &rExportNames = rData.GetExportSymbolNamesArray(); + sal_uInt16 nCount = sal::static_int_cast< xub_StrLen >(rUiNames.Count()); + for (sal_uInt16 i = 0; i < nCount && !aRes.Len(); ++i) + { + if (rUiName == rUiNames.GetString(i)) + { + aRes = rExportNames.GetString(i); + break; + } + } + + return aRes; +} + + +const String SmLocalizedSymbolData::GetUiSymbolSetName( const String &rExportName ) const +{ + String aRes; + + const SmLocalizedSymbolData &rData = SM_MOD()->GetLocSymbolData(); + const ResStringArray &rUiNames = rData.GetUiSymbolSetNamesArray(); + const ResStringArray &rExportNames = rData.GetExportSymbolSetNamesArray(); + sal_uInt16 nCount = sal::static_int_cast< xub_StrLen >(rExportNames.Count()); + for (sal_uInt16 i = 0; i < nCount && !aRes.Len(); ++i) + { + if (rExportName == rExportNames.GetString(i)) + { + aRes = rUiNames.GetString(i); + break; + } + } + + return aRes; +} + + +const String SmLocalizedSymbolData::GetExportSymbolSetName( const String &rUiName ) const +{ + String aRes; + + const SmLocalizedSymbolData &rData = SM_MOD()->GetLocSymbolData(); + const ResStringArray &rUiNames = rData.GetUiSymbolSetNamesArray(); + const ResStringArray &rExportNames = rData.GetExportSymbolSetNamesArray(); + sal_uInt16 nCount = sal::static_int_cast< xub_StrLen >(rUiNames.Count()); + for (sal_uInt16 i = 0; i < nCount && !aRes.Len(); ++i) + { + if (rUiName == rUiNames.GetString(i)) + { + aRes = rExportNames.GetString(i); + break; + } + } + + return aRes; +} + + +const ResStringArray* SmLocalizedSymbolData::Get50NamesArray( LanguageType nLang ) +{ + if (nLang != n50NamesLang) + { + int nRID; + switch (nLang) + { + case LANGUAGE_FRENCH : nRID = RID_FRENCH_50_NAMES; break; + case LANGUAGE_ITALIAN : nRID = RID_ITALIAN_50_NAMES; break; + case LANGUAGE_SWEDISH : nRID = RID_SWEDISH_50_NAMES; break; + case LANGUAGE_SPANISH : nRID = RID_SPANISH_50_NAMES; break; + default : nRID = -1; break; + } + delete p50NamesAry; + p50NamesAry = 0; + n50NamesLang = nLang; + if (-1 != nRID) + p50NamesAry = new SmNamesArray( n50NamesLang, nRID ); + } + + return p50NamesAry ? &p50NamesAry->GetNamesArray() : 0; +} + + +const ResStringArray* SmLocalizedSymbolData::Get60NamesArray( LanguageType nLang ) +{ + if (nLang != n60NamesLang) + { + int nRID; + switch (nLang) + { + case LANGUAGE_FRENCH : nRID = RID_FRENCH_60_NAMES; break; + case LANGUAGE_ITALIAN : nRID = RID_ITALIAN_60_NAMES; break; + case LANGUAGE_SWEDISH : nRID = RID_SWEDISH_60_NAMES; break; + case LANGUAGE_SPANISH : nRID = RID_SPANISH_60_NAMES; break; + default : nRID = -1; break; + } + delete p60NamesAry; + p60NamesAry = 0; + n60NamesLang = nLang; + if (-1 != nRID) + p60NamesAry = new SmNamesArray( n60NamesLang, nRID ); + } + + return p60NamesAry ? &p60NamesAry->GetNamesArray() : 0; +} + +///////////////////////////////////////////////////////////////// + +SFX_IMPL_INTERFACE(SmModule, SfxModule, SmResId(RID_APPLICATION)) +{ + SFX_STATUSBAR_REGISTRATION(SmResId(RID_STATUSBAR)); +} + + +SmModule::SmModule(SfxObjectFactory* pObjFact) : + SfxModule(SfxApplication::CreateResManager("sm"), sal_False, pObjFact, NULL), + pColorConfig( 0 ), + pConfig( 0 ), + pLocSymbolData( 0 ), + pSysLocale( 0 ), + pVirtualDev( 0 ) +{ + SetName( C2S("StarMath" )); + + SvxModifyControl::RegisterControl(SID_DOC_MODIFIED, this); +} + + +SmModule::~SmModule() +{ + delete pConfig; + if (pColorConfig) + pColorConfig->RemoveListener(this); + delete pColorConfig; + delete pLocSymbolData; + delete pSysLocale; + delete pVirtualDev; +} + +void SmModule::_CreateSysLocale() const +{ + SmModule* pThis = (SmModule*)this; + pThis->pSysLocale = new SvtSysLocale; +} + +void SmModule::_CreateVirtualDev() const +{ + SmModule* pThis = (SmModule*)this; + pThis->pVirtualDev = new VirtualDevice; + pThis->pVirtualDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 ); +} + +void SmModule::ApplyColorConfigValues( const svtools::ColorConfig &rColorCfg ) +{ + //invalidate all graphic and edit windows + const TypeId aSmViewTypeId = TYPE(SmViewShell); + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while (pViewShell) + { + if ((pViewShell->IsA(aSmViewTypeId))) + { + SmViewShell *pSmView = (SmViewShell *) pViewShell; + pSmView->GetGraphicWindow().ApplyColorConfigValues( rColorCfg ); + SmEditWindow *pEditWin = pSmView->GetEditWindow(); + if (pEditWin) + pEditWin->ApplyColorConfigValues( rColorCfg ); + } + pViewShell = SfxViewShell::GetNext( *pViewShell ); + } +} + +svtools::ColorConfig & SmModule::GetColorConfig() +{ + if(!pColorConfig) + { + pColorConfig = new svtools::ColorConfig; + ApplyColorConfigValues( *pColorConfig ); + pColorConfig->AddListener(this); + } + return *pColorConfig; +} + +void SmModule::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ) +{ + ApplyColorConfigValues(*pColorConfig); +} + +SmConfig * SmModule::GetConfig() +{ + if(!pConfig) + pConfig = new SmConfig; + return pConfig; +} + +SmSymbolManager & SmModule::GetSymbolManager() +{ + return GetConfig()->GetSymbolManager(); +} + +SmLocalizedSymbolData & SmModule::GetLocSymbolData() const +{ + if (!pLocSymbolData) + ((SmModule *) this)->pLocSymbolData = new SmLocalizedSymbolData; + return *pLocSymbolData; +} + +void SmModule::GetState(SfxItemSet &rSet) +{ + SfxWhichIter aIter(rSet); + + for (sal_uInt16 nWh = aIter.FirstWhich(); 0 != nWh; nWh = aIter.NextWhich()) + switch (nWh) + { + case SID_CONFIGEVENT : + rSet.DisableItem(SID_CONFIGEVENT); + break; + } +} + +SfxItemSet* SmModule::CreateItemSet( sal_uInt16 nId ) +{ + SfxItemSet* pRet = 0; + if(nId == SID_SM_EDITOPTIONS) + { + pRet = new SfxItemSet(GetPool(), + //TP_SMPRINT + SID_PRINTSIZE, SID_PRINTSIZE, + SID_PRINTZOOM, SID_PRINTZOOM, + SID_PRINTTITLE, SID_PRINTTITLE, + SID_PRINTTEXT, SID_PRINTTEXT, + SID_PRINTFRAME, SID_PRINTFRAME, + SID_NO_RIGHT_SPACES, SID_NO_RIGHT_SPACES, + SID_SAVE_ONLY_USED_SYMBOLS, SID_SAVE_ONLY_USED_SYMBOLS, + 0 ); + + GetConfig()->ConfigToItemSet(*pRet); + } + return pRet; +} +void SmModule::ApplyItemSet( sal_uInt16 nId, const SfxItemSet& rSet ) +{ + if(nId == SID_SM_EDITOPTIONS) + { + GetConfig()->ItemSetToConfig(rSet); + } +} +SfxTabPage* SmModule::CreateTabPage( sal_uInt16 nId, Window* pParent, const SfxItemSet& rSet ) +{ + SfxTabPage* pRet = 0; + if(nId == SID_SM_TP_PRINTOPTIONS) + pRet = SmPrintOptionsTabPage::Create( pParent, rSet ); + return pRet; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/smres.src b/starmath/source/smres.src new file mode 100644 index 000000000000..dd616848f277 --- /dev/null +++ b/starmath/source/smres.src @@ -0,0 +1,1670 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include <sfx2/sfx.hrc> +#include <svx/globlmn.hrc> +#include "starmath.hrc" +#include "dialog.hrc" +#include "toolbox.hrc" +#include "smcommands.h" + +#define IMAGE_STDBTN_COLOR Color { Red = 0xff00; Green = 0x0000; Blue = 0xff00; } +#define MN_SUB_TOOLBAR 32 +#define WORKARROUND_1 1 +#define WORKARROUND_3 3 +#define WORKARROUND_10 10 + +ModalDialog RID_FONTDIALOG +{ + HelpID = "starmath:ModalDialog:RID_FONTDIALOG"; + Moveable = TRUE ; + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 183 , 150 ) ; + Text [ en-US ] = "Fonts" ; + FixedText 1 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 40 , 8 ) ; + Text [ en-US ] = "~Font"; + }; + ComboBox 1 + { + HelpID = "starmath:ComboBox:RID_FONTDIALOG:1"; + Pos = MAP_APPFONT ( 6 , 17 ) ; + Size = MAP_APPFONT ( 111 , 60 ) ; + TabStop = TRUE ; + Sort = TRUE ; + VScroll = TRUE ; + }; + CheckBox 1 + { + HelpID = "starmath:CheckBox:RID_FONTDIALOG:1"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 60 , 84 ) ; + Size = MAP_APPFONT ( 33 , 10 ) ; + Text [ en-US ] = "~Bold" ; + }; + CheckBox 2 + { + HelpID = "starmath:CheckBox:RID_FONTDIALOG:2"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 60 , 97 ) ; + Size = MAP_APPFONT ( 33 , 10 ) ; + Text [ en-US ] = "~Italic" ; + }; + OKButton 1 + { + Pos = MAP_APPFONT ( 126 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton 1 + { + Pos = MAP_APPFONT ( 126 , 24 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + Control 1 + { + Disable = TRUE ; + Border = TRUE; + Pos = MAP_APPFONT ( 6 , 113 ) ; + Size = MAP_APPFONT ( 111 , 31 ) ; + }; + FixedText 2 + { + Pos = MAP_APPFONT ( 6 , 85 ) ; + Size = MAP_APPFONT ( 42 , 8 ) ; + Text [ en-US ] = "Attributes" ; + }; +}; + +ModalDialog RID_FONTSIZEDIALOG +{ + Moveable = TRUE ; + OutputSize = TRUE ; + SVLook = TRUE ; + HelpId = CMD_SID_FONTSIZE ; + Size = MAP_APPFONT ( 171 , 120 ) ; + Text [ en-US ] = "Font Sizes" ; + FixedText 1 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 12 , 7 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Text [ en-US ] = "Base ~size"; + }; + MetricField 1 + { + HelpID = "starmath:MetricField:RID_FONTSIZEDIALOG:1"; + Border = TRUE ; + Pos = MAP_APPFONT ( 57 , 6 ) ; + Size = MAP_APPFONT ( 40 , 12 ) ; + TabStop = TRUE ; + Left = TRUE ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 4 ; + Maximum = 127 ; + Unit = FUNIT_POINT ; + }; + FixedText 4 + { + Pos = MAP_APPFONT ( 12 , 37 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Left = TRUE ; + Text [ en-US ] = "~Text"; + }; + MetricField 4 + { + HelpID = "starmath:MetricField:RID_FONTSIZEDIALOG:4"; + Border = TRUE ; + Pos = MAP_APPFONT ( 57 , 36 ) ; + Size = MAP_APPFONT ( 40 , 12 ) ; + TabStop = TRUE ; + Left = TRUE ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 5 ; + Maximum = 200 ; + Unit = FUNIT_CUSTOM ; + CustomUnitText = "%" ; + }; + FixedText 5 + { + Pos = MAP_APPFONT ( 12 , 52 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Left = TRUE ; + Text [ en-US ] = "~Indexes"; + }; + MetricField 5 + { + HelpID = "starmath:MetricField:RID_FONTSIZEDIALOG:5"; + Border = TRUE ; + Pos = MAP_APPFONT ( 57 , 51 ) ; + Size = MAP_APPFONT ( 40 , 12 ) ; + TabStop = TRUE ; + Left = TRUE ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 5 ; + Maximum = 200 ; + Unit = FUNIT_CUSTOM ; + CustomUnitText = "%" ; + }; + FixedText 6 + { + Pos = MAP_APPFONT ( 12 , 67 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Left = TRUE ; + Text [ en-US ] = "~Functions"; + }; + MetricField 6 + { + HelpID = "starmath:MetricField:RID_FONTSIZEDIALOG:6"; + Border = TRUE ; + Pos = MAP_APPFONT ( 57 , 66 ) ; + Size = MAP_APPFONT ( 40 , 12 ) ; + TabStop = TRUE ; + Left = TRUE ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 5 ; + Maximum = 200 ; + Unit = FUNIT_CUSTOM ; + CustomUnitText = "%" ; + }; + FixedText 7 + { + Pos = MAP_APPFONT ( 12 , 82 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Left = TRUE ; + Text [ en-US ] = "~Operators"; + }; + MetricField 7 + { + HelpID = "starmath:MetricField:RID_FONTSIZEDIALOG:7"; + Border = TRUE ; + Pos = MAP_APPFONT ( 57 , 81 ) ; + Size = MAP_APPFONT ( 40 , 12 ) ; + TabStop = TRUE ; + Left = TRUE ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 5 ; + Maximum = 200 ; + Unit = FUNIT_CUSTOM ; + CustomUnitText = "%" ; + }; + FixedText 8 + { + Pos = MAP_APPFONT ( 12 , 97 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Left = TRUE ; + Text [ en-US ] = "~Limits"; + }; + MetricField 8 + { + HelpID = "starmath:MetricField:RID_FONTSIZEDIALOG:8"; + Border = TRUE ; + Pos = MAP_APPFONT ( 57 , 96 ) ; + Size = MAP_APPFONT ( 40 , 12 ) ; + TabStop = TRUE ; + Left = TRUE ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 5 ; + Maximum = 200 ; + Unit = FUNIT_CUSTOM ; + CustomUnitText = "%" ; + }; + FixedLine 1 + { + Pos = MAP_APPFONT ( 6 , 24 ) ; + Size = MAP_APPFONT ( 99 , 8 ) ; + Text [ en-US ] = "Relative sizes" ; + }; + OKButton 1 + { + Pos = MAP_APPFONT ( 114 , 3 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton 1 + { + Pos = MAP_APPFONT ( 114 , 21 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + PushButton 1 + { + HelpID = "starmath:PushButton:RID_FONTSIZEDIALOG:1"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 114 , 45 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Default" ; + }; +}; + +ModalDialog RID_FONTTYPEDIALOG +{ + OutputSize = TRUE ; + SVLook = TRUE ; + HelpId = CMD_SID_FONT ; + Size = MAP_APPFONT ( 282 , 153 ) ; + Text [ en-US ] = "Fonts" ; + Moveable = TRUE ; + FixedLine 1 + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 207 , 8 ) ; + Text [ en-US ] = "Formula fonts" ; + }; + FixedLine 2 + { + Pos = MAP_APPFONT ( 6 , 84 ) ; + Size = MAP_APPFONT ( 207 , 8 ) ; + Text [ en-US ] = "Custom fonts" ; + }; + FixedText 1 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 12 , 18 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Text [ en-US ] = "~Variables"; + }; + ListBox 1 + { + HelpID = "starmath:ListBox:RID_FONTTYPEDIALOG:1"; + Border = TRUE ; + Pos = MAP_APPFONT ( 54 , 18 ) ; + Size = MAP_APPFONT ( 150 , 69 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + }; + FixedText 2 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 12 , 33 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Text [ en-US ] = "~Functions"; + }; + ListBox 2 + { + HelpID = "starmath:ListBox:RID_FONTTYPEDIALOG:2"; + Border = TRUE ; + Pos = MAP_APPFONT ( 54 , 33 ) ; + Size = MAP_APPFONT ( 150 , 69 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + }; + FixedText 3 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 12 , 51 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Text [ en-US ] = "~Numbers"; + }; + ListBox 3 + { + HelpID = "starmath:ListBox:RID_FONTTYPEDIALOG:3"; + Border = TRUE ; + Pos = MAP_APPFONT ( 54 , 48 ) ; + Size = MAP_APPFONT ( 150 , 69 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + }; + FixedText 4 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 12 , 66 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Text [ en-US ] = "~Text"; + }; + ListBox 4 + { + HelpID = "starmath:ListBox:RID_FONTTYPEDIALOG:4"; + Border = TRUE ; + Pos = MAP_APPFONT ( 54 , 63 ) ; + Size = MAP_APPFONT ( 150 , 69 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + }; + FixedText 5 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 12 , 97 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Text [ en-US ] = "~Serif"; + }; + ListBox 5 + { + HelpID = "starmath:ListBox:RID_FONTTYPEDIALOG:5"; + Border = TRUE ; + Pos = MAP_APPFONT ( 54 , 96 ) ; + Size = MAP_APPFONT ( 150 , 69 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + }; + FixedText 6 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 12 , 112 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Text [ en-US ] = "S~ans"; + }; + ListBox 6 + { + HelpID = "starmath:ListBox:RID_FONTTYPEDIALOG:6"; + Border = TRUE ; + Pos = MAP_APPFONT ( 54 , 111 ) ; + Size = MAP_APPFONT ( 150 , 69 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + }; + FixedText 7 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 12 , 127 ) ; + Size = MAP_APPFONT ( 40 , 10 ) ; + Text [ en-US ] = "F~ixed"; + }; + ListBox 7 + { + HelpID = "starmath:ListBox:RID_FONTTYPEDIALOG:7"; + Border = TRUE ; + Pos = MAP_APPFONT ( 54 , 126 ) ; + Size = MAP_APPFONT ( 150 , 69 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + }; + OKButton 1 + { + Pos = MAP_APPFONT ( 225 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton 1 + { + Pos = MAP_APPFONT ( 225 , 24 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + MenuButton 1 + { + HelpID = "starmath:MenuButton:RID_FONTTYPEDIALOG:1"; + TabStop = TRUE ; + ButtonMenu = Menu , RID_FONTMENU ; + Pos = MAP_APPFONT ( 225 , 48 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Modify" ; + }; + PushButton 2 + { + HelpID = "starmath:PushButton:RID_FONTTYPEDIALOG:2"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 225 , 66 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Default" ; + }; +}; + +ModalDialog RID_DISTANCEDIALOG +{ + Moveable = TRUE ; + OutputSize = TRUE ; + SVLook = TRUE ; + HelpId = CMD_SID_DISTANCE ; + Size = MAP_APPFONT ( 240 , 90 ) ; + Text [ en-US ] = "Spacing" ; + FixedText 1 + { + Pos = MAP_APPFONT ( 12 , 19 ) ; + Size = MAP_APPFONT ( 65 , 10 ) ; + Left = TRUE ; + }; + MetricField 1 + { + HelpID = "starmath:MetricField:RID_DISTANCEDIALOG:1"; + Border = TRUE ; + TabStop = TRUE ; + Left = TRUE ; + Spin = TRUE ; + SpinSize = 1 ; + Repeat = TRUE; + Pos = MAP_APPFONT ( 78 , 18 ) ; + Size = MAP_APPFONT ( 38 , 12 ) ; + CustomUnitText [ en-US ] = "%" ; + }; + FixedText 2 + { + Disable = TRUE ; + Hide = TRUE ; + Pos = MAP_APPFONT ( 12 , 35 ) ; + Size = MAP_APPFONT ( 65 , 10 ) ; + Left = TRUE ; + }; + MetricField 2 + { + HelpID = "starmath:MetricField:RID_DISTANCEDIALOG:2"; + Border = TRUE ; + TabStop = TRUE ; + Left = TRUE ; + Spin = TRUE ; + SpinSize = 1 ; + Repeat = TRUE; + Pos = MAP_APPFONT ( 78 , 34 ) ; + Size = MAP_APPFONT ( 38 , 12 ) ; + CustomUnitText [ en-US ] = "%" ; + }; + CheckBox 1 + { + HelpID = "starmath:CheckBox:RID_DISTANCEDIALOG:1"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 55 ) ; + Size = MAP_APPFONT ( 110 , 12 ) ; + Text [ en-US ] = "Scale all brackets"; + }; + FixedText 3 + { + Disable = TRUE ; + Hide = TRUE ; + Pos = MAP_APPFONT ( 12 , 51 ) ; + Size = MAP_APPFONT ( 65 , 10 ) ; + Left = TRUE ; + }; + MetricField 3 + { + HelpID = "starmath:MetricField:RID_DISTANCEDIALOG:3"; + Border = TRUE ; + TabStop = TRUE ; + Left = TRUE ; + Spin = TRUE ; + SpinSize = 1 ; + Repeat = TRUE; + Pos = MAP_APPFONT ( 78 , 50 ) ; + Size = MAP_APPFONT ( 38 , 12 ) ; + CustomUnitText [ en-US ] = "%" ; + }; + FixedText 4 + { + Disable = TRUE ; + Hide = TRUE ; + Pos = MAP_APPFONT ( 12 , 67 ) ; + Size = MAP_APPFONT ( 65 , 10 ) ; + Left = TRUE ; + }; + MetricField 4 + { + HelpID = "starmath:MetricField:RID_DISTANCEDIALOG:4"; + Border = TRUE ; + TabStop = TRUE ; + Left = TRUE ; + Spin = TRUE ; + SpinSize = 1 ; + Repeat = TRUE; + Pos = MAP_APPFONT ( 78 , 66 ) ; + Size = MAP_APPFONT ( 38 , 12 ) ; + TabStop = TRUE ; + }; + OKButton 1 + { + Pos = MAP_APPFONT ( 184 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton 1 + { + Pos = MAP_APPFONT ( 184 , 24 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + PushButton 1 + { + HelpID = "starmath:PushButton:RID_DISTANCEDIALOG:1"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 184 , 69 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Default" ; + }; + MenuButton 1 + { + HelpID = "starmath:MenuButton:RID_DISTANCEDIALOG:1"; + TabStop = TRUE ; + ButtonMenu = Menu , RID_DISTANCEMENU ; + Pos = MAP_APPFONT ( 184 , 51 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Category" ; + }; + FixedBitmap 1 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 122 , 18 ) ; + Size = MAP_APPFONT ( 49 , 53 ) ; + }; + FixedLine 1 + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 171 , 8 ) ; + Text [ en-US ] = "Category" ; + }; + Resource 1 + { + String 1 + { + Text [ en-US ] = "Spacing" ; + }; + String 2 + { + Text [ en-US ] = "~Spacing"; + }; + Bitmap 20 + { + File = "dist11.bmp" ; + }; + String 3 + { + Text [ en-US ] = "~Line spacing"; + }; + Bitmap 30 + { + File = "dist12.bmp" ; + }; + String 4 + { + Text [ en-US ] = "~Root spacing"; + }; + Bitmap 40 + { + File = "dist13.bmp" ; + }; + }; + Resource 2 + { + String 1 + { + Text [ en-US ] = "Indexes"; + }; + String 2 + { + Text [ en-US ] = "~Superscript"; + }; + Bitmap 20 + { + File = "dist21.bmp" ; + }; + String 3 + { + Text [ en-US ] = "S~ubscript"; + }; + Bitmap 30 + { + File = "dist22.bmp" ; + }; + }; + Resource 3 + { + String 1 + { + Text [ en-US ] = "Fractions" ; + }; + String 2 + { + Text [ en-US ] = "~Numerator"; + }; + Bitmap 20 + { + File = "dist31.bmp" ; + }; + String 3 + { + Text [ en-US ] = "~Denominator"; + }; + Bitmap 30 + { + File = "dist32.bmp" ; + }; + }; + Resource 4 + { + String 1 + { + Text [ en-US ] = "Fraction bar" ; + }; + String 2 + { + Text [ en-US ] = "~Excess length"; + }; + Bitmap 20 + { + File = "dist41.bmp" ; + }; + String 3 + { + Text [ en-US ] = "~Weight"; + }; + Bitmap 30 + { + File = "dist42.bmp" ; + }; + }; + Resource 5 + { + String 1 + { + Text [ en-US ] = "Limits" ; + }; + String 2 + { + Text [ en-US ] = "~Upper limit"; + }; + Bitmap 20 + { + File = "dist51.bmp" ; + }; + String 3 + { + Text [ en-US ] = "~Lower limit"; + }; + Bitmap 30 + { + File = "dist52.bmp" ; + }; + }; + Resource 6 + { + String 1 + { + Text [ en-US ] = "Brackets" ; + }; + String 2 + { + Text [ en-US ] = "~Excess size (left/right)"; + }; + Bitmap 20 + { + File = "dist61.bmp" ; + }; + String 3 + { + Text [ en-US ] = "~Spacing"; + }; + Bitmap 30 + { + File = "dist62.bmp" ; + }; + String 5 + { + Text [ en-US ] = "~Excess size"; + }; + Bitmap 50 + { + File = "dist61.bmp" ; + }; + }; + Resource 7 + { + String 1 + { + Text [ en-US ] = "Matrix" ; + }; + String 2 + { + Text [ en-US ] = "~Line spacing"; + }; + Bitmap 20 + { + File = "dist71.bmp" ; + }; + String 3 + { + Text [ en-US ] = "~Column spacing"; + }; + Bitmap 30 + { + File = "dist72.bmp" ; + }; + }; + Resource 8 + { + String 1 + { + Text [ en-US ] = "Symbols" ; + }; + String 2 + { + Text [ en-US ] = "~Primary height"; + }; + Bitmap 20 + { + File = "dist81.bmp" ; + }; + String 3 + { + Text [ en-US ] = "~Minimum spacing"; + }; + Bitmap 30 + { + File = "dist82.bmp" ; + }; + }; + Resource 9 + { + String 1 + { + Text [ en-US ] = "Operators" ; + }; + String 2 + { + Text [ en-US ] = "~Excess size"; + }; + Bitmap 20 + { + File = "dist91.bmp" ; + }; + String 3 + { + Text [ en-US ] = "~Spacing"; + }; + Bitmap 30 + { + File = "dist92.bmp" ; + }; + }; + Resource 10 + { + String 1 + { + Text [ en-US ] = "Borders"; + }; + String 2 + { + Text [ en-US ] = "~Left"; + }; + Bitmap 20 + { + File = "dist101.bmp" ; + }; + String 3 + { + Text [ en-US ] = "~Right"; + }; + Bitmap 30 + { + File = "dist102.bmp" ; + }; + String 4 + { + Text [ en-US ] = "~Top"; + }; + Bitmap 40 + { + File = "dist103.bmp" ; + }; + String 5 + { + Text [ en-US ] = "~Bottom"; + }; + Bitmap 50 + { + File = "dist104.bmp" ; + }; + }; +}; + + +ModalDialog RID_ALIGNDIALOG +{ + Moveable = TRUE ; + OutputSize = TRUE ; + SVLook = TRUE ; + HelpId = CMD_SID_ALIGN ; + Size = MAP_APPFONT ( 139 , 66 ) ; + Text [ en-US ] = "Alignment" ; + RadioButton 1 + { + HelpID = "starmath:RadioButton:RID_ALIGNDIALOG:1"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 17 ) ; + Size = MAP_APPFONT ( 60 , 10 ) ; + Text [ en-US ] = "~Left" ; + }; + RadioButton 2 + { + HelpID = "starmath:RadioButton:RID_ALIGNDIALOG:2"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 31 ) ; + Size = MAP_APPFONT ( 60 , 10 ) ; + Text [ en-US ] = "~Centered" ; + }; + RadioButton 3 + { + HelpID = "starmath:RadioButton:RID_ALIGNDIALOG:3"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 44 ) ; + Size = MAP_APPFONT ( 60 , 10 ) ; + Text [ en-US ] = "~Right" ; + }; + FixedLine 1 + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 71 , 8 ) ; + Text [ en-US ] = "Horizontal" ; + }; + OKButton 1 + { + Pos = MAP_APPFONT ( 83 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton 1 + { + Pos = MAP_APPFONT ( 83 , 23 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + PushButton 1 + { + HelpID = "starmath:PushButton:RID_ALIGNDIALOG:1"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 83 , 46 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Default" ; + }; +}; + +TabPage RID_PRINTOPTIONPAGE +{ + HelpID = "starmath:TabPage:RID_PRINTOPTIONPAGE"; + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 260 , 185 ) ; + Text [ en-US ] = "Formula Options:Settings"; + FixedLine FL_PRINTOPTIONS + { + Pos = MAP_APPFONT ( 6 , 3 ) ; + Size = MAP_APPFONT ( 248 , 8 ) ; + Text [ en-US ] = "Print options"; + }; + CheckBox CB_TITLEROW + { + HelpID = "starmath:CheckBox:RID_PRINTOPTIONPAGE:CB_TITLEROW"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 14 ) ; + Size = MAP_APPFONT ( 68 , 10 ) ; + Text [ en-US ] = "~Title row" ; + }; + CheckBox CB_EQUATION_TEXT + { + HelpID = "starmath:CheckBox:RID_PRINTOPTIONPAGE:CB_EQUATION_TEXT"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 28 ) ; + Size = MAP_APPFONT ( 68 , 10 ) ; + Text [ en-US ] = "~Formula text" ; + }; + CheckBox CB_FRAME + { + HelpID = "starmath:CheckBox:RID_PRINTOPTIONPAGE:CB_FRAME"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 42 ) ; + Size = MAP_APPFONT ( 68 , 10 ) ; + Text [ en-US ] = "B~order" ; + }; + FixedLine FL_PRINT_FORMAT + { + Pos = MAP_APPFONT ( 6 , 58 ) ; + Size = MAP_APPFONT ( 248 , 8 ) ; + Text [ en-US ] = "Print format" ; + }; + RadioButton RB_ORIGINAL_SIZE + { + HelpID = "starmath:RadioButton:RID_PRINTOPTIONPAGE:RB_ORIGINAL_SIZE"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 69 ) ; + Size = MAP_APPFONT ( 90 , 10 ) ; + Text [ en-US ] = "O~riginal size" ; + }; + RadioButton RB_FIT_TO_PAGE + { + HelpID = "starmath:RadioButton:RID_PRINTOPTIONPAGE:RB_FIT_TO_PAGE"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 83 ) ; + Size = MAP_APPFONT ( 90 , 10 ) ; + Text [ en-US ] = "Fit to ~page" ; + }; + RadioButton RB_ZOOM + { + HelpID = "starmath:RadioButton:RID_PRINTOPTIONPAGE:RB_ZOOM"; + Pos = MAP_APPFONT ( 12 , 97 ) ; + Size = MAP_APPFONT ( 90 , 10 ) ; + Text [ en-US ] = "~Scaling" ; + TabStop = TRUE ; + }; + MetricField MF_ZOOM + { + HelpID = "starmath:MetricField:RID_PRINTOPTIONPAGE:MF_ZOOM"; + Border = TRUE ; + Pos = MAP_APPFONT ( 18 , 111 ) ; + Size = MAP_APPFONT ( 30 , 12 ) ; + TabStop = TRUE ; + Left = TRUE ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 10 ; + Maximum = 400 ; + Unit = FUNIT_CUSTOM ; + CustomUnitText = "%" ; + }; + FixedLine FL_MISC_OPTIONS + { + Pos = MAP_APPFONT ( 6 , 129 ) ; + Size = MAP_APPFONT ( 248 , 8 ) ; + Text [ en-US ] = "Miscellaneous options"; + }; + CheckBox CB_IGNORE_SPACING + { + HelpID = "starmath:CheckBox:RID_PRINTOPTIONPAGE:CB_IGNORE_SPACING"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 140 ) ; + Size = MAP_APPFONT ( 236 , 10 ) ; + Text [ en-US ] = "Ig~nore ~~ and ` at the end of the line"; + }; + CheckBox CB_SAVE_ONLY_USED_SYMBOLS + { + TabStop = TRUE ; + Pos = MAP_APPFONT ( 12 , 154 ) ; + Size = MAP_APPFONT ( 236 , 10 ) ; + Text [ en-US ] = "Embed only used symbols (smaller file size)"; + }; +}; + +ModalDialog RID_SYMBOLDIALOG +{ + HelpID = "starmath:ModalDialog:RID_SYMBOLDIALOG"; + OutputSize = TRUE ; + SVLook = TRUE ; + Closeable = TRUE; // Close Button in Window Leiste explizit einbauen + Size = MAP_APPFONT ( 239 , 123 ) ; + Text [ en-US ] = "Symbols" ; + Moveable = TRUE ; + FixedText 1 + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 92 , 8 ) ; + Left = TRUE ; + Text [ en-US ] = "~Symbol set"; + }; + ListBox 1 + { + HelpID = "starmath:ListBox:RID_SYMBOLDIALOG:1"; + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 17 ) ; + Size = MAP_APPFONT ( 92, 57 ) ; + TabStop = TRUE ; + Sort = TRUE ; + DropDown = TRUE ; + VScroll = TRUE ; + }; + Control 1 + { + HelpID = HID_SMA_CONTROL_SYMBOLSET_VIEW ; + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 35 ) ; + Size = MAP_APPFONT ( 96 , 72 ) ; + TabStop = TRUE ; + }; + Control 2 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 108 , 35 ) ; + Size = MAP_APPFONT ( 63 , 72 ) ; + }; + FixedText 2 + { + Center = TRUE ; + Pos = MAP_APPFONT ( 6 , 108 ) ; + Size = MAP_APPFONT ( 92 , 8 ) ; + Text [ en-US ] = "Unknown" ; + }; + PushButton 2 + { + HelpID = "starmath:PushButton:RID_SYMBOLDIALOG:2"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 177 , 6 ) ; + Size = MAP_APPFONT ( 56 , 14 ) ; + DefButton = TRUE ; + Text [ en-US ] = "~Insert" ; + }; + PushButton 3 + { + HelpID = "starmath:PushButton:RID_SYMBOLDIALOG:3"; + Pos = MAP_APPFONT ( 177 , 24 ) ; + Size = MAP_APPFONT ( 56 , 14 ) ; + TabStop = TRUE ; + Text [ en-US ] = "~Close"; + }; + PushButton 1 + { + HelpID = "starmath:PushButton:RID_SYMBOLDIALOG:1"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 177 , 42 ) ; + Size = MAP_APPFONT ( 56 , 14 ) ; + Text [ en-US ] = "~Edit..." ; + }; +}; + +ModalDialog RID_SYMDEFINEDIALOG +{ + HelpID = "starmath:ModalDialog:RID_SYMDEFINEDIALOG"; + Moveable = TRUE ; + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 365 , 215 ) ; + Text [ en-US ] = "Edit Symbols" ; + FixedText 1 + { + Pos = MAP_APPFONT ( 6 , 8 ) ; + Size = MAP_APPFONT ( 50 , 8 ) ; + Left = TRUE ; + Text [ en-US ] = "~Old symbol"; + }; + ComboBox 1 + { + HelpID = "starmath:ComboBox:RID_SYMDEFINEDIALOG:1"; + Pos = MAP_APPFONT ( 59 , 6 ) ; + Size = MAP_APPFONT ( 80 , 100 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + Sort = TRUE ; + }; + FixedText 2 + { + Pos = MAP_APPFONT ( 145 , 8 ) ; + Size = MAP_APPFONT ( 60 , 8 ) ; + Left = TRUE ; + Text [ en-US ] = "O~ld symbol set"; + }; + ComboBox 2 + { + HelpID = "starmath:ComboBox:RID_SYMDEFINEDIALOG:2"; + Pos = MAP_APPFONT ( 210 , 6 ) ; + Size = MAP_APPFONT ( 80 , 100 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + Sort = TRUE ; + }; + Control 1 + { + HelpID = HID_SMA_CONTROL_FONTCHAR_VIEW ; + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 24 ) ; + Size = MAP_APPFONT ( 295 , 87 ) ; + TabStop = TRUE ; + Group = TRUE ; + }; + FixedText 9 + { + Pos = MAP_APPFONT ( 6 , 118 ) ; + Size = MAP_APPFONT ( 71 , 8 ) ; + Left = TRUE ; + Text [ en-US ] = "~Symbol"; + }; + ComboBox 4 + { + HelpID = "starmath:ComboBox:RID_SYMDEFINEDIALOG:4"; + Pos = MAP_APPFONT ( 80 , 115 ) ; + Size = MAP_APPFONT ( 100 , 100 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + Sort = TRUE ; + }; + FixedText 10 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 6 , 133 ) ; + Size = MAP_APPFONT ( 71 , 8 ) ; + Text [ en-US ] = "Symbol s~et"; + }; + ComboBox 5 + { + HelpID = "starmath:ComboBox:RID_SYMDEFINEDIALOG:5"; + Pos = MAP_APPFONT ( 80 , 130 ) ; + Size = MAP_APPFONT ( 100 , 100 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + Sort = TRUE ; + }; + FixedText 3 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 6 , 148 ) ; + Size = MAP_APPFONT ( 71 , 8 ) ; + Text [ en-US ] = "~Font"; + }; + ListBox 1 + { + HelpID = "starmath:ListBox:RID_SYMDEFINEDIALOG:1"; + Border = TRUE ; + Pos = MAP_APPFONT ( 80 , 145 ) ; + Size = MAP_APPFONT ( 100 , 100 ) ; + TabStop = TRUE ; + Sort = TRUE ; + DropDown = TRUE ; + }; + FixedText FT_FONTS_SUBSET + { + Left = TRUE ; + Pos = MAP_APPFONT ( 6 , 163 ) ; + Size = MAP_APPFONT ( 71 , 8 ) ; + Text [ en-US ] = "~Subset"; + }; + ListBox LB_FONTS_SUBSET + { + HelpID = "starmath:ListBox:RID_SYMDEFINEDIALOG:LB_FONTS_SUBSET"; + Border = TRUE ; + Pos = MAP_APPFONT ( 80 , 160 ) ; + Size = MAP_APPFONT ( 100 , 100 ) ; + TabStop = TRUE ; + Sort = FALSE ; + DropDown = TRUE ; + }; + FixedText 4 + { + Left = TRUE ; + Pos = MAP_APPFONT ( 6 , 178 ) ; + Size = MAP_APPFONT ( 71 , 8 ) ; + Text [ en-US ] = "~Typeface"; + }; + ComboBox 3 + { + HelpID = "starmath:ComboBox:RID_SYMDEFINEDIALOG:3"; + Border = TRUE; + Pos = MAP_APPFONT ( 80 , 175 ) ; + Size = MAP_APPFONT ( 100 , 100 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + Sort = FALSE ; + }; + FixedText 5 + { + Center = TRUE ; + Pos = MAP_APPFONT ( 303 , 130 ) ; + Size = MAP_APPFONT ( 54 , 8 ) ; + }; + Control 2 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 310 , 140 ) ; + Size = MAP_APPFONT ( 40 , 40 ) ; + }; + FixedText 6 + { + Center = TRUE ; + Pos = MAP_APPFONT ( 303 , 182 ) ; + Size = MAP_APPFONT ( 54 , 8 ) ; + }; + Image 1 + { + ImageBitmap = Bitmap { File = "ar_right.bmp" ; }; + MaskColor = IMAGE_STDBTN_COLOR ; + }; + FixedImage BMP_ARROW_RIGHT + { + Pos = MAP_APPFONT ( 252 , 142 ) ; + Size = MAP_APPFONT ( 36 , 36 ) ; + + Fixed = Image + { + ImageBitmap = Bitmap { File = "ar_right.bmp" ; }; + MaskColor = IMAGE_STDBTN_COLOR ; + }; + }; + FixedText 7 + { + Center = TRUE ; + Pos = MAP_APPFONT ( 183 , 130 ) ; + Size = MAP_APPFONT ( 54 , 9 ) ; + }; + Control 3 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 190 , 140 ) ; + Size = MAP_APPFONT ( 40 , 40 ) ; + }; + FixedText 8 + { + Center = TRUE ; + Pos = MAP_APPFONT ( 183 , 182 ) ; + Size = MAP_APPFONT ( 54 , 8 ) ; + }; + PushButton 1 + { + HelpID = "starmath:PushButton:RID_SYMDEFINEDIALOG:1"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 305 , 195 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Add" ; + }; + PushButton 2 + { + HelpID = "starmath:PushButton:RID_SYMDEFINEDIALOG:2"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 245 , 195 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Modify" ; + }; + PushButton 3 + { + HelpID = "starmath:PushButton:RID_SYMDEFINEDIALOG:3"; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 185 , 195 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Delete" ; + }; + OKButton 1 + { + Pos = MAP_APPFONT ( 310 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton 1 + { + Pos = MAP_APPFONT ( 310 , 24 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; +}; + +WarningBox RID_NOMATHTYPEFACEWARNING +{ + Message [ en-US ] = "The 'StarMath' font has not been installed.\nWithout this font %PRODUCTNAME Math cannot function correctly.\nPlease install this font and restart %PRODUCTNAME Math." ; +}; + +QueryBox RID_DEFAULTSAVEQUERY +{ + Buttons = WB_YES_NO ; + DefButton = WB_DEF_YES ; + Message [ en-US ] = "Should the changes be saved as defaults?\n\nThese changes will apply for all new formulas." ; +}; + +String RID_FONTREGULAR +{ + Text [ en-US ] = "Standard" ; +}; +String RID_FONTITALIC +{ + Text [ en-US ] = "Italic" ; +}; +String RID_FONTBOLD +{ + Text [ en-US ] = "Bold" ; +}; +String RID_APPLICATION +{ + Text = "StarMath" ; +}; +String RID_OBJECTNAME +{ + Text = "SMath3" ; +}; +String RID_UNDOEDITNAME +{ + Text = "Edit" ; +}; +String RID_UNDOFORMATNAME +{ + Text = "Format" ; +}; +String GID_FORMEL +{ + Text = "StarMath" ; +}; +Menu RID_VIEWMENU +{ + ItemList = + { + MenuItem + { + Identifier = SID_VIEW050 ; + HelpId = CMD_SID_VIEW050 ; + Text [ en-US ] = "~View 50%" ; + }; + MenuItem + { + Identifier = SID_VIEW100 ; + HelpId = CMD_SID_VIEW100 ; + Text [ en-US ] = "View ~100%" ; + }; + MenuItem + { + Identifier = SID_VIEW200 ; + HelpId = CMD_SID_VIEW200 ; + Text [ en-US ] = "View ~200%" ; + }; + MenuItem + { + Identifier = SID_ZOOMIN ; + HelpId = CMD_SID_ZOOMIN ; + Text [ en-US ] = "~Zoom In" ; + }; + MenuItem + { + Identifier = SID_ZOOMOUT ; + HelpId = CMD_SID_ZOOMOUT ; + Text [ en-US ] = "Zoom ~Out" ; + }; + MenuItem + { + Identifier = SID_ADJUST ; + HelpId = CMD_SID_ADJUST ; + Text [ en-US ] = "~Display All" ; + }; + MenuItem + { + Separator = TRUE ; + }; + MenuItem + { + Identifier = SID_DRAW ; + HelpId = CMD_SID_DRAW ; + Text [ en-US ] = "U~pdate" ; + }; + }; +}; +Menu RID_DISTANCEMENU +{ + ItemList = + { + MenuItem + { + Identifier = WORKARROUND_1 ; + Text [ en-US ] = "Spacing" ; + }; + MenuItem + { + Identifier = 2 ; + Text [ en-US ] = "Indexes" ; + }; + MenuItem + { + Identifier = WORKARROUND_3 ; + Text [ en-US ] = "Fractions" ; + }; + MenuItem + { + Identifier = 4 ; + Text [ en-US ] = "Fraction Bars" ; + }; + MenuItem + { + Identifier = 5 ; + Text [ en-US ] = "Limits" ; + }; + MenuItem + { + Identifier = 6 ; + Text [ en-US ] = "Brackets" ; + }; + MenuItem + { + Identifier = 7 ; + Text [ en-US ] = "Matrices" ; + }; + MenuItem + { + Identifier = 8 ; + Text [ en-US ] = "Symbols" ; + }; + MenuItem + { + Identifier = 9 ; + Text [ en-US ] = "Operators" ; + }; + MenuItem + { + Identifier = WORKARROUND_10 ; + Text [ en-US ] = "Borders"; + }; + }; +}; + +Menu RID_FONTMENU +{ + ItemList = + { + MenuItem + { + Identifier = 1 ; + Text [ en-US ] = "Variables" ; + }; + MenuItem + { + Identifier = 2 ; + Text [ en-US ] = "Functions" ; + }; + MenuItem + { + Identifier = 3 ; + Text [ en-US ] = "Numbers" ; + }; + MenuItem + { + Identifier = 4 ; + Text [ en-US ] = "Text" ; + }; + MenuItem + { + Identifier = 5 ; + Text [ en-US ] = "Serif" ; + }; + MenuItem + { + Identifier = 6 ; + Text [ en-US ] = "Sans" ; + }; + MenuItem + { + Identifier = 7 ; + Text [ en-US ] = "Fixed" ; + }; + }; +}; + +#define CMDBOXWINDOW_TEXT \ + Text [ en-US ] = "Commands" ; \ + +DockingWindow RID_CMDBOXWINDOW\ +{ + HelpId = HID_SMA_COMMAND_WIN ; + Moveable = TRUE ; + Closeable = FALSE ; + Sizeable = TRUE ; + OutputSize = TRUE ; + HideWhenDeactivate = FALSE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 292 , 94 ) ; + Dockable = TRUE ; + CMDBOXWINDOW_TEXT +}; + + +String STR_CMDBOXWINDOW +{ + CMDBOXWINDOW_TEXT +}; + +String RID_DOCUMENTSTR +{ + Text [ en-US ] = "Formula" ; +}; + +String STR_STATSTR_READING +{ + Text [ en-US ] = "Loading document..." ; +}; + +String STR_STATSTR_WRITING +{ + Text [ en-US ] = "Saving document..." ; +}; + + +String STR_MATH_DOCUMENT_FULLTYPE_CURRENT +{ + Text [ en-US ] = "%PRODUCTNAME %PRODUCTVERSION Formula"; +}; + +String RID_SYMBOLFILESSTR +{ + Text [ en-US ] = "Symbol files (*.sms)" ; +}; + +String RID_ALLFILESSTR +{ + Text [ en-US ] = "All Files (*.*)" ; +}; + +String RID_ERR_IDENT +{ + Text [ en-US ] = "ERROR : " ; +}; + +String RID_ERR_UNKOWN +{ + Text [ en-US ] = "Unknown error occurred" ; +}; + +String RID_ERR_UNEXPECTEDCHARACTER +{ + Text [ en-US ] = "Unexpected character" ; +}; + +String RID_ERR_OVERFLOW +{ + Text [ en-US ] = "Formula entry too complex" ; +}; + +String RID_ERR_LGROUPEXPECTED +{ + Text [ en-US ] = "'{' expected" ; +}; + +String RID_ERR_RGROUPEXPECTED +{ + Text [ en-US ] = "'}' expected" ; +}; + +String RID_ERR_LBRACEEXPECTED +{ + Text [ en-US ] = "'(' expected" ; +}; + +String RID_ERR_RBRACEEXPECTED +{ + Text [ en-US ] = "')' expected" ; +}; + +String RID_ERR_FUNCEXPECTED +{ + Text [ en-US ] = "Function expected" ; +}; + +String RID_ERR_UNOPEREXPECTED +{ + Text [ en-US ] = "Unary operator expected" ; +}; + +String RID_ERR_BINOPEREXPECTED +{ + Text [ en-US ] = "Binary operator expected" ; +}; + +String RID_ERR_SYMBOLEXPECTED +{ + Text [ en-US ] = "Symbol expected" ; +}; + +String RID_ERR_IDENTEXPECTED +{ + Text [ en-US ] = "Identifier expected" ; +}; + +String RID_ERR_POUNDEXPECTED +{ + Text [ en-US ] = "'#' expected" ; +}; + +String RID_ERR_COLOREXPECTED +{ + Text [ en-US ] = "Color required" ; +}; + +String RID_ERR_LPARENTEXPECTED +{ + Text [ en-US ] = "Left limit expected" ; +}; + +String RID_ERR_RPARENTEXPECTED +{ + Text [ en-US ] = "Right limit expected" ; +}; + +String RID_ERR_RIGHTEXPECTED +{ + Text [ en-US ] = "'RIGHT' expected" ; +}; + +String RID_MATH_TOOLBOX +{ + Text [ en-US ] = "Main Toolbar" ; +}; + +StringArray RID_PRINTUIOPTIONS +{ + ItemList [en-US] = + { + < "%PRODUCTNAME %s"; >; + < "Contents"; >; + < "~Title"; >; + < "~Formula text"; >; + < "B~orders"; >; + < "Size"; >; + < "O~riginal size"; >; + < "Fit to ~page"; >; + < "~Scaling"; >; + }; +}; + diff --git a/starmath/source/symbol.cxx b/starmath/source/symbol.cxx new file mode 100644 index 000000000000..21b9051d64b9 --- /dev/null +++ b/starmath/source/symbol.cxx @@ -0,0 +1,338 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <osl/mutex.hxx> +#include <ucbhelper/content.hxx> +#include <vcl/msgbox.hxx> + +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> + +#include <map> +#include <vector> +#include <iterator> + +#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; + + +/**************************************************************************/ + +SmSym::SmSym() : + m_aName(C2S("unknown")), + m_aSetName(C2S("unknown")), + m_cChar('\0'), + m_bPredefined(false), + m_bDocSymbol(false) +{ + m_aExportName = m_aName; + m_aFace.SetTransparent(true); + m_aFace.SetAlign(ALIGN_BASELINE); +} + + +SmSym::SmSym(const SmSym& rSymbol) +{ + *this = rSymbol; +} + + +SmSym::SmSym(const String& rName, const Font& rFont, sal_UCS4 cChar, + const String& rSet, bool bIsPredefined) +{ + m_aName = m_aExportName = rName; + + m_aFace = rFont; + m_aFace.SetTransparent(true); + m_aFace.SetAlign(ALIGN_BASELINE); + + m_cChar = cChar; + m_aSetName = rSet; + m_bPredefined = bIsPredefined; + m_bDocSymbol = false; +} + + +SmSym& SmSym::operator = (const SmSym& rSymbol) +{ + m_aName = rSymbol.m_aName; + m_aExportName = rSymbol.m_aExportName; + m_cChar = rSymbol.m_cChar; + m_aFace = rSymbol.m_aFace; + m_aSetName = rSymbol.m_aSetName; + m_bPredefined = rSymbol.m_bPredefined; + m_bDocSymbol = rSymbol.m_bDocSymbol; + + SmSymbolManager * pSymSetManager = &SM_MOD()->GetSymbolManager(); + if (pSymSetManager) + pSymSetManager->SetModified(true); + + return *this; +} + + +bool SmSym::IsEqualInUI( const SmSym& rSymbol ) const +{ + return m_aName == rSymbol.m_aName && + m_aFace == rSymbol.m_aFace && + m_cChar == rSymbol.m_cChar; +} + +/**************************************************************************/ + +void SmSymbolManager::SFX_NOTIFY(SfxBroadcaster& /*rBC*/, const TypeId& rBCType, + const SfxHint& /*rHint*/, const TypeId& rHintType) +{ +} + + +void SmSymbolManager::Init() +{ + SmModule *pp = SM_MOD(); + StartListening(*pp->GetConfig()); +} + + +void SmSymbolManager::Exit() +{ + SmModule *pp = SM_MOD(); + EndListening(*pp->GetConfig()); +} + + +SmSymbolManager::SmSymbolManager() +{ + m_bModified = false; +} + + +SmSymbolManager::SmSymbolManager(const SmSymbolManager& rSymbolSetManager) : + SfxListener() +{ + m_aSymbols = rSymbolSetManager.m_aSymbols; + m_bModified = true; +} + + +SmSymbolManager::~SmSymbolManager() +{ +} + + +SmSymbolManager& SmSymbolManager::operator = (const SmSymbolManager& rSymbolSetManager) +{ + m_aSymbols = rSymbolSetManager.m_aSymbols; + m_bModified = true; + return *this; +} + + +SmSym *SmSymbolManager::GetSymbolByName(const String& rSymbolName) +{ + SmSym *pRes = NULL; + SymbolMap_t::iterator aIt( m_aSymbols.find( rSymbolName ) ); + if (aIt != m_aSymbols.end()) + pRes = &aIt->second; + return pRes; +} + + +const SymbolPtrVec_t SmSymbolManager::GetSymbols() const +{ + SymbolPtrVec_t aRes; + SymbolMap_t::const_iterator aIt( m_aSymbols.begin() ); + for ( ; aIt != m_aSymbols.end(); ++aIt) + aRes.push_back( &aIt->second ); +// OSL_ENSURE( sSymbols.size() == m_aSymbols.size(), "number of symbols mismatch " ); + return aRes; +} + + +bool SmSymbolManager::AddOrReplaceSymbol( const SmSym &rSymbol, bool bForceChange ) +{ + bool bAdded = false; + + const String aSymbolName( rSymbol.GetName() ); + if (aSymbolName.Len() > 0 && rSymbol.GetSymbolSetName().Len() > 0) + { + const SmSym *pFound = GetSymbolByName( aSymbolName ); + const bool bSymbolConflict = pFound && !pFound->IsEqualInUI( rSymbol ); + + // avoid having the same symbol name twice but with different symbols in use + if (!pFound || bForceChange) + { + m_aSymbols[ aSymbolName ] = rSymbol; + bAdded = true; + } + else if (pFound && !bForceChange && bSymbolConflict) + { + // TODO: to solve this a document owned symbol manager would be required ... + OSL_FAIL( "symbol conflict, different symbol with same name found!" ); + // symbols in all formulas. A copy of the global one would be needed here + // and then the new symbol has to be forcefully applied. This would keep + // the current formula intact but will leave the set of symbols in the + // global symbol manager somewhat to chance. + } + + OSL_ENSURE( bAdded, "failed to add symbol" ); + if (bAdded) + m_bModified = true; + OSL_ENSURE( bAdded || (pFound && !bSymbolConflict), "AddOrReplaceSymbol: unresolved symbol conflict" ); + } + + return bAdded; +} + + +void SmSymbolManager::RemoveSymbol( const String & rSymbolName ) +{ + if (rSymbolName.Len() > 0) + { + size_t nOldSize = m_aSymbols.size(); + m_aSymbols.erase( rSymbolName ); + m_bModified = nOldSize != m_aSymbols.size(); + } +} + + +std::set< String > SmSymbolManager::GetSymbolSetNames() const +{ + std::set< String > aRes; + SymbolMap_t::const_iterator aIt( m_aSymbols.begin() ); + for ( ; aIt != m_aSymbols.end(); ++aIt ) + aRes.insert( aIt->second.GetSymbolSetName() ); + return aRes; +} + + +const SymbolPtrVec_t SmSymbolManager::GetSymbolSet( const String& rSymbolSetName ) +{ + SymbolPtrVec_t aRes; + if (rSymbolSetName.Len() > 0) + { + SymbolMap_t::const_iterator aIt( m_aSymbols.begin() ); + for ( ; aIt != m_aSymbols.end(); ++aIt ) + { + if (aIt->second.GetSymbolSetName() == rSymbolSetName) + aRes.push_back( &aIt->second ); + } + } + return aRes; +} + + +void SmSymbolManager::Load() +{ + std::vector< SmSym > aSymbols; + SmMathConfig &rCfg = *SM_MOD()->GetConfig(); + rCfg.GetSymbols( aSymbols ); + size_t nSymbolCount = aSymbols.size(); + + m_aSymbols.clear(); + for (size_t i = 0; i < nSymbolCount; ++i) + { + const SmSym &rSym = aSymbols[i]; + OSL_ENSURE( rSym.GetName().Len() > 0, "symbol without name!" ); + if (rSym.GetName().Len() > 0) + AddOrReplaceSymbol( rSym ); + } + m_bModified = true; + + if (0 == nSymbolCount) + { + OSL_FAIL( "no symbol set found" ); + m_bModified = false; + } + + // now add a %i... symbol to the 'iGreek' set for every symbol found in the 'Greek' set. + SmLocalizedSymbolData aLocalizedData; + const String aGreekSymbolSetName( aLocalizedData.GetUiSymbolSetName( A2OU("Greek") ) ); + const SymbolPtrVec_t aGreekSymbols( GetSymbolSet( aGreekSymbolSetName ) ); + String aSymbolSetName( (sal_Unicode) 'i' ); + aSymbolSetName += aGreekSymbolSetName; + size_t nSymbols = aGreekSymbols.size(); + for (size_t i = 0; i < nSymbols; ++i) + { + // make the new symbol a copy but with ITALIC_NORMAL, and add it to iGreek + const SmSym &rSym = *aGreekSymbols[i]; + Font aFont( rSym.GetFace() ); + OSL_ENSURE( aFont.GetItalic() == ITALIC_NONE, "expected Font with ITALIC_NONE, failed." ); + aFont.SetItalic( ITALIC_NORMAL ); + String aSymbolName( (sal_Unicode)'i' ); + aSymbolName += rSym.GetName(); + SmSym aSymbol( aSymbolName, aFont, rSym.GetCharacter(), + aSymbolSetName, true /*bIsPredefined*/ ); + + AddOrReplaceSymbol( aSymbol ); + } +} + +void SmSymbolManager::Save() +{ + if (m_bModified) + { + SmMathConfig &rCfg = *SM_MOD()->GetConfig(); + + // prepare to skip symbols from iGreek on saving + SmLocalizedSymbolData aLocalizedData; + String aSymbolSetName( (sal_Unicode) 'i' ); + aSymbolSetName += aLocalizedData.GetUiSymbolSetName( A2OU("Greek") ); + + SymbolPtrVec_t aTmp( GetSymbols() ); + std::vector< SmSym > aSymbols; + for (size_t i = 0; i < aTmp.size(); ++i) + { + // skip symbols from iGreek set since those symbols always get added + // by computational means in SmSymbolManager::Load + if (aTmp[i]->GetSymbolSetName() != aSymbolSetName) + aSymbols.push_back( *aTmp[i] ); + } + rCfg.SetSymbols( aSymbols ); + + m_bModified = false; + } +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/symbol.src b/starmath/source/symbol.src new file mode 100644 index 000000000000..7f8e15a15817 --- /dev/null +++ b/starmath/source/symbol.src @@ -0,0 +1,344 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <starmath.hrc> + + +///////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////// + +Resource RID_LOCALIZED_NAMES +{ + StringArray RID_FRENCH_50_NAMES + { + ItemList = + { + < "BETA" ; > ; + < "beta" ; > ; + < "ETA" ; > ; + < "eta" ; > ; + < "JOTA" ; > ; + < "jota" ; > ; + < "CHI" ; > ; + < "chi" ; > ; + < "MY" ; > ; + < "my" ; > ; + < "NY" ; > ; + < "ny" ; > ; + < "OMIKRON" ; > ; + < "omikron" ; > ; + < "OMEGA" ; > ; + < "omega" ; > ; + < "RHO" ; > ; + < "rho" ; > ; + < "THETA" ; > ; + < "theta" ; > ; + < "YPSILON" ; > ; + < "ypsilon" ; > ; + < "ZETA" ; > ; + < "zeta" ; > ; + < "varrho" ; > ; + < "vartheta" ; > ; + }; + }; + StringArray RID_FRENCH_60_NAMES + { + ItemList = + { + < "BÊTA" ; > ; + < "bêta" ; > ; + < "ÊTA" ; > ; + < "êta" ; > ; + < "IOTA" ; > ; + < "iota" ; > ; + < "KHI" ; > ; + < "khi" ; > ; + < "MU" ; > ; + < "mu" ; > ; + < "NU" ; > ; + < "nu" ; > ; + < "OMICRON" ; > ; + < "omicron" ; > ; + < "OMÉGA" ; > ; + < "oméga" ; > ; + < "RHÔ" ; > ; + < "rhô" ; > ; + < "THÊTA" ; > ; + < "thêta" ; > ; + < "UPSILON" ; > ; + < "upsilon" ; > ; + < "ZÊTA" ; > ; + < "zêta" ; > ; + < "varrhô" ; > ; + < "varthêta" ; > ; + }; + }; + StringArray RID_ITALIAN_50_NAMES + { + ItemList = + { + < "nu" ; > ; + < "Nu" ; > ; + < "varrho" ; > ; + < "moltomaggioredi" ; > ; + < "indentico" ; > ; + < "nonelemento" ; > ; + < "moltoinferioredi" ; > ; + < "o" ; > ; + < "permille" ; > ; + < "tendentea" ; > ; + < "nonuguale" ; > ; + < "infinite" ; > ; + }; + }; + StringArray RID_ITALIAN_60_NAMES + { + ItemList = + { + < "ni" ; > ; + < "Ni" ; > ; + < "varro" ; > ; + < "molto.maggiore.di" ; > ; + < "identico" ; > ; + < "non.elemento" ; > ; + < "molto.minore.di" ; > ; + < "oppure" ; > ; + < "per.mille" ; > ; + < "tendente.a" ; > ; + < "non.uguale" ; > ; + < "infinito" ; > ; + }; + }; + StringArray RID_SWEDISH_50_NAMES + { + ItemList = + { + < "iota" ; > ; + < "IOTA" ; > ; + < "xi" ; > ; + < "XI" ; > ; + < "rho" ; > ; + < "RHO" ; > ; + < "element" ; > ; + }; + }; + StringArray RID_SWEDISH_60_NAMES + { + ItemList = + { + < "jota" ; > ; + < "JOTA" ; > ; + < "ksi" ; > ; + < "KSI" ; > ; + < "ro" ; > ; + < "RO" ; > ; + < "tillhör" ; > ; + }; + }; + StringArray RID_SPANISH_50_NAMES + { + ItemList = + { + < "distino" ; > ; + < "muchomenos" ; > ; + < "pertenece" ; > ; + < "nopertenece" ; > ; + }; + }; + StringArray RID_SPANISH_60_NAMES + { + ItemList = + { + < "diferente" ; > ; + < "muchomenor" ; > ; + < "elemento" ; > ; + < "sinelemento" ; > ; + }; + }; + StringArray RID_EXPORT_SYMBOLSET_NAMES + { + ItemList = + { + < "Greek" ; > ; + < "Special" ; > ; + }; + }; + StringArray RID_UI_SYMBOLSET_NAMES + { + ItemList [ en-US ] = + { + < "Greek" ; > ; + < "Special" ; > ; + }; + }; + StringArray RID_EXPORT_SYMBOL_NAMES + { + ItemList = + { + < "alpha" ; > ; + < "ALPHA" ; > ; + < "beta" ; > ; + < "BETA" ; > ; + < "gamma" ; > ; + < "GAMMA" ; > ; + < "delta" ; > ; + < "DELTA" ; > ; + < "epsilon" ; > ; + < "EPSILON" ; > ; + < "zeta" ; > ; + < "ZETA" ; > ; + < "eta" ; > ; + < "ETA" ; > ; + < "theta" ; > ; + < "THETA" ; > ; + < "iota" ; > ; + < "IOTA" ; > ; + < "kappa" ; > ; + < "KAPPA" ; > ; + < "lambda" ; > ; + < "LAMBDA" ; > ; + < "mu" ; > ; + < "MU" ; > ; + < "nu" ; > ; + < "NU" ; > ; + < "xi" ; > ; + < "XI" ; > ; + < "omicron" ; > ; + < "OMICRON" ; > ; + < "pi" ; > ; + < "PI" ; > ; + < "rho" ; > ; + < "RHO" ; > ; + < "sigma" ; > ; + < "SIGMA" ; > ; + < "tau" ; > ; + < "TAU" ; > ; + < "upsilon" ; > ; + < "UPSILON" ; > ; + < "phi" ; > ; + < "PHI" ; > ; + < "chi" ; > ; + < "CHI" ; > ; + < "psi" ; > ; + < "PSI" ; > ; + < "omega" ; > ; + < "OMEGA" ; > ; + < "varepsilon" ; > ; + < "vartheta" ; > ; + < "varpi" ; > ; + < "varrho" ; > ; + < "varsigma" ; > ; + < "varphi" ; > ; + < "element" ; > ; + < "noelement" ; > ; + < "strictlylessthan" ; > ; + < "strictlygreaterthan" ; > ; + < "notequal" ; > ; + < "identical" ; > ; + < "tendto" ; > ; + < "infinite" ; > ; + < "angle" ; > ; + < "perthousand" ; > ; + < "and" ; > ; + < "or" ; > ; + }; + }; + StringArray RID_UI_SYMBOL_NAMES + { + ItemList [ en-US ] = + { + < "alpha" ; > ; + < "ALPHA" ; > ; + < "beta" ; > ; + < "BETA" ; > ; + < "gamma" ; > ; + < "GAMMA" ; > ; + < "delta" ; > ; + < "DELTA" ; > ; + < "epsilon" ; > ; + < "EPSILON" ; > ; + < "zeta" ; > ; + < "ZETA" ; > ; + < "eta" ; > ; + < "ETA" ; > ; + < "theta" ; > ; + < "THETA" ; > ; + < "iota" ; > ; + < "IOTA" ; > ; + < "kappa" ; > ; + < "KAPPA" ; > ; + < "lambda" ; > ; + < "LAMBDA" ; > ; + < "mu" ; > ; + < "MU" ; > ; + < "nu" ; > ; + < "NU" ; > ; + < "xi" ; > ; + < "XI" ; > ; + < "omicron" ; > ; + < "OMICRON" ; > ; + < "pi" ; > ; + < "PI" ; > ; + < "rho" ; > ; + < "RHO" ; > ; + < "sigma" ; > ; + < "SIGMA" ; > ; + < "tau" ; > ; + < "TAU" ; > ; + < "upsilon" ; > ; + < "UPSILON" ; > ; + < "phi" ; > ; + < "PHI" ; > ; + < "chi" ; > ; + < "CHI" ; > ; + < "psi" ; > ; + < "PSI" ; > ; + < "omega" ; > ; + < "OMEGA" ; > ; + < "varepsilon" ; > ; + < "vartheta" ; > ; + < "varpi" ; > ; + < "varrho" ; > ; + < "varsigma" ; > ; + < "varphi" ; > ; + < "element" ; > ; + < "noelement" ; > ; + < "strictlylessthan" ; > ; + < "strictlygreaterthan" ; > ; + < "notequal" ; > ; + < "identical" ; > ; + < "tendto" ; > ; + < "infinite" ; > ; + < "angle" ; > ; + < "perthousand" ; > ; + < "and" ; > ; + < "or" ; > ; + }; + }; +}; diff --git a/starmath/source/toolbox.cxx b/starmath/source/toolbox.cxx new file mode 100644 index 000000000000..68e15f6079d0 --- /dev/null +++ b/starmath/source/toolbox.cxx @@ -0,0 +1,383 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <rtl/logfile.hxx> +#include <svl/eitem.hxx> +#include <sfx2/app.hxx> +#include <svl/intitem.hxx> +#include <svtools/imgdef.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/imgmgr.hxx> +#include <vcl/wrkwin.hxx> +#include "toolbox.hxx" +#include "starmath.hrc" +#include "toolbox.hrc" +#include "view.hxx" + + +//////////////////////////////////////////////////////////// + +static sal_uInt16 GetImageListRID( sal_uInt16 nCategoryRID ) +{ + sal_uInt16 nRes = 0xFFFF; + switch (nCategoryRID) + { + case RID_UNBINOPS_CAT : nRes = RID_IL_UNBINOPS; break; + case RID_RELATIONS_CAT : nRes = RID_IL_RELATIONS; break; + case RID_SETOPERATIONS_CAT : nRes = RID_IL_SETOPERATIONS; break; + case RID_FUNCTIONS_CAT : nRes = RID_IL_FUNCTIONS; break; + case RID_OPERATORS_CAT : nRes = RID_IL_OPERATORS; break; + case RID_ATTRIBUTES_CAT : nRes = RID_IL_ATTRIBUTES; break; + case RID_BRACKETS_CAT : nRes = RID_IL_BRACKETS; break; + case RID_FORMAT_CAT : nRes = RID_IL_FORMAT; break; + case RID_MISC_CAT : nRes = RID_IL_MISC; break; + default : + OSL_FAIL( "unkown category" ); + } + return nRes; +} + + +static sal_Int16 GetToolBoxCategoriesIndex( sal_uInt16 nCategoryRID ) +{ + sal_Int16 nIdx = -1; + switch (nCategoryRID) + { + case RID_UNBINOPS_CAT : nIdx = 0; break; + case RID_RELATIONS_CAT : nIdx = 1; break; + case RID_SETOPERATIONS_CAT : nIdx = 2; break; + case RID_FUNCTIONS_CAT : nIdx = 3; break; + case RID_OPERATORS_CAT : nIdx = 4; break; + case RID_ATTRIBUTES_CAT : nIdx = 5; break; + case RID_BRACKETS_CAT : nIdx = 6; break; + case RID_FORMAT_CAT : nIdx = 7; break; + case RID_MISC_CAT : nIdx = 8; break; + default: + ; + } + return nIdx; +} + + +static sal_uInt16 GetCategoryRID( sal_uInt16 nResId ) +{ + sal_uInt16 nRes = 0xFFFF; + switch (nResId) + { + case RID_IL_UNBINOPS : nRes = RID_UNBINOPS_CAT; break; + case RID_IL_RELATIONS : nRes = RID_RELATIONS_CAT; break; + case RID_IL_SETOPERATIONS : nRes = RID_SETOPERATIONS_CAT; break; + case RID_IL_FUNCTIONS : nRes = RID_FUNCTIONS_CAT; break; + case RID_IL_OPERATORS : nRes = RID_OPERATORS_CAT; break; + case RID_IL_ATTRIBUTES : nRes = RID_ATTRIBUTES_CAT; break; + case RID_IL_BRACKETS : nRes = RID_BRACKETS_CAT; break; + case RID_IL_FORMAT : nRes = RID_FORMAT_CAT; break; + case RID_IL_MISC : nRes = RID_MISC_CAT; break; + default : + if (nResId != RID_IL_CATALOG) + { +#if OSL_DEBUG_LEVEL > 1 + OSL_FAIL( "unkown category" ); +#endif + } + } + return nRes; +} + + +//////////////////////////////////////////////////////////// + + +SmToolBoxWindow::SmToolBoxWindow(SfxBindings *pTmpBindings, + SfxChildWindow *pChildWindow, + Window *pParent) : + SfxFloatingWindow(pTmpBindings, pChildWindow, pParent, SmResId(RID_TOOLBOXWINDOW)), + aToolBoxCat(this, SmResId(TOOLBOX_CATALOG)), + aToolBoxCat_Delim(this, SmResId( FL_TOOLBOX_CAT_DELIM )) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmToolBoxWindow::SmToolBoxWindow" ); + + // allow for cursor travelling between toolbox and sub-categories + SetStyle( GetStyle() | WB_DIALOGCONTROL ); + + nActiveCategoryRID = USHRT_MAX; + + aToolBoxCat.SetClickHdl(LINK(this, SmToolBoxWindow, CategoryClickHdl)); + + sal_uInt16 i; + for (i = 0; i < NUM_TBX_CATEGORIES; ++i) + { + ToolBox *pBox = new ToolBox(this, SmResId( TOOLBOX_CAT_A + i )); + vToolBoxCategories[i] = pBox; + pBox->SetSelectHdl(LINK(this, SmToolBoxWindow, CmdSelectHdl)); + } + pToolBoxCmd = vToolBoxCategories[0]; + + for (i = 0; i <= NUM_TBX_CATEGORIES; ++i) + aImageLists [i] = 0; + + FreeResource(); +} + +SmToolBoxWindow::~SmToolBoxWindow() +{ + int i; + for (i = 0; i < NUM_TBX_CATEGORIES; ++i) + { + ToolBox *pBox = vToolBoxCategories[i]; + delete pBox; + } + for (i = 0; i < NUM_TBX_CATEGORIES + 1; ++i) + delete aImageLists[i]; +} + + +SmViewShell * SmToolBoxWindow::GetView() +{ + SfxViewShell *pView = GetBindings().GetDispatcher()->GetFrame()->GetViewShell(); + return PTR_CAST(SmViewShell, pView); +} + + +const ImageList * SmToolBoxWindow::GetImageList( sal_uInt16 nResId ) +{ + // creates the image list via its resource id and stores that + // list for later use in the respective array. + + const ImageList *pIL = 0; + + // get index to use + sal_uInt16 nCategoryRID = GetCategoryRID( nResId ); + sal_Int16 nIndex = GetToolBoxCategoriesIndex( nCategoryRID ); + if (nIndex == -1 && (nResId == RID_IL_CATALOG)) + nIndex = NUM_TBX_CATEGORIES; + + if (nIndex >= 0) + { + ImageList **pImgList = aImageLists; + if (!pImgList[ nIndex ]) + pImgList[ nIndex ] = new ImageList( SmResId(nResId) ); + pIL = pImgList[ nIndex ]; + } + + OSL_ENSURE( pIL, "image list not found!" ); + return pIL; +} + + +void SmToolBoxWindow::ApplyImageLists( sal_uInt16 nCategoryRID ) +{ + // set image list for toolbox 'catalog' + const ImageList *pImageList = GetImageList( RID_IL_CATALOG ); + OSL_ENSURE( pImageList, "image list missing" ); + if (pImageList) + aToolBoxCat.SetImageList( *pImageList ); + + // set image list for active (visible) category of 'catalog' + sal_Int16 nIdx = GetToolBoxCategoriesIndex( nCategoryRID ); + sal_uInt16 nResId = GetImageListRID( nCategoryRID ); + pImageList = GetImageList( nResId ); + OSL_ENSURE( pImageList && nIdx >= 0, "image list or index missing" ); + if (pImageList && nIdx >= 0) + vToolBoxCategories[ nIdx ]->SetImageList( *pImageList ); +} + +void SmToolBoxWindow::DataChanged( const DataChangedEvent &rEvt ) +{ + if ( (rEvt.GetType() == DATACHANGED_SETTINGS) && (rEvt.GetFlags() & SETTINGS_STYLE) ) + ApplyImageLists( nActiveCategoryRID ); + + SfxFloatingWindow::DataChanged( rEvt ); +} + +void SmToolBoxWindow::StateChanged( StateChangedType nStateChange ) +{ + static bool bSetPosition = true; + if (STATE_CHANGE_INITSHOW == nStateChange) + { + SetCategory( nActiveCategoryRID == USHRT_MAX ? RID_UNBINOPS_CAT : nActiveCategoryRID ); + + // calculate initial position to be used after creation of the window... + AdjustPosSize( bSetPosition ); + bSetPosition = false; + } + //... otherwise the base class will remember the last position of the window + SfxFloatingWindow::StateChanged( nStateChange ); +} + + +void SmToolBoxWindow::AdjustPosSize( bool bSetPos ) +{ + Size aCatSize( aToolBoxCat.CalcWindowSizePixel( 2 ) ); + Size aCmdSize( pToolBoxCmd->CalcWindowSizePixel( 5 /* see nLines in SetCategory*/ ) ); + OSL_ENSURE( aCatSize.Width() == aCmdSize.Width(), "width mismatch" ); + + // catalog settings + aToolBoxCat.SetPosPixel( Point(0, 3) ); + aToolBoxCat.SetSizePixel( aCatSize ); + // settings for catalog / category delimiter + Point aP( aToolBoxCat_Delim.GetPosPixel() ); + aP.X() = 0; + aToolBoxCat_Delim.SetPosPixel( aP ); + aToolBoxCat_Delim.SetSizePixel( Size( aCatSize.Width(), aToolBoxCat_Delim.GetSizePixel().Height() ) ); + // category settings + aP.Y() += aToolBoxCat_Delim.GetSizePixel().Height(); + for (int i = 0; i < NUM_TBX_CATEGORIES; ++i) + { + vToolBoxCategories[i]->SetPosPixel( aP ); + vToolBoxCategories[i]->SetSizePixel( aCmdSize ); + } + // main window settings + Size aWndSize ( aCatSize.Width(), pToolBoxCmd->GetPosPixel().Y() + pToolBoxCmd->GetSizePixel().Height() + 3); + SetOutputSizePixel( aWndSize ); + + if (bSetPos) + { + SmViewShell *pView = GetView(); + OSL_ENSURE( pView, "view shell missing" ); + Point aPos( 50, 75 ); + if (pView) + { + SmGraphicWindow &rWin = pView->GetGraphicWindow(); + aPos = Point( rWin.OutputToScreenPixel( + Point( rWin.GetSizePixel().Width() - aWndSize.Width(), 0) ) ); + } + if (aPos.X() < 0) + aPos.X() = 0; + if (aPos.Y() < 0) + aPos.Y() = 0; + SetPosPixel( aPos ); + } +} + + +sal_Bool SmToolBoxWindow::Close() +{ + SmViewShell *pViewSh = GetView(); + if (pViewSh) + pViewSh->GetViewFrame()->GetDispatcher()->Execute( + SID_TOOLBOX, SFX_CALLMODE_STANDARD, + new SfxBoolItem(SID_TOOLBOX, false), 0L); + return true; +} + +void SmToolBoxWindow::GetFocus() +{ + // give focus to category toolbox + // (allow for cursor travelling when a category is selected with the mouse) + aToolBoxCat.GrabFocus(); +} + +void SmToolBoxWindow::SetCategory(sal_uInt16 nCategoryRID) +{ + if (nCategoryRID != nActiveCategoryRID) + ApplyImageLists( nCategoryRID ); + + sal_uInt16 nLines; + // check for valid resource id + switch (nCategoryRID) + { + case RID_UNBINOPS_CAT : nLines = 4; break; + case RID_RELATIONS_CAT: nLines = 5; break; + case RID_SETOPERATIONS_CAT: nLines = 5; break; + case RID_FUNCTIONS_CAT: nLines = 5; break; + case RID_OPERATORS_CAT: nLines = 3; break; + case RID_ATTRIBUTES_CAT: nLines = 5; break; + case RID_MISC_CAT: nLines = 4; break; + case RID_BRACKETS_CAT: nLines = 5; break; + case RID_FORMAT_CAT: nLines = 3; break; + default: + // nothing to be done + return; + } + + pToolBoxCmd->Hide(); + + sal_Int16 nIdx = GetToolBoxCategoriesIndex( nCategoryRID ); + OSL_ENSURE( nIdx >= 0, "unkown category" ); + if (nIdx >= 0) + pToolBoxCmd = vToolBoxCategories[nIdx]; + + // calculate actual size of window to use + Size aCatSize( aToolBoxCat.CalcWindowSizePixel( 2 ) ); + Size aCmdSize( pToolBoxCmd->CalcWindowSizePixel( nLines ) ); + OSL_ENSURE( aCatSize.Width() == aCmdSize.Width(), "width mismatch" ); + // main window settings + Size aWndSize ( aCatSize.Width(), pToolBoxCmd->GetPosPixel().Y() + aCmdSize.Height() + 3); + SetOutputSizePixel( aWndSize ); + + if (nActiveCategoryRID) + aToolBoxCat.CheckItem(nActiveCategoryRID, false); + nActiveCategoryRID = nCategoryRID; + aToolBoxCat.CheckItem(nActiveCategoryRID, true); + + pToolBoxCmd->Show(); +} + + +IMPL_LINK( SmToolBoxWindow, CategoryClickHdl, ToolBox*, pToolBox) +{ + int nItemId = pToolBox->GetCurItemId(); + if (nItemId != 0) + SetCategory( sal::static_int_cast< sal_uInt16 >(nItemId) ); + return 0; +} + + +IMPL_LINK( SmToolBoxWindow, CmdSelectHdl, ToolBox*, pToolBox) +{ + SmViewShell *pViewSh = GetView(); + if (pViewSh) + pViewSh->GetViewFrame()->GetDispatcher()->Execute( + SID_INSERTCOMMAND, SFX_CALLMODE_STANDARD, + new SfxInt16Item(SID_INSERTCOMMAND, pToolBox->GetCurItemId()), 0L); + return 0; +} + + +/**************************************************************************/ + +SFX_IMPL_FLOATINGWINDOW(SmToolBoxWrapper, SID_TOOLBOXWINDOW); + +SmToolBoxWrapper::SmToolBoxWrapper(Window *pParentWindow, + sal_uInt16 nId, SfxBindings* pBindings, + SfxChildWinInfo *pInfo) : + SfxChildWindow(pParentWindow, nId) +{ + eChildAlignment = SFX_ALIGN_NOALIGNMENT; + + pWindow = new SmToolBoxWindow(pBindings, this, pParentWindow); + ((SfxFloatingWindow *)pWindow)->Initialize(pInfo); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/toolbox.hrc b/starmath/source/toolbox.hrc new file mode 100755 index 000000000000..29adff303a3e --- /dev/null +++ b/starmath/source/toolbox.hrc @@ -0,0 +1,46 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _TOOLBOX_HRC_ +#define _TOOLBOX_HRC_ + +#define FL_TOOLBOX_CAT_DELIM 1 +#define TOOLBOX_CATALOG 10 +#define TOOLBOX_CAT_A 11 +#define TOOLBOX_CAT_B 12 +#define TOOLBOX_CAT_C 13 +#define TOOLBOX_CAT_D 14 +#define TOOLBOX_CAT_E 15 +#define TOOLBOX_CAT_F 16 +#define TOOLBOX_CAT_G 17 +#define TOOLBOX_CAT_H 18 +#define TOOLBOX_CAT_I 19 + +#define NUM_TBX_CATEGORIES (TOOLBOX_CAT_I - TOOLBOX_CAT_A + 1) + +#endif + diff --git a/starmath/source/toolbox.src b/starmath/source/toolbox.src new file mode 100644 index 000000000000..07e728f1e6cb --- /dev/null +++ b/starmath/source/toolbox.src @@ -0,0 +1,1777 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include <sfx2/sfx.hrc> +#include <svx/globlmn.hrc> +#include "starmath.hrc" +#include "toolbox.hrc" + +#define IMAGE_STDBTN_COLOR Color { Red = 0xff00; Green = 0x0000; Blue = 0xff00; } +#define IMAGE_STDBTN_COLOR_HC IMAGE_STDBTN_COLOR + + +FloatingWindow RID_TOOLBOXWINDOW +{ + HelpId = HID_SMA_OPERATOR_WIN ; + Border = TRUE ; + Moveable = TRUE ; + Closeable = TRUE ; + Hide = TRUE ; + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 0 , 0 ) ; // to be calculated programmatically + Text [ en-US ] = "Elements" ; + + ToolBox TOOLBOX_CATALOG + { + // main menu of selection-window + HelpId = HID_SMA_SELECTION_TBX ; + Pos = MAP_APPFONT ( 0 , 0 ) ; + Size = MAP_APPFONT ( 65 , 38 ) ; + SVLook = TRUE ; + LineCount = 2 ; + ItemList = + { + ToolBoxItem + { + Identifier = RID_UNBINOPS_CAT ; + HelpId = HID_SMA_UNBINOPS_CAT ; + Text [ en-US ] = "Unary/Binary Operators" ; + }; + ToolBoxItem + { + Identifier = RID_RELATIONS_CAT ; + HelpId = HID_SMA_RELATIONS_CAT ; + Text [ en-US ] = "Relations" ; + }; + ToolBoxItem + { + Identifier = RID_SETOPERATIONS_CAT ; + HelpId = HID_SMA_SETOPERATIONS_CAT ; + Text [ en-US ] = "Set Operations" ; + }; + ToolBoxItem + { + Identifier = RID_FUNCTIONS_CAT ; + HelpId = HID_SMA_FUNCTIONS_CAT ; + Text [ en-US ] = "Functions" ; + }; + ToolBoxItem + { + Identifier = RID_OPERATORS_CAT ; + HelpId = HID_SMA_OPERATORS_CAT ; + Text [ en-US ] = "Operators" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_ATTRIBUTES_CAT ; + HelpId = HID_SMA_ATTRIBUTES_CAT ; + Text [ en-US ] = "Attributes" ; + }; + ToolBoxItem + { + Identifier = RID_MISC_CAT ; + HelpId = HID_SMA_MISC_CAT ; + Text [ en-US ] = "Others"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Identifier = RID_BRACKETS_CAT ; + HelpId = HID_SMA_BRACKETS_CAT ; + Text [ en-US ] = "Brackets" ; + }; + ToolBoxItem + { + Identifier = RID_FORMAT_CAT ; + HelpId = HID_SMA_FORMAT_CAT ; + Text [ en-US ] = "Formats" ; + }; + }; + }; + + FixedLine FL_TOOLBOX_CAT_DELIM + { + Pos = MAP_APPFONT ( 0 , 44 ) ; + Size = MAP_APPFONT ( 65 , 8 ) ; + }; + + ToolBox TOOLBOX_CAT_A + { + // unary/binary operators + HelpId = HID_SMA_UNBINOPS_TBX ; + Pos = MAP_APPFONT ( 0 , 45 ) ; + Size = MAP_APPFONT ( 65 , 95 ) ; + SVLook = TRUE ; + Hide = TRUE ; + LineCount = 4 ; + + ItemList = + { + ToolBoxItem + { + Identifier = RID_PLUSX ; + HelpId = HID_SMA_PLUSX ; + Text [ en-US ] = "+ Sign" ; + }; + ToolBoxItem + { + Identifier = RID_MINUSX ; + HelpId = HID_SMA_MINUSX ; + Text [ en-US ] = "- Sign" ; + }; + ToolBoxItem + { + Identifier = RID_PLUSMINUSX ; + HelpId = HID_SMA_PLUSMINUSX ; + Text [ en-US ] = "+- Sign" ; + }; + ToolBoxItem + { + Identifier = RID_MINUSPLUSX ; + HelpId = HID_SMA_MINUSPLUSX ; + Text [ en-US ] = "-+ Sign" ; + }; + ToolBoxItem + { + Identifier = RID_NEGX ; + HelpId = HID_SMA_NEGX ; + Text [ en-US ] = "Boolean NOT" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XPLUSY ; + HelpId = HID_SMA_XPLUSY ; + Text [ en-US ] = "Addition +" ; + }; + ToolBoxItem + { + Identifier = RID_XCDOTY ; + HelpId = HID_SMA_XCDOTY ; + Text [ en-US ] = "Multiplication (Dot )" ; + }; + ToolBoxItem + { + Identifier = RID_XTIMESY ; + HelpId = HID_SMA_XTIMESY ; + Text [ en-US ] = "Multiplication (x)" ; + }; + ToolBoxItem + { + Identifier = RID_XSYMTIMESY ; + HelpId = HID_SMA_XSYMTIMESY ; + Text [ en-US ] = "Multiplication (*)" ; + }; + ToolBoxItem + { + Identifier = RID_XANDY ; + HelpId = HID_SMA_XANDY ; + Text [ en-US ] = "Boolean AND" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XMINUSY ; + HelpId = HID_SMA_XMINUSY ; + Text [ en-US ] = "Subtraction -" ; + }; + ToolBoxItem + { + Identifier = RID_XOVERY ; + HelpId = HID_SMA_XOVERY ; + Text [ en-US ] = "Division (Fraction)" ; + }; + ToolBoxItem + { + Identifier = RID_XDIVY ; + HelpId = HID_SMA_XDIVY ; + Text [ en-US ] = "Division (÷)" ; + }; + ToolBoxItem + { + Identifier = RID_XSYMDIVIDEY ; + HelpId = HID_SMA_XSYMDIVIDEY ; + Text [ en-US ] = "Division (Slash)" ; + }; + ToolBoxItem + { + Identifier = RID_XORY ; + HelpId = HID_SMA_XORY ; + Text [ en-US ] = "Boolean OR" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XCIRCY ; + HelpId = HID_SMA_XCIRCY ; + Text [ en-US ] = "Concatenate"; + }; + }; + }; + + ToolBox TOOLBOX_CAT_B + { + // relations + HelpId = HID_SMA_RELATIONS_TBX ; + Pos = MAP_APPFONT ( 0 , 45 ) ; + Size = MAP_APPFONT ( 65 , 95 ) ; + SVLook = TRUE ; + Hide = TRUE ; + LineCount = 5 ; + ItemList = + { + ToolBoxItem + { + Identifier = RID_XEQY ; + HelpId = HID_SMA_XEQY ; + Text [ en-US ] = "Is Equal" ; + }; + ToolBoxItem + { + Identifier = RID_XNEQY ; + HelpId = HID_SMA_XNEQY ; + Text [ en-US ] = "Is Not Equal" ; + }; + ToolBoxItem + { + Identifier = RID_XAPPROXY ; + HelpId = HID_SMA_XAPPROXY ; + Text [ en-US ] = "Is Approximately Equal" ; + }; + ToolBoxItem + { + Identifier = RID_XDIVIDESY ; + HelpId = HID_SMA_XDIVIDESY ; + Text [ en-US ] = "Divides"; + }; + ToolBoxItem + { + Identifier = RID_XNDIVIDESY ; + HelpId = HID_SMA_XNDIVIDESY ; + Text [ en-US ] = "Does Not Divide"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XLTY ; + HelpId = HID_SMA_XLTY ; + Text [ en-US ] = "Is Less Than" ; + }; + ToolBoxItem + { + Identifier = RID_XGTY ; + HelpId = HID_SMA_XGTY ; + Text [ en-US ] = "Is Greater Than" ; + }; + ToolBoxItem + { + Identifier = RID_XSIMEQY ; + HelpId = HID_SMA_XSIMEQY ; + /* ### ACHTUNG: Neuer Text in Resource? ist �hnlich oder gleich : ist �hnlich oder glech */ + Text [ en-US ] = "Is Similar Or Equal" ; + }; + ToolBoxItem + { + Identifier = RID_XPARALLELY ; + HelpId = HID_SMA_XPARALLELY ; + Text [ en-US ] = "Is Parallel To" ; + }; + ToolBoxItem + { + Identifier = RID_XORTHOY ; + HelpId = HID_SMA_XORTHOY ; + Text [ en-US ] = "Is Orthogonal To" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XLESLANTY ; + HelpId = HID_SMA_XLESLANTY ; + Text [ en-US ] = "Is Less Than Or Equal To" ; + }; + ToolBoxItem + { + Identifier = RID_XGESLANTY ; + HelpId = HID_SMA_XGESLANTY ; + Text [ en-US ] = "Is Greater Than Or Equal To" ; + }; + ToolBoxItem + { + Identifier = RID_XSIMY ; + HelpId = HID_SMA_XSIMY ; + Text [ en-US ] = "Is Similar To" ; + }; + ToolBoxItem + { + Identifier = RID_XEQUIVY ; + HelpId = HID_SMA_XEQUIVY ; + Text [ en-US ] = "Is Congruent To" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XLEY ; + HelpId = HID_SMA_XLEY ; + Text [ en-US ] = "Is Less Than Or Equal To" ; + }; + ToolBoxItem + { + Identifier = RID_XGEY ; + HelpId = HID_SMA_XGEY ; + Text [ en-US ] = "Is Greater Than Or Equal To" ; + }; + ToolBoxItem + { + Identifier = RID_XPROPY ; + HelpId = HID_SMA_XPROPY ; + Text [ en-US ] = "Is Proportional To" ; + }; + ToolBoxItem + { + Identifier = RID_XTOWARDY ; + HelpId = HID_SMA_XTOWARDY ; + Text [ en-US ] = "Toward" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_DLARROW ; + HelpId = HID_SMA_DLARROW ; + Text [ en-US ] = "Double Arrow Left"; + }; + ToolBoxItem + { + Identifier = RID_DLRARROW ; + HelpId = HID_SMA_DLRARROW ; + Text [ en-US ] = "Double Arrow Left And Right"; + }; + ToolBoxItem + { + Identifier = RID_DRARROW ; + HelpId = HID_SMA_DRARROW ; + Text [ en-US ] = "Double Arrow Right"; + }; + }; + }; + + ToolBox TOOLBOX_CAT_C + { + // set operations + HelpId = HID_SMA_SETOPERATIONS_TBX ; + Pos = MAP_APPFONT ( 0 , 45 ) ; + Size = MAP_APPFONT ( 65 , 95 ) ; + SVLook = TRUE ; + Hide = TRUE ; + LineCount = 5 ; + ItemList = + { + ToolBoxItem + { + Identifier = RID_XINY ; + HelpId = HID_SMA_XINY ; + Text [ en-US ] = "Is In" ; + }; + ToolBoxItem + { + Identifier = RID_XNOTINY ; + HelpId = HID_SMA_XNOTINY ; + Text [ en-US ] = "Is Not In" ; + }; + ToolBoxItem + { + Identifier = RID_XOWNSY ; + HelpId = HID_SMA_XOWNSY ; + Text [ en-US ] = "Owns" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Identifier = RID_EMPTYSET ; + HelpId = HID_SMA_EMPTYSET ; + Text [ en-US ] = "Empty Set"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XINTERSECTIONY ; + HelpId = HID_SMA_XINTERSECTIONY ; + Text [ en-US ] = "Intersection" ; + }; + ToolBoxItem + { + Identifier = RID_XUNIONY ; + HelpId = HID_SMA_XUNIONY ; + Text [ en-US ] = "Union" ; + }; + ToolBoxItem + { + Identifier = RID_XSETMINUSY ; + HelpId = HID_SMA_XSETMINUSY ; + Text [ en-US ] = "Difference" ; + }; + ToolBoxItem + { + Identifier = RID_XSLASHY ; + HelpId = HID_SMA_XSLASHY ; + Text [ en-US ] = "Quotient Set" ; + }; + ToolBoxItem + { + Identifier = RID_ALEPH ; + HelpId = HID_SMA_ALEPH ; + Text [ en-US ] = "Aleph"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XSUBSETY ; + HelpId = HID_SMA_XSUBSETY ; + Text [ en-US ] = "Subset" ; + }; + ToolBoxItem + { + Identifier = RID_XSUBSETEQY ; + HelpId = HID_SMA_XSUBSETEQY ; + Text [ en-US ] = "Subset Or Equal To" ; + }; + ToolBoxItem + { + Identifier = RID_XSUPSETY ; + HelpId = HID_SMA_XSUPSETY ; + Text [ en-US ] = "Superset" ; + }; + ToolBoxItem + { + Identifier = RID_XSUPSETEQY ; + HelpId = HID_SMA_XSUPSETEQY ; + Text [ en-US ] = "Superset Or Equal To" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XNSUBSETY ; + HelpId = HID_SMA_XNSUBSETY ; + Text [ en-US ] = "Not Subset" ; + }; + ToolBoxItem + { + Identifier = RID_XNSUBSETEQY ; + HelpId = HID_SMA_XNSUBSETEQY ; + Text [ en-US ] = "Not Subset Or Equal" ; + }; + ToolBoxItem + { + Identifier = RID_XNSUPSETY ; + HelpId = HID_SMA_XNSUPSETY ; + Text [ en-US ] = "Not Superset" ; + }; + ToolBoxItem + { + Identifier = RID_XNSUPSETEQY ; + HelpId = HID_SMA_XNSUPSETEQY ; + Text [ en-US ] = "Not Superset Or Equal" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_SETN ; + HelpId = HID_SMA_SETN ; + Text [ en-US ] = "Natural Numbers Set"; + }; + ToolBoxItem + { + Identifier = RID_SETZ ; + HelpId = HID_SMA_SETZ ; + Text [ en-US ] = "Integers Set"; + }; + ToolBoxItem + { + Identifier = RID_SETQ ; + HelpId = HID_SMA_SETQ ; + Text [ en-US ] = "Set of Rational Numbers"; + }; + ToolBoxItem + { + Identifier = RID_SETR ; + HelpId = HID_SMA_SETR ; + Text [ en-US ] = "Real Numbers Set"; + }; + ToolBoxItem + { + Identifier = RID_SETC ; + HelpId = HID_SMA_SETC ; + Text [ en-US ] = "Complex Numbers Set"; + }; + }; + }; + + ToolBox TOOLBOX_CAT_D + { + // functions + HelpId = HID_SMA_FUNCTIONS_TBX ; + Pos = MAP_APPFONT ( 0 , 45 ) ; + Size = MAP_APPFONT ( 65 , 95 ) ; + SVLook = TRUE ; + Hide = TRUE ; + LineCount = 5 ; + ItemList = + { + ToolBoxItem + { + Identifier = RID_EX ; + HelpId = HID_SMA_EX ; + Text [ en-US ] = "Exponential Function" ; + }; + ToolBoxItem + { + Identifier = RID_LNX ; + HelpId = HID_SMA_LNX ; + Text [ en-US ] = "Natural Logarithm" ; + }; + ToolBoxItem + { + Identifier = RID_EXPX ; + HelpId = HID_SMA_EXPX ; + Text [ en-US ] = "Exponential Function" ; + }; + ToolBoxItem + { + Identifier = RID_LOGX ; + HelpId = HID_SMA_LOGX ; + Text [ en-US ] = "Logarithm" ; + }; + ToolBoxItem + { + Identifier = RID_RSUPX ; + HelpId = HID_SMA_RSUPX ; + Text [ en-US ] = "Power"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_SINX ; + HelpId = HID_SMA_SINX ; + Text [ en-US ] = "Sine" ; + }; + ToolBoxItem + { + Identifier = RID_COSX ; + HelpId = HID_SMA_COSX ; + Text [ en-US ] = "Cosine" ; + }; + ToolBoxItem + { + Identifier = RID_TANX ; + HelpId = HID_SMA_TANX ; + Text [ en-US ] = "Tangent" ; + }; + ToolBoxItem + { + Identifier = RID_COTX ; + HelpId = HID_SMA_COTX ; + Text [ en-US ] = "Cotangent" ; + }; + ToolBoxItem + { + Identifier = RID_SQRTX ; + HelpId = HID_SMA_SQRTX ; + Text [ en-US ] = "Square Root" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_ARCSINX ; + HelpId = HID_SMA_ARCSINX ; + Text [ en-US ] = "Arcsine" ; + }; + ToolBoxItem + { + Identifier = RID_ARCCOSX ; + HelpId = HID_SMA_ARCCOSX ; + Text [ en-US ] = "Arccosine" ; + }; + ToolBoxItem + { + Identifier = RID_ARCTANX ; + HelpId = HID_SMA_ARCTANX ; + Text [ en-US ] = "Arctangent" ; + }; + ToolBoxItem + { + Identifier = RID_ARCCOTX ; + HelpId = HID_SMA_ARCCOTX ; + Text [ en-US ] = "Arccotangent" ; + }; + ToolBoxItem + { + Identifier = RID_NROOTXY ; + HelpId = HID_SMA_NROOTXY ; + Text [ en-US ] = "N-th Root" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_SINHX ; + HelpId = HID_SMA_SINHX ; + Text [ en-US ] = "Hyperbolic Sine" ; + }; + ToolBoxItem + { + Identifier = RID_COSHX ; + HelpId = HID_SMA_COSHX ; + Text [ en-US ] = "Hyperbolic Cosine" ; + }; + ToolBoxItem + { + Identifier = RID_TANHX ; + HelpId = HID_SMA_TANHX ; + Text [ en-US ] = "Hyperbolic Tangent" ; + }; + ToolBoxItem + { + Identifier = RID_COTHX ; + HelpId = HID_SMA_COTHX ; + Text [ en-US ] = "Hyperbolic Cotangent" ; + }; + ToolBoxItem + { + Identifier = RID_ABSX ; + HelpId = HID_SMA_ABSX ; + Text [ en-US ] = "Absolute Value" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_ARSINHX ; + HelpId = HID_SMA_ARSINHX ; + Text [ en-US ] = "Area Hyperbolic Sine" ; + }; + ToolBoxItem + { + Identifier = RID_ARCOSHX ; + HelpId = HID_SMA_ARCOSHX ; + Text [ en-US ] = "Area Hyperbolic Cosine" ; + }; + ToolBoxItem + { + Identifier = RID_ARTANHX ; + HelpId = HID_SMA_ARTANHX ; + Text [ en-US ] = "Area Hyperbolic Tangent" ; + }; + ToolBoxItem + { + Identifier = RID_ARCOTHX ; + HelpId = HID_SMA_ARCOTHX ; + Text [ en-US ] = "Area Hyperbolic Cotangent" ; + }; + ToolBoxItem + { + Identifier = RID_FACTX ; + HelpId = HID_SMA_FACTX ; + Text [ en-US ] = "Factorial" ; + }; + }; + }; + + ToolBox TOOLBOX_CAT_E + { + // operators + HelpId = HID_SMA_OPERATORS_TBX ; + Pos = MAP_APPFONT ( 0 , 45 ) ; + Size = MAP_APPFONT ( 65 , 95 ) ; + SVLook = TRUE ; + Hide = TRUE ; + LineCount = 3 ; + ItemList = + { + ToolBoxItem + { + Identifier = RID_LIMX ; + HelpId = HID_SMA_LIMX ; + Text [ en-US ] = "Limes" ; + }; + ToolBoxItem + { + Identifier = RID_SUMX ; + HelpId = HID_SMA_SUMX ; + Text [ en-US ] = "Sum" ; + }; + ToolBoxItem + { + Identifier = RID_PRODX ; + HelpId = HID_SMA_PRODX ; + Text [ en-US ] = "Product" ; + }; + ToolBoxItem + { + Identifier = RID_COPRODX ; + HelpId = HID_SMA_COPRODX ; + Text [ en-US ] = "Coproduct" ; + }; + ToolBoxItem + { + Identifier = RID_FROMXTOY ; + HelpId = HID_SMA_FROMXTOY ; + Text [ en-US ] = "Upper And Lower Limit" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_INTX ; + HelpId = HID_SMA_INTX ; + Text [ en-US ] = "Integral" ; + }; + ToolBoxItem + { + Identifier = RID_IINTX ; + HelpId = HID_SMA_IINTX ; + Text [ en-US ] = "Double Integral" ; + }; + ToolBoxItem + { + Identifier = RID_IIINTX ; + HelpId = HID_SMA_IIINTX ; + Text [ en-US ] = "Triple Integral" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Identifier = RID_FROMX ; + HelpId = HID_SMA_FROMX ; + Text [ en-US ] = "Lower Limit" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_LINTX ; + HelpId = HID_SMA_LINTX ; + Text [ en-US ] = "Curve Integral" ; + }; + ToolBoxItem + { + Identifier = RID_LLINTX ; + HelpId = HID_SMA_LLINTX ; + Text [ en-US ] = "Double Curve Integral" ; + }; + ToolBoxItem + { + Identifier = RID_LLLINTX ; + HelpId = HID_SMA_LLLINTX ; + Text [ en-US ] = "Triple Curve Integral" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Identifier = RID_TOX ; + HelpId = HID_SMA_TOX ; + Text [ en-US ] = "Upper Limit" ; + }; + }; + }; + + ToolBox TOOLBOX_CAT_F + { + // attributs + HelpId = HID_SMA_ATTRIBUTES_TBX ; + Pos = MAP_APPFONT ( 0 , 45 ) ; + Size = MAP_APPFONT ( 65 , 95 ) ; + SVLook = TRUE ; + Hide = TRUE ; + LineCount = 5 ; + ItemList = + { + ToolBoxItem + { + Identifier = RID_ACUTEX ; + HelpId = HID_SMA_ACUTEX ; + Text [ en-US ] = "Acute Accent"; + }; + ToolBoxItem + { + Identifier = RID_GRAVEX ; + HelpId = HID_SMA_GRAVEX ; + Text [ en-US ] = "Grave Accent"; + }; + ToolBoxItem + { + Identifier = RID_CHECKX ; + HelpId = HID_SMA_CHECKX ; + Text [ en-US ] = "Reverse Circumflex" ; + }; + ToolBoxItem + { + Identifier = RID_BREVEX ; + HelpId = HID_SMA_BREVEX ; + Text [ en-US ] = "Breve" ; + }; + ToolBoxItem + { + Identifier = RID_CIRCLEX ; + HelpId = HID_SMA_CIRCLEX ; + Text [ en-US ] = "Circle" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_VECX ; + HelpId = HID_SMA_VECX ; + Text [ en-US ] = "Vector Arrow" ; + }; + ToolBoxItem + { + Identifier = RID_TILDEX ; + HelpId = HID_SMA_TILDEX ; + Text [ en-US ] = "Tilde" ; + }; + ToolBoxItem + { + Identifier = RID_HATX ; + HelpId = HID_SMA_HATX ; + Text [ en-US ] = "Circumflex" ; + }; + ToolBoxItem + { + Identifier = RID_BARX ; + HelpId = HID_SMA_BARX ; + Text [ en-US ] = "Line Above" ; + }; + ToolBoxItem + { + Identifier = RID_DOTX ; + HelpId = HID_SMA_DOTX ; + Text [ en-US ] = "Dot" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_WIDEVECX ; + HelpId = HID_SMA_WIDEVECX ; + Text [ en-US ] = "Large Vector Arrow"; + }; + ToolBoxItem + { + Identifier = RID_WIDETILDEX ; + HelpId = HID_SMA_WIDETILDEX ; + Text [ en-US ] = "Large Tilde"; + }; + ToolBoxItem + { + Identifier = RID_WIDEHATX ; + HelpId = HID_SMA_WIDEHATX ; + Text [ en-US ] = "Large Circumflex"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Identifier = RID_DDOTX ; + HelpId = HID_SMA_DDOTX ; + Text [ en-US ] = "Double Dot" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_OVERLINEX ; + HelpId = HID_SMA_OVERLINEX ; + Text [ en-US ] = "Line Over" ; + }; + ToolBoxItem + { + Identifier = RID_UNDERLINEX ; + HelpId = HID_SMA_UNDERLINEX ; + Text [ en-US ] = "Line Below" ; + }; + ToolBoxItem + { + Identifier = RID_OVERSTRIKEX ; + HelpId = HID_SMA_OVERSTRIKEX ; + Text [ en-US ] = "Line Through" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Identifier = RID_DDDOTX ; + HelpId = HID_SMA_DDDOTX ; + Text [ en-US ] = "Triple Dot" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_PHANTOMX ; + HelpId = HID_SMA_PHANTOMX ; + Text [ en-US ] = "Transparent" ; + }; + ToolBoxItem + { + Identifier = RID_BOLDX ; + HelpId = HID_SMA_BOLDX ; + Text [ en-US ] = "Bold Font" ; + }; + ToolBoxItem + { + Identifier = RID_ITALX ; + HelpId = HID_SMA_ITALX ; + Text [ en-US ] = "Italic Font" ; + }; + ToolBoxItem + { + Identifier = RID_SIZEXY ; + HelpId = HID_SMA_SIZEXY ; + Text [ en-US ] = "Resize" ; + }; + ToolBoxItem + { + Identifier = RID_FONTXY ; + HelpId = HID_SMA_FONTXY ; + Text [ en-US ] = "Change Font" ; + }; + }; + }; + + ToolBox TOOLBOX_CAT_G + { + // parentheses + HelpId = HID_SMA_BRACKETS_TBX ; + Pos = MAP_APPFONT ( 0 , 45 ) ; + Size = MAP_APPFONT ( 65 , 95 ) ; + SVLook = TRUE ; + Hide = TRUE ; + LineCount = 5 ; + ItemList = + { + ToolBoxItem + { + Identifier = RID_LRPARENTX ; + HelpId = HID_SMA_LRPARENTX ; + Text [ en-US ] = "Round Brackets" ; + }; + ToolBoxItem + { + Identifier = RID_LRBRACKETX ; + HelpId = HID_SMA_LRBRACKETX ; + Text [ en-US ] = "Square Brackets" ; + }; + ToolBoxItem + { + Identifier = RID_LRDBRACKETX ; + HelpId = HID_SMA_LRDBRACKETX ; + Text [ en-US ] = "Double Square Brackets"; + }; + ToolBoxItem + { + Identifier = RID_LRLINEX ; + HelpId = HID_SMA_LRLINEX ; + Text [ en-US ] = "Single Lines" ; + }; + ToolBoxItem + { + Identifier = RID_LRDLINEX ; + HelpId = HID_SMA_LRDLINEX ; + Text [ en-US ] = "Double Lines" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_LRBRACEX ; + HelpId = HID_SMA_LRBRACEX ; + Text [ en-US ] = "Braces" ; + }; + ToolBoxItem + { + Identifier = RID_LRANGLEX ; + HelpId = HID_SMA_LRANGLEX ; + Text [ en-US ] = "Angle Brackets" ; + }; + ToolBoxItem + { + Identifier = RID_LMRANGLEXY ; + HelpId = HID_SMA_LMRANGLEXY ; + Text [ en-US ] = "Operator Brackets"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Identifier = RID_LRGROUPX ; + HelpId = HID_SMA_LRGROUPX ; + Text [ en-US ] = "Group Brackets" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_SLRPARENTX ; + HelpId = HID_SMA_SLRPARENTX ; + Text [ en-US ] = "Round Brackets (Scalable)" ; + }; + ToolBoxItem + { + Identifier = RID_SLRBRACKETX ; + HelpId = HID_SMA_SLRBRACKETX ; + Text [ en-US ] = "Square Brackets (Scalable)" ; + }; + ToolBoxItem + { + Identifier = RID_SLRDBRACKETX ; + HelpId = HID_SMA_SLRDBRACKETX ; + Text [ en-US ] = "Double Square Brackets (Scalable)"; + }; + ToolBoxItem + { + Identifier = RID_SLRLINEX ; + HelpId = HID_SMA_SLRLINEX ; + Text [ en-US ] = "Single Lines (Scalable)" ; + }; + ToolBoxItem + { + Identifier = RID_SLRDLINEX ; + HelpId = HID_SMA_SLRDLINEX ; + Text [ en-US ] = "Double Lines (Scalable)" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_SLRBRACEX ; + HelpId = HID_SMA_SLRBRACEX ; + Text [ en-US ] = "Braces (Scalable)" ; + }; + ToolBoxItem + { + Identifier = RID_SLRANGLEX ; + HelpId = HID_SMA_SLRANGLEX ; + Text [ en-US ] = "Angle Brackets (Scalable)" ; + }; + ToolBoxItem + { + Identifier = RID_SLMRANGLEXY ; + HelpId = HID_SMA_SLMRANGLEXY ; + Text [ en-US ] = "Operator Brackets (Scalable)"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_XOVERBRACEY ; + HelpId = HID_SMA_XOVERBRACEY ; + Text [ en-US ] = "Braces Top (Scalable)"; + }; + ToolBoxItem + { + Identifier = RID_XUNDERBRACEY ; + HelpId = HID_SMA_XUNDERBRACEY ; + Text [ en-US ] = "Braces Bottom (Scalable)"; + }; + }; + }; + + ToolBox TOOLBOX_CAT_H + { + // format + HelpId = HID_SMA_FORMAT_TBX ; + Pos = MAP_APPFONT ( 0 , 45 ) ; + Size = MAP_APPFONT ( 65 , 95 ) ; + SVLook = TRUE ; + Hide = TRUE ; + LineCount = 3 ; + ItemList = + { + ToolBoxItem + { + Identifier = RID_LSUPX ; + HelpId = HID_SMA_LSUPX ; + Text [ en-US ] = "Superscript Left" ; + }; + ToolBoxItem + { + Identifier = RID_CSUPX ; + HelpId = HID_SMA_CSUPX ; + Text [ en-US ] = "Superscript Top"; + }; + ToolBoxItem + { + Identifier = RID_RSUPX ; + HelpId = HID_SMA_RSUPX ; + Text [ en-US ] = "Superscript Right" ; + }; + ToolBoxItem + { + Identifier = RID_BINOMXY ; + HelpId = HID_SMA_BINOMXY ; + Text [ en-US ] = "Vertical Stack (2 Elements)" ; + }; + ToolBoxItem + { + Identifier = RID_NEWLINE ; + HelpId = HID_SMA_NEWLINE ; + Text [ en-US ] = "New Line" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_LSUBX ; + HelpId = HID_SMA_LSUBX ; + Text [ en-US ] = "Subscript Left" ; + }; + ToolBoxItem + { + Identifier = RID_CSUBX ; + HelpId = HID_SMA_CSUBX ; + Text [ en-US ] = "Subscript Bottom"; + }; + ToolBoxItem + { + Identifier = RID_RSUBX ; + HelpId = HID_SMA_RSUBX ; + Text [ en-US ] = "Subscript Right" ; + }; + ToolBoxItem + { + Identifier = RID_STACK ; + HelpId = HID_SMA_STACK ; + Text [ en-US ] = "Vertical Stack" ; + }; + ToolBoxItem + { + Identifier = RID_SBLANK ; + HelpId = HID_SMA_SBLANK ; + Text [ en-US ] = "Small Gap" ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_ALIGNLX ; + HelpId = HID_SMA_ALIGNLX ; + Text [ en-US ] = "Align Left" ; + }; + ToolBoxItem + { + Identifier = RID_ALIGNCX ; + HelpId = HID_SMA_ALIGNCX ; + Text [ en-US ] = "Align Center" ; + }; + ToolBoxItem + { + Identifier = RID_ALIGNRX ; + HelpId = HID_SMA_ALIGNRX ; + Text [ en-US ] = "Align Right" ; + }; + ToolBoxItem + { + Identifier = RID_MATRIX ; + HelpId = HID_SMA_MATRIX ; + Text [ en-US ] = "Matrix Stack" ; + }; + ToolBoxItem + { + Identifier = RID_BLANK ; + HelpId = HID_SMA_BLANK ; + Text [ en-US ] = "Gap" ; + }; + }; + }; + + ToolBox TOOLBOX_CAT_I + { + // misc + HelpId = HID_SMA_FORMAT_TBX ; + Pos = MAP_APPFONT ( 0 , 45 ) ; + Size = MAP_APPFONT ( 65 , 95 ) ; + SVLook = TRUE ; + Hide = TRUE ; + LineCount = 4 ; + ItemList = + { + ToolBoxItem + { + Identifier = RID_INFINITY ; + HelpId = HID_SMA_INFINITY ; + Text [ en-US ] = "infinite"; + }; + ToolBoxItem + { + Identifier = RID_PARTIAL ; + HelpId = HID_SMA_PARTIAL ; + Text [ en-US ] = "Partial"; + }; + ToolBoxItem + { + Identifier = RID_NABLA ; + HelpId = HID_SMA_NABLA ; + Text [ en-US ] = "Nabla"; + }; + ToolBoxItem + { + Identifier = RID_EXISTS ; + HelpId = HID_SMA_EXISTS ; + Text [ en-US ] = "There Exists"; + }; + ToolBoxItem + { + Identifier = RID_FORALL ; + HelpId = HID_SMA_FORALL ; + Text [ en-US ] = "For All"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_HBAR ; + HelpId = HID_SMA_HBAR ; + Text [ en-US ] = "h Bar"; + }; + ToolBoxItem + { + Identifier = RID_LAMBDABAR ; + HelpId = HID_SMA_LAMBDABAR ; + Text [ en-US ] = "Lambda Bar"; + }; + ToolBoxItem + { + Identifier = RID_RE ; + HelpId = HID_SMA_RE ; + Text [ en-US ] = "Real Part"; + }; + ToolBoxItem + { + Identifier = RID_IM ; + HelpId = HID_SMA_IM ; + Text [ en-US ] = "Imaginary Part"; + }; + ToolBoxItem + { + Identifier = RID_WP ; + HelpId = HID_SMA_WP ; + Text [ en-US ] = "Weierstrass p"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_LEFTARROW ; + HelpId = HID_SMA_LEFTARROW ; + Text [ en-US ] = "Left Arrow"; + }; + ToolBoxItem + { + Identifier = RID_RIGHTARROW ; + HelpId = HID_SMA_RIGHTARROW ; + Text [ en-US ] = "Right Arrow"; + }; + ToolBoxItem + { + Identifier = RID_UPARROW ; + HelpId = HID_SMA_UPARROW ; + Text [ en-US ] = "Up Arrow"; + }; + ToolBoxItem + { + Identifier = RID_DOWNARROW ; + HelpId = HID_SMA_DOWNARROW ; + Text [ en-US ] = "Down Arrow"; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_SPACE ; + }; + ToolBoxItem + { + Type = TOOLBOXITEM_BREAK ; + }; + ToolBoxItem + { + Identifier = RID_DOTSLOW ; + HelpId = HID_SMA_DOTSLOW ; + Text [ en-US ] = "Dots At Bottom"; + }; + ToolBoxItem + { + Identifier = RID_DOTSAXIS ; + HelpId = HID_SMA_DOTSAXIS ; + Text [ en-US ] = "Dots In Middle"; + }; + ToolBoxItem + { + Identifier = RID_DOTSVERT ; + HelpId = HID_SMA_DOTSVERT ; + Text [ en-US ] = "Dots Vertically"; + }; + ToolBoxItem + { + Identifier = RID_DOTSUP ; + HelpId = HID_SMA_DOTSUP ; + Text [ en-US ] = "Dots To Top"; + }; + ToolBoxItem + { + Identifier = RID_DOTSDOWN ; + HelpId = HID_SMA_DOTSDOWN ; + Text [ en-US ] = "Dots to Bottom"; + }; + }; + }; +}; + + + +#define UNBINOPS_IDLIST \ + IdList = \ + { \ + RID_PLUSX ; \ + RID_MINUSX ; \ + RID_PLUSMINUSX ; \ + RID_MINUSPLUSX ; \ + RID_XPLUSY ; \ + RID_XCDOTY ; \ + RID_XTIMESY ; \ + RID_XSYMTIMESY ; \ + RID_XMINUSY ; \ + RID_XOVERY ; \ + RID_XDIVY ; \ + RID_XSYMDIVIDEY ; \ + RID_NEGX ; \ + RID_XANDY ; \ + RID_XORY ; \ + RID_XCIRCY ; \ + }; \ + IdCount = { 16 ; }; + + ImageList RID_IL_UNBINOPS + { + Prefix = "un"; + MaskColor = IMAGE_STDBTN_COLOR ; + UNBINOPS_IDLIST + }; + +#define RELATIONS_IDLIST \ + IdList = \ + { \ + RID_XEQY ; \ + RID_XNEQY ; \ + RID_XEQUIVY ; \ + RID_XORTHOY ; \ + RID_XLTY ; \ + RID_XGTY ; \ + RID_XAPPROXY ; \ + RID_XPARALLELY ; \ + RID_XLESLANTY ; \ + RID_XGESLANTY ; \ + RID_XSIMEQY ; \ + RID_XPROPY ; \ + RID_XLEY ; \ + RID_XGEY ; \ + RID_XSIMY ; \ + RID_XTOWARDY ; \ + RID_XDIVIDESY ; \ + RID_XNDIVIDESY; \ + RID_DLARROW ; \ + RID_DLRARROW ; \ + RID_DRARROW ; \ + }; \ + IdCount ={ 21 ; }; + + ImageList RID_IL_RELATIONS + { + Prefix = "bi"; + MaskColor = IMAGE_STDBTN_COLOR ; + RELATIONS_IDLIST + }; + +#define SETOPERATIONS_IDLIST \ + IdList = \ + { \ + RID_XINY ; \ + RID_XNOTINY ; \ + RID_XOWNSY ; \ + RID_XINTERSECTIONY ; \ + RID_XUNIONY ; \ + RID_XSETMINUSY ; \ + RID_XSLASHY ; \ + RID_XSUBSETY ; \ + RID_XSUBSETEQY ; \ + RID_XSUPSETY ; \ + RID_XSUPSETEQY ; \ + RID_XNSUBSETY ; \ + RID_XNSUBSETEQY ; \ + RID_XNSUPSETY ; \ + RID_XNSUPSETEQY ; \ + RID_EMPTYSET ; \ + RID_ALEPH ; \ + RID_SETN ; \ + RID_SETZ ; \ + RID_SETQ ; \ + RID_SETR ; \ + RID_SETC ; \ + }; \ + IdCount = { 22 ; }; + + ImageList RID_IL_SETOPERATIONS + { + Prefix = "op"; + MaskColor = IMAGE_STDBTN_COLOR ; + SETOPERATIONS_IDLIST + }; + +#define FUNCTIONS_IDLIST \ + IdList = \ + { \ + RID_ABSX ; \ + RID_FACTX ; \ + RID_SQRTX ; \ + RID_NROOTXY ; \ + RID_EX ; \ + RID_LNX ; \ + RID_EXPX ; \ + RID_LOGX ; \ + RID_SINX ; \ + RID_COSX ; \ + RID_TANX ; \ + RID_COTX ; \ + RID_SINHX ; \ + RID_COSHX ; \ + RID_TANHX ; \ + RID_COTHX ; \ + RID_ARCSINX ; \ + RID_ARCCOSX ; \ + RID_ARCTANX ; \ + RID_ARCCOTX ; \ + RID_ARSINHX ; \ + RID_ARCOSHX ; \ + RID_ARTANHX ; \ + RID_ARCOTHX ; \ + RID_RSUPX ; \ + }; \ + IdCount = { 25 ; }; + + ImageList RID_IL_FUNCTIONS + { + Prefix = "fu"; + MaskColor = IMAGE_STDBTN_COLOR ; + FUNCTIONS_IDLIST + }; + +#define OPERATORS_IDLIST \ + IdList = \ + { \ + RID_LIMX ; \ + RID_SUMX ; \ + RID_PRODX ; \ + RID_COPRODX ; \ + RID_INTX ; \ + RID_IINTX ; \ + RID_IIINTX ; \ + RID_LINTX ; \ + RID_LLINTX ; \ + RID_LLLINTX ; \ + RID_FROMXTOY ; \ + RID_FROMX ; \ + RID_TOX ; \ + }; \ + IdCount = { 13 ; }; + + ImageList RID_IL_OPERATORS + { + Prefix = "fo"; + MaskColor = IMAGE_STDBTN_COLOR ; + OPERATORS_IDLIST + }; + +#define ATTRIBUTES_IDLIST \ + IdList = \ + { \ + RID_ACUTEX ; \ + RID_GRAVEX ; \ + RID_CHECKX ; \ + RID_BREVEX ; \ + RID_BARX ; \ + RID_VECX ; \ + RID_HATX ; \ + RID_TILDEX ; \ + RID_CIRCLEX ; \ + RID_DOTX ; \ + RID_DDOTX ; \ + RID_DDDOTX ; \ + RID_OVERLINEX ; \ + RID_UNDERLINEX ; \ + RID_OVERSTRIKEX ; \ + RID_PHANTOMX ; \ + RID_BOLDX ; \ + RID_ITALX ; \ + RID_SIZEXY ; \ + RID_FONTXY ; \ + RID_WIDEHATX ; \ + RID_WIDETILDEX ; \ + RID_WIDEVECX ; \ + }; \ + IdCount = { 23 ; }; + + ImageList RID_IL_ATTRIBUTES + { + Prefix = "at"; + MaskColor = IMAGE_STDBTN_COLOR ; + ATTRIBUTES_IDLIST + }; + +#define BRACKETS_IDLIST \ + IdList = \ + { \ + RID_LRPARENTX ; \ + RID_LRBRACKETX ; \ + RID_LRANGLEX ; \ + RID_LRBRACEX ; \ + RID_LRLINEX ; \ + RID_LRDLINEX ; \ + RID_LMRANGLEXY ; \ + RID_LRGROUPX ; \ + RID_SLRPARENTX ; \ + RID_SLRBRACKETX ; \ + RID_SLRANGLEX ; \ + RID_SLRBRACEX ; \ + RID_SLRLINEX ; \ + RID_SLRDLINEX ; \ + RID_SLMRANGLEXY ; \ + RID_LRDBRACKETX ; \ + RID_SLRDBRACKETX ; \ + RID_XOVERBRACEY ; \ + RID_XUNDERBRACEY ; \ + }; \ + IdCount = { 19 ; }; + + ImageList RID_IL_BRACKETS + { + Prefix = "al"; + MaskColor = IMAGE_STDBTN_COLOR ; + BRACKETS_IDLIST + }; + +#define FORMAT_IDLIST \ + IdList = \ + { \ + RID_NEWLINE ; \ + RID_SBLANK ; \ + RID_BLANK ; \ + RID_BINOMXY ; \ + RID_STACK ; \ + RID_MATRIX ; \ + RID_ALIGNLX ; \ + RID_ALIGNCX ; \ + RID_ALIGNRX ; \ + RID_RSUBX ; \ + RID_RSUPX ; \ + RID_LSUBX ; \ + RID_LSUPX ; \ + RID_CSUBX ; \ + RID_CSUPX ; \ + }; \ + IdCount = { 15 ; }; + + ImageList RID_IL_FORMAT + { + Prefix = "co"; + MaskColor = IMAGE_STDBTN_COLOR ; + FORMAT_IDLIST + }; + +#define MISC_IDLIST \ + IdList = \ + { \ + RID_INFINITY ; \ + RID_PARTIAL ; \ + RID_NABLA ; \ + RID_EXISTS ; \ + RID_FORALL ; \ + RID_HBAR; \ + RID_LAMBDABAR ; \ + RID_RE ; \ + RID_IM ; \ + RID_WP ; \ + RID_LEFTARROW ; \ + RID_RIGHTARROW ; \ + RID_UPARROW ; \ + RID_DOWNARROW ; \ + RID_DOTSLOW ; \ + RID_DOTSAXIS ; \ + RID_DOTSVERT ; \ + RID_DOTSUP ; \ + RID_DOTSDOWN ; \ + }; \ + IdCount = { 19 ; }; + + ImageList RID_IL_MISC + { + Prefix = "mi"; + MaskColor = IMAGE_STDBTN_COLOR ; + MISC_IDLIST + }; + +#define CATALOG_IDLIST \ + IdList = \ + { \ + RID_UNBINOPS_CAT ; \ + RID_RELATIONS_CAT ; \ + RID_SETOPERATIONS_CAT ; \ + RID_FUNCTIONS_CAT ; \ + RID_OPERATORS_CAT ; \ + RID_ATTRIBUTES_CAT ; \ + RID_MISC_CAT ; \ + RID_BRACKETS_CAT ; \ + RID_FORMAT_CAT ; \ + }; \ + IdCount = { 9 ; }; + + ImageList RID_IL_CATALOG + { + Prefix = "im"; + MaskColor = IMAGE_STDBTN_COLOR ; + CATALOG_IDLIST + }; + + + diff --git a/starmath/source/typemap.cxx b/starmath/source/typemap.cxx new file mode 100644 index 000000000000..767e29dcad34 --- /dev/null +++ b/starmath/source/typemap.cxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#define ITEMID_PTR 0 +#define ITEMID_SHADOW 0 +#define ITEMID_PAGE 0 +#define ITEMID_SETITEM 0 +#define ITEMID_HORJUSTIFY 0 +#define ITEMID_VERJUSTIFY 0 +#define ITEMID_ORIENTATION 0 +#define ITEMID_MARGIN 0 +#define ITEMID_AUTHOR 0 +#define ITEMID_DATE 0 +#define ITEMID_TEXT 0 +#define ITEMID_SPELLCHECK 0 +#define ITEMID_HYPHENREGION 0 +#define ITEMID_FONT 0 +#define ITEMID_FONTHEIGHT 0 +#define ITEMID_BRUSH 0 +#define ITEMID_BOX 0 +#define ITEMID_LINE 0 +#define ITEMID_LINESPACING 0 +#define ITEMID_ADJUST 0 +#define ITEMID_WIDOWS 0 +#define ITEMID_ORPHANS 0 +#define ITEMID_HYPHENZONE 0 +#define ITEMID_TABSTOP 0 +#define ITEMID_FMTSPLIT 0 +#define ITEMID_PAGEMODEL 0 +#define ITEMID_FONTLIST 0 +#define ITEMID_POSTURE 0 +#define ITEMID_WEIGHT 0 +#define ITEMID_FONTWIDTH 0 +#define ITEMID_UNDERLINE 0 +#define ITEMID_CROSSEDOUT 0 +#define ITEMID_SHADOWED 0 +#define ITEMID_AUTOKERN 0 +#define ITEMID_WORDLINEMODE 0 +#define ITEMID_CONTOUR 0 +#define ITEMID_PROPSIZE 0 +#define ITEMID_COLOR 0 +#define ITEMID_CHARSETCOLOR 0 +#define ITEMID_KERNING 0 +#define ITEMID_CASEMAP 0 +#define ITEMID_ESCAPEMENT 0 +#define ITEMID_LANGUAGE 0 +#define ITEMID_NOLINEBREAK 0 +#define ITEMID_NOHYPHENHERE 0 +#define ITEMID_SEARCH 0 +#define ITEMID_COLOR_TABLE 0 +#define ITEMID_GRADIENT_LIST 0 +#define ITEMID_HATCH_LIST 0 +#define ITEMID_BITMAP_LIST 0 +#define ITEMID_DASH_LIST 0 +#define ITEMID_LINEEND_LIST 0 +#define ITEMID_NUMBERINFO 0 +#define ITEMID_CHARTSTYLE 0 +#define ITEMID_CHARTDATADESCR 0 +#define ITEMID_CHARTLEGENDPOS 0 +#define ITEMID_CHARTTEXTORDER 0 +#define ITEMID_CHARTTEXTORIENT 0 +#define ITEMID_DOUBLE 0 +#define ITEMID_PAPERBIN 0 +#define ITEMID_SIZE 0 +#define ITEMID_LRSPACE 0 +#define ITEMID_ULSPACE 0 +#define ITEMID_PRINT 0 +#define ITEMID_OPAQUE 0 +#define ITEMID_PROTECT 0 +#define ITEMID_MACRO 0 +#define ITEMID_BOXINFO 0 +#define ITEMID_FMTBREAK 0 +#define ITEMID_FMTKEEP 0 + +#define CharSetItem SfxVoidItem +#define FontFamilyItem SfxVoidItem +#define FontPitchItem SfxVoidItem +#define FontAlignItem SfxVoidItem +#define FontWeightItem SfxVoidItem +#define FontUnderlineItem SfxVoidItem +#define FontStrikeoutItem SfxVoidItem +#define FontItalicItem SfxVoidItem +#define SvxDbTypeItem SfxVoidItem +#define SvxLineSpaceItem SfxVoidItem +#define SvxInterLineSpaceItem SfxVoidItem +#define SvxBreakItem SfxVoidItem +#define BrushStyleItem SfxVoidItem +#define SvxNumTypeItem SfxVoidItem +#define SvxShadowLocationItem SfxVoidItem +#define SvxLanguage SfxVoidItem +#define SvxChooseControlEnumItem SfxVoidItem +#define SvxDrawToolEnumItem SfxVoidItem +#define SvxChooseControlItem SfxVoidItem +#define SvxDrawToolItem SfxVoidItem +#define SvxCellHorJustifyEnumItem SfxVoidItem +#define SvxCellVerJustifyEnumItem SfxVoidItem +#define SvxCellOrientationEnumItem SfxVoidItem +#include <sfx2/msg.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <svx/zoomitem.hxx> +#include <svl/slstitm.hxx> + +#define SFX_TYPEMAP +#include "smslots.hxx" + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/types.cxx b/starmath/source/types.cxx new file mode 100644 index 000000000000..185ec069b797 --- /dev/null +++ b/starmath/source/types.cxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <types.hxx> +#include <osl/diagnose.h> + + +sal_Unicode ConvertMathPrivateUseAreaToUnicode( sal_Unicode cChar ) +{ + sal_Unicode cRes = cChar; + if (IsInPrivateUseArea( cChar )) + { + OSL_FAIL( "Error: private use area characters should no longer be in use!" ); + cRes = (sal_Unicode) '@'; // just some character that should easily be notice as odd in the context + } + return cRes; +} + + +sal_Unicode ConvertMathToMathML( sal_Unicode cChar ) +{ + sal_Unicode cRes = ConvertMathPrivateUseAreaToUnicode( cChar ); + return cRes; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/unodoc.cxx b/starmath/source/unodoc.cxx new file mode 100644 index 000000000000..aa322f9b6810 --- /dev/null +++ b/starmath/source/unodoc.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + +// System - Includes ----------------------------------------------------- + +#include <tools/string.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/sfxmodelfactory.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include "smdll.hxx" +#include "document.hxx" +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> + +using namespace ::com::sun::star; + +::rtl::OUString SAL_CALL SmDocument_getImplementationName() throw() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.FormulaDocument" ) ); +} + +uno::Sequence< rtl::OUString > SAL_CALL SmDocument_getSupportedServiceNames() throw() +{ + uno::Sequence< rtl::OUString > aSeq( 1 ); + aSeq[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.formula.FormulaProperties" )); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL SmDocument_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & /*rSMgr*/, const sal_uInt64 _nCreationFlags ) throw( uno::Exception ) +{ + SolarMutexGuard aGuard; + SmGlobals::ensure(); + SfxObjectShell* pShell = new SmDocShell( _nCreationFlags ); + return uno::Reference< uno::XInterface >( pShell->GetModel() ); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/unomodel.cxx b/starmath/source/unomodel.cxx new file mode 100644 index 000000000000..4ac92976567e --- /dev/null +++ b/starmath/source/unomodel.cxx @@ -0,0 +1,1140 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <osl/mutex.hxx> +#include <sfx2/printer.hxx> +#include <vcl/svapp.hxx> +#include <svtools/ctrltool.hxx> +#include <svl/itemprop.hxx> +#include <unotools/localedatawrapper.hxx> +#include <unotools/processfactory.hxx> +#include <editeng/paperinf.hxx> +#include <vcl/settings.hxx> +#include <vcl/print.hxx> +#include <toolkit/awt/vclxdevice.hxx> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/formula/SymbolDescriptor.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <xmloff/xmluconv.hxx> +#include <rtl/ustrbuf.hxx> +#include <comphelper/propertysetinfo.hxx> +#include <comphelper/servicehelper.hxx> +#include <unotools/moduleoptions.hxx> + +#include <unomodel.hxx> +#include <document.hxx> +#include <view.hxx> +#include <symbol.hxx> +#include <starmath.hrc> +#include <config.hxx> +#include <smdll.hxx> + +using namespace ::cppu; +using namespace ::std; +using namespace ::comphelper; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::formula; +using namespace ::com::sun::star::view; +using namespace ::com::sun::star::script; + + +using rtl::OUString; + +#define TWIP_TO_MM100(TWIP) ((TWIP) >= 0 ? (((TWIP)*127L+36L)/72L) : (((TWIP)*127L-36L)/72L)) +#define MM100_TO_TWIP(MM100) ((MM100) >= 0 ? (((MM100)*72L+63L)/127L) : (((MM100)*72L-63L)/127L)) + +//////////////////////////////////////////////////////////// + +SmPrintUIOptions::SmPrintUIOptions() +{ + ResStringArray aLocalizedStrings( SmResId( RID_PRINTUIOPTIONS ) ); + OSL_ENSURE( aLocalizedStrings.Count() >= 18, "resource incomplete" ); + if( aLocalizedStrings.Count() < 9 ) // bad resource ? + return; + + SmModule *pp = SM_MOD(); + SmConfig *pConfig = pp->GetConfig(); + OSL_ENSURE( pConfig, "SmConfig not found" ); + if (!pConfig) + return; + + // create sequence of print UI options + // (Actually IsIgnoreSpacesRight is a parser option. Without it we need only 8 properties here.) + m_aUIProperties.realloc( 9 ); + + // create Section for formula (results in an extra tab page in dialog) + SvtModuleOptions aOpt; + String aAppGroupname( aLocalizedStrings.GetString( 0 ) ); + aAppGroupname.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%s" ) ), + aOpt.GetModuleName( SvtModuleOptions::E_SMATH ) ); + m_aUIProperties[0].Value = getGroupControlOpt( aAppGroupname, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:TabPage:AppPage" ) ) ); + + // create subgroup for print options + m_aUIProperties[1].Value = getSubgroupControlOpt( aLocalizedStrings.GetString( 1 ), rtl::OUString() ); + + // create a bool option for title row (matches to SID_PRINTTITLE) + m_aUIProperties[2].Value = getBoolControlOpt( aLocalizedStrings.GetString( 2 ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:TitleRow:CheckBox" ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PRTUIOPT_TITLE_ROW ) ), + pConfig->IsPrintTitle() ); + // create a bool option for formula text (matches to SID_PRINTTEXT) + m_aUIProperties[3].Value = getBoolControlOpt( aLocalizedStrings.GetString( 3 ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:FormulaText:CheckBox" ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PRTUIOPT_FORMULA_TEXT ) ), + pConfig->IsPrintFormulaText() ); + // create a bool option for border (matches to SID_PRINTFRAME) + m_aUIProperties[4].Value = getBoolControlOpt( aLocalizedStrings.GetString( 4 ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:Border:CheckBox" ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PRTUIOPT_BORDER ) ), + pConfig->IsPrintFrame() ); + + // create subgroup for print format + m_aUIProperties[5].Value = getSubgroupControlOpt( aLocalizedStrings.GetString( 5 ), rtl::OUString() ); + + // create a radio button group for print format (matches to SID_PRINTSIZE) + Sequence< rtl::OUString > aChoices( 3 ); + aChoices[0] = aLocalizedStrings.GetString( 6 ); + aChoices[1] = aLocalizedStrings.GetString( 7 ); + aChoices[2] = aLocalizedStrings.GetString( 8 ); + Sequence< rtl::OUString > aHelpIds( 3 ); + aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintFormat:RadioButton:0" ) ); + aHelpIds[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintFormat:RadioButton:1" ) ); + aHelpIds[2] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintFormat:RadioButton:2" ) ); + OUString aPrintFormatProp( RTL_CONSTASCII_USTRINGPARAM( PRTUIOPT_PRINT_FORMAT ) ); + m_aUIProperties[6].Value = getChoiceControlOpt( rtl::OUString(), + aHelpIds, + aPrintFormatProp, + aChoices, static_cast< sal_Int32 >(pConfig->GetPrintSize()) + ); + + // create a numeric box for scale dependent on PrintFormat = "Scaling" (matches to SID_PRINTZOOM) + vcl::PrinterOptionsHelper::UIControlOptions aRangeOpt( aPrintFormatProp, 2, sal_True ); + m_aUIProperties[ 7 ].Value = getRangeControlOpt( rtl::OUString(), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintScale:NumericField" ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PRTUIOPT_PRINT_SCALE ) ), + pConfig->GetPrintZoomFactor(), // initial value + 10, // min value + 1000, // max value + aRangeOpt ); + + Sequence< PropertyValue > aHintNoLayoutPage( 1 ); + aHintNoLayoutPage[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HintNoLayoutPage" ) ); + aHintNoLayoutPage[0].Value = makeAny( sal_True ); + m_aUIProperties[8].Value <<= aHintNoLayoutPage; + +} + + +//////////////////////////////////////////////////////////// +// +// class SmModel +// + +// values from com/sun/star/beans/PropertyAttribute +#define PROPERTY_NONE 0 +#define PROPERTY_READONLY 16 + +enum SmModelPropertyHandles +{ + HANDLE_FORMULA, + HANDLE_FONT_NAME_VARIABLES, + HANDLE_FONT_NAME_FUNCTIONS, + HANDLE_FONT_NAME_NUMBERS, + HANDLE_FONT_NAME_TEXT, + HANDLE_CUSTOM_FONT_NAME_SERIF, + HANDLE_CUSTOM_FONT_NAME_SANS, + HANDLE_CUSTOM_FONT_NAME_FIXED, + HANDLE_CUSTOM_FONT_FIXED_POSTURE, + HANDLE_CUSTOM_FONT_FIXED_WEIGHT, + HANDLE_CUSTOM_FONT_SANS_POSTURE, + HANDLE_CUSTOM_FONT_SANS_WEIGHT, + HANDLE_CUSTOM_FONT_SERIF_POSTURE, + HANDLE_CUSTOM_FONT_SERIF_WEIGHT, + HANDLE_FONT_VARIABLES_POSTURE, + HANDLE_FONT_VARIABLES_WEIGHT, + HANDLE_FONT_FUNCTIONS_POSTURE, + HANDLE_FONT_FUNCTIONS_WEIGHT, + HANDLE_FONT_NUMBERS_POSTURE, + HANDLE_FONT_NUMBERS_WEIGHT, + HANDLE_FONT_TEXT_POSTURE, + HANDLE_FONT_TEXT_WEIGHT, + HANDLE_BASE_FONT_HEIGHT, + HANDLE_RELATIVE_FONT_HEIGHT_TEXT, + HANDLE_RELATIVE_FONT_HEIGHT_INDICES, + HANDLE_RELATIVE_FONT_HEIGHT_FUNCTIONS, + HANDLE_RELATIVE_FONT_HEIGHT_OPERATORS, + HANDLE_RELATIVE_FONT_HEIGHT_LIMITS, + HANDLE_IS_TEXT_MODE, + HANDLE_GREEK_CHAR_STYLE, + HANDLE_ALIGNMENT, + HANDLE_RELATIVE_SPACING, + HANDLE_RELATIVE_LINE_SPACING, + HANDLE_RELATIVE_ROOT_SPACING, + HANDLE_RELATIVE_INDEX_SUPERSCRIPT, + HANDLE_RELATIVE_INDEX_SUBSCRIPT, + HANDLE_RELATIVE_FRACTION_NUMERATOR_HEIGHT, + HANDLE_RELATIVE_FRACTION_DENOMINATOR_DEPTH, + HANDLE_RELATIVE_FRACTION_BAR_EXCESS_LENGTH, + HANDLE_RELATIVE_FRACTION_BAR_LINE_WEIGHT, + HANDLE_RELATIVE_UPPER_LIMIT_DISTANCE, + HANDLE_RELATIVE_LOWER_LIMIT_DISTANCE, + HANDLE_RELATIVE_BRACKET_EXCESS_SIZE, + HANDLE_RELATIVE_BRACKET_DISTANCE, + HANDLE_IS_SCALE_ALL_BRACKETS, + HANDLE_RELATIVE_SCALE_BRACKET_EXCESS_SIZE, + HANDLE_RELATIVE_MATRIX_LINE_SPACING, + HANDLE_RELATIVE_MATRIX_COLUMN_SPACING, + HANDLE_RELATIVE_SYMBOL_PRIMARY_HEIGHT, + HANDLE_RELATIVE_SYMBOL_MINIMUM_HEIGHT, + HANDLE_RELATIVE_OPERATOR_EXCESS_SIZE, + HANDLE_RELATIVE_OPERATOR_SPACING, + HANDLE_LEFT_MARGIN, + HANDLE_RIGHT_MARGIN, + HANDLE_TOP_MARGIN, + HANDLE_BOTTOM_MARGIN, + HANDLE_PRINTER_NAME, + HANDLE_PRINTER_SETUP, + HANDLE_SYMBOLS, + HANDLE_USED_SYMBOLS, + HANDLE_BASIC_LIBRARIES, + HANDLE_RUNTIME_UID, + HANDLE_LOAD_READONLY, // Security Options + HANDLE_DIALOG_LIBRARIES, // #i73329# + HANDLE_BASELINE +}; + +PropertySetInfo * lcl_createModelPropertyInfo () +{ + static PropertyMapEntry aModelPropertyInfoMap[] = + { + { RTL_CONSTASCII_STRINGPARAM( "Alignment" ), HANDLE_ALIGNMENT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0}, + { RTL_CONSTASCII_STRINGPARAM( "BaseFontHeight" ), HANDLE_BASE_FONT_HEIGHT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0}, + { RTL_CONSTASCII_STRINGPARAM( "BasicLibraries" ), HANDLE_BASIC_LIBRARIES , &::getCppuType((const uno::Reference< script::XLibraryContainer > *)0), PropertyAttribute::READONLY, 0}, + { RTL_CONSTASCII_STRINGPARAM( "BottomMargin" ), HANDLE_BOTTOM_MARGIN , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_BOTTOMSPACE }, + { RTL_CONSTASCII_STRINGPARAM( "CustomFontNameFixed" ), HANDLE_CUSTOM_FONT_NAME_FIXED , &::getCppuType((const OUString*)0), PROPERTY_NONE, FNT_FIXED }, + { RTL_CONSTASCII_STRINGPARAM( "CustomFontNameSans" ), HANDLE_CUSTOM_FONT_NAME_SANS , &::getCppuType((const OUString*)0), PROPERTY_NONE, FNT_SANS }, + { RTL_CONSTASCII_STRINGPARAM( "CustomFontNameSerif" ), HANDLE_CUSTOM_FONT_NAME_SERIF , &::getCppuType((const OUString*)0), PROPERTY_NONE, FNT_SERIF }, + { RTL_CONSTASCII_STRINGPARAM( "DialogLibraries" ), HANDLE_DIALOG_LIBRARIES , &::getCppuType((const uno::Reference< script::XLibraryContainer > *)0), PropertyAttribute::READONLY, 0}, + { RTL_CONSTASCII_STRINGPARAM( "FontFixedIsBold"), HANDLE_CUSTOM_FONT_FIXED_WEIGHT , &::getBooleanCppuType(), PROPERTY_NONE, FNT_FIXED}, + { RTL_CONSTASCII_STRINGPARAM( "FontFixedIsItalic"), HANDLE_CUSTOM_FONT_FIXED_POSTURE , &::getBooleanCppuType(), PROPERTY_NONE, FNT_FIXED}, + { RTL_CONSTASCII_STRINGPARAM( "FontFunctionsIsBold"), HANDLE_FONT_FUNCTIONS_WEIGHT , &::getBooleanCppuType(), PROPERTY_NONE, FNT_FUNCTION}, + { RTL_CONSTASCII_STRINGPARAM( "FontFunctionsIsItalic"), HANDLE_FONT_FUNCTIONS_POSTURE , &::getBooleanCppuType(), PROPERTY_NONE, FNT_FUNCTION}, + { RTL_CONSTASCII_STRINGPARAM( "FontNameFunctions" ), HANDLE_FONT_NAME_FUNCTIONS , &::getCppuType((const OUString*)0), PROPERTY_NONE, FNT_FUNCTION }, + { RTL_CONSTASCII_STRINGPARAM( "FontNameNumbers" ), HANDLE_FONT_NAME_NUMBERS , &::getCppuType((const OUString*)0), PROPERTY_NONE, FNT_NUMBER }, + { RTL_CONSTASCII_STRINGPARAM( "FontNameText" ), HANDLE_FONT_NAME_TEXT , &::getCppuType((const OUString*)0), PROPERTY_NONE, FNT_TEXT }, + { RTL_CONSTASCII_STRINGPARAM( "FontNameVariables" ), HANDLE_FONT_NAME_VARIABLES , &::getCppuType((const OUString*)0), PROPERTY_NONE, FNT_VARIABLE }, + { RTL_CONSTASCII_STRINGPARAM( "FontNumbersIsBold"), HANDLE_FONT_NUMBERS_WEIGHT , &::getBooleanCppuType(), PROPERTY_NONE, FNT_NUMBER}, + { RTL_CONSTASCII_STRINGPARAM( "FontNumbersIsItalic"), HANDLE_FONT_NUMBERS_POSTURE , &::getBooleanCppuType(), PROPERTY_NONE, FNT_NUMBER}, + { RTL_CONSTASCII_STRINGPARAM( "FontSansIsBold"), HANDLE_CUSTOM_FONT_SANS_WEIGHT , &::getBooleanCppuType(), PROPERTY_NONE, FNT_SANS}, + { RTL_CONSTASCII_STRINGPARAM( "FontSansIsItalic"), HANDLE_CUSTOM_FONT_SANS_POSTURE , &::getBooleanCppuType(), PROPERTY_NONE, FNT_SANS}, + { RTL_CONSTASCII_STRINGPARAM( "FontSerifIsBold"), HANDLE_CUSTOM_FONT_SERIF_WEIGHT , &::getBooleanCppuType(), PROPERTY_NONE, FNT_SERIF}, + { RTL_CONSTASCII_STRINGPARAM( "FontSerifIsItalic"), HANDLE_CUSTOM_FONT_SERIF_POSTURE , &::getBooleanCppuType(), PROPERTY_NONE, FNT_SERIF}, + { RTL_CONSTASCII_STRINGPARAM( "FontTextIsBold"), HANDLE_FONT_TEXT_WEIGHT , &::getBooleanCppuType(), PROPERTY_NONE, FNT_TEXT}, + { RTL_CONSTASCII_STRINGPARAM( "FontTextIsItalic"), HANDLE_FONT_TEXT_POSTURE , &::getBooleanCppuType(), PROPERTY_NONE, FNT_TEXT}, + { RTL_CONSTASCII_STRINGPARAM( "FontVariablesIsBold"), HANDLE_FONT_VARIABLES_WEIGHT , &::getBooleanCppuType(), PROPERTY_NONE, FNT_VARIABLE}, + { RTL_CONSTASCII_STRINGPARAM( "FontVariablesIsItalic"), HANDLE_FONT_VARIABLES_POSTURE, &::getBooleanCppuType(), PROPERTY_NONE, FNT_VARIABLE}, + { RTL_CONSTASCII_STRINGPARAM( "Formula" ), HANDLE_FORMULA , &::getCppuType((const OUString*)0), PROPERTY_NONE, 0}, + { RTL_CONSTASCII_STRINGPARAM( "IsScaleAllBrackets" ), HANDLE_IS_SCALE_ALL_BRACKETS , &::getBooleanCppuType(), PROPERTY_NONE, 0}, + { RTL_CONSTASCII_STRINGPARAM( "IsTextMode" ), HANDLE_IS_TEXT_MODE , &::getBooleanCppuType(), PROPERTY_NONE, 0}, + { RTL_CONSTASCII_STRINGPARAM( "GreekCharStyle" ), HANDLE_GREEK_CHAR_STYLE, &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0}, + { RTL_CONSTASCII_STRINGPARAM( "LeftMargin" ), HANDLE_LEFT_MARGIN , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_LEFTSPACE }, + { RTL_CONSTASCII_STRINGPARAM( "PrinterName" ), HANDLE_PRINTER_NAME , &::getCppuType((const OUString*)0), PROPERTY_NONE, 0 }, + { RTL_CONSTASCII_STRINGPARAM( "PrinterSetup" ), HANDLE_PRINTER_SETUP , &::getCppuType((const Sequence < sal_Int8 >*)0), PROPERTY_NONE, 0 }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeBracketDistance" ), HANDLE_RELATIVE_BRACKET_DISTANCE , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_BRACKETSPACE }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeBracketExcessSize" ), HANDLE_RELATIVE_BRACKET_EXCESS_SIZE , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_BRACKETSIZE }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeFontHeightFunctions" ), HANDLE_RELATIVE_FONT_HEIGHT_FUNCTIONS , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, SIZ_FUNCTION}, + { RTL_CONSTASCII_STRINGPARAM( "RelativeFontHeightIndices" ), HANDLE_RELATIVE_FONT_HEIGHT_INDICES , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, SIZ_INDEX }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeFontHeightLimits" ), HANDLE_RELATIVE_FONT_HEIGHT_LIMITS , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, SIZ_LIMITS }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeFontHeightOperators" ), HANDLE_RELATIVE_FONT_HEIGHT_OPERATORS , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, SIZ_OPERATOR}, + { RTL_CONSTASCII_STRINGPARAM( "RelativeFontHeightText" ), HANDLE_RELATIVE_FONT_HEIGHT_TEXT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, SIZ_TEXT }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeFractionBarExcessLength"), HANDLE_RELATIVE_FRACTION_BAR_EXCESS_LENGTH, &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_FRACTION }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeFractionBarLineWeight" ), HANDLE_RELATIVE_FRACTION_BAR_LINE_WEIGHT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_STROKEWIDTH }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeFractionDenominatorDepth"), HANDLE_RELATIVE_FRACTION_DENOMINATOR_DEPTH, &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_DENOMINATOR }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeFractionNumeratorHeight" ), HANDLE_RELATIVE_FRACTION_NUMERATOR_HEIGHT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_NUMERATOR }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeIndexSubscript" ), HANDLE_RELATIVE_INDEX_SUBSCRIPT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_SUBSCRIPT }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeIndexSuperscript" ), HANDLE_RELATIVE_INDEX_SUPERSCRIPT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_SUPERSCRIPT }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeLineSpacing" ), HANDLE_RELATIVE_LINE_SPACING , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_VERTICAL }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeLowerLimitDistance" ), HANDLE_RELATIVE_LOWER_LIMIT_DISTANCE , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_LOWERLIMIT }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeMatrixColumnSpacing" ), HANDLE_RELATIVE_MATRIX_COLUMN_SPACING , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_MATRIXCOL}, + { RTL_CONSTASCII_STRINGPARAM( "RelativeMatrixLineSpacing" ), HANDLE_RELATIVE_MATRIX_LINE_SPACING , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_MATRIXROW}, + { RTL_CONSTASCII_STRINGPARAM( "RelativeOperatorExcessSize" ), HANDLE_RELATIVE_OPERATOR_EXCESS_SIZE , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_OPERATORSIZE }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeOperatorSpacing" ), HANDLE_RELATIVE_OPERATOR_SPACING , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_OPERATORSPACE}, + { RTL_CONSTASCII_STRINGPARAM( "RelativeRootSpacing" ), HANDLE_RELATIVE_ROOT_SPACING , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_ROOT }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeScaleBracketExcessSize" ), HANDLE_RELATIVE_SCALE_BRACKET_EXCESS_SIZE , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_NORMALBRACKETSIZE}, + { RTL_CONSTASCII_STRINGPARAM( "RelativeSpacing" ), HANDLE_RELATIVE_SPACING , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_HORIZONTAL }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeSymbolMinimumHeight" ), HANDLE_RELATIVE_SYMBOL_MINIMUM_HEIGHT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_ORNAMENTSPACE }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeSymbolPrimaryHeight" ), HANDLE_RELATIVE_SYMBOL_PRIMARY_HEIGHT , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_ORNAMENTSIZE }, + { RTL_CONSTASCII_STRINGPARAM( "RelativeUpperLimitDistance" ), HANDLE_RELATIVE_UPPER_LIMIT_DISTANCE , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_UPPERLIMIT }, + { RTL_CONSTASCII_STRINGPARAM( "RightMargin" ), HANDLE_RIGHT_MARGIN , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_RIGHTSPACE }, + { RTL_CONSTASCII_STRINGPARAM( "RuntimeUID" ), HANDLE_RUNTIME_UID , &::getCppuType(static_cast< const rtl::OUString * >(0)), PropertyAttribute::READONLY, 0 }, + { RTL_CONSTASCII_STRINGPARAM( "Symbols" ), HANDLE_SYMBOLS , &::getCppuType((const Sequence < SymbolDescriptor > *)0), PROPERTY_NONE, 0 }, + { RTL_CONSTASCII_STRINGPARAM( "UserDefinedSymbolsInUse" ), HANDLE_USED_SYMBOLS , &::getCppuType((const Sequence < SymbolDescriptor > *)0), PropertyAttribute::READONLY, 0 }, + { RTL_CONSTASCII_STRINGPARAM( "TopMargin" ), HANDLE_TOP_MARGIN , &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, DIS_TOPSPACE }, + // #i33095# Security Options + { RTL_CONSTASCII_STRINGPARAM( "LoadReadonly" ), HANDLE_LOAD_READONLY, &::getBooleanCppuType(), PROPERTY_NONE, 0 }, + // #i972# + { RTL_CONSTASCII_STRINGPARAM( "BaseLine"), HANDLE_BASELINE, &::getCppuType((const sal_Int16*)0), PROPERTY_NONE, 0}, + { NULL, 0, 0, NULL, 0, 0 } + }; + PropertySetInfo *pInfo = new PropertySetInfo ( aModelPropertyInfoMap ); + return pInfo; +} + +SmModel::SmModel( SfxObjectShell *pObjSh ) +: SfxBaseModel(pObjSh) +, PropertySetHelper ( lcl_createModelPropertyInfo () ) +, m_pPrintUIOptions( NULL ) + +{ +} + +SmModel::~SmModel() throw () +{ + delete m_pPrintUIOptions; +} + +uno::Any SAL_CALL SmModel::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException) +{ + uno::Any aRet = ::cppu::queryInterface ( rType, + // OWeakObject interfaces + dynamic_cast< XInterface* > ( static_cast< XUnoTunnel* > ( this )), + static_cast< XWeak* > ( this ), + // PropertySetHelper interfaces + static_cast< XPropertySet* > ( this ), + static_cast< XMultiPropertySet* > ( this ), + //static_cast< XPropertyState* > ( this ), + // my own interfaces + static_cast< XServiceInfo* > ( this ), + static_cast< XRenderable* > ( this ) ); + if (!aRet.hasValue()) + aRet = SfxBaseModel::queryInterface ( rType ); + return aRet; +} + +void SAL_CALL SmModel::acquire() throw() +{ + OWeakObject::acquire(); +} + +void SAL_CALL SmModel::release() throw() +{ + OWeakObject::release(); +} + +uno::Sequence< uno::Type > SAL_CALL SmModel::getTypes( ) throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + uno::Sequence< uno::Type > aTypes = SfxBaseModel::getTypes(); + sal_Int32 nLen = aTypes.getLength(); + aTypes.realloc(nLen + 4); + uno::Type* pTypes = aTypes.getArray(); + pTypes[nLen++] = ::getCppuType((Reference<XServiceInfo>*)0); + pTypes[nLen++] = ::getCppuType((Reference<XPropertySet>*)0); + pTypes[nLen++] = ::getCppuType((Reference<XMultiPropertySet>*)0); + pTypes[nLen++] = ::getCppuType((Reference<XRenderable>*)0); + + return aTypes; +} + +namespace +{ + class theSmModelUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSmModelUnoTunnelId> {}; +} + +const uno::Sequence< sal_Int8 > & SmModel::getUnoTunnelId() +{ + return theSmModelUnoTunnelId::get().getSeq(); +} + +sal_Int64 SAL_CALL SmModel::getSomething( const uno::Sequence< sal_Int8 >& rId ) + throw(uno::RuntimeException) +{ + if( rId.getLength() == 16 + && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_uIntPtr >(this)); + } + + return SfxBaseModel::getSomething( rId ); +} + +sal_Int16 lcl_AnyToINT16(const uno::Any& rAny) +{ + uno::TypeClass eType = rAny.getValueType().getTypeClass(); + + sal_Int16 nRet = 0; + if( eType == uno::TypeClass_DOUBLE ) + nRet = (sal_Int16)*(double*)rAny.getValue(); + else if( eType == uno::TypeClass_FLOAT ) + nRet = (sal_Int16)*(float*)rAny.getValue(); + else + rAny >>= nRet; + return nRet; +} + +OUString SmModel::getImplementationName(void) throw( uno::RuntimeException ) +{ + return getImplementationName_Static(); +} + + +::rtl::OUString SmModel::getImplementationName_Static() +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.math.FormulaDocument")); +} + +sal_Bool SmModel::supportsService(const OUString& rServiceName) throw( uno::RuntimeException ) +{ + return ( + rServiceName == A2OU("com.sun.star.document.OfficeDocument" ) || + rServiceName == A2OU("com.sun.star.formula.FormulaProperties") + ); +} + +uno::Sequence< OUString > SmModel::getSupportedServiceNames(void) throw( uno::RuntimeException ) +{ + return getSupportedServiceNames_Static(); +} + +uno::Sequence< OUString > SmModel::getSupportedServiceNames_Static(void) +{ + SolarMutexGuard aGuard; + + uno::Sequence< OUString > aRet(2); + OUString* pArray = aRet.getArray(); + pArray[0] = A2OU("com.sun.star.document.OfficeDocument"); + pArray[1] = A2OU("com.sun.star.formula.FormulaProperties"); + return aRet; +} + +void SmModel::_setPropertyValues(const PropertyMapEntry** ppEntries, const Any* pValues) + throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException) +{ + SolarMutexGuard aGuard; + + SmDocShell *pDocSh = static_cast < SmDocShell * > (GetObjectShell()); + + if ( NULL == pDocSh ) + throw UnknownPropertyException(); + + SmFormat aFormat = pDocSh->GetFormat(); + + for (; *ppEntries; ppEntries++, pValues++ ) + { + if ((*ppEntries)->mnAttributes & PropertyAttribute::READONLY) + throw PropertyVetoException(); + + switch ( (*ppEntries)->mnHandle ) + { + case HANDLE_FORMULA: + { + OUString aText; + *pValues >>= aText; + pDocSh->SetText(aText); + } + break; + case HANDLE_FONT_NAME_VARIABLES : + case HANDLE_FONT_NAME_FUNCTIONS : + case HANDLE_FONT_NAME_NUMBERS : + case HANDLE_FONT_NAME_TEXT : + case HANDLE_CUSTOM_FONT_NAME_SERIF : + case HANDLE_CUSTOM_FONT_NAME_SANS : + case HANDLE_CUSTOM_FONT_NAME_FIXED : + { + OUString aText; + *pValues >>= aText; + String sFontName = aText; + if(!sFontName.Len()) + throw IllegalArgumentException(); + + if(aFormat.GetFont((*ppEntries)->mnMemberId).GetName() != sFontName) + { + const SmFace rOld = aFormat.GetFont((*ppEntries)->mnMemberId); + + SmFace aSet( sFontName, rOld.GetSize() ); + aSet.SetBorderWidth( rOld.GetBorderWidth() ); + aSet.SetAlign( ALIGN_BASELINE ); + aFormat.SetFont( (*ppEntries)->mnMemberId, aSet ); + } + } + break; + case HANDLE_CUSTOM_FONT_FIXED_POSTURE: + case HANDLE_CUSTOM_FONT_SANS_POSTURE : + case HANDLE_CUSTOM_FONT_SERIF_POSTURE: + case HANDLE_FONT_VARIABLES_POSTURE : + case HANDLE_FONT_FUNCTIONS_POSTURE : + case HANDLE_FONT_NUMBERS_POSTURE : + case HANDLE_FONT_TEXT_POSTURE : + { + if((*pValues).getValueType() != ::getBooleanCppuType()) + throw IllegalArgumentException(); + bool bVal = *(sal_Bool*)(*pValues).getValue(); + Font aNewFont(aFormat.GetFont((*ppEntries)->mnMemberId)); + aNewFont.SetItalic((bVal) ? ITALIC_NORMAL : ITALIC_NONE); + aFormat.SetFont((*ppEntries)->mnMemberId, aNewFont); + } + break; + case HANDLE_CUSTOM_FONT_FIXED_WEIGHT : + case HANDLE_CUSTOM_FONT_SANS_WEIGHT : + case HANDLE_CUSTOM_FONT_SERIF_WEIGHT : + case HANDLE_FONT_VARIABLES_WEIGHT : + case HANDLE_FONT_FUNCTIONS_WEIGHT : + case HANDLE_FONT_NUMBERS_WEIGHT : + case HANDLE_FONT_TEXT_WEIGHT : + { + if((*pValues).getValueType() != ::getBooleanCppuType()) + throw IllegalArgumentException(); + bool bVal = *(sal_Bool*)(*pValues).getValue(); + Font aNewFont(aFormat.GetFont((*ppEntries)->mnMemberId)); + aNewFont.SetWeight((bVal) ? WEIGHT_BOLD : WEIGHT_NORMAL); + aFormat.SetFont((*ppEntries)->mnMemberId, aNewFont); + } + break; + case HANDLE_BASE_FONT_HEIGHT : + { + // Point! + sal_Int16 nVal = lcl_AnyToINT16(*pValues); + if(nVal < 1) + throw IllegalArgumentException(); + Size aSize = aFormat.GetBaseSize(); + nVal *= 20; + nVal = static_cast < sal_Int16 > ( TWIP_TO_MM100(nVal) ); + aSize.Height() = nVal; + aFormat.SetBaseSize(aSize); + + // apply base size to fonts + const Size aTmp( aFormat.GetBaseSize() ); + for (sal_uInt16 i = FNT_BEGIN; i <= FNT_END; i++) + aFormat.SetFontSize(i, aTmp); + } + break; + case HANDLE_RELATIVE_FONT_HEIGHT_TEXT : + case HANDLE_RELATIVE_FONT_HEIGHT_INDICES : + case HANDLE_RELATIVE_FONT_HEIGHT_FUNCTIONS : + case HANDLE_RELATIVE_FONT_HEIGHT_OPERATORS : + case HANDLE_RELATIVE_FONT_HEIGHT_LIMITS : + { + sal_Int16 nVal = 0; + *pValues >>= nVal; + if(nVal < 1) + throw IllegalArgumentException(); + aFormat.SetRelSize((*ppEntries)->mnMemberId, nVal); + } + break; + + case HANDLE_IS_TEXT_MODE : + { + aFormat.SetTextmode(*(sal_Bool*)(*pValues).getValue()); + } + break; + + case HANDLE_GREEK_CHAR_STYLE : + { + sal_Int16 nVal = 0; + *pValues >>= nVal; + if (nVal < 0 || nVal > 2) + throw IllegalArgumentException(); + aFormat.SetGreekCharStyle( nVal ); + } + break; + + case HANDLE_ALIGNMENT : + { + // SmHorAlign uses the same values as HorizontalAlignment + sal_Int16 nVal = 0; + *pValues >>= nVal; + if(nVal < 0 || nVal > 2) + throw IllegalArgumentException(); + aFormat.SetHorAlign((SmHorAlign)nVal); + } + break; + + case HANDLE_RELATIVE_SPACING : + case HANDLE_RELATIVE_LINE_SPACING : + case HANDLE_RELATIVE_ROOT_SPACING : + case HANDLE_RELATIVE_INDEX_SUPERSCRIPT : + case HANDLE_RELATIVE_INDEX_SUBSCRIPT : + case HANDLE_RELATIVE_FRACTION_NUMERATOR_HEIGHT : + case HANDLE_RELATIVE_FRACTION_DENOMINATOR_DEPTH: + case HANDLE_RELATIVE_FRACTION_BAR_EXCESS_LENGTH: + case HANDLE_RELATIVE_FRACTION_BAR_LINE_WEIGHT : + case HANDLE_RELATIVE_UPPER_LIMIT_DISTANCE : + case HANDLE_RELATIVE_LOWER_LIMIT_DISTANCE : + case HANDLE_RELATIVE_BRACKET_EXCESS_SIZE : + case HANDLE_RELATIVE_BRACKET_DISTANCE : + case HANDLE_RELATIVE_SCALE_BRACKET_EXCESS_SIZE : + case HANDLE_RELATIVE_MATRIX_LINE_SPACING : + case HANDLE_RELATIVE_MATRIX_COLUMN_SPACING : + case HANDLE_RELATIVE_SYMBOL_PRIMARY_HEIGHT : + case HANDLE_RELATIVE_SYMBOL_MINIMUM_HEIGHT : + case HANDLE_RELATIVE_OPERATOR_EXCESS_SIZE : + case HANDLE_RELATIVE_OPERATOR_SPACING : + case HANDLE_LEFT_MARGIN : + case HANDLE_RIGHT_MARGIN : + case HANDLE_TOP_MARGIN : + case HANDLE_BOTTOM_MARGIN : + { + sal_Int16 nVal = 0; + *pValues >>= nVal; + if(nVal < 0) + throw IllegalArgumentException(); + aFormat.SetDistance((*ppEntries)->mnMemberId, nVal); + } + break; + case HANDLE_IS_SCALE_ALL_BRACKETS : + aFormat.SetScaleNormalBrackets(*(sal_Bool*)(*pValues).getValue()); + break; + case HANDLE_PRINTER_NAME: + { + // embedded documents just ignore this property for now + if ( pDocSh->GetCreateMode() != SFX_CREATE_MODE_EMBEDDED ) + { + SfxPrinter *pPrinter = pDocSh->GetPrinter ( ); + if (pPrinter) + { + OUString sPrinterName; + if (*pValues >>= sPrinterName ) + { + if ( sPrinterName.getLength() ) + { + SfxPrinter *pNewPrinter = new SfxPrinter ( pPrinter->GetOptions().Clone(), sPrinterName ); + if (pNewPrinter->IsKnown()) + pDocSh->SetPrinter ( pNewPrinter ); + else + delete pNewPrinter; + } + } + else + throw IllegalArgumentException(); + } + } + } + break; + case HANDLE_PRINTER_SETUP: + { + Sequence < sal_Int8 > aSequence; + if ( *pValues >>= aSequence ) + { + sal_uInt32 nSize = aSequence.getLength(); + SvMemoryStream aStream ( aSequence.getArray(), nSize, STREAM_READ ); + aStream.Seek ( STREAM_SEEK_TO_BEGIN ); + static sal_uInt16 const nRange[] = + { + SID_PRINTSIZE, SID_PRINTSIZE, + SID_PRINTZOOM, SID_PRINTZOOM, + SID_PRINTTITLE, SID_PRINTTITLE, + SID_PRINTTEXT, SID_PRINTTEXT, + SID_PRINTFRAME, SID_PRINTFRAME, + SID_NO_RIGHT_SPACES, SID_NO_RIGHT_SPACES, + 0 + }; + SfxItemSet *pItemSet = new SfxItemSet( pDocSh->GetPool(), nRange ); + SmModule *pp = SM_MOD(); + pp->GetConfig()->ConfigToItemSet(*pItemSet); + SfxPrinter *pPrinter = SfxPrinter::Create ( aStream, pItemSet ); + + pDocSh->SetPrinter( pPrinter ); + } + else + throw IllegalArgumentException(); + } + break; + case HANDLE_SYMBOLS: + { + // this is set + Sequence < SymbolDescriptor > aSequence; + if ( *pValues >>= aSequence ) + { + sal_uInt32 nSize = aSequence.getLength(); + SmModule *pp = SM_MOD(); + SmSymbolManager &rManager = pp->GetSymbolManager(); + SymbolDescriptor *pDescriptor = aSequence.getArray(); + for (sal_uInt32 i = 0; i < nSize ; i++, pDescriptor++) + { + Font aFont; + aFont.SetName ( pDescriptor->sFontName ); + aFont.SetCharSet ( static_cast < rtl_TextEncoding > (pDescriptor->nCharSet) ); + aFont.SetFamily ( static_cast < FontFamily > (pDescriptor->nFamily ) ); + aFont.SetPitch ( static_cast < FontPitch > (pDescriptor->nPitch ) ); + aFont.SetWeight ( static_cast < FontWeight > (pDescriptor->nWeight ) ); + aFont.SetItalic ( static_cast < FontItalic > (pDescriptor->nItalic ) ); + SmSym aSymbol ( pDescriptor->sName, aFont, static_cast < sal_Unicode > (pDescriptor->nCharacter), + pDescriptor->sSymbolSet ); + aSymbol.SetExportName ( pDescriptor->sExportName ); + aSymbol.SetDocSymbol( sal_True ); + rManager.AddOrReplaceSymbol ( aSymbol ); + } + } + else + throw IllegalArgumentException(); + } + break; + // #i33095# Security Options + case HANDLE_LOAD_READONLY : + { + if ( (*pValues).getValueType() != ::getBooleanCppuType() ) + throw IllegalArgumentException(); + sal_Bool bReadonly = sal_False; + if ( *pValues >>= bReadonly ) + pDocSh->SetLoadReadonly( bReadonly ); + break; + } + } + } + + pDocSh->SetFormat( aFormat ); + + // #i67283# since about all of the above changes are likely to change + // the formula size we have to recalculate the vis-area now + pDocSh->SetVisArea( Rectangle( Point(0, 0), pDocSh->GetSize() ) ); +} + +void SmModel::_getPropertyValues( const PropertyMapEntry **ppEntries, Any *pValue ) + throw( UnknownPropertyException, WrappedTargetException ) +{ + SmDocShell *pDocSh = static_cast < SmDocShell * > (GetObjectShell()); + + if ( NULL == pDocSh ) + throw UnknownPropertyException(); + + const SmFormat & aFormat = pDocSh->GetFormat(); + + for (; *ppEntries; ppEntries++, pValue++ ) + { + switch ( (*ppEntries)->mnHandle ) + { + case HANDLE_FORMULA: + *pValue <<= OUString(pDocSh->GetText()); + break; + case HANDLE_FONT_NAME_VARIABLES : + case HANDLE_FONT_NAME_FUNCTIONS : + case HANDLE_FONT_NAME_NUMBERS : + case HANDLE_FONT_NAME_TEXT : + case HANDLE_CUSTOM_FONT_NAME_SERIF : + case HANDLE_CUSTOM_FONT_NAME_SANS : + case HANDLE_CUSTOM_FONT_NAME_FIXED : + { + const SmFace & rFace = aFormat.GetFont((*ppEntries)->mnMemberId); + *pValue <<= OUString(rFace.GetName()); + } + break; + case HANDLE_CUSTOM_FONT_FIXED_POSTURE: + case HANDLE_CUSTOM_FONT_SANS_POSTURE : + case HANDLE_CUSTOM_FONT_SERIF_POSTURE: + case HANDLE_FONT_VARIABLES_POSTURE : + case HANDLE_FONT_FUNCTIONS_POSTURE : + case HANDLE_FONT_NUMBERS_POSTURE : + case HANDLE_FONT_TEXT_POSTURE : + { + const SmFace & rFace = aFormat.GetFont((*ppEntries)->mnMemberId); + bool bVal = IsItalic( rFace ); + (*pValue).setValue(&bVal, *(*ppEntries)->mpType); + } + break; + case HANDLE_CUSTOM_FONT_FIXED_WEIGHT : + case HANDLE_CUSTOM_FONT_SANS_WEIGHT : + case HANDLE_CUSTOM_FONT_SERIF_WEIGHT : + case HANDLE_FONT_VARIABLES_WEIGHT : + case HANDLE_FONT_FUNCTIONS_WEIGHT : + case HANDLE_FONT_NUMBERS_WEIGHT : + case HANDLE_FONT_TEXT_WEIGHT : + { + const SmFace & rFace = aFormat.GetFont((*ppEntries)->mnMemberId); + bool bVal = IsBold( rFace ); // bold? + (*pValue).setValue(&bVal, *(*ppEntries)->mpType); + } + break; + case HANDLE_BASE_FONT_HEIGHT : + { + // Point! + sal_Int16 nVal = static_cast < sal_Int16 > (aFormat.GetBaseSize().Height()); + nVal = static_cast < sal_Int16 > (MM100_TO_TWIP(nVal)); + nVal = (nVal + 10) / 20; + *pValue <<= nVal; + } + break; + case HANDLE_RELATIVE_FONT_HEIGHT_TEXT : + case HANDLE_RELATIVE_FONT_HEIGHT_INDICES : + case HANDLE_RELATIVE_FONT_HEIGHT_FUNCTIONS : + case HANDLE_RELATIVE_FONT_HEIGHT_OPERATORS : + case HANDLE_RELATIVE_FONT_HEIGHT_LIMITS : + *pValue <<= (sal_Int16) aFormat.GetRelSize((*ppEntries)->mnMemberId); + break; + + case HANDLE_IS_TEXT_MODE : + { + sal_Bool bVal = aFormat.IsTextmode(); + (*pValue).setValue(&bVal, ::getBooleanCppuType()); + } + break; + + case HANDLE_GREEK_CHAR_STYLE : + *pValue <<= (sal_Int16)aFormat.GetGreekCharStyle(); + break; + + case HANDLE_ALIGNMENT : + // SmHorAlign uses the same values as HorizontalAlignment + *pValue <<= (sal_Int16)aFormat.GetHorAlign(); + break; + + case HANDLE_RELATIVE_SPACING : + case HANDLE_RELATIVE_LINE_SPACING : + case HANDLE_RELATIVE_ROOT_SPACING : + case HANDLE_RELATIVE_INDEX_SUPERSCRIPT : + case HANDLE_RELATIVE_INDEX_SUBSCRIPT : + case HANDLE_RELATIVE_FRACTION_NUMERATOR_HEIGHT : + case HANDLE_RELATIVE_FRACTION_DENOMINATOR_DEPTH: + case HANDLE_RELATIVE_FRACTION_BAR_EXCESS_LENGTH: + case HANDLE_RELATIVE_FRACTION_BAR_LINE_WEIGHT : + case HANDLE_RELATIVE_UPPER_LIMIT_DISTANCE : + case HANDLE_RELATIVE_LOWER_LIMIT_DISTANCE : + case HANDLE_RELATIVE_BRACKET_EXCESS_SIZE : + case HANDLE_RELATIVE_BRACKET_DISTANCE : + case HANDLE_RELATIVE_SCALE_BRACKET_EXCESS_SIZE : + case HANDLE_RELATIVE_MATRIX_LINE_SPACING : + case HANDLE_RELATIVE_MATRIX_COLUMN_SPACING : + case HANDLE_RELATIVE_SYMBOL_PRIMARY_HEIGHT : + case HANDLE_RELATIVE_SYMBOL_MINIMUM_HEIGHT : + case HANDLE_RELATIVE_OPERATOR_EXCESS_SIZE : + case HANDLE_RELATIVE_OPERATOR_SPACING : + case HANDLE_LEFT_MARGIN : + case HANDLE_RIGHT_MARGIN : + case HANDLE_TOP_MARGIN : + case HANDLE_BOTTOM_MARGIN : + *pValue <<= (sal_Int16)aFormat.GetDistance((*ppEntries)->mnMemberId); + break; + case HANDLE_IS_SCALE_ALL_BRACKETS : + { + sal_Bool bVal = aFormat.IsScaleNormalBrackets(); + (*pValue).setValue(&bVal, ::getBooleanCppuType()); + } + break; + case HANDLE_PRINTER_NAME: + { + SfxPrinter *pPrinter = pDocSh->GetPrinter ( ); + *pValue <<= pPrinter ? OUString ( pPrinter->GetName()) : OUString(); + } + break; + case HANDLE_PRINTER_SETUP: + { + SfxPrinter *pPrinter = pDocSh->GetPrinter (); + if (pPrinter) + { + SvMemoryStream aStream; + pPrinter->Store( aStream ); + aStream.Seek ( STREAM_SEEK_TO_END ); + sal_uInt32 nSize = aStream.Tell(); + aStream.Seek ( STREAM_SEEK_TO_BEGIN ); + Sequence < sal_Int8 > aSequence ( nSize ); + aStream.Read ( aSequence.getArray(), nSize ); + *pValue <<= aSequence; + } + } + break; + case HANDLE_SYMBOLS: + case HANDLE_USED_SYMBOLS: + { + const bool bUsedSymbolsOnly = (*ppEntries)->mnHandle == HANDLE_USED_SYMBOLS; + const std::set< rtl::OUString > &rUsedSymbols = pDocSh->GetUsedSymbols(); + + // this is get + SmModule *pp = SM_MOD(); + const SmSymbolManager &rManager = pp->GetSymbolManager(); + vector < const SmSym * > aVector; + + const SymbolPtrVec_t aSymbols( rManager.GetSymbols() ); + size_t nCount = 0; + for (size_t i = 0; i < aSymbols.size(); ++i) + { + const SmSym * pSymbol = aSymbols[ i ]; + const bool bIsUsedSymbol = rUsedSymbols.find( pSymbol->GetName() ) != rUsedSymbols.end(); + if (pSymbol && !pSymbol->IsPredefined() && + (!bUsedSymbolsOnly || bIsUsedSymbol)) + { + aVector.push_back ( pSymbol ); + nCount++; + } + } + Sequence < SymbolDescriptor > aSequence ( nCount ); + SymbolDescriptor * pDescriptor = aSequence.getArray(); + + vector < const SmSym * >::const_iterator aIter = aVector.begin(), aEnd = aVector.end(); + for(; aIter != aEnd; pDescriptor++, aIter++) + { + pDescriptor->sName = (*aIter)->GetName(); + pDescriptor->sExportName = (*aIter)->GetExportName(); + pDescriptor->sSymbolSet = (*aIter)->GetSymbolSetName(); + pDescriptor->nCharacter = static_cast < sal_Int32 > ((*aIter)->GetCharacter()); + + Font rFont = (*aIter)->GetFace(); + pDescriptor->sFontName = rFont.GetName(); + pDescriptor->nCharSet = sal::static_int_cast< sal_Int16 >(rFont.GetCharSet()); + pDescriptor->nFamily = sal::static_int_cast< sal_Int16 >(rFont.GetFamily()); + pDescriptor->nPitch = sal::static_int_cast< sal_Int16 >(rFont.GetPitch()); + pDescriptor->nWeight = sal::static_int_cast< sal_Int16 >(rFont.GetWeight()); + pDescriptor->nItalic = sal::static_int_cast< sal_Int16 >(rFont.GetItalic()); + } + *pValue <<= aSequence; + } + break; + case HANDLE_BASIC_LIBRARIES: + *pValue <<= pDocSh->GetBasicContainer(); + break; + case HANDLE_DIALOG_LIBRARIES: + *pValue <<= pDocSh->GetDialogContainer(); + break; + case HANDLE_RUNTIME_UID: + *pValue <<= getRuntimeUID(); + break; + // #i33095# Security Options + case HANDLE_LOAD_READONLY : + { + *pValue <<= pDocSh->IsLoadReadonly(); + break; + } + // #i972# + case HANDLE_BASELINE: + { + if ( !pDocSh->pTree ) + pDocSh->Parse(); + if ( pDocSh->pTree ) + { + if ( !pDocSh->IsFormulaArranged() ) + pDocSh->ArrangeFormula(); + + *pValue <<= static_cast<sal_Int32>( pDocSh->pTree->GetFormulaBaseline() ); + } + } + break; + } + } +} + +////////////////////////////////////////////////////////////////////// + +sal_Int32 SAL_CALL SmModel::getRendererCount( + const uno::Any& /*rSelection*/, + const uno::Sequence< beans::PropertyValue >& /*xOptions*/ ) + throw (IllegalArgumentException, RuntimeException) +{ + SolarMutexGuard aGuard; + return 1; +} + + +static Size lcl_GuessPaperSize() +{ + Size aRes; + Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() ); + LocaleDataWrapper aLocWrp( xMgr, AllSettings().GetLocale() ); + if( MEASURE_METRIC == aLocWrp.getMeasurementSystemEnum() ) + { + // in 100th mm + PaperInfo aInfo( PAPER_A4 ); + aRes.Width() = aInfo.getWidth(); + aRes.Height() = aInfo.getHeight(); + } + else + { + // in 100th mm + PaperInfo aInfo( PAPER_LETTER ); + aRes.Width() = aInfo.getWidth(); + aRes.Height() = aInfo.getHeight(); + } + return aRes; +} + +uno::Sequence< beans::PropertyValue > SAL_CALL SmModel::getRenderer( + sal_Int32 nRenderer, + const uno::Any& /*rSelection*/, + const uno::Sequence< beans::PropertyValue >& /*rxOptions*/ ) + throw (IllegalArgumentException, RuntimeException) +{ + SolarMutexGuard aGuard; + + if (0 != nRenderer) + throw IllegalArgumentException(); + + SmDocShell *pDocSh = static_cast < SmDocShell * >( GetObjectShell() ); + if (!pDocSh) + throw RuntimeException(); + + SmPrinterAccess aPrinterAccess( *pDocSh ); + Printer *pPrinter = aPrinterAccess.GetPrinter(); + Size aPrtPaperSize ( pPrinter->GetPaperSize() ); + + // if paper size is 0 (usually if no 'real' printer is found), + // guess the paper size + if (aPrtPaperSize.Height() == 0 || aPrtPaperSize.Width() == 0) + aPrtPaperSize = lcl_GuessPaperSize(); + awt::Size aPageSize( aPrtPaperSize.Width(), aPrtPaperSize.Height() ); + + uno::Sequence< beans::PropertyValue > aRenderer(1); + PropertyValue &rValue = aRenderer.getArray()[0]; + rValue.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ); + rValue.Value <<= aPageSize; + + if (!m_pPrintUIOptions) + m_pPrintUIOptions = new SmPrintUIOptions(); + m_pPrintUIOptions->appendPrintUIOptions( aRenderer ); + + return aRenderer; +} + +void SAL_CALL SmModel::render( + sal_Int32 nRenderer, + const uno::Any& rSelection, + const uno::Sequence< beans::PropertyValue >& rxOptions ) + throw (IllegalArgumentException, RuntimeException) +{ + SolarMutexGuard aGuard; + + if (0 != nRenderer) + throw IllegalArgumentException(); + + SmDocShell *pDocSh = static_cast < SmDocShell * >( GetObjectShell() ); + if (!pDocSh) + throw RuntimeException(); + + // get device to be rendered in + uno::Reference< awt::XDevice > xRenderDevice; + for (sal_Int32 i = 0, nCount = rxOptions.getLength(); i < nCount; ++i) + { + if( rxOptions[i].Name == OUString( RTL_CONSTASCII_USTRINGPARAM( "RenderDevice" ) ) ) + rxOptions[i].Value >>= xRenderDevice; + } + + if (xRenderDevice.is()) + { + VCLXDevice* pDevice = VCLXDevice::GetImplementation( xRenderDevice ); + OutputDevice* pOut = pDevice ? pDevice->GetOutputDevice() : NULL; + + if (!pOut) + throw RuntimeException(); + + pOut->SetMapMode( MAP_100TH_MM ); + + uno::Reference< frame::XModel > xModel; + rSelection >>= xModel; + if (xModel == pDocSh->GetModel()) + { + //!! when called via API we may not have an active view + //!! thus we go and look for a view that can be used. + const TypeId aTypeId = TYPE( SmViewShell ); + SfxViewShell* pViewSh = SfxViewShell::GetFirst( &aTypeId, sal_False /* search non-visible views as well*/ ); + while (pViewSh && pViewSh->GetObjectShell() != pDocSh) + pViewSh = SfxViewShell::GetNext( *pViewSh, &aTypeId, sal_False /* search non-visible views as well*/ ); + SmViewShell *pView = PTR_CAST( SmViewShell, pViewSh ); + OSL_ENSURE( pView, "SmModel::render : no SmViewShell found" ); + + if (pView) + { + SmPrinterAccess aPrinterAccess( *pDocSh ); + Printer *pPrinter = aPrinterAccess.GetPrinter(); + + Size aPrtPaperSize ( pPrinter->GetPaperSize() ); + Size aOutputSize ( pPrinter->GetOutputSize() ); + Point aPrtPageOffset( pPrinter->GetPageOffset() ); + + // no real printer ?? + if (aPrtPaperSize.Height() == 0 || aPrtPaperSize.Width() == 0) + { + aPrtPaperSize = lcl_GuessPaperSize(); + // factors from Windows DIN A4 + aOutputSize = Size( (long)(aPrtPaperSize.Width() * 0.941), + (long)(aPrtPaperSize.Height() * 0.961)); + aPrtPageOffset = Point( (long)(aPrtPaperSize.Width() * 0.0250), + (long)(aPrtPaperSize.Height() * 0.0214)); + } + Point aZeroPoint; + Rectangle OutputRect( aZeroPoint, aOutputSize ); + + + // set minimum top and bottom border + if (aPrtPageOffset.Y() < 2000) + OutputRect.Top() += 2000 - aPrtPageOffset.Y(); + if ((aPrtPaperSize.Height() - (aPrtPageOffset.Y() + OutputRect.Bottom())) < 2000) + OutputRect.Bottom() -= 2000 - (aPrtPaperSize.Height() - + (aPrtPageOffset.Y() + OutputRect.Bottom())); + + // set minimum left and right border + if (aPrtPageOffset.X() < 2500) + OutputRect.Left() += 2500 - aPrtPageOffset.X(); + if ((aPrtPaperSize.Width() - (aPrtPageOffset.X() + OutputRect.Right())) < 1500) + OutputRect.Right() -= 1500 - (aPrtPaperSize.Width() - + (aPrtPageOffset.X() + OutputRect.Right())); + + if (!m_pPrintUIOptions) + m_pPrintUIOptions = new SmPrintUIOptions(); + m_pPrintUIOptions->processProperties( rxOptions ); + + pView->Impl_Print( *pOut, *m_pPrintUIOptions, Rectangle( OutputRect ), Point() ); + + // release SmPrintUIOptions when everything is done. + // That way, when SmPrintUIOptions is needed again it will read the latest configuration settings in its c-tor. + if (m_pPrintUIOptions->getBoolValue( "IsLastPage", sal_False )) + { + delete m_pPrintUIOptions; m_pPrintUIOptions = 0; + } + } + } + } +} + +void SAL_CALL SmModel::setParent( const uno::Reference< uno::XInterface >& xParent) + throw( lang::NoSupportException, uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + SfxBaseModel::setParent( xParent ); + uno::Reference< lang::XUnoTunnel > xParentTunnel( xParent, uno::UNO_QUERY ); + if ( xParentTunnel.is() ) + { + SvGlobalName aSfxIdent( SFX_GLOBAL_CLASSID ); + SfxObjectShell* pDoc = reinterpret_cast<SfxObjectShell *>(xParentTunnel->getSomething( + uno::Sequence< sal_Int8 >( aSfxIdent.GetByteSequence() ) ) ); + if ( pDoc ) + GetObjectShell()->OnDocumentPrinterChanged( pDoc->GetDocumentPrinter() ); + } +} + +void SmModel::writeFormulaOoxml( ::sax_fastparser::FSHelperPtr m_pSerializer, oox::core::OoxmlVersion version ) +{ + static_cast< SmDocShell* >( GetObjectShell())->writeFormulaOoxml( m_pSerializer, version ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/utility.cxx b/starmath/source/utility.cxx new file mode 100644 index 000000000000..a5e4cc3d6ccd --- /dev/null +++ b/starmath/source/utility.cxx @@ -0,0 +1,378 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <sfx2/app.hxx> +#include <vcl/virdev.hxx> +#include <tools/string.hxx> +#include <tools/tenccvt.hxx> +#include <osl/thread.h> + +#include <tools/stream.hxx> + +#include "starmath.hrc" + +#include "utility.hxx" +#include "dialog.hxx" +#include "view.hxx" +#include "smdll.hxx" + + +//////////////////////////////////////////////////////////// + +// return pointer to active SmViewShell, if this is not possible +// return 0 instead. +//!! Since this method is based on the current focus it is somewhat +//!! unreliable and may return unexpected 0 pointers! +SmViewShell * SmGetActiveView() +{ + SfxViewShell *pView = SfxViewShell::Current(); + return PTR_CAST(SmViewShell, pView); +} + + +//////////////////////////////////////////////////////////// + + +/**************************************************************************/ + +SmPickList::SmPickList(sal_uInt16 nInitSize, sal_uInt16 nMaxSize) : + SfxPtrArr((sal_uInt8) nInitSize, 1) +{ + nSize = nMaxSize; +} + + +SmPickList::~SmPickList() +{ + Clear(); +} + + +SmPickList& SmPickList::operator=(const SmPickList& rList) +{ + sal_uInt16 nPos; + + Clear(); + nSize = rList.nSize; + for (nPos = 0; nPos < rList.Count(); nPos++) + InsertPtr(nPos, CreateItem(rList.Get(nPos))); + + return *this; +} + + +void SmPickList::Insert(const void *pItem) +{ + Remove(pItem); + InsertPtr(0, CreateItem(pItem)); + + if (Count() > nSize) + { + DestroyItem(GetPtr(nSize)); + RemovePtr(nSize, 1); + } +} + + +void SmPickList::Update(const void *pItem, const void *pNewItem) +{ + sal_uInt16 nPos; + + for (nPos = 0; nPos < Count(); nPos++) + if (CompareItem(GetPtr(nPos), pItem)) + { + DestroyItem(GetPtr(nPos)); + GetPtr(nPos) = CreateItem(pNewItem); + break; + } +} + +void SmPickList::Remove(const void *pItem) +{ + sal_uInt16 nPos; + + for (nPos = 0; nPos < Count(); nPos++) + if (CompareItem(GetPtr(nPos), pItem)) + { + DestroyItem(GetPtr(nPos)); + RemovePtr(nPos, 1); + break; + } +} + +void SmPickList::Clear() +{ + sal_uInt16 nPos; + + for (nPos = 0; nPos < Count(); nPos++) + DestroyItem(GetPtr(nPos)); + + RemovePtr(0, Count()); +} + + +/**************************************************************************/ + +void * SmFontPickList::CreateItem(const String& /*rString*/) +{ + return new Font(); +} + +void * SmFontPickList::CreateItem(const void *pItem) +{ + return new Font(*((Font *) pItem)); +} + +void SmFontPickList::DestroyItem(void *pItem) +{ + delete (Font *)pItem; +} + +bool SmFontPickList::CompareItem(const void *pFirstItem, const void *pSecondItem) const +{ + Font *pFirstFont, *pSecondFont; + + pFirstFont = (Font *)pFirstItem; + pSecondFont = (Font *)pSecondItem; + + if (pFirstFont->GetName() == pSecondFont->GetName()) + if ((pFirstFont->GetFamily() == pSecondFont->GetFamily()) && + (pFirstFont->GetCharSet() == pSecondFont->GetCharSet()) && + (pFirstFont->GetWeight() == pSecondFont->GetWeight()) && + (pFirstFont->GetItalic() == pSecondFont->GetItalic())) + return (true); + + return false; +} + +String SmFontPickList::GetStringItem(void *pItem) +{ + Font *pFont; + String aString; + const sal_Char *pDelim = ", "; + + pFont = (Font *)pItem; + + aString = pFont->GetName(); + + if (IsItalic( *pFont )) + { + aString.AppendAscii( pDelim ); + aString += String(SmResId(RID_FONTITALIC)); + } + if (IsBold( *pFont )) + { + aString.AppendAscii( pDelim ); + aString += String(SmResId(RID_FONTBOLD)); + } + + return (aString); +} + +void SmFontPickList::Insert(const Font &rFont) +{ + SmPickList::Insert((void *)&rFont); +} + +void SmFontPickList::Update(const Font &rFont, const Font &rNewFont) +{ + SmPickList::Update((void *)&rFont, (void *)&rNewFont); +} + +void SmFontPickList::Remove(const Font &rFont) +{ + SmPickList::Remove((void *)&rFont); +} + + +void SmFontPickList::ReadFrom(const SmFontDialog& rDialog) +{ + Insert(rDialog.GetFont()); +} + +void SmFontPickList::WriteTo(SmFontDialog& rDialog) const +{ + rDialog.SetFont(Get()); +} + + +/**************************************************************************/ + + +IMPL_LINK( SmFontPickListBox, SelectHdl, ListBox *, /*pListBox*/ ) +{ + sal_uInt16 nPos; + String aString; + + nPos = GetSelectEntryPos(); + + if (nPos != 0) + { + SmFontPickList::Insert(Get(nPos)); + aString = GetEntry(nPos); + RemoveEntry(nPos); + InsertEntry(aString, 0); + } + + SelectEntryPos(0); + + return 0; +} + + +SmFontPickListBox::SmFontPickListBox(Window* pParent, const ResId& rResId, sal_uInt16 nMax) : + SmFontPickList(nMax, nMax), + ListBox(pParent, rResId) +{ + SetSelectHdl(LINK(this, SmFontPickListBox, SelectHdl)); +} + + +SmFontPickListBox& SmFontPickListBox::operator=(const SmFontPickList& rList) +{ + sal_uInt16 nPos; + + *(SmFontPickList *)this = rList; + + for (nPos = 0; nPos < Count(); nPos++) + InsertEntry(GetStringItem(GetPtr(nPos)), nPos); + + if (Count() > 0) + SelectEntry(GetStringItem(GetPtr(0))); + + return *this; +} + +void SmFontPickListBox::Insert(const Font &rFont) +{ + SmFontPickList::Insert(rFont); + + RemoveEntry(GetStringItem(GetPtr(0))); + InsertEntry(GetStringItem(GetPtr(0)), 0); + SelectEntry(GetStringItem(GetPtr(0))); + + while (GetEntryCount() > nSize) + RemoveEntry(GetEntryCount() - 1); + + return; +} + + +void SmFontPickListBox::Update(const Font &rFont, const Font &rNewFont) +{ + SmFontPickList::Update(rFont, rNewFont); + + return; +} + + +void SmFontPickListBox::Remove(const Font &rFont) +{ + SmFontPickList::Remove(rFont); + + return; +} + +//////////////////////////////////////// + +bool IsItalic( const Font &rFont ) +{ + FontItalic eItalic = rFont.GetItalic(); + // the code below leaves only _NONE and _DONTKNOW as not italic + return eItalic == ITALIC_OBLIQUE || eItalic == ITALIC_NORMAL; +} + + +bool IsBold( const Font &rFont ) +{ + FontWeight eWeight = rFont.GetWeight(); + return eWeight != WEIGHT_DONTKNOW && eWeight > WEIGHT_NORMAL; +} + + +void SmFace::Impl_Init() +{ + SetSize( GetSize() ); + SetTransparent( true ); + SetAlign( ALIGN_BASELINE ); + SetColor( COL_AUTO ); +} + +void SmFace::SetSize(const Size& rSize) +{ + Size aSize (rSize); + + // check the requested size against minimum value + static int const nMinVal = SmPtsTo100th_mm(2); + + if (aSize.Height() < nMinVal) + aSize.Height() = nMinVal; + + //! we don't force a maximum value here because this may prevent eg the + //! parentheses in "left ( ... right )" from matching up with large + //! bodies (eg stack{...} with many entries). + //! Of course this is holds only if characters are used and not polygons. + + Font::SetSize(aSize); +} + + +long SmFace::GetBorderWidth() const +{ + if (nBorderWidth < 0) + return GetDefaultBorderWidth(); + else + return nBorderWidth; +} + +SmFace & SmFace::operator = (const SmFace &rFace) +{ + Font::operator = (rFace); + nBorderWidth = -1; + return *this; +} + + +SmFace & operator *= (SmFace &rFace, const Fraction &rFrac) + // scales the width and height of 'rFace' by 'rFrac' and returns a + // reference to 'rFace'. + // It's main use is to make scaling fonts look easier. +{ const Size &rFaceSize = rFace.GetSize(); + + rFace.SetSize(Size(Fraction(rFaceSize.Width()) *= rFrac, + Fraction(rFaceSize.Height()) *= rFrac)); + return rFace; +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/view.cxx b/starmath/source/view.cxx new file mode 100644 index 000000000000..ffd5413eced8 --- /dev/null +++ b/starmath/source/view.cxx @@ -0,0 +1,2124 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_starmath.hxx" + + +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleEventObject.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/container/XChild.hpp> + +#include <comphelper/processfactory.hxx> +#include <comphelper/storagehelper.hxx> +#include <rtl/logfile.hxx> +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/docinsert.hxx> +#include <sfx2/filedlghelper.hxx> +#include <sfx2/msg.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/request.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/itemset.hxx> +#include <svl/poolitem.hxx> +#include <svl/ptitem.hxx> +#include <svl/stritem.hxx> +#include <svtools/transfer.hxx> +#include <svtools/miscopt.hxx> +#include <svl/undo.hxx> +#include <svl/whiter.hxx> +#include <svx/dialogs.hrc> +#include <editeng/editeng.hxx> +#include <svx/svxdlg.hxx> +#include <svx/zoomitem.hxx> +#include <vcl/decoview.hxx> +#include <vcl/menu.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/wrkwin.hxx> +#include <fstream> + +#include "unomodel.hxx" +#include "view.hxx" +#include "config.hxx" +#include "dialog.hxx" +#include "document.hxx" +#include "starmath.hrc" +#include "toolbox.hxx" +#include "mathmlimport.hxx" +#include "cursor.hxx" +#include "accessibility.hxx" + +#define MINWIDTH 200 +#define MINHEIGHT 200 +#define MINSPLIT 40 +#define SPLITTERWIDTH 2 + +#define MINZOOM 25 +#define MAXZOOM 800 + +#define SmViewShell +#include "smslots.hxx" + +using namespace com::sun::star; +using namespace com::sun::star::accessibility; +using namespace com::sun::star::uno; + +////////////////////////////////////////////////////////////////////// + +SmGraphicWindow::SmGraphicWindow(SmViewShell* pShell): + ScrollableWindow(&pShell->GetViewFrame()->GetWindow(), 0), + pAccessible(0), + pViewShell(pShell), + nZoom(100) +{ + // docking windows are usually hidden (often already done in the + // resource) and will be shown by the sfx framework. + Hide(); + + const Fraction aFraction (1,1); + SetMapMode( MapMode(MAP_100TH_MM, Point(), aFraction, aFraction)); + + ApplyColorConfigValues( SM_MOD()->GetColorConfig() ); + + SetTotalSize(); + + SetHelpId(HID_SMA_WIN_DOCUMENT); + SetUniqueId(HID_SMA_WIN_DOCUMENT); + + ShowLine(false); + CaretBlinkInit(); +} + +SmGraphicWindow::~SmGraphicWindow() +{ + if (pAccessible) + pAccessible->ClearWin(); // make Accessible defunctional + // Note: memory for pAccessible will be freed when the reference + // xAccessible is released. + CaretBlinkStop(); +} + +void SmGraphicWindow::StateChanged( StateChangedType eType ) +{ + if ( eType == STATE_CHANGE_INITSHOW ) + Show(); + ScrollableWindow::StateChanged( eType ); +} + + +void SmGraphicWindow::ApplyColorConfigValues( const svtools::ColorConfig &rColorCfg ) +{ + // Note: SetTextColor not necessary since the nodes that + // get painted have the color information. +#if OSL_DEBUG_LEVEL > 1 +// ColorData nVal = rColorCfg.GetColorValue(svtools::DOCCOLOR).nColor; +#endif + SetBackground( Color( (ColorData) rColorCfg.GetColorValue(svtools::DOCCOLOR).nColor ) ); + Invalidate(); +} + + +void SmGraphicWindow::DataChanged( const DataChangedEvent& rEvt ) +{ + ApplyColorConfigValues( SM_MOD()->GetColorConfig() ); + + ScrollableWindow::DataChanged( rEvt ); +} + + +void SmGraphicWindow::MouseButtonDown(const MouseEvent& rMEvt) +{ + ScrollableWindow::MouseButtonDown(rMEvt); + + GrabFocus(); + + // + // set formula-cursor and selection of edit window according to the + // position clicked at + // + OSL_ENSURE(rMEvt.GetClicks() > 0, "Sm : 0 clicks"); + if ( rMEvt.IsLeft() ) + { + // get click position relativ to formula + Point aPos (PixelToLogic(rMEvt.GetPosPixel()) + - GetFormulaDrawPos()); + + const SmNode *pTree = pViewShell->GetDoc()->GetFormulaTree(); + if (!pTree) + return; + + if (IsInlineEditEnabled()) { + // if it was clicked inside the formula then get the appropriate node + if (pTree->OrientedDist(aPos) <= 0) + pViewShell->GetDoc()->GetCursor().MoveTo(this, aPos, !rMEvt.IsShift()); + return; + } + const SmNode *pNode = 0; + // if it was clicked inside the formula then get the appropriate node + if (pTree->OrientedDist(aPos) <= 0) + pNode = pTree->FindRectClosestTo(aPos); + + if (pNode) + { SmEditWindow *pEdit = pViewShell->GetEditWindow(); + if (!pEdit) + return; + const SmToken aToken (pNode->GetToken()); + + // set selection to the beginning of the token + ESelection aSel (aToken.nRow - 1, aToken.nCol - 1); + + if (rMEvt.GetClicks() != 1 || aToken.eType == TPLACE) + aSel.nEndPos = aSel.nEndPos + sal::static_int_cast< sal_uInt16 >(aToken.aText.Len()); + + pEdit->SetSelection(aSel); + SetCursor(pNode); + + // allow for immediate editing and + //! implicitly synchronize the cursor position mark in this window + pEdit->GrabFocus(); + } + } +} + +bool SmGraphicWindow::IsInlineEditEnabled() const +{ + return pViewShell->IsInlineEditEnabled(); +} + +void SmGraphicWindow::GetFocus() +{ + if (!IsInlineEditEnabled()) + return; + if (pViewShell->GetEditWindow()) + pViewShell->GetEditWindow()->Flush(); + //Let view shell know what insertions should be done in visual editor + pViewShell->SetInsertIntoEditWindow(false); + SetIsCursorVisible(true); + ShowLine(true); + CaretBlinkStart(); + RepaintViewShellDoc(); +} + +void SmGraphicWindow::LoseFocus() +{ + ScrollableWindow::LoseFocus(); + if (xAccessible.is()) + { + uno::Any aOldValue, aNewValue; + aOldValue <<= AccessibleStateType::FOCUSED; + // aNewValue remains empty + pAccessible->LaunchEvent( AccessibleEventId::STATE_CHANGED, + aOldValue, aNewValue ); + } + if (!IsInlineEditEnabled()) + return; + SetIsCursorVisible(false); + ShowLine(false); + CaretBlinkStop(); + RepaintViewShellDoc(); +} + +void SmGraphicWindow::RepaintViewShellDoc() +{ + SmDocShell &rDoc = *pViewShell->GetDoc(); + rDoc.Repaint(); +} + +IMPL_LINK( SmGraphicWindow, CaretBlinkTimerHdl, AutoTimer *, EMPTYARG ) +{ + if (IsCursorVisible()) + SetIsCursorVisible(false); + else + SetIsCursorVisible(true); + + RepaintViewShellDoc(); + + return 0; +} + +void SmGraphicWindow::CaretBlinkInit() +{ + aCaretBlinkTimer.SetTimeoutHdl(LINK(this, SmGraphicWindow, CaretBlinkTimerHdl)); + aCaretBlinkTimer.SetTimeout( ScrollableWindow::GetSettings().GetStyleSettings().GetCursorBlinkTime() ); +} + +void SmGraphicWindow::CaretBlinkStart() +{ + if (!IsInlineEditEnabled()) + return; + if ( aCaretBlinkTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME ) + aCaretBlinkTimer.Start(); +} + +void SmGraphicWindow::CaretBlinkStop() +{ + if (!IsInlineEditEnabled()) + return; + aCaretBlinkTimer.Stop(); +} + +void SmGraphicWindow::ShowCursor(bool bShow) + // shows or hides the formula-cursor depending on 'bShow' is true or not +{ + if (IsInlineEditEnabled()) + return; + + bool bInvert = bShow != IsCursorVisible(); + + if (bInvert) + InvertTracking(aCursorRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW); + + SetIsCursorVisible(bShow); +} + +void SmGraphicWindow::ShowLine(bool bShow) +{ + if (!IsInlineEditEnabled()) + return; + + bIsLineVisible = bShow; +} + +void SmGraphicWindow::SetCursor(const SmNode *pNode) +{ + if (IsInlineEditEnabled()) + return; + + const SmNode *pTree = pViewShell->GetDoc()->GetFormulaTree(); + + // get appropriate rectangle + Point aOffset (pNode->GetTopLeft() - pTree->GetTopLeft()), + aTLPos (GetFormulaDrawPos() + aOffset); + aTLPos.X() -= pNode->GetItalicLeftSpace(); + Size aSize (pNode->GetItalicSize()); + Point aBRPos (aTLPos.X() + aSize.Width(), aTLPos.Y() + aSize.Height()); + + SetCursor(Rectangle(aTLPos, aSize)); +} + +void SmGraphicWindow::SetCursor(const Rectangle &rRect) + // sets cursor to new position (rectangle) 'rRect'. + // The old cursor will be removed, and the new one will be shown if + // that is activated in the ConfigItem +{ + if (IsInlineEditEnabled()) + return; + + SmModule *pp = SM_MOD(); + + if (IsCursorVisible()) + ShowCursor(false); // clean up remainings of old cursor + aCursorRect = rRect; + if (pp->GetConfig()->IsShowFormulaCursor()) + ShowCursor(true); // draw new cursor +} + +const SmNode * SmGraphicWindow::SetCursorPos(sal_uInt16 nRow, sal_uInt16 nCol) + // looks for a VISIBLE node in the formula tree with it's token at + // (or around) the position 'nRow', 'nCol' in the edit window + // (row and column numbering starts with 1 there!). + // If there is such a node the formula-cursor is set to cover that nodes + // rectangle. If not the formula-cursor will be hidden. + // In any case the search result is being returned. +{ + if (IsInlineEditEnabled()) + return NULL; + + // find visible node with token at nRow, nCol + const SmNode *pTree = pViewShell->GetDoc()->GetFormulaTree(), + *pNode = 0; + if (pTree) + pNode = pTree->FindTokenAt(nRow, nCol); + + if (pNode) + SetCursor(pNode); + else + ShowCursor(false); + + return pNode; +} + +void SmGraphicWindow::Paint(const Rectangle&) +{ + OSL_ENSURE(pViewShell, "Sm : NULL pointer"); + + SmDocShell &rDoc = *pViewShell->GetDoc(); + Point aPoint; + + rDoc.DrawFormula(*this, aPoint, true); //! modifies aPoint to be the topleft + //! corner of the formula + SetFormulaDrawPos(aPoint); + if(IsInlineEditEnabled()) { + //Draw cursor if any... + if(pViewShell->GetDoc()->HasCursor() && IsLineVisible()) + pViewShell->GetDoc()->GetCursor().Draw(*this, aPoint, IsCursorVisible()); + } else { + SetIsCursorVisible(false); // (old) cursor must be drawn again + + const SmEditWindow *pEdit = pViewShell->GetEditWindow(); + if (pEdit) + { // get new position for formula-cursor (for possible altered formula) + sal_uInt16 nRow, nCol; + SmGetLeftSelectionPart(pEdit->GetSelection(), nRow, nCol); + nRow++; + nCol++; + const SmNode *pFound = SetCursorPos(nRow, nCol); + + SmModule *pp = SM_MOD(); + if (pFound && pp->GetConfig()->IsShowFormulaCursor()) + ShowCursor(true); + } + } +} + + +void SmGraphicWindow::SetTotalSize () +{ + SmDocShell &rDoc = *pViewShell->GetDoc(); + const Size aTmp( PixelToLogic( LogicToPixel( rDoc.GetSize() ))); + if ( aTmp != ScrollableWindow::GetTotalSize() ) + ScrollableWindow::SetTotalSize( aTmp ); +} + +void SmGraphicWindow::KeyInput(const KeyEvent& rKEvt) +{ + if (!IsInlineEditEnabled()) { + if (! (GetView() && GetView()->KeyInput(rKEvt)) ) + ScrollableWindow::KeyInput(rKEvt); + return; + } + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + SmCursor& rCursor = pViewShell->GetDoc()->GetCursor(); + switch(nCode) + { + case KEY_LEFT: + { + rCursor.Move(this, MoveLeft, !rKEvt.GetKeyCode().IsShift()); + }break; + case KEY_RIGHT: + { + rCursor.Move(this, MoveRight, !rKEvt.GetKeyCode().IsShift()); + }break; + case KEY_UP: + { + rCursor.Move(this, MoveUp, !rKEvt.GetKeyCode().IsShift()); + }break; + case KEY_DOWN: + { + rCursor.Move(this, MoveDown, !rKEvt.GetKeyCode().IsShift()); + }break; + case KEY_RETURN: + { + if(!rKEvt.GetKeyCode().IsShift()) + rCursor.InsertRow(); +#ifdef DEBUG_ENABLE_DUMPASDOT + else { + SmNode *pTree = (SmNode*)pViewShell->GetDoc()->GetFormulaTree(); + std::fstream file("/tmp/smath-dump.gv", std::fstream::out); + String label(pViewShell->GetDoc()->GetText()); + pTree->DumpAsDot(file, &label); + file.close(); + } +#endif /* DEBUG_ENABLE_DUMPASDOT */ + }break; + case KEY_DELETE: + { + if(!rCursor.HasSelection()){ + rCursor.Move(this, nCode == KEY_DELETE ? MoveRight : MoveLeft, false); + if(rCursor.HasComplexSelection()) break; + } + rCursor.Delete(); + }break; + case KEY_BACKSPACE: + { + rCursor.DeletePrev(this); + }break; + case KEY_ADD: + rCursor.InsertElement(PlusElement); + break; + case KEY_SUBTRACT: + if(rKEvt.GetKeyCode().IsShift()) + rCursor.InsertSubSup(RSUB); + else + rCursor.InsertElement(MinusElement); + break; + case KEY_MULTIPLY: + rCursor.InsertElement(CDotElement); + break; + case KEY_DIVIDE: + rCursor.InsertFraction(); + break; + case KEY_LESS: + rCursor.InsertElement(LessThanElement); + break; + case KEY_GREATER: + rCursor.InsertElement(GreaterThanElement); + break; + case KEY_EQUAL: + rCursor.InsertElement(EqualElement); + break; + case KEY_COPY: + rCursor.Copy(); + break; + case KEY_CUT: + rCursor.Cut(); + break; + case KEY_PASTE: + rCursor.Paste(); + break; + default: + { + sal_Unicode code = rKEvt.GetCharCode(); + if(code == ' ') { + rCursor.InsertElement(BlankElement); + }else if(code == 'c' && rKEvt.GetKeyCode().IsMod1()) { + rCursor.Copy(); + }else if(code == 'x' && rKEvt.GetKeyCode().IsMod1()) { + rCursor.Cut(); + }else if(code == 'v' && rKEvt.GetKeyCode().IsMod1()) { + rCursor.Paste(); + }else if(code == '^') { + rCursor.InsertSubSup(RSUP); + }else if(code == '(') { + rCursor.InsertBrackets(RoundBrackets); + }else if(code == '[') { + rCursor.InsertBrackets(SquareBrackets); + }else if(code == '{') { + rCursor.InsertBrackets(CurlyBrackets); + }else if(code == '!') { + rCursor.InsertElement(FactorialElement); + }else if(code == '%') { + rCursor.InsertElement(PercentElement); + }else{ + if(code != 0){ + rCursor.InsertText(code); + }else if (! (GetView() && GetView()->KeyInput(rKEvt)) ) + ScrollableWindow::KeyInput(rKEvt); + } + } + } + CaretBlinkStop(); + CaretBlinkStart(); + SetIsCursorVisible(true); + RepaintViewShellDoc(); +} + + +void SmGraphicWindow::Command(const CommandEvent& rCEvt) +{ + bool bCallBase = true; + if ( !pViewShell->GetViewFrame()->GetFrame().IsInPlace() ) + { + switch ( rCEvt.GetCommand() ) + { + case COMMAND_CONTEXTMENU: + { + GetParent()->ToTop(); + SmResId aResId( RID_VIEWMENU ); + PopupMenu* pPopupMenu = new PopupMenu(aResId); + pPopupMenu->SetSelectHdl(LINK(this, SmGraphicWindow, MenuSelectHdl)); + Point aPos(5, 5); + if (rCEvt.IsMouseEvent()) + aPos = rCEvt.GetMousePosPixel(); + OSL_ENSURE( pViewShell, "view shell missing" ); + + // added for replaceability of context menus + pViewShell->GetViewFrame()->GetBindings().GetDispatcher() + ->ExecutePopup( aResId, this, &aPos ); + + delete pPopupMenu; + bCallBase = false; + } + break; + + case COMMAND_WHEEL: + { + const CommandWheelData* pWData = rCEvt.GetWheelData(); + if ( pWData && COMMAND_WHEEL_ZOOM == pWData->GetMode() ) + { + sal_uInt16 nTmpZoom = GetZoom(); + if( 0L > pWData->GetDelta() ) + nTmpZoom -= 10; + else + nTmpZoom += 10; + SetZoom( nTmpZoom ); + bCallBase = false; + } + } + break; + } + } + if ( bCallBase ) + ScrollableWindow::Command (rCEvt); +} + + +IMPL_LINK_INLINE_START( SmGraphicWindow, MenuSelectHdl, Menu *, pMenu ) +{ + SmViewShell *pViewSh = GetView(); + if (pViewSh) + pViewSh->GetViewFrame()->GetDispatcher()->Execute( pMenu->GetCurItemId() ); + return 0; +} +IMPL_LINK_INLINE_END( SmGraphicWindow, MenuSelectHdl, Menu *, pMenu ) + + +void SmGraphicWindow::SetZoom(sal_uInt16 Factor) +{ + nZoom = Min(Max((sal_uInt16) Factor, (sal_uInt16) MINZOOM), (sal_uInt16) MAXZOOM); + Fraction aFraction (nZoom, 100); + SetMapMode( MapMode(MAP_100TH_MM, Point(), aFraction, aFraction) ); + SetTotalSize(); + SmViewShell *pViewSh = GetView(); + if (pViewSh) + pViewSh->GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOM); + Invalidate(); +} + + +void SmGraphicWindow::ZoomToFitInWindow() +{ + SmDocShell &rDoc = *pViewShell->GetDoc(); + + // set defined mapmode before calling 'LogicToPixel' below + SetMapMode(MapMode(MAP_100TH_MM)); + + Size aSize (LogicToPixel(rDoc.GetSize())); + Size aWindowSize (GetSizePixel()); + + if (aSize.Width() > 0 && aSize.Height() > 0) + { + long nVal = Min ((85 * aWindowSize.Width()) / aSize.Width(), + (85 * aWindowSize.Height()) / aSize.Height()); + SetZoom ( sal::static_int_cast< sal_uInt16 >(nVal) ); + } +} + +uno::Reference< XAccessible > SmGraphicWindow::CreateAccessible() +{ + if (!pAccessible) + { + pAccessible = new SmGraphicAccessible( this ); + xAccessible = pAccessible; + } + return xAccessible; +} + +/**************************************************************************/ + + +SmGraphicController::SmGraphicController(SmGraphicWindow &rSmGraphic, + sal_uInt16 nId_, + SfxBindings &rBindings) : + SfxControllerItem(nId_, rBindings), + rGraphic(rSmGraphic) +{ +} + + +void SmGraphicController::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState) +{ + rGraphic.SetTotalSize(); + rGraphic.Invalidate(); + SfxControllerItem::StateChanged (nSID, eState, pState); +} + + +/**************************************************************************/ + + +SmEditController::SmEditController(SmEditWindow &rSmEdit, + sal_uInt16 nId_, + SfxBindings &rBindings) : + SfxControllerItem(nId_, rBindings), + rEdit(rSmEdit) +{ +} + + +#if OSL_DEBUG_LEVEL > 1 +SmEditController::~SmEditController() +{ +} +#endif + + +void SmEditController::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState) +{ + const SfxStringItem *pItem = PTR_CAST(SfxStringItem, pState); + + if ((pItem != NULL) && (rEdit.GetText() != pItem->GetValue())) + rEdit.SetText(pItem->GetValue()); + SfxControllerItem::StateChanged (nSID, eState, pState); +} + + +/**************************************************************************/ + +SmCmdBoxWindow::SmCmdBoxWindow(SfxBindings *pBindings_, SfxChildWindow *pChildWindow, + Window *pParent) : + SfxDockingWindow(pBindings_, pChildWindow, pParent, SmResId(RID_CMDBOXWINDOW)), + aEdit (*this), + aController (aEdit, SID_TEXT, *pBindings_), + bExiting (false) +{ + Hide (); + + aInitialFocusTimer.SetTimeoutHdl(LINK(this, SmCmdBoxWindow, InitialFocusTimerHdl)); + aInitialFocusTimer.SetTimeout(100); +} + + +SmCmdBoxWindow::~SmCmdBoxWindow () +{ + aInitialFocusTimer.Stop(); + bExiting = true; +} + + +SmViewShell * SmCmdBoxWindow::GetView() +{ + SfxDispatcher *pDispatcher = GetBindings().GetDispatcher(); + SfxViewShell *pView = pDispatcher ? pDispatcher->GetFrame()->GetViewShell() : NULL; + return PTR_CAST(SmViewShell, pView); +} + +void SmCmdBoxWindow::Resize() +{ + Rectangle aRect = Rectangle(Point(0, 0), GetOutputSizePixel()); + + if (! IsFloatingMode()) + { + switch (GetAlignment()) + { + case SFX_ALIGN_TOP: aRect.Bottom()--; break; + case SFX_ALIGN_BOTTOM: aRect.Top()++; break; + case SFX_ALIGN_LEFT: aRect.Right()--; break; + case SFX_ALIGN_RIGHT: aRect.Left()++; break; + default: + break; + } + } + + DecorationView aView(this); + aRect.Left() += 8; aRect.Top() += 8; + aRect.Right()-= 8; aRect.Bottom()-= 8; + aRect = aView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN ); + + aEdit.SetPosSizePixel(aRect.TopLeft(), aRect.GetSize()); + SfxDockingWindow::Resize(); + Invalidate(); +} + + +void SmCmdBoxWindow::Paint(const Rectangle& /*rRect*/) +{ + Rectangle aRect = Rectangle(Point(0, 0), GetOutputSizePixel()); + DecorationView aView(this); + + if (! IsFloatingMode()) + { + Point aFrom, aTo; + switch (GetAlignment()) + { + case SFX_ALIGN_TOP: + aFrom = aRect.BottomLeft(); aTo = aRect.BottomRight(); + aRect.Bottom()--; + break; + + case SFX_ALIGN_BOTTOM: + aFrom = aRect.TopLeft(); aTo = aRect.TopRight(); + aRect.Top()++; + break; + + case SFX_ALIGN_LEFT: + aFrom = aRect.TopRight(); aTo = aRect.BottomRight(); + aRect.Right()--; + break; + + case SFX_ALIGN_RIGHT: + aFrom = aRect.TopLeft(); aTo = aRect.BottomLeft(); + aRect.Left()++; + break; + + default: + break; + } + DrawLine( aFrom, aTo ); + aView.DrawFrame(aRect, FRAME_DRAW_OUT); + } + aRect.Left() += 8; aRect.Top() += 8; + aRect.Right()-= 8; aRect.Bottom()-= 8; + aRect = aView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN ); +} + + +Size SmCmdBoxWindow::CalcDockingSize(SfxChildAlignment eAlign) +{ + switch (eAlign) + { + case SFX_ALIGN_LEFT: + case SFX_ALIGN_RIGHT: + return Size(); + default: + break; + } + return SfxDockingWindow::CalcDockingSize(eAlign); +} + + +SfxChildAlignment SmCmdBoxWindow::CheckAlignment(SfxChildAlignment eActual, + SfxChildAlignment eWish) +{ + switch (eWish) + { + case SFX_ALIGN_TOP: + case SFX_ALIGN_BOTTOM: + case SFX_ALIGN_NOALIGNMENT: + return eWish; + default: + break; + } + + return eActual; +} + + +void SmCmdBoxWindow::StateChanged( StateChangedType nStateChange ) +{ + if (STATE_CHANGE_INITSHOW == nStateChange) + { + Resize(); // avoid SmEditWindow not being painted correctly + + // set initial position of window in floating mode + if (true == IsFloatingMode()) + AdjustPosition(); //! don't change pos in docking-mode ! + + aInitialFocusTimer.Start(); + } + + SfxDockingWindow::StateChanged( nStateChange ); +} + + +IMPL_LINK( SmCmdBoxWindow, InitialFocusTimerHdl, Timer *, EMPTYARG /*pTimer*/ ) +{ + // We want to have the focus in the edit window once Math has been opened + // to allow for immediate typing. + // Problem: There is no proper way to do this + // Thus: this timer based soultion has been implemented (see GrabFocus below) + // + // Follow-up problem (#i114910): grabing the focus may bust the help system since + // it relies on getting the current frame which conflicts with grabbing the focus. + // Thus aside from the 'GrabFocus' call everything else is to get the + // help reliably working despite using 'GrabFocus'. + + try + { + uno::Reference< frame::XDesktop > xDesktop; + uno::Reference< lang::XMultiServiceFactory > xSMGR( comphelper::getProcessServiceFactory() ); + if (xSMGR.is()) + { + xDesktop = uno::Reference< frame::XDesktop >( + xSMGR->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop"))), uno::UNO_QUERY_THROW ); + } + + aEdit.GrabFocus(); + + if (xDesktop.is()) + { + bool bInPlace = GetView()->GetViewFrame()->GetFrame().IsInPlace(); + uno::Reference< frame::XFrame > xFrame( GetBindings().GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface()); + if ( bInPlace ) + { + uno::Reference< container::XChild > xModel( GetView()->GetDoc()->GetModel(), uno::UNO_QUERY_THROW ); + uno::Reference< frame::XModel > xParent( xModel->getParent(), uno::UNO_QUERY_THROW ); + uno::Reference< frame::XController > xParentCtrler( xParent->getCurrentController() ); + uno::Reference< frame::XFramesSupplier > xParentFrame( xParentCtrler->getFrame(), uno::UNO_QUERY_THROW ); + xParentFrame->setActiveFrame( xFrame ); + } + else + { + uno::Reference< frame::XFramesSupplier > xFramesSupplier( xDesktop, uno::UNO_QUERY ); + xFramesSupplier->setActiveFrame( xFrame ); + } + } + } + catch (uno::Exception &) + { + OSL_FAIL( "failed to properly set initial focus to edit window" ); + } + return 0; +} + + +void SmCmdBoxWindow::AdjustPosition() +{ + Point aPt; + const Rectangle aRect( aPt, GetParent()->GetOutputSizePixel() ); + Point aTopLeft( Point( aRect.Left(), + aRect.Bottom() - GetSizePixel().Height() ) ); + Point aPos( GetParent()->OutputToScreenPixel( aTopLeft ) ); + if (aPos.X() < 0) + aPos.X() = 0; + if (aPos.Y() < 0) + aPos.Y() = 0; + SetPosPixel( aPos ); +} + + +void SmCmdBoxWindow::ToggleFloatingMode() +{ + SfxDockingWindow::ToggleFloatingMode(); + + if (GetFloatingWindow()) + GetFloatingWindow()->SetMinOutputSizePixel(Size (200, 50)); +} + + +void SmCmdBoxWindow::GetFocus() +{ + if (!bExiting) + aEdit.GrabFocus(); +} + +/**************************************************************************/ + + +SFX_IMPL_DOCKINGWINDOW(SmCmdBoxWrapper, SID_CMDBOXWINDOW); + +SmCmdBoxWrapper::SmCmdBoxWrapper(Window *pParentWindow, sal_uInt16 nId, + SfxBindings *pBindings, + SfxChildWinInfo *pInfo) : + SfxChildWindow(pParentWindow, nId) +{ + pWindow = new SmCmdBoxWindow(pBindings, this, pParentWindow); + + // make window docked to the bottom initially (after first start) + eChildAlignment = SFX_ALIGN_BOTTOM; + ((SfxDockingWindow *)pWindow)->Initialize(pInfo); +} + + +#if OSL_DEBUG_LEVEL > 1 +SmCmdBoxWrapper::~SmCmdBoxWrapper() +{ +} +#endif + + +/**************************************************************************/ + +struct SmViewShell_Impl +{ + sfx2::DocumentInserter* pDocInserter; + SfxRequest* pRequest; + SvtMiscOptions aOpts; + + SmViewShell_Impl() : + pDocInserter( NULL ) + , pRequest( NULL ) + {} + + ~SmViewShell_Impl() + { + delete pDocInserter; + delete pRequest; + } +}; + +TYPEINIT1( SmViewShell, SfxViewShell ); + +SFX_IMPL_INTERFACE(SmViewShell, SfxViewShell, SmResId(0)) +{ + SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_TOOLS | SFX_VISIBILITY_STANDARD | + SFX_VISIBILITY_FULLSCREEN | SFX_VISIBILITY_SERVER, + SmResId(RID_MATH_TOOLBOX )); + //Dummy-Objectbar, to avoid quiver while activating + + SFX_CHILDWINDOW_REGISTRATION(SID_TASKPANE); + SFX_CHILDWINDOW_REGISTRATION(SmToolBoxWrapper::GetChildWindowId()); + SFX_CHILDWINDOW_REGISTRATION(SmCmdBoxWrapper::GetChildWindowId()); +} + + +SFX_IMPL_NAMED_VIEWFACTORY(SmViewShell, "Default") +{ + SFX_VIEW_REGISTRATION(SmDocShell); +} + + +Size SmViewShell::GetOptimalSizePixel() const +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::GetOptimalSizePixel" ); + + return aGraphic.LogicToPixel( ((SmViewShell*)this)->GetDoc()->GetSize() ); +} + + +void SmViewShell::AdjustPosSizePixel(const Point &rPos, const Size &rSize) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::AdjustPosSizePixel" ); + + aGraphic.SetPosSizePixel(rPos, rSize); +} + + +void SmViewShell::InnerResizePixel(const Point &rOfs, const Size &rSize) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::InnerResizePixel" ); + + Size aObjSize = GetObjectShell()->GetVisArea().GetSize(); + if ( aObjSize.Width() > 0 && aObjSize.Height() > 0 ) + { + Size aProvidedSize = GetWindow()->PixelToLogic( rSize, MAP_100TH_MM ); + SfxViewShell::SetZoomFactor( Fraction( aProvidedSize.Width(), aObjSize.Width() ), + Fraction( aProvidedSize.Height(), aObjSize.Height() ) ); + } + + SetBorderPixel( SvBorder() ); + GetGraphicWindow().SetPosSizePixel(rOfs, rSize); + GetGraphicWindow().SetTotalSize(); +} + + +void SmViewShell::OuterResizePixel(const Point &rOfs, const Size &rSize) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::OuterResizePixel" ); + + SmGraphicWindow &rWin = GetGraphicWindow(); + rWin.SetPosSizePixel(rOfs, rSize); + if (GetDoc()->IsPreview()) + rWin.ZoomToFitInWindow(); + rWin.Update(); +} + + +void SmViewShell::QueryObjAreaPixel( Rectangle& rRect ) const +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::QueryObjAreaPixel" ); + + rRect.SetSize( GetGraphicWindow().GetSizePixel() ); +} + + +void SmViewShell::SetZoomFactor( const Fraction &rX, const Fraction &rY ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::SetZoomFactor" ); + + const Fraction &rFrac = rX < rY ? rX : rY; + GetGraphicWindow().SetZoom( (sal_uInt16) long(rFrac * Fraction( 100, 1 )) ); + + //To avoid rounding errors base class regulates crooked values too + //if necessary + SfxViewShell::SetZoomFactor( rX, rY ); +} + + +Size SmViewShell::GetTextLineSize(OutputDevice& rDevice, const String& rLine) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::GetTextLineSize" ); + + String aText; + Size aSize(rDevice.GetTextWidth(rLine), rDevice.GetTextHeight()); + sal_uInt16 nTabs = rLine.GetTokenCount('\t'); + + if (nTabs > 0) + { + long TabPos = rDevice.GetTextWidth('n') * 8; + + aSize.Width() = 0; + + for (sal_uInt16 i = 0; i < nTabs; i++) + { + if (i > 0) + aSize.Width() = ((aSize.Width() / TabPos) + 1) * TabPos; + + aText = rLine.GetToken(i, '\t'); + aText.EraseLeadingChars('\t'); + aText.EraseTrailingChars('\t'); + aSize.Width() += rDevice.GetTextWidth(aText); + } + } + + return aSize; +} + + +Size SmViewShell::GetTextSize(OutputDevice& rDevice, const String& rText, long MaxWidth) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::GetTextSize" ); + + Size aSize; + String aLine; + Size TextSize; + String aText; + sal_uInt16 nLines = rText.GetTokenCount('\n'); + + for (sal_uInt16 i = 0; i < nLines; i++) + { + aLine = rText.GetToken(i, '\n'); + aLine.EraseAllChars('\r'); + aLine.EraseLeadingChars('\n'); + aLine.EraseTrailingChars('\n'); + + aSize = GetTextLineSize(rDevice, aLine); + + if (aSize.Width() > MaxWidth) + { + do + { + xub_StrLen m = aLine.Len(); + xub_StrLen nLen = m; + + for (xub_StrLen n = 0; n < nLen; n++) + { + sal_Unicode cLineChar = aLine.GetChar(n); + if ((cLineChar == ' ') || (cLineChar == '\t')) + { + aText = aLine.Copy(0, n); + if (GetTextLineSize(rDevice, aText).Width() < MaxWidth) + m = n; + else + break; + } + } + + aText = aLine.Copy(0, m); + aLine.Erase(0, m); + aSize = GetTextLineSize(rDevice, aText); + TextSize.Height() += aSize.Height(); + TextSize.Width() = Max(TextSize.Width(), Min(aSize.Width(), MaxWidth)); + + aLine.EraseLeadingChars(' '); + aLine.EraseLeadingChars('\t'); + aLine.EraseLeadingChars(' '); + } + while (aLine.Len() > 0); + } + else + { + TextSize.Height() += aSize.Height(); + TextSize.Width() = Max(TextSize.Width(), aSize.Width()); + } + } + + return TextSize; +} + + +void SmViewShell::DrawTextLine(OutputDevice& rDevice, const Point& rPosition, const String& rLine) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::DrawTextLine" ); + + String aText; + Point aPoint (rPosition); + sal_uInt16 nTabs = rLine.GetTokenCount('\t'); + + if (nTabs > 0) + { + long TabPos = rDevice.GetTextWidth('n') * 8; + + for (sal_uInt16 i = 0; i < nTabs; i++) + { + if (i > 0) + aPoint.X() = ((aPoint.X() / TabPos) + 1) * TabPos; + + aText = rLine.GetToken(i, '\t'); + aText.EraseLeadingChars('\t'); + aText.EraseTrailingChars('\t'); + rDevice.DrawText(aPoint, aText); + aPoint.X() += rDevice.GetTextWidth(aText); + } + } + else + rDevice.DrawText(aPoint, rLine); +} + + +void SmViewShell::DrawText(OutputDevice& rDevice, const Point& rPosition, const String& rText, sal_uInt16 MaxWidth) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::DrawText" ); + + sal_uInt16 nLines = rText.GetTokenCount('\n'); + Point aPoint (rPosition); + Size aSize; + String aLine; + String aText; + + for (sal_uInt16 i = 0; i < nLines; i++) + { + aLine = rText.GetToken(i, '\n'); + aLine.EraseAllChars('\r'); + aLine.EraseLeadingChars('\n'); + aLine.EraseTrailingChars('\n'); + aSize = GetTextLineSize(rDevice, aLine); + if (aSize.Width() > MaxWidth) + { + do + { + xub_StrLen m = aLine.Len(); + xub_StrLen nLen = m; + + for (xub_StrLen n = 0; n < nLen; n++) + { + sal_Unicode cLineChar = aLine.GetChar(n); + if ((cLineChar == ' ') || (cLineChar == '\t')) + { + aText = aLine.Copy(0, n); + if (GetTextLineSize(rDevice, aText).Width() < MaxWidth) + m = n; + else + break; + } + } + aText = aLine.Copy(0, m); + aLine.Erase(0, m); + + DrawTextLine(rDevice, aPoint, aText); + aPoint.Y() += aSize.Height(); + + aLine.EraseLeadingChars(' '); + aLine.EraseLeadingChars('\t'); + aLine.EraseLeadingChars(' '); + } + while (GetTextLineSize(rDevice, aLine).Width() > MaxWidth); + + // print the remaining text + if (aLine.Len() > 0) + { + DrawTextLine(rDevice, aPoint, aLine); + aPoint.Y() += aSize.Height(); + } + } + else + { + DrawTextLine(rDevice, aPoint, aLine); + aPoint.Y() += aSize.Height(); + } + } +} + +void SmViewShell::Impl_Print( + OutputDevice &rOutDev, + const SmPrintUIOptions &rPrintUIOptions, + Rectangle aOutRect, Point aZeroPoint ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::Impl_Print" ); + + const bool bIsPrintTitle = rPrintUIOptions.getBoolValue( PRTUIOPT_TITLE_ROW, sal_True ); + const bool bIsPrintFrame = rPrintUIOptions.getBoolValue( PRTUIOPT_BORDER, sal_True ); + const bool bIsPrintFormulaText = rPrintUIOptions.getBoolValue( PRTUIOPT_FORMULA_TEXT, sal_True ); + SmPrintSize ePrintSize( static_cast< SmPrintSize >( rPrintUIOptions.getIntValue( PRTUIOPT_PRINT_FORMAT, PRINT_SIZE_NORMAL ) )); + const sal_uInt16 nZoomFactor = static_cast< sal_uInt16 >(rPrintUIOptions.getIntValue( PRTUIOPT_PRINT_SCALE, 100 )); + + rOutDev.Push(); + rOutDev.SetLineColor( Color(COL_BLACK) ); + + // output text on top + if (bIsPrintTitle) + { + Size aSize600 (0, 600); + Size aSize650 (0, 650); + Font aFont(FAMILY_DONTKNOW, aSize600); + + aFont.SetAlign(ALIGN_TOP); + aFont.SetWeight(WEIGHT_BOLD); + aFont.SetSize(aSize650); + aFont.SetColor( Color(COL_BLACK) ); + rOutDev.SetFont(aFont); + + Size aTitleSize (GetTextSize(rOutDev, GetDoc()->GetTitle(), aOutRect.GetWidth() - 200)); + + aFont.SetWeight(WEIGHT_NORMAL); + aFont.SetSize(aSize600); + rOutDev.SetFont(aFont); + + Size aDescSize (GetTextSize(rOutDev, GetDoc()->GetComment(), aOutRect.GetWidth() - 200)); + + if (bIsPrintFrame) + rOutDev.DrawRect(Rectangle(aOutRect.TopLeft(), + Size(aOutRect.GetWidth(), 100 + aTitleSize.Height() + 200 + aDescSize.Height() + 100))); + aOutRect.Top() += 200; + + // output title + aFont.SetWeight(WEIGHT_BOLD); + aFont.SetSize(aSize650); + rOutDev.SetFont(aFont); + Point aPoint(aOutRect.Left() + (aOutRect.GetWidth() - aTitleSize.Width()) / 2, + aOutRect.Top()); + DrawText(rOutDev, aPoint, GetDoc()->GetTitle(), + sal::static_int_cast< sal_uInt16 >(aOutRect.GetWidth() - 200)); + aOutRect.Top() += aTitleSize.Height() + 200; + + // output description + aFont.SetWeight(WEIGHT_NORMAL); + aFont.SetSize(aSize600); + rOutDev.SetFont(aFont); + aPoint.X() = aOutRect.Left() + (aOutRect.GetWidth() - aDescSize.Width()) / 2; + aPoint.Y() = aOutRect.Top(); + DrawText(rOutDev, aPoint, GetDoc()->GetComment(), + sal::static_int_cast< sal_uInt16 >(aOutRect.GetWidth() - 200)); + aOutRect.Top() += aDescSize.Height() + 300; + } + + // output text on bottom + if (bIsPrintFormulaText) + { + Font aFont(FAMILY_DONTKNOW, Size(0, 600)); + aFont.SetAlign(ALIGN_TOP); + aFont.SetColor( Color(COL_BLACK) ); + + // get size + rOutDev.SetFont(aFont); + + Size aSize (GetTextSize(rOutDev, GetDoc()->GetText(), aOutRect.GetWidth() - 200)); + + aOutRect.Bottom() -= aSize.Height() + 600; + + if (bIsPrintFrame) + rOutDev.DrawRect(Rectangle(aOutRect.BottomLeft(), + Size(aOutRect.GetWidth(), 200 + aSize.Height() + 200))); + + Point aPoint (aOutRect.Left() + (aOutRect.GetWidth() - aSize.Width()) / 2, + aOutRect.Bottom() + 300); + DrawText(rOutDev, aPoint, GetDoc()->GetText(), + sal::static_int_cast< sal_uInt16 >(aOutRect.GetWidth() - 200)); + aOutRect.Bottom() -= 200; + } + + if (bIsPrintFrame) + rOutDev.DrawRect(aOutRect); + + aOutRect.Top() += 100; + aOutRect.Left() += 100; + aOutRect.Bottom() -= 100; + aOutRect.Right() -= 100; + + Size aSize (GetDoc()->GetSize()); + + MapMode OutputMapMode; + // PDF export should always use PRINT_SIZE_NORMAL ... + if (!rPrintUIOptions.getBoolValue( "IsPrinter", sal_False ) ) + ePrintSize = PRINT_SIZE_NORMAL; + switch (ePrintSize) + { + case PRINT_SIZE_NORMAL: + OutputMapMode = MapMode(MAP_100TH_MM); + break; + + case PRINT_SIZE_SCALED: + if ((aSize.Width() > 0) && (aSize.Height() > 0)) + { + Size OutputSize (rOutDev.LogicToPixel(Size(aOutRect.GetWidth(), + aOutRect.GetHeight()), MapMode(MAP_100TH_MM))); + Size GraphicSize (rOutDev.LogicToPixel(aSize, MapMode(MAP_100TH_MM))); + sal_uInt16 nZ = (sal_uInt16) Min((long)Fraction(OutputSize.Width() * 100L, GraphicSize.Width()), + (long)Fraction(OutputSize.Height() * 100L, GraphicSize.Height())); + Fraction aFraction ((sal_uInt16) Max ((sal_uInt16) MINZOOM, Min((sal_uInt16) MAXZOOM, (sal_uInt16) (nZ - 10))), (sal_uInt16) 100); + + OutputMapMode = MapMode(MAP_100TH_MM, aZeroPoint, aFraction, aFraction); + } + else + OutputMapMode = MapMode(MAP_100TH_MM); + break; + + case PRINT_SIZE_ZOOMED: + { + Fraction aFraction( nZoomFactor, 100 ); + + OutputMapMode = MapMode(MAP_100TH_MM, aZeroPoint, aFraction, aFraction); + break; + } + } + + aSize = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aSize, OutputMapMode), + MapMode(MAP_100TH_MM)); + + Point aPos (aOutRect.Left() + (aOutRect.GetWidth() - aSize.Width()) / 2, + aOutRect.Top() + (aOutRect.GetHeight() - aSize.Height()) / 2); + + aPos = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aPos, MapMode(MAP_100TH_MM)), + OutputMapMode); + aOutRect = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aOutRect, MapMode(MAP_100TH_MM)), + OutputMapMode); + + rOutDev.SetMapMode(OutputMapMode); + rOutDev.SetClipRegion(Region(aOutRect)); + GetDoc()->DrawFormula(rOutDev, aPos, false); + rOutDev.SetClipRegion(); + + rOutDev.Pop(); +} + +sal_uInt16 SmViewShell::Print(SfxProgress & /*rProgress*/, sal_Bool /*bIsAPI*/) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::Print" ); + OSL_FAIL( "SmViewShell::Print: no longer used with new UI print dialog. Should be removed!!" ); + return 0; +} + + +SfxPrinter* SmViewShell::GetPrinter(sal_Bool bCreate) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::GetPrinter" ); + + SmDocShell *pDoc = GetDoc(); + if ( pDoc->HasPrinter() || bCreate ) + return pDoc->GetPrinter(); + return 0; +} + + +sal_uInt16 SmViewShell::SetPrinter(SfxPrinter *pNewPrinter, sal_uInt16 nDiffFlags, bool ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::SetPrinter" ); + SfxPrinter *pOld = GetDoc()->GetPrinter(); + if ( pOld && pOld->IsPrinting() ) + return SFX_PRINTERROR_BUSY; + + if ((nDiffFlags & SFX_PRINTER_PRINTER) == SFX_PRINTER_PRINTER) + GetDoc()->SetPrinter( pNewPrinter ); + + if ((nDiffFlags & SFX_PRINTER_OPTIONS) == SFX_PRINTER_OPTIONS) + { + SmModule *pp = SM_MOD(); + pp->GetConfig()->ItemSetToConfig(pNewPrinter->GetOptions()); + } + return 0; +} + + +SfxTabPage* SmViewShell::CreatePrintOptionsPage(Window *pParent, + const SfxItemSet &rOptions) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::CreatePrintOptionsPage" ); + + return SmPrintOptionsTabPage::Create(pParent, rOptions); +} + + +SmEditWindow *SmViewShell::GetEditWindow() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::GetEditWindow" ); + + SmCmdBoxWrapper *pWrapper = (SmCmdBoxWrapper *) GetViewFrame()-> + GetChildWindow( SmCmdBoxWrapper::GetChildWindowId() ); + + if (pWrapper != NULL) + { + SmEditWindow *pEditWin = pWrapper->GetEditWindow(); + OSL_ENSURE( pEditWin, "SmEditWindow missing" ); + return pEditWin; + } + + return NULL; +} + + +void SmViewShell::SetStatusText(const String& Text) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::SetStatusText" ); + + StatusText = Text; + GetViewFrame()->GetBindings().Invalidate(SID_TEXTSTATUS); +} + + +void SmViewShell::ShowError( const SmErrorDesc *pErrorDesc ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::ShowError" ); + + OSL_ENSURE(GetDoc(), "Sm : Document missing"); + if (pErrorDesc || 0 != (pErrorDesc = GetDoc()->GetParser().GetError(0)) ) + { + SetStatusText( pErrorDesc->Text ); + GetEditWindow()->MarkError( Point( pErrorDesc->pNode->GetColumn(), + pErrorDesc->pNode->GetRow())); + } +} + + +void SmViewShell::NextError() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::NextError" ); + + OSL_ENSURE(GetDoc(), "Sm : Document missing"); + const SmErrorDesc *pErrorDesc = GetDoc()->GetParser().NextError(); + + if (pErrorDesc) + ShowError( pErrorDesc ); +} + + +void SmViewShell::PrevError() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::PrevError" ); + + OSL_ENSURE(GetDoc(), "Sm : Document missing"); + const SmErrorDesc *pErrorDesc = GetDoc()->GetParser().PrevError(); + + if (pErrorDesc) + ShowError( pErrorDesc ); +} + + +bool SmViewShell::Insert( SfxMedium& rMedium ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::Insert" ); + + SmDocShell *pDoc = GetDoc(); + String aText( pDoc->GetText() ); + String aTemp = aText; + bool bRet = false; + + uno::Reference < embed::XStorage > xStorage = rMedium.GetStorage(); + uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY ); + if ( xNameAccess.is() && xNameAccess->getElementNames().getLength() ) + { + if ( xNameAccess->hasByName( C2S( "content.xml" ) ) || xNameAccess->hasByName( C2S( "Content.xml" ) )) + { + // is this a fabulous math package ? + Reference<com::sun::star::frame::XModel> xModel(pDoc->GetModel()); + SmXMLImportWrapper aEquation(xModel); //!! modifies the result of pDoc->GetText() !! + bRet = 0 == aEquation.Import(rMedium); + } + } + + if( bRet ) + { + aText = pDoc->GetText(); + SmEditWindow *pEditWin = GetEditWindow(); + if (pEditWin) + pEditWin->InsertText( aText ); + else + { + OSL_FAIL( "EditWindow missing" ); + aTemp += aText; + aText = aTemp; + } + + pDoc->Parse(); + pDoc->SetModified(true); + + SfxBindings &rBnd = GetViewFrame()->GetBindings(); + rBnd.Invalidate(SID_GAPHIC_SM); + rBnd.Invalidate(SID_TEXT); + } + return bRet; +} + + +bool SmViewShell::InsertFrom(SfxMedium &rMedium) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::InsertFrom" ); + + bool bSuccess = false; + SmDocShell *pDoc = GetDoc(); + SvStream *pStream = rMedium.GetInStream(); + String aText( pDoc->GetText() ); + String aTemp = aText; + + if (pStream) + { + const String& rFltName = rMedium.GetFilter()->GetFilterName(); + if ( rFltName.EqualsAscii(MATHML_XML) ) + { + Reference<com::sun::star::frame::XModel> xModel( pDoc->GetModel() ); + SmXMLImportWrapper aEquation(xModel); //!! modifies the result of pDoc->GetText() !! + bSuccess = 0 == aEquation.Import(rMedium); + } + } + + if( bSuccess ) + { + aText = pDoc->GetText(); + SmEditWindow *pEditWin = GetEditWindow(); + if (pEditWin) + pEditWin->InsertText( aText ); + else + { + OSL_FAIL( "EditWindow missing" ); + aTemp += aText; + aText = aTemp; + } + + pDoc->Parse(); + pDoc->SetModified(true); + + SfxBindings &rBnd = GetViewFrame()->GetBindings(); + rBnd.Invalidate(SID_GAPHIC_SM); + rBnd.Invalidate(SID_TEXT); + } + + return bSuccess; +} + + +void SmViewShell::Execute(SfxRequest& rReq) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::Execute" ); + + SmEditWindow *pWin = GetEditWindow(); + + switch (rReq.GetSlot()) + { + case SID_FORMULACURSOR: + { + SmModule *pp = SM_MOD(); + + const SfxItemSet *pArgs = rReq.GetArgs(); + const SfxPoolItem *pItem; + + bool bVal; + if ( pArgs && + SFX_ITEM_SET == pArgs->GetItemState( SID_FORMULACURSOR, false, &pItem)) + bVal = ((SfxBoolItem *) pItem)->GetValue(); + else + bVal = !pp->GetConfig()->IsShowFormulaCursor(); + + pp->GetConfig()->SetShowFormulaCursor(bVal); + if (!IsInlineEditEnabled()) + GetGraphicWindow().ShowCursor(bVal); + break; + } + case SID_DRAW: + if (pWin) + { + GetDoc()->SetText( pWin->GetText() ); + SetStatusText(String()); + ShowError( 0 ); + GetDoc()->Repaint(); + } + break; + + case SID_ADJUST: + case SID_FITINWINDOW: + aGraphic.ZoomToFitInWindow(); + break; + + case SID_VIEW050: + aGraphic.SetZoom(50); + break; + + case SID_VIEW100: + aGraphic.SetZoom(100); + break; + + case SID_VIEW200: + aGraphic.SetZoom(200); + break; + + case SID_ZOOMIN: + aGraphic.SetZoom(aGraphic.GetZoom() + 25); + break; + + case SID_ZOOMOUT: + OSL_ENSURE(aGraphic.GetZoom() >= 25, "Sm: incorrect sal_uInt16 argument"); + aGraphic.SetZoom(aGraphic.GetZoom() - 25); + break; + + case SID_COPYOBJECT: + { + //TODO/LATER: does not work because of UNO Tunneling - will be fixed later + Reference< datatransfer::XTransferable > xTrans( GetDoc()->GetModel(), uno::UNO_QUERY ); + if( xTrans.is() ) + { + Reference< lang::XUnoTunnel> xTnnl( xTrans, uno::UNO_QUERY); + if( xTnnl.is() ) + { + TransferableHelper* pTrans = reinterpret_cast< TransferableHelper * >( + sal::static_int_cast< sal_uIntPtr >( + xTnnl->getSomething( TransferableHelper::getUnoTunnelId() ))); + if( pTrans ) + pTrans->CopyToClipboard( this ? GetEditWindow() : 0 ); + } + } + } + break; + + case SID_PASTEOBJECT: + { + TransferableDataHelper aData( TransferableDataHelper::CreateFromSystemClipboard(this ? GetEditWindow(): 0) ); + uno::Reference < io::XInputStream > xStrm; + SotFormatStringId nId; + if( aData.GetTransferable().is() && + ( aData.HasFormat( nId = SOT_FORMATSTR_ID_EMBEDDED_OBJ ) || + (aData.HasFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) && + aData.HasFormat( nId = SOT_FORMATSTR_ID_EMBED_SOURCE ))) && + aData.GetInputStream( nId, xStrm ) && xStrm.is() ) + { + try + { + uno::Reference < embed::XStorage > xStorage = + ::comphelper::OStorageHelper::GetStorageFromInputStream( xStrm, ::comphelper::getProcessServiceFactory() ); + uno::Reference < beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY ); + SfxMedium aMedium( xStorage, String() ); + Insert( aMedium ); + GetDoc()->UpdateText(); + } + catch (uno::Exception &) + { + OSL_FAIL( "SmViewShell::Execute (SID_PASTEOBJECT): failed to get storage from input stream" ); + } + } + } + break; + + + case SID_CUT: + if (pWin) + pWin->Cut(); + break; + + case SID_COPY: + if (pWin) + { + if (pWin->IsAllSelected()) + { + GetViewFrame()->GetDispatcher()->Execute( + SID_COPYOBJECT, SFX_CALLMODE_STANDARD, + new SfxVoidItem(SID_COPYOBJECT), 0L); + } + else + pWin->Copy(); + } + break; + + case SID_PASTE: + { + bool bCallExec = 0 == pWin; + if( !bCallExec ) + { + TransferableDataHelper aDataHelper( + TransferableDataHelper::CreateFromSystemClipboard( + GetEditWindow()) ); + + if( aDataHelper.GetTransferable().is() && + aDataHelper.HasFormat( FORMAT_STRING )) + pWin->Paste(); + else + bCallExec = true; + } + if( bCallExec ) + { + GetViewFrame()->GetDispatcher()->Execute( + SID_PASTEOBJECT, SFX_CALLMODE_STANDARD, + new SfxVoidItem(SID_PASTEOBJECT), 0L); + } + } + break; + + case SID_DELETE: + if (pWin) + pWin->Delete(); + break; + + case SID_SELECT: + if (pWin) + pWin->SelectAll(); + break; + + case SID_INSERTCOMMAND: + { + const SfxInt16Item& rItem = + (const SfxInt16Item&)rReq.GetArgs()->Get(SID_INSERTCOMMAND); + + if (pWin && (bInsertIntoEditWindow || !IsInlineEditEnabled())) + pWin->InsertCommand(rItem.GetValue()); + if (IsInlineEditEnabled() && (GetDoc() && !bInsertIntoEditWindow)) { + GetDoc()->GetCursor().InsertCommand(rItem.GetValue()); + GetGraphicWindow().GrabFocus(); + } + break; + } + + case SID_INSERTSYMBOL: + { + const SfxStringItem& rItem = + (const SfxStringItem&)rReq.GetArgs()->Get(SID_INSERTSYMBOL); + + if (pWin && (bInsertIntoEditWindow || !IsInlineEditEnabled())) + pWin->InsertText(rItem.GetValue()); + if (IsInlineEditEnabled() && (GetDoc() && !bInsertIntoEditWindow)) + GetDoc()->GetCursor().InsertSpecial(rItem.GetValue()); + break; + } + + case SID_IMPORT_FORMULA: + { + delete pImpl->pRequest; + pImpl->pRequest = new SfxRequest( rReq ); + delete pImpl->pDocInserter; + pImpl->pDocInserter = + new ::sfx2::DocumentInserter( 0, GetDoc()->GetFactory().GetFactoryName(), 0 ); + pImpl->pDocInserter->StartExecuteModal( LINK( this, SmViewShell, DialogClosedHdl ) ); + break; + } + + case SID_NEXTERR: + NextError(); + if (pWin) + pWin->GrabFocus(); + break; + + case SID_PREVERR: + PrevError(); + if (pWin) + pWin->GrabFocus(); + break; + + case SID_NEXTMARK: + if (pWin) + { + pWin->SelNextMark(); + pWin->GrabFocus(); + } + break; + + case SID_PREVMARK: + if (pWin) + { + pWin->SelPrevMark(); + pWin->GrabFocus(); + } + break; + + case SID_TEXTSTATUS: + { + if (rReq.GetArgs() != NULL) + { + const SfxStringItem& rItem = + (const SfxStringItem&)rReq.GetArgs()->Get(SID_TEXTSTATUS); + + SetStatusText(rItem.GetValue()); + } + + break; + } + + case SID_GETEDITTEXT: + if (pWin) + if (pWin->GetText ().Len ()) GetDoc()->SetText( pWin->GetText() ); + break; + + case SID_ATTR_ZOOM: + { + if ( !GetViewFrame()->GetFrame().IsInPlace() ) + { + AbstractSvxZoomDialog *pDlg = 0; + const SfxItemSet *pSet = rReq.GetArgs(); + if ( !pSet ) + { + SfxItemSet aSet( GetDoc()->GetPool(), SID_ATTR_ZOOM, SID_ATTR_ZOOM); + aSet.Put( SvxZoomItem( SVX_ZOOM_PERCENT, aGraphic.GetZoom())); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if(pFact) + { + pDlg = pFact->CreateSvxZoomDialog(&GetViewFrame()->GetWindow(), aSet); + OSL_ENSURE(pDlg, "Dialogdiet fail!"); + pDlg->SetLimits( MINZOOM, MAXZOOM ); + if( pDlg->Execute() != RET_CANCEL ) + pSet = pDlg->GetOutputItemSet(); + } + } + if ( pSet ) + { + const SvxZoomItem &rZoom = (const SvxZoomItem &)pSet->Get(SID_ATTR_ZOOM); + switch( rZoom.GetType() ) + { + case SVX_ZOOM_PERCENT: + aGraphic.SetZoom((sal_uInt16)rZoom.GetValue ()); + break; + + case SVX_ZOOM_OPTIMAL: + aGraphic.ZoomToFitInWindow(); + break; + + case SVX_ZOOM_PAGEWIDTH: + case SVX_ZOOM_WHOLEPAGE: + { + const MapMode aMap( MAP_100TH_MM ); + SfxPrinter *pPrinter = GetPrinter( true ); + Point aPoint; + Rectangle OutputRect(aPoint, pPrinter->GetOutputSize()); + Size OutputSize(pPrinter->LogicToPixel(Size(OutputRect.GetWidth(), + OutputRect.GetHeight()), aMap)); + Size GraphicSize(pPrinter->LogicToPixel(GetDoc()->GetSize(), aMap)); + sal_uInt16 nZ = (sal_uInt16) Min((long)Fraction(OutputSize.Width() * 100L, GraphicSize.Width()), + (long)Fraction(OutputSize.Height() * 100L, GraphicSize.Height())); + aGraphic.SetZoom (nZ); + break; + } + default: + break; + } + } + delete pDlg; + } + } + break; + + case SID_TOOLBOX: + { + GetViewFrame()->ToggleChildWindow( SmToolBoxWrapper::GetChildWindowId() ); + } + break; + + case SID_SYMBOLS_CATALOGUE: + { + + // get device used to retrieve the FontList + SmDocShell *pDoc = GetDoc(); + OutputDevice *pDev = pDoc->GetPrinter(); + if (!pDev || pDev->GetDevFontCount() == 0) + pDev = &SM_MOD()->GetDefaultVirtualDev(); + OSL_ENSURE (pDev, "device for font list missing" ); + + SmModule *pp = SM_MOD(); + SmSymbolDialog( NULL, pDev, pp->GetSymbolManager(), *this ).Execute(); + } + break; + } + rReq.Done(); +} + + +void SmViewShell::GetState(SfxItemSet &rSet) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::GetState" ); + + SfxWhichIter aIter(rSet); + + SmEditWindow *pEditWin = GetEditWindow(); + for (sal_uInt16 nWh = aIter.FirstWhich(); nWh != 0; nWh = aIter.NextWhich()) + { + switch (nWh) + { + case SID_CUT: + case SID_COPY: + case SID_DELETE: + if (! pEditWin || ! pEditWin->IsSelected()) + rSet.DisableItem(nWh); + break; + + case SID_PASTE: + if( !xClipEvtLstnr.is() && pEditWin) + { + TransferableDataHelper aDataHelper( + TransferableDataHelper::CreateFromSystemClipboard( + pEditWin) ); + + bPasteState = aDataHelper.GetTransferable().is() && + ( aDataHelper.HasFormat( FORMAT_STRING ) || + aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ ) || + (aDataHelper.HasFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) + && aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))); + } + if( !bPasteState ) + rSet.DisableItem( nWh ); + break; + + case SID_ATTR_ZOOM: + rSet.Put(SvxZoomItem( SVX_ZOOM_PERCENT, aGraphic.GetZoom())); + /* no break here */ + case SID_VIEW050: + case SID_VIEW100: + case SID_VIEW200: + case SID_ADJUST: + case SID_ZOOMIN: + case SID_ZOOMOUT: + case SID_FITINWINDOW: + if ( GetViewFrame()->GetFrame().IsInPlace() ) + rSet.DisableItem( nWh ); + break; + + case SID_NEXTERR: + case SID_PREVERR: + case SID_NEXTMARK: + case SID_PREVMARK: + case SID_DRAW: + case SID_SELECT: + if (! pEditWin || pEditWin->IsEmpty()) + rSet.DisableItem(nWh); + break; + + case SID_TEXTSTATUS: + { + rSet.Put(SfxStringItem(nWh, StatusText)); + } + break; + + case SID_FORMULACURSOR: + { + SmModule *pp = SM_MOD(); + rSet.Put(SfxBoolItem(nWh, pp->GetConfig()->IsShowFormulaCursor())); + } + break; + + case SID_TOOLBOX: + { + bool bState = false; + SfxChildWindow *pChildWnd = GetViewFrame()-> + GetChildWindow( SmToolBoxWrapper::GetChildWindowId() ); + if (pChildWnd && pChildWnd->GetWindow()->IsVisible()) + bState = true; + rSet.Put(SfxBoolItem(SID_TOOLBOX, bState)); + } + break; + + } + } +} + + +SmViewShell::SmViewShell(SfxViewFrame *pFrame_, SfxViewShell *): + SfxViewShell(pFrame_, SFX_VIEW_HAS_PRINTOPTIONS | SFX_VIEW_CAN_PRINT), + pImpl( new SmViewShell_Impl ), + aGraphic(this), + aGraphicController(aGraphic, SID_GAPHIC_SM, pFrame_->GetBindings()) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::SmViewShell" ); + + SetStatusText(String()); + SetWindow(&aGraphic); + SfxShell::SetName(C2S("SmView")); + SfxShell::SetUndoManager( &GetDoc()->GetEditEngine().GetUndoManager() ); + SetHelpId( HID_SMA_VIEWSHELL_DOCUMENT ); +} + + +SmViewShell::~SmViewShell() +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::~SmViewShell" ); + + //!! this view shell is not active anymore !! + // Thus 'SmGetActiveView' will give a 0 pointer. + // Thus we need to supply this view as argument + SmEditWindow *pEditWin = GetEditWindow(); + if (pEditWin) + pEditWin->DeleteEditView( *this ); + delete pImpl; +} + +void SmViewShell::Deactivate( sal_Bool bIsMDIActivate ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::Deactivate" ); + + SmEditWindow *pEdit = GetEditWindow(); + if ( pEdit ) + pEdit->Flush(); + + SfxViewShell::Deactivate( bIsMDIActivate ); +} + + +void SmViewShell::Activate( sal_Bool bIsMDIActivate ) +{ + RTL_LOGFILE_CONTEXT( aLog, "starmath: SmViewShell::Activate" ); + + SfxViewShell::Activate( bIsMDIActivate ); + + SmEditWindow *pEdit = GetEditWindow(); + if ( pEdit ) + { + //! Since there is no way to be informed if a "drag and drop" + //! event has taken place, we call SetText here in order to + //! syncronize the GraphicWindow display with the text in the + //! EditEngine. + SmDocShell *pDoc = GetDoc(); + pDoc->SetText( pDoc->GetEditEngine().GetText( LINEEND_LF ) ); + + if ( bIsMDIActivate ) + pEdit->GrabFocus(); + } +} + +IMPL_LINK( SmViewShell, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg ) +{ + OSL_ENSURE( _pFileDlg, "SmViewShell::DialogClosedHdl(): no file dialog" ); + OSL_ENSURE( pImpl->pDocInserter, "ScDocShell::DialogClosedHdl(): no document inserter" ); + + if ( ERRCODE_NONE == _pFileDlg->GetError() ) + { + SfxMedium* pMedium = pImpl->pDocInserter->CreateMedium(); + + if ( pMedium != NULL ) + { + if ( pMedium->IsStorage() ) + Insert( *pMedium ); + else + InsertFrom( *pMedium ); + delete pMedium; + + SmDocShell* pDoc = GetDoc(); + pDoc->UpdateText(); + pDoc->ArrangeFormula(); + pDoc->Repaint(); + // adjust window, repaint, increment ModifyCount,... + GetViewFrame()->GetBindings().Invalidate(SID_GAPHIC_SM); + } + } + + pImpl->pRequest->SetReturnValue( SfxBoolItem( pImpl->pRequest->GetSlot(), true ) ); + pImpl->pRequest->Done(); + return 0; +} + +void SmViewShell::Notify( SfxBroadcaster& , const SfxHint& rHint ) +{ + if ( rHint.IsA(TYPE(SfxSimpleHint)) ) + { + switch( ( (SfxSimpleHint&) rHint ).GetId() ) + { + case SFX_HINT_MODECHANGED: + case SFX_HINT_DOCCHANGED: + GetViewFrame()->GetBindings().InvalidateAll(false); + break; + default: + break; + } + } +} + +bool SmViewShell::IsInlineEditEnabled() const +{ + return pImpl->aOpts.IsExperimentalMode(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/starmath/source/visitors.cxx b/starmath/source/visitors.cxx new file mode 100644 index 000000000000..f342b3dbb73a --- /dev/null +++ b/starmath/source/visitors.cxx @@ -0,0 +1,2541 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Jonas Finnemann Jensen <jopsen@gmail.com> + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jonas Finnemann Jensen <jopsen@gmail.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include "visitors.hxx" +#include "cursor.hxx" + +///////////////////////////////////// SmVisitorTest ///////////////////////////////////// + +void SmVisitorTest::Visit( SmTableNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NTABLE, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmBraceNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NBRACE, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmBracebodyNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NBRACEBODY, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmOperNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NOPER, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmAlignNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NALIGN, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmAttributNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NATTRIBUT, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmFontNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NFONT, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmUnHorNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NUNHOR, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmBinHorNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NBINHOR, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmBinVerNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NBINVER, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmBinDiagonalNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NBINDIAGONAL, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmSubSupNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NSUBSUP, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmMatrixNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NMATRIX, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmPlaceNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NPLACE, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmTextNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NTEXT, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmSpecialNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NSPECIAL, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmGlyphSpecialNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NGLYPH_SPECIAL, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmMathSymbolNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NMATH, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmBlankNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NBLANK, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmErrorNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NERROR, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmLineNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NLINE, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmExpressionNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NEXPRESSION, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmPolyLineNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NPOLYLINE, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmRootNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NROOT, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmRootSymbolNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NROOTSYMBOL, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmRectangleNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NRECTANGLE, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::Visit( SmVerticalBraceNode* pNode ) +{ + OSL_ENSURE( pNode->GetType( ) == NVERTICAL_BRACE, "the visitor-patterns isn't implemented correctly" ); + VisitChildren( pNode ); +} + +void SmVisitorTest::VisitChildren( SmNode* pNode ) +{ + SmNodeIterator it( pNode ); + while( it.Next( ) ) + it->Accept( this ); +} + +/////////////////////////////// SmDefaultingVisitor //////////////////////////////// + +void SmDefaultingVisitor::Visit( SmTableNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmBraceNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmBracebodyNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmOperNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmAlignNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmAttributNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmFontNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmUnHorNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmBinHorNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmBinVerNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmBinDiagonalNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmSubSupNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmMatrixNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmPlaceNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmTextNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmSpecialNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmGlyphSpecialNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmMathSymbolNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmBlankNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmErrorNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmLineNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmExpressionNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmPolyLineNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmRootNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmRootSymbolNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmRectangleNode* pNode ) +{ + DefaultVisit( pNode ); +} + +void SmDefaultingVisitor::Visit( SmVerticalBraceNode* pNode ) +{ + DefaultVisit( pNode ); +} + +/////////////////////////////// SmCaretDrawingVisitor //////////////////////////////// + +SmCaretDrawingVisitor::SmCaretDrawingVisitor( OutputDevice& rDevice, + SmCaretPos position, + Point offset, + bool caretVisible ) + : rDev( rDevice ) +{ + pos = position; + Offset = offset; + isCaretVisible = caretVisible; + OSL_ENSURE( position.IsValid( ), "Cannot draw invalid position!" ); + if( !position.IsValid( ) ) + return; + + //Save device state + rDev.Push( PUSH_FONT | PUSH_MAPMODE | PUSH_LINECOLOR | PUSH_FILLCOLOR | PUSH_TEXTCOLOR ); + + pos.pSelectedNode->Accept( this ); + //Restore device state + rDev.Pop( ); +} + +void SmCaretDrawingVisitor::Visit( SmTextNode* pNode ) +{ + long i = pos.Index; + + rDev.SetFont( pNode->GetFont( ) ); + + //Find the line + SmNode* pLine = SmCursor::FindTopMostNodeInLine( pNode ); + + //Find coordinates + long left = pNode->GetLeft( ) + rDev.GetTextWidth( pNode->GetText( ), 0, i ) + Offset.X( ); + long top = pLine->GetTop( ) + Offset.Y( ); + long height = pLine->GetHeight( ); + long left_line = pLine->GetLeft( ) + Offset.X( ); + long right_line = pLine->GetRight( ) + Offset.X( ); + + //Set color + rDev.SetLineColor( Color( COL_BLACK ) ); + + if ( isCaretVisible ) { + //Draw vertical line + Point p1( left, top ); + Point p2( left, top + height ); + rDev.DrawLine( p1, p2 ); + } + + //Underline the line + Point pLeft( left_line, top + height ); + Point pRight( right_line, top + height ); + rDev.DrawLine( pLeft, pRight ); +} + +void SmCaretDrawingVisitor::DefaultVisit( SmNode* pNode ) +{ + rDev.SetLineColor( Color( COL_BLACK ) ); + + //Find the line + SmNode* pLine = SmCursor::FindTopMostNodeInLine( pNode ); + + //Find coordinates + long left = pNode->GetLeft( ) + Offset.X( ) + ( pos.Index == 1 ? pNode->GetWidth( ) : 0 ); + long top = pLine->GetTop( ) + Offset.Y( ); + long height = pLine->GetHeight( ); + long left_line = pLine->GetLeft( ) + Offset.X( ); + long right_line = pLine->GetRight( ) + Offset.X( ); + + //Set color + rDev.SetLineColor( Color( COL_BLACK ) ); + + if ( isCaretVisible ) { + //Draw vertical line + Point p1( left, top ); + Point p2( left, top + height ); + rDev.DrawLine( p1, p2 ); + } + + //Underline the line + Point pLeft( left_line, top + height ); + Point pRight( right_line, top + height ); + rDev.DrawLine( pLeft, pRight ); +} + +/////////////////////////////// SmCaretPos2LineVisitor //////////////////////////////// + +void SmCaretPos2LineVisitor::Visit( SmTextNode* pNode ) +{ + //Save device state + pDev->Push( PUSH_FONT | PUSH_TEXTCOLOR ); + + long i = pos.Index; + + pDev->SetFont( pNode->GetFont( ) ); + + //Find coordinates + long left = pNode->GetLeft( ) + pDev->GetTextWidth( pNode->GetText( ), 0, i ); + long top = pNode->GetTop( ); + long height = pNode->GetHeight( ); + + line = SmCaretLine( left, top, height ); + + //Restore device state + pDev->Pop( ); +} + +void SmCaretPos2LineVisitor::DefaultVisit( SmNode* pNode ) +{ + //Vertical line ( code from SmCaretDrawingVisitor ) + Point p1 = pNode->GetTopLeft( ); + if( pos.Index == 1 ) + p1.Move( pNode->GetWidth( ), 0 ); + + line = SmCaretLine( p1.X( ), p1.Y( ), pNode->GetHeight( ) ); +} + +/////////////////////////////// Nasty temporary device!!! //////////////////////////////// + +#include <tools/gen.hxx> +#include <tools/fract.hxx> +#include <rtl/math.hxx> +#include <tools/color.hxx> +#include <vcl/metric.hxx> +#include <vcl/lineinfo.hxx> +#include <vcl/outdev.hxx> +#include <sfx2/module.hxx> +#include "symbol.hxx" +#include "smmod.hxx" + +class SmTmpDevice2 +{ + OutputDevice &rOutDev; + + // disallow use of copy-constructor and assignment-operator + SmTmpDevice2( const SmTmpDevice2 &rTmpDev ); + SmTmpDevice2 & operator = ( const SmTmpDevice2 &rTmpDev ); + + Color Impl_GetColor( const Color& rColor ); + +public: + SmTmpDevice2( OutputDevice &rTheDev, bool bUseMap100th_mm ); + ~SmTmpDevice2( ) { rOutDev.Pop( ); } + + void SetFont( const Font &rNewFont ); + + void SetLineColor( const Color& rColor ) { rOutDev.SetLineColor( Impl_GetColor( rColor ) ); } + void SetFillColor( const Color& rColor ) { rOutDev.SetFillColor( Impl_GetColor( rColor ) ); } + void SetTextColor( const Color& rColor ) { rOutDev.SetTextColor( Impl_GetColor( rColor ) ); } + + operator OutputDevice & ( ) const { return rOutDev; } +}; + +SmTmpDevice2::SmTmpDevice2( OutputDevice &rTheDev, bool bUseMap100th_mm ) : + rOutDev( rTheDev ) +{ + rOutDev.Push( PUSH_FONT | PUSH_MAPMODE | + PUSH_LINECOLOR | PUSH_FILLCOLOR | PUSH_TEXTCOLOR ); + if ( bUseMap100th_mm && MAP_100TH_MM != rOutDev.GetMapMode( ).GetMapUnit( ) ) + { + OSL_FAIL( "incorrect MapMode?" ); + rOutDev.SetMapMode( MAP_100TH_MM ); //format for 100% always + } +} + +Color SmTmpDevice2::Impl_GetColor( const Color& rColor ) +{ + ColorData nNewCol = rColor.GetColor( ); + if ( COL_AUTO == nNewCol ) + { + if ( OUTDEV_PRINTER == rOutDev.GetOutDevType( ) ) + nNewCol = COL_BLACK; + else + { + Color aBgCol( rOutDev.GetBackground( ).GetColor( ) ); + if ( OUTDEV_WINDOW == rOutDev.GetOutDevType( ) ) + aBgCol = ( ( Window & ) rOutDev ).GetDisplayBackground( ).GetColor( ); + + nNewCol = SM_MOD( )->GetColorConfig( ).GetColorValue( svtools::FONTCOLOR ).nColor; + + Color aTmpColor( nNewCol ); + if ( aBgCol.IsDark( ) && aTmpColor.IsDark( ) ) + nNewCol = COL_WHITE; + else if ( aBgCol.IsBright( ) && aTmpColor.IsBright( ) ) + nNewCol = COL_BLACK; + } + } + return Color( nNewCol ); +} + +void SmTmpDevice2::SetFont( const Font &rNewFont ) +{ + rOutDev.SetFont( rNewFont ); + rOutDev.SetTextColor( Impl_GetColor( rNewFont.GetColor( ) ) ); +} + +/////////////////////////////// SmDrawingVisitor //////////////////////////////// + +void SmDrawingVisitor::Visit( SmTableNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmBraceNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmBracebodyNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmOperNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmAlignNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmAttributNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmFontNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmUnHorNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmBinHorNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmBinVerNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmBinDiagonalNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmSubSupNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmMatrixNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmPlaceNode* pNode ) +{ + DrawSpecialNode( pNode ); +} + +void SmDrawingVisitor::Visit( SmTextNode* pNode ) +{ + DrawTextNode( pNode ); +} + +void SmDrawingVisitor::Visit( SmSpecialNode* pNode ) +{ + DrawSpecialNode( pNode ); +} + +void SmDrawingVisitor::Visit( SmGlyphSpecialNode* pNode ) +{ + DrawSpecialNode( pNode ); +} + +void SmDrawingVisitor::Visit( SmMathSymbolNode* pNode ) +{ + DrawSpecialNode( pNode ); +} + +void SmDrawingVisitor::Visit( SmBlankNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmErrorNode* pNode ) +{ + DrawSpecialNode( pNode ); +} + +void SmDrawingVisitor::Visit( SmLineNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmExpressionNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmRootNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmVerticalBraceNode* pNode ) +{ + DrawChildren( pNode ); +} + +void SmDrawingVisitor::Visit( SmRootSymbolNode* pNode ) +{ + if ( pNode->IsPhantom( ) ) + return; + + // draw root-sign itself + DrawSpecialNode( pNode ); + + SmTmpDevice2 aTmpDev( ( OutputDevice & ) rDev, true ); + aTmpDev.SetFillColor( pNode->GetFont( ).GetColor( ) ); + rDev.SetLineColor( ); + aTmpDev.SetFont( pNode->GetFont( ) ); + + // since the width is always unscaled it corresponds ot the _original_ + // _unscaled_ font height to be used, we use that to calculate the + // bar height. Thus it is independent of the arguments height. + // ( see display of sqrt QQQ versus sqrt stack{Q#Q#Q#Q} ) + long nBarHeight = pNode->GetWidth( ) * 7L / 100L; + long nBarWidth = pNode->GetBodyWidth( ) + pNode->GetBorderWidth( ); + Point aBarOffset( pNode->GetWidth( ), +pNode->GetBorderWidth( ) ); + Point aBarPos( Position + aBarOffset ); + + Rectangle aBar( aBarPos, Size( nBarWidth, nBarHeight ) ); + //! avoid GROWING AND SHRINKING of drawn rectangle when constantly + //! increasing zoomfactor. + // This is done by shifting its output-position to a point that + // corresponds exactly to a pixel on the output device. + Point aDrawPos( rDev.PixelToLogic( rDev.LogicToPixel( aBar.TopLeft( ) ) ) ); + aBar.SetPos( aDrawPos ); + + rDev.DrawRect( aBar ); +} + +void SmDrawingVisitor::Visit( SmPolyLineNode* pNode ) +{ + if ( pNode->IsPhantom( ) ) + return; + + long nBorderwidth = pNode->GetFont( ).GetBorderWidth( ); + + LineInfo aInfo; + aInfo.SetWidth( pNode->GetWidth( ) - 2 * nBorderwidth ); + + Point aOffset ( Point( ) - pNode->GetPolygon( ).GetBoundRect( ).TopLeft( ) + + Point( nBorderwidth, nBorderwidth ) ), + aPos ( Position + aOffset ); + pNode->GetPolygon( ).Move( aPos.X( ), aPos.Y( ) ); //Works because Polygon wraps a pointer + + SmTmpDevice2 aTmpDev ( ( OutputDevice & ) rDev, false ); + aTmpDev.SetLineColor( pNode->GetFont( ).GetColor( ) ); + + rDev.DrawPolyLine( pNode->GetPolygon( ), aInfo ); +} + +void SmDrawingVisitor::Visit( SmRectangleNode* pNode ) +{ + if ( pNode->IsPhantom( ) ) + return; + + SmTmpDevice2 aTmpDev ( ( OutputDevice & ) rDev, false ); + aTmpDev.SetFillColor( pNode->GetFont( ).GetColor( ) ); + rDev.SetLineColor( ); + aTmpDev.SetFont( pNode->GetFont( ) ); + + sal_uLong nTmpBorderWidth = pNode->GetFont( ).GetBorderWidth( ); + + // get rectangle and remove borderspace + Rectangle aTmp ( pNode->AsRectangle( ) + Position - pNode->GetTopLeft( ) ); + aTmp.Left( ) += nTmpBorderWidth; + aTmp.Right( ) -= nTmpBorderWidth; + aTmp.Top( ) += nTmpBorderWidth; + aTmp.Bottom( ) -= nTmpBorderWidth; + + OSL_ENSURE( aTmp.GetHeight( ) > 0 && aTmp.GetWidth( ) > 0, + "Sm: leeres Rechteck" ); + + //! avoid GROWING AND SHRINKING of drawn rectangle when constantly + //! increasing zoomfactor. + // This is done by shifting its output-position to a point that + // corresponds exactly to a pixel on the output device. + Point aPos ( rDev.PixelToLogic( rDev.LogicToPixel( aTmp.TopLeft( ) ) ) ); + aTmp.SetPos( aPos ); + + rDev.DrawRect( aTmp ); +} + +void SmDrawingVisitor::DrawTextNode( SmTextNode* pNode ) +{ + if ( pNode->IsPhantom( ) || pNode->GetText( ).Len( ) == 0 || pNode->GetText( ).GetChar( 0 ) == xub_Unicode( '\0' ) ) + return; + + SmTmpDevice2 aTmpDev ( ( OutputDevice & ) rDev, false ); + aTmpDev.SetFont( pNode->GetFont( ) ); + + Point aPos ( Position ); + aPos.Y( ) += pNode->GetBaselineOffset( ); + // auf Pixelkoordinaten runden + aPos = rDev.PixelToLogic( rDev.LogicToPixel( aPos ) ); + + rDev.DrawStretchText( aPos, pNode->GetWidth( ), pNode->GetText( ) ); +} + +void SmDrawingVisitor::DrawSpecialNode( SmSpecialNode* pNode ) +{ + //! since this chars might come from any font, that we may not have + //! set to ALIGN_BASELINE yet, we do it now. + pNode->GetFont( ).SetAlign( ALIGN_BASELINE ); + + DrawTextNode( pNode ); +} + +void SmDrawingVisitor::DrawChildren( SmNode* pNode ) +{ + if ( pNode->IsPhantom( ) ) + return; + + Point rPosition = Position; + + SmNodeIterator it( pNode ); + while( it.Next( ) ) + { + Point aOffset ( it->GetTopLeft( ) - pNode->GetTopLeft( ) ); + Position = rPosition + aOffset; + it->Accept( this ); + } +} + +/////////////////////////////// SmSetSelectionVisitor //////////////////////////////// + +SmSetSelectionVisitor::SmSetSelectionVisitor( SmCaretPos startPos, SmCaretPos endPos, SmNode* pTree) { + StartPos = startPos; + EndPos = endPos; + IsSelecting = false; + + //Assume that pTree is a SmTableNode + OSL_ENSURE(pTree->GetType() == NTABLE, "pTree should be a SmTableNode!"); + //Visit root node, this is special as this node cannot be selected, but its children can! + if(pTree->GetType() == NTABLE){ + //Change state if StartPos is in front of this node + if( StartPos.pSelectedNode == pTree && StartPos.Index == 0 ) + IsSelecting = !IsSelecting; + //Change state if EndPos is in front of this node + if( EndPos.pSelectedNode == pTree && EndPos.Index == 0 ) + IsSelecting = !IsSelecting; + OSL_ENSURE(!IsSelecting, "Caret positions needed to set IsSelecting about, shouldn't be possible!"); + + //Visit lines + SmNodeIterator it( pTree ); + while( it.Next( ) ) { + it->Accept( this ); + //If we started a selection in this line and it haven't ended, we do that now! + if(IsSelecting) { + IsSelecting = false; + SetSelectedOnAll(it.Current(), true); + //Set StartPos and EndPos to invalid positions, this ensures that an unused + //start or end (because we forced end above), doesn't start a new selection. + StartPos = EndPos = SmCaretPos(); + } + } + //Check if pTree isn't selected + OSL_ENSURE(!pTree->IsSelected(), "pTree should never be selected!"); + //Discard the selection if there's a bug (it's better than crashing) + if(pTree->IsSelected()) + SetSelectedOnAll(pTree, false); + }else //This shouldn't happen, but I don't see any reason to die if it does + pTree->Accept(this); +} + +void SmSetSelectionVisitor::SetSelectedOnAll( SmNode* pSubTree, bool IsSelected ) { + pSubTree->SetSelected( IsSelected ); + + //Quick BFS to set all selections + SmNodeIterator it( pSubTree ); + while( it.Next( ) ) + SetSelectedOnAll( it.Current( ), IsSelected ); +} + +void SmSetSelectionVisitor::DefaultVisit( SmNode* pNode ) { + //Change state if StartPos is in front of this node + if( StartPos.pSelectedNode == pNode && StartPos.Index == 0 ) + IsSelecting = !IsSelecting; + //Change state if EndPos is in front of this node + if( EndPos.pSelectedNode == pNode && EndPos.Index == 0 ) + IsSelecting = !IsSelecting; + + //Cache current state + bool WasSelecting = IsSelecting; + bool ChangedState = false; + + //Set selected + pNode->SetSelected( IsSelecting ); + + //Visit children + SmNodeIterator it( pNode ); + while( it.Next( ) ) + { + it->Accept( this ); + ChangedState = ( WasSelecting != IsSelecting ) || ChangedState; + } + + //If state changed + if( ChangedState ) + { + //Select this node and all of its children + //(Make exception for SmBracebodyNode) + if( pNode->GetType() != NBRACEBODY || + !pNode->GetParent() || + pNode->GetParent()->GetType() != NBRACE ) + SetSelectedOnAll( pNode, true ); + else + SetSelectedOnAll( pNode->GetParent(), true ); + /* If the equation is: sqrt{2 + 4} + 5 + * And the selection is: sqrt{2 + [4} +] 5 + * Where [ denotes StartPos and ] denotes EndPos + * Then the sqrt node should be selected, so that the + * effective selection is: [sqrt{2 + 4} +] 5 + * The same is the case if we swap StartPos and EndPos. + */ + } + + //Change state if StartPos is after this node + if( StartPos.pSelectedNode == pNode && StartPos.Index == 1 ) + { + IsSelecting = !IsSelecting; + } + //Change state if EndPos is after of this node + if( EndPos.pSelectedNode == pNode && EndPos.Index == 1 ) + { + IsSelecting = !IsSelecting; + } +} + +void SmSetSelectionVisitor::VisitCompositionNode( SmNode* pNode ) { + //Change state if StartPos is in front of this node + if( StartPos.pSelectedNode == pNode && StartPos.Index == 0 ) + IsSelecting = !IsSelecting; + //Change state if EndPos is in front of this node + if( EndPos.pSelectedNode == pNode && EndPos.Index == 0 ) + IsSelecting = !IsSelecting; + + //Cache current state + bool WasSelecting = IsSelecting; + + //Visit children + SmNodeIterator it( pNode ); + while( it.Next( ) ) + it->Accept( this ); + + //Set selected, if everything was selected + pNode->SetSelected( WasSelecting && IsSelecting ); + + //Change state if StartPos is after this node + if( StartPos.pSelectedNode == pNode && StartPos.Index == 1 ) + IsSelecting = !IsSelecting; + //Change state if EndPos is after of this node + if( EndPos.pSelectedNode == pNode && EndPos.Index == 1 ) + IsSelecting = !IsSelecting; +} + +void SmSetSelectionVisitor::Visit( SmTextNode* pNode ) { + long i1 = -1, + i2 = -1; + if( StartPos.pSelectedNode == pNode ) + i1 = StartPos.Index; + if( EndPos.pSelectedNode == pNode ) + i2 = EndPos.Index; + + long start, end; + pNode->SetSelected( true ); + if( i1 != -1 && i2 != -1 ) { + start = i1 < i2 ? i1 : i2; //MIN + end = i1 > i2 ? i1 : i2; //MAX + } else if( IsSelecting && i1 != -1 ) { + start = 0; + end = i1; + IsSelecting = false; + } else if( IsSelecting && i2 != -1 ) { + start = 0; + end = i2; + IsSelecting = false; + } else if( !IsSelecting && i1 != -1 ) { + start = i1; + end = pNode->GetText( ).Len( ); + IsSelecting = true; + } else if( !IsSelecting && i2 != -1 ) { + start = i2; + end = pNode->GetText( ).Len( ); + IsSelecting = true; + } else if( IsSelecting ) { + start = 0; + end = pNode->GetText( ).Len( ); + } else { + pNode->SetSelected( false ); + start = 0; + end = 0; + } + pNode->SetSelected( start != end ); + pNode->SetSelectionStart( start ); + pNode->SetSelectionEnd( end ); +} + +void SmSetSelectionVisitor::Visit( SmExpressionNode* pNode ) { + VisitCompositionNode( pNode ); +} + +void SmSetSelectionVisitor::Visit( SmLineNode* pNode ) { + VisitCompositionNode( pNode ); +} + +void SmSetSelectionVisitor::Visit( SmAlignNode* pNode ) { + VisitCompositionNode( pNode ); +} + +void SmSetSelectionVisitor::Visit( SmBinHorNode* pNode ) { + VisitCompositionNode( pNode ); +} + +void SmSetSelectionVisitor::Visit( SmUnHorNode* pNode ) { + VisitCompositionNode( pNode ); +} + +void SmSetSelectionVisitor::Visit( SmFontNode* pNode ) { + VisitCompositionNode( pNode ); +} + +/////////////////////////////// SmCaretPosGraphBuildingVisitor //////////////////////////////// + +SmCaretPosGraphBuildingVisitor::SmCaretPosGraphBuildingVisitor( SmNode* pRootNode ) { + pRightMost = NULL; + pGraph = new SmCaretPosGraph( ); + //pRootNode should always be a table + OSL_ENSURE( pRootNode->GetType( ) == NTABLE, "pRootNode must be a table node"); + //Handle the special case where NTABLE is used a rootnode + if( pRootNode->GetType( ) == NTABLE ){ + //Children are SmLineNodes + //Or so I thought... Aparently, the children can be instances of SmExpression + //especially if there's a error in the formula... So he we go, a simple work around. + SmNodeIterator it( pRootNode ); + while( it.Next( ) ){ + //There's a special invariant between this method and the Visit( SmLineNode* ) + //Usually pRightMost may not be NULL, to avoid this pRightMost should here be + //set to a new SmCaretPos in front of it.Current( ), however, if it.Current( ) is + //an instance of SmLineNode we let SmLineNode create this position in front of + //the visual line. + //The argument for doing this is that we now don't have to worry about SmLineNode + //being a visual line composition node. Thus, no need for yet another special case + //in SmCursor::IsLineCompositionNode and everywhere this method is used. + //if( it->GetType( ) != NLINE ) + pRightMost = pGraph->Add( SmCaretPos( it.Current( ), 0 ) ); + it->Accept( this ); + } + }else + pRootNode->Accept(this); +} + +void SmCaretPosGraphBuildingVisitor::Visit( SmLineNode* pNode ){ + SmNodeIterator it( pNode ); + while( it.Next( ) ){ + it->Accept( this ); + } +} + +/** Build SmCaretPosGraph for SmTableNode + * This method covers cases where SmTableNode is used in a binom or stack, + * the special case where it is used as root node for the entire formula is + * handled in the constructor. + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmTableNode* pNode ){ + SmCaretPosGraphEntry *left = pRightMost, + *right = pGraph->Add( SmCaretPos( pNode, 1) ); + bool bIsFirst = true; + SmNodeIterator it( pNode ); + while( it.Next() ){ + pRightMost = pGraph->Add( SmCaretPos( it.Current(), 0 ), left); + if(bIsFirst) + left->SetRight(pRightMost); + it->Accept( this ); + pRightMost->SetRight(right); + if(bIsFirst) + right->SetLeft(pRightMost); + bIsFirst = false; + } + pRightMost = right; +} + +/** Build SmCaretPosGraph for SmSubSupNode + * + * The child positions in a SubSupNode, where H is the body: + * \code + * CSUP + * + * LSUP H H RSUP + * H H + * HHHH + * H H + * LSUB H H RSUB + * + * CSUB + * \endcode + * + * Graph over these, where "left" is before the SmSubSupNode and "right" is after: + * \dot + * digraph Graph{ + * left -> H; + * H -> right; + * LSUP -> H; + * LSUB -> H; + * CSUP -> right; + * CSUB -> right; + * RSUP -> right; + * RSUB -> right; + * }; + * \enddot + * + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmSubSupNode* pNode ) +{ + SmCaretPosGraphEntry *left, + *right, + *bodyLeft, + *bodyRight; + + left = pRightMost; + OSL_ENSURE( pRightMost, "pRightMost shouldn't be NULL here!" ); + + //Create bodyLeft + OSL_ENSURE( pNode->GetBody( ), "SmSubSupNode Doesn't have a body!" ); + bodyLeft = pGraph->Add( SmCaretPos( pNode->GetBody( ), 0 ), left ); + left->SetRight( bodyLeft ); //TODO: Don't make this if LSUP or LSUB are NULL ( not sure??? ) + + //Create right + right = pGraph->Add( SmCaretPos( pNode, 1 ) ); + + //Visit the body, to get bodyRight + pRightMost = bodyLeft; + pNode->GetBody( )->Accept( this ); + bodyRight = pRightMost; + bodyRight->SetRight( right ); + right->SetLeft( bodyRight ); + + SmNode* pChild; + //If there's an LSUP + if( ( pChild = pNode->GetSubSup( LSUP ) ) ){ + SmCaretPosGraphEntry *cLeft; //Child left + cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + + pRightMost = cLeft; + pChild->Accept( this ); + + pRightMost->SetRight( bodyLeft ); + } + //If there's an LSUB + if( ( pChild = pNode->GetSubSup( LSUB ) ) ){ + SmCaretPosGraphEntry *cLeft; //Child left + cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + + pRightMost = cLeft; + pChild->Accept( this ); + + pRightMost->SetRight( bodyLeft ); + } + //If there's an CSUP + if( ( pChild = pNode->GetSubSup( CSUP ) ) ){ + SmCaretPosGraphEntry *cLeft; //Child left + cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + + pRightMost = cLeft; + pChild->Accept( this ); + + pRightMost->SetRight( right ); + } + //If there's an CSUB + if( ( pChild = pNode->GetSubSup( CSUB ) ) ){ + SmCaretPosGraphEntry *cLeft; //Child left + cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + + pRightMost = cLeft; + pChild->Accept( this ); + + pRightMost->SetRight( right ); + } + //If there's an RSUP + if( ( pChild = pNode->GetSubSup( RSUP ) ) ){ + SmCaretPosGraphEntry *cLeft; //Child left + cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), bodyRight ); + + pRightMost = cLeft; + pChild->Accept( this ); + + pRightMost->SetRight( right ); + } + //If there's an RSUB + if( ( pChild = pNode->GetSubSup( RSUB ) ) ){ + SmCaretPosGraphEntry *cLeft; //Child left + cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), bodyRight ); + + pRightMost = cLeft; + pChild->Accept( this ); + + pRightMost->SetRight( right ); + } + + //Set return parameters + pRightMost = right; +} + +/** Build caret position for SmOperNode + * + * If first child is an SmSubSupNode we will ignore its + * body, as this body is a SmMathSymbol, for SUM, INT or similar + * that shouldn't be subject to modification. + * If first child is not a SmSubSupNode, ignore it completely + * as it is a SmMathSymbol. + * + * The child positions in a SmOperNode, where H is symbol, e.g. int, sum or similar: + * \code + * TO + * + * LSUP H H RSUP BBB BB BBB B B + * H H B B B B B B B B + * HHHH BBB B B B B B + * H H B B B B B B B + * LSUB H H RSUB BBB BB BBB B + * + * FROM + * \endcode + * Notice, CSUP, etc. are actually granchildren, but inorder to ignore H, these are visited + * from here. If they are present, that is if pOper is an instance of SmSubSupNode. + * + * Graph over these, where "left" is before the SmOperNode and "right" is after: + * \dot + * digraph Graph{ + * left -> BODY; + * BODY -> right; + * LSUP -> BODY; + * LSUB -> BODY; + * TO -> BODY; + * FROM -> BODY; + * RSUP -> BODY; + * RSUB -> BODY; + * }; + * \enddot + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmOperNode* pNode ) +{ + SmNode *pOper = pNode->GetSubNode( 0 ), + *pBody = pNode->GetSubNode( 1 ); + + SmCaretPosGraphEntry *left = pRightMost, + *bodyLeft, + *bodyRight, + *right; + //Create body left + bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left ); + left->SetRight( bodyLeft ); + + //Visit body, get bodyRight + pRightMost = bodyLeft; + pBody->Accept( this ); + bodyRight = pRightMost; + + //Create right + right = pGraph->Add( SmCaretPos( pNode, 1 ), bodyRight ); + bodyRight->SetRight( right ); + + //Get subsup pNode if any + SmSubSupNode* pSubSup = pOper->GetType( ) == NSUBSUP ? ( SmSubSupNode* )pOper : NULL; + + SmNode* pChild; + SmCaretPosGraphEntry *childLeft; + if( pSubSup && ( pChild = pSubSup->GetSubSup( LSUP ) ) ) { + //Create position in front of pChild + childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + //Visit pChild + pRightMost = childLeft; + pChild->Accept( this ); + //Set right on pRightMost from pChild + pRightMost->SetRight( bodyLeft ); + } + if( pSubSup && ( pChild = pSubSup->GetSubSup( LSUB ) ) ) { + //Create position in front of pChild + childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + //Visit pChild + pRightMost = childLeft; + pChild->Accept( this ); + //Set right on pRightMost from pChild + pRightMost->SetRight( bodyLeft ); + } + if( pSubSup && ( pChild = pSubSup->GetSubSup( CSUP ) ) ) {//TO + //Create position in front of pChild + childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + //Visit pChild + pRightMost = childLeft; + pChild->Accept( this ); + //Set right on pRightMost from pChild + pRightMost->SetRight( bodyLeft ); + } + if( pSubSup && ( pChild = pSubSup->GetSubSup( CSUB ) ) ) { //FROM + //Create position in front of pChild + childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + //Visit pChild + pRightMost = childLeft; + pChild->Accept( this ); + //Set right on pRightMost from pChild + pRightMost->SetRight( bodyLeft ); + } + if( pSubSup && ( pChild = pSubSup->GetSubSup( RSUP ) ) ) { + //Create position in front of pChild + childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + //Visit pChild + pRightMost = childLeft; + pChild->Accept( this ); + //Set right on pRightMost from pChild + pRightMost->SetRight( bodyLeft ); + } + if( pSubSup && ( pChild = pSubSup->GetSubSup( RSUB ) ) ) { + //Create position in front of pChild + childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left ); + //Visit pChild + pRightMost = childLeft; + pChild->Accept( this ); + //Set right on pRightMost from pChild + pRightMost->SetRight( bodyLeft ); + } + + //Return right + pRightMost = right; +} + +void SmCaretPosGraphBuildingVisitor::Visit( SmMatrixNode* pNode ) +{ + SmCaretPosGraphEntry *left = pRightMost, + *right = pGraph->Add( SmCaretPos( pNode, 1 ) ); + + for ( sal_uInt16 i = 0; i < pNode->GetNumRows( ); i++ ) { + SmCaretPosGraphEntry* r = left; + for ( sal_uInt16 j = 0; j < pNode->GetNumCols( ); j++ ){ + SmNode* pSubNode = pNode->GetSubNode( i * pNode->GetNumCols( ) + j ); + + pRightMost = pGraph->Add( SmCaretPos( pSubNode, 0 ), r ); + if( j != 0 || ( pNode->GetNumRows( ) - 1 ) / 2 == i ) + r->SetRight( pRightMost ); + + pSubNode->Accept( this ); + + r = pRightMost; + } + pRightMost->SetRight( right ); + if( ( pNode->GetNumRows( ) - 1 ) / 2 == i ) + right->SetLeft( pRightMost ); + } + + pRightMost = right; +} + +/** Build SmCaretPosGraph for SmTextNode + * + * Lines in an SmTextNode: + * \code + * A B C + * \endcode + * Where A B and C are characters in the text. + * + * Graph over these, where "left" is before the SmTextNode and "right" is after: + * \dot + * digraph Graph{ + * left -> A; + * A -> B + * B -> right; + * }; + * \enddot + * Notice that C and right is the same position here. + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmTextNode* pNode ) +{ + OSL_ENSURE( pNode->GetText( ).Len( ) > 0, "Empty SmTextNode is bad" ); + + int size = pNode->GetText( ).Len( ); + for( int i = 1; i <= size; i++ ){ + SmCaretPosGraphEntry* pRight = pRightMost; + pRightMost = pGraph->Add( SmCaretPos( pNode, i ), pRight ); + pRight->SetRight( pRightMost ); + } +} + +/** Build SmCaretPosGraph for SmBinVerNode + * + * Lines in an SmBinVerNode: + * \code + * A + * ----- + * B + * \endcode + * + * Graph over these, where "left" is before the SmBinVerNode and "right" is after: + * \dot + * digraph Graph{ + * left -> A; + * A -> right; + * B -> right; + * }; + * \enddot + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmBinVerNode* pNode ) +{ + //None if these children can be NULL, see SmBinVerNode::Arrange + SmNode *pNum = pNode->GetSubNode( 0 ), + *pDenom = pNode->GetSubNode( 2 ); + + SmCaretPosGraphEntry *left, + *right, + *numLeft, + *denomLeft; + + //Set left + left = pRightMost; + OSL_ENSURE( pRightMost, "There must be a position in front of this" ); + + //Create right + right = pGraph->Add( SmCaretPos( pNode, 1 ) ); + + //Create numLeft + numLeft = pGraph->Add( SmCaretPos( pNum, 0 ), left ); + left->SetRight( numLeft ); + + //Visit pNum + pRightMost = numLeft; + pNum->Accept( this ); + pRightMost->SetRight( right ); + right->SetLeft( pRightMost ); + + //Create denomLeft + denomLeft = pGraph->Add( SmCaretPos( pDenom, 0 ), left ); + + //Visit pDenom + pRightMost = denomLeft; + pDenom->Accept( this ); + pRightMost->SetRight( right ); + + //Set return parameter + pRightMost = right; +} + +/** Build SmCaretPosGraph for SmVerticalBraceNode + * + * Lines in an SmVerticalBraceNode: + * \code + * pScript + * ________ + * / \ + * pBody + * \endcode + * + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmVerticalBraceNode* pNode ) +{ + SmNode *pBody = pNode->GetSubNode( 0 ), + *pScript = pNode->GetSubNode( 2 ); + //None of these children can be NULL + + SmCaretPosGraphEntry *left, + *bodyLeft, + *scriptLeft, + *right; + + left = pRightMost; + + //Create right + right = pGraph->Add( SmCaretPos( pNode, 1 ) ); + + //Create bodyLeft + bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left ); + left->SetRight( bodyLeft ); + pRightMost = bodyLeft; + pBody->Accept( this ); + pRightMost->SetRight( right ); + right->SetLeft( pRightMost ); + + //Create script + scriptLeft = pGraph->Add( SmCaretPos( pScript, 0 ), left ); + pRightMost = scriptLeft; + pScript->Accept( this ); + pRightMost->SetRight( right ); + + //Set return value + pRightMost = right; +} + +/** Build SmCaretPosGraph for SmBinDiagonalNode + * + * Lines in an SmBinDiagonalNode: + * \code + * A / + * / + * / B + * \endcode + * Where A and B are lines. + * + * Used in formulas such as "A wideslash B" + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmBinDiagonalNode* pNode ) +{ + SmNode *A = pNode->GetSubNode( 0 ), + *B = pNode->GetSubNode( 1 ); + + SmCaretPosGraphEntry *left, + *leftA, + *rightA, + *leftB, + *right; + left = pRightMost; + + //Create right + right = pGraph->Add( SmCaretPos( pNode, 1 ) ); + + //Create left A + leftA = pGraph->Add( SmCaretPos( A, 0 ), left ); + left->SetRight( leftA ); + + //Visit A + pRightMost = leftA; + A->Accept( this ); + rightA = pRightMost; + + //Create left B + leftB = pGraph->Add( SmCaretPos( B, 0 ), rightA ); + rightA->SetRight( leftB ); + + //Visit B + pRightMost = leftB; + B->Accept( this ); + pRightMost->SetRight( right ); + right->SetLeft( pRightMost ); + + //Set return value + pRightMost = right; +} + +//Straigt forward ( I think ) +void SmCaretPosGraphBuildingVisitor::Visit( SmBinHorNode* pNode ) +{ + SmNodeIterator it( pNode ); + while( it.Next( ) ) + it->Accept( this ); +} +void SmCaretPosGraphBuildingVisitor::Visit( SmUnHorNode* pNode ) +{ + // Unary operator node + SmNodeIterator it( pNode ); + while( it.Next( ) ) + it->Accept( this ); + +} + +void SmCaretPosGraphBuildingVisitor::Visit( SmExpressionNode* pNode ) +{ + SmNodeIterator it( pNode ); + while( it.Next( ) ) + it->Accept( this ); +} + +void SmCaretPosGraphBuildingVisitor::Visit( SmFontNode* pNode ) +{ + //Has only got one child, should act as an expression if possible + SmNodeIterator it( pNode ); + while( it.Next( ) ) + it->Accept( this ); +} + +/** Build SmCaretPosGraph for SmBracebodyNode + * Acts as an SmExpressionNode + * + * Below is an example of a formula tree that has multiple children for SmBracebodyNode + * \dot + * digraph { + * labelloc = "t"; + * label= "Equation: \"lbrace i mline i in setZ rbrace\""; + * n0 [label="SmTableNode"]; + * n0 -> n1 [label="0"]; + * n1 [label="SmLineNode"]; + * n1 -> n2 [label="0"]; + * n2 [label="SmExpressionNode"]; + * n2 -> n3 [label="0"]; + * n3 [label="SmBraceNode"]; + * n3 -> n4 [label="0"]; + * n4 [label="SmMathSymbolNode: {"]; + * n3 -> n5 [label="1"]; + * n5 [label="SmBracebodyNode"]; + * n5 -> n6 [label="0"]; + * n6 [label="SmExpressionNode"]; + * n6 -> n7 [label="0"]; + * n7 [label="SmTextNode: i"]; + * n5 -> n8 [label="1"]; + * n8 [label="SmMathSymbolNode: ∣"]; + * n5 -> n9 [label="2"]; + * n9 [label="SmExpressionNode"]; + * n9 -> n10 [label="0"]; + * n10 [label="SmBinHorNode"]; + * n10 -> n11 [label="0"]; + * n11 [label="SmTextNode: i"]; + * n10 -> n12 [label="1"]; + * n12 [label="SmMathSymbolNode: ∈"]; + * n10 -> n13 [label="2"]; + * n13 [label="SmMathSymbolNode: ℤ"]; + * n3 -> n14 [label="2"]; + * n14 [label="SmMathSymbolNode: }"]; + * } + * \enddot + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmBracebodyNode* pNode ) +{ + SmNodeIterator it( pNode ); + while( it.Next( ) ) { + SmCaretPosGraphEntry* pStart = pGraph->Add( SmCaretPos( it.Current(), 0), pRightMost ); + pRightMost->SetRight( pStart ); + pRightMost = pStart; + it->Accept( this ); + } +} + +/** Build SmCaretPosGraph for SmAlignNode + * Acts as an SmExpressionNode, as it only has one child this okay + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmAlignNode* pNode ) +{ + SmNodeIterator it( pNode ); + while( it.Next( ) ) + it->Accept( this ); +} + +/** Build SmCaretPosGraph for SmRootNode + * + * Lines in an SmRootNode: + * \code + * _________ + * A/ + * \/ B + * + * \endcode + * A: pExtra ( optional, can be NULL ), + * B: pBody + * + * Graph over these, where "left" is before the SmRootNode and "right" is after: + * \dot + * digraph Graph{ + * left -> B; + * B -> right; + * A -> B; + * } + * \enddot + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmRootNode* pNode ) +{ + SmNode *pExtra = pNode->GetSubNode( 0 ), //Argument, NULL for sqrt, and SmTextNode if cubicroot + *pBody = pNode->GetSubNode( 2 ); //Body of the root + OSL_ENSURE( pBody, "pBody cannot be NULL" ); + + SmCaretPosGraphEntry *left, + *right, + *bodyLeft, + *bodyRight; + + //Get left and save it + OSL_ENSURE( pRightMost, "There must be a position in front of this" ); + left = pRightMost; + + //Create body left + bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left ); + left->SetRight( bodyLeft ); + + //Create right + right = pGraph->Add( SmCaretPos( pNode, 1 ) ); + + //Visit body + pRightMost = bodyLeft; + pBody->Accept( this ); + bodyRight = pRightMost; + bodyRight->SetRight( right ); + right->SetLeft( bodyRight ); + + //Visit pExtra + if( pExtra ){ + pRightMost = pGraph->Add( SmCaretPos( pExtra, 0 ), left ); + pExtra->Accept( this ); + pRightMost->SetRight( bodyLeft ); + } + + pRightMost = right; +} + +/** Build SmCaretPosGraph for SmPlaceNode + * Consider this a single character. + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmPlaceNode* pNode ) +{ + SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost ); + pRightMost->SetRight( right ); + pRightMost = right; +} + +/** SmErrorNode is context dependent metadata, it can't be selected + * + * @remarks There's no point in deleting, copying and/or moving an instance + * of SmErrorNode as it may not exist in an other context! Thus there are no + * positions to select an SmErrorNode. + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmErrorNode* ) +{ +} + +/** Build SmCaretPosGraph for SmBlankNode + * Consider this a single character, as it is only a blank space + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmBlankNode* pNode ) +{ + SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost ); + pRightMost->SetRight( right ); + pRightMost = right; +} + +/** Build SmCaretPosGraph for SmBraceNode + * + * Lines in an SmBraceNode: + * \code + * | | + * | B | + * | | + * \endcode + * B: Body + * + * Graph over these, where "left" is before the SmBraceNode and "right" is after: + * \dot + * digraph Graph{ + * left -> B; + * B -> right; + * } + * \enddot + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmBraceNode* pNode ) +{ + SmNode* pBody = pNode->GetSubNode( 1 ); + + SmCaretPosGraphEntry *left = pRightMost, + *right = pGraph->Add( SmCaretPos( pNode, 1 ) ); + + if( pBody->GetType() != NBRACEBODY ) { + pRightMost = pGraph->Add( SmCaretPos( pBody, 0 ), left ); + left->SetRight( pRightMost ); + }else + pRightMost = left; + + pBody->Accept( this ); + pRightMost->SetRight( right ); + right->SetLeft( pRightMost ); + + pRightMost = right; +} + +/** Build SmCaretPosGraph for SmAttributNode + * + * Lines in an SmAttributNode: + * \code + * Attr + * Body + * \endcode + * + * There's a body and an attribute, the construction is used for "widehat A", where "A" is the body + * and "^" is the attribute ( note GetScaleMode( ) on SmAttributNode tells how the attribute should be + * scaled ). + */ +void SmCaretPosGraphBuildingVisitor::Visit( SmAttributNode* pNode ) +{ + SmNode *pAttr = pNode->GetSubNode( 0 ), + *pBody = pNode->GetSubNode( 1 ); + //None of the children can be NULL + + SmCaretPosGraphEntry *left = pRightMost, + *attrLeft, + *bodyLeft, + *bodyRight, + *right; + + //Creating bodyleft + bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left ); + left->SetRight( bodyLeft ); + + //Creating right + right = pGraph->Add( SmCaretPos( pNode, 1 ) ); + + //Visit the body + pRightMost = bodyLeft; + pBody->Accept( this ); + bodyRight = pRightMost; + bodyRight->SetRight( right ); + right->SetLeft( bodyRight ); + + //Create attrLeft + attrLeft = pGraph->Add( SmCaretPos( pAttr, 0 ), left ); + + //Visit attribute + pRightMost = attrLeft; + pAttr->Accept( this ); + pRightMost->SetRight( right ); + + //Set return value + pRightMost = right; +} + +//Consider these single symboles +void SmCaretPosGraphBuildingVisitor::Visit( SmSpecialNode* pNode ) +{ + SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost ); + pRightMost->SetRight( right ); + pRightMost = right; +} +void SmCaretPosGraphBuildingVisitor::Visit( SmGlyphSpecialNode* pNode ) +{ + SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost ); + pRightMost->SetRight( right ); + pRightMost = right; +} +void SmCaretPosGraphBuildingVisitor::Visit( SmMathSymbolNode* pNode ) +{ + SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost ); + pRightMost->SetRight( right ); + pRightMost = right; +} + +void SmCaretPosGraphBuildingVisitor::Visit( SmRootSymbolNode* ) +{ + //Do nothing +} +void SmCaretPosGraphBuildingVisitor::Visit( SmRectangleNode* ) +{ + //Do nothing +} +void SmCaretPosGraphBuildingVisitor::Visit( SmPolyLineNode* ) +{ + //Do nothing +} + +/////////////////////////////// SmCloningVisitor /////////////////////////////// + +SmNode* SmCloningVisitor::Clone( SmNode* pNode ) +{ + SmNode* pCurrResult = pResult; + pNode->Accept( this ); + SmNode* pClone = pResult; + pResult = pCurrResult; + return pClone; +} + +void SmCloningVisitor::CloneNodeAttr( SmNode* pSource, SmNode* pTarget ) +{ + pTarget->SetScaleMode( pSource->GetScaleMode( ) ); + //Other attributes are set when prepare or arrange is executed + //and may depend on stuff not being cloned here. +} + +void SmCloningVisitor::CloneKids( SmStructureNode* pSource, SmStructureNode* pTarget ) +{ + //Cache current result + SmNode* pCurrResult = pResult; + + //Create array for holding clones + sal_uInt16 nSize = pSource->GetNumSubNodes( ); + SmNodeArray aNodes( nSize ); + + //Clone children + SmNode* pKid; + for( sal_uInt16 i = 0; i < nSize; i++ ){ + if( NULL != ( pKid = pSource->GetSubNode( i ) ) ) + pKid->Accept( this ); + else + pResult = NULL; + aNodes[i] = pResult; + } + + //Set subnodes of pTarget + pTarget->SetSubNodes( aNodes ); + + //Restore result as where prior to call + pResult = pCurrResult; +} + +void SmCloningVisitor::Visit( SmTableNode* pNode ) +{ + SmTableNode* pClone = new SmTableNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmBraceNode* pNode ) +{ + SmBraceNode* pClone = new SmBraceNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmBracebodyNode* pNode ) +{ + SmBracebodyNode* pClone = new SmBracebodyNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmOperNode* pNode ) +{ + SmOperNode* pClone = new SmOperNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmAlignNode* pNode ) +{ + SmAlignNode* pClone = new SmAlignNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmAttributNode* pNode ) +{ + SmAttributNode* pClone = new SmAttributNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmFontNode* pNode ) +{ + SmFontNode* pClone = new SmFontNode( pNode->GetToken( ) ); + pClone->SetSizeParameter( pNode->GetSizeParameter( ), pNode->GetSizeType( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmUnHorNode* pNode ) +{ + SmUnHorNode* pClone = new SmUnHorNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmBinHorNode* pNode ) +{ + SmBinHorNode* pClone = new SmBinHorNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmBinVerNode* pNode ) +{ + SmBinVerNode* pClone = new SmBinVerNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmBinDiagonalNode* pNode ) +{ + SmBinDiagonalNode *pClone = new SmBinDiagonalNode( pNode->GetToken( ) ); + pClone->SetAscending( pNode->IsAscending( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmSubSupNode* pNode ) +{ + SmSubSupNode *pClone = new SmSubSupNode( pNode->GetToken( ) ); + pClone->SetUseLimits( pNode->IsUseLimits( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmMatrixNode* pNode ) +{ + SmMatrixNode *pClone = new SmMatrixNode( pNode->GetToken( ) ); + pClone->SetRowCol( pNode->GetNumRows( ), pNode->GetNumCols( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmPlaceNode* pNode ) +{ + pResult = new SmPlaceNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pResult ); +} + +void SmCloningVisitor::Visit( SmTextNode* pNode ) +{ + SmTextNode* pClone = new SmTextNode( pNode->GetToken( ), pNode->GetFontDesc( ) ); + pClone->ChangeText( pNode->GetText( ) ); + CloneNodeAttr( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmSpecialNode* pNode ) +{ + pResult = new SmSpecialNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pResult ); +} + +void SmCloningVisitor::Visit( SmGlyphSpecialNode* pNode ) +{ + pResult = new SmGlyphSpecialNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pResult ); +} + +void SmCloningVisitor::Visit( SmMathSymbolNode* pNode ) +{ + pResult = new SmMathSymbolNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pResult ); +} + +void SmCloningVisitor::Visit( SmBlankNode* pNode ) +{ + SmBlankNode* pClone = new SmBlankNode( pNode->GetToken( ) ); + pClone->SetBlankNum( pNode->GetBlankNum( ) ); + pResult = pClone; + CloneNodeAttr( pNode, pResult ); +} + +void SmCloningVisitor::Visit( SmErrorNode* pNode ) +{ + //PE_NONE is used the information have been discarded and isn't used + pResult = new SmErrorNode( PE_NONE, pNode->GetToken( ) ); + CloneNodeAttr( pNode, pResult ); +} + +void SmCloningVisitor::Visit( SmLineNode* pNode ) +{ + SmLineNode* pClone = new SmLineNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmExpressionNode* pNode ) +{ + SmExpressionNode* pClone = new SmExpressionNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmPolyLineNode* pNode ) +{ + pResult = new SmPolyLineNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pResult ); +} + +void SmCloningVisitor::Visit( SmRootNode* pNode ) +{ + SmRootNode* pClone = new SmRootNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +void SmCloningVisitor::Visit( SmRootSymbolNode* pNode ) +{ + pResult = new SmRootSymbolNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pResult ); +} + +void SmCloningVisitor::Visit( SmRectangleNode* pNode ) +{ + pResult = new SmRectangleNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pResult ); +} + +void SmCloningVisitor::Visit( SmVerticalBraceNode* pNode ) +{ + SmVerticalBraceNode* pClone = new SmVerticalBraceNode( pNode->GetToken( ) ); + CloneNodeAttr( pNode, pClone ); + CloneKids( pNode, pClone ); + pResult = pClone; +} + +/////////////////////////////// SmSelectionDrawingVisitor /////////////////////////////// + +SmSelectionDrawingVisitor::SmSelectionDrawingVisitor( OutputDevice& rDevice, SmNode* pTree, Point Offset ) + : rDev( rDevice ) { + bHasSelectionArea = false; + + //Visit everything + OSL_ENSURE( pTree, "pTree can't be null!" ); + if( pTree ) + pTree->Accept( this ); + + //Draw selection if there's any + if( bHasSelectionArea ){ + aSelectionArea.Move( Offset.X( ), Offset.Y( ) ); + + //Save device state + rDev.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); + //Change colors + rDev.SetLineColor( ); + rDev.SetFillColor( Color( COL_LIGHTGRAY ) ); + + //Draw rectangle + rDev.DrawRect( aSelectionArea ); + + //Restore device state + rDev.Pop( ); + } +} + +void SmSelectionDrawingVisitor::ExtendSelectionArea( Rectangle aArea ) +{ + if ( ! bHasSelectionArea ) { + aSelectionArea = aArea; + bHasSelectionArea = true; + } else + aSelectionArea.Union( aArea ); +} + +void SmSelectionDrawingVisitor::DefaultVisit( SmNode* pNode ) +{ + if( pNode->IsSelected( ) ) + ExtendSelectionArea( pNode->AsRectangle( ) ); + VisitChildren( pNode ); +} + +void SmSelectionDrawingVisitor::VisitChildren( SmNode* pNode ) +{ + SmNodeIterator it( pNode ); + while( it.Next( ) ) + it->Accept( this ); +} + +void SmSelectionDrawingVisitor::Visit( SmTextNode* pNode ) +{ + if( pNode->IsSelected( ) ){ + rDev.Push( PUSH_TEXTCOLOR | PUSH_FONT ); + + rDev.SetFont( pNode->GetFont( ) ); + Point Position = pNode->GetTopLeft( ); + long left = Position.getX( ) + rDev.GetTextWidth( pNode->GetText( ), 0, pNode->GetSelectionStart( ) ); + long right = Position.getX( ) + rDev.GetTextWidth( pNode->GetText( ), 0, pNode->GetSelectionEnd( ) ); + long top = Position.getY( ); + long bottom = top + pNode->GetHeight( ); + Rectangle rect( left, top, right, bottom ); + + ExtendSelectionArea( rect ); + + rDev.Pop( ); + } +} + +/////////////////////////////// SmNodeToTextVisitor /////////////////////////////// + +void SmNodeToTextVisitor::Visit( SmTableNode* pNode ) +{ + if( pNode->GetToken( ).eType == TBINOM ) { + Append( "{ binom" ); + LineToText( pNode->GetSubNode( 0 ) ); + LineToText( pNode->GetSubNode( 1 ) ); + Append("} "); + } else if( pNode->GetToken( ).eType == TSTACK ) { + Append( "stack{ " ); + SmNodeIterator it( pNode ); + it.Next( ); + while( true ) { + LineToText( it.Current( ) ); + if( it.Next( ) ) { + Separate( ); + Append( "# " ); + }else + break; + } + Separate( ); + Append( "}" ); + } else { //Assume it's a toplevel table, containing lines + SmNodeIterator it( pNode ); + it.Next( ); + while( true ) { + Separate( ); + it->Accept( this ); + if( it.Next( ) ) { + Separate( ); + Append( "newline" ); + }else + break; + } + } +} + +void SmNodeToTextVisitor::Visit( SmBraceNode* pNode ) +{ + SmNode *pLeftBrace = pNode->GetSubNode( 0 ), + *pBody = pNode->GetSubNode( 1 ), + *pRightBrace = pNode->GetSubNode( 2 ); + //Handle special case where it's absolute function + if( pNode->GetToken( ).eType == TABS ) { + Append( "abs" ); + LineToText( pBody ); + } else { + if( pNode->GetScaleMode( ) == SCALE_HEIGHT ) + Append( "left " ); + pLeftBrace->Accept( this ); + Separate( ); + pBody->Accept( this ); + Separate( ); + if( pNode->GetScaleMode( ) == SCALE_HEIGHT ) + Append( "right " ); + pRightBrace->Accept( this ); + } +} + +void SmNodeToTextVisitor::Visit( SmBracebodyNode* pNode ) +{ + SmNodeIterator it( pNode ); + while( it.Next( ) ){ + Separate( ); + it->Accept( this ); + } +} + +void SmNodeToTextVisitor::Visit( SmOperNode* pNode ) +{ + Append( pNode->GetToken( ).aText ); + Separate( ); + if( pNode->GetToken( ).eType == TOPER ){ + //There's an SmGlyphSpecialNode if eType == TOPER + if( pNode->GetSubNode( 0 )->GetType( ) == NSUBSUP ) + Append( pNode->GetSubNode( 0 )->GetSubNode( 0 )->GetToken( ).aText ); + else + Append( pNode->GetSubNode( 0 )->GetToken( ).aText ); + } + if( pNode->GetSubNode( 0 )->GetType( ) == NSUBSUP ) { + SmSubSupNode *pSubSup = ( SmSubSupNode* )pNode->GetSubNode( 0 ); + SmNode* pChild; + if( ( pChild = pSubSup->GetSubSup( LSUP ) ) ) { + Separate( ); + Append( "lsup { " ); + LineToText( pChild ); + Append( "} " ); + } + if( ( pChild = pSubSup->GetSubSup( LSUB ) ) ) { + Separate( ); + Append( "lsub { " ); + LineToText( pChild ); + Append( "} " ); + } + if( ( pChild = pSubSup->GetSubSup( RSUP ) ) ) { + Separate( ); + Append( "rsup { " ); + LineToText( pChild ); + Append( "} " ); + } + if( ( pChild = pSubSup->GetSubSup( RSUB ) ) ) { + Separate( ); + Append( "rsub { " ); + LineToText( pChild ); + Append( "} " ); + } + if( ( pChild = pSubSup->GetSubSup( CSUP ) ) ) { + Separate( ); + Append( "csup { " ); + LineToText( pChild ); + Append( "} " ); + } + if( ( pChild = pSubSup->GetSubSup( CSUB ) ) ) { + Separate( ); + Append( "csub { " ); + LineToText( pChild ); + Append( "} " ); + } + } + LineToText( pNode->GetSubNode( 1 ) ); +} + +void SmNodeToTextVisitor::Visit( SmAlignNode* pNode ) +{ + Append( pNode->GetToken( ).aText ); + LineToText( pNode->GetSubNode( 0 ) ); +} + +void SmNodeToTextVisitor::Visit( SmAttributNode* pNode ) +{ + Append( pNode->GetToken( ).aText ); + LineToText( pNode->GetSubNode( 1 ) ); +} + +void SmNodeToTextVisitor::Visit( SmFontNode* pNode ) +{ + switch ( pNode->GetToken( ).eType ) + { + case TBOLD: + Append( "bold " ); + break; + case TNBOLD: + Append( "nbold " ); + break; + case TITALIC: + Append( "italic " ); + break; + case TNITALIC: + Append( "nitalic " ); + break; + case TPHANTOM: + Append( "phantom " ); + break; + case TSIZE: + { + Append( "size " ); + switch ( pNode->GetSizeType( ) ) + { + case FNTSIZ_PLUS: + Append( "+" ); + break; + case FNTSIZ_MINUS: + Append( "-" ); + break; + case FNTSIZ_MULTIPLY: + Append( "*" ); + break; + case FNTSIZ_DIVIDE: + Append( "/" ); + break; + case FNTSIZ_ABSOLUT: + default: + break; + } + Append( String( ::rtl::math::doubleToUString( + static_cast<double>( pNode->GetSizeParameter( ) ), + rtl_math_StringFormat_Automatic, + rtl_math_DecimalPlaces_Max, '.', sal_True ) ) ); + Append( " " ); + } + break; + case TBLACK: + Append( "color black " ); + break; + case TWHITE: + Append( "color white " ); + break; + case TRED: + Append( "color red " ); + break; + case TGREEN: + Append( "color green " ); + break; + case TBLUE: + Append( "color blue " ); + break; + case TCYAN: + Append( "color cyan " ); + break; + case TMAGENTA: + Append( "color magenta " ); + break; + case TYELLOW: + Append( "color yellow " ); + break; + case TSANS: + Append( "font sans " ); + break; + case TSERIF: + Append( "font serif " ); + break; + case TFIXED: + Append( "font fixed " ); + break; + default: + break; + } + LineToText( pNode->GetSubNode( 1 ) ); +} + +void SmNodeToTextVisitor::Visit( SmUnHorNode* pNode ) +{ + SmNodeIterator it( pNode, pNode->GetSubNode( 1 )->GetToken( ).eType == TFACT ); + while( it.Next( ) ) { + Separate( ); + it->Accept( this ); + } +} + +void SmNodeToTextVisitor::Visit( SmBinHorNode* pNode ) +{ + SmNode *pLeft = pNode->GetSubNode( 0 ), + *pOper = pNode->GetSubNode( 1 ), + *pRight = pNode->GetSubNode( 2 ); + Separate( ); + pLeft->Accept( this ); + Separate( ); + pOper->Accept( this ); + Separate( ); + pRight->Accept( this ); + Separate( ); +} + +void SmNodeToTextVisitor::Visit( SmBinVerNode* pNode ) +{ + SmNode *pNum = pNode->GetSubNode( 0 ), + *pDenom = pNode->GetSubNode( 2 ); + Append( "{ " ); + LineToText( pNum ); + Append( "over" ); + LineToText( pDenom ); + Append( "} " ); +} + +void SmNodeToTextVisitor::Visit( SmBinDiagonalNode* pNode ) +{ + SmNode *pLeftOperand = pNode->GetSubNode( 0 ), + *pRightOperand = pNode->GetSubNode( 1 ); + Append( "{ " ); + LineToText( pLeftOperand ); + Separate( ); + Append( "wideslash " ); + LineToText( pRightOperand ); + Append( "} " ); +} + +void SmNodeToTextVisitor::Visit( SmSubSupNode* pNode ) +{ + LineToText( pNode->GetBody( ) ); + SmNode *pChild; + if( ( pChild = pNode->GetSubSup( LSUP ) ) ) { + Separate( ); + Append( "lsup " ); + LineToText( pChild ); + } + if( ( pChild = pNode->GetSubSup( LSUB ) ) ) { + Separate( ); + Append( "lsub " ); + LineToText( pChild ); + } + if( ( pChild = pNode->GetSubSup( RSUP ) ) ) { + Separate( ); + Append( "rsup " ); + LineToText( pChild ); + } + if( ( pChild = pNode->GetSubSup( RSUB ) ) ) { + Separate( ); + Append( "rsub " ); + LineToText( pChild ); + } + if( ( pChild = pNode->GetSubSup( CSUP ) ) ) { + Separate( ); + Append( "csup " ); + LineToText( pChild ); + } + if( ( pChild = pNode->GetSubSup( CSUB ) ) ) { + Separate( ); + Append( "csub " ); + LineToText( pChild ); + } +} + +void SmNodeToTextVisitor::Visit( SmMatrixNode* pNode ) +{ + Append( "matrix{" ); + for ( sal_uInt16 i = 0; i < pNode->GetNumRows( ); i++ ) { + for ( sal_uInt16 j = 0; j < pNode->GetNumCols( ); j++ ) { + SmNode* pSubNode = pNode->GetSubNode( i * pNode->GetNumCols( ) + j ); + Separate( ); + pSubNode->Accept( this ); + Separate( ); + if( j != pNode->GetNumCols( ) - 1 ) + Append( "#" ); + } + Separate( ); + if( i != pNode->GetNumRows( ) - 1 ) + Append( "##" ); + } + Append( "} " ); +} + +void SmNodeToTextVisitor::Visit( SmPlaceNode* ) +{ + Append( "<?>" ); +} + +void SmNodeToTextVisitor::Visit( SmTextNode* pNode ) +{ + //TODO: This method might need improvements, see SmTextNode::CreateTextFromNode + if( pNode->GetToken( ).eType == TTEXT ) + Append( "\"" ); + Append( pNode->GetText( ) ); + if( pNode->GetToken( ).eType == TTEXT ) + Append( "\"" ); +} + +void SmNodeToTextVisitor::Visit( SmSpecialNode* pNode ) +{ + Append( pNode->GetToken( ).aText ); +} + +void SmNodeToTextVisitor::Visit( SmGlyphSpecialNode* pNode ) +{ + if( pNode->GetToken( ).eType == TBOPER ) + Append( "boper " ); + else + Append( "uoper " ); + Append( pNode->GetToken( ).aText ); +} + +void SmNodeToTextVisitor::Visit( SmMathSymbolNode* pNode ) +{ + Append( pNode->GetToken( ).aText ); +} + +void SmNodeToTextVisitor::Visit( SmBlankNode* pNode ) +{ + Append( pNode->GetToken( ).aText ); +} + +void SmNodeToTextVisitor::Visit( SmErrorNode* ) +{ +} + +void SmNodeToTextVisitor::Visit( SmLineNode* pNode ) +{ + SmNodeIterator it( pNode ); + while( it.Next( ) ){ + Separate( ); + it->Accept( this ); + } +} + +void SmNodeToTextVisitor::Visit( SmExpressionNode* pNode ) +{ + bool bracketsNeeded = pNode->GetNumSubNodes() != 1 || pNode->GetSubNode(0)->GetType() == NBINHOR; + if (bracketsNeeded) { + Append( "{ " ); + } + SmNodeIterator it( pNode ); + while( it.Next( ) ) { + it->Accept( this ); + Separate( ); + } + if (bracketsNeeded) { + Append( "} " ); + } +} + +void SmNodeToTextVisitor::Visit( SmPolyLineNode* ) +{ +} + +void SmNodeToTextVisitor::Visit( SmRootNode* pNode ) +{ + SmNode *pExtra = pNode->GetSubNode( 0 ), + *pBody = pNode->GetSubNode( 2 ); + if( pExtra ) { + Append( "nroot" ); + LineToText( pExtra ); + } else + Append( "sqrt" ); + LineToText( pBody ); +} + +void SmNodeToTextVisitor::Visit( SmRootSymbolNode* ) +{ +} + +void SmNodeToTextVisitor::Visit( SmRectangleNode* ) +{ +} + +void SmNodeToTextVisitor::Visit( SmVerticalBraceNode* pNode ) +{ + SmNode *pBody = pNode->GetSubNode( 0 ), + *pScript = pNode->GetSubNode( 2 ); + LineToText( pBody ); + Append( pNode->GetToken( ).aText ); + LineToText( pScript ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |