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