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