/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

//------------------------------------------------------------------

#include "scitems.hxx"

#include <svl/slstitm.hxx>
#include <svl/stritem.hxx>
#include <svl/whiter.hxx>
#include <unotools/moduleoptions.hxx>
#include <svtools/cliplistener.hxx>
#include <svtools/insdlg.hxx>
#include <sot/formats.hxx>
#include <svx/hlnkitem.hxx>
#include <sfx2/app.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/childwin.hxx>
#include <sfx2/objface.hxx>
#include <sfx2/request.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/sidebar/EnumContext.hxx>
#include <svx/clipfmtitem.hxx>
#include <svx/sidebar/ContextChangeEventMultiplexer.hxx>
#include <editeng/langitem.hxx>

#include "cellsh.hxx"
#include "sc.hrc"
#include "docsh.hxx"
#include "attrib.hxx"
#include "scresid.hxx"
#include "tabvwsh.hxx"
#include "impex.hxx"
#include "cell.hxx"
#include "scmod.hxx"
#include "globstr.hrc"
#include "transobj.hxx"
#include "drwtrans.hxx"
#include "scabstdlg.hxx"
#include "dociter.hxx"
#include "postit.hxx"

//------------------------------------------------------------------

#define ScCellShell
#define	CellMovement
#include "scslots.hxx"

TYPEINIT1( ScCellShell, ScFormatShell );

SFX_IMPL_INTERFACE(ScCellShell, ScFormatShell , ScResId(SCSTR_CELLSHELL) )
{
	SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_OBJECT | SFX_VISIBILITY_STANDARD |
								SFX_VISIBILITY_SERVER,
								ScResId(RID_OBJECTBAR_FORMAT));
	SFX_POPUPMENU_REGISTRATION(ScResId(RID_POPUP_CELLS));
}


ScCellShell::ScCellShell(ScViewData* pData) :
	ScFormatShell(pData),
    pImpl( new CellShell_Impl() ),
	bPastePossible(sal_False)
{
	SetHelpId(HID_SCSHELL_CELLSH);
	SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Cell")));
    SfxShell::SetContextName(sfx2::sidebar::EnumContext::GetContextName(sfx2::sidebar::EnumContext::Context_Cell));
}

ScCellShell::~ScCellShell()
{
    if ( pImpl->m_pClipEvtLstnr )
	{
        pImpl->m_pClipEvtLstnr->AddRemoveListener( GetViewData()->GetActiveWin(), sal_False );

		//  #103849# The listener may just now be waiting for the SolarMutex and call the link
		//  afterwards, in spite of RemoveListener. So the link has to be reset, too.
        pImpl->m_pClipEvtLstnr->ClearCallbackLink();

        pImpl->m_pClipEvtLstnr->release();
	}

    delete pImpl->m_pLinkedDlg;
    delete pImpl->m_pRequest;
    delete pImpl;
}

//------------------------------------------------------------------

void ScCellShell::GetBlockState( SfxItemSet& rSet )
{
	ScTabViewShell*	pTabViewShell  	= GetViewData()->GetViewShell();
	ScRange aMarkRange;
    ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange );
	sal_Bool bSimpleArea = (eMarkType == SC_MARK_SIMPLE);
	sal_Bool bOnlyNotBecauseOfMatrix;
	sal_Bool bEditable = pTabViewShell->SelectionEditable( &bOnlyNotBecauseOfMatrix );
	ScDocument* pDoc = GetViewData()->GetDocument();
    ScDocShell* pDocShell = GetViewData()->GetDocShell();
    ScMarkData& rMark = GetViewData()->GetMarkData();
	SCCOL nCol1, nCol2;
	SCROW nRow1, nRow2;
	nCol1 = aMarkRange.aStart.Col();
	nRow1 = aMarkRange.aStart.Row();
	nCol2 = aMarkRange.aEnd.Col();
	nRow2 = aMarkRange.aEnd.Row();

	SfxWhichIter aIter(rSet);
	sal_uInt16 nWhich = aIter.FirstWhich();
	while ( nWhich )
	{
		sal_Bool bDisable = sal_False;
		sal_Bool bNeedEdit = sal_True;		// muss Selektion editierbar sein?
		switch ( nWhich )
		{
			case FID_FILL_TO_BOTTOM:	// Fuellen oben/unten
			case FID_FILL_TO_TOP:		// mind. 2 Zeilen markiert?
				bDisable = (!bSimpleArea) || (nRow1 == nRow2);
				if ( !bDisable && bEditable )
				{	// Matrix nicht zerreissen
					if ( nWhich == FID_FILL_TO_BOTTOM )
						bDisable = pDoc->HasSelectedBlockMatrixFragment(
							nCol1, nRow1, nCol2, nRow1, rMark );	// erste Zeile
					else
						bDisable = pDoc->HasSelectedBlockMatrixFragment(
							nCol1, nRow2, nCol2, nRow2, rMark );	// letzte Zeile
				}
				break;

			case FID_FILL_TO_RIGHT:		// Fuellen links/rechts
			case FID_FILL_TO_LEFT:		// mind. 2 Spalten markiert?
				bDisable = (!bSimpleArea) || (nCol1 == nCol2);
				if ( !bDisable && bEditable )
				{	// Matrix nicht zerreissen
					if ( nWhich == FID_FILL_TO_RIGHT )
						bDisable = pDoc->HasSelectedBlockMatrixFragment(
							nCol1, nRow1, nCol1, nRow2, rMark );	// erste Spalte
					else
						bDisable = pDoc->HasSelectedBlockMatrixFragment(
							nCol2, nRow1, nCol2, nRow2, rMark );	// letzte Spalte
				}
				break;

			case FID_FILL_SERIES:		// Block fuellen
			case SID_OPENDLG_TABOP:		// Mehrfachoperationen, mind. 2 Zellen markiert?
				if (pDoc->GetChangeTrack()!=NULL &&nWhich ==SID_OPENDLG_TABOP)
					bDisable = sal_True;
				else
					bDisable = (!bSimpleArea) || (nCol1 == nCol2 && nRow1 == nRow2);

				if ( !bDisable && bEditable && nWhich == FID_FILL_SERIES )
				{	// Matrix nicht zerreissen
					bDisable = pDoc->HasSelectedBlockMatrixFragment(
							nCol1, nRow1, nCol2, nRow1, rMark )	// erste Zeile
						||	pDoc->HasSelectedBlockMatrixFragment(
							nCol1, nRow2, nCol2, nRow2, rMark )	// letzte Zeile
						||	pDoc->HasSelectedBlockMatrixFragment(
							nCol1, nRow1, nCol1, nRow2, rMark )	// erste Spalte
						||	pDoc->HasSelectedBlockMatrixFragment(
							nCol2, nRow1, nCol2, nRow2, rMark );	// letzte Spalte
				}
				break;

			case SID_CUT:				// Ausschneiden,
			case FID_INS_CELL:			// Zellen einfuegen, nur einf. Selektion
				bDisable = (!bSimpleArea);
				break;

            case FID_INS_ROW:           // insert rows
            case FID_INS_CELLSDOWN:
                bDisable = (!bSimpleArea) || GetViewData()->SimpleColMarked();
                break;

            case FID_INS_COLUMN:        // insert columns
            case FID_INS_CELLSRIGHT:
                bDisable = (!bSimpleArea) || GetViewData()->SimpleRowMarked();
                break;

			case SID_COPY:						// Kopieren
				// nur wegen Matrix nicht editierbar? Matrix nicht zerreissen
				//! schlaegt nicht zu, wenn geschuetzt UND Matrix, aber damit
				//! muss man leben.. wird in Copy-Routine abgefangen, sonst
				//! muesste hier nochmal Aufwand getrieben werden
				if ( !(!bEditable && bOnlyNotBecauseOfMatrix) )
					bNeedEdit = sal_False;			// erlaubt, wenn geschuetzt/ReadOnly
				break;

			case SID_AUTOFORMAT:		// Autoformat, mind. 3x3 selektiert
				bDisable =    (!bSimpleArea)
						   || ((nCol2 - nCol1) < 2) || ((nRow2 - nRow1) < 2);
				break;

			case SID_OPENDLG_CONDFRMT :
                {
                    if ( !bEditable && bOnlyNotBecauseOfMatrix )
                    {
                        bNeedEdit = sal_False;
                    }
                    if ( pDocShell && pDocShell->IsDocShared() )
                    {
                        bDisable = sal_True;
                    }
                }
                break;

			case FID_CONDITIONAL_FORMAT :
			case SID_CELL_FORMAT_RESET :
			case FID_CELL_FORMAT :
			case SID_ENABLE_HYPHENATION :
				// nur wegen Matrix nicht editierbar? Attribute trotzdem ok
				if ( !bEditable && bOnlyNotBecauseOfMatrix )
					bNeedEdit = sal_False;
				break;

            case FID_VALIDATION:
                {
                    if ( pDocShell && pDocShell->IsDocShared() )
                    {
                        bDisable = sal_True;
                    }
                }
                break;

			case SID_TRANSLITERATE_HALFWIDTH:
			case SID_TRANSLITERATE_FULLWIDTH:
			case SID_TRANSLITERATE_HIRAGANA:
			case SID_TRANSLITERATE_KATAGANA:
                ScViewUtil::HideDisabledSlot( rSet, GetViewData()->GetBindings(), nWhich );
            break;
		}
		if (!bDisable && bNeedEdit && !bEditable)
			bDisable = sal_True;

		if (bDisable)
			rSet.DisableItem(nWhich);
		else if (nWhich == SID_ENABLE_HYPHENATION)
		{
			// toggle slots need a bool item
			rSet.Put( SfxBoolItem( nWhich, sal_False ) );
		}
		nWhich = aIter.NextWhich();
	}
}

//	Funktionen, die je nach Cursorposition disabled sind
//	Default:
//		SID_INSERT_POSTIT, SID_CHARMAP, SID_OPENDLG_FUNCTION

void ScCellShell::GetCellState( SfxItemSet& rSet )
{
    ScDocShell* pDocShell = GetViewData()->GetDocShell();
	ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument();
	ScAddress aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
						GetViewData()->GetTabNo() );

	SfxWhichIter aIter(rSet);
	sal_uInt16 nWhich = aIter.FirstWhich();
	while ( nWhich )
	{
		sal_Bool bDisable = sal_False;
		sal_Bool bNeedEdit = sal_True;		// muss Cursorposition editierbar sein?
		switch ( nWhich )
		{
            case SID_THESAURUS:
				{
					CellType eType = pDoc->GetCellType( aCursor );
					bDisable = ( eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT);
					if (!bDisable)
					{
						//	test for available languages
						sal_uInt16 nLang = ScViewUtil::GetEffLanguage( pDoc, aCursor );
						bDisable = !ScModule::HasThesaurusLanguage( nLang );
					}
				}
				break;
			case SID_OPENDLG_FUNCTION:
				{
					ScMarkData aMarkData=GetViewData()->GetMarkData();
					aMarkData.MarkToSimple();
					ScRange aRange;
					aMarkData.GetMarkArea(aRange);
					if(aMarkData.IsMarked())
					{
						if (!pDoc->IsBlockEditable( aCursor.Tab(), aRange.aStart.Col(),aRange.aStart.Row(),
											aRange.aEnd.Col(),aRange.aEnd.Row() ))
						{
							bDisable = sal_True;
						}
						bNeedEdit=sal_False;
					}

				}
				break;
            case SID_INSERT_POSTIT:
                {
                    if ( pDocShell && pDocShell->IsDocShared() )
                    {
                        bDisable = sal_True;
                    }
                }
                break;
		}
		if (!bDisable && bNeedEdit)
			if (!pDoc->IsBlockEditable( aCursor.Tab(), aCursor.Col(),aCursor.Row(),
										aCursor.Col(),aCursor.Row() ))
				bDisable = sal_True;
		if (bDisable)
			rSet.DisableItem(nWhich);
		nWhich = aIter.NextWhich();
	}
}

sal_Bool lcl_TestFormat( SvxClipboardFmtItem& rFormats, const TransferableDataHelper& rDataHelper,
						SotFormatStringId nFormatId )
{
	if ( rDataHelper.HasFormat( nFormatId ) )
	{
		//	#90675# translated format name strings are no longer inserted here,
		//	handled by "paste special" dialog / toolbox controller instead.
		//	Only the object type name has to be set here:
		String aStrVal;
		if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE )
		{
			TransferableObjectDescriptor aDesc;
			if ( ((TransferableDataHelper&)rDataHelper).GetTransferableObjectDescriptor(
										SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aDesc ) )
				aStrVal = aDesc.maTypeName;
		}
		else if ( nFormatId == SOT_FORMATSTR_ID_EMBED_SOURCE_OLE
		  || nFormatId == SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE )
		{
			String aSource;
            SvPasteObjectHelper::GetEmbeddedName( rDataHelper, aStrVal, aSource, nFormatId );
		}

		if ( aStrVal.Len() )
			rFormats.AddClipbrdFormat( nFormatId, aStrVal );
		else
			rFormats.AddClipbrdFormat( nFormatId );

		return sal_True;
	}

	return sal_False;
}

void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFmtItem& rFormats )
{
	Window* pWin = GetViewData()->GetActiveWin();
	sal_Bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != NULL );

	TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );

	lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_DRAWING );
	lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_SVXB );
	lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_GDIMETAFILE );
	lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_BITMAP );
	lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBED_SOURCE );

	if ( !bDraw )
	{
		lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_LINK );
		lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_STRING );
		lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_DIF );
		lcl_TestFormat( rFormats, aDataHelper, SOT_FORMAT_RTF );
		lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_HTML );
		lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_HTML_SIMPLE );
        lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_BIFF_8 );
		lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_BIFF_5 );
	}

	if ( !lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) )
		lcl_TestFormat( rFormats, aDataHelper, SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE );
}

//	Einfuegen, Inhalte einfuegen

sal_Bool lcl_IsCellPastePossible( const TransferableDataHelper& rData )
{
	sal_Bool bPossible = sal_False;
	if ( ScTransferObj::GetOwnClipboard( NULL ) || ScDrawTransferObj::GetOwnClipboard( NULL ) )
		bPossible = sal_True;
	else
	{
		if ( rData.HasFormat( SOT_FORMAT_BITMAP ) ||
			 rData.HasFormat( SOT_FORMAT_GDIMETAFILE ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_SVXB ) ||
			 rData.HasFormat( FORMAT_PRIVATE ) ||
			 rData.HasFormat( SOT_FORMAT_RTF ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ||
			 rData.HasFormat( SOT_FORMAT_STRING ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_SYLK ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_LINK ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_HTML ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) ||
			 rData.HasFormat( SOT_FORMATSTR_ID_DIF ) )
		{
			bPossible = sal_True;
		}
	}
	return bPossible;
}

IMPL_LINK( ScCellShell, ClipboardChanged, TransferableDataHelper*, pDataHelper )
{
	if ( pDataHelper )
	{
		bPastePossible = lcl_IsCellPastePossible( *pDataHelper );

		SfxBindings& rBindings = GetViewData()->GetBindings();
		rBindings.Invalidate( SID_PASTE );
        rBindings.Invalidate( SID_PASTE_SPECIAL );
		rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
	}
	return 0;
}


void __EXPORT ScCellShell::GetClipState( SfxItemSet& rSet )
{
// SID_PASTE
// SID_PASTE_SPECIAL
// SID_CLIPBOARD_FORMAT_ITEMS

    if ( !pImpl->m_pClipEvtLstnr )
	{
		// create listener
        pImpl->m_pClipEvtLstnr = new TransferableClipboardListener( LINK( this, ScCellShell, ClipboardChanged ) );
        pImpl->m_pClipEvtLstnr->acquire();
		Window* pWin = GetViewData()->GetActiveWin();
        pImpl->m_pClipEvtLstnr->AddRemoveListener( pWin, sal_True );

		// get initial state
		TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
		bPastePossible = lcl_IsCellPastePossible( aDataHelper );
	}

	sal_Bool bDisable = !bPastePossible;

	//	Zellschutz / Multiselektion

	if (!bDisable)
	{
		SCCOL nCol = GetViewData()->GetCurX();
		SCROW nRow = GetViewData()->GetCurY();
		SCTAB nTab = GetViewData()->GetTabNo();
		ScDocument* pDoc = GetViewData()->GetDocShell()->GetDocument();
		if (!pDoc->IsBlockEditable( nTab, nCol,nRow, nCol,nRow ))
			bDisable = sal_True;
        ScRange aDummy;
        ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy);
        if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
			bDisable = sal_True;
	}

	if (bDisable)
	{
		rSet.DisableItem( SID_PASTE );
        rSet.DisableItem( SID_PASTE_SPECIAL );
		rSet.DisableItem( SID_CLIPBOARD_FORMAT_ITEMS );
	}
	else if ( rSet.GetItemState( SID_CLIPBOARD_FORMAT_ITEMS ) != SFX_ITEM_UNKNOWN )
	{
		SvxClipboardFmtItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
		GetPossibleClipboardFormats( aFormats );
		rSet.Put( aFormats );
	}
}

//	only SID_HYPERLINK_GETLINK:

void ScCellShell::GetHLinkState( SfxItemSet& rSet )
{
	//	always return an item (or inserting will be disabled)
	//	if the cell at the cursor contains only a link, return that link

	SvxHyperlinkItem aHLinkItem;
	if ( !GetViewData()->GetView()->HasBookmarkAtCursor( &aHLinkItem ) )
	{
		//!	put selected text into item?
	}

	rSet.Put(aHLinkItem);
}

void ScCellShell::GetState(SfxItemSet &rSet)
{
	// removed: SID_BORDER_OBJECT (old Basic)

	ScTabViewShell*	pTabViewShell  	= GetViewData()->GetViewShell();
//     sal_Bool bOle = pTabViewShell->GetViewFrame()->GetFrame().IsInPlace();
// 	sal_Bool bTabProt = GetViewData()->GetDocument()->IsTabProtected(GetViewData()->GetTabNo());
	ScDocShell* pDocSh = GetViewData()->GetDocShell();
    ScViewData* pData       = GetViewData();
	ScDocument* pDoc		= pData->GetDocument();
	ScMarkData& rMark		= pData->GetMarkData();
	SCCOL		nPosX		= pData->GetCurX();
	SCROW		nPosY		= pData->GetCurY();
	SCTAB		nTab		= pData->GetTabNo();

	SCTAB nTabCount = pDoc->GetTableCount();
	SCTAB nTabSelCount = rMark.GetSelectCount();



	SfxWhichIter aIter(rSet);
	sal_uInt16 nWhich = aIter.FirstWhich();
	while ( nWhich )
	{
		switch ( nWhich )
		{
			case SID_DETECTIVE_REFRESH:
				if (!pDoc->HasDetectiveOperations())
					rSet.DisableItem( nWhich );
				break;

			case SID_RANGE_ADDRESS:
				{
					ScRange aRange;
					if ( pData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
					{
						String aStr;
						sal_uInt16 nFlags = SCA_VALID | SCA_TAB_3D;
						aRange.Format(aStr,nFlags,pDoc);
						rSet.Put( SfxStringItem( nWhich, aStr ) );
					}
				}
				break;

			case SID_RANGE_NOTETEXT:
				{
					//	#43343# always take cursor position, do not use top-left cell of selection
					ScAddress aPos( nPosX, nPosY, nTab );
					String aNoteText;
					if ( const ScPostIt* pNote = pDoc->GetNote( aPos ) )
                        aNoteText = pNote->GetText();
					rSet.Put( SfxStringItem( nWhich, aNoteText ) );
				}
				break;

			case SID_RANGE_ROW:
				rSet.Put( SfxInt32Item( nWhich, nPosY+1 ) );
				break;

			case SID_RANGE_COL:
				rSet.Put( SfxInt16Item( nWhich, nPosX+1 ) );
				break;

			case SID_RANGE_TABLE:
				rSet.Put( SfxInt16Item( nWhich, nTab+1 ) );
				break;

			case SID_RANGE_VALUE:
				{
					double nValue;
					pDoc->GetValue( nPosX, nPosY, nTab, nValue );
					rSet.Put( ScDoubleItem( nWhich, nValue ) );
				}
				break;

			case SID_RANGE_FORMULA:
				{
					String aString;
					pDoc->GetFormula( nPosX, nPosY, nTab, aString );
					if( aString.Len() == 0 )
					{
						pDoc->GetInputString( nPosX, nPosY, nTab, aString );
					}
					rSet.Put( SfxStringItem( nWhich, aString ) );
				}
				break;

			case SID_RANGE_TEXTVALUE:
				{
					String aString;
					pDoc->GetString( nPosX, nPosY, nTab, aString );
					rSet.Put( SfxStringItem( nWhich, aString ) );
				}
				break;

			case SID_STATUS_SELMODE:
				{
					/* 0: STD	Click hebt Sel auf
					 * 1: ER	Click erweitert Selektion
					 * 2: ERG	Click definiert weitere Selektion
					 */
					sal_uInt16 nMode = pTabViewShell->GetLockedModifiers();

					switch ( nMode )
					{
						case KEY_SHIFT: nMode = 1;	break;
						case KEY_MOD1:	nMode = 2;	break; // Control-Taste
						case 0:
						default:
							nMode = 0;
					}

					rSet.Put( SfxUInt16Item( nWhich, nMode ) );
				}
				break;

			case SID_STATUS_DOCPOS:
				{
					String	aStr( ScGlobal::GetRscString( STR_TABLE ) );

					aStr += ' ';
					aStr += String::CreateFromInt32( nTab + 1 );
					aStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " / " ));
					aStr += String::CreateFromInt32( nTabCount );
					rSet.Put( SfxStringItem( nWhich, aStr ) );
				}
				break;

			//	Summe etc. mit Datum/Zeit/Fehler/Pos&Groesse zusammengefasst

            // #i34458# The SfxStringItem belongs only into SID_TABLE_CELL. It no longer has to be
            // duplicated in SID_ATTR_POSITION or SID_ATTR_SIZE for SvxPosSizeStatusBarControl.
			case SID_TABLE_CELL:
				{
					//	Testen, ob Fehler unter Cursor
					//	(nicht pDoc->GetErrCode, um keine zirkulaeren Referenzen auszuloesen)

					// In interpreter may happen via rescheduled Basic
					if ( pDoc->IsInInterpreter() )
						rSet.Put( SfxStringItem( nWhich,
							String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("...")) ) );
					else
					{
						sal_uInt16 nErrCode = 0;
						ScBaseCell* pCell;
						pDoc->GetCell( nPosX, nPosY, nTab, pCell );
						if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
						{
							ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
							if (!pFCell->IsRunning())
								nErrCode = pFCell->GetErrCode();
						}

                        String aFuncStr;
                        if ( pTabViewShell->GetFunction( aFuncStr, nErrCode ) )
                            rSet.Put( SfxStringItem( nWhich, aFuncStr ) );
					}
				}
				break;

			case SID_DATA_SELECT:
                // HasSelectionData includes column content and validity,
                // page fields have to be checked separately.
                if ( !pDoc->HasSelectionData( nPosX, nPosY, nTab ) &&
                     !pTabViewShell->HasPageFieldDataAtCursor() )
					rSet.DisableItem( nWhich );
				break;

			case SID_STATUS_SUM:
				{
					String aFuncStr;
					if ( pTabViewShell->GetFunction( aFuncStr ) )
						rSet.Put( SfxStringItem( nWhich, aFuncStr ) );
				}
				break;

			case FID_MERGE_ON:
				if ( pDoc->GetChangeTrack() || !pTabViewShell->TestMergeCells() )
					rSet.DisableItem( nWhich );
				break;

			case FID_MERGE_OFF:
				if ( pDoc->GetChangeTrack() || !pTabViewShell->TestRemoveMerge() )
					rSet.DisableItem( nWhich );
				break;

            case FID_MERGE_TOGGLE:
                if ( pDoc->GetChangeTrack() )
                    rSet.DisableItem( nWhich );
                else
                {
                    bool bCanMerge = pTabViewShell->TestMergeCells();
                    bool bCanSplit = pTabViewShell->TestRemoveMerge();
                    if( !bCanMerge && !bCanSplit )
                        rSet.DisableItem( nWhich );
                    else
                        rSet.Put( SfxBoolItem( nWhich, bCanSplit ) );
                }
                break;

			case FID_INS_ROWBRK:
                if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) )
					rSet.DisableItem( nWhich );
				break;

			case FID_INS_COLBRK:
                if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) )
					rSet.DisableItem( nWhich );
				break;

			case FID_DEL_ROWBRK:
                if ( nPosY==0 || (pDoc->HasRowBreak(nPosY, nTab) & BREAK_MANUAL) == 0 )
					rSet.DisableItem( nWhich );
				break;

			case FID_DEL_COLBRK:
                if ( nPosX==0 || (pDoc->HasColBreak(nPosX, nTab) & BREAK_MANUAL) == 0 )
					rSet.DisableItem( nWhich );
				break;

			case FID_FILL_TAB:
				if ( nTabSelCount < 2 )
					rSet.DisableItem( nWhich );
				break;

			case SID_SELECT_SCENARIO:
				{
                    // ScDocument* pDoc = GetViewData()->GetDocument();
                    // SCTAB       nTab = GetViewData()->GetTabNo();
					List		aList;

					Color	aDummyCol;

					if ( !pDoc->IsScenario(nTab) )
					{
						String aStr;
						sal_uInt16 nFlags;
						SCTAB nScTab = nTab + 1;
						String aProtect;
						bool bSheetProtected = pDoc->IsTabProtected(nTab);

						while ( pDoc->IsScenario(nScTab) )
						{
							pDoc->GetName( nScTab, aStr );
							aList.Insert( new String( aStr ), LIST_APPEND );
							pDoc->GetScenarioData( nScTab, aStr, aDummyCol, nFlags );
							aList.Insert( new String( aStr ), LIST_APPEND );
							// Protection is sal_True if both Sheet and Scenario are protected
							aProtect = (bSheetProtected && (nFlags & SC_SCENARIO_PROTECT)) ? '1' : '0';
							aList.Insert( new String( aProtect), LIST_APPEND );
							++nScTab;
						}
					}
					else
					{
						String	aComment;
						sal_uInt16	nDummyFlags;
						pDoc->GetScenarioData( nTab, aComment, aDummyCol, nDummyFlags );
						DBG_ASSERT( aList.Count() == 0, "List not empty!" );
						aList.Insert( new String( aComment ) );
					}

					rSet.Put( SfxStringListItem( nWhich, &aList ) );

					sal_uLong nCount = aList.Count();
					for ( sal_uLong i=0; i<nCount; i++ )
						delete (String*) aList.GetObject(i);
				}
				break;

			case FID_ROW_HIDE:
			case FID_ROW_SHOW:
			case FID_COL_HIDE:
			case FID_COL_SHOW:
			case FID_COL_OPT_WIDTH:
			case FID_ROW_OPT_HEIGHT:
			case FID_DELETE_CELL:
				if ( pDoc->IsTabProtected(nTab) || pDocSh->IsReadOnly())
					rSet.DisableItem( nWhich );
				break;

/*	Zellschutz bei selektierten Zellen wird bei anderen Funktionen auch nicht abgefragt...
			case SID_DELETE:
				{
					if ( pDoc->IsTabProtected(nTab) )
					{
						const SfxItemSet&		rAttrSet  = GetSelectionPattern()->GetItemSet();
						const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&)rAttrSet.Get( ATTR_PROTECTION, sal_True );
						if ( rProtAttr.GetProtection() )
							rSet.DisableItem( nWhich );
					}
				}
				break;
*/
			case SID_OUTLINE_MAKE:
				{
    				if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
                							GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
                    {
                        //! test for data pilot operation
                    }
					else if (pDoc->GetChangeTrack()!=NULL || GetViewData()->IsMultiMarked())
					{
						rSet.DisableItem( nWhich );
					}
				}
				break;
			case SID_OUTLINE_SHOW:
				if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
            							GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
                {
                    //! test for data pilot operation
                }
				else if (!pTabViewShell->OutlinePossible(sal_False))
					rSet.DisableItem( nWhich );
				break;

			case SID_OUTLINE_HIDE:
				if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
            							GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
                {
                    //! test for data pilot operation
                }
				else if (!pTabViewShell->OutlinePossible(sal_True))
					rSet.DisableItem( nWhich );
				break;

			case SID_OUTLINE_REMOVE:
				{
    				if ( GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
                							GetViewData()->GetCurY(), GetViewData()->GetTabNo() ) )
                    {
                        //! test for data pilot operation
                    }
                    else
                    {
    					sal_Bool bCol, bRow;
    					pTabViewShell->TestRemoveOutline( bCol, bRow );
    					if ( !bCol && !bRow )
    						rSet.DisableItem( nWhich );
                    }
				}
				break;

			case FID_COL_WIDTH:
				{
					//GetViewData()->GetCurX();
					SfxUInt16Item aWidthItem( FID_COL_WIDTH, pDoc->GetColWidth( nPosX , nTab) );
					rSet.Put( aWidthItem );
					if ( pDocSh->IsReadOnly())
						rSet.DisableItem( nWhich );

					//XXX Disablen wenn nicht eindeutig
				}
				break;

			case FID_ROW_HEIGHT:
				{
					//GetViewData()->GetCurY();
					SfxUInt16Item aHeightItem( FID_ROW_HEIGHT, pDoc->GetRowHeight( nPosY , nTab) );
					rSet.Put( aHeightItem );
					//XXX Disablen wenn nicht eindeutig
					if ( pDocSh->IsReadOnly())
						rSet.DisableItem( nWhich );
				}
				break;

			case SID_DETECTIVE_FILLMODE:
				rSet.Put(SfxBoolItem( nWhich, pTabViewShell->IsAuditShell() ));
				break;

			case FID_INPUTLINE_STATUS:
				DBG_ERROR( "Old update method. Use ScTabViewShell::UpdateInputHandler()." );
				break;

			case SID_SCENARIOS:										// Szenarios:
				if (!(rMark.IsMarked() || rMark.IsMultiMarked()))	// nur, wenn etwas selektiert
					rSet.DisableItem( nWhich );
				break;

			case FID_NOTE_VISIBLE:
				{
                    const ScPostIt* pNote = pDoc->GetNote( ScAddress( nPosX, nPosY, nTab ) );
					if ( pNote && pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) )
						rSet.Put( SfxBoolItem( nWhich, pNote->IsCaptionShown() ) );
					else
						rSet.DisableItem( nWhich );
				}
				break;

            case SID_DELETE_NOTE:
                {
                    sal_Bool bEnable = sal_False;
                    if ( rMark.IsMarked() || rMark.IsMultiMarked() )
                    {
                        if ( pDoc->IsSelectionEditable( rMark ) )
                        {
                            // look for at least one note in selection
                            ScRangeList aRanges;
                            rMark.FillRangeListWithMarks( &aRanges, sal_False );
                            sal_uLong nCount = aRanges.Count();
                            for (sal_uLong nPos=0; nPos<nCount && !bEnable; nPos++)
                            {
                                ScCellIterator aCellIter( pDoc, *aRanges.GetObject(nPos) );
                                for( ScBaseCell* pCell = aCellIter.GetFirst(); pCell && !bEnable; pCell = aCellIter.GetNext() )
                                    if ( pCell->HasNote() )
                                        bEnable = sal_True;             // note found
                            }
                        }
                    }
                    else
                    {
                        bEnable = pDoc->IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) &&
                                  pDoc->GetNote( ScAddress( nPosX, nPosY, nTab ) );
                    }
                    if ( !bEnable )
                        rSet.DisableItem( nWhich );
                }
                break;

			case SID_OPENDLG_CONSOLIDATE:
			case SCITEM_CONSOLIDATEDATA:
				{
					if(pDoc->GetChangeTrack()!=NULL)
								rSet.DisableItem( nWhich);
				}
				break;

            case SID_CHINESE_CONVERSION:
            case SID_HANGUL_HANJA_CONVERSION:
                ScViewUtil::HideDisabledSlot( rSet, pData->GetBindings(), nWhich );
            break;

            case FID_USE_NAME:
                {
                    if ( pDocSh && pDocSh->IsDocShared() )
                        rSet.DisableItem( nWhich );
                    else
                    {
                        ScRange aRange;
                        if ( pData->GetSimpleArea( aRange ) != SC_MARK_SIMPLE )
                            rSet.DisableItem( nWhich );
                    }
                }
                break;

            case FID_DEFINE_NAME:
            case FID_INSERT_NAME:
            case SID_DEFINE_COLROWNAMERANGES:
                {
                    if ( pDocSh && pDocSh->IsDocShared() )
                    {
                        rSet.DisableItem( nWhich );
                    }
                }
                break;

            case SID_SPELL_DIALOG:
                {
                    if ( pDoc && pData && pDoc->IsTabProtected( pData->GetTabNo() ) )
                    {
                        bool bVisible = false;
                        SfxViewFrame* pViewFrame = ( pTabViewShell ? pTabViewShell->GetViewFrame() : NULL );
                        if ( pViewFrame && pViewFrame->HasChildWindow( nWhich ) )
                        {
                            SfxChildWindow* pChild = pViewFrame->GetChildWindow( nWhich );
                            Window* pWin = ( pChild ? pChild->GetWindow() : NULL );
                            if ( pWin && pWin->IsVisible() )
                            {
                                bVisible = true;
                            }
                        }
                        if ( !bVisible )
                        {
                            rSet.DisableItem( nWhich );
                        }
                    }
                }
                break;

		} // switch ( nWitch )
		nWhich = aIter.NextWhich();
	} // while ( nWitch )
}

//------------------------------------------------------------------



