1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 // ============================================================================
32 #include "AccessibleCsvControl.hxx"
33 #include <com/sun/star/accessibility/AccessibleRole.hpp>
34 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLERELATIONTYPE_HPP_
35 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
36 #endif
37 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
38 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
39 #endif
40 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
41 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
42 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
43 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
44 #include <tools/debug.hxx>
45 #include <rtl/uuid.h>
46 #include <toolkit/helper/convert.hxx>
47 #include <unotools/accessiblerelationsethelper.hxx>
48 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
49 #include <unotools/accessiblestatesethelper.hxx>
50 #endif
51 #include <comphelper/sequence.hxx>
52 #include "scitems.hxx"
53 #include <editeng/fontitem.hxx>
54 #include <editeng/fhgtitem.hxx>
55 #include <editeng/langitem.hxx>
56 #include "csvcontrol.hxx"
57 #include "csvruler.hxx"
58 #include "csvgrid.hxx"
59 #include "AccessibleText.hxx"
60 #include "editsrc.hxx"
61 #include "unoguard.hxx"
62 #include "scresid.hxx"
63 #include "sc.hrc"
64 #include "scmod.hxx"
65 #include <svtools/colorcfg.hxx>
66 // ause
67 #include "editutil.hxx"
68 
69 using ::rtl::OUString;
70 using ::rtl::OUStringBuffer;
71 using ::utl::AccessibleRelationSetHelper;
72 using ::utl::AccessibleStateSetHelper;
73 using ::accessibility::AccessibleStaticTextBase;
74 using ::com::sun::star::uno::Any;
75 using ::com::sun::star::uno::Reference;
76 using ::com::sun::star::uno::Sequence;
77 using ::com::sun::star::uno::RuntimeException;
78 using ::com::sun::star::uno::XInterface;
79 using ::com::sun::star::lang::DisposedException;
80 using ::com::sun::star::lang::IndexOutOfBoundsException;
81 using ::com::sun::star::lang::IllegalArgumentException;
82 using ::com::sun::star::beans::PropertyValue;
83 using namespace	::com::sun::star::accessibility;
84 
85 
86 // ----------------------------------------------------------------------------
87 
88 const sal_uInt16 nRulerRole         = AccessibleRole::TEXT;
89 const sal_uInt16 nGridRole          = AccessibleRole::TABLE;
90 const sal_uInt16 nCellRole          = AccessibleRole::TEXT;
91 
92 #define CREATE_OUSTRING( name )     OUString( RTL_CONSTASCII_USTRINGPARAM( name ) )
93 
94 #define RULER_IMPL_NAME             "ScAccessibleCsvRuler"
95 #define GRID_IMPL_NAME              "ScAccessibleCsvGrid"
96 #define CELL_IMPL_NAME              "ScAccessibleCsvCell"
97 
98 const sal_Unicode cRulerDot         = '.';
99 const sal_Unicode cRulerLine        = '|';
100 
101 const sal_Int32 CSV_LINE_HEADER     = CSV_POS_INVALID;
102 const sal_uInt32 CSV_COLUMN_HEADER  = CSV_COLUMN_INVALID;
103 
104 
105 // CSV base control ===========================================================
106 
107 DBG_NAME( ScAccessibleCsvControl )
108 
109 ScAccessibleCsvControl::ScAccessibleCsvControl(
110         const Reference< XAccessible >& rxParent,
111         ScCsvControl& rControl,
112         sal_uInt16 nRole ) :
113     ScAccessibleContextBase( rxParent, nRole ),
114     mpControl( &rControl )
115 {
116     DBG_CTOR( ScAccessibleCsvControl, NULL );
117 }
118 
119 ScAccessibleCsvControl::~ScAccessibleCsvControl()
120 {
121     DBG_DTOR( ScAccessibleCsvControl, NULL );
122     implDispose();
123 }
124 
125 void SAL_CALL ScAccessibleCsvControl::disposing()
126 {
127     ScUnoGuard aGuard;
128     mpControl = NULL;
129     ScAccessibleContextBase::disposing();
130 }
131 
132 
133 // XAccessibleComponent -------------------------------------------------------
134 
135 Reference< XAccessible > SAL_CALL ScAccessibleCsvControl::getAccessibleAtPoint( const AwtPoint& /* rPoint */ )
136         throw( RuntimeException )
137 {
138     ensureAlive();
139     return NULL;
140 }
141 
142 sal_Bool SAL_CALL ScAccessibleCsvControl::isVisible() throw( RuntimeException )
143 {
144     ScUnoGuard aGuard;
145     ensureAlive();
146     return implGetControl().IsVisible();
147 }
148 
149 void SAL_CALL ScAccessibleCsvControl::grabFocus() throw( RuntimeException )
150 {
151     ScUnoGuard aGuard;
152     ensureAlive();
153     implGetControl().GrabFocus();
154 }
155 
156 
157 // events ---------------------------------------------------------------------
158 
159 void ScAccessibleCsvControl::SendFocusEvent( bool bFocused )
160 {
161     if( bFocused )
162         CommitFocusGained();
163     else
164         CommitFocusLost();
165 }
166 
167 void ScAccessibleCsvControl::SendCaretEvent()
168 {
169     DBG_ERRORFILE( "ScAccessibleCsvControl::SendCaretEvent - Illegal call" );
170 }
171 
172 void ScAccessibleCsvControl::SendVisibleEvent()
173 {
174     AccessibleEventObject aEvent;
175     aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
176     aEvent.Source = Reference< XAccessible >( this );
177     CommitChange( aEvent );
178 }
179 
180 void ScAccessibleCsvControl::SendSelectionEvent()
181 {
182     AccessibleEventObject aEvent;
183     aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
184     aEvent.Source = Reference< XAccessible >( this );
185     CommitChange( aEvent );
186 }
187 
188 void ScAccessibleCsvControl::SendTableUpdateEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */, bool /* bAllRows */ )
189 {
190     DBG_ERRORFILE( "ScAccessibleCsvControl::SendTableUpdateEvent - Illegal call" );
191 }
192 
193 void ScAccessibleCsvControl::SendInsertColumnEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */ )
194 {
195     DBG_ERRORFILE( "ScAccessibleCsvControl::SendInsertColumnEvent - Illegal call" );
196 }
197 
198 void ScAccessibleCsvControl::SendRemoveColumnEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */ )
199 {
200     DBG_ERRORFILE( "ScAccessibleCsvControl::SendRemoveColumnEvent - Illegal call" );
201 }
202 
203 
204 // helpers --------------------------------------------------------------------
205 
206 Rectangle ScAccessibleCsvControl::GetBoundingBoxOnScreen() const throw( RuntimeException )
207 {
208     ScUnoGuard aGuard;
209     ensureAlive();
210     return implGetControl().GetWindowExtentsRelative( NULL );
211 }
212 
213 Rectangle ScAccessibleCsvControl::GetBoundingBox() const throw( RuntimeException )
214 {
215     ScUnoGuard aGuard;
216     ensureAlive();
217     return implGetControl().GetWindowExtentsRelative( implGetControl().GetAccessibleParentWindow() );
218 }
219 
220 void ScAccessibleCsvControl::getUuid( Sequence< sal_Int8 >& rSeq )
221 {
222     ScUnoGuard aGuard;
223     ensureAlive();
224     if( !rSeq.hasElements() )
225     {
226         rSeq.realloc( 16 );
227         rtl_createUuid( reinterpret_cast< sal_uInt8* >( rSeq.getArray() ), NULL, sal_True );
228     }
229 }
230 
231 void ScAccessibleCsvControl::ensureAlive() const throw( DisposedException )
232 {
233     if( !implIsAlive() )
234         throw DisposedException();
235 }
236 
237 ScCsvControl& ScAccessibleCsvControl::implGetControl() const
238 {
239     DBG_ASSERT( mpControl, "ScAccessibleCsvControl::implGetControl - missing control" );
240     return *mpControl;
241 }
242 
243 Reference< XAccessible > ScAccessibleCsvControl::implGetChildByRole(
244         const Reference< XAccessible >& rxParentObj, sal_uInt16 nRole ) throw( RuntimeException )
245 {
246     Reference< XAccessible > xAccObj;
247     if( rxParentObj.is() )
248     {
249         Reference< XAccessibleContext > xParentCtxt = rxParentObj->getAccessibleContext();
250         if( xParentCtxt.is() )
251         {
252             sal_Int32 nCount = xParentCtxt->getAccessibleChildCount();
253             sal_Int32 nIndex = 0;
254             while( !xAccObj.is() && (nIndex < nCount) )
255             {
256                 Reference< XAccessible > xCurrObj = xParentCtxt->getAccessibleChild( nIndex );
257                 if( xCurrObj.is() )
258                 {
259                     Reference< XAccessibleContext > xCurrCtxt = xCurrObj->getAccessibleContext();
260                     if( xCurrCtxt.is() && (xCurrCtxt->getAccessibleRole() == nRole) )
261                         xAccObj = xCurrObj;
262                 }
263                 ++nIndex;
264             }
265         }
266     }
267     return xAccObj;
268 }
269 
270 AccessibleStateSetHelper* ScAccessibleCsvControl::implCreateStateSet()
271 {
272     ScUnoGuard aGuard;
273     AccessibleStateSetHelper* pStateSet = new AccessibleStateSetHelper();
274     if( implIsAlive() )
275     {
276         const ScCsvControl& rCtrl = implGetControl();
277         pStateSet->AddState( AccessibleStateType::OPAQUE );
278         if( rCtrl.IsEnabled() )
279             pStateSet->AddState( AccessibleStateType::ENABLED );
280         if( isShowing() )
281             pStateSet->AddState( AccessibleStateType::SHOWING );
282         if( isVisible() )
283             pStateSet->AddState( AccessibleStateType::VISIBLE );
284     }
285     else
286         pStateSet->AddState( AccessibleStateType::DEFUNC );
287     return pStateSet;
288 }
289 
290 void ScAccessibleCsvControl::implDispose()
291 {
292     if( implIsAlive() )
293     {
294         // prevent multiple call of dtor
295         osl_incrementInterlockedCount( &m_refCount );
296         dispose();
297     }
298 }
299 
300 Point ScAccessibleCsvControl::implGetAbsPos( const Point& rPos ) const
301 {
302     return rPos + implGetControl().GetWindowExtentsRelative( NULL ).TopLeft();
303 }
304 
305 
306 // Ruler ======================================================================
307 
308 /** Converts a ruler cursor position to API text index. */
309 sal_Int32 lcl_GetApiPos( sal_Int32 nRulerPos )
310 {
311     sal_Int32 nApiPos = nRulerPos;
312     sal_Int32 nStart = (nRulerPos - 1) / 10;
313     sal_Int32 nExp = 1;
314     while( nStart >= nExp )
315     {
316         nApiPos += nStart - nExp + 1;
317         nExp *= 10;
318     }
319     return ::std::max( nApiPos, static_cast<sal_Int32>(0) );
320 }
321 
322 /** Converts an API text index to a ruler cursor position. */
323 sal_Int32 lcl_GetRulerPos( sal_Int32 nApiPos )
324 {
325     sal_Int32 nDiv = 10;
326     sal_Int32 nExp = 10;
327     sal_Int32 nRulerPos = 0;
328     sal_Int32 nApiBase = 0;
329     sal_Int32 nApiLimit = 10;
330     while( nApiPos >= nApiLimit )
331     {
332         ++nDiv;
333         nRulerPos = nExp;
334         nExp *= 10;
335         nApiBase = nApiLimit;
336         nApiLimit = lcl_GetApiPos( nExp );
337     }
338     sal_Int32 nRelPos = nApiPos - nApiBase;
339     return nRulerPos + nRelPos / nDiv * 10 + ::std::max( nRelPos % nDiv - nDiv + 10L, 0L );
340 }
341 
342 /** Expands the sequence's size and returns the base index of the new inserted elements. */
343 inline sal_Int32 lcl_ExpandSequence( Sequence< PropertyValue >& rSeq, sal_Int32 nExp )
344 {
345     DBG_ASSERT( nExp > 0, "lcl_ExpandSequence - invalid value" );
346     rSeq.realloc( rSeq.getLength() + nExp );
347     return rSeq.getLength() - nExp;
348 }
349 
350 /** Fills the property value rVal with the specified name and value from the item. */
351 inline void lcl_FillProperty( PropertyValue& rVal, const OUString& rPropName, const SfxPoolItem& rItem, sal_uInt8 nMID )
352 {
353     rVal.Name = rPropName;
354     rItem.QueryValue( rVal.Value, nMID );
355 }
356 
357 /** Fills the sequence with all font attributes of rFont. */
358 void lcl_FillFontAttributes( Sequence< PropertyValue >& rSeq, const Font& rFont )
359 {
360     SvxFontItem aFontItem( rFont.GetFamily(), rFont.GetName(), rFont.GetStyleName(), rFont.GetPitch(), rFont.GetCharSet(), ATTR_FONT );
361     SvxFontHeightItem aHeightItem( rFont.GetSize().Height(), 100, ATTR_FONT_HEIGHT );
362     SvxLanguageItem aLangItem( rFont.GetLanguage(), ATTR_FONT_LANGUAGE );
363 
364     sal_Int32 nIndex = lcl_ExpandSequence( rSeq, 7 );
365     lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontName" ),      aFontItem,   MID_FONT_FAMILY_NAME );
366     lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontFamily" ),    aFontItem,   MID_FONT_FAMILY );
367     lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontStyleName" ), aFontItem,   MID_FONT_STYLE_NAME );
368     lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontCharSet" ),   aFontItem,   MID_FONT_PITCH );
369     lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontPitch" ),     aFontItem,   MID_FONT_CHAR_SET );
370     lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharHeight" ),        aHeightItem, MID_FONTHEIGHT );
371     lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharLocale" ),        aLangItem,   MID_LANG_LOCALE );
372 }
373 
374 
375 
376 // ----------------------------------------------------------------------------
377 
378 DBG_NAME( ScAccessibleCsvRuler )
379 
380 ScAccessibleCsvRuler::ScAccessibleCsvRuler( ScCsvRuler& rRuler ) :
381     ScAccessibleCsvControl( rRuler.GetAccessibleParentWindow()->GetAccessible(), rRuler, nRulerRole )
382 {
383     DBG_CTOR( ScAccessibleCsvRuler, NULL );
384     constructStringBuffer();
385 }
386 
387 ScAccessibleCsvRuler::~ScAccessibleCsvRuler()
388 {
389     DBG_DTOR( ScAccessibleCsvRuler, NULL );
390     implDispose();
391 }
392 
393 // XAccessibleComponent -----------------------------------------------------
394 
395 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getForeground(  )
396     throw (RuntimeException)
397 {
398     ScUnoGuard aGuard;
399     ensureAlive();
400     return implGetRuler().GetSettings().GetStyleSettings().GetLabelTextColor().GetColor();
401 }
402 
403 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getBackground(  )
404     throw (RuntimeException)
405 {
406     ScUnoGuard aGuard;
407     ensureAlive();
408     return implGetRuler().GetSettings().GetStyleSettings().GetFaceColor().GetColor();
409 }
410 
411 // XAccessibleContext ---------------------------------------------------------
412 
413 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getAccessibleChildCount() throw( RuntimeException )
414 {
415     ensureAlive();
416     return 0;
417 }
418 
419 Reference< XAccessible > SAL_CALL ScAccessibleCsvRuler::getAccessibleChild( sal_Int32 /* nIndex */ )
420         throw( IndexOutOfBoundsException, RuntimeException )
421 {
422     ensureAlive();
423     throw IndexOutOfBoundsException();
424 }
425 
426 Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvRuler::getAccessibleRelationSet()
427         throw( RuntimeException )
428 {
429     ScUnoGuard aGuard;
430     ensureAlive();
431     AccessibleRelationSetHelper* pRelationSet = new AccessibleRelationSetHelper();
432     Reference< XAccessible > xAccObj = implGetChildByRole( getAccessibleParent(), nGridRole );
433     if( xAccObj.is() )
434     {
435         Sequence< Reference< XInterface > > aSeq( 1 );
436         aSeq[ 0 ] = xAccObj;
437         pRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::CONTROLLER_FOR, aSeq ) );
438     }
439     return pRelationSet;
440 }
441 
442 Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvRuler::getAccessibleStateSet()
443         throw( RuntimeException )
444 {
445     ScUnoGuard aGuard;
446     AccessibleStateSetHelper* pStateSet = implCreateStateSet();
447     if( implIsAlive() )
448     {
449         pStateSet->AddState( AccessibleStateType::FOCUSABLE );
450         pStateSet->AddState( AccessibleStateType::SINGLE_LINE );
451         if( implGetRuler().HasFocus() )
452             pStateSet->AddState( AccessibleStateType::FOCUSED );
453     }
454     return pStateSet;
455 }
456 
457 
458 // XAccessibleText ------------------------------------------------------------
459 
460 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getCaretPosition() throw( RuntimeException )
461 {
462     ScUnoGuard aGuard;
463     ensureAlive();
464     return lcl_GetApiPos( implGetRuler().GetRulerCursorPos() );
465 }
466 
467 sal_Bool SAL_CALL ScAccessibleCsvRuler::setCaretPosition( sal_Int32 nIndex )
468         throw( IndexOutOfBoundsException, RuntimeException )
469 {
470     ScUnoGuard aGuard;
471     ensureAlive();
472     ensureValidIndex( nIndex );
473     ScCsvRuler& rRuler = implGetRuler();
474     sal_Int32 nOldCursor = rRuler.GetRulerCursorPos();
475     rRuler.Execute( CSVCMD_MOVERULERCURSOR, lcl_GetRulerPos( nIndex ) );
476     return rRuler.GetRulerCursorPos() != nOldCursor;
477 }
478 
479 sal_Unicode SAL_CALL ScAccessibleCsvRuler::getCharacter( sal_Int32 nIndex )
480         throw( IndexOutOfBoundsException, RuntimeException )
481 {
482     ScUnoGuard aGuard;
483     ensureAlive();
484     ensureValidIndex( nIndex );
485     return maBuffer.charAt( nIndex );
486 }
487 
488 Sequence< PropertyValue > SAL_CALL ScAccessibleCsvRuler::getCharacterAttributes( sal_Int32 nIndex,
489             const ::com::sun::star::uno::Sequence< ::rtl::OUString >& /* aRequestedAttributes */ )
490         throw( IndexOutOfBoundsException, RuntimeException )
491 {
492     ScUnoGuard aGuard;
493     ensureAlive();
494     ensureValidIndexWithEnd( nIndex );
495     Sequence< PropertyValue > aSeq;
496     lcl_FillFontAttributes( aSeq, implGetRuler().GetFont() );
497 //! TODO split attribute: waiting for #102221#
498 //    if( implHasSplit( nIndex ) )
499 //    {
500 //        sal_Int32 nIndex = lcl_ExpandSequence( aSeq, 1 );
501 //        aSeq[ nIndex ].Name = CREATE_OUSTRING( "..." );
502 //        aSeq[ nIndex ].Value <<= ...;
503 //    }
504     return aSeq;
505 }
506 
507 ScAccessibleCsvRuler::AwtRectangle SAL_CALL ScAccessibleCsvRuler::getCharacterBounds( sal_Int32 nIndex )
508         throw( IndexOutOfBoundsException, RuntimeException )
509 {
510     ScUnoGuard aGuard;
511     ensureAlive();
512     ensureValidIndexWithEnd( nIndex );
513     ScCsvRuler& rRuler = implGetRuler();
514     Point aPos( rRuler.GetX( lcl_GetRulerPos( nIndex ) ) - rRuler.GetCharWidth() / 2, 0 );
515     AwtRectangle aRect( aPos.X(), aPos.Y(), rRuler.GetCharWidth(), rRuler.GetSizePixel().Height() );
516     // #107054# do not return rectangle out of window
517     sal_Int32 nWidth = rRuler.GetOutputSizePixel().Width();
518     if( aRect.X >= nWidth )
519         throw IndexOutOfBoundsException();
520     if( aRect.X + aRect.Width > nWidth )
521         aRect.Width = nWidth - aRect.X;
522     return aRect;
523 }
524 
525 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getCharacterCount() throw( RuntimeException )
526 {
527     ScUnoGuard aGuard;
528     ensureAlive();
529     return implGetTextLength();
530 }
531 
532 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getIndexAtPoint( const AwtPoint& rPoint )
533         throw( RuntimeException )
534 {
535     ScUnoGuard aGuard;
536     ensureAlive();
537     ScCsvRuler& rRuler = implGetRuler();
538     // #107054# use object's coordinate system, convert to API position
539     return lcl_GetApiPos( ::std::min( ::std::max( rRuler.GetPosFromX( rPoint.X ), static_cast<sal_Int32>(0) ), rRuler.GetPosCount() ) );
540 }
541 
542 OUString SAL_CALL ScAccessibleCsvRuler::getSelectedText() throw( RuntimeException )
543 {
544     ensureAlive();
545     return OUString();
546 }
547 
548 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getSelectionStart() throw( RuntimeException )
549 {
550     ensureAlive();
551     return -1;
552 }
553 
554 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getSelectionEnd() throw( RuntimeException )
555 {
556     ensureAlive();
557     return -1;
558 }
559 
560 sal_Bool SAL_CALL ScAccessibleCsvRuler::setSelection( sal_Int32 /* nStartIndex */, sal_Int32 /* nEndIndex */ )
561         throw( IndexOutOfBoundsException, RuntimeException )
562 {
563     ensureAlive();
564     return sal_False;
565 }
566 
567 OUString SAL_CALL ScAccessibleCsvRuler::getText() throw( RuntimeException )
568 {
569     ScUnoGuard aGuard;
570     ensureAlive();
571     return OUString( maBuffer.getStr(), implGetTextLength() );
572 }
573 
574 OUString SAL_CALL ScAccessibleCsvRuler::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
575         throw( IndexOutOfBoundsException, RuntimeException )
576 {
577     ScUnoGuard aGuard;
578     ensureAlive();
579     ensureValidRange( nStartIndex, nEndIndex );
580     return OUString( maBuffer.getStr() + nStartIndex, nEndIndex - nStartIndex );
581 }
582 
583 TextSegment SAL_CALL ScAccessibleCsvRuler::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType )
584         throw( IndexOutOfBoundsException, IllegalArgumentException, RuntimeException )
585 {
586     ScUnoGuard aGuard;
587     ensureAlive();
588 
589     TextSegment aResult;
590     aResult.SegmentStart = -1;
591     aResult.SegmentEnd = -1;
592 
593     if( (nIndex == implGetTextLength()) && (nTextType != AccessibleTextType::LINE) )
594         return aResult;
595 
596     ensureValidIndex( nIndex );
597 
598     OUStringBuffer aResultText;     // will be assigned to aResult.SegmentText below
599     sal_Int32 nRulerPos = lcl_GetRulerPos( nIndex );
600 
601     switch( nTextType )
602     {
603         // single character
604         case AccessibleTextType::CHARACTER:
605         {
606             aResult.SegmentStart = nIndex;
607             aResultText.append( maBuffer.charAt( nIndex ) );
608         }
609         break;
610 
611         // entire number or single dot/line
612         case AccessibleTextType::WORD:
613         case AccessibleTextType::GLYPH:
614             aResult.SegmentStart = nIndex;
615             if( nRulerPos % 10 )
616                 aResultText.append( maBuffer.charAt( nIndex ) );
617             else
618                 aResultText.append( nRulerPos );    // string representation of sal_Int32!!!
619         break;
620 
621         // entire text
622         case AccessibleTextType::SENTENCE:
623         case AccessibleTextType::PARAGRAPH:
624         case AccessibleTextType::LINE:
625             aResult.SegmentStart = 0;
626             aResultText.append( maBuffer.getStr(), implGetTextLength() );
627         break;
628 
629         // equal-formatted text
630         case AccessibleTextType::ATTRIBUTE_RUN:
631         {
632             sal_Int32 nFirstIndex = implGetFirstEqualFormatted( nIndex );
633             sal_Int32 nLastIndex = implGetLastEqualFormatted( nIndex );
634             aResult.SegmentStart = nFirstIndex;
635             aResultText.append( maBuffer.getStr() + nFirstIndex, nLastIndex - nFirstIndex + 1 );
636         }
637         break;
638 
639         default:
640             throw RuntimeException();
641     }
642 
643     aResult.SegmentText = aResultText.makeStringAndClear();
644     aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength();
645     return aResult;
646 }
647 
648 TextSegment SAL_CALL ScAccessibleCsvRuler::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType )
649         throw( IndexOutOfBoundsException, IllegalArgumentException, RuntimeException )
650 {
651     ScUnoGuard aGuard;
652     ensureAlive();
653     ensureValidIndexWithEnd( nIndex );
654 
655     TextSegment aResult;
656     aResult.SegmentStart = -1;
657     aResult.SegmentEnd = -1;
658 
659     sal_Int32 nRulerPos = lcl_GetRulerPos( nIndex );
660 
661     switch( nTextType )
662     {
663         // single character
664         case AccessibleTextType::CHARACTER:
665             if( nIndex > 0 )
666                 aResult = getTextAtIndex( nIndex - 1, nTextType );
667             // else empty
668         break;
669 
670         // entire number or single dot/line
671         case AccessibleTextType::WORD:
672         case AccessibleTextType::GLYPH:
673             if( nRulerPos > 0 )
674                 aResult = getTextAtIndex( lcl_GetApiPos( nRulerPos - 1 ), nTextType );
675             // else empty
676         break;
677 
678         // entire text
679         case AccessibleTextType::SENTENCE:
680         case AccessibleTextType::PARAGRAPH:
681         case AccessibleTextType::LINE:
682             // empty
683         break;
684 
685         // equal-formatted text
686         case AccessibleTextType::ATTRIBUTE_RUN:
687         {
688             sal_Int32 nFirstIndex = implGetFirstEqualFormatted( nIndex );
689             if( nFirstIndex > 0 )
690                 aResult = getTextAtIndex( nFirstIndex - 1, nTextType );
691             // else empty
692         }
693         break;
694 
695         default:
696             throw RuntimeException();
697     }
698     return aResult;
699 }
700 
701 TextSegment SAL_CALL ScAccessibleCsvRuler::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType )
702         throw( IndexOutOfBoundsException, IllegalArgumentException, RuntimeException )
703 {
704     ScUnoGuard aGuard;
705     ensureAlive();
706     ensureValidIndexWithEnd( nIndex );
707 
708     TextSegment aResult;
709     aResult.SegmentStart = -1;
710     aResult.SegmentEnd = -1;
711 
712     sal_Int32 nRulerPos = lcl_GetRulerPos( nIndex );
713     sal_Int32 nLastValid = implGetTextLength();
714 
715     switch( nTextType )
716     {
717         // single character
718         case AccessibleTextType::CHARACTER:
719             if( nIndex < nLastValid )
720                 aResult = getTextAtIndex( nIndex + 1, nTextType );
721             // else empty
722         break;
723 
724         // entire number or single dot/line
725         case AccessibleTextType::WORD:
726         case AccessibleTextType::GLYPH:
727             if( nRulerPos < implGetRuler().GetPosCount() )
728                 aResult = getTextAtIndex( lcl_GetApiPos( nRulerPos + 1 ), nTextType );
729             // else empty
730         break;
731 
732         // entire text
733         case AccessibleTextType::SENTENCE:
734         case AccessibleTextType::PARAGRAPH:
735         case AccessibleTextType::LINE:
736             // empty
737         break;
738 
739         // equal-formatted text
740         case AccessibleTextType::ATTRIBUTE_RUN:
741         {
742             sal_Int32 nLastIndex = implGetLastEqualFormatted( nIndex );
743             if( nLastIndex < nLastValid )
744                 aResult = getTextAtIndex( nLastIndex + 1, nTextType );
745             // else empty
746         }
747         break;
748 
749         default:
750             throw RuntimeException();
751     }
752     return aResult;
753 }
754 
755 sal_Bool SAL_CALL ScAccessibleCsvRuler::copyText( sal_Int32 /* nStartIndex */, sal_Int32 /* nEndIndex */ )
756         throw( IndexOutOfBoundsException, RuntimeException )
757 {
758     ensureAlive();
759     return sal_False;
760 }
761 
762 
763 // XInterface -----------------------------------------------------------------
764 
765 Any SAL_CALL ScAccessibleCsvRuler::queryInterface( const ::com::sun::star::uno::Type& rType )
766         throw( RuntimeException )
767 {
768     Any aAny( ScAccessibleCsvRulerImpl::queryInterface( rType ) );
769     return aAny.hasValue() ? aAny : ScAccessibleCsvControl::queryInterface( rType );
770 }
771 
772 void SAL_CALL ScAccessibleCsvRuler::acquire() throw ()
773 {
774     ScAccessibleCsvControl::acquire();
775 }
776 
777 void SAL_CALL ScAccessibleCsvRuler::release() throw ()
778 {
779     ScAccessibleCsvControl::release();
780 }
781 
782 
783 // XServiceInfo ---------------------------------------------------------------
784 
785 OUString SAL_CALL ScAccessibleCsvRuler::getImplementationName() throw( RuntimeException )
786 {
787     return CREATE_OUSTRING( RULER_IMPL_NAME );
788 }
789 
790 
791 // XTypeProvider --------------------------------------------------------------
792 
793 Sequence< ::com::sun::star::uno::Type > SAL_CALL ScAccessibleCsvRuler::getTypes() throw( RuntimeException )
794 {
795     Sequence< ::com::sun::star::uno::Type > aSeq( 1 );
796     aSeq[ 0 ] = getCppuType( static_cast< const Reference< XAccessibleText >* >( NULL ) );
797     return ::comphelper::concatSequences( ScAccessibleCsvControl::getTypes(), aSeq );
798 }
799 
800 Sequence< sal_Int8 > SAL_CALL ScAccessibleCsvRuler::getImplementationId() throw( RuntimeException )
801 {
802     static Sequence< sal_Int8 > aSeq;
803     getUuid( aSeq );
804     return aSeq;
805 }
806 
807 
808 // events ---------------------------------------------------------------------
809 
810 void ScAccessibleCsvRuler::SendCaretEvent()
811 {
812     sal_Int32 nPos = implGetRuler().GetRulerCursorPos();
813     if( nPos != CSV_POS_INVALID )
814     {
815         AccessibleEventObject aEvent;
816         aEvent.EventId = AccessibleEventId::CARET_CHANGED;
817         aEvent.Source = Reference< XAccessible >( this );
818         aEvent.NewValue <<= nPos;
819         CommitChange( aEvent );
820     }
821 }
822 
823 
824 // helpers --------------------------------------------------------------------
825 
826 OUString SAL_CALL ScAccessibleCsvRuler::createAccessibleName() throw( RuntimeException )
827 {
828     return String( ScResId( STR_ACC_CSVRULER_NAME ) );
829 }
830 
831 OUString SAL_CALL ScAccessibleCsvRuler::createAccessibleDescription() throw( RuntimeException )
832 {
833     return String( ScResId( STR_ACC_CSVRULER_DESCR ) );
834 }
835 
836 void ScAccessibleCsvRuler::ensureValidIndex( sal_Int32 nIndex ) const
837         throw( IndexOutOfBoundsException )
838 {
839     if( (nIndex < 0) || (nIndex >= implGetTextLength()) )
840         throw IndexOutOfBoundsException();
841 }
842 
843 void ScAccessibleCsvRuler::ensureValidIndexWithEnd( sal_Int32 nIndex ) const
844         throw( IndexOutOfBoundsException )
845 {
846     if( (nIndex < 0) || (nIndex > implGetTextLength()) )
847         throw IndexOutOfBoundsException();
848 }
849 
850 void ScAccessibleCsvRuler::ensureValidRange( sal_Int32& rnStartIndex, sal_Int32& rnEndIndex ) const
851         throw( IndexOutOfBoundsException )
852 {
853     if( rnStartIndex > rnEndIndex )
854         ::std::swap( rnStartIndex, rnEndIndex );
855     if( (rnStartIndex < 0) || (rnEndIndex > implGetTextLength()) )
856         throw IndexOutOfBoundsException();
857 }
858 
859 ScCsvRuler& ScAccessibleCsvRuler::implGetRuler() const
860 {
861     return static_cast< ScCsvRuler& >( implGetControl() );
862 }
863 
864 void ScAccessibleCsvRuler::constructStringBuffer() throw( RuntimeException )
865 {
866     ScUnoGuard aGuard;
867     ensureAlive();
868     // extend existing string buffer to new ruler size
869     sal_Int32 nRulerCount = implGetRuler().GetPosCount();
870     sal_Int32 nRulerPos = lcl_GetRulerPos( maBuffer.getLength() );
871     for( ; nRulerPos <= nRulerCount; ++nRulerPos ) // include last position
872     {
873         switch( nRulerPos % 10 )
874         {
875             case 0:     maBuffer.append( nRulerPos );   break;
876             case 5:     maBuffer.append( cRulerLine );  break;
877             default:    maBuffer.append( cRulerDot );
878         }
879     }
880 }
881 
882 sal_Int32 ScAccessibleCsvRuler::implGetTextLength() const
883 {
884     return lcl_GetApiPos( implGetRuler().GetPosCount() + 1 );
885 }
886 
887 bool ScAccessibleCsvRuler::implHasSplit( sal_Int32 nApiPos )
888 {
889     sal_Int32 nRulerPos = lcl_GetRulerPos( nApiPos );
890     return implGetRuler().HasSplit( nRulerPos ) && (nApiPos == lcl_GetApiPos( nRulerPos ));
891 }
892 
893 sal_Int32 ScAccessibleCsvRuler::implGetFirstEqualFormatted( sal_Int32 nApiPos )
894 {
895     bool bSplit = implHasSplit( nApiPos );
896     while( (nApiPos > 0) && (implHasSplit( nApiPos - 1 ) == bSplit) )
897         --nApiPos;
898     return nApiPos;
899 }
900 
901 sal_Int32 ScAccessibleCsvRuler::implGetLastEqualFormatted( sal_Int32 nApiPos )
902 {
903     bool bSplit = implHasSplit( nApiPos );
904     sal_Int32 nLength = implGetTextLength();
905     while( (nApiPos < nLength - 1) && (implHasSplit( nApiPos + 1 ) == bSplit) )
906         ++nApiPos;
907     return nApiPos;
908 }
909 
910 
911 // Grid =======================================================================
912 
913 /** Converts a grid columnm index to an API column index. */
914 inline sal_Int32 lcl_GetApiColumn( sal_uInt32 nGridColumn )
915 {
916     return (nGridColumn != CSV_COLUMN_HEADER) ? static_cast< sal_Int32 >( nGridColumn + 1 ) : 0;
917 }
918 
919 /** Converts an API columnm index to a ScCsvGrid column index. */
920 inline sal_uInt32 lcl_GetGridColumn( sal_Int32 nApiColumn )
921 {
922     return (nApiColumn > 0) ? static_cast< sal_uInt32 >( nApiColumn - 1 ) : CSV_COLUMN_HEADER;
923 }
924 
925 
926 // ----------------------------------------------------------------------------
927 
928 DBG_NAME( ScAccessibleCsvGrid )
929 
930 ScAccessibleCsvGrid::ScAccessibleCsvGrid( ScCsvGrid& rGrid ) :
931     ScAccessibleCsvControl( rGrid.GetAccessibleParentWindow()->GetAccessible(), rGrid, nGridRole )
932 {
933     DBG_CTOR( ScAccessibleCsvGrid, NULL );
934 }
935 
936 ScAccessibleCsvGrid::~ScAccessibleCsvGrid()
937 {
938     DBG_DTOR( ScAccessibleCsvGrid, NULL );
939     implDispose();
940 }
941 
942 
943 // XAccessibleComponent -------------------------------------------------------
944 
945 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleAtPoint( const AwtPoint& rPoint )
946         throw( RuntimeException )
947 {
948     Reference< XAccessible > xRet;
949     if( containsPoint( rPoint ) )
950     {
951         ScUnoGuard aGuard;
952         ensureAlive();
953 
954         const ScCsvGrid& rGrid = implGetGrid();
955         // #102679#; use <= instead of <, because the offset is the size and not the point
956         sal_Int32 nColumn = ((rGrid.GetFirstX() <= rPoint.X) && (rPoint.X <= rGrid.GetLastX())) ?
957             lcl_GetApiColumn( rGrid.GetColumnFromX( rPoint.X ) ) : 0;
958         sal_Int32 nRow = (rPoint.Y >= rGrid.GetHdrHeight()) ?
959             (rGrid.GetLineFromY( rPoint.Y ) - rGrid.GetFirstVisLine() + 1) : 0;
960         xRet = implCreateCellObj( nRow, nColumn );
961     }
962     return xRet;
963 }
964 
965 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getForeground(  )
966 throw (RuntimeException)
967 {
968     ScUnoGuard aGuard;
969     ensureAlive();
970     return implGetGrid().GetSettings().GetStyleSettings().GetButtonTextColor().GetColor();
971 }
972 
973 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getBackground(  )
974 throw (RuntimeException)
975 {
976     ScUnoGuard aGuard;
977     ensureAlive();
978     return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor;
979 }
980 
981 // XAccessibleContext ---------------------------------------------------------
982 
983 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleChildCount() throw( RuntimeException )
984 {
985     ScUnoGuard aGuard;
986     ensureAlive();
987     return implGetCellCount();
988 }
989 
990 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleChild( sal_Int32 nIndex )
991         throw( IndexOutOfBoundsException, RuntimeException )
992 {
993     ScUnoGuard aGuard;
994     ensureAlive();
995     ensureValidIndex( nIndex );
996     return implCreateCellObj( implGetRow( nIndex ), implGetColumn( nIndex ) );
997 }
998 
999 Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvGrid::getAccessibleRelationSet()
1000         throw( RuntimeException )
1001 {
1002     ScUnoGuard aGuard;
1003     ensureAlive();
1004     AccessibleRelationSetHelper* pRelationSet = new AccessibleRelationSetHelper();
1005     Reference< XAccessible > xAccObj = implGetChildByRole( getAccessibleParent(), nRulerRole );
1006     if( xAccObj.is() )
1007     {
1008         Sequence< Reference< XInterface > > aSeq( 1 );
1009         aSeq[ 0 ] = xAccObj;
1010         pRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::CONTROLLED_BY, aSeq ) );
1011     }
1012     return pRelationSet;
1013 }
1014 
1015 Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvGrid::getAccessibleStateSet()
1016         throw( RuntimeException )
1017 {
1018     ScUnoGuard aGuard;
1019     AccessibleStateSetHelper* pStateSet = implCreateStateSet();
1020     if( implIsAlive() )
1021     {
1022         pStateSet->AddState( AccessibleStateType::FOCUSABLE );
1023         pStateSet->AddState( AccessibleStateType::MULTI_SELECTABLE );
1024         pStateSet->AddState( AccessibleStateType::MANAGES_DESCENDANTS );
1025         if( implGetGrid().HasFocus() )
1026             pStateSet->AddState( AccessibleStateType::FOCUSED );
1027     }
1028     else
1029         pStateSet->AddState( AccessibleStateType::DEFUNC );
1030     return pStateSet;
1031 }
1032 
1033 
1034 // XAccessibleTable -----------------------------------------------------------
1035 
1036 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRowCount() throw( RuntimeException )
1037 {
1038     ScUnoGuard aGuard;
1039     ensureAlive();
1040     return implGetRowCount();
1041 }
1042 
1043 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnCount() throw( RuntimeException )
1044 {
1045     ScUnoGuard aGuard;
1046     ensureAlive();
1047     return implGetColumnCount();
1048 }
1049 
1050 OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleRowDescription( sal_Int32 nRow )
1051         throw( IndexOutOfBoundsException, RuntimeException )
1052 {
1053     ScUnoGuard aGuard;
1054     ensureAlive();
1055     ensureValidPosition( nRow, 0 );
1056     return implGetCellText( nRow, 0 );
1057 }
1058 
1059 OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnDescription( sal_Int32 nColumn )
1060         throw( IndexOutOfBoundsException, RuntimeException )
1061 {
1062     ScUnoGuard aGuard;
1063     ensureAlive();
1064     ensureValidPosition( 0, nColumn );
1065     return implGetCellText( 0, nColumn );
1066 }
1067 
1068 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
1069         throw( IndexOutOfBoundsException, RuntimeException )
1070 {
1071     ensureAlive();
1072     ensureValidPosition( nRow, nColumn );
1073     return 1;
1074 }
1075 
1076 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
1077         throw( IndexOutOfBoundsException, RuntimeException )
1078 {
1079     ensureAlive();
1080     ensureValidPosition( nRow, nColumn );
1081     return 1;
1082 }
1083 
1084 Reference< XAccessibleTable > SAL_CALL ScAccessibleCsvGrid::getAccessibleRowHeaders()
1085         throw( RuntimeException )
1086 {
1087     ensureAlive();
1088     return NULL;
1089 }
1090 
1091 Reference< XAccessibleTable > SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnHeaders()
1092         throw( RuntimeException )
1093 {
1094     ensureAlive();
1095     return NULL;
1096 }
1097 
1098 Sequence< sal_Int32 > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleRows()
1099         throw( RuntimeException )
1100 {
1101     ensureAlive();
1102     return Sequence< sal_Int32 >();
1103 }
1104 
1105 Sequence< sal_Int32 > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleColumns()
1106         throw( RuntimeException )
1107 {
1108     ScUnoGuard aGuard;
1109     ensureAlive();
1110 
1111     ScCsvGrid& rGrid = implGetGrid();
1112     Sequence< sal_Int32 > aSeq( implGetColumnCount() );
1113 
1114     sal_Int32 nSeqIx = 0;
1115     sal_uInt32 nColIx = rGrid.GetFirstSelected();
1116     for( ; nColIx != CSV_COLUMN_INVALID; ++nSeqIx, nColIx = rGrid.GetNextSelected( nColIx ) )
1117         aSeq[ nSeqIx ] = lcl_GetApiColumn( nColIx );
1118 
1119     aSeq.realloc( nSeqIx );
1120     return aSeq;
1121 }
1122 
1123 sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleRowSelected( sal_Int32 /* nRow */ )
1124         throw( IndexOutOfBoundsException, RuntimeException )
1125 {
1126     ensureAlive();
1127     return sal_False;
1128 }
1129 
1130 sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleColumnSelected( sal_Int32 nColumn )
1131         throw( IndexOutOfBoundsException, RuntimeException )
1132 {
1133     ScUnoGuard aGuard;
1134     ensureAlive();
1135     ensureValidIndex( nColumn );
1136     return implIsColumnSelected( nColumn );
1137 }
1138 
1139 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
1140         throw( IndexOutOfBoundsException, RuntimeException )
1141 {
1142     ScUnoGuard aGuard;
1143     ensureAlive();
1144     ensureValidPosition( nRow, nColumn );
1145     return implCreateCellObj( nRow, nColumn );
1146 }
1147 
1148 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleCaption()
1149         throw( RuntimeException )
1150 {
1151     ensureAlive();
1152     return NULL;
1153 }
1154 
1155 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleSummary()
1156         throw( RuntimeException )
1157 {
1158     ensureAlive();
1159     return NULL;
1160 }
1161 
1162 sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleSelected( sal_Int32 /* nRow */, sal_Int32 nColumn )
1163         throw( IndexOutOfBoundsException, RuntimeException )
1164 {
1165     return isAccessibleColumnSelected( nColumn );
1166 }
1167 
1168 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
1169         throw( IndexOutOfBoundsException, RuntimeException )
1170 {
1171     ScUnoGuard aGuard;
1172     ensureAlive();
1173     ensureValidPosition( nRow, nColumn );
1174     return implGetIndex( nRow, nColumn );
1175 }
1176 
1177 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRow( sal_Int32 nChildIndex )
1178         throw( IndexOutOfBoundsException, RuntimeException )
1179 {
1180     ScUnoGuard aGuard;
1181     ensureAlive();
1182     ensureValidIndex( nChildIndex );
1183     return implGetRow( nChildIndex );
1184 }
1185 
1186 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumn( sal_Int32 nChildIndex )
1187         throw( IndexOutOfBoundsException, RuntimeException )
1188 {
1189     ScUnoGuard aGuard;
1190     ensureAlive();
1191     ensureValidIndex( nChildIndex );
1192     return implGetColumn( nChildIndex );
1193 }
1194 
1195 
1196 // XAccessibleSelection -------------------------------------------------------
1197 
1198 void SAL_CALL ScAccessibleCsvGrid::selectAccessibleChild( sal_Int32 nChildIndex )
1199         throw( IndexOutOfBoundsException, RuntimeException )
1200 {
1201     ScUnoGuard aGuard;
1202     ensureAlive();
1203     ensureValidIndex( nChildIndex );
1204     sal_Int32 nColumn = implGetColumn( nChildIndex );
1205     if( nChildIndex == 0 )
1206         implGetGrid().SelectAll();
1207     else
1208         implSelectColumn( nColumn, true );
1209 }
1210 
1211 sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleChildSelected( sal_Int32 nChildIndex )
1212         throw( IndexOutOfBoundsException, RuntimeException )
1213 {
1214     ScUnoGuard aGuard;
1215     ensureAlive();
1216     ensureValidIndex( nChildIndex );
1217     sal_Int32 nColumn = implGetColumn( nChildIndex );
1218     return implIsColumnSelected( nColumn );
1219 }
1220 
1221 void SAL_CALL ScAccessibleCsvGrid::clearAccessibleSelection() throw( RuntimeException )
1222 {
1223     ScUnoGuard aGuard;
1224     ensureAlive();
1225     implGetGrid().SelectAll( false );
1226 }
1227 
1228 void SAL_CALL ScAccessibleCsvGrid::selectAllAccessibleChildren() throw( RuntimeException )
1229 {
1230     selectAccessibleChild( 0 );
1231 }
1232 
1233 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleChildCount() throw( RuntimeException )
1234 {
1235     ScUnoGuard aGuard;
1236     ensureAlive();
1237     return implGetRowCount() * implGetSelColumnCount();
1238 }
1239 
1240 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
1241         throw( IndexOutOfBoundsException, RuntimeException )
1242 {
1243     ScUnoGuard aGuard;
1244     ensureAlive();
1245     sal_Int32 nColumns = implGetSelColumnCount();
1246     if( nColumns == 0 )
1247         throw IndexOutOfBoundsException();
1248 
1249     sal_Int32 nRow = nSelectedChildIndex / nColumns;
1250     sal_Int32 nColumn = implGetSelColumn( nSelectedChildIndex % nColumns );
1251     return getAccessibleCellAt( nRow, nColumn );
1252 }
1253 
1254 void SAL_CALL ScAccessibleCsvGrid::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
1255         throw( IndexOutOfBoundsException, RuntimeException )
1256 {
1257     ScUnoGuard aGuard;
1258     ensureAlive();
1259     sal_Int32 nColumns = implGetSelColumnCount();
1260     if( nColumns == 0 )
1261         throw IndexOutOfBoundsException();
1262 
1263     sal_Int32 nColumn = implGetSelColumn( nSelectedChildIndex % nColumns );
1264     ensureValidPosition( nSelectedChildIndex / nColumns, nColumn );
1265     if( nColumn > 0 )
1266         implSelectColumn( nColumn, false );
1267 }
1268 
1269 
1270 // XInterface -----------------------------------------------------------------
1271 
1272 Any SAL_CALL ScAccessibleCsvGrid::queryInterface( const ::com::sun::star::uno::Type& rType )
1273         throw( RuntimeException )
1274 {
1275     Any aAny( ScAccessibleCsvGridImpl::queryInterface( rType ) );
1276     return aAny.hasValue() ? aAny : ScAccessibleCsvControl::queryInterface( rType );
1277 }
1278 
1279 void SAL_CALL ScAccessibleCsvGrid::acquire() throw ()
1280 {
1281     ScAccessibleCsvControl::acquire();
1282 }
1283 
1284 void SAL_CALL ScAccessibleCsvGrid::release() throw ()
1285 {
1286     ScAccessibleCsvControl::release();
1287 }
1288 
1289 
1290 // XServiceInfo ---------------------------------------------------------------
1291 
1292 OUString SAL_CALL ScAccessibleCsvGrid::getImplementationName() throw( RuntimeException )
1293 {
1294     return CREATE_OUSTRING( GRID_IMPL_NAME );
1295 }
1296 
1297 
1298 // XTypeProvider --------------------------------------------------------------
1299 
1300 Sequence< ::com::sun::star::uno::Type > SAL_CALL ScAccessibleCsvGrid::getTypes() throw( RuntimeException )
1301 {
1302     Sequence< ::com::sun::star::uno::Type > aSeq( 2 );
1303     aSeq[ 0 ] = getCppuType( static_cast< const Reference< XAccessibleTable >* >( NULL ) );
1304     aSeq[ 1 ] = getCppuType( static_cast< const Reference< XAccessibleSelection >* >( NULL ) );
1305     return ::comphelper::concatSequences( ScAccessibleCsvControl::getTypes(), aSeq );
1306 }
1307 
1308 Sequence< sal_Int8 > SAL_CALL ScAccessibleCsvGrid::getImplementationId() throw( RuntimeException )
1309 {
1310     static Sequence< sal_Int8 > aSeq;
1311     getUuid( aSeq );
1312     return aSeq;
1313 }
1314 
1315 
1316 // events ---------------------------------------------------------------------
1317 
1318 void ScAccessibleCsvGrid::SendFocusEvent( bool bFocused )
1319 {
1320     ScAccessibleCsvControl::SendFocusEvent( bFocused );
1321 
1322     AccessibleEventObject aEvent;
1323     aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
1324     aEvent.Source = Reference< XAccessible >( this );
1325     (bFocused ? aEvent.NewValue : aEvent.OldValue) <<=
1326         getAccessibleCellAt( 0, lcl_GetApiColumn( implGetGrid().GetFocusColumn() ) );
1327     CommitChange( aEvent );
1328 }
1329 
1330 void ScAccessibleCsvGrid::SendTableUpdateEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn, bool bAllRows )
1331 {
1332     if( nFirstColumn <= nLastColumn )
1333     {
1334         AccessibleTableModelChange aModelChange(
1335             AccessibleTableModelChangeType::UPDATE, 0, bAllRows ? implGetRowCount() - 1 : 0,
1336             lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) );
1337         AccessibleEventObject aEvent;
1338         aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED;
1339         aEvent.Source = Reference< XAccessible >( this );
1340         aEvent.NewValue <<= aModelChange;
1341         CommitChange( aEvent );
1342     }
1343 }
1344 
1345 void ScAccessibleCsvGrid::SendInsertColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn )
1346 {
1347     if( nFirstColumn <= nLastColumn )
1348     {
1349         AccessibleTableModelChange aModelChange(
1350             AccessibleTableModelChangeType::INSERT, 0, implGetRowCount() - 1,
1351             lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) );
1352         AccessibleEventObject aEvent;
1353         aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED;
1354         aEvent.Source = Reference< XAccessible >( this );
1355         aEvent.NewValue <<= aModelChange;
1356         CommitChange( aEvent );
1357     }
1358 }
1359 
1360 void ScAccessibleCsvGrid::SendRemoveColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn )
1361 {
1362     if( nFirstColumn <= nLastColumn )
1363     {
1364         AccessibleTableModelChange aModelChange(
1365             AccessibleTableModelChangeType::DELETE, 0, implGetRowCount() - 1,
1366             lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) );
1367         AccessibleEventObject aEvent;
1368         aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED;
1369         aEvent.Source = Reference< XAccessible >( this );
1370         aEvent.NewValue <<= aModelChange;
1371         CommitChange( aEvent );
1372     }
1373 }
1374 
1375 
1376 // helpers --------------------------------------------------------------------
1377 
1378 OUString SAL_CALL ScAccessibleCsvGrid::createAccessibleName() throw( RuntimeException )
1379 {
1380     return String( ScResId( STR_ACC_CSVGRID_NAME ) );
1381 }
1382 
1383 OUString SAL_CALL ScAccessibleCsvGrid::createAccessibleDescription() throw( RuntimeException )
1384 {
1385     return String( ScResId( STR_ACC_CSVGRID_DESCR ) );
1386 }
1387 
1388 void ScAccessibleCsvGrid::ensureValidIndex( sal_Int32 nIndex ) const
1389         throw( IndexOutOfBoundsException )
1390 {
1391     if( (nIndex < 0) || (nIndex >= implGetCellCount()) )
1392         throw IndexOutOfBoundsException();
1393 }
1394 
1395 void ScAccessibleCsvGrid::ensureValidPosition( sal_Int32 nRow, sal_Int32 nColumn ) const
1396         throw( IndexOutOfBoundsException )
1397 {
1398     if( (nRow < 0) || (nRow >= implGetRowCount()) || (nColumn < 0) || (nColumn >= implGetColumnCount()) )
1399         throw IndexOutOfBoundsException();
1400 }
1401 
1402 ScCsvGrid& ScAccessibleCsvGrid::implGetGrid() const
1403 {
1404     return static_cast< ScCsvGrid& >( implGetControl() );
1405 }
1406 
1407 bool ScAccessibleCsvGrid::implIsColumnSelected( sal_Int32 nColumn ) const
1408 {
1409     return (nColumn > 0) && implGetGrid().IsSelected( lcl_GetGridColumn( nColumn ) );
1410 }
1411 
1412 void ScAccessibleCsvGrid::implSelectColumn( sal_Int32 nColumn, bool bSelect )
1413 {
1414     if( nColumn > 0 )
1415         implGetGrid().Select( lcl_GetGridColumn( nColumn ), bSelect );
1416 }
1417 
1418 sal_Int32 ScAccessibleCsvGrid::implGetRowCount() const
1419 {
1420     return static_cast< sal_Int32 >( implGetGrid().GetLastVisLine() - implGetGrid().GetFirstVisLine() + 2 );
1421 }
1422 
1423 sal_Int32 ScAccessibleCsvGrid::implGetColumnCount() const
1424 {
1425     return static_cast< sal_Int32 >( implGetGrid().GetColumnCount() + 1 );
1426 }
1427 
1428 sal_Int32 ScAccessibleCsvGrid::implGetSelColumnCount() const
1429 {
1430     ScCsvGrid& rGrid = implGetGrid();
1431     sal_Int32 nCount = 0;
1432     for( sal_uInt32 nColIx = rGrid.GetFirstSelected(); nColIx != CSV_COLUMN_INVALID; nColIx = rGrid.GetNextSelected( nColIx ) )
1433         ++nCount;
1434     return nCount;
1435 }
1436 
1437 sal_Int32 ScAccessibleCsvGrid::implGetSelColumn( sal_Int32 nSelColumn ) const
1438 {
1439     ScCsvGrid& rGrid = implGetGrid();
1440     sal_Int32 nColumn = 0;
1441     for( sal_uInt32 nColIx = rGrid.GetFirstSelected(); nColIx != CSV_COLUMN_INVALID; nColIx = rGrid.GetNextSelected( nColIx ) )
1442     {
1443         if( nColumn == nSelColumn )
1444             return static_cast< sal_Int32 >( nColIx + 1 );
1445         ++nColumn;
1446     }
1447     return 0;
1448 }
1449 
1450 String ScAccessibleCsvGrid::implGetCellText( sal_Int32 nRow, sal_Int32 nColumn ) const
1451 {
1452     ScCsvGrid& rGrid = implGetGrid();
1453     sal_Int32 nLine = nRow + rGrid.GetFirstVisLine() - 1;
1454     String aCellStr;
1455     if( (nColumn > 0) && (nRow > 0) )
1456         aCellStr = rGrid.GetCellText( lcl_GetGridColumn( nColumn ), nLine );
1457     else if( nRow > 0 )
1458         aCellStr = String::CreateFromInt32( nLine + 1L );
1459     else if( nColumn > 0 )
1460         aCellStr = rGrid.GetColumnTypeName( lcl_GetGridColumn( nColumn ) );
1461     return aCellStr;
1462 }
1463 
1464 
1465 ScAccessibleCsvControl* ScAccessibleCsvGrid::implCreateCellObj( sal_Int32 nRow, sal_Int32 nColumn ) const
1466 {
1467     return new ScAccessibleCsvCell( implGetGrid(), implGetCellText( nRow, nColumn ), nRow, nColumn );
1468 }
1469 
1470 
1471 // ============================================================================
1472 
1473 DBG_NAME( ScAccessibleCsvCell )
1474 
1475 ScAccessibleCsvCell::ScAccessibleCsvCell(
1476         ScCsvGrid& rGrid,
1477         const String& rCellText,
1478         sal_Int32 nRow, sal_Int32 nColumn ) :
1479     ScAccessibleCsvControl( rGrid.GetAccessible(), rGrid, nCellRole ),
1480     AccessibleStaticTextBase( SvxEditSourcePtr( NULL ) ),
1481     maCellText( rCellText ),
1482     mnLine( nRow ? (nRow + rGrid.GetFirstVisLine() - 1) : CSV_LINE_HEADER ),
1483     mnColumn( lcl_GetGridColumn( nColumn ) ),
1484     mnIndex( nRow * (rGrid.GetColumnCount() + 1) + nColumn )
1485 {
1486     DBG_CTOR( ScAccessibleCsvCell, NULL );
1487     SetEditSource( implCreateEditSource() );
1488 }
1489 
1490 ScAccessibleCsvCell::~ScAccessibleCsvCell()
1491 {
1492     DBG_DTOR( ScAccessibleCsvCell, NULL );
1493 }
1494 
1495 void SAL_CALL ScAccessibleCsvCell::disposing()
1496 {
1497     ScUnoGuard aGuard;
1498     SetEditSource( SvxEditSourcePtr( NULL ) );
1499     ScAccessibleCsvControl::disposing();
1500 }
1501 
1502 
1503 // XAccessibleComponent -------------------------------------------------------
1504 
1505 void SAL_CALL ScAccessibleCsvCell::grabFocus() throw( RuntimeException )
1506 {
1507     ScUnoGuard aGuard;
1508     ensureAlive();
1509     ScCsvGrid& rGrid = implGetGrid();
1510     rGrid.Execute( CSVCMD_MOVEGRIDCURSOR, rGrid.GetColumnPos( mnColumn ) );
1511 }
1512 
1513 sal_Int32 SAL_CALL ScAccessibleCsvCell::getForeground(  )
1514 throw (RuntimeException)
1515 {
1516     ScUnoGuard aGuard;
1517     ensureAlive();
1518     return implGetGrid().GetSettings().GetStyleSettings().GetButtonTextColor().GetColor();
1519 }
1520 
1521 sal_Int32 SAL_CALL ScAccessibleCsvCell::getBackground(  )
1522 throw (RuntimeException)
1523 {
1524     ScUnoGuard aGuard;
1525     ensureAlive();
1526     return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor;
1527 }
1528 
1529 // XAccessibleContext -----------------------------------------------------
1530 
1531 sal_Int32 SAL_CALL ScAccessibleCsvCell::getAccessibleChildCount() throw( RuntimeException )
1532 {
1533     return AccessibleStaticTextBase::getAccessibleChildCount();
1534 }
1535 
1536 Reference< XAccessible > SAL_CALL ScAccessibleCsvCell::getAccessibleChild( sal_Int32 nIndex )
1537         throw( IndexOutOfBoundsException, RuntimeException )
1538 {
1539     return AccessibleStaticTextBase::getAccessibleChild( nIndex );
1540 }
1541 
1542 sal_Int32 SAL_CALL ScAccessibleCsvCell::getAccessibleIndexInParent() throw( RuntimeException )
1543 {
1544     ScUnoGuard aGuard;
1545     ensureAlive();
1546     return mnIndex;
1547 }
1548 
1549 Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvCell::getAccessibleRelationSet()
1550         throw( RuntimeException )
1551 {
1552     ScUnoGuard aGuard;
1553     ensureAlive();
1554     return new AccessibleRelationSetHelper();
1555 }
1556 
1557 Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvCell::getAccessibleStateSet()
1558         throw( RuntimeException )
1559 {
1560     ScUnoGuard aGuard;
1561     AccessibleStateSetHelper* pStateSet = implCreateStateSet();
1562     if( implIsAlive() )
1563     {
1564         const ScCsvGrid& rGrid = implGetGrid();
1565         pStateSet->AddState( AccessibleStateType::SINGLE_LINE );
1566         if( mnColumn != CSV_COLUMN_HEADER )
1567             pStateSet->AddState( AccessibleStateType::SELECTABLE );
1568         if( rGrid.HasFocus() && (rGrid.GetFocusColumn() == mnColumn) && (mnLine == CSV_LINE_HEADER) )
1569             pStateSet->AddState( AccessibleStateType::ACTIVE );
1570         if( rGrid.IsSelected( mnColumn ) )
1571             pStateSet->AddState( AccessibleStateType::SELECTED );
1572     }
1573     return pStateSet;
1574 }
1575 
1576 // XInterface -----------------------------------------------------------------
1577 
1578 IMPLEMENT_FORWARD_XINTERFACE2( ScAccessibleCsvCell, ScAccessibleCsvControl, AccessibleStaticTextBase )
1579 
1580 // XTypeProvider --------------------------------------------------------------
1581 
1582 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScAccessibleCsvCell, ScAccessibleCsvControl, AccessibleStaticTextBase )
1583 
1584 // XServiceInfo ---------------------------------------------------------------
1585 
1586 OUString SAL_CALL ScAccessibleCsvCell::getImplementationName() throw( RuntimeException )
1587 {
1588     return CREATE_OUSTRING( CELL_IMPL_NAME );
1589 }
1590 
1591 // helpers --------------------------------------------------------------------
1592 
1593 Rectangle ScAccessibleCsvCell::GetBoundingBoxOnScreen() const throw( RuntimeException )
1594 {
1595     ScUnoGuard aGuard;
1596     ensureAlive();
1597     Rectangle aRect( implGetBoundingBox() );
1598     aRect.SetPos( implGetAbsPos( aRect.TopLeft() ) );
1599     return aRect;
1600 }
1601 
1602 Rectangle ScAccessibleCsvCell::GetBoundingBox() const throw( RuntimeException )
1603 {
1604     ScUnoGuard aGuard;
1605     ensureAlive();
1606     return implGetBoundingBox();
1607 }
1608 
1609 OUString SAL_CALL ScAccessibleCsvCell::createAccessibleName() throw( RuntimeException )
1610 {
1611     return maCellText;
1612 }
1613 
1614 OUString SAL_CALL ScAccessibleCsvCell::createAccessibleDescription() throw( RuntimeException )
1615 {
1616     return OUString();
1617 }
1618 
1619 ScCsvGrid& ScAccessibleCsvCell::implGetGrid() const
1620 {
1621     return static_cast< ScCsvGrid& >( implGetControl() );
1622 }
1623 
1624 Point ScAccessibleCsvCell::implGetRealPos() const
1625 {
1626     ScCsvGrid& rGrid = implGetGrid();
1627     return Point(
1628         (mnColumn == CSV_COLUMN_HEADER) ? rGrid.GetHdrX() : rGrid.GetColumnX( mnColumn ),
1629         (mnLine == CSV_LINE_HEADER) ? 0 : rGrid.GetY( mnLine ) );
1630 }
1631 
1632 sal_uInt32 ScAccessibleCsvCell::implCalcPixelWidth(sal_uInt32 nChars) const
1633 {
1634     ScCsvGrid& rGrid = implGetGrid();
1635     return rGrid.GetCharWidth() * nChars;
1636 }
1637 
1638 Size ScAccessibleCsvCell::implGetRealSize() const
1639 {
1640     ScCsvGrid& rGrid = implGetGrid();
1641     return Size(
1642         (mnColumn == CSV_COLUMN_HEADER) ? rGrid.GetHdrWidth() : implCalcPixelWidth( rGrid.GetColumnWidth( mnColumn ) ),
1643         (mnLine == CSV_LINE_HEADER) ? rGrid.GetHdrHeight() : rGrid.GetLineHeight() );
1644 }
1645 
1646 Rectangle ScAccessibleCsvCell::implGetBoundingBox() const
1647 {
1648     ScCsvGrid& rGrid = implGetGrid();
1649     Rectangle aClipRect( Point( 0, 0 ), rGrid.GetSizePixel() );
1650     if( mnColumn != CSV_COLUMN_HEADER )
1651     {
1652         aClipRect.Left() = rGrid.GetFirstX();
1653         aClipRect.Right() = rGrid.GetLastX();
1654     }
1655     if( mnLine != CSV_LINE_HEADER )
1656          aClipRect.Top() = rGrid.GetHdrHeight();
1657 
1658     Rectangle aRect( implGetRealPos(), implGetRealSize() );
1659     aRect.Intersection( aClipRect );
1660     if( (aRect.GetWidth() <= 0) || (aRect.GetHeight() <= 0) )
1661         aRect.SetSize( Size( -1, -1 ) );
1662     return aRect;
1663 }
1664 
1665 ::std::auto_ptr< SvxEditSource > ScAccessibleCsvCell::implCreateEditSource()
1666 {
1667     ScCsvGrid& rGrid = implGetGrid();
1668     Rectangle aBoundRect( implGetBoundingBox() );
1669     aBoundRect -= implGetRealPos();
1670 
1671     ::std::auto_ptr< ScAccessibleTextData > pCsvTextData( new ScAccessibleCsvTextData(
1672         &rGrid, rGrid.GetEditEngine(), maCellText, aBoundRect, implGetRealSize() ) );
1673 
1674     ::std::auto_ptr< SvxEditSource > pEditSource( new ScAccessibilityEditSource( pCsvTextData ) );
1675     return pEditSource;
1676 }
1677 
1678 
1679 // ============================================================================
1680 
1681