1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #include "vbaselection.hxx"
20 #include <vbahelper/vbahelper.hxx>
21 #include "vbarange.hxx"
22 #include "vbafind.hxx"
23 #include <com/sun/star/text/XTextRange.hpp>
24 #include <com/sun/star/text/XTextTable.hpp>
25 #include <com/sun/star/text/XTextTableCursor.hpp>
26 #include <com/sun/star/table/XCell.hpp>
27 #include <basic/sberrors.hxx>
28 #include <ooo/vba/word/WdUnits.hpp>
29 #include <ooo/vba/word/WdMovementType.hpp>
30 #include <ooo/vba/word/WdGoToItem.hpp>
31 #include <ooo/vba/word/WdGoToDirection.hpp>
32 #include <ooo/vba/word/XBookmark.hpp>
33 #include <ooo/vba/word/XApplication.hpp>
34 #include <ooo/vba/word/WdCollapseDirection.hpp>
35 #include <com/sun/star/text/XPageCursor.hpp>
36 #include <unotbl.hxx>
37 #include <unocoll.hxx>
38 #include "vbatable.hxx"
39 #include <com/sun/star/view/XViewCursor.hpp>
40 #include <com/sun/star/view/XLineCursor.hpp>
41 #include <com/sun/star/text/XWordCursor.hpp>
42 #include <com/sun/star/text/XParagraphCursor.hpp>
43 #include <ooo/vba/word/WdInformation.hpp>
44 #include <ooo/vba/word/WdHeaderFooterIndex.hpp>
45 #include <ooo/vba/word/WdSeekView.hpp>
46 #include "vbainformationhelper.hxx"
47 #include "vbafield.hxx"
48 #include "vbaheaderfooter.hxx"
49 #include "vbaheaderfooterhelper.hxx"
50 #include <vbahelper/vbashaperange.hxx>
51 #include <com/sun/star/drawing/ShapeCollection.hpp>
52 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
53 #include <com/sun/star/drawing/XDrawPage.hpp>
54 #include "vbarows.hxx"
55 #include "vbacolumns.hxx"
56 #include "vbatablehelper.hxx"
57 #include "vbacells.hxx"
58 #include "vbaview.hxx"
59 #include "vbaparagraph.hxx"
60 #include "vbastyle.hxx"
61 #include <docsh.hxx>
62 #include <tblenum.hxx>
63 #include <fesh.hxx>
64 
65 using namespace ::ooo::vba;
66 using namespace ::com::sun::star;
67 
SwVbaSelection(const uno::Reference<ooo::vba::XHelperInterface> & rParent,const uno::Reference<uno::XComponentContext> & rContext,const uno::Reference<frame::XModel> & rModel)68 SwVbaSelection::SwVbaSelection( const uno::Reference< ooo::vba::XHelperInterface >& rParent, const uno::Reference< uno::XComponentContext >& rContext, const uno::Reference< frame::XModel >& rModel ) : SwVbaSelection_BASE( rParent, rContext ), mxModel( rModel )
69 {
70     mxTextViewCursor = word::getXTextViewCursor( mxModel );
71 }
72 
~SwVbaSelection()73 SwVbaSelection::~SwVbaSelection()
74 {
75 }
76 
GetSelectedRange()77 uno::Reference< text::XTextRange > SwVbaSelection::GetSelectedRange()
78 {
79     uno::Reference< text::XTextRange > xTextRange;
80     uno::Reference< lang::XServiceInfo > xServiceInfo( mxModel->getCurrentSelection(), uno::UNO_QUERY_THROW );
81     if( !xServiceInfo->supportsService("com.sun.star.text.TextRanges") )
82     {
83         throw uno::RuntimeException("Not implemented" );
84     }
85 
86     uno::Reference< container::XIndexAccess > xTextRanges( xServiceInfo, uno::UNO_QUERY_THROW );
87     if( xTextRanges->getCount() > 0 )
88     {
89         // if there are multiple selection, just return the last selected Range.
90         xTextRange.set( xTextRanges->getByIndex( xTextRanges->getCount()-1 ), uno::UNO_QUERY_THROW );
91     }
92 
93     return xTextRange;
94 }
95 
96 uno::Reference< word::XRange > SAL_CALL
getRange()97 SwVbaSelection::getRange()
98 {
99     uno::Reference< text::XTextRange > xTextRange = GetSelectedRange();
100     uno::Reference< text::XTextDocument > xDocument( mxModel, uno::UNO_QUERY_THROW );
101     return uno::Reference< word::XRange >( new SwVbaRange( this, mxContext, xDocument, xTextRange->getStart(), xTextRange->getEnd(), mxTextViewCursor->getText() ) );
102 }
103 
104 OUString SAL_CALL
getText()105 SwVbaSelection::getText()
106 {
107     return getRange()->getText();
108 }
109 
110 void SAL_CALL
setText(const OUString & rText)111 SwVbaSelection::setText( const OUString& rText )
112 {
113     getRange()->setText( rText );
114 }
115 
116 void SAL_CALL
TypeText(const OUString & rText)117 SwVbaSelection::TypeText( const OUString& rText )
118 {
119     // FIXME: handle the property Options.ReplaceSelection, the default value is true
120     setText( rText );
121 }
122 
123 void SAL_CALL
HomeKey(const uno::Any & _unit,const uno::Any & _extend)124 SwVbaSelection::HomeKey( const uno::Any& _unit, const uno::Any& _extend )
125 {
126     sal_Int32 nUnit = word::WdUnits::wdLine;
127     sal_Int32 nExtend = word::WdMovementType::wdMove;
128     _unit >>= nUnit;
129     _extend >>= nExtend;
130     bool bExtend = nExtend == word::WdMovementType::wdExtend;
131 
132     switch( nUnit )
133     {
134         case word::WdUnits::wdStory:
135         {
136             // go to the valid text first so that the current view cursor is valid to call gotoRange.
137             word::gotoSelectedObjectAnchor(mxModel);
138             // go to the begin of the document
139             uno::Reference< text::XText > xCurrentText = word::getCurrentXText( mxModel );
140             uno::Reference< text::XTextRange > xFirstRange = word::getFirstObjectPosition( xCurrentText );
141             mxTextViewCursor->gotoRange( xFirstRange, bExtend );
142             break;
143         }
144         case word::WdUnits::wdLine:
145         {
146             // go to the begin of the Line
147             uno::Reference< view::XLineCursor > xLineCursor( mxTextViewCursor, uno::UNO_QUERY_THROW );
148             xLineCursor->gotoStartOfLine( bExtend );
149             break;
150         }
151         default:
152         {
153             throw uno::RuntimeException("Not implemented" );
154         }
155     }
156 }
157 
158 void SAL_CALL
EndKey(const uno::Any & _unit,const uno::Any & _extend)159 SwVbaSelection::EndKey( const uno::Any& _unit, const uno::Any& _extend )
160 {
161     sal_Int32 nUnit = word::WdUnits::wdLine;
162     sal_Int32 nExtend = word::WdMovementType::wdMove;
163     _unit >>= nUnit;
164     _extend >>= nExtend;
165     bool bExtend = nExtend == word::WdMovementType::wdExtend;
166 
167     switch( nUnit )
168     {
169         case word::WdUnits::wdStory:
170         {
171             // go to the valid text first so that the current view cursor is valid to call gotoRange.
172             word::gotoSelectedObjectAnchor(mxModel);
173             // go to the end of the document
174             uno::Reference< text::XText > xCurrentText = word::getCurrentXText( mxModel );
175             uno::Reference< text::XTextRange > xEnd = xCurrentText->getEnd();
176             mxTextViewCursor->gotoRange( xEnd, bExtend );
177             break;
178         }
179         case word::WdUnits::wdLine:
180         {
181             // go to the end of the Line
182             uno::Reference< view::XLineCursor > xLineCursor( mxTextViewCursor, uno::UNO_QUERY_THROW );
183             xLineCursor->gotoEndOfLine( bExtend );
184             break;
185         }
186         default:
187         {
188             throw uno::RuntimeException("Not implemented" );
189         }
190     }
191 }
192 
193 void SAL_CALL
Delete(const uno::Any & _unit,const uno::Any & _count)194 SwVbaSelection::Delete( const uno::Any& _unit, const uno::Any& _count )
195 {
196     sal_Int32 nUnit = word::WdUnits::wdLine;
197     sal_Int32 nCount = 0;
198     if( _count.hasValue() )
199         _count >>= nCount;
200     if( _unit.hasValue() && ( nCount > 0 ) )
201     {
202         _unit >>= nUnit;
203         switch( nUnit )
204         {
205             case word::WdUnits::wdCharacter:
206             {
207                 if( HasSelection() )
208                     nCount--;
209                 mxTextViewCursor->goRight( nCount, true );
210                 break;
211             }
212             default:
213             {
214                 throw uno::RuntimeException("Not implemented" );
215             }
216         }
217     }
218     dispatchRequests( mxModel,".uno:Delete" );
219 }
220 
221 void
Move(const uno::Any & _unit,const uno::Any & _count,const uno::Any & _extend,word::E_DIRECTION eDirection)222 SwVbaSelection::Move( const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend, word::E_DIRECTION eDirection )
223 {
224     sal_Int32 nUnit = word::WdUnits::wdCharacter;
225     sal_Int32 nCount = 1;
226     sal_Int32 nExtend = word::WdMovementType::wdMove;
227 
228     if( _unit.hasValue() )
229         _unit >>= nUnit;
230     if( _count.hasValue() )
231         _count >>= nCount;
232     if( _extend.hasValue() )
233         _extend >>= nExtend;
234 
235     if( nCount == 0 )
236         return;
237 
238     bool bExpand = nExtend != word::WdMovementType::wdMove;
239 
240     switch( nUnit )
241     {
242         case word::WdUnits::wdCell:
243         {
244             if(  nExtend == word::WdMovementType::wdExtend )
245             {
246                 DebugHelper::basicexception(ERRCODE_BASIC_BAD_ARGUMENT, {});
247                 return;
248             }
249             NextCell( nCount, eDirection );
250             break;
251         }
252         case word::WdUnits::wdLine:
253         {
254             if( eDirection == word::MOVE_LEFT || eDirection == word::MOVE_RIGHT )
255             {
256                 throw uno::RuntimeException("Not implemented" );
257             }
258             uno::Reference< view::XViewCursor > xViewCursor( mxTextViewCursor, uno::UNO_QUERY_THROW );
259             if( eDirection == word::MOVE_UP )
260                 xViewCursor->goUp( nCount, bExpand );
261             else if( eDirection == word::MOVE_DOWN )
262                 xViewCursor->goDown( nCount, bExpand );
263             break;
264         }
265         case word::WdUnits::wdCharacter:
266         {
267             if( eDirection == word::MOVE_UP || eDirection == word::MOVE_DOWN )
268             {
269                 throw uno::RuntimeException("Not implemented" );
270             }
271             if( word::gotoSelectedObjectAnchor( mxModel ) )
272             {
273                 nCount--;
274             }
275             uno::Reference< view::XViewCursor > xViewCursor( mxTextViewCursor, uno::UNO_QUERY_THROW );
276             if( eDirection == word::MOVE_LEFT )
277             {
278                 // if current select is a cellrange or table,
279                 // the first count of move should move to the first selected cell.
280                 uno::Reference< text::XTextTableCursor > xTextTableCursor( mxModel->getCurrentSelection(), uno::UNO_QUERY );
281                 if ( xTextTableCursor.is() )
282                 {
283                     uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW );
284                     uno::Reference< text::XTextTable > xTextTable;
285                     xCursorProps->getPropertyValue("TextTable") >>= xTextTable;
286                     if( xTextTable.is() )
287                     {
288                         uno::Reference< text::XTextRange > xRange( xTextTable->getCellByName( xTextTableCursor->getRangeName()), uno::UNO_QUERY_THROW );
289                         mxTextViewCursor->gotoRange( xRange->getStart(), bExpand );
290                         nCount--;
291                     }
292                 }
293                 xViewCursor->goLeft( nCount, bExpand );
294             }
295             else if( eDirection == word::MOVE_RIGHT )
296                 xViewCursor->goRight( nCount, bExpand );
297             break;
298         }
299         case word::WdUnits::wdWord:
300         case word::WdUnits::wdParagraph:
301         {
302             uno::Reference< text::XTextRange > xRange = GetSelectedRange();
303             uno::Reference< text::XText > xText = xRange->getText();
304             uno::Reference< text::XTextCursor > xTextCursor = xText->createTextCursorByRange( xRange );
305             if( nUnit == word::WdUnits::wdParagraph )
306             {
307                 if( eDirection == word::MOVE_LEFT || eDirection == word::MOVE_RIGHT )
308                 {
309                     throw uno::RuntimeException("Not implemented" );
310                 }
311                 uno::Reference< text::XParagraphCursor > xParagraphCursor( xTextCursor, uno::UNO_QUERY_THROW );
312                 for( sal_Int32 i=0; i<nCount; i++ )
313                 {
314                     if( ( eDirection == word::MOVE_UP ) && !xParagraphCursor->gotoPreviousParagraph( bExpand ) )
315                         break;
316                     else if( ( eDirection == word::MOVE_DOWN ) && !xParagraphCursor->gotoNextParagraph( bExpand ) )
317                         break;
318                 }
319             }
320             else if( nUnit == word::WdUnits::wdWord )
321             {
322                 if( eDirection == word::MOVE_UP || eDirection == word::MOVE_DOWN )
323                 {
324                     throw uno::RuntimeException("Not implemented" );
325                 }
326                 uno::Reference< text::XWordCursor > xWordCursor( xTextCursor, uno::UNO_QUERY_THROW );
327                 for( sal_Int32 i=0; i<nCount; i++ )
328                 {
329                     if( (eDirection == word::MOVE_LEFT ) && !xWordCursor->gotoPreviousWord( bExpand ) )
330                         break;
331                     else if( ( eDirection == word::MOVE_RIGHT ) && !xWordCursor->gotoNextWord( bExpand ) )
332                         break;
333                 }
334             }
335             mxTextViewCursor->gotoRange( xTextCursor->getStart(), false );
336             mxTextViewCursor->gotoRange( xTextCursor->getEnd(), true );
337             break;
338         }
339         default:
340         {
341             throw uno::RuntimeException("Not implemented" );
342         }
343     }
344 }
345 
NextCell(sal_Int32 nCount,word::E_DIRECTION eDirection)346 void SwVbaSelection::NextCell(sal_Int32 nCount, word::E_DIRECTION eDirection)
347 {
348     uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW );
349     uno::Reference< text::XTextTable > xTextTable;
350     uno::Reference< table::XCell > xCell;
351     xCursorProps->getPropertyValue("TextTable") >>= xTextTable;
352     xCursorProps->getPropertyValue("Cell") >>= xCell;
353     if( !xTextTable.is() || !xCell.is() )
354     {
355         DebugHelper::basicexception(ERRCODE_BASIC_BAD_ARGUMENT, {});
356         return;
357     }
358     uno::Reference< beans::XPropertySet > xCellProps( xCell, uno::UNO_QUERY_THROW );
359     OUString aCellName;
360     xCellProps->getPropertyValue("CellName") >>= aCellName;
361     uno::Reference< text::XTextTableCursor > xTextTableCursor = xTextTable->createCursorByCellName( aCellName );
362     // move the table cursor
363     switch( eDirection )
364     {
365         case word::MOVE_LEFT:
366         {
367             xTextTableCursor->goLeft( nCount, false );
368             break;
369         }
370         case word::MOVE_RIGHT:
371         {
372             xTextTableCursor->goRight( nCount, false );
373             break;
374         }
375         case word::MOVE_UP:
376         {
377             xTextTableCursor->goUp( nCount, false );
378             break;
379         }
380         case word::MOVE_DOWN:
381         {
382             xTextTableCursor->goDown( nCount, false );
383             break;
384         }
385         default:
386         {
387             DebugHelper::basicexception(ERRCODE_BASIC_BAD_ARGUMENT, {});
388             return;
389         }
390     }
391     // move the view cursor
392     xCell = xTextTable->getCellByName( xTextTableCursor->getRangeName() );
393     mxTextViewCursor->gotoRange( uno::Reference< text::XTextRange >( xCell, uno::UNO_QUERY_THROW ), false );
394 }
395 
396 void SAL_CALL
MoveRight(const uno::Any & _unit,const uno::Any & _count,const uno::Any & _extend)397 SwVbaSelection::MoveRight(const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend)
398 {
399     sal_Int32 nCount = 1;
400 
401     if( _count.hasValue() )
402         _count >>= nCount;
403 
404     if( nCount == 0 )
405         return;
406 
407     if( nCount < 0 )
408     {
409         MoveLeft( _unit, uno::makeAny( -nCount ), _extend );
410         return;
411     }
412 
413     Move( _unit, _count, _extend, word::MOVE_RIGHT );
414 }
415 
416 void SAL_CALL
MoveLeft(const uno::Any & _unit,const uno::Any & _count,const uno::Any & _extend)417 SwVbaSelection::MoveLeft(const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend)
418 {
419     sal_Int32 nCount = 1;
420     if( _count.hasValue() )
421         _count >>= nCount;
422 
423     if( nCount == 0 )
424         return;
425 
426     if( nCount < 0 )
427     {
428         MoveRight( _unit, uno::makeAny( -nCount ), _extend );
429         return;
430     }
431 
432     Move( _unit, _count, _extend, word::MOVE_LEFT );
433 }
434 
435 void SAL_CALL
MoveDown(const uno::Any & _unit,const uno::Any & _count,const uno::Any & _extend)436 SwVbaSelection::MoveDown(const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend)
437 {
438     sal_Int32 nCount = 1;
439 
440     if( _count.hasValue() )
441         _count >>= nCount;
442 
443     if( nCount == 0 )
444         return;
445 
446     if( nCount < 0 )
447     {
448         MoveUp( _unit, uno::makeAny( -nCount ), _extend );
449         return;
450     }
451 
452     Move( _unit, _count, _extend, word::MOVE_DOWN );
453 }
454 
455 void SAL_CALL
MoveUp(const uno::Any & _unit,const uno::Any & _count,const uno::Any & _extend)456 SwVbaSelection::MoveUp(const uno::Any& _unit, const uno::Any& _count, const uno::Any& _extend)
457 {
458     sal_Int32 nCount = 1;
459 
460     if( _count.hasValue() )
461         _count >>= nCount;
462 
463     if( nCount == 0 )
464         return;
465 
466     if( nCount < 0 )
467     {
468         MoveDown( _unit, uno::makeAny( -nCount ), _extend );
469         return;
470     }
471 
472     Move( _unit, _count, _extend, word::MOVE_UP );
473 }
474 
475 void SAL_CALL
TypeParagraph()476 SwVbaSelection::TypeParagraph()
477 {
478     // #FIXME: if the selection is an entire paragraph, it's replaced
479     // by the new paragraph
480     bool isCollapsed = mxTextViewCursor->isCollapsed();
481     InsertParagraph();
482     if( isCollapsed )
483         mxTextViewCursor->collapseToStart();
484 }
485 
486 void SAL_CALL
InsertParagraph()487 SwVbaSelection::InsertParagraph()
488 {
489     // #FIXME: the selection should include the new paragraph.
490     getRange()->InsertParagraph();
491 }
492 
493 void SAL_CALL
InsertParagraphBefore()494 SwVbaSelection::InsertParagraphBefore()
495 {
496     getRange()->InsertParagraphBefore();
497 }
498 
499 void SAL_CALL
InsertParagraphAfter()500 SwVbaSelection::InsertParagraphAfter()
501 {
502     getRange()->InsertParagraphAfter();
503 }
504 
505 uno::Reference< word::XParagraphFormat > SAL_CALL
getParagraphFormat()506 SwVbaSelection::getParagraphFormat()
507 {
508     return getRange()->getParagraphFormat();
509 }
510 
511 void SAL_CALL
setParagraphFormat(const uno::Reference<word::XParagraphFormat> & rParagraphFormat)512 SwVbaSelection::setParagraphFormat( const uno::Reference< word::XParagraphFormat >& rParagraphFormat )
513 {
514     return getRange()->setParagraphFormat( rParagraphFormat );
515 }
516 
517 uno::Reference< word::XFind > SAL_CALL
getFind()518 SwVbaSelection::getFind()
519 {
520     uno::Reference< text::XTextRange > xTextRange = GetSelectedRange();
521     return uno::Reference< word::XFind >( new SwVbaFind( this, mxContext, mxModel, xTextRange ) );
522 }
523 
524 uno::Any SAL_CALL
getStyle()525 SwVbaSelection::getStyle()
526 {
527     return getRange()->getStyle();
528 }
529 
530 void SAL_CALL
setStyle(const uno::Any & rStyle)531 SwVbaSelection::setStyle( const uno::Any& rStyle )
532 {
533     uno::Reference< beans::XPropertySet > xParaProps( mxTextViewCursor, uno::UNO_QUERY_THROW );
534     return SwVbaStyle::setStyle( xParaProps, rStyle );
535 }
536 
537 uno::Reference< word::XFont > SAL_CALL
getFont()538 SwVbaSelection::getFont()
539 {
540     return getRange()->getFont();
541 }
542 
543 void SAL_CALL
TypeBackspace()544 SwVbaSelection::TypeBackspace()
545 {
546     dispatchRequests( mxModel,".uno:SwBackspace" );
547 }
548 
GoTo(const uno::Any & _what,const uno::Any & _which,const uno::Any & _count,const uno::Any & _name)549 uno::Reference< word::XRange > SAL_CALL SwVbaSelection::GoTo( const uno::Any& _what, const uno::Any& _which, const uno::Any& _count, const uno::Any& _name )
550 {
551     sal_Int32 nWhat = 0;
552     if( !( _what >>= nWhat ) )
553          DebugHelper::basicexception(ERRCODE_BASIC_BAD_ARGUMENT, {});
554     switch( nWhat )
555     {
556         case word::WdGoToItem::wdGoToBookmark:
557         {
558             uno::Reference< word::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
559             uno::Reference< word::XBookmark > xBookmark( xApplication->getActiveDocument()->Bookmarks(_name), uno::UNO_QUERY_THROW );
560             xBookmark->Select();
561             break;
562         }
563         case word::WdGoToItem::wdGoToPage:
564         {
565             uno::Reference< text::XPageCursor > xPageCursor( mxTextViewCursor, uno::UNO_QUERY_THROW );
566             sal_Int32 nCurrPage = xPageCursor->getPage();
567             sal_Int32 nLastPage = word::getPageCount( mxModel );
568             sal_Int32 nCount = 0;
569             if( _count.hasValue() )
570                 _count >>= nCount;
571             sal_Int32 nWhich = 0;
572             if( _which.hasValue() )
573                 _which >>= nWhich;
574             sal_Int32 nPage = 0;
575             switch( nWhich )
576             {
577                case word::WdGoToDirection::wdGoToLast:
578                {
579                    nPage = nLastPage;
580                    break;
581                }
582                case word::WdGoToDirection::wdGoToNext:
583                {
584                    if( nCount !=0 )
585                        nPage = nCurrPage + nCount;
586                    else
587                        nPage = nCurrPage + 1;
588                    break;
589                }
590                case word::WdGoToDirection::wdGoToPrevious:
591                {
592                    if( nCount !=0 )
593                        nPage = nCurrPage - nCount;
594                    else
595                        nPage = nCurrPage - 1;
596                    break;
597                }
598                default:
599                {
600                    nPage = nCount;
601                }
602             }
603             if( _name.hasValue() )
604             {
605                 OUString sName;
606                 _name >>= sName;
607                 sal_Int32 nName = sName.toInt32();
608                 if( nName !=0 )
609                     nPage = nName;
610             }
611             if( nPage <= 0 )
612                nPage = 1;
613             if( nPage > nLastPage )
614                nPage = nLastPage;
615             xPageCursor->jumpToPage( static_cast<sal_Int16>(nPage) );
616             break;
617         }
618         case word::WdGoToItem::wdGoToSection:
619         {
620             uno::Reference< text::XPageCursor > xPageCursor( mxTextViewCursor, uno::UNO_QUERY_THROW );
621             sal_Int32 nCount = 0;
622             if( _count.hasValue() )
623                 _count >>= nCount;
624             sal_Int32 nWhich = 0;
625             if( _which.hasValue() )
626                 _which >>= nWhich;
627             sal_Int32 nPage = 0;
628             switch( nWhich )
629             {
630                case word::WdGoToDirection::wdGoToAbsolute:
631                {
632                     // currently only support this type
633                     if( nCount == 1 )
634                         nPage = 1;
635                     break;
636                }
637                default:
638                {
639                     nPage = 0;
640                }
641             }
642             if( nPage == 0 )
643                 throw uno::RuntimeException("Not implemented" );
644             xPageCursor->jumpToPage( static_cast<sal_Int16>(nPage) );
645             break;
646         }
647         default:
648             throw uno::RuntimeException("Not implemented" );
649     }
650     return getRange();
651 }
652 
getLanguageID()653 ::sal_Int32 SAL_CALL SwVbaSelection::getLanguageID()
654 {
655     return getRange()->getLanguageID();
656 }
657 
setLanguageID(::sal_Int32 _languageid)658 void SAL_CALL SwVbaSelection::setLanguageID( ::sal_Int32 _languageid )
659 {
660     getRange()->setLanguageID( _languageid );
661 }
662 
Information(sal_Int32 _type)663 uno::Any SAL_CALL SwVbaSelection::Information( sal_Int32 _type )
664 {
665     uno::Any result;
666     switch( _type )
667     {
668         case word::WdInformation::wdActiveEndPageNumber:
669         {
670             result <<= SwVbaInformationHelper::handleWdActiveEndPageNumber( mxTextViewCursor );
671             break;
672         }
673         case word::WdInformation::wdNumberOfPagesInDocument:
674         {
675             result <<= SwVbaInformationHelper::handleWdNumberOfPagesInDocument( mxModel );
676             break;
677         }
678         case word::WdInformation::wdVerticalPositionRelativeToPage:
679         {
680             result <<= SwVbaInformationHelper::handleWdVerticalPositionRelativeToPage( mxModel, mxTextViewCursor );
681             break;
682         }
683         case word::WdInformation::wdWithInTable:
684         {
685             uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW );
686             uno::Reference< text::XTextTable > xTextTable;
687             xCursorProps->getPropertyValue("TextTable") >>= xTextTable;
688             result <<= xTextTable.is();
689             break;
690         }
691         case word::WdInformation::wdHeaderFooterType:
692         {
693             uno::Reference< word::XView > xView( new SwVbaView( this, mxContext, mxModel ) );
694             sal_Int32 nView = xView->getSeekView();
695             sal_Int32 nHeaderFooterType = 0;
696             switch( nView )
697             {
698                 case word::WdSeekView::wdSeekMainDocument:
699                 {
700                     nHeaderFooterType = -1; // not in a header or footer
701                     break;
702                 }
703                 case word::WdSeekView::wdSeekEvenPagesHeader:
704                 {
705                     nHeaderFooterType = 0; // even page header
706                     break;
707                 }
708                 case word::WdSeekView::wdSeekPrimaryHeader:
709                 {
710                     nHeaderFooterType = 1; // odd page header
711                     break;
712                 }
713                 case word::WdSeekView::wdSeekEvenPagesFooter:
714                 {
715                     nHeaderFooterType = 2; // even page footer
716                     break;
717                 }
718                 case word::WdSeekView::wdSeekPrimaryFooter:
719                 {
720                     nHeaderFooterType = 3; // odd page footer
721                     break;
722                 }
723                 case word::WdSeekView::wdSeekFirstPageHeader:
724                 case word::WdSeekView::wdSeekFirstPageFooter:
725                 {
726                     uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW );
727                     OUString aPageStyleName;
728                     xCursorProps->getPropertyValue("PageStyleName") >>= aPageStyleName;
729                     bool bFirstPage = false;
730                     if ( aPageStyleName == "First Page" )
731                         bFirstPage = true;
732                     if( nView == word::WdSeekView::wdSeekFirstPageHeader )
733                     {
734                         if( bFirstPage )
735                             nHeaderFooterType = 4;
736                         else
737                             nHeaderFooterType = 1;
738                     }
739                     else
740                     {
741                         if( bFirstPage )
742                             nHeaderFooterType = 5;
743                         else
744                             nHeaderFooterType = 3;
745                     }
746                     break;
747                 }
748                 default:
749                 {
750                     nHeaderFooterType = -1;
751                 }
752             }
753             result <<= nHeaderFooterType;
754             break;
755         }
756         default:
757             throw uno::RuntimeException("Not implemented" );
758     }
759     return result;
760 }
761 
InsertBreak(const uno::Any & _breakType)762 void SAL_CALL SwVbaSelection::InsertBreak( const uno::Any& _breakType )
763 {
764     getRange()->InsertBreak( _breakType );
765 }
766 
767 uno::Any SAL_CALL
Tables(const uno::Any & aIndex)768 SwVbaSelection::Tables( const uno::Any& aIndex )
769 {
770     // Hacky implementation due to missing api ( and lack of knowledge )
771     // we can only support a selection that is a single table
772     if ( !aIndex.hasValue() ) // currently we can't support multiple tables in a selection
773        throw uno::RuntimeException();
774 
775     sal_Int32 nIndex = 0;
776     aIndex >>= nIndex;
777 
778     uno::Any aRet;
779 
780     if ( nIndex != 1 )
781        throw uno::RuntimeException();
782 
783     uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW );
784     uno::Reference< text::XTextTable > xTextTable;
785     xCursorProps->getPropertyValue("TextTable") >>= xTextTable;
786     if( xTextTable.is() )
787     {
788             uno::Reference< css::text::XTextDocument > xTextDoc( mxModel, uno::UNO_QUERY_THROW );
789             uno::Reference< word::XTable > xVBATable = new SwVbaTable( mxParent, mxContext, xTextDoc, xTextTable );
790             aRet <<= xVBATable;
791             return aRet;
792     }
793 
794     // if the current selection is a XTextTableCursor and the index is 1 then we can service this request, otherwise we just have to throw
795     uno::Reference< text::XTextTableCursor > xTextTableCursor( mxModel->getCurrentSelection(), uno::UNO_QUERY_THROW );
796     SwXTextTableCursor* pTTCursor = dynamic_cast< SwXTextTableCursor* >( xTextTableCursor.get() );
797     if ( pTTCursor )
798     {
799         SwFrameFormat* pFormat = pTTCursor->GetFrameFormat();
800         if ( pFormat )
801         {
802             uno::Reference< text::XTextTable > xTable = SwXTextTables::GetObject(*pFormat);
803             uno::Reference< css::text::XTextDocument > xTextDoc( mxModel, uno::UNO_QUERY_THROW );
804             uno::Reference< word::XTable > xVBATable = new SwVbaTable( mxParent, mxContext, xTextDoc, xTable );
805             aRet <<= xVBATable;
806         }
807     }
808     return aRet;
809 
810 }
811 
812 uno::Any SAL_CALL
Fields(const uno::Any & index)813 SwVbaSelection::Fields( const uno::Any& index )
814 {
815     uno::Reference< XCollection > xCol( new SwVbaFields( mxParent, mxContext, mxModel ) );
816     if ( index.hasValue() )
817         return xCol->Item( index, uno::Any() );
818     return uno::makeAny( xCol );
819 }
820 
821 uno::Reference< word::XHeaderFooter > SAL_CALL
getHeaderFooter()822 SwVbaSelection::getHeaderFooter()
823 {
824     if( HeaderFooterHelper::isHeaderFooter( mxModel ) )
825     {
826         uno::Reference< beans::XPropertySet > xPageStyleProps( word::getCurrentPageStyle( mxModel ), uno::UNO_QUERY_THROW );
827         sal_Int32 nIndex = word::WdHeaderFooterIndex::wdHeaderFooterPrimary;
828         bool isHeader = HeaderFooterHelper::isHeader( mxModel );
829         if( HeaderFooterHelper::isEvenPagesHeader( mxModel ) || HeaderFooterHelper::isEvenPagesFooter( mxModel ) )
830             nIndex = word::WdHeaderFooterIndex::wdHeaderFooterEvenPages;
831         else if( HeaderFooterHelper::isFirstPageHeader( mxModel ) || HeaderFooterHelper::isFirstPageFooter( mxModel ) )
832             nIndex = word::WdHeaderFooterIndex::wdHeaderFooterFirstPage;
833 
834         return uno::Reference< word::XHeaderFooter >( new SwVbaHeaderFooter( this, mxContext, mxModel, xPageStyleProps, isHeader, nIndex ) );
835 
836     }
837     return uno::Reference< word::XHeaderFooter >();
838 }
839 
840 uno::Any SAL_CALL
ShapeRange()841 SwVbaSelection::ShapeRange( )
842 {
843     uno::Reference< drawing::XShapes > xShapes( mxModel->getCurrentSelection(), uno::UNO_QUERY );
844     if ( !xShapes.is() )
845     {
846         uno::Reference< drawing::XShape > xShape( mxModel->getCurrentSelection(), uno::UNO_QUERY_THROW );
847         xShapes.set( drawing::ShapeCollection::create(mxContext) );
848         xShapes->add( xShape );
849     }
850 
851     uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( mxModel, uno::UNO_QUERY_THROW );
852     uno::Reference< drawing::XDrawPage > xDrawPage = xDrawPageSupplier->getDrawPage();
853     uno::Reference< container::XIndexAccess > xShapesAccess( xShapes, uno::UNO_QUERY_THROW );
854     return uno::makeAny( uno::Reference< msforms::XShapeRange >( new ScVbaShapeRange( this, mxContext, xShapesAccess, xDrawPage, mxModel ) ) );
855 }
856 
getStart()857 ::sal_Int32 SAL_CALL SwVbaSelection::getStart()
858 {
859     return getRange()->getStart();
860 }
861 
setStart(::sal_Int32 _start)862 void SAL_CALL SwVbaSelection::setStart( ::sal_Int32 _start )
863 {
864     getRange()->setStart( _start );
865 }
getEnd()866 ::sal_Int32 SAL_CALL SwVbaSelection::getEnd()
867 {
868     return getRange()->getEnd();
869 }
870 
setEnd(::sal_Int32 _end)871 void SAL_CALL SwVbaSelection::setEnd( ::sal_Int32 _end )
872 {
873     getRange()->setEnd( _end );
874 }
875 
SelectRow()876 void SAL_CALL SwVbaSelection::SelectRow()
877 {
878     uno::Reference< word::XRows > xRows( Rows( uno::Any() ), uno::UNO_QUERY_THROW );
879     xRows->Select();
880 }
881 
SelectColumn()882 void SAL_CALL SwVbaSelection::SelectColumn()
883 {
884     uno::Reference< word::XColumns > xColumns( Columns( uno::Any() ), uno::UNO_QUERY_THROW );
885     xColumns->Select();
886 }
887 
Rows(const uno::Any & index)888 uno::Any SAL_CALL SwVbaSelection::Rows( const uno::Any& index )
889 {
890     OUString sTLName;
891     OUString sBRName;
892     GetSelectedCellRange( sTLName, sBRName );
893 
894     sal_Int32 nStartRow = 0;
895     sal_Int32 nEndRow = 0;
896     uno::Reference< text::XTextTable > xTextTable = GetXTextTable();
897     SwVbaTableHelper aTableHelper( xTextTable );
898     nStartRow = aTableHelper.getTabRowIndex( sTLName );
899     if( !sBRName.isEmpty() )
900     {
901         nEndRow = aTableHelper.getTabRowIndex( sBRName );
902     }
903     else
904     {
905         nEndRow = nStartRow;
906     }
907 
908     uno::Reference< XCollection > xCol( new SwVbaRows( this, mxContext, xTextTable, xTextTable->getRows(), nStartRow, nEndRow ) );
909     if ( index.hasValue() )
910         return xCol->Item( index, uno::Any() );
911     return uno::makeAny( xCol );
912 }
913 
Columns(const uno::Any & index)914 uno::Any SAL_CALL SwVbaSelection::Columns( const uno::Any& index )
915 {
916     OUString sTLName;
917     OUString sBRName;
918     GetSelectedCellRange( sTLName, sBRName );
919     sal_Int32 nStartColumn = 0;
920     sal_Int32 nEndColumn = 0;
921 
922     uno::Reference< text::XTextTable > xTextTable = GetXTextTable();
923     SwVbaTableHelper aTableHelper( xTextTable );
924     nStartColumn = aTableHelper.getTabColIndex( sTLName );
925     if( !sBRName.isEmpty() )
926     {
927         nEndColumn = aTableHelper.getTabColIndex( sBRName );
928     }
929     else
930     {
931         nEndColumn = nStartColumn;
932     }
933 
934     uno::Reference< XCollection > xCol( new SwVbaColumns( this, mxContext, xTextTable, xTextTable->getColumns(), nStartColumn, nEndColumn ) );
935     if ( index.hasValue() )
936         return xCol->Item( index, uno::Any() );
937     return uno::makeAny( xCol );
938 }
939 
GetXTextTable() const940 uno::Reference< text::XTextTable > SwVbaSelection::GetXTextTable() const
941 {
942     uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW );
943     uno::Reference< text::XTextTable > xTextTable;
944     xCursorProps->getPropertyValue("TextTable") >>= xTextTable;
945     return xTextTable;
946 }
947 
IsInTable() const948 bool SwVbaSelection::IsInTable() const
949 {
950     uno::Reference< text::XTextTable > xTextTable = GetXTextTable();
951     return xTextTable.is();
952 }
953 
HasSelection()954 bool SwVbaSelection::HasSelection()
955 {
956     uno::Reference< text::XTextRange > xStart = mxTextViewCursor->getStart();
957     uno::Reference< text::XTextRange > xEnd = mxTextViewCursor->getEnd();
958     uno::Reference< text::XTextRangeCompare > xTRC( mxTextViewCursor->getText(), uno::UNO_QUERY_THROW );
959     return xTRC->compareRegionStarts( xStart, xEnd ) != 0 || xTRC->compareRegionEnds( xStart, xEnd ) != 0;
960 }
961 
GetSelectedCellRange(OUString & sTLName,OUString & sBRName)962 void SwVbaSelection::GetSelectedCellRange( OUString& sTLName, OUString& sBRName )
963 {
964     uno::Reference< beans::XPropertySet > xCursorProps( mxTextViewCursor, uno::UNO_QUERY_THROW );
965     uno::Reference< text::XTextTable > xTextTable;
966     xCursorProps->getPropertyValue("TextTable") >>= xTextTable;
967     if( !xTextTable.is() )
968         throw uno::RuntimeException( );
969 
970     uno::Reference< text::XTextTableCursor > xTextTableCursor( mxModel->getCurrentSelection(), uno::UNO_QUERY );
971     if( xTextTableCursor.is() )
972     {
973         const OUString sRange( xTextTableCursor->getRangeName() );
974         if (!sRange.isEmpty())
975         {
976             sal_Int32 nIdx{0};
977             sTLName = sRange.getToken(0, ':', nIdx);
978             sBRName = sRange.getToken(0, ':', nIdx);
979         }
980     }
981     if( sTLName.isEmpty() )
982     {
983         uno::Reference< table::XCell > xCell;
984         xCursorProps->getPropertyValue("Cell") >>= xCell;
985         if( !xCell.is() )
986         {
987             throw uno::RuntimeException( );
988         }
989         uno::Reference< beans::XPropertySet > xCellProps( xCell, uno::UNO_QUERY_THROW );
990         xCellProps->getPropertyValue("CellName") >>= sTLName;
991     }
992 }
993 
Cells(const uno::Any & index)994 uno::Any SAL_CALL SwVbaSelection::Cells( const uno::Any& index )
995 {
996     OUString sTLName;
997     OUString sBRName;
998     GetSelectedCellRange( sTLName, sBRName );
999     sal_Int32 nLeft = 0;
1000     sal_Int32 nTop = 0;
1001     sal_Int32 nRight = 0;
1002     sal_Int32 nBottom = 0;
1003 
1004     uno::Reference< text::XTextTable > xTextTable = GetXTextTable();
1005     SwVbaTableHelper aTableHelper( xTextTable );
1006     nLeft = aTableHelper.getTabColIndex( sTLName );
1007     nTop = aTableHelper.getTabRowIndex( sTLName );
1008     if( !sBRName.isEmpty() )
1009     {
1010         nRight = aTableHelper.getTabColIndex( sBRName );
1011         nBottom = aTableHelper.getTabRowIndex( sBRName );
1012     }
1013     else
1014     {
1015         nRight = nLeft;
1016         nBottom = nTop;
1017     }
1018 
1019     uno::Reference< XCollection > xCol( new SwVbaCells( this, mxContext, xTextTable, nLeft, nTop, nRight, nBottom ) );
1020     if ( index.hasValue() )
1021         return xCol->Item( index, uno::Any() );
1022     return uno::makeAny( xCol );
1023 }
1024 
Copy()1025 void SAL_CALL SwVbaSelection::Copy(  )
1026 {
1027     dispatchRequests( mxModel,".uno:Copy" );
1028 }
1029 
CopyAsPicture()1030 void SAL_CALL SwVbaSelection::CopyAsPicture(  )
1031 {
1032     // seems not support in Writer
1033     Copy();
1034 }
1035 
Paste()1036 void SAL_CALL SwVbaSelection::Paste(  )
1037 {
1038     dispatchRequests( mxModel,".uno:Paste" );
1039 }
1040 
Collapse(const uno::Any & Direction)1041 void SAL_CALL SwVbaSelection::Collapse( const uno::Any& Direction )
1042 {
1043     if( word::gotoSelectedObjectAnchor( mxModel ) )
1044         return;
1045 
1046     sal_Int32 nDirection = word::WdCollapseDirection::wdCollapseStart;
1047     if( Direction.hasValue() )
1048         Direction >>= nDirection;
1049 
1050     uno::Reference< text::XTextViewCursor > xTextViewCursor = word::getXTextViewCursor( mxModel );
1051     if( nDirection == word::WdCollapseDirection::wdCollapseStart )
1052     {
1053         // it is inaccurate if current selection is multiple cells, so it needs to go to start
1054         uno::Reference< text::XTextRange > xTextRange = mxTextViewCursor->getStart();
1055         xTextViewCursor->gotoRange( xTextRange, false );
1056         xTextViewCursor->collapseToStart();
1057     }
1058     else if( nDirection == word::WdCollapseDirection::wdCollapseEnd )
1059     {
1060         uno::Reference< text::XTextRange > xTextRange = mxTextViewCursor->getEnd();
1061         xTextViewCursor->gotoRange( xTextRange, false );
1062         xTextViewCursor->collapseToEnd();
1063     }
1064     else
1065     {
1066         throw uno::RuntimeException();
1067     }
1068 }
1069 
WholeStory()1070 void SAL_CALL SwVbaSelection::WholeStory(  )
1071 {
1072     uno::Reference< text::XText > xText = word::getCurrentXText( mxModel );
1073     // FIXME: for i#7747,if the first line is a table, it fails to select all the contents in the story.
1074     // Temporary solution, insert an empty line before the table so that it could select all the contents.
1075     uno::Reference< container::XEnumerationAccess > xParaAccess( xText, uno::UNO_QUERY_THROW );
1076     uno::Reference< container::XEnumeration> xParaEnum = xParaAccess->createEnumeration();
1077     if( xParaEnum->hasMoreElements() )
1078     {
1079         uno::Reference< text::XTextTable > xTextTable( xParaEnum->nextElement(), uno::UNO_QUERY );
1080         if( xTextTable.is() )
1081         {
1082             // insert an empty line
1083             uno::Reference< text::XTextRange > xFirstCellRange = word::getFirstObjectPosition( xText );
1084             mxTextViewCursor->gotoRange( xFirstCellRange, false );
1085             dispatchRequests( mxModel,".uno:InsertPara" );
1086         }
1087     }
1088     uno::Reference< text::XTextRange > xStart = xText->getStart();
1089     uno::Reference< text::XTextRange > xEnd = xText->getEnd();
1090     mxTextViewCursor->gotoRange( xStart, false );
1091     mxTextViewCursor->gotoRange( xEnd, true );
1092 }
1093 
InRange(const uno::Reference<::ooo::vba::word::XRange> & Range)1094 sal_Bool SAL_CALL SwVbaSelection::InRange( const uno::Reference< ::ooo::vba::word::XRange >& Range )
1095 {
1096     return getRange()->InRange( Range );
1097 }
1098 
SplitTable()1099 void SAL_CALL SwVbaSelection::SplitTable()
1100 {
1101     if( !IsInTable() )
1102         throw uno::RuntimeException();
1103 
1104     SwDocShell* pDocShell = word::getDocShell( mxModel );
1105     if( pDocShell )
1106     {
1107         SwFEShell* pFEShell = pDocShell->GetFEShell();
1108         if( pFEShell )
1109         {
1110             pFEShell->SplitTable( SplitTable_HeadlineOption::ContentCopy );
1111         }
1112     }
1113 }
1114 
1115 uno::Any SAL_CALL
Paragraphs(const uno::Any & aIndex)1116 SwVbaSelection::Paragraphs( const uno::Any& aIndex )
1117 {
1118     // Hacky implementation due to missing api ( and lack of knowledge )
1119     // we can only support a selection that is a single paragraph
1120     if ( !aIndex.hasValue() ) // currently we can't support multiple paragraphs in a selection
1121        throw uno::RuntimeException();
1122 
1123     sal_Int32 nIndex = 0;
1124     aIndex >>= nIndex;
1125 
1126     uno::Any aRet;
1127 
1128     if ( nIndex != 1 )
1129        throw uno::RuntimeException();
1130 
1131     uno::Reference< text::XTextRange > xTextRange = mxTextViewCursor->getStart();
1132     uno::Reference< text::XText > xText = xTextRange->getText();
1133     uno::Reference< text::XParagraphCursor > xParaCursor( xText->createTextCursor(), uno::UNO_QUERY_THROW );
1134     xParaCursor->gotoStartOfParagraph( false );
1135     xParaCursor->gotoStartOfParagraph( true );
1136 
1137     uno::Reference< text::XTextDocument > xTextDoc( mxModel, uno::UNO_QUERY_THROW );
1138     uno::Reference< text::XTextRange > xParaRange( xParaCursor, uno::UNO_QUERY_THROW );
1139     uno::Reference< word::XParagraph > xParagraph = new SwVbaParagraph( mxParent, mxContext, xTextDoc, xParaRange );
1140 
1141     aRet <<= xParagraph;
1142     return aRet;
1143 }
1144 
1145 OUString
getServiceImplName()1146 SwVbaSelection::getServiceImplName()
1147 {
1148     return "SwVbaSelection";
1149 }
1150 
1151 uno::Sequence< OUString >
getServiceNames()1152 SwVbaSelection::getServiceNames()
1153 {
1154     static uno::Sequence< OUString > const aServiceNames
1155     {
1156         "ooo.vba.word.Selection"
1157     };
1158     return aServiceNames;
1159 }
1160 
1161 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1162