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 {
261 // return value
262 Any aRet; aRet <<= sal_False;
263
264 try
265 {
266 ::rtl::OUString aBaseInstallPath;
267 Bootstrap::PathStatus aBaseLocateResult =
268 Bootstrap::locateBaseInstallation(aBaseInstallPath);
269 if (aBaseLocateResult != Bootstrap::PATH_EXISTS)
270 {
271 // base install noit found
272 // prepare termination
273 // m_bTerminate = sal_True;
274 // Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
275 aRet <<= sal_False;
276 return aRet;
277 }
278 // determine the filename of the license to show
279 ::rtl::OUString aLangString;
280 ::com::sun::star::lang::Locale aLocale;
281 ::rtl::OString aMgrName = ::rtl::OString("fwe");
282 AllSettings aSettings(Application::GetSettings());
283 aLocale = aSettings.GetUILocale();
284 ResMgr* pResMgr = ResMgr::SearchCreateResMgr( aMgrName.getStr(), aLocale);
285
286 aLangString = aLocale.Language;
287 if ( aLocale.Country.getLength() != 0 )
288 {
289 aLangString += ::rtl::OUString::createFromAscii("-");
290 aLangString += aLocale.Country;
291 if ( aLocale.Variant.getLength() != 0 )
292 {
293 aLangString += ::rtl::OUString::createFromAscii("-");
294 aLangString += aLocale.Variant;
295 }
296 }
297 #if defined(WNT) || defined(OS2)
298 ::rtl::OUString aLicensePath =
299 aBaseInstallPath + ::rtl::OUString::createFromAscii(szLicensePath)
300 + ::rtl::OUString::createFromAscii(szWNTLicenseName)
301 + ::rtl::OUString::createFromAscii("_")
302 + aLangString
303 + ::rtl::OUString::createFromAscii(szWNTLicenseExt);
304 #else
305 ::rtl::OUString aLicensePath =
306 aBaseInstallPath + ::rtl::OUString::createFromAscii(szLicensePath)
307 + ::rtl::OUString::createFromAscii(szUNXLicenseName)
308 + ::rtl::OUString::createFromAscii("_")
309 + aLangString
310 + ::rtl::OUString::createFromAscii(szUNXLicenseExt);
311 #endif
312 // check if we need to show the license at all
313 // open org.openoffice.Setup/Office/ooLicenseAcceptDate
314 ::rtl::OUString sConfigSrvc = SERVICENAME_CFGPROVIDER;
315 ::rtl::OUString sAccessSrvc = ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
316 ::rtl::OUString sReadSrvc = SERVICENAME_CFGREADACCESS;
317
318 // get configuration provider
319 Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
320 m_xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW);
321 Sequence< Any > theArgs(1);
322 NamedValue v;
323 v.Name = ::rtl::OUString::createFromAscii("NodePath");
324 v.Value <<= ::rtl::OUString::createFromAscii("org.openoffice.Setup/Office");
325 theArgs[0] <<= v;
326 Reference< XPropertySet > pset = Reference< XPropertySet >(
327 theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
328
329 // if we find a date there, compare it to baseinstall license date
330 ::rtl::OUString aAcceptDate;
331 if (pset->getPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate")) >>= aAcceptDate)
332 {
333 // get LicenseFileDate from base install
334 ::rtl::OUString aLicenseURL = aLicensePath;
335 /*
336 if (FileBase::getFileURLFromSystemPath(aLicensePath, aLicenseURL) != FileBase::E_None)
337 return makeAny(sal_False);
338 */
339 DirectoryItem aDirItem;
340 if (DirectoryItem::get(aLicenseURL, aDirItem) != FileBase::E_None)
341 return makeAny(sal_False);
342 FileStatus aStatus(FileStatusMask_All);
343 if (aDirItem.getFileStatus(aStatus) != FileBase::E_None)
344 return makeAny(sal_False);
345 TimeValue aTimeVal = aStatus.getModifyTime();
346 oslDateTime aDateTimeVal;
347 if (!osl_getDateTimeFromTimeValue(&aTimeVal, &aDateTimeVal))
348 return makeAny(sal_False);
349
350 // compare dates
351 DateTime aLicenseDateTime = _oslDateTimeToDateTime(aDateTimeVal);
352 DateTime aAcceptDateTime;
353 if (!_parseDateTime(aAcceptDate, aAcceptDateTime))
354 return makeAny(sal_False);
355
356 if ( aAcceptDateTime > aLicenseDateTime )
357 return makeAny(sal_True);
358 }
359 // prepare to show
360 // display license dialog
361 LicenseDialog* pDialog = new LicenseDialog(aLicensePath, pResMgr);
362 sal_Bool bAgreed = (pDialog->Execute() == 1);
363 delete pDialog;
364
365 if (bAgreed) {
366
367 // write org.openoffice.Setup/ooLicenseAcceptDate
368 aAcceptDate = _getCurrentDateString();
369 pset->setPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate"), makeAny(aAcceptDate));
370 Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();
371
372 // enable quickstarter
373 sal_Bool bQuickstart( sal_True );
374 sal_Bool bAutostart( sal_True );
375 Sequence< Any > aSeq( 2 );
376 aSeq[0] <<= bQuickstart;
377 aSeq[1] <<= bAutostart;
378
379 Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance(
380 ::rtl::OUString::createFromAscii( "com.sun.star.office.Quickstart" )),UNO_QUERY );
381 if ( xQuickstart.is() )
382 xQuickstart->initialize( aSeq );
383
384 aRet <<= sal_True;
385 }
386 else
387 {
388 // license was not accepted
389 // prepare termination
390 // m_bTerminate = sal_True;
391 // Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
392 aRet <<= sal_False;
393 }
394 }
395 catch (RuntimeException&)
396 {
397 // license could not be verified
398 aRet <<= sal_False;
399 }
400 return aRet;
401 }
402
close(sal_Bool)403 void SAL_CALL License::close(sal_Bool /*bDeliverOwnership*/)
404 {
405 if (!m_bTerminate)
406 throw CloseVetoException();
407 }
addCloseListener(const css::uno::Reference<css::util::XCloseListener> &)408 void SAL_CALL License::addCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
409 {
410 }
removeCloseListener(const css::uno::Reference<css::util::XCloseListener> &)411 void SAL_CALL License::removeCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
412 {
413 }
414
415
416 //************************************************************************
417 // License Dialog
418 //************************************************************************
419
LicenseDialog(const::rtl::OUString & aLicensePath,ResMgr * pResMgr)420 LicenseDialog::LicenseDialog(const ::rtl::OUString & aLicensePath, ResMgr *pResMgr) :
421 ModalDialog(NULL, ResId(DLG_LICENSE, *pResMgr)),
422 aLicenseML(this, ResId(ML_LICENSE, *pResMgr)),
423 aInfo1FT(this, ResId(FT_INFO1, *pResMgr)),
424 aInfo2FT(this, ResId(FT_INFO2, *pResMgr)),
425 aInfo3FT(this, ResId(FT_INFO3, *pResMgr)),
426 aInfo2_1FT(this, ResId(FT_INFO2_1, *pResMgr)),
427 aInfo3_1FT(this, ResId(FT_INFO3_1, *pResMgr)),
428 aFixedLine(this, ResId(FL_DIVIDE, *pResMgr)),
429 aPBPageDown(this, ResId(PB_PAGEDOWN, *pResMgr)),
430 aPBDecline( this, ResId(PB_DECLINE, *pResMgr) ),
431 aPBAccept( this, ResId(PB_ACCEPT, *pResMgr) ),
432 aArrow(this, ResId(IMG_ARROW, *pResMgr)),
433 aStrAccept( ResId(LICENSE_ACCEPT, *pResMgr) ),
434 aStrNotAccept( ResId(LICENSE_NOTACCEPT, *pResMgr) ),
435 bEndReached(sal_False)
436 {
437 FreeResource();
438
439 aLicenseML.SetEndReachedHdl( LINK(this, LicenseDialog, EndReachedHdl) );
440 aLicenseML.SetScrolledHdl( LINK(this, LicenseDialog, ScrolledHdl) );
441
442 aPBPageDown.SetClickHdl( LINK(this, LicenseDialog, PageDownHdl) );
443 aPBDecline.SetClickHdl( LINK(this, LicenseDialog, DeclineBtnHdl) );
444 aPBAccept.SetClickHdl( LINK(this, LicenseDialog, AcceptBtnHdl) );
445
446 // We want a automatic repeating page down button
447 WinBits aStyle = aPBPageDown.GetStyle();
448 aStyle |= WB_REPEAT;
449 aPBPageDown.SetStyle( aStyle );
450
451 String aText = aInfo2FT.GetText();
452 aText.SearchAndReplaceAll( UniString::CreateFromAscii("%PAGEDOWN"), aPBPageDown.GetText() );
453 aInfo2FT.SetText( aText );
454
455 aPBDecline.SetText( aStrNotAccept );
456 aPBAccept.SetText( aStrAccept );
457
458 aPBAccept.Disable();
459
460 // load license text
461 File aLicenseFile(aLicensePath);
462 if ( aLicenseFile.open(OpenFlag_Read) == FileBase::E_None)
463 {
464 DirectoryItem d;
465 DirectoryItem::get(aLicensePath, d);
466 FileStatus fs(FileStatusMask_FileSize);
467 d.getFileStatus(fs);
468 sal_uInt64 nBytesRead = 0;
469 sal_uInt64 nPosition = 0;
470 sal_uInt32 nBytes = (sal_uInt32)fs.getFileSize();
471 sal_Char *pBuffer = new sal_Char[nBytes];
472 // FileBase RC r = FileBase::E_None;
473 while (aLicenseFile.read(pBuffer+nPosition, nBytes-nPosition, nBytesRead) == FileBase::E_None
474 && nPosition + nBytesRead < nBytes)
475 {
476 nPosition += nBytesRead;
477 }
478 ::rtl::OUString aLicenseString(pBuffer, nBytes, RTL_TEXTENCODING_UTF8,
479 OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_GLOBAL_SIGNATURE);
480 delete[] pBuffer;
481 aLicenseML.SetText(aLicenseString);
482 }
483
484 }
485
~LicenseDialog()486 LicenseDialog::~LicenseDialog()
487 {
488 }
489
IMPL_LINK(LicenseDialog,PageDownHdl,PushButton *,EMPTYARG)490 IMPL_LINK( LicenseDialog, PageDownHdl, PushButton *, EMPTYARG )
491 {
492 aLicenseML.ScrollDown( SCROLL_PAGEDOWN );
493 return 0;
494 }
495
IMPL_LINK(LicenseDialog,EndReachedHdl,LicenseView *,EMPTYARG)496 IMPL_LINK( LicenseDialog, EndReachedHdl, LicenseView *, EMPTYARG )
497 {
498 bEndReached = sal_True;
499
500 EnableControls();
501
502 return 0;
503 }
504
IMPL_LINK(LicenseDialog,ScrolledHdl,LicenseView *,EMPTYARG)505 IMPL_LINK( LicenseDialog, ScrolledHdl, LicenseView *, EMPTYARG )
506 {
507 EnableControls();
508
509 return 0;
510 }
511
IMPL_LINK(LicenseDialog,DeclineBtnHdl,PushButton *,EMPTYARG)512 IMPL_LINK( LicenseDialog, DeclineBtnHdl, PushButton *, EMPTYARG )
513 {
514 EndDialog(0);
515 return 0;
516 }
IMPL_LINK(LicenseDialog,AcceptBtnHdl,PushButton *,EMPTYARG)517 IMPL_LINK( LicenseDialog, AcceptBtnHdl, PushButton *, EMPTYARG )
518 {
519 EndDialog(1);
520 return 0;
521 }
522
523
EnableControls()524 void LicenseDialog::EnableControls()
525 {
526 if( !bEndReached &&
527 ( aLicenseML.IsEndReached() || !aLicenseML.GetText().Len() ) )
528 bEndReached = sal_True;
529
530 if ( bEndReached )
531 {
532 Point aPos( aInfo1FT.GetPosPixel().X(),
533 aInfo3_1FT.GetPosPixel().Y() );
534 aArrow.SetPosPixel( aPos );
535 aPBAccept.Enable();
536 }
537 else
538 {
539 Point aPos( aInfo1FT.GetPosPixel().X(),
540 aInfo2_1FT.GetPosPixel().Y() );
541 aArrow.SetPosPixel( aPos );
542 aPBAccept.Disable();
543 }
544
545 if ( aLicenseML.IsEndReached() )
546 aPBPageDown.Disable();
547 else
548 aPBPageDown.Enable();
549
550 }
551
552
LicenseView(Window * pParent,const ResId & rResId)553 LicenseView::LicenseView( Window* pParent, const ResId& rResId )
554 : MultiLineEdit( pParent, rResId )
555 {
556 SetLeftMargin( 5 );
557
558 mbEndReached = IsEndReached();
559
560 StartListening( *GetTextEngine() );
561 }
562
~LicenseView()563 LicenseView::~LicenseView()
564 {
565 maEndReachedHdl = Link();
566 maScrolledHdl = Link();
567
568 EndListeningAll();
569 }
570
ScrollDown(ScrollType eScroll)571 void LicenseView::ScrollDown( ScrollType eScroll )
572 {
573 ScrollBar* pScroll = GetVScrollBar();
574
575 if ( pScroll )
576 pScroll->DoScrollAction( eScroll );
577 }
578
IsEndReached() const579 sal_Bool LicenseView::IsEndReached() const
580 {
581 sal_Bool bEndReached;
582
583 ExtTextView* pView = GetTextView();
584 ExtTextEngine* pEdit = GetTextEngine();
585 sal_uLong nHeight = pEdit->GetTextHeight();
586 Size aOutSize = pView->GetWindow()->GetOutputSizePixel();
587 Point aBottom( 0, aOutSize.Height() );
588
589 if ( (sal_uLong) pView->GetDocPos( aBottom ).Y() >= nHeight - 1 )
590 bEndReached = sal_True;
591 else
592 bEndReached = sal_False;
593
594 return bEndReached;
595 }
596
Notify(SfxBroadcaster &,const SfxHint & rHint)597 void LicenseView::Notify( SfxBroadcaster&, const SfxHint& rHint )
598 {
599 if ( rHint.IsA( TYPE(TextHint) ) )
600 {
601 sal_Bool bLastVal = EndReached();
602 sal_uLong nId = ((const TextHint&)rHint).GetId();
603
604 if ( nId == TEXT_HINT_PARAINSERTED )
605 {
606 if ( bLastVal )
607 mbEndReached = IsEndReached();
608 }
609 else if ( nId == TEXT_HINT_VIEWSCROLLED )
610 {
611 if ( ! mbEndReached )
612 mbEndReached = IsEndReached();
613 maScrolledHdl.Call( this );
614 }
615
616 if ( EndReached() && !bLastVal )
617 {
618 maEndReachedHdl.Call( this );
619 }
620 }
621 }
622
623 } // namespace framework
624