| /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| /* |
| * This file is part of the Collabora Office project. |
| * |
| * This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| * |
| * This file incorporates work covered by the following license notice: |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed |
| * with this work for additional information regarding copyright |
| * ownership. The ASF licenses this file to you under the Apache |
| * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 . |
| */ |
| #include "vbaselection.hxx" |
| #include <utility> |
| #include <vbahelper/vbahelper.hxx> |
| #include "vbarange.hxx" |
| #include "vbafind.hxx" |
| #include <com/sun/star/text/XTextRange.hpp> |
| #include <com/sun/star/text/XTextTable.hpp> |
| #include <com/sun/star/text/XTextTableCursor.hpp> |
| #include <com/sun/star/table/XCell.hpp> |
| #include <basic/sberrors.hxx> |
| #include <ooo/vba/word/WdUnits.hpp> |
| #include <ooo/vba/word/WdMovementType.hpp> |
| #include <ooo/vba/word/WdGoToItem.hpp> |
| #include <ooo/vba/word/WdGoToDirection.hpp> |
| #include <ooo/vba/word/XBookmark.hpp> |
| #include <ooo/vba/word/XApplication.hpp> |
| #include <ooo/vba/word/WdCollapseDirection.hpp> |
| #include <com/sun/star/text/XPageCursor.hpp> |
| #include <unotbl.hxx> |
| #include <unocoll.hxx> |
| #include "vbatable.hxx" |
| #include <com/sun/star/view/XViewCursor.hpp> |
| #include <com/sun/star/view/XLineCursor.hpp> |
| #include <com/sun/star/text/XWordCursor.hpp> |
| #include <com/sun/star/text/XParagraphCursor.hpp> |
| #include <ooo/vba/word/WdInformation.hpp> |
| #include <ooo/vba/word/WdHeaderFooterIndex.hpp> |
| #include <ooo/vba/word/WdSeekView.hpp> |
| #include "vbainformationhelper.hxx" |
| #include "vbafield.hxx" |
| #include "vbaheaderfooter.hxx" |
| #include "vbaheaderfooterhelper.hxx" |
| #include <vbahelper/vbashaperange.hxx> |
| #include <com/sun/star/drawing/ShapeCollection.hpp> |
| #include <com/sun/star/drawing/XDrawPageSupplier.hpp> |
| #include <com/sun/star/drawing/XDrawPage.hpp> |
| #include "vbarows.hxx" |
| #include "vbacolumns.hxx" |
| #include "vbatablehelper.hxx" |
| #include "vbacells.hxx" |
| #include "vbaview.hxx" |
| #include "vbaparagraph.hxx" |
| #include "vbastyle.hxx" |
| #include <docsh.hxx> |
| #include <tblenum.hxx> |
| #include <sal/log.hxx> |
| #include <fesh.hxx> |
| #include <unotxdoc.hxx> |
| #include <unodraw.hxx> |
| #include <unobasestyle.hxx> |
| #include <unotextcursor.hxx> |
| |
| using namespace ::ooo::vba; |
| using namespace ::com::sun::star; |
| |
| SwVbaSelection::SwVbaSelection( const uno::Reference< ooo::vba::XHelperInterface >& rParent, |
| const uno::Reference< uno::XComponentContext >& rContext, |
| rtl::Reference< SwXTextDocument > xModel ) |
| : SwVbaSelection_BASE( rParent, rContext ), |
| mxModel(std::move( xModel )) |
| { |
| mxTextViewCursor = word::getXTextViewCursor( mxModel ); |
| } |
| |
| SwVbaSelection::~SwVbaSelection() |
| { |
| } |
| |
| uno::Reference< text::XTextRange > SwVbaSelection::GetSelectedRange() |
| { |
| uno::Reference< text::XTextRange > xTextRange; |
| uno::Reference< lang::XServiceInfo > xServiceInfo( mxModel->getCurrentSelection(), uno::UNO_QUERY_THROW ); |
| if( !xServiceInfo->supportsService(u"com.sun.star.text.TextRanges"_ustr) ) |
| { |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| |
| uno::Reference< container::XIndexAccess > xTextRanges( xServiceInfo, uno::UNO_QUERY_THROW ); |
| if( xTextRanges->getCount() > 0 ) |
| { |
| // if there are multiple selection, just return the last selected Range. |
| xTextRange.set( xTextRanges->getByIndex( xTextRanges->getCount()-1 ), uno::UNO_QUERY_THROW ); |
| } |
| |
| return xTextRange; |
| } |
| |
| uno::Reference< word::XRange > SAL_CALL |
| SwVbaSelection::getRange() |
| { |
| uno::Reference< text::XTextRange > xTextRange = GetSelectedRange(); |
| return uno::Reference< word::XRange >( new SwVbaRange( this, mxContext, mxModel, xTextRange->getStart(), xTextRange->getEnd(), mxTextViewCursor->getText() ) ); |
| } |
| |
| OUString SAL_CALL |
| SwVbaSelection::getText() |
| { |
| return getRange()->getText(); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::setText( const OUString& rText ) |
| { |
| getRange()->setText( rText ); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::TypeText( const OUString& rText ) |
| { |
| // FIXME: handle the property Options.ReplaceSelection, the default value is true |
| setText( rText ); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::HomeKey( const uno::Any& _unit, const uno::Any& _extend ) |
| { |
| sal_Int32 nUnit = word::WdUnits::wdLine; |
| sal_Int32 nExtend = word::WdMovementType::wdMove; |
| _unit >>= nUnit; |
| _extend >>= nExtend; |
| bool bExtend = nExtend == word::WdMovementType::wdExtend; |
| |
| switch( nUnit ) |
| { |
| case word::WdUnits::wdStory: |
| { |
| // go to the valid text first so that the current view cursor is valid to call gotoRange. |
| word::gotoSelectedObjectAnchor(mxModel); |
| // go to the begin of the document |
| uno::Reference< text::XText > xCurrentText = word::getCurrentXText( mxModel ); |
| uno::Reference< text::XTextRange > xFirstRange = word::getFirstObjectPosition( xCurrentText ); |
| mxTextViewCursor->gotoRange( xFirstRange, bExtend ); |
| break; |
| } |
| case word::WdUnits::wdLine: |
| { |
| // go to the begin of the Line |
| uno::Reference< view::XLineCursor > xLineCursor( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| xLineCursor->gotoStartOfLine( bExtend ); |
| break; |
| } |
| default: |
| { |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| } |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::EndKey( const uno::Any& _unit, const uno::Any& _extend ) |
| { |
| sal_Int32 nUnit = word::WdUnits::wdLine; |
| sal_Int32 nExtend = word::WdMovementType::wdMove; |
| _unit >>= nUnit; |
| _extend >>= nExtend; |
| bool bExtend = nExtend == word::WdMovementType::wdExtend; |
| |
| switch( nUnit ) |
| { |
| case word::WdUnits::wdStory: |
| { |
| // go to the valid text first so that the current view cursor is valid to call gotoRange. |
| word::gotoSelectedObjectAnchor(mxModel); |
| // go to the end of the document |
| uno::Reference< text::XText > xCurrentText = word::getCurrentXText( mxModel ); |
| uno::Reference< text::XTextRange > xEnd = xCurrentText->getEnd(); |
| mxTextViewCursor->gotoRange( xEnd, bExtend ); |
| break; |
| } |
| case word::WdUnits::wdLine: |
| { |
| // go to the end of the Line |
| uno::Reference< view::XLineCursor > xLineCursor( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| xLineCursor->gotoEndOfLine( bExtend ); |
| break; |
| } |
| default: |
| { |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| } |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::Delete( const uno::Any& _unit, const uno::Any& _count ) |
| { |
| sal_Int32 nUnit = word::WdUnits::wdLine; |
| sal_Int32 nCount = 0; |
| if( _count.hasValue() ) |
| _count >>= nCount; |
| if( _unit.hasValue() && ( nCount > 0 ) ) |
| { |
| _unit >>= nUnit; |
| switch( nUnit ) |
| { |
| case word::WdUnits::wdCharacter: |
| { |
| if( HasSelection() ) |
| nCount--; |
| mxTextViewCursor->goRight( nCount, true ); |
| break; |
| } |
| default: |
| { |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| } |
| } |
| dispatchRequests( static_cast<SfxBaseModel*>(mxModel.get()), u".uno:Delete"_ustr ); |
| } |
| |
| void |
| SwVbaSelection::Move( const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend, word::E_DIRECTION eDirection ) |
| { |
| sal_Int32 nUnit = word::WdUnits::wdCharacter; |
| sal_Int32 nCount = 1; |
| sal_Int32 nExtend = word::WdMovementType::wdMove; |
| |
| if( _unit.hasValue() ) |
| _unit >>= nUnit; |
| if( _count.hasValue() ) |
| _count >>= nCount; |
| if( _extend.hasValue() ) |
| _extend >>= nExtend; |
| |
| if( nCount == 0 ) |
| return; |
| |
| bool bExpand = nExtend != word::WdMovementType::wdMove; |
| |
| switch( nUnit ) |
| { |
| case word::WdUnits::wdCell: |
| { |
| if( nExtend == word::WdMovementType::wdExtend ) |
| { |
| DebugHelper::basicexception(ERRCODE_BASIC_BAD_ARGUMENT, {}); |
| return; |
| } |
| NextCell( nCount, eDirection ); |
| break; |
| } |
| case word::WdUnits::wdLine: |
| { |
| if( eDirection == word::MOVE_LEFT || eDirection == word::MOVE_RIGHT ) |
| { |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| uno::Reference< view::XViewCursor > xViewCursor( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| if( eDirection == word::MOVE_UP ) |
| xViewCursor->goUp( nCount, bExpand ); |
| else if( eDirection == word::MOVE_DOWN ) |
| xViewCursor->goDown( nCount, bExpand ); |
| break; |
| } |
| case word::WdUnits::wdCharacter: |
| { |
| if( eDirection == word::MOVE_UP || eDirection == word::MOVE_DOWN ) |
| { |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| if( word::gotoSelectedObjectAnchor( mxModel ) ) |
| { |
| nCount--; |
| } |
| uno::Reference< view::XViewCursor > xViewCursor( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| if( eDirection == word::MOVE_LEFT ) |
| { |
| // if current select is a cellrange or table, |
| // the first count of move should move to the first selected cell. |
| uno::Reference< text::XTextTableCursor > xTextTableCursor( mxModel->getCurrentSelection(), uno::UNO_QUERY ); |
| if ( xTextTableCursor.is() ) |
| { |
| uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| uno::Reference< text::XTextTable > xTextTable; |
| xCursorProps->getPropertyValue(u"TextTable"_ustr) >>= xTextTable; |
| if( xTextTable.is() ) |
| { |
| uno::Reference< text::XTextRange > xRange( xTextTable->getCellByName( xTextTableCursor->getRangeName()), uno::UNO_QUERY_THROW ); |
| mxTextViewCursor->gotoRange( xRange->getStart(), bExpand ); |
| nCount--; |
| } |
| } |
| xViewCursor->goLeft( nCount, bExpand ); |
| } |
| else if( eDirection == word::MOVE_RIGHT ) |
| xViewCursor->goRight( nCount, bExpand ); |
| break; |
| } |
| case word::WdUnits::wdWord: |
| case word::WdUnits::wdParagraph: |
| { |
| uno::Reference< text::XTextRange > xRange = GetSelectedRange(); |
| uno::Reference< text::XText > xText = xRange->getText(); |
| uno::Reference< text::XTextCursor > xTextCursor = xText->createTextCursorByRange( xRange ); |
| if( nUnit == word::WdUnits::wdParagraph ) |
| { |
| if( eDirection == word::MOVE_LEFT || eDirection == word::MOVE_RIGHT ) |
| { |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| rtl::Reference< SwXTextCursor > xParagraphCursor = dynamic_cast<SwXTextCursor*>( xTextCursor.get() ); |
| if (!xParagraphCursor) |
| throw uno::RuntimeException(); |
| for( sal_Int32 i=0; i<nCount; i++ ) |
| { |
| if( ( eDirection == word::MOVE_UP ) && !xParagraphCursor->gotoPreviousParagraph( bExpand ) ) |
| break; |
| else if( ( eDirection == word::MOVE_DOWN ) && !xParagraphCursor->gotoNextParagraph( bExpand ) ) |
| break; |
| } |
| } |
| else if( nUnit == word::WdUnits::wdWord ) |
| { |
| if( eDirection == word::MOVE_UP || eDirection == word::MOVE_DOWN ) |
| { |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| uno::Reference< text::XWordCursor > xWordCursor( xTextCursor, uno::UNO_QUERY_THROW ); |
| for( sal_Int32 i=0; i<nCount; i++ ) |
| { |
| if( (eDirection == word::MOVE_LEFT ) && !xWordCursor->gotoPreviousWord( bExpand ) ) |
| break; |
| else if( ( eDirection == word::MOVE_RIGHT ) && !xWordCursor->gotoNextWord( bExpand ) ) |
| break; |
| } |
| } |
| mxTextViewCursor->gotoRange( xTextCursor->getStart(), false ); |
| mxTextViewCursor->gotoRange( xTextCursor->getEnd(), true ); |
| break; |
| } |
| default: |
| { |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| } |
| } |
| |
| void SwVbaSelection::NextCell(sal_Int32 nCount, word::E_DIRECTION eDirection) |
| { |
| uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| uno::Reference< text::XTextTable > xTextTable; |
| uno::Reference< table::XCell > xCell; |
| xCursorProps->getPropertyValue(u"TextTable"_ustr) >>= xTextTable; |
| xCursorProps->getPropertyValue(u"Cell"_ustr) >>= xCell; |
| if( !xTextTable.is() || !xCell.is() ) |
| { |
| DebugHelper::basicexception(ERRCODE_BASIC_BAD_ARGUMENT, {}); |
| return; |
| } |
| uno::Reference< beans::XPropertySet > xCellProps( xCell, uno::UNO_QUERY_THROW ); |
| OUString aCellName; |
| xCellProps->getPropertyValue(u"CellName"_ustr) >>= aCellName; |
| uno::Reference< text::XTextTableCursor > xTextTableCursor = xTextTable->createCursorByCellName( aCellName ); |
| // move the table cursor |
| switch( eDirection ) |
| { |
| case word::MOVE_LEFT: |
| { |
| xTextTableCursor->goLeft( nCount, false ); |
| break; |
| } |
| case word::MOVE_RIGHT: |
| { |
| xTextTableCursor->goRight( nCount, false ); |
| break; |
| } |
| case word::MOVE_UP: |
| { |
| xTextTableCursor->goUp( nCount, false ); |
| break; |
| } |
| case word::MOVE_DOWN: |
| { |
| xTextTableCursor->goDown( nCount, false ); |
| break; |
| } |
| default: |
| { |
| DebugHelper::basicexception(ERRCODE_BASIC_BAD_ARGUMENT, {}); |
| return; |
| } |
| } |
| // move the view cursor |
| xCell = xTextTable->getCellByName( xTextTableCursor->getRangeName() ); |
| mxTextViewCursor->gotoRange( uno::Reference< text::XTextRange >( xCell, uno::UNO_QUERY_THROW ), false ); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::MoveRight(const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend) |
| { |
| sal_Int32 nCount = 1; |
| |
| if( _count.hasValue() ) |
| _count >>= nCount; |
| |
| if( nCount == 0 ) |
| return; |
| |
| if( nCount < 0 ) |
| { |
| MoveLeft( _unit, uno::Any( -nCount ), _extend ); |
| return; |
| } |
| |
| Move( _unit, _count, _extend, word::MOVE_RIGHT ); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::MoveLeft(const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend) |
| { |
| sal_Int32 nCount = 1; |
| if( _count.hasValue() ) |
| _count >>= nCount; |
| |
| if( nCount == 0 ) |
| return; |
| |
| if( nCount < 0 ) |
| { |
| MoveRight( _unit, uno::Any( -nCount ), _extend ); |
| return; |
| } |
| |
| Move( _unit, _count, _extend, word::MOVE_LEFT ); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::MoveDown(const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend) |
| { |
| sal_Int32 nCount = 1; |
| |
| if( _count.hasValue() ) |
| _count >>= nCount; |
| |
| if( nCount == 0 ) |
| return; |
| |
| if( nCount < 0 ) |
| { |
| MoveUp( _unit, uno::Any( -nCount ), _extend ); |
| return; |
| } |
| |
| Move( _unit, _count, _extend, word::MOVE_DOWN ); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::MoveUp(const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend) |
| { |
| sal_Int32 nCount = 1; |
| |
| if( _count.hasValue() ) |
| _count >>= nCount; |
| |
| if( nCount == 0 ) |
| return; |
| |
| if( nCount < 0 ) |
| { |
| MoveDown( _unit, uno::Any( -nCount ), _extend ); |
| return; |
| } |
| |
| Move( _unit, _count, _extend, word::MOVE_UP ); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::TypeParagraph() |
| { |
| // #FIXME: if the selection is an entire paragraph, it's replaced |
| // by the new paragraph |
| bool isCollapsed = mxTextViewCursor->isCollapsed(); |
| InsertParagraph(); |
| if( isCollapsed ) |
| mxTextViewCursor->collapseToStart(); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::InsertParagraph() |
| { |
| // #FIXME: the selection should include the new paragraph. |
| getRange()->InsertParagraph(); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::InsertParagraphBefore() |
| { |
| getRange()->InsertParagraphBefore(); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::InsertParagraphAfter() |
| { |
| getRange()->InsertParagraphAfter(); |
| } |
| |
| uno::Reference< word::XParagraphFormat > SAL_CALL |
| SwVbaSelection::getParagraphFormat() |
| { |
| return getRange()->getParagraphFormat(); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::setParagraphFormat( const uno::Reference< word::XParagraphFormat >& rParagraphFormat ) |
| { |
| return getRange()->setParagraphFormat( rParagraphFormat ); |
| } |
| |
| uno::Reference< word::XFind > SAL_CALL |
| SwVbaSelection::getFind() |
| { |
| uno::Reference< text::XTextRange > xTextRange = GetSelectedRange(); |
| uno::Reference< text::XTextRange > xStart = xTextRange->getStart(); |
| uno::Reference< text::XTextRange > xEnd = xTextRange->getEnd(); |
| uno::Reference< text::XTextRangeCompare > xTRC( xTextRange->getText(), uno::UNO_QUERY_THROW ); |
| int n = xTRC->compareRegionStarts( xStart, xEnd); |
| if( n == 0 ) |
| { |
| WholeStory(); |
| xTextRange = GetSelectedRange(); |
| } |
| return SwVbaFind::GetOrCreateFind(this, mxContext, mxModel, xTextRange); |
| } |
| |
| uno::Any SAL_CALL |
| SwVbaSelection::getStyle() |
| { |
| return getRange()->getStyle(); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::setStyle( const uno::Any& rStyle ) |
| { |
| uno::Reference< beans::XPropertySet > xParaProps( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| return SwVbaStyle::setStyle( xParaProps, rStyle ); |
| } |
| |
| uno::Reference< word::XFont > SAL_CALL |
| SwVbaSelection::getFont() |
| { |
| return getRange()->getFont(); |
| } |
| |
| void SAL_CALL |
| SwVbaSelection::TypeBackspace() |
| { |
| dispatchRequests( static_cast<SfxBaseModel*>(mxModel.get()), u".uno:SwBackspace"_ustr ); |
| } |
| |
| uno::Reference< word::XRange > SAL_CALL SwVbaSelection::GoTo( const uno::Any& _what, const uno::Any& _which, const uno::Any& _count, const uno::Any& _name ) |
| { |
| sal_Int32 nWhat = 0; |
| if( !( _what >>= nWhat ) ) |
| DebugHelper::basicexception(ERRCODE_BASIC_BAD_ARGUMENT, {}); |
| switch( nWhat ) |
| { |
| case word::WdGoToItem::wdGoToBookmark: |
| { |
| uno::Reference< word::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW ); |
| uno::Reference< word::XBookmark > xBookmark( xApplication->getActiveDocument()->Bookmarks(_name), uno::UNO_QUERY_THROW ); |
| xBookmark->Select(); |
| break; |
| } |
| case word::WdGoToItem::wdGoToPage: |
| { |
| uno::Reference< text::XPageCursor > xPageCursor( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| sal_Int32 nCurrPage = xPageCursor->getPage(); |
| sal_Int32 nLastPage = word::getPageCount( mxModel ); |
| sal_Int32 nCount = 0; |
| if( _count.hasValue() ) |
| _count >>= nCount; |
| sal_Int32 nWhich = 0; |
| if( _which.hasValue() ) |
| _which >>= nWhich; |
| sal_Int32 nPage = 0; |
| switch( nWhich ) |
| { |
| case word::WdGoToDirection::wdGoToLast: |
| { |
| nPage = nLastPage; |
| break; |
| } |
| case word::WdGoToDirection::wdGoToNext: |
| { |
| if( nCount !=0 ) |
| nPage = nCurrPage + nCount; |
| else |
| nPage = nCurrPage + 1; |
| break; |
| } |
| case word::WdGoToDirection::wdGoToPrevious: |
| { |
| if( nCount !=0 ) |
| nPage = nCurrPage - nCount; |
| else |
| nPage = nCurrPage - 1; |
| break; |
| } |
| default: |
| { |
| nPage = nCount; |
| } |
| } |
| if( _name.hasValue() ) |
| { |
| OUString sName; |
| _name >>= sName; |
| sal_Int32 nName = sName.toInt32(); |
| if( nName !=0 ) |
| nPage = nName; |
| } |
| if( nPage <= 0 ) |
| nPage = 1; |
| if( nPage > nLastPage ) |
| nPage = nLastPage; |
| xPageCursor->jumpToPage( static_cast<sal_Int16>(nPage) ); |
| break; |
| } |
| case word::WdGoToItem::wdGoToSection: |
| { |
| uno::Reference< text::XPageCursor > xPageCursor( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| sal_Int32 nCount = 0; |
| if( _count.hasValue() ) |
| _count >>= nCount; |
| sal_Int32 nWhich = 0; |
| if( _which.hasValue() ) |
| _which >>= nWhich; |
| sal_Int32 nPage = 0; |
| switch( nWhich ) |
| { |
| case word::WdGoToDirection::wdGoToAbsolute: |
| { |
| // currently only support this type |
| if( nCount == 1 ) |
| nPage = 1; |
| break; |
| } |
| default: |
| { |
| nPage = 0; |
| } |
| } |
| if( nPage == 0 ) |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| xPageCursor->jumpToPage( static_cast<sal_Int16>(nPage) ); |
| break; |
| } |
| default: |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| return getRange(); |
| } |
| |
| ::sal_Int32 SAL_CALL SwVbaSelection::getLanguageID() |
| { |
| return getRange()->getLanguageID(); |
| } |
| |
| void SAL_CALL SwVbaSelection::setLanguageID( ::sal_Int32 _languageid ) |
| { |
| getRange()->setLanguageID( _languageid ); |
| } |
| |
| uno::Any SAL_CALL SwVbaSelection::Information( sal_Int32 _type ) |
| { |
| uno::Any result; |
| switch( _type ) |
| { |
| case word::WdInformation::wdActiveEndPageNumber: |
| { |
| result <<= SwVbaInformationHelper::handleWdActiveEndPageNumber( mxTextViewCursor ); |
| break; |
| } |
| case word::WdInformation::wdNumberOfPagesInDocument: |
| { |
| result <<= SwVbaInformationHelper::handleWdNumberOfPagesInDocument( mxModel ); |
| break; |
| } |
| case word::WdInformation::wdVerticalPositionRelativeToPage: |
| { |
| result <<= SwVbaInformationHelper::handleWdVerticalPositionRelativeToPage( mxModel, mxTextViewCursor ); |
| break; |
| } |
| case word::WdInformation::wdWithInTable: |
| { |
| uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| uno::Reference< text::XTextTable > xTextTable; |
| xCursorProps->getPropertyValue(u"TextTable"_ustr) >>= xTextTable; |
| result <<= xTextTable.is(); |
| break; |
| } |
| case word::WdInformation::wdHeaderFooterType: |
| { |
| uno::Reference< word::XView > xView( new SwVbaView( this, mxContext, mxModel ) ); |
| sal_Int32 nView = xView->getSeekView(); |
| sal_Int32 nHeaderFooterType = 0; |
| switch( nView ) |
| { |
| case word::WdSeekView::wdSeekMainDocument: |
| { |
| nHeaderFooterType = -1; // not in a header or footer |
| break; |
| } |
| case word::WdSeekView::wdSeekEvenPagesHeader: |
| { |
| nHeaderFooterType = 0; // even page header |
| break; |
| } |
| case word::WdSeekView::wdSeekPrimaryHeader: |
| { |
| nHeaderFooterType = 1; // odd page header |
| break; |
| } |
| case word::WdSeekView::wdSeekEvenPagesFooter: |
| { |
| nHeaderFooterType = 2; // even page footer |
| break; |
| } |
| case word::WdSeekView::wdSeekPrimaryFooter: |
| { |
| nHeaderFooterType = 3; // odd page footer |
| break; |
| } |
| case word::WdSeekView::wdSeekFirstPageHeader: |
| case word::WdSeekView::wdSeekFirstPageFooter: |
| { |
| uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| OUString aPageStyleName; |
| xCursorProps->getPropertyValue(u"PageStyleName"_ustr) >>= aPageStyleName; |
| bool bFirstPage = false; |
| if ( aPageStyleName == "First Page" ) |
| bFirstPage = true; |
| if( nView == word::WdSeekView::wdSeekFirstPageHeader ) |
| { |
| if( bFirstPage ) |
| nHeaderFooterType = 4; |
| else |
| nHeaderFooterType = 1; |
| } |
| else |
| { |
| if( bFirstPage ) |
| nHeaderFooterType = 5; |
| else |
| nHeaderFooterType = 3; |
| } |
| break; |
| } |
| default: |
| { |
| nHeaderFooterType = -1; |
| } |
| } |
| result <<= nHeaderFooterType; |
| break; |
| } |
| default: |
| throw uno::RuntimeException(u"Not implemented"_ustr ); |
| } |
| return result; |
| } |
| |
| void SAL_CALL SwVbaSelection::InsertBreak( const uno::Any& _breakType ) |
| { |
| getRange()->InsertBreak( _breakType ); |
| } |
| |
| uno::Any SAL_CALL |
| SwVbaSelection::Tables( const uno::Any& aIndex ) |
| { |
| // Hacky implementation due to missing api ( and lack of knowledge ) |
| // we can only support a selection that is a single table |
| if ( !aIndex.hasValue() ) // currently we can't support multiple tables in a selection |
| throw uno::RuntimeException(); |
| |
| sal_Int32 nIndex = 0; |
| aIndex >>= nIndex; |
| |
| uno::Any aRet; |
| |
| if ( nIndex != 1 ) |
| throw uno::RuntimeException(); |
| |
| uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| uno::Reference< text::XTextTable > xTextTable; |
| xCursorProps->getPropertyValue(u"TextTable"_ustr) >>= xTextTable; |
| if( xTextTable.is() ) |
| { |
| auto pSwTextTable = dynamic_cast<SwXTextTable*>(xTextTable.get()); |
| assert(pSwTextTable); |
| uno::Reference< word::XTable > xVBATable = new SwVbaTable( mxParent, mxContext, mxModel, pSwTextTable ); |
| aRet <<= xVBATable; |
| return aRet; |
| } |
| |
| // if the current selection is a XTextTableCursor and the index is 1 then we can service this request, otherwise we just have to throw |
| uno::Reference< text::XTextTableCursor > xTextTableCursor( mxModel->getCurrentSelection(), uno::UNO_QUERY_THROW ); |
| SwXTextTableCursor* pTTCursor = dynamic_cast< SwXTextTableCursor* >( xTextTableCursor.get() ); |
| if ( pTTCursor ) |
| { |
| SwFrameFormat* pFormat = pTTCursor->GetFrameFormat(); |
| if ( pFormat ) |
| { |
| rtl::Reference<SwXTextTable> xTable = SwXTextTable::CreateXTextTable(pFormat); |
| uno::Reference< word::XTable > xVBATable = new SwVbaTable( mxParent, mxContext, mxModel, xTable ); |
| aRet <<= xVBATable; |
| } |
| } |
| return aRet; |
| |
| } |
| |
| uno::Any SAL_CALL |
| SwVbaSelection::Fields( const uno::Any& index ) |
| { |
| uno::Reference< XCollection > xCol( new SwVbaFields( mxParent, mxContext, mxModel ) ); |
| if ( index.hasValue() ) |
| return xCol->Item( index, uno::Any() ); |
| return uno::Any( xCol ); |
| } |
| |
| uno::Reference< word::XHeaderFooter > SAL_CALL |
| SwVbaSelection::getHeaderFooter() |
| { |
| if( HeaderFooterHelper::isHeaderFooter( mxModel ) ) |
| { |
| rtl::Reference< SwXBaseStyle > xPageStyleProps( word::getCurrentPageStyle( mxModel ) ); |
| sal_Int32 nIndex = word::WdHeaderFooterIndex::wdHeaderFooterPrimary; |
| bool isHeader = HeaderFooterHelper::isHeader( mxModel ); |
| if( HeaderFooterHelper::isEvenPagesHeader( mxModel ) || HeaderFooterHelper::isEvenPagesFooter( mxModel ) ) |
| nIndex = word::WdHeaderFooterIndex::wdHeaderFooterEvenPages; |
| else if( HeaderFooterHelper::isFirstPageHeader( mxModel ) || HeaderFooterHelper::isFirstPageFooter( mxModel ) ) |
| nIndex = word::WdHeaderFooterIndex::wdHeaderFooterFirstPage; |
| |
| return uno::Reference< word::XHeaderFooter >( new SwVbaHeaderFooter( this, mxContext, mxModel, xPageStyleProps, isHeader, nIndex ) ); |
| |
| } |
| return uno::Reference< word::XHeaderFooter >(); |
| } |
| |
| uno::Any SAL_CALL |
| SwVbaSelection::ShapeRange( ) |
| { |
| uno::Reference< drawing::XShapes > xShapes( mxModel->getCurrentSelection(), uno::UNO_QUERY ); |
| if ( !xShapes.is() ) |
| { |
| uno::Reference< drawing::XShape > xShape( mxModel->getCurrentSelection(), uno::UNO_QUERY_THROW ); |
| xShapes.set( drawing::ShapeCollection::create(mxContext) ); |
| xShapes->add( xShape ); |
| } |
| |
| rtl::Reference< SwFmDrawPage > xDrawPage = mxModel->getSwDrawPage(); |
| uno::Reference< container::XIndexAccess > xShapesAccess( xShapes, uno::UNO_QUERY_THROW ); |
| return uno::Any( uno::Reference< msforms::XShapeRange >( new ScVbaShapeRange( this, mxContext, xShapesAccess, xDrawPage, static_cast<SfxBaseModel*>(mxModel.get()) ) ) ); |
| } |
| |
| ::sal_Int32 SAL_CALL SwVbaSelection::getStart() |
| { |
| return getRange()->getStart(); |
| } |
| |
| void SAL_CALL SwVbaSelection::setStart( ::sal_Int32 _start ) |
| { |
| getRange()->setStart( _start ); |
| } |
| ::sal_Int32 SAL_CALL SwVbaSelection::getEnd() |
| { |
| return getRange()->getEnd(); |
| } |
| |
| void SAL_CALL SwVbaSelection::setEnd( ::sal_Int32 _end ) |
| { |
| getRange()->setEnd( _end ); |
| } |
| |
| void SAL_CALL SwVbaSelection::SelectRow() |
| { |
| uno::Reference< word::XRows > xRows( Rows( uno::Any() ), uno::UNO_QUERY_THROW ); |
| xRows->Select(); |
| } |
| |
| void SAL_CALL SwVbaSelection::SelectColumn() |
| { |
| uno::Reference< word::XColumns > xColumns( Columns( uno::Any() ), uno::UNO_QUERY_THROW ); |
| xColumns->Select(); |
| } |
| |
| uno::Any SAL_CALL SwVbaSelection::Rows( const uno::Any& index ) |
| { |
| OUString sTLName; |
| OUString sBRName; |
| GetSelectedCellRange( sTLName, sBRName ); |
| |
| sal_Int32 nStartRow = 0; |
| sal_Int32 nEndRow = 0; |
| rtl::Reference< SwXTextTable > xTextTable = GetXTextTable(); |
| SwVbaTableHelper aTableHelper( xTextTable ); |
| nStartRow = aTableHelper.getTabRowIndex( sTLName ); |
| if( !sBRName.isEmpty() ) |
| { |
| nEndRow = aTableHelper.getTabRowIndex( sBRName ); |
| } |
| else |
| { |
| nEndRow = nStartRow; |
| } |
| |
| uno::Reference< XCollection > xCol( new SwVbaRows( this, mxContext, xTextTable, xTextTable->getRows(), nStartRow, nEndRow ) ); |
| if ( index.hasValue() ) |
| return xCol->Item( index, uno::Any() ); |
| return uno::Any( xCol ); |
| } |
| |
| uno::Any SAL_CALL SwVbaSelection::Columns( const uno::Any& index ) |
| { |
| OUString sTLName; |
| OUString sBRName; |
| GetSelectedCellRange( sTLName, sBRName ); |
| sal_Int32 nStartColumn = 0; |
| sal_Int32 nEndColumn = 0; |
| |
| uno::Reference< text::XTextTable > xTextTable = GetXTextTable(); |
| SwVbaTableHelper aTableHelper( xTextTable ); |
| nStartColumn = aTableHelper.getTabColIndex( sTLName ); |
| if( !sBRName.isEmpty() ) |
| { |
| nEndColumn = aTableHelper.getTabColIndex( sBRName ); |
| } |
| else |
| { |
| nEndColumn = nStartColumn; |
| } |
| |
| uno::Reference< XCollection > xCol( new SwVbaColumns( this, mxContext, xTextTable, xTextTable->getColumns(), nStartColumn, nEndColumn ) ); |
| if ( index.hasValue() ) |
| return xCol->Item( index, uno::Any() ); |
| return uno::Any( xCol ); |
| } |
| |
| rtl::Reference< SwXTextTable > SwVbaSelection::GetXTextTable() const |
| { |
| uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| uno::Reference< text::XTextTable > xTextTable; |
| xCursorProps->getPropertyValue(u"TextTable"_ustr) >>= xTextTable; |
| if (!xTextTable) |
| return nullptr; |
| auto pSwTextTable = dynamic_cast<SwXTextTable*>(xTextTable.get()); |
| assert(pSwTextTable); |
| return pSwTextTable; |
| } |
| |
| bool SwVbaSelection::IsInTable() const |
| { |
| uno::Reference< text::XTextTable > xTextTable = GetXTextTable(); |
| return xTextTable.is(); |
| } |
| |
| bool SwVbaSelection::HasSelection() |
| { |
| uno::Reference< text::XTextRange > xStart = mxTextViewCursor->getStart(); |
| uno::Reference< text::XTextRange > xEnd = mxTextViewCursor->getEnd(); |
| uno::Reference< text::XTextRangeCompare > xTRC( mxTextViewCursor->getText(), uno::UNO_QUERY_THROW ); |
| return xTRC->compareRegionStarts( xStart, xEnd ) != 0 || xTRC->compareRegionEnds( xStart, xEnd ) != 0; |
| } |
| |
| void SwVbaSelection::GetSelectedCellRange( OUString& sTLName, OUString& sBRName ) |
| { |
| uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW ); |
| uno::Reference< text::XTextTable > xTextTable; |
| xCursorProps->getPropertyValue(u"TextTable"_ustr) >>= xTextTable; |
| if( !xTextTable.is() ) |
| throw uno::RuntimeException( ); |
| |
| uno::Reference< text::XTextTableCursor > xTextTableCursor( mxModel->getCurrentSelection(), uno::UNO_QUERY ); |
| if( xTextTableCursor.is() ) |
| { |
| const OUString sRange( xTextTableCursor->getRangeName() ); |
| if (!sRange.isEmpty()) |
| { |
| sal_Int32 nIdx{0}; |
| sTLName = sRange.getToken(0, ':', nIdx); |
| sBRName = sRange.getToken(0, ':', nIdx); |
| } |
| } |
| if( sTLName.isEmpty() ) |
| { |
| uno::Reference< table::XCell > xCell; |
| xCursorProps->getPropertyValue(u"Cell"_ustr) >>= xCell; |
| if( !xCell.is() ) |
| { |
| throw uno::RuntimeException( ); |
| } |
| uno::Reference< beans::XPropertySet > xCellProps( xCell, uno::UNO_QUERY_THROW ); |
| xCellProps->getPropertyValue(u"CellName"_ustr) >>= sTLName; |
| } |
| } |
| |
| uno::Any SAL_CALL SwVbaSelection::Cells( const uno::Any& index ) |
| { |
| OUString sTLName; |
| OUString sBRName; |
| GetSelectedCellRange( sTLName, sBRName ); |
| sal_Int32 nLeft = 0; |
| sal_Int32 nTop = 0; |
| sal_Int32 nRight = 0; |
| sal_Int32 nBottom = 0; |
| |
| uno::Reference< text::XTextTable > xTextTable = GetXTextTable(); |
| SwVbaTableHelper aTableHelper( xTextTable ); |
| nLeft = aTableHelper.getTabColIndex( sTLName ); |
| nTop = aTableHelper.getTabRowIndex( sTLName ); |
| if( !sBRName.isEmpty() ) |
| { |
| nRight = aTableHelper.getTabColIndex( sBRName ); |
| nBottom = aTableHelper.getTabRowIndex( sBRName ); |
| } |
| else |
| { |
| nRight = nLeft; |
| nBottom = nTop; |
| } |
| |
| uno::Reference< XCollection > xCol( new SwVbaCells( this, mxContext, xTextTable, nLeft, nTop, nRight, nBottom ) ); |
| if ( index.hasValue() ) |
| return xCol->Item( index, uno::Any() ); |
| return uno::Any( xCol ); |
| } |
| |
| void SAL_CALL SwVbaSelection::Copy( ) |
| { |
| dispatchRequests( static_cast<SfxBaseModel*>(mxModel.get()), u".uno:Copy"_ustr ); |
| } |
| |
| void SAL_CALL SwVbaSelection::CopyAsPicture( ) |
| { |
| // seems not support in Writer |
| Copy(); |
| } |
| |
| void SAL_CALL SwVbaSelection::Paste( ) |
| { |
| dispatchRequests( static_cast<SfxBaseModel*>(mxModel.get()), u".uno:Paste"_ustr ); |
| } |
| |
| void SAL_CALL SwVbaSelection::Collapse( const uno::Any& Direction ) |
| { |
| if( word::gotoSelectedObjectAnchor( mxModel ) ) |
| return; |
| |
| sal_Int32 nDirection = word::WdCollapseDirection::wdCollapseStart; |
| if( Direction.hasValue() ) |
| Direction >>= nDirection; |
| |
| uno::Reference< text::XTextViewCursor > xTextViewCursor = word::getXTextViewCursor( mxModel ); |
| if( nDirection == word::WdCollapseDirection::wdCollapseStart ) |
| { |
| // it is inaccurate if current selection is multiple cells, so it needs to go to start |
| uno::Reference< text::XTextRange > xTextRange = mxTextViewCursor->getStart(); |
| xTextViewCursor->gotoRange( xTextRange, false ); |
| xTextViewCursor->collapseToStart(); |
| } |
| else if( nDirection == word::WdCollapseDirection::wdCollapseEnd ) |
| { |
| uno::Reference< text::XTextRange > xTextRange = mxTextViewCursor->getEnd(); |
| xTextViewCursor->gotoRange( xTextRange, false ); |
| xTextViewCursor->collapseToEnd(); |
| } |
| else |
| { |
| throw uno::RuntimeException(); |
| } |
| } |
| |
| void SAL_CALL SwVbaSelection::WholeStory( ) |
| { |
| uno::Reference< text::XText > xText = word::getCurrentXText( mxModel ); |
| // FIXME: for i#7747,if the first line is a table, it fails to select all the contents in the story. |
| // Temporary solution, insert an empty line before the table so that it could select all the contents. |
| uno::Reference< container::XEnumerationAccess > xParaAccess( xText, uno::UNO_QUERY_THROW ); |
| uno::Reference< container::XEnumeration> xParaEnum = xParaAccess->createEnumeration(); |
| if( xParaEnum->hasMoreElements() ) |
| { |
| uno::Reference< text::XTextTable > xTextTable( xParaEnum->nextElement(), uno::UNO_QUERY ); |
| if( xTextTable.is() ) |
| { |
| // insert an empty line |
| uno::Reference< text::XTextRange > xFirstCellRange = word::getFirstObjectPosition( xText ); |
| mxTextViewCursor->gotoRange( xFirstCellRange, false ); |
| dispatchRequests( static_cast<SfxBaseModel*>(mxModel.get()), u".uno:InsertPara"_ustr ); |
| } |
| } |
| uno::Reference< text::XTextRange > xStart = xText->getStart(); |
| uno::Reference< text::XTextRange > xEnd = xText->getEnd(); |
| mxTextViewCursor->gotoRange( xStart, false ); |
| mxTextViewCursor->gotoRange( xEnd, true ); |
| } |
| |
| sal_Bool SAL_CALL SwVbaSelection::InRange( const uno::Reference< ::ooo::vba::word::XRange >& Range ) |
| { |
| return getRange()->InRange( Range ); |
| } |
| |
| void SAL_CALL SwVbaSelection::SplitTable() |
| { |
| if( !IsInTable() ) |
| throw uno::RuntimeException(); |
| |
| SwDocShell* pDocShell = mxModel->GetDocShell(); |
| if( pDocShell ) |
| { |
| if (SwFEShell* pFEShell = pDocShell->GetFEShell()) |
| pFEShell->SplitTable( SplitTable_HeadlineOption::ContentCopy ); |
| } |
| } |
| |
| uno::Any SAL_CALL |
| SwVbaSelection::Paragraphs( const uno::Any& aIndex ) |
| { |
| // Hacky implementation due to missing api ( and lack of knowledge ) |
| // we can only support a selection that is a single paragraph |
| if ( !aIndex.hasValue() ) // currently we can't support multiple paragraphs in a selection |
| throw uno::RuntimeException(); |
| |
| sal_Int32 nIndex = 0; |
| aIndex >>= nIndex; |
| |
| uno::Any aRet; |
| |
| if ( nIndex != 1 ) |
| throw uno::RuntimeException(); |
| |
| uno::Reference< text::XTextRange > xTextRange = mxTextViewCursor->getStart(); |
| uno::Reference< text::XText > xText = xTextRange->getText(); |
| rtl::Reference< SwXTextCursor > xParaCursor = dynamic_cast<SwXTextCursor*>( xText->createTextCursor().get() ); |
| if (!xParaCursor) |
| throw uno::RuntimeException(); |
| xParaCursor->gotoStartOfParagraph( false ); |
| xParaCursor->gotoStartOfParagraph( true ); |
| |
| uno::Reference< text::XTextRange > xParaRange( static_cast<text::XSentenceCursor*>(xParaCursor.get()) ); |
| uno::Reference< word::XParagraph > xParagraph = new SwVbaParagraph( mxParent, mxContext, mxModel, xParaRange ); |
| |
| aRet <<= xParagraph; |
| return aRet; |
| } |
| |
| OUString |
| SwVbaSelection::getServiceImplName() |
| { |
| return u"SwVbaSelection"_ustr; |
| } |
| |
| uno::Sequence< OUString > |
| SwVbaSelection::getServiceNames() |
| { |
| static uno::Sequence< OUString > const aServiceNames |
| { |
| u"ooo.vba.word.Selection"_ustr |
| }; |
| return aServiceNames; |
| } |
| |
| /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |