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_sc.hxx"
26 
27 
28 #include "AccessibleCell.hxx"
29 #include "scitems.hxx"
30 #include <editeng/eeitem.hxx>
31 
32 
33 #include "AccessibleText.hxx"
34 #include "AccessibleDocument.hxx"
35 #include "tabvwsh.hxx"
36 #include "document.hxx"
37 #include "attrib.hxx"
38 #include "miscuno.hxx"
39 #include "unoguard.hxx"
40 #include "editsrc.hxx"
41 #include "dociter.hxx"
42 #include "cell.hxx"
43 #include "validat.hxx"
44 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
45 #include <unotools/accessiblestatesethelper.hxx>
46 #endif
47 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
48 #include <com/sun/star/accessibility/AccessibleRole.hpp>
49 #endif
50 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
51 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
52 #endif
53 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
54 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
55 #include <rtl/uuid.h>
56 #include <tools/debug.hxx>
57 #include <editeng/brshitem.hxx>
58 #include <comphelper/sequence.hxx>
59 #include <float.h>
60 
61 #include "AccessibleSpreadsheet.hxx"
62 using namespace	::com::sun::star;
63 using namespace	::com::sun::star::accessibility;
64 
65 //=====  internal  ============================================================
66 
67 ScAccessibleCell::ScAccessibleCell(
68         const uno::Reference<XAccessible>& rxParent,
69 		ScTabViewShell* pViewShell,
70 		ScAddress& rCellAddress,
71 		sal_Int32 nIndex,
72 		ScSplitPos eSplitPos,
73         ScAccessibleDocument* pAccDoc)
74 	:
75 	ScAccessibleCellBase(rxParent, GetDocument(pViewShell), rCellAddress, nIndex),
76         ::accessibility::AccessibleStaticTextBase(CreateEditSource(pViewShell, rCellAddress, eSplitPos)),
77 	mpViewShell(pViewShell),
78     mpAccDoc(pAccDoc),
79 	meSplitPos(eSplitPos)
80 {
81 	if (pViewShell)
82 		pViewShell->AddAccessibilityObject(*this);
83 }
84 
85 ScAccessibleCell::~ScAccessibleCell()
86 {
87 	if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
88 	{
89 		// increment refcount to prevent double call off dtor
90 		osl_incrementInterlockedCount( &m_refCount );
91 		// call dispose to inform object wich have a weak reference to this object
92 		dispose();
93 	}
94 }
95 
96 void ScAccessibleCell::Init()
97 {
98     ScAccessibleCellBase::Init();
99 
100     SetEventSource(this);
101 }
102 
103 void SAL_CALL ScAccessibleCell::disposing()
104 {
105     ScUnoGuard aGuard;
106     // #100593# dispose in AccessibleStaticTextBase
107     Dispose();
108 
109 	if (mpViewShell)
110 	{
111 		mpViewShell->RemoveAccessibilityObject(*this);
112 		mpViewShell = NULL;
113 	}
114     mpAccDoc = NULL;
115 
116     ScAccessibleCellBase::disposing();
117 }
118 
119 	//=====  XInterface  =====================================================
120 
121 IMPLEMENT_FORWARD_XINTERFACE3( ScAccessibleCell, ScAccessibleCellBase, AccessibleStaticTextBase, ScAccessibleCellAttributeImpl )
122 
123     //=====  XTypeProvider  ===================================================
124 
125 IMPLEMENT_FORWARD_XTYPEPROVIDER3( ScAccessibleCell, ScAccessibleCellBase, AccessibleStaticTextBase, ScAccessibleCellAttributeImpl )
126 
127 	//=====  XAccessibleComponent  ============================================
128 
129 uno::Reference< XAccessible > SAL_CALL ScAccessibleCell::getAccessibleAtPoint(
130 		const awt::Point& rPoint )
131 		throw (uno::RuntimeException)
132 {
133     return AccessibleStaticTextBase::getAccessibleAtPoint(rPoint);
134 }
135 
136 void SAL_CALL ScAccessibleCell::grabFocus(  )
137 		throw (uno::RuntimeException)
138 {
139  	ScUnoGuard aGuard;
140     IsObjectValid();
141 	if (getAccessibleParent().is() && mpViewShell)
142 	{
143 		uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
144 		if (xAccessibleComponent.is())
145 		{
146 			xAccessibleComponent->grabFocus();
147 			mpViewShell->SetCursor(maCellAddress.Col(), maCellAddress.Row());
148 		}
149 	}
150 }
151 
152 Rectangle ScAccessibleCell::GetBoundingBoxOnScreen(void) const
153 		throw (uno::RuntimeException)
154 {
155 	Rectangle aCellRect(GetBoundingBox());
156 	if (mpViewShell)
157 	{
158 		Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
159 		if (pWindow)
160 		{
161 			Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL);
162 			aCellRect.setX(aCellRect.getX() + aRect.getX());
163 			aCellRect.setY(aCellRect.getY() + aRect.getY());
164 		}
165 	}
166 	return aCellRect;
167 }
168 
169 Rectangle ScAccessibleCell::GetBoundingBox(void) const
170 		throw (uno::RuntimeException)
171 {
172 	Rectangle aCellRect;
173 	if (mpViewShell)
174 	{
175 		long nSizeX, nSizeY;
176 		mpViewShell->GetViewData()->GetMergeSizePixel(
177 			maCellAddress.Col(), maCellAddress.Row(), nSizeX, nSizeY);
178 		aCellRect.SetSize(Size(nSizeX, nSizeY));
179 		aCellRect.SetPos(mpViewShell->GetViewData()->GetScrPos(maCellAddress.Col(), maCellAddress.Row(), meSplitPos, sal_True));
180 
181 		Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
182 		if (pWindow)
183 		{
184 			Rectangle aRect(pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow()));
185 			aRect.Move(-aRect.Left(), -aRect.Top());
186 			aCellRect = aRect.Intersection(aCellRect);
187 		}
188 
189         /*  #i19430# Gnopernicus reads text partly if it sticks out of the cell
190             boundaries. This leads to wrong results in cases where the cell
191             text is rotated, because rotation is not taken into account when
192             calculating the visible part of the text. In these cases we will
193             simply expand the cell size to the width of the unrotated text. */
194         if (mpDoc)
195         {
196             const SfxInt32Item* pItem = static_cast< const SfxInt32Item* >(
197                 mpDoc->GetAttr( maCellAddress.Col(), maCellAddress.Row(), maCellAddress.Tab(), ATTR_ROTATE_VALUE ) );
198             if( pItem && (pItem->GetValue() != 0) )
199             {
200                 Rectangle aParaRect = GetParagraphBoundingBox();
201                 if( !aParaRect.IsEmpty() && (aCellRect.GetWidth() < aParaRect.GetWidth()) )
202                     aCellRect.SetSize( Size( aParaRect.GetWidth(), aCellRect.GetHeight() ) );
203             }
204         }
205 	}
206     if (aCellRect.IsEmpty())
207         aCellRect.SetPos(Point(-1, -1));
208 	return aCellRect;
209 }
210 
211 	//=====  XAccessibleContext  ==============================================
212 
213 sal_Int32 SAL_CALL
214 	ScAccessibleCell::getAccessibleChildCount(void)
215     				throw (uno::RuntimeException)
216 {
217     return AccessibleStaticTextBase::getAccessibleChildCount();
218 }
219 
220 uno::Reference< XAccessible > SAL_CALL
221 	ScAccessibleCell::getAccessibleChild(sal_Int32 nIndex)
222         throw (uno::RuntimeException,
223 		lang::IndexOutOfBoundsException)
224 {
225     return AccessibleStaticTextBase::getAccessibleChild(nIndex);
226 }
227 
228 uno::Reference<XAccessibleStateSet> SAL_CALL
229 	ScAccessibleCell::getAccessibleStateSet(void)
230     throw (uno::RuntimeException)
231 {
232 	ScUnoGuard aGuard;
233 	uno::Reference<XAccessibleStateSet> xParentStates;
234 	if (getAccessibleParent().is())
235 	{
236 		uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
237 		xParentStates = xParentContext->getAccessibleStateSet();
238 	}
239 	utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
240 	if (IsDefunc(xParentStates))
241 		pStateSet->AddState(AccessibleStateType::DEFUNC);
242     else
243     {
244 		if (IsFormulaMode())
245 		{
246 			pStateSet->AddState(AccessibleStateType::ENABLED);
247 		    pStateSet->AddState(AccessibleStateType::MULTI_LINE);
248 			pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
249 			if (IsOpaque(xParentStates))
250 				pStateSet->AddState(AccessibleStateType::OPAQUE);
251 			pStateSet->AddState(AccessibleStateType::SELECTABLE);
252 			if (IsSelected())
253 				pStateSet->AddState(AccessibleStateType::SELECTED);
254 			if (isShowing())
255 				pStateSet->AddState(AccessibleStateType::SHOWING);
256 			pStateSet->AddState(AccessibleStateType::TRANSIENT);
257 			if (isVisible())
258 				pStateSet->AddState(AccessibleStateType::VISIBLE);
259 			return pStateSet;
260 		}
261 	    if (IsEditable(xParentStates))
262 	    {
263 		    pStateSet->AddState(AccessibleStateType::EDITABLE);
264 		    pStateSet->AddState(AccessibleStateType::RESIZABLE);
265 	    }
266 	    pStateSet->AddState(AccessibleStateType::ENABLED);
267 	    pStateSet->AddState(AccessibleStateType::MULTI_LINE);
268 	    pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
269 	    pStateSet->AddState(AccessibleStateType::FOCUSABLE);
270 	    if (IsOpaque(xParentStates))
271 		    pStateSet->AddState(AccessibleStateType::OPAQUE);
272 	    pStateSet->AddState(AccessibleStateType::SELECTABLE);
273 	    if (IsSelected())
274 		    pStateSet->AddState(AccessibleStateType::SELECTED);
275 	    if (isShowing())
276 		    pStateSet->AddState(AccessibleStateType::SHOWING);
277 	    pStateSet->AddState(AccessibleStateType::TRANSIENT);
278 	    if (isVisible())
279 		    pStateSet->AddState(AccessibleStateType::VISIBLE);
280     }
281 	return pStateSet;
282 }
283 
284 uno::Reference<XAccessibleRelationSet> SAL_CALL
285    	ScAccessibleCell::getAccessibleRelationSet(void)
286     throw (uno::RuntimeException)
287 {
288 	ScUnoGuard aGuard;
289     IsObjectValid();
290     utl::AccessibleRelationSetHelper* pRelationSet = NULL;
291     if (mpAccDoc)
292         pRelationSet = mpAccDoc->GetRelationSet(&maCellAddress);
293     if (!pRelationSet)
294 	    pRelationSet = new utl::AccessibleRelationSetHelper();
295 	FillDependends(pRelationSet);
296 	FillPrecedents(pRelationSet);
297 	return pRelationSet;
298 }
299 
300 	//=====  XServiceInfo  ====================================================
301 
302 ::rtl::OUString SAL_CALL ScAccessibleCell::getImplementationName(void)
303         throw (uno::RuntimeException)
304 {
305 	return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleCell"));
306 }
307 
308 uno::Sequence< ::rtl::OUString> SAL_CALL
309 	ScAccessibleCell::getSupportedServiceNames(void)
310         throw (uno::RuntimeException)
311 {
312 	uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
313     sal_Int32 nOldSize(aSequence.getLength());
314     aSequence.realloc(nOldSize + 1);
315     ::rtl::OUString* pNames = aSequence.getArray();
316 
317 	pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.AccessibleCell"));
318 
319 	return aSequence;
320 }
321 
322 	//====  internal  =========================================================
323 
324 sal_Bool ScAccessibleCell::IsDefunc(
325 	const uno::Reference<XAccessibleStateSet>& rxParentStates)
326 {
327 	return ScAccessibleContextBase::IsDefunc() || (mpDoc == NULL) || (mpViewShell == NULL) || !getAccessibleParent().is() ||
328 		 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
329 }
330 
331 sal_Bool ScAccessibleCell::IsEditable(
332 	const uno::Reference<XAccessibleStateSet>& rxParentStates)
333 {
334 	sal_Bool bEditable(sal_True);
335 	if (rxParentStates.is() && !rxParentStates->contains(AccessibleStateType::EDITABLE) &&
336 		mpDoc)
337 	{
338 		// here I have to test whether the protection of the table should influence this cell.
339 		const ScProtectionAttr* pItem = (const ScProtectionAttr*)mpDoc->GetAttr(
340 			maCellAddress.Col(), maCellAddress.Row(),
341 			maCellAddress.Tab(), ATTR_PROTECTION);
342 		if (pItem)
343 			bEditable = !pItem->GetProtection();
344 	}
345 	return bEditable;
346 }
347 
348 sal_Bool ScAccessibleCell::IsOpaque(
349     const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
350 {
351 	// test whether there is a background color
352 	sal_Bool bOpaque(sal_True);
353 	if (mpDoc)
354 	{
355 		const SvxBrushItem* pItem = (const SvxBrushItem*)mpDoc->GetAttr(
356 			maCellAddress.Col(), maCellAddress.Row(),
357 			maCellAddress.Tab(), ATTR_BACKGROUND);
358 		if (pItem)
359 			bOpaque = pItem->GetColor() != COL_TRANSPARENT;
360 	}
361 	return bOpaque;
362 }
363 
364 sal_Bool ScAccessibleCell::IsSelected()
365 {
366 	if (IsFormulaMode())
367 	{
368 		const ScAccessibleSpreadsheet *pSheet =static_cast<const ScAccessibleSpreadsheet*>(mxParent.get());
369 		if (pSheet)
370 		{
371 			return pSheet->IsScAddrFormulaSel(maCellAddress);
372 		}
373 		return sal_False;
374 	}
375 	sal_Bool bResult(sal_False);
376 	if (mpViewShell && mpViewShell->GetViewData())
377 	{
378 		const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
379 		bResult = rMarkdata.IsCellMarked(maCellAddress.Col(), maCellAddress.Row());
380 	}
381 	return bResult;
382 }
383 
384 ScDocument* ScAccessibleCell::GetDocument(ScTabViewShell* pViewShell)
385 {
386 	ScDocument* pDoc = NULL;
387 	if (pViewShell && pViewShell->GetViewData())
388 		pDoc = pViewShell->GetViewData()->GetDocument();
389 	return pDoc;
390 }
391 
392 ::std::auto_ptr< SvxEditSource > ScAccessibleCell::CreateEditSource(ScTabViewShell* pViewShell, ScAddress aCell, ScSplitPos eSplitPos)
393 {
394 	if (IsFormulaMode())
395 	{
396 		return ::std::auto_ptr< SvxEditSource >();
397 	}
398 	::std::auto_ptr < ScAccessibleTextData > pAccessibleCellTextData
399         ( new ScAccessibleCellTextData( pViewShell, aCell, eSplitPos, this ) );
400 	::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleCellTextData));
401 
402     return pEditSource;
403 }
404 
405 void ScAccessibleCell::FillDependends(utl::AccessibleRelationSetHelper* pRelationSet)
406 {
407 	if (mpDoc)
408 	{
409 		ScCellIterator aCellIter( mpDoc, 0,0, maCellAddress.Tab(), MAXCOL,MAXROW, maCellAddress.Tab() );
410 		ScBaseCell* pCell = aCellIter.GetFirst();
411 		while (pCell)
412 		{
413 			if (pCell->GetCellType() == CELLTYPE_FORMULA)
414 			{
415 				sal_Bool bFound(sal_False);
416 				ScDetectiveRefIter aIter( (ScFormulaCell*) pCell );
417                 ScRange aRef;
418 				while ( !bFound && aIter.GetNextRef( aRef ) )
419 				{
420 					if (aRef.In(maCellAddress))
421 						bFound = sal_True;
422 				}
423 				if (bFound)
424 					AddRelation(ScAddress(aCellIter.GetCol(), aCellIter.GetRow(), aCellIter.GetTab()), AccessibleRelationType::CONTROLLER_FOR, pRelationSet);
425 			}
426 			pCell = aCellIter.GetNext();
427 		}
428 	}
429 }
430 
431 void ScAccessibleCell::FillPrecedents(utl::AccessibleRelationSetHelper* pRelationSet)
432 {
433 	if (mpDoc)
434 	{
435 		ScBaseCell* pBaseCell = mpDoc->GetCell(maCellAddress);
436 		if (pBaseCell && (pBaseCell->GetCellType() == CELLTYPE_FORMULA))
437 		{
438 			ScFormulaCell* pFCell = (ScFormulaCell*) pBaseCell;
439 
440 			ScDetectiveRefIter aIter( pFCell );
441             ScRange aRef;
442 			while ( aIter.GetNextRef( aRef ) )
443 			{
444 				AddRelation( aRef, AccessibleRelationType::CONTROLLED_BY, pRelationSet);
445 			}
446 		}
447 	}
448 }
449 
450 void ScAccessibleCell::AddRelation(const ScAddress& rCell,
451 	const sal_uInt16 aRelationType,
452 	utl::AccessibleRelationSetHelper* pRelationSet)
453 {
454 	AddRelation(ScRange(rCell, rCell), aRelationType, pRelationSet);
455 }
456 
457 void ScAccessibleCell::AddRelation(const ScRange& rRange,
458 	const sal_uInt16 aRelationType,
459 	utl::AccessibleRelationSetHelper* pRelationSet)
460 {
461 	uno::Reference < XAccessibleTable > xTable ( getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY );
462 	if (xTable.is())
463 	{
464         sal_uInt32 nCount(static_cast<sal_uInt32>(rRange.aEnd.Col() -
465                     rRange.aStart.Col() + 1) * (rRange.aEnd.Row() -
466                     rRange.aStart.Row() + 1));
467 		uno::Sequence < uno::Reference < uno::XInterface > > aTargetSet( nCount );
468 		uno::Reference < uno::XInterface >* pTargetSet = aTargetSet.getArray();
469 		if (pTargetSet)
470 		{
471 			sal_uInt32 nPos(0);
472             for (sal_uInt32 nRow = rRange.aStart.Row(); nRow <= sal::static_int_cast<sal_uInt32>(rRange.aEnd.Row()); ++nRow)
473 			{
474                 for (sal_uInt32 nCol = rRange.aStart.Col(); nCol <= sal::static_int_cast<sal_uInt32>(rRange.aEnd.Col()); ++nCol)
475 				{
476 					pTargetSet[nPos] = xTable->getAccessibleCellAt(nRow, nCol);
477 					++nPos;
478 				}
479 			}
480 			DBG_ASSERT(nCount == nPos, "something wents wrong");
481 		}
482 		AccessibleRelation aRelation;
483 		aRelation.RelationType = aRelationType;
484 		aRelation.TargetSet = aTargetSet;
485 		pRelationSet->AddRelation(aRelation);
486 	}
487 }
488 ::rtl::OUString ReplaceOneChar(::rtl::OUString oldOUString, ::rtl::OUString replacedChar, ::rtl::OUString replaceStr)
489 {
490 	int iReplace = -1;
491 	iReplace = oldOUString.lastIndexOf(replacedChar);
492 	if (iReplace > -1)
493 	{
494 		for(;iReplace>-1;)
495 		{
496 			oldOUString = oldOUString.replaceAt(iReplace,1, replaceStr);
497 			iReplace=oldOUString.lastIndexOf(replacedChar,iReplace);
498 		}
499 	}
500 	return oldOUString;
501 }
502 ::rtl::OUString ReplaceFourChar(::rtl::OUString oldOUString)
503 {
504 	oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii("\\"),::rtl::OUString::createFromAscii("\\\\"));
505 	oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii(";"),::rtl::OUString::createFromAscii("\\;"));
506 	oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii("="),::rtl::OUString::createFromAscii("\\="));
507 	oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii(","),::rtl::OUString::createFromAscii("\\,"));
508 	oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii(":"),::rtl::OUString::createFromAscii("\\:"));
509 	return oldOUString;
510 }
511 
512 uno::Any SAL_CALL ScAccessibleCell::getExtendedAttributes()
513 		throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
514 {
515 	uno::Any strRet;
516 	if (mpViewShell)
517 	{
518 		const ::rtl::OUString strAttr(::rtl::OUString::createFromAscii(":"));
519 		const ::rtl::OUString strSplit(::rtl::OUString::createFromAscii(";"));
520 		::rtl::OUString strFor = mpViewShell->GetFormula(maCellAddress) ;
521 		strFor = strFor.replaceAt(0,1,::rtl::OUString::createFromAscii(""));
522 		strFor = ReplaceFourChar(strFor);
523 		strFor =::rtl::OUString::createFromAscii("Formula:") + strFor;
524 		strFor +=strSplit;
525 		strFor +=::rtl::OUString::createFromAscii("Note:");
526 		strFor +=ReplaceFourChar(GetAllDisplayNote());
527 		strFor +=strSplit;
528 		strFor += getShadowAttrs();//the string returned contains the spliter ";"
529 		strFor += getBorderAttrs();//the string returned contains the spliter ";"
530 		//end of cell attributes
531 		if( mpDoc )
532 		{
533 			strFor += ::rtl::OUString::createFromAscii("isdropdown:");
534 			if( IsDropdown() )
535 				strFor+= ::rtl::OUString::createFromAscii("true");
536 			else
537 				strFor+= ::rtl::OUString::createFromAscii("false");
538 			strFor += ::rtl::OUString::createFromAscii(";");
539 		}
540 		strRet <<= strFor ;
541 	}
542 	return strRet;
543 }
544 
545 // cell has its own ParaIndent property, so when calling character attributes on cell, the ParaIndent should replace the ParaLeftMargin if its value is not zero.
546 uno::Sequence< beans::PropertyValue > SAL_CALL ScAccessibleCell::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
547 {
548 	uno::Sequence< beans::PropertyValue > aAttribs = AccessibleStaticTextBase::getCharacterAttributes( nIndex, aRequestedAttributes );
549 	beans::PropertyValue *pAttribs = aAttribs.getArray();
550 
551 	sal_uInt16 nParaIndent = static_cast< const SfxUInt16Item* >( mpDoc->GetAttr( maCellAddress.Col(), maCellAddress.Row(), maCellAddress.Tab(), ATTR_INDENT ) )->GetValue();
552 	if (nParaIndent > 0)
553 	{
554 		::rtl::OUString sLeftMarginName (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParaLeftMargin")));
555 		for (int i = 0; i < aAttribs.getLength(); ++i)
556 		{
557 			if (sLeftMarginName == pAttribs[i].Name)
558 			{
559 				pAttribs[i].Value = uno::makeAny( nParaIndent );
560 				break;
561 			}
562 		}
563 	}
564 	return aAttribs;
565 }
566 
567 sal_Bool ScAccessibleCell::IsFormulaMode()
568 {
569 	ScAccessibleSpreadsheet* pSheet =static_cast<ScAccessibleSpreadsheet*>(mxParent.get());
570 	if (pSheet)
571 	{
572 		return pSheet->IsFormulaMode();
573 	}
574 	return sal_False;
575 }
576 sal_Bool ScAccessibleCell::IsDropdown()
577 {
578 	sal_uInt16 nPosX = maCellAddress.Col();
579 	sal_uInt16 nPosY = sal_uInt16(maCellAddress.Row());
580 	sal_uInt16 nTab = maCellAddress.Tab();
581 	sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( mpDoc->GetAttr( nPosX, nPosY, nTab, ATTR_VALIDDATA ) )->GetValue();
582     if( nValidation )
583     {
584         const ScValidationData* pData = mpDoc->GetValidationEntry( nValidation );
585         if( pData && pData->HasSelectionList() )
586             return sal_True;
587     }
588 	ScMergeFlagAttr* pAttr;
589 	pAttr = (ScMergeFlagAttr*)mpDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG );
590 	if( pAttr->HasAutoFilter() )
591 	{
592 		return sal_True;
593 	}
594 	else
595 	{
596 		sal_uInt16 nTabCount = mpDoc->GetTableCount();
597 		if ( nTab+1<nTabCount && mpDoc->IsScenario(nTab+1) && !mpDoc->IsScenario(nTab) )
598 		{
599 			sal_uInt16 i;
600 			ScMarkData aMarks;
601 			for (i=nTab+1; i<nTabCount && mpDoc->IsScenario(i); i++)
602 				mpDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME );
603 			ScRangeList aRanges;
604 			aMarks.FillRangeListWithMarks( &aRanges, sal_False );
605 			sal_Bool bHasScenario;
606 			sal_uInt16 nRangeCount = (sal_uInt16)aRanges.Count();
607 			for (i=0; i<nRangeCount; i++)
608 			{
609 				ScRange aRange = *aRanges.GetObject(i);
610 				mpDoc->ExtendTotalMerge( aRange );
611 				sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 );
612 				// MT IA2: Not used: sal_Bool bIsInScen = sal_False;
613 				if ( bTextBelow )
614 				{
615 					bHasScenario = (aRange.aStart.Col() == nPosX && aRange.aEnd.Row() == nPosY-1);
616 				}
617 				else
618 				{
619 					bHasScenario = (aRange.aStart.Col() == nPosX && aRange.aStart.Row() == nPosY+1);
620 				}
621 				if( bHasScenario ) return sal_True;
622 			}
623 		}
624 	}
625 	return sal_False;
626 }
627