ITEM: Refactor ItemType
[LibreOffice.git] / sw / source / core / access / accdoc.cxx
blob30c2a500cad903f6898e3385213b8a9b52c4eed7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/window.hxx>
21 #include <rootfrm.hxx>
23 #include <com/sun/star/accessibility/AccessibleRole.hpp>
24 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
26 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
27 #include <cppuhelper/typeprovider.hxx>
28 #include <vcl/svapp.hxx>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <viewsh.hxx>
31 #include <doc.hxx>
32 #include <accmap.hxx>
33 #include "accdoc.hxx"
34 #include <strings.hrc>
35 #include <pagefrm.hxx>
37 #include <swatrset.hxx>
38 #include <docsh.hxx>
39 #include <crsrsh.hxx>
40 #include <fesh.hxx>
41 #include <fmtclds.hxx>
42 #include <flyfrm.hxx>
43 #include <txtfrm.hxx>
44 #include <sectfrm.hxx>
45 #include <section.hxx>
46 #include <swmodule.hxx>
47 #include <svtools/colorcfg.hxx>
49 #include <fmtanchr.hxx>
50 #include <viewimp.hxx>
51 #include <dview.hxx>
52 #include <dcontact.hxx>
53 #include <svx/svdmark.hxx>
54 constexpr OUString sServiceName = u"com.sun.star.text.AccessibleTextDocumentView"_ustr;
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::accessibility;
59 using lang::IndexOutOfBoundsException;
61 // SwAccessibleDocumentBase: base class for SwAccessibleDocument and
62 // SwAccessiblePreview
64 SwAccessibleDocumentBase::SwAccessibleDocumentBase(
65 std::shared_ptr<SwAccessibleMap> const& pMap)
66 : SwAccessibleContext(pMap, AccessibleRole::DOCUMENT_TEXT,
67 pMap->GetShell()->GetLayout())
68 , mxParent(pMap->GetShell()->GetWin()->GetAccessibleParentWindow()->GetAccessible())
69 , mpChildWin(nullptr)
73 SwAccessibleDocumentBase::~SwAccessibleDocumentBase()
77 void SwAccessibleDocumentBase::SetVisArea()
79 SolarMutexGuard aGuard;
81 SwRect aOldVisArea( GetVisArea() );
82 const SwRect& rNewVisArea = GetMap()->GetVisArea();
83 if( aOldVisArea != rNewVisArea )
85 SwAccessibleFrame::SetVisArea( GetMap()->GetVisArea() );
86 // #i58139# - showing state of document view needs also be updated.
87 // Thus, call method <Scrolled(..)> instead of <ChildrenScrolled(..)>
88 // ChildrenScrolled( GetFrame(), aOldVisArea );
89 Scrolled( aOldVisArea );
93 void SwAccessibleDocumentBase::AddChild( vcl::Window *pWin, bool bFireEvent )
95 SolarMutexGuard aGuard;
97 OSL_ENSURE( !mpChildWin, "only one child window is supported" );
98 if( !mpChildWin )
100 mpChildWin = pWin;
102 if( bFireEvent )
104 AccessibleEventObject aEvent;
105 aEvent.EventId = AccessibleEventId::CHILD;
106 aEvent.NewValue <<= mpChildWin->GetAccessible();
107 aEvent.IndexHint = -1;
108 FireAccessibleEvent( aEvent );
113 void SwAccessibleDocumentBase::RemoveChild( vcl::Window *pWin )
115 SolarMutexGuard aGuard;
117 OSL_ENSURE( !mpChildWin || pWin == mpChildWin, "invalid child window to remove" );
118 if( mpChildWin && pWin == mpChildWin )
120 AccessibleEventObject aEvent;
121 aEvent.EventId = AccessibleEventId::CHILD;
122 aEvent.OldValue <<= mpChildWin->GetAccessible();
123 aEvent.IndexHint = -1;
124 FireAccessibleEvent( aEvent );
126 mpChildWin = nullptr;
130 sal_Int64 SAL_CALL SwAccessibleDocumentBase::getAccessibleChildCount()
132 SolarMutexGuard aGuard;
134 // ThrowIfDisposed is called by parent
136 sal_Int64 nChildren = SwAccessibleContext::getAccessibleChildCount();
137 if( !IsDisposing() && mpChildWin )
138 nChildren++;
140 return nChildren;
143 uno::Reference< XAccessible> SAL_CALL
144 SwAccessibleDocumentBase::getAccessibleChild( sal_Int64 nIndex )
146 SolarMutexGuard aGuard;
148 if( mpChildWin )
150 ThrowIfDisposed();
152 if ( nIndex == GetChildCount( *(GetMap()) ) )
154 return mpChildWin->GetAccessible();
158 return SwAccessibleContext::getAccessibleChild( nIndex );
161 uno::Reference< XAccessible> SAL_CALL SwAccessibleDocumentBase::getAccessibleParent()
163 return mxParent;
166 sal_Int64 SAL_CALL SwAccessibleDocumentBase::getAccessibleIndexInParent()
168 SolarMutexGuard aGuard;
170 uno::Reference < XAccessibleContext > xAcc( mxParent->getAccessibleContext() );
171 uno::Reference < XAccessible > xThis( this );
172 sal_Int64 nCount = xAcc->getAccessibleChildCount();
174 for( sal_Int64 i=0; i < nCount; i++ )
178 if( xAcc->getAccessibleChild( i ) == xThis )
179 return i;
181 catch(const css::lang::IndexOutOfBoundsException &)
183 return -1;
186 return -1;
189 OUString SAL_CALL SwAccessibleDocumentBase::getAccessibleDescription()
191 return GetResource( STR_ACCESS_DOC_DESC );
194 OUString SAL_CALL SwAccessibleDocumentBase::getAccessibleName()
196 SolarMutexGuard g;
198 OUString sAccName = GetResource( STR_ACCESS_DOC_WORDPROCESSING );
199 SwDoc *pDoc = GetMap() ? GetShell()->GetDoc() : nullptr;
200 if ( pDoc )
202 OUString sFileName = pDoc->getDocAccTitle();
203 if ( sFileName.isEmpty() )
205 SwDocShell* pDocSh = pDoc->GetDocShell();
206 if ( pDocSh )
208 sFileName = pDocSh->GetTitle( SFX_TITLE_APINAME );
212 if ( !sFileName.isEmpty() )
214 sAccName = sFileName + " - " + sAccName;
218 return sAccName;
221 awt::Rectangle SAL_CALL SwAccessibleDocumentBase::getBounds()
225 SolarMutexGuard aGuard;
227 vcl::Window *pWin = GetWindow();
228 if (!pWin)
230 throw uno::RuntimeException(u"no Window"_ustr, getXWeak());
233 tools::Rectangle aPixBounds( pWin->GetWindowExtentsRelative( *pWin->GetAccessibleParentWindow() ) );
234 awt::Rectangle aBox( aPixBounds.Left(), aPixBounds.Top(),
235 aPixBounds.GetWidth(), aPixBounds.GetHeight() );
237 return aBox;
239 catch(const css::lang::IndexOutOfBoundsException &)
241 return awt::Rectangle();
245 awt::Point SAL_CALL SwAccessibleDocumentBase::getLocation()
247 SolarMutexGuard aGuard;
249 vcl::Window *pWin = GetWindow();
250 if (!pWin)
252 throw uno::RuntimeException(u"no Window"_ustr, getXWeak());
255 Point aPixPos( pWin->GetWindowExtentsRelative( *pWin->GetAccessibleParentWindow() ).TopLeft() );
256 awt::Point aLoc( aPixPos.getX(), aPixPos.getY() );
258 return aLoc;
261 css::awt::Point SAL_CALL SwAccessibleDocumentBase::getLocationOnScreen()
263 SolarMutexGuard aGuard;
265 vcl::Window *pWin = GetWindow();
266 if (!pWin)
268 throw uno::RuntimeException(u"no Window"_ustr, getXWeak());
271 Point aPixPos( pWin->GetWindowExtentsAbsolute().TopLeft() );
272 awt::Point aLoc( aPixPos.getX(), aPixPos.getY() );
274 return aLoc;
277 css::awt::Size SAL_CALL SwAccessibleDocumentBase::getSize()
279 SolarMutexGuard aGuard;
281 vcl::Window *pWin = GetWindow();
282 if (!pWin)
284 throw uno::RuntimeException(u"no Window"_ustr, getXWeak());
287 Size aPixSize( pWin->GetWindowExtentsAbsolute().GetSize() );
288 awt::Size aSize( aPixSize.Width(), aPixSize.Height() );
290 return aSize;
293 sal_Bool SAL_CALL SwAccessibleDocumentBase::containsPoint(
294 const awt::Point& aPoint )
296 SolarMutexGuard aGuard;
298 vcl::Window *pWin = GetWindow();
299 if (!pWin)
301 throw uno::RuntimeException(u"no Window"_ustr, getXWeak());
304 tools::Rectangle aPixBounds( pWin->GetWindowExtentsAbsolute() );
305 aPixBounds.Move(-aPixBounds.Left(), -aPixBounds.Top());
307 Point aPixPoint( aPoint.X, aPoint.Y );
308 return aPixBounds.Contains( aPixPoint );
311 uno::Reference< XAccessible > SAL_CALL SwAccessibleDocumentBase::getAccessibleAtPoint(
312 const awt::Point& aPoint )
314 SolarMutexGuard aGuard;
316 if( mpChildWin )
318 ThrowIfDisposed();
320 vcl::Window *pWin = GetWindow();
321 if (!pWin)
323 throw uno::RuntimeException(u"no Window"_ustr, getXWeak());
325 if (pWin->isDisposed()) // tdf#147967
326 return nullptr;
328 Point aPixPoint( aPoint.X, aPoint.Y ); // px rel to window
329 if( mpChildWin->GetWindowExtentsRelative( *pWin ).Contains( aPixPoint ) )
330 return mpChildWin->GetAccessible();
333 return SwAccessibleContext::getAccessibleAtPoint( aPoint );
336 // SwAccessibleDocument
338 void SwAccessibleDocument::GetStates( sal_Int64& rStateSet )
340 SwAccessibleContext::GetStates( rStateSet );
342 // MULTISELECTABLE
343 rStateSet |= AccessibleStateType::MULTI_SELECTABLE;
344 rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
347 SwAccessibleDocument::SwAccessibleDocument(
348 std::shared_ptr<SwAccessibleMap> const& pInitMap)
349 : SwAccessibleDocument_BASE(pInitMap)
350 , maSelectionHelper(*this)
352 SetName(pInitMap->GetDocName());
353 vcl::Window *pWin = pInitMap->GetShell()->GetWin();
354 if( pWin )
356 pWin->AddChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
357 sal_uInt16 nCount = pWin->GetChildCount();
358 for( sal_uInt16 i=0; i < nCount; i++ )
360 vcl::Window* pChildWin = pWin->GetChild( i );
361 if( pChildWin &&
362 AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
363 AddChild( pChildWin, false );
368 SwAccessibleDocument::~SwAccessibleDocument()
370 vcl::Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : nullptr;
371 if( pWin )
372 pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
375 void SwAccessibleDocument::Dispose(bool bRecursive, bool bCanSkipInvisible)
377 OSL_ENSURE( GetFrame() && GetMap(), "already disposed" );
379 vcl::Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : nullptr;
380 if( pWin )
381 pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener ));
382 SwAccessibleContext::Dispose(bRecursive, bCanSkipInvisible);
385 IMPL_LINK( SwAccessibleDocument, WindowChildEventListener, VclWindowEvent&, rEvent, void )
387 OSL_ENSURE( rEvent.GetWindow(), "Window???" );
388 switch ( rEvent.GetId() )
390 case VclEventId::WindowShow: // send create on show for direct accessible children
392 vcl::Window* pChildWin = static_cast< vcl::Window* >( rEvent.GetData() );
393 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
395 AddChild( pChildWin );
398 break;
399 case VclEventId::WindowHide: // send destroy on hide for direct accessible children
401 vcl::Window* pChildWin = static_cast< vcl::Window* >( rEvent.GetData() );
402 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
404 RemoveChild( pChildWin );
407 break;
408 case VclEventId::ObjectDying: // send destroy on hide for direct accessible children
410 vcl::Window* pChildWin = rEvent.GetWindow();
411 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
413 RemoveChild( pChildWin );
416 break;
417 default: break;
421 OUString SAL_CALL SwAccessibleDocument::getImplementationName()
423 return u"com.sun.star.comp.Writer.SwAccessibleDocumentView"_ustr;
426 sal_Bool SAL_CALL SwAccessibleDocument::supportsService(const OUString& sTestServiceName)
428 return cppu::supportsService(this, sTestServiceName);
431 uno::Sequence< OUString > SAL_CALL SwAccessibleDocument::getSupportedServiceNames()
433 return { sServiceName, sAccessibleServiceName };
436 // XAccessibleSelection
438 void SwAccessibleDocument::selectAccessibleChild(
439 sal_Int64 nChildIndex )
441 maSelectionHelper.selectAccessibleChild(nChildIndex);
444 sal_Bool SwAccessibleDocument::isAccessibleChildSelected(
445 sal_Int64 nChildIndex )
447 return maSelectionHelper.isAccessibleChildSelected(nChildIndex);
450 void SwAccessibleDocument::clearAccessibleSelection( )
454 void SwAccessibleDocument::selectAllAccessibleChildren( )
456 maSelectionHelper.selectAllAccessibleChildren();
459 sal_Int64 SwAccessibleDocument::getSelectedAccessibleChildCount( )
461 return maSelectionHelper.getSelectedAccessibleChildCount();
464 uno::Reference<XAccessible> SwAccessibleDocument::getSelectedAccessibleChild(
465 sal_Int64 nSelectedChildIndex )
467 return maSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
470 // index has to be treated as global child index.
471 void SwAccessibleDocument::deselectAccessibleChild(
472 sal_Int64 nChildIndex )
474 maSelectionHelper.deselectAccessibleChild( nChildIndex );
477 uno::Any SAL_CALL SwAccessibleDocument::getExtendedAttributes()
479 SolarMutexGuard g;
481 uno::Any anyAttribute;
482 SwDoc *pDoc = GetMap() ? GetShell()->GetDoc() : nullptr;
484 if (!pDoc)
485 return anyAttribute;
486 SwCursorShell* pCursorShell = GetCursorShell();
487 if( !pCursorShell )
488 return anyAttribute;
490 SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCursorShell);
491 if( pFEShell )
493 OUString sDisplay;
494 sal_uInt16 nPage, nLogPage;
495 pFEShell->GetPageNumber(-1,true,nPage,nLogPage,sDisplay);
497 OUString sValue = "page-name:" + sDisplay +
498 ";page-number:" +
499 OUString::number( nPage ) +
500 ";total-pages:" +
501 OUString::number( pCursorShell->GetPageCnt() ) + ";";
503 // cursor position relative to the page
504 Point aCursorPagePos = pFEShell->GetCursorPagePos();
505 sValue += "cursor-position-in-page-horizontal:" + OUString::number(aCursorPagePos.getX())
506 + ";cursor-position-in-page-vertical:" + OUString::number(aCursorPagePos.getY()) + ";";
508 SwContentFrame* pCurrFrame = pCursorShell->GetCurrFrame();
509 SwPageFrame* pCurrPage=static_cast<SwFrame*>(pCurrFrame)->FindPageFrame();
510 sal_Int32 nLineNum = 0;
511 SwTextFrame* pTextFrame = nullptr;
512 SwTextFrame* pCurrTextFrame = nullptr;
513 pTextFrame = static_cast< SwTextFrame* >(pCurrPage->ContainsContent());
514 if (pCurrFrame->IsInFly())//such as, graphic,chart
516 SwFlyFrame *pFlyFrame = pCurrFrame->FindFlyFrame();
517 const SwFormatAnchor& rAnchor = pFlyFrame->GetFormat()->GetAnchor();
518 RndStdIds eAnchorId = rAnchor.GetAnchorId();
519 if(eAnchorId == RndStdIds::FLY_AS_CHAR)
521 const SwFrame *pSwFrame = pFlyFrame->GetAnchorFrame();
522 if(pSwFrame->IsTextFrame())
523 pCurrTextFrame = const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pSwFrame));
526 else
528 assert(dynamic_cast<SwTextFrame*>(pCurrFrame));
529 pCurrTextFrame = static_cast<SwTextFrame* >(pCurrFrame);
531 //check whether the text frame where the Graph/OLE/Frame anchored is in the Header/Footer
532 SwFrame* pFrame = pCurrTextFrame;
533 while ( pFrame && !pFrame->IsHeaderFrame() && !pFrame->IsFooterFrame() )
534 pFrame = pFrame->GetUpper();
535 if ( pFrame )
536 pCurrTextFrame = nullptr;
537 //check shape
538 if(pCursorShell->Imp()->GetDrawView())
540 const SdrMarkList &rMrkList = pCursorShell->Imp()->GetDrawView()->GetMarkedObjectList();
541 for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
543 SdrObject *pObj = rMrkList.GetMark(i)->GetMarkedSdrObj();
544 SwFrameFormat* pFormat = static_cast<SwDrawContact*>(pObj->GetUserCall())->GetFormat();
545 const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
546 if( RndStdIds::FLY_AS_CHAR != rAnchor.GetAnchorId() )
547 pCurrTextFrame = nullptr;
550 //calculate line number
551 if (pCurrTextFrame && pTextFrame)
553 if (!(pCurrTextFrame->IsInTab() || pCurrTextFrame->IsInFootnote()))
555 while( pTextFrame && pTextFrame != pCurrTextFrame )
557 //check header/footer
558 pFrame = pTextFrame;
559 while ( pFrame && !pFrame->IsHeaderFrame() && !pFrame->IsFooterFrame() )
560 pFrame = pFrame->GetUpper();
561 if ( pFrame )
563 pTextFrame = static_cast< SwTextFrame*>(pTextFrame->GetNextContentFrame());
564 continue;
566 if (!(pTextFrame->IsInTab() || pTextFrame->IsInFootnote() || pTextFrame->IsInFly()))
567 nLineNum += pTextFrame->GetThisLines();
568 pTextFrame = static_cast< SwTextFrame* >(pTextFrame ->GetNextContentFrame());
570 SwPaM* pCaret = pCursorShell->GetCursor();
571 if (!pCurrTextFrame->IsEmpty() && pCaret)
573 assert(pCurrTextFrame->IsTextFrame());
574 const SwPosition* pPoint = nullptr;
575 if (pCurrTextFrame->IsInFly())
577 SwFlyFrame *pFlyFrame = pCurrTextFrame->FindFlyFrame();
578 const SwFormatAnchor& rAnchor = pFlyFrame->GetFormat()->GetAnchor();
579 pPoint = rAnchor.GetContentAnchor();
580 SwContentNode *const pNode(pPoint->GetNode().GetContentNode());
581 pCurrTextFrame = pNode
582 ? static_cast<SwTextFrame*>(pNode->getLayoutFrame(
583 pCurrTextFrame->getRootFrame(), pPoint))
584 : nullptr;
586 else
587 pPoint = pCaret->GetPoint();
588 if (pCurrTextFrame)
590 TextFrameIndex const nActPos(pCurrTextFrame->MapModelToViewPos(*pPoint));
591 nLineNum += pCurrTextFrame->GetLineCount( nActPos );
594 else
595 ++nLineNum;
599 sValue += "line-number:" + OUString::number( nLineNum ) + ";";
601 SwFrame* pCurrCol=static_cast<SwFrame*>(pCurrFrame)->FindColFrame();
603 sValue += "column-number:";
605 int nCurrCol = 1;
606 if(pCurrCol!=nullptr)
608 //SwLayoutFrame* pParent = pCurrCol->GetUpper();
609 SwFrame* pCurrPageCol=static_cast<SwFrame*>(pCurrFrame)->FindColFrame();
610 while(pCurrPageCol && pCurrPageCol->GetUpper() && pCurrPageCol->GetUpper()->IsPageFrame())
612 pCurrPageCol = pCurrPageCol->GetUpper();
615 SwLayoutFrame* pParent = pCurrPageCol->GetUpper();
617 if(pParent!=nullptr)
619 SwFrame* pCol = pParent->Lower();
620 while(pCol&&(pCol!=pCurrPageCol))
622 pCol = pCol->GetNext();
623 ++nCurrCol;
627 sValue += OUString::number( nCurrCol ) + ";";
629 const SwFormatCol &rFormatCol=pCurrPage->GetAttrSet()->GetCol();
630 sal_uInt16 nColCount=rFormatCol.GetNumCols();
631 nColCount = nColCount>0?nColCount:1;
632 sValue += "total-columns:" + OUString::number( nColCount ) + ";";
634 SwSectionFrame* pCurrSctFrame=static_cast<SwFrame*>(pCurrFrame)->FindSctFrame();
635 if(pCurrSctFrame!=nullptr && pCurrSctFrame->GetSection()!=nullptr )
637 OUString sectionName = pCurrSctFrame->GetSection()->GetSectionName();
639 sectionName = sectionName.replaceFirst( "\\" , "\\\\" );
640 sectionName = sectionName.replaceFirst( "=" , "\\=" );
641 sectionName = sectionName.replaceFirst( ";" , "\\;" );
642 sectionName = sectionName.replaceFirst( "," , "\\," );
643 sectionName = sectionName.replaceFirst( ":" , "\\:" );
645 sValue += "section-name:" + sectionName + ";";
647 //section-columns-number
649 nCurrCol = 1;
651 if(pCurrCol!=nullptr)
653 SwLayoutFrame* pParent = pCurrCol->GetUpper();
654 if(pParent!=nullptr)
656 SwFrame* pCol = pParent->Lower();
657 while(pCol&&(pCol!=pCurrCol))
659 pCol = pCol->GetNext();
660 nCurrCol +=1;
664 sValue += "section-columns-number:" +
665 OUString::number( nCurrCol ) + ";";
667 //section-total-columns
668 const SwFormatCol &rFormatSctCol=pCurrSctFrame->GetAttrSet()->GetCol();
669 sal_uInt16 nSctColCount=rFormatSctCol.GetNumCols();
670 nSctColCount = nSctColCount>0?nSctColCount:1;
671 sValue += "section-total-columns:" +
672 OUString::number( nSctColCount ) + ";";
675 anyAttribute <<= sValue;
677 return anyAttribute;
680 sal_Int32 SAL_CALL SwAccessibleDocument::getBackground()
682 SolarMutexGuard aGuard;
683 return sal_Int32(SwModule::get()->GetColorConfig().GetColorValue(::svtools::DOCCOLOR).nColor);
686 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */