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
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26
27 //_________________________________________________________________________________________________________________
28 // my own includes
29 //_________________________________________________________________________________________________________________
30 #include <services/license.hxx>
31 #include <threadhelp/resetableguard.hxx>
32 #include <macros/debug.hxx>
33 #include <services.h>
34
35 // local header for UI implementation
36 #include "services/licensedlg.hxx"
37 #include "classes/resource.hrc"
38
39 //_________________________________________________________________________________________________________________
40 // interface includes
41 //_________________________________________________________________________________________________________________
42
43 #include <com/sun/star/frame/XDesktop.hpp>
44 #include <com/sun/star/lang/XInitialization.hpp>
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 #include <com/sun/star/uno/Any.hxx>
47 #include <com/sun/star/util/XChangesBatch.hpp>
48 #include <com/sun/star/beans/NamedValue.hpp>
49 #include <com/sun/star/lang/XComponent.hpp>
50
51
52 //_________________________________________________________________________________________________________________
53 // includes of other projects
54 //_________________________________________________________________________________________________________________
55
56 #include <rtl/ustrbuf.hxx>
57 #include <rtl/strbuf.hxx>
58 #include <rtl/ustring.hxx>
59 #include <rtl/string.hxx>
60 #include <unotools/bootstrap.hxx>
61 #include <osl/file.hxx>
62 #include <svtools/xtextedt.hxx>
63 #include <vcl/svapp.hxx>
64 #include <comphelper/processfactory.hxx>
65 #include <tools/date.hxx>
66 #include <tools/time.hxx>
67 #include <tools/datetime.hxx>
68 #include <osl/file.hxx>
69 #include <osl/time.h>
70
71 //_________________________________________________________________________________________________________________
72 // namespace
73 //_________________________________________________________________________________________________________________
74
75 namespace framework{
76 using namespace utl;
77 using namespace ::osl ;
78 using namespace ::cppu ;
79 using namespace ::com::sun::star::uno ;
80 using namespace ::com::sun::star::beans ;
81 using namespace ::com::sun::star::lang ;
82 using namespace ::com::sun::star::util ;
83 using namespace ::com::sun::star::frame ;
84
85 //_________________________________________________________________________________________________________________
86 // non exported const
87 //_________________________________________________________________________________________________________________
88
89 // license file name
90 static const char *szLicensePath = "/share/readme";
91 #ifdef UNX
92 static const char *szUNXLicenseName = "/LICENSE";
93 static const char *szUNXLicenseExt = "";
94 #elif defined(WNT) || defined(OS2)
95 static const char *szWNTLicenseName = "/license";
96 static const char *szWNTLicenseExt = ".txt";
97 #endif
98
99 //_________________________________________________________________________________________________________________
100 // non exported definitions
101 //_________________________________________________________________________________________________________________
102
103 //_________________________________________________________________________________________________________________
104 // declarations
105 //_________________________________________________________________________________________________________________
106
107 //*****************************************************************************************************************
108 // constructor
109 //*****************************************************************************************************************
License(const Reference<XMultiServiceFactory> & xFactory)110 License::License( const Reference< XMultiServiceFactory >& xFactory )
111 // Init baseclasses first
112 // Attention:
113 // Don't change order of initialization!
114 // ThreadHelpBase is a struct with a mutex as member. We can't use a mutex as member, while
115 // we must garant right initialization and a valid value of this! First initialize
116 // baseclasses and then members. And we need the mutex for other baseclasses !!!
117 : ThreadHelpBase ( &Application::GetSolarMutex() )
118 , OWeakObject ( )
119 // Init member
120 , m_xFactory ( xFactory )
121 , m_bTerminate ( sal_False )
122 {
123 }
124
125 //*****************************************************************************************************************
126 // destructor
127 //*****************************************************************************************************************
~License()128 License::~License()
129 {
130 }
131
132 //*****************************************************************************************************************
133 // XInterface, XTypeProvider, XServiceInfo
134 //*****************************************************************************************************************
135
DEFINE_XINTERFACE_4(License,OWeakObject,DIRECT_INTERFACE (XTypeProvider),DIRECT_INTERFACE (XServiceInfo),DIRECT_INTERFACE (XJob),DIRECT_INTERFACE (XCloseable))136 DEFINE_XINTERFACE_4 ( License ,
137 OWeakObject ,
138 DIRECT_INTERFACE(XTypeProvider ),
139 DIRECT_INTERFACE(XServiceInfo ),
140 DIRECT_INTERFACE(XJob ),
141 DIRECT_INTERFACE(XCloseable )
142 )
143
144 DEFINE_XTYPEPROVIDER_4 ( License ,
145 XTypeProvider ,
146 XServiceInfo ,
147 XJob ,
148 XCloseable
149 )
150
151 DEFINE_XSERVICEINFO_MULTISERVICE ( License,
152 OWeakObject ,
153 SERVICENAME_LICENSE ,
154 IMPLEMENTATIONNAME_LICENSE
155 )
156
157 DEFINE_INIT_SERVICE ( License,
158 {
159 }
160 )
161
162
163 #if 0
164 IMPL_STATIC_LINK_NOINSTANCE( License, Terminate, void*, EMPTYARG )
165 {
166 /*
167 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
168 Reference< XDesktop > xDesktop(xFactory->createInstance(
169 ::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY);
170 if (xDesktop.is())
171 xDesktop->terminate();
172 */
173 /*
174 _exit(0);
175 */
176 return 0;
177 }
178 #endif
179
180 static DateTime _oslDateTimeToDateTime(const oslDateTime& aDateTime)
181 {
182 return DateTime(
183 Date(aDateTime.Day, aDateTime.Month, aDateTime.Year),
184 Time(aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds));
185 }
186
_makeDateTimeString(const DateTime & aDateTime,sal_Bool bUTC=sal_False)187 static ::rtl::OUString _makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_False)
188 {
189 ::rtl::OStringBuffer aDateTimeString;
190 aDateTimeString.append((sal_Int32)aDateTime.GetYear());
191 aDateTimeString.append("-");
192 if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
193 aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
194 aDateTimeString.append("-");
195 if (aDateTime.GetDay()<10) aDateTimeString.append("0");
196 aDateTimeString.append((sal_Int32)aDateTime.GetDay());
197 aDateTimeString.append("T");
198 if (aDateTime.GetHour()<10) aDateTimeString.append("0");
199 aDateTimeString.append((sal_Int32)aDateTime.GetHour());
200 aDateTimeString.append(":");
201 if (aDateTime.GetMin()<10) aDateTimeString.append("0");
202 aDateTimeString.append((sal_Int32)aDateTime.GetMin());
203 aDateTimeString.append(":");
204 if (aDateTime.GetSec()<10) aDateTimeString.append("0");
205 aDateTimeString.append((sal_Int32)aDateTime.GetSec());
206 if (bUTC) aDateTimeString.append("Z");
207
208 return OStringToOUString(aDateTimeString.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
209 }
210
_parseDateTime(const::rtl::OUString & aString,DateTime & aDateTime)211 static sal_Bool _parseDateTime(const ::rtl::OUString& aString, DateTime& aDateTime)
212 {
213 // take apart a canonical literal xsd:dateTime string
214 //CCYY-MM-DDThh:mm:ss(Z)
215
216 ::rtl::OUString aDateTimeString = aString.trim();
217
218 // check length
219 if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20)
220 return sal_False;
221
222 sal_Int32 nDateLength = 10;
223 sal_Int32 nTimeLength = 8;
224
225 ::rtl::OUString aDateTimeSep = ::rtl::OUString::createFromAscii("T");
226 ::rtl::OUString aDateSep = ::rtl::OUString::createFromAscii("-");
227 ::rtl::OUString aTimeSep = ::rtl::OUString::createFromAscii(":");
228 ::rtl::OUString aUTCString = ::rtl::OUString::createFromAscii("Z");
229
230 ::rtl::OUString aDateString = aDateTimeString.copy(0, nDateLength);
231 ::rtl::OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength);
232
233 sal_Int32 nIndex = 0;
234 sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32();
235 sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32();
236 sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32();
237 nIndex = 0;
238 sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32();
239 sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32();
240 sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32();
241
242 Date tmpDate((sal_uInt16)nDay, (sal_uInt16)nMonth, (sal_uInt16)nYear);
243 Time tmpTime(nHour, nMinute, nSecond);
244 DateTime tmpDateTime(tmpDate, tmpTime);
245 if (aString.indexOf(aUTCString) < 0)
246 tmpDateTime.ConvertToUTC();
247
248 aDateTime = tmpDateTime;
249 return sal_True;
250 }
251
_getCurrentDateString()252 static ::rtl::OUString _getCurrentDateString()
253 {
254 ::rtl::OUString aString;
255 return _makeDateTimeString(DateTime());
256 }
257
258 // execution of license check...
execute(const css::uno::Sequence<css::beans::NamedValue> &)259 css::uno::Any SAL_CALL License::execute(const css::uno::Sequence< css::beans::NamedValue >& )
260 throw( css::lang::IllegalArgumentException, css::uno::Exception)
261 {
262 // return value
263 Any aRet; aRet <<= sal_False;
264
265 try
266 {
267 ::rtl::OUString aBaseInstallPath;
268 Bootstrap::PathStatus aBaseLocateResult =
269 Bootstrap::locateBaseInstallation(aBaseInstallPath);
270 if (aBaseLocateResult != Bootstrap::PATH_EXISTS)
271 {
272 // base install noit found
273 // prepare termination
274 // m_bTerminate = sal_True;
275 // Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
276 aRet <<= sal_False;
277 return aRet;
278 }
279 // determine the filename of the license to show
280 ::rtl::OUString aLangString;
281 ::com::sun::star::lang::Locale aLocale;
282 ::rtl::OString aMgrName = ::rtl::OString("fwe");
283 AllSettings aSettings(Application::GetSettings());
284 aLocale = aSettings.GetUILocale();
285 ResMgr* pResMgr = ResMgr::SearchCreateResMgr( aMgrName.getStr(), aLocale);
286
287 aLangString = aLocale.Language;
288 if ( aLocale.Country.getLength() != 0 )
289 {
290 aLangString += ::rtl::OUString::createFromAscii("-");
291 aLangString += aLocale.Country;
292 if ( aLocale.Variant.getLength() != 0 )
293 {
294 aLangString += ::rtl::OUString::createFromAscii("-");
295 aLangString += aLocale.Variant;
296 }
297 }
298 #if defined(WNT) || defined(OS2)
299 ::rtl::OUString aLicensePath =
300 aBaseInstallPath + ::rtl::OUString::createFromAscii(szLicensePath)
301 + ::rtl::OUString::createFromAscii(szWNTLicenseName)
302 + ::rtl::OUString::createFromAscii("_")
303 + aLangString
304 + ::rtl::OUString::createFromAscii(szWNTLicenseExt);
305 #else
306 ::rtl::OUString aLicensePath =
307 aBaseInstallPath + ::rtl::OUString::createFromAscii(szLicensePath)
308 + ::rtl::OUString::createFromAscii(szUNXLicenseName)
309 + ::rtl::OUString::createFromAscii("_")
310 + aLangString
311 + ::rtl::OUString::createFromAscii(szUNXLicenseExt);
312 #endif
313 // check if we need to show the license at all
314 // open org.openoffice.Setup/Office/ooLicenseAcceptDate
315 ::rtl::OUString sConfigSrvc = SERVICENAME_CFGPROVIDER;
316 ::rtl::OUString sAccessSrvc = ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
317 ::rtl::OUString sReadSrvc = SERVICENAME_CFGREADACCESS;
318
319 // get configuration provider
320 Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
321 m_xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW);
322 Sequence< Any > theArgs(1);
323 NamedValue v;
324 v.Name = ::rtl::OUString::createFromAscii("NodePath");
325 v.Value <<= ::rtl::OUString::createFromAscii("org.openoffice.Setup/Office");
326 theArgs[0] <<= v;
327 Reference< XPropertySet > pset = Reference< XPropertySet >(
328 theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
329
330 // if we find a date there, compare it to baseinstall license date
331 ::rtl::OUString aAcceptDate;
332 if (pset->getPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate")) >>= aAcceptDate)
333 {
334 // get LicenseFileDate from base install
335 ::rtl::OUString aLicenseURL = aLicensePath;
336 /*
337 if (FileBase::getFileURLFromSystemPath(aLicensePath, aLicenseURL) != FileBase::E_None)
338 return makeAny(sal_False);
339 */
340 DirectoryItem aDirItem;
341 if (DirectoryItem::get(aLicenseURL, aDirItem) != FileBase::E_None)
342 return makeAny(sal_False);
343 FileStatus aStatus(FileStatusMask_All);
344 if (aDirItem.getFileStatus(aStatus) != FileBase::E_None)
345 return makeAny(sal_False);
346 TimeValue aTimeVal = aStatus.getModifyTime();
347 oslDateTime aDateTimeVal;
348 if (!osl_getDateTimeFromTimeValue(&aTimeVal, &aDateTimeVal))
349 return makeAny(sal_False);
350
351 // compare dates
352 DateTime aLicenseDateTime = _oslDateTimeToDateTime(aDateTimeVal);
353 DateTime aAcceptDateTime;
354 if (!_parseDateTime(aAcceptDate, aAcceptDateTime))
355 return makeAny(sal_False);
356
357 if ( aAcceptDateTime > aLicenseDateTime )
358 return makeAny(sal_True);
359 }
360 // prepare to show
361 // display license dialog
362 LicenseDialog* pDialog = new LicenseDialog(aLicensePath, pResMgr);
363 sal_Bool bAgreed = (pDialog->Execute() == 1);
364 delete pDialog;
365
366 if (bAgreed) {
367
368 // write org.openoffice.Setup/ooLicenseAcceptDate
369 aAcceptDate = _getCurrentDateString();
370 pset->setPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate"), makeAny(aAcceptDate));
371 Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();
372
373 // enable quickstarter
374 sal_Bool bQuickstart( sal_True );
375 sal_Bool bAutostart( sal_True );
376 Sequence< Any > aSeq( 2 );
377 aSeq[0] <<= bQuickstart;
378 aSeq[1] <<= bAutostart;
379
380 Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance(
381 ::rtl::OUString::createFromAscii( "com.sun.star.office.Quickstart" )),UNO_QUERY );
382 if ( xQuickstart.is() )
383 xQuickstart->initialize( aSeq );
384
385 aRet <<= sal_True;
386 }
387 else
388 {
389 // license was not accepted
390 // prepare termination
391 // m_bTerminate = sal_True;
392 // Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
393 aRet <<= sal_False;
394 }
395 }
396 catch (RuntimeException&)
397 {
398 // license could not be verified
399 aRet <<= sal_False;
400 }
401 return aRet;
402 }
403
close(sal_Bool)404 void SAL_CALL License::close(sal_Bool /*bDeliverOwnership*/) throw (css::util::CloseVetoException)
405 {
406 if (!m_bTerminate)
407 throw CloseVetoException();
408 }
addCloseListener(const css::uno::Reference<css::util::XCloseListener> &)409 void SAL_CALL License::addCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
410 throw (css::uno::RuntimeException)
411 {
412 }
removeCloseListener(const css::uno::Reference<css::util::XCloseListener> &)413 void SAL_CALL License::removeCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
414 throw (css::uno::RuntimeException)
415 {
416 }
417
418
419 //************************************************************************
420 // License Dialog
421 //************************************************************************
422
LicenseDialog(const::rtl::OUString & aLicensePath,ResMgr * pResMgr)423 LicenseDialog::LicenseDialog(const ::rtl::OUString & aLicensePath, ResMgr *pResMgr) :
424 ModalDialog(NULL, ResId(DLG_LICENSE, *pResMgr)),
425 aLicenseML(this, ResId(ML_LICENSE, *pResMgr)),
426 aInfo1FT(this, ResId(FT_INFO1, *pResMgr)),
427 aInfo2FT(this, ResId(FT_INFO2, *pResMgr)),
428 aInfo3FT(this, ResId(FT_INFO3, *pResMgr)),
429 aInfo2_1FT(this, ResId(FT_INFO2_1, *pResMgr)),
430 aInfo3_1FT(this, ResId(FT_INFO3_1, *pResMgr)),
431 aFixedLine(this, ResId(FL_DIVIDE, *pResMgr)),
432 aPBPageDown(this, ResId(PB_PAGEDOWN, *pResMgr)),
433 aPBDecline( this, ResId(PB_DECLINE, *pResMgr) ),
434 aPBAccept( this, ResId(PB_ACCEPT, *pResMgr) ),
435 aArrow(this, ResId(IMG_ARROW, *pResMgr)),
436 aStrAccept( ResId(LICENSE_ACCEPT, *pResMgr) ),
437 aStrNotAccept( ResId(LICENSE_NOTACCEPT, *pResMgr) ),
438 bEndReached(sal_False)
439 {
440 FreeResource();
441
442 aLicenseML.SetEndReachedHdl( LINK(this, LicenseDialog, EndReachedHdl) );
443 aLicenseML.SetScrolledHdl( LINK(this, LicenseDialog, ScrolledHdl) );
444
445 aPBPageDown.SetClickHdl( LINK(this, LicenseDialog, PageDownHdl) );
446 aPBDecline.SetClickHdl( LINK(this, LicenseDialog, DeclineBtnHdl) );
447 aPBAccept.SetClickHdl( LINK(this, LicenseDialog, AcceptBtnHdl) );
448
449 // We want a automatic repeating page down button
450 WinBits aStyle = aPBPageDown.GetStyle();
451 aStyle |= WB_REPEAT;
452 aPBPageDown.SetStyle( aStyle );
453
454 String aText = aInfo2FT.GetText();
455 aText.SearchAndReplaceAll( UniString::CreateFromAscii("%PAGEDOWN"), aPBPageDown.GetText() );
456 aInfo2FT.SetText( aText );
457
458 aPBDecline.SetText( aStrNotAccept );
459 aPBAccept.SetText( aStrAccept );
460
461 aPBAccept.Disable();
462
463 // load license text
464 File aLicenseFile(aLicensePath);
465 if ( aLicenseFile.open(OpenFlag_Read) == FileBase::E_None)
466 {
467 DirectoryItem d;
468 DirectoryItem::get(aLicensePath, d);
469 FileStatus fs(FileStatusMask_FileSize);
470 d.getFileStatus(fs);
471 sal_uInt64 nBytesRead = 0;
472 sal_uInt64 nPosition = 0;
473 sal_uInt32 nBytes = (sal_uInt32)fs.getFileSize();
474 sal_Char *pBuffer = new sal_Char[nBytes];
475 // FileBase RC r = FileBase::E_None;
476 while (aLicenseFile.read(pBuffer+nPosition, nBytes-nPosition, nBytesRead) == FileBase::E_None
477 && nPosition + nBytesRead < nBytes)
478 {
479 nPosition += nBytesRead;
480 }
481 ::rtl::OUString aLicenseString(pBuffer, nBytes, RTL_TEXTENCODING_UTF8,
482 OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_GLOBAL_SIGNATURE);
483 delete[] pBuffer;
484 aLicenseML.SetText(aLicenseString);
485 }
486
487 }
488
~LicenseDialog()489 LicenseDialog::~LicenseDialog()
490 {
491 }
492
IMPL_LINK(LicenseDialog,PageDownHdl,PushButton *,EMPTYARG)493 IMPL_LINK( LicenseDialog, PageDownHdl, PushButton *, EMPTYARG )
494 {
495 aLicenseML.ScrollDown( SCROLL_PAGEDOWN );
496 return 0;
497 }
498
IMPL_LINK(LicenseDialog,EndReachedHdl,LicenseView *,EMPTYARG)499 IMPL_LINK( LicenseDialog, EndReachedHdl, LicenseView *, EMPTYARG )
500 {
501 bEndReached = sal_True;
502
503 EnableControls();
504
505 return 0;
506 }
507
IMPL_LINK(LicenseDialog,ScrolledHdl,LicenseView *,EMPTYARG)508 IMPL_LINK( LicenseDialog, ScrolledHdl, LicenseView *, EMPTYARG )
509 {
510 EnableControls();
511
512 return 0;
513 }
514
IMPL_LINK(LicenseDialog,DeclineBtnHdl,PushButton *,EMPTYARG)515 IMPL_LINK( LicenseDialog, DeclineBtnHdl, PushButton *, EMPTYARG )
516 {
517 EndDialog(0);
518 return 0;
519 }
IMPL_LINK(LicenseDialog,AcceptBtnHdl,PushButton *,EMPTYARG)520 IMPL_LINK( LicenseDialog, AcceptBtnHdl, PushButton *, EMPTYARG )
521 {
522 EndDialog(1);
523 return 0;
524 }
525
526
EnableControls()527 void LicenseDialog::EnableControls()
528 {
529 if( !bEndReached &&
530 ( aLicenseML.IsEndReached() || !aLicenseML.GetText().Len() ) )
531 bEndReached = sal_True;
532
533 if ( bEndReached )
534 {
535 Point aPos( aInfo1FT.GetPosPixel().X(),
536 aInfo3_1FT.GetPosPixel().Y() );
537 aArrow.SetPosPixel( aPos );
538 aPBAccept.Enable();
539 }
540 else
541 {
542 Point aPos( aInfo1FT.GetPosPixel().X(),
543 aInfo2_1FT.GetPosPixel().Y() );
544 aArrow.SetPosPixel( aPos );
545 aPBAccept.Disable();
546 }
547
548 if ( aLicenseML.IsEndReached() )
549 aPBPageDown.Disable();
550 else
551 aPBPageDown.Enable();
552
553 }
554
555
LicenseView(Window * pParent,const ResId & rResId)556 LicenseView::LicenseView( Window* pParent, const ResId& rResId )
557 : MultiLineEdit( pParent, rResId )
558 {
559 SetLeftMargin( 5 );
560
561 mbEndReached = IsEndReached();
562
563 StartListening( *GetTextEngine() );
564 }
565
~LicenseView()566 LicenseView::~LicenseView()
567 {
568 maEndReachedHdl = Link();
569 maScrolledHdl = Link();
570
571 EndListeningAll();
572 }
573
ScrollDown(ScrollType eScroll)574 void LicenseView::ScrollDown( ScrollType eScroll )
575 {
576 ScrollBar* pScroll = GetVScrollBar();
577
578 if ( pScroll )
579 pScroll->DoScrollAction( eScroll );
580 }
581
IsEndReached() const582 sal_Bool LicenseView::IsEndReached() const
583 {
584 sal_Bool bEndReached;
585
586 ExtTextView* pView = GetTextView();
587 ExtTextEngine* pEdit = GetTextEngine();
588 sal_uLong nHeight = pEdit->GetTextHeight();
589 Size aOutSize = pView->GetWindow()->GetOutputSizePixel();
590 Point aBottom( 0, aOutSize.Height() );
591
592 if ( (sal_uLong) pView->GetDocPos( aBottom ).Y() >= nHeight - 1 )
593 bEndReached = sal_True;
594 else
595 bEndReached = sal_False;
596
597 return bEndReached;
598 }
599
Notify(SfxBroadcaster &,const SfxHint & rHint)600 void LicenseView::Notify( SfxBroadcaster&, const SfxHint& rHint )
601 {
602 if ( rHint.IsA( TYPE(TextHint) ) )
603 {
604 sal_Bool bLastVal = EndReached();
605 sal_uLong nId = ((const TextHint&)rHint).GetId();
606
607 if ( nId == TEXT_HINT_PARAINSERTED )
608 {
609 if ( bLastVal )
610 mbEndReached = IsEndReached();
611 }
612 else if ( nId == TEXT_HINT_VIEWSCROLLED )
613 {
614 if ( ! mbEndReached )
615 mbEndReached = IsEndReached();
616 maScrolledHdl.Call( this );
617 }
618
619 if ( EndReached() && !bLastVal )
620 {
621 maEndReachedHdl.Call( this );
622 }
623 }
624 }
625
626 } // namespace framework
627
628