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
SwVbaView(const uno::Reference<ooo::vba::XHelperInterface> & rParent,const uno::Reference<uno::XComponentContext> & rContext,const uno::Reference<frame::XModel> & rModel)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
~SwVbaView()66 SwVbaView::~SwVbaView()
67 {
68 }
69
70 ::sal_Int32 SAL_CALL
getSeekView()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
setSeekView(::sal_Int32 _seekview)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
getSplitSpecial()187 SwVbaView::getSplitSpecial() throw (css::uno::RuntimeException)
188 {
189 return word::WdSpecialPane::wdPaneNone;
190 }
191
192 void SAL_CALL
setSplitSpecial(::sal_Int32)193 SwVbaView::setSplitSpecial( ::sal_Int32/* _splitspecial */) throw (css::uno::RuntimeException)
194 {
195 // not support in Writer
196 }
197
198 ::sal_Bool SAL_CALL
getTableGridLines()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
setTableGridLines(::sal_Bool _tablegridlines)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
getType()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
setType(::sal_Int32 _type)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
getHFTextRange(sal_Int32 nType)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
getFirstObjectPosition(const uno::Reference<text::XText> & xText)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&
getServiceImplName()401 SwVbaView::getServiceImplName()
402 {
403 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaView") );
404 return sImplName;
405 }
406
407 uno::Sequence< rtl::OUString >
getServiceNames()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