1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 #include "vbaview.hxx" 28 #include <vbahelper/vbahelper.hxx> 29 #include <tools/diagnose_ex.h> 30 #include <com/sun/star/beans/XPropertySet.hpp> 31 #include <com/sun/star/view/XViewSettingsSupplier.hpp> 32 #include <com/sun/star/text/XTextViewCursorSupplier.hpp> 33 #include <com/sun/star/text/XText.hpp> 34 #include <com/sun/star/text/XTextTable.hpp> 35 #include <com/sun/star/table/XCellRange.hpp> 36 #include <com/sun/star/text/XTextDocument.hpp> 37 #include <com/sun/star/text/XFootnotesSupplier.hpp> 38 #include <com/sun/star/text/XEndnotesSupplier.hpp> 39 #include <com/sun/star/container/XIndexAccess.hpp> 40 #include <com/sun/star/container/XEnumerationAccess.hpp> 41 #include <com/sun/star/container/XEnumeration.hpp> 42 #include <com/sun/star/frame/XController.hpp> 43 #include <com/sun/star/lang/XServiceInfo.hpp> 44 #include <ooo/vba/word/WdSpecialPane.hpp> 45 #include <ooo/vba/word/WdViewType.hpp> 46 #include <ooo/vba/word/WdSeekView.hpp> 47 48 #include "wordvbahelper.hxx" 49 #include "vbaheaderfooterhelper.hxx" 50 #include <view.hxx> 51 52 using namespace ::ooo::vba; 53 using namespace ::com::sun::star; 54 55 static const sal_Int32 DEFAULT_BODY_DISTANCE = 500; 56 57 SwVbaView::SwVbaView( const uno::Reference< ooo::vba::XHelperInterface >& rParent, const uno::Reference< uno::XComponentContext >& rContext, 58 const uno::Reference< frame::XModel >& rModel ) throw ( uno::RuntimeException ) : 59 SwVbaView_BASE( rParent, rContext ), mxModel( rModel ) 60 { 61 uno::Reference< frame::XController > xController = mxModel->getCurrentController(); 62 63 uno::Reference< text::XTextViewCursorSupplier > xTextViewCursorSupp( xController, uno::UNO_QUERY_THROW ); 64 mxViewCursor = xTextViewCursorSupp->getViewCursor(); 65 66 uno::Reference< view::XViewSettingsSupplier > xViewSettingSupp( xController, uno::UNO_QUERY_THROW ); 67 mxViewSettings.set( xViewSettingSupp->getViewSettings(), uno::UNO_QUERY_THROW ); 68 } 69 70 SwVbaView::~SwVbaView() 71 { 72 } 73 74 ::sal_Int32 SAL_CALL 75 SwVbaView::getSeekView() throw (css::uno::RuntimeException) 76 { 77 // FIXME: if the view cursor is in table, field, section and frame 78 // handle if the cursor is in table 79 uno::Reference< text::XText > xCurrentText = mxViewCursor->getText(); 80 uno::Reference< beans::XPropertySet > xCursorProps( mxViewCursor, uno::UNO_QUERY_THROW ); 81 uno::Reference< text::XTextContent > xTextContent; 82 while( xCursorProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("TextTable") ) ) >>= xTextContent ) 83 { 84 xCurrentText = xTextContent->getAnchor()->getText(); 85 xCursorProps.set( xCurrentText->createTextCursor(), uno::UNO_QUERY_THROW ); 86 } 87 uno::Reference< lang::XServiceInfo > xServiceInfo( xCurrentText, uno::UNO_QUERY_THROW ); 88 rtl::OUString aImplName = xServiceInfo->getImplementationName(); 89 if( aImplName.equalsAscii("SwXBodyText") ) 90 { 91 return word::WdSeekView::wdSeekMainDocument; 92 } 93 else if( aImplName.equalsAscii("SwXHeadFootText") ) 94 { 95 if( HeaderFooterHelper::isHeader( mxModel, xCurrentText ) ) 96 { 97 if( HeaderFooterHelper::isFirstPageHeader( mxModel, xCurrentText ) ) 98 return word::WdSeekView::wdSeekFirstPageHeader; 99 else if( HeaderFooterHelper::isEvenPagesHeader( mxModel, xCurrentText ) ) 100 return word::WdSeekView::wdSeekEvenPagesHeader; 101 else 102 return word::WdSeekView::wdSeekPrimaryHeader; 103 } 104 else 105 { 106 if( HeaderFooterHelper::isFirstPageFooter( mxModel, xCurrentText ) ) 107 return word::WdSeekView::wdSeekFirstPageFooter; 108 else if( HeaderFooterHelper::isEvenPagesFooter( mxModel, xCurrentText ) ) 109 return word::WdSeekView::wdSeekEvenPagesFooter; 110 else 111 return word::WdSeekView::wdSeekPrimaryFooter; 112 } 113 } 114 else if( aImplName.equalsAscii("SwXFootnote") ) 115 { 116 if( xServiceInfo->supportsService( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Endnote") ) ) ) 117 return word::WdSeekView::wdSeekEndnotes; 118 else 119 return word::WdSeekView::wdSeekFootnotes; 120 } 121 122 return word::WdSeekView::wdSeekMainDocument; 123 } 124 125 void SAL_CALL 126 SwVbaView::setSeekView( ::sal_Int32 _seekview ) throw (css::uno::RuntimeException) 127 { 128 // FIXME: save the current cursor position, if the cursor is in the main 129 // document, so we can jump back to this position, if the macro sets 130 // the ViewMode back to wdSeekMainDocument 131 132 // if( _seekview == getSeekView() ) 133 // return; 134 135 switch( _seekview ) 136 { 137 case word::WdSeekView::wdSeekFirstPageFooter: 138 case word::WdSeekView::wdSeekFirstPageHeader: 139 case word::WdSeekView::wdSeekCurrentPageFooter: 140 case word::WdSeekView::wdSeekCurrentPageHeader: 141 case word::WdSeekView::wdSeekPrimaryFooter: 142 case word::WdSeekView::wdSeekPrimaryHeader: 143 case word::WdSeekView::wdSeekEvenPagesFooter: 144 case word::WdSeekView::wdSeekEvenPagesHeader: 145 { 146 // need to test 147 mxViewCursor->gotoRange( getHFTextRange( _seekview ), sal_False ); 148 break; 149 } 150 case word::WdSeekView::wdSeekFootnotes: 151 { 152 uno::Reference< text::XFootnotesSupplier > xFootnotesSupp( mxModel, uno::UNO_QUERY_THROW ); 153 uno::Reference< container::XIndexAccess > xFootnotes( xFootnotesSupp->getFootnotes(), uno::UNO_QUERY_THROW ); 154 if( xFootnotes->getCount() > 0 ) 155 { 156 uno::Reference< text::XText > xText( xFootnotes->getByIndex(0), uno::UNO_QUERY_THROW ); 157 mxViewCursor->gotoRange( xText->getStart(), sal_False ); 158 } 159 else 160 { 161 DebugHelper::exception( SbERR_NO_ACTIVE_OBJECT, rtl::OUString() ); 162 } 163 break; 164 } 165 case word::WdSeekView::wdSeekEndnotes: 166 { 167 uno::Reference< text::XEndnotesSupplier > xEndnotesSupp( mxModel, uno::UNO_QUERY_THROW ); 168 uno::Reference< container::XIndexAccess > xEndnotes( xEndnotesSupp->getEndnotes(), uno::UNO_QUERY_THROW ); 169 if( xEndnotes->getCount() > 0 ) 170 { 171 uno::Reference< text::XText > xText( xEndnotes->getByIndex(0), uno::UNO_QUERY_THROW ); 172 mxViewCursor->gotoRange( xText->getStart(), sal_False ); 173 } 174 else 175 { 176 DebugHelper::exception( SbERR_NO_ACTIVE_OBJECT, rtl::OUString() ); 177 } 178 break; 179 } 180 case word::WdSeekView::wdSeekMainDocument: 181 { 182 uno::Reference< text::XTextDocument > xTextDocument( mxModel, uno::UNO_QUERY_THROW ); 183 uno::Reference< text::XText > xText = xTextDocument->getText(); 184 mxViewCursor->gotoRange( getFirstObjectPosition( xText ), sal_False ); 185 break; 186 } 187 } 188 } 189 190 ::sal_Int32 SAL_CALL 191 SwVbaView::getSplitSpecial() throw (css::uno::RuntimeException) 192 { 193 return word::WdSpecialPane::wdPaneNone; 194 } 195 196 void SAL_CALL 197 SwVbaView::setSplitSpecial( ::sal_Int32/* _splitspecial */) throw (css::uno::RuntimeException) 198 { 199 // not support in Writer 200 } 201 202 ::sal_Bool SAL_CALL 203 SwVbaView::getTableGridLines() throw (css::uno::RuntimeException) 204 { 205 sal_Bool bShowTableGridLine = sal_False; 206 mxViewSettings->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowTableBoundaries"))) >>= bShowTableGridLine; 207 return bShowTableGridLine; 208 } 209 210 void SAL_CALL 211 SwVbaView::setTableGridLines( ::sal_Bool _tablegridlines ) throw (css::uno::RuntimeException) 212 { 213 mxViewSettings->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowTableBoundaries")), uno::makeAny( _tablegridlines ) ); 214 } 215 216 ::sal_Int32 SAL_CALL 217 SwVbaView::getType() throw (css::uno::RuntimeException) 218 { 219 // FIXME: handle wdPrintPreview type 220 sal_Bool bOnlineLayout = sal_False; 221 mxViewSettings->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowOnlineLayout"))) >>= bOnlineLayout; 222 return bOnlineLayout ? word::WdViewType::wdWebView : word::WdViewType::wdPrintView; 223 } 224 225 void SAL_CALL 226 SwVbaView::setType( ::sal_Int32 _type ) throw (css::uno::RuntimeException) 227 { 228 // FIXME: handle wdPrintPreview type 229 switch( _type ) 230 { 231 case word::WdViewType::wdPrintView: 232 case word::WdViewType::wdNormalView: 233 { 234 mxViewSettings->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowOnlineLayout")), uno::makeAny( sal_False ) ); 235 break; 236 } 237 case word::WdViewType::wdWebView: 238 { 239 mxViewSettings->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ShowOnlineLayout")), uno::makeAny( sal_True ) ); 240 break; 241 } 242 case word::WdViewType::wdPrintPreview: 243 { 244 PrintPreviewHelper( uno::Any(),word::getView( mxModel ) ); 245 break; 246 } 247 default: 248 DebugHelper::exception( SbERR_NOT_IMPLEMENTED, rtl::OUString() ); 249 250 } 251 } 252 253 uno::Reference< text::XTextRange > SwVbaView::getHFTextRange( sal_Int32 nType ) throw (uno::RuntimeException) 254 { 255 mxModel->lockControllers(); 256 257 rtl::OUString aPropIsOn; 258 rtl::OUString aPropIsShared; 259 rtl::OUString aPropBodyDistance; 260 rtl::OUString aPropText; 261 262 switch( nType ) 263 { 264 case word::WdSeekView::wdSeekCurrentPageFooter: 265 case word::WdSeekView::wdSeekFirstPageFooter: 266 case word::WdSeekView::wdSeekPrimaryFooter: 267 case word::WdSeekView::wdSeekEvenPagesFooter: 268 { 269 aPropIsOn = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FooterIsOn") ); 270 aPropIsShared = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FooterIsShared") ); 271 aPropBodyDistance = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FooterBodyDistance") ); 272 aPropText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("FooterText") ); 273 break; 274 } 275 case word::WdSeekView::wdSeekCurrentPageHeader: 276 case word::WdSeekView::wdSeekFirstPageHeader: 277 case word::WdSeekView::wdSeekPrimaryHeader: 278 case word::WdSeekView::wdSeekEvenPagesHeader: 279 { 280 aPropIsOn = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("HeaderIsOn") ); 281 aPropIsShared = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("HeaderIsShared") ); 282 aPropBodyDistance = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("HeaderBodyDistance") ); 283 aPropText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("HeaderText") ); 284 break; 285 } 286 } 287 288 uno::Reference< text::XPageCursor > xPageCursor( mxViewCursor, uno::UNO_QUERY_THROW ); 289 290 if( nType == word::WdSeekView::wdSeekFirstPageFooter 291 || nType == word::WdSeekView::wdSeekFirstPageHeader ) 292 { 293 xPageCursor->jumpToFirstPage(); 294 } 295 296 uno::Reference< style::XStyle > xStyle; 297 uno::Reference< text::XText > xText; 298 switch( nType ) 299 { 300 case word::WdSeekView::wdSeekPrimaryFooter: 301 case word::WdSeekView::wdSeekPrimaryHeader: 302 case word::WdSeekView::wdSeekEvenPagesFooter: 303 case word::WdSeekView::wdSeekEvenPagesHeader: 304 { 305 // The primary header is the first header of the section. 306 // If the header is not shared between odd and even pages 307 // the odd page's header is the primary header. If the 308 // first page's header is different from the rest of the 309 // document, it is NOT the primary header ( the next primary 310 // header would be on page 3 ) 311 // The even pages' header is only available if the header is 312 // not shared and the current style is applied to a page with 313 // an even page number 314 uno::Reference< beans::XPropertySet > xCursorProps( mxViewCursor, uno::UNO_QUERY_THROW ); 315 rtl::OUString aPageStyleName; 316 xCursorProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("PageStyleName"))) >>= aPageStyleName; 317 if( aPageStyleName.equalsAscii("First Page") ) 318 { 319 // go to the beginning of where the next style is used 320 sal_Bool hasNextPage = sal_False; 321 xStyle = word::getCurrentPageStyle( mxModel ); 322 do 323 { 324 hasNextPage = xPageCursor->jumpToNextPage(); 325 } 326 while( hasNextPage && ( xStyle == word::getCurrentPageStyle( mxModel ) ) ); 327 328 if( !hasNextPage ) 329 DebugHelper::exception( SbERR_BAD_ACTION, rtl::OUString() ); 330 } 331 break; 332 } 333 default: 334 { 335 break; 336 } 337 } 338 339 xStyle = word::getCurrentPageStyle( mxModel ); 340 uno::Reference< beans::XPropertySet > xPageProps( xStyle, uno::UNO_QUERY_THROW ); 341 sal_Bool isOn = sal_False; 342 xPageProps->getPropertyValue( aPropIsOn ) >>= isOn; 343 sal_Bool isShared = sal_False; 344 xPageProps->getPropertyValue( aPropIsShared ) >>= isShared; 345 if( !isOn ) 346 { 347 xPageProps->setPropertyValue( aPropIsOn, uno::makeAny( sal_True ) ); 348 xPageProps->setPropertyValue( aPropBodyDistance, uno::makeAny( DEFAULT_BODY_DISTANCE ) ); 349 } 350 if( !isShared ) 351 { 352 rtl::OUString aTempPropText = aPropText; 353 if( nType == word::WdSeekView::wdSeekEvenPagesFooter 354 || nType == word::WdSeekView::wdSeekEvenPagesHeader ) 355 { 356 aTempPropText += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Left") ); 357 } 358 else 359 { 360 aTempPropText += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Right") ); 361 } 362 xText.set( xPageProps->getPropertyValue( aTempPropText), uno::UNO_QUERY_THROW ); 363 } 364 else 365 { 366 if( nType == word::WdSeekView::wdSeekEvenPagesFooter 367 || nType == word::WdSeekView::wdSeekEvenPagesHeader ) 368 { 369 DebugHelper::exception( SbERR_BAD_ACTION, rtl::OUString() ); 370 } 371 xText.set( xPageProps->getPropertyValue( aPropText ), uno::UNO_QUERY_THROW ); 372 } 373 374 mxModel->unlockControllers(); 375 if( !xText.is() ) 376 { 377 DebugHelper::exception( SbERR_INTERNAL_ERROR, rtl::OUString() ); 378 } 379 uno::Reference< text::XTextRange > xTextRange = getFirstObjectPosition( xText ); 380 return xTextRange; 381 } 382 383 uno::Reference< text::XTextRange > SwVbaView::getFirstObjectPosition( const uno::Reference< text::XText >& xText ) throw (uno::RuntimeException) 384 { 385 // if the first object is table, get the position of first cell 386 uno::Reference< text::XTextRange > xTextRange; 387 uno::Reference< container::XEnumerationAccess > xParaAccess( xText, uno::UNO_QUERY_THROW ); 388 uno::Reference< container::XEnumeration> xParaEnum = xParaAccess->createEnumeration(); 389 if( xParaEnum->hasMoreElements() ) 390 { 391 uno::Reference< lang::XServiceInfo > xServiceInfo( xParaEnum->nextElement(), uno::UNO_QUERY_THROW ); 392 if( xServiceInfo->supportsService( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextTable") ) ) ) 393 { 394 uno::Reference< table::XCellRange > xCellRange( xServiceInfo, uno::UNO_QUERY_THROW ); 395 uno::Reference< text::XText> xFirstCellText( xCellRange->getCellByPosition(0, 0), uno::UNO_QUERY_THROW ); 396 xTextRange = xFirstCellText->getStart(); 397 } 398 } 399 if( !xTextRange.is() ) 400 xTextRange = xText->getStart(); 401 return xTextRange; 402 } 403 404 rtl::OUString& 405 SwVbaView::getServiceImplName() 406 { 407 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaView") ); 408 return sImplName; 409 } 410 411 uno::Sequence< rtl::OUString > 412 SwVbaView::getServiceNames() 413 { 414 static uno::Sequence< rtl::OUString > aServiceNames; 415 if ( aServiceNames.getLength() == 0 ) 416 { 417 aServiceNames.realloc( 1 ); 418 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.View" ) ); 419 } 420 return aServiceNames; 421 } 422 423