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