summaryrefslogtreecommitdiff
path: root/sc/source/ui/app/inputwin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/app/inputwin.cxx')
-rw-r--r--sc/source/ui/app/inputwin.cxx1800
1 files changed, 1800 insertions, 0 deletions
diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx
new file mode 100644
index 000000000000..8f95c3e5e304
--- /dev/null
+++ b/sc/source/ui/app/inputwin.cxx
@@ -0,0 +1,1800 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+#include <algorithm>
+
+#include "scitems.hxx"
+#include <editeng/eeitem.hxx>
+
+#include <sfx2/app.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/editstat.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/event.hxx>
+#include <sfx2/imgmgr.hxx>
+#include <stdlib.h> // qsort
+#include <editeng/scriptspaceitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <vcl/cursor.hxx>
+#include <vcl/help.hxx>
+#include <svl/stritem.hxx>
+
+#include "inputwin.hxx"
+#include "scmod.hxx"
+#include "uiitems.hxx"
+#include "global.hxx"
+#include "scresid.hxx"
+#include "sc.hrc"
+#include "globstr.hrc"
+#include "editutil.hxx"
+#include "inputhdl.hxx"
+#include "tabvwsh.hxx"
+#include "document.hxx"
+#include "docsh.hxx"
+#include "appoptio.hxx"
+#include "rangenam.hxx"
+#include <formula/compiler.hrc>
+#include "dbcolect.hxx"
+#include "rangeutl.hxx"
+#include "docfunc.hxx"
+#include "funcdesc.hxx"
+#include <editeng/fontitem.hxx>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include "AccessibleEditObject.hxx"
+#include "AccessibleText.hxx"
+
+#define TEXT_STARTPOS 3
+#define THESIZE 1000000 //!!! langt... :-)
+#define TBX_WINDOW_HEIGHT 22 // in Pixeln - fuer alle Systeme gleich?
+
+enum ScNameInputType
+{
+ SC_NAME_INPUT_CELL,
+ SC_NAME_INPUT_RANGE,
+ SC_NAME_INPUT_NAMEDRANGE,
+ SC_NAME_INPUT_DATABASE,
+ SC_NAME_INPUT_ROW,
+ SC_NAME_INPUT_SHEET,
+ SC_NAME_INPUT_DEFINE,
+ SC_NAME_INPUT_BAD_NAME,
+ SC_NAME_INPUT_BAD_SELECTION
+};
+
+
+//==================================================================
+// class ScInputWindowWrapper
+//==================================================================
+
+SFX_IMPL_CHILDWINDOW(ScInputWindowWrapper,FID_INPUTLINE_STATUS)
+
+ScInputWindowWrapper::ScInputWindowWrapper( Window* pParentP,
+ sal_uInt16 nId,
+ SfxBindings* pBindings,
+ SfxChildWinInfo* /* pInfo */ )
+ : SfxChildWindow( pParentP, nId )
+{
+ ScInputWindow* pWin=new ScInputWindow( pParentP, pBindings );
+ pWindow = pWin;
+
+ pWin->Show();
+
+ pWin->SetSizePixel( pWin->CalcWindowSizePixel() );
+
+ eChildAlignment = SFX_ALIGN_LOWESTTOP;
+ pBindings->Invalidate( FID_TOGGLEINPUTLINE );
+}
+
+// GetInfo fliegt wieder raus, wenn es ein SFX_IMPL_TOOLBOX gibt !!!!
+
+SfxChildWinInfo ScInputWindowWrapper::GetInfo() const
+{
+ SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
+ return aInfo;
+}
+
+//==================================================================
+
+#define IMAGE(id) pImgMgr->SeekImage(id)
+
+//==================================================================
+// class ScInputWindow
+//==================================================================
+
+ScInputWindow::ScInputWindow( Window* pParent, SfxBindings* pBind ) :
+#ifdef OS2
+// ohne WB_CLIPCHILDREN wg. os/2 Paintproblem
+ ToolBox ( pParent, WinBits(WB_BORDER|WB_3DLOOK) ),
+#else
+// mit WB_CLIPCHILDREN, sonst Flicker
+ ToolBox ( pParent, WinBits(WB_BORDER|WB_3DLOOK|WB_CLIPCHILDREN) ),
+#endif
+ aWndPos ( this ),
+ aTextWindow ( this ),
+ pInputHdl ( NULL ),
+ pBindings ( pBind ),
+ aTextOk ( ScResId( SCSTR_QHELP_BTNOK ) ), // nicht immer neu aus Resource
+ aTextCancel ( ScResId( SCSTR_QHELP_BTNCANCEL ) ),
+ aTextSum ( ScResId( SCSTR_QHELP_BTNSUM ) ),
+ aTextEqual ( ScResId( SCSTR_QHELP_BTNEQUAL ) ),
+ bIsOkCancelMode ( false )
+{
+ ScModule* pScMod = SC_MOD();
+ SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
+
+ // #i73615# don't rely on SfxViewShell::Current while constructing the input line
+ // (also for GetInputHdl below)
+ ScTabViewShell* pViewSh = NULL;
+ SfxDispatcher* pDisp = pBind->GetDispatcher();
+ if ( pDisp )
+ {
+ SfxViewFrame* pViewFrm = pDisp->GetFrame();
+ if ( pViewFrm )
+ pViewSh = PTR_CAST( ScTabViewShell, pViewFrm->GetViewShell() );
+ }
+ DBG_ASSERT( pViewSh, "no view shell for input window" );
+
+ // Positionsfenster, 3 Buttons, Eingabefenster
+ InsertWindow ( 1, &aWndPos, 0, 0 );
+ InsertSeparator ( 1 );
+ InsertItem ( SID_INPUT_FUNCTION, IMAGE( SID_INPUT_FUNCTION ), 0, 2 );
+ InsertItem ( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ), 0, 3 );
+ InsertItem ( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ), 0, 4 );
+ InsertSeparator ( 5 );
+ InsertWindow ( 7, &aTextWindow, 0, 6 );
+
+ aWndPos .SetQuickHelpText( ScResId( SCSTR_QHELP_POSWND ) );
+ aWndPos .SetHelpId ( HID_INSWIN_POS );
+ aTextWindow.SetQuickHelpText( ScResId( SCSTR_QHELP_INPUTWND ) );
+ aTextWindow.SetHelpId ( HID_INSWIN_INPUT );
+
+ // kein SetHelpText, die Hilfetexte kommen aus der Hilfe
+
+ SetItemText ( SID_INPUT_FUNCTION, ScResId( SCSTR_QHELP_BTNCALC ) );
+ SetHelpId ( SID_INPUT_FUNCTION, HID_INSWIN_CALC );
+
+ SetItemText ( SID_INPUT_SUM, aTextSum );
+ SetHelpId ( SID_INPUT_SUM, HID_INSWIN_SUMME );
+
+ SetItemText ( SID_INPUT_EQUAL, aTextEqual );
+ SetHelpId ( SID_INPUT_EQUAL, HID_INSWIN_FUNC );
+
+ SetHelpId( HID_SC_INPUTWIN ); // fuer die ganze Eingabezeile
+
+ aWndPos .Show();
+ aTextWindow .Show();
+
+ pInputHdl = SC_MOD()->GetInputHdl( pViewSh, false ); // use own handler even if ref-handler is set
+ if (pInputHdl)
+ pInputHdl->SetInputWindow( this );
+
+ if ( pInputHdl && pInputHdl->GetFormString().Len() )
+ {
+ // Umschalten waehrend der Funktionsautopilot aktiv ist
+ // -> Inhalt des Funktionsautopiloten wieder anzeigen
+ //! auch Selektion (am InputHdl gemerkt) wieder anzeigen
+
+ aTextWindow.SetTextString( pInputHdl->GetFormString() );
+ }
+ else if ( pInputHdl && pInputHdl->IsInputMode() )
+ {
+ // wenn waehrend des Editierens die Eingabezeile weg war
+ // (Editieren einer Formel, dann umschalten zu fremdem Dokument/Hilfe),
+ // wieder den gerade editierten Text aus dem InputHandler anzeigen
+
+ aTextWindow.SetTextString( pInputHdl->GetEditString() ); // Text anzeigen
+ if ( pInputHdl->IsTopMode() )
+ pInputHdl->SetMode( SC_INPUT_TABLE ); // Focus kommt eh nach unten
+ }
+ else if ( pViewSh )
+ pViewSh->UpdateInputHandler( sal_True ); // unbedingtes Update
+
+ pImgMgr->RegisterToolBox( this );
+ SetAccessibleName(ScResId(STR_ACC_TOOLBAR_FORMULA));
+}
+
+ScInputWindow::~ScInputWindow()
+{
+ sal_Bool bDown = ( ScGlobal::pSysLocale == NULL ); // after Clear?
+
+ // if any view's input handler has a pointer to this input window, reset it
+ // (may be several ones, #74522#)
+ // member pInputHdl is not used here
+
+ if ( !bDown )
+ {
+ TypeId aScType = TYPE(ScTabViewShell);
+ SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
+ while ( pSh )
+ {
+ ScInputHandler* pHdl = ((ScTabViewShell*)pSh)->GetInputHandler();
+ if ( pHdl && pHdl->GetInputWindow() == this )
+ {
+ pHdl->SetInputWindow( NULL );
+ pHdl->StopInputWinEngine( false ); // reset pTopView pointer
+ }
+ pSh = SfxViewShell::GetNext( *pSh, &aScType );
+ }
+ }
+
+ SfxImageManager::GetImageManager( SC_MOD() )->ReleaseToolBox( this );
+}
+
+void ScInputWindow::SetInputHandler( ScInputHandler* pNew )
+{
+ // wird im Activate der View gerufen...
+
+ if ( pNew != pInputHdl )
+ {
+ // Bei Reload (letzte Version) ist pInputHdl der Input-Handler der alten,
+ // geloeschten ViewShell, darum hier auf keinen Fall anfassen!
+
+ pInputHdl = pNew;
+ if (pInputHdl)
+ pInputHdl->SetInputWindow( this );
+ }
+}
+
+sal_Bool ScInputWindow::UseSubTotal(ScRangeList* pRangeList) const
+{
+ sal_Bool bSubTotal(false);
+ ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
+ if ( pViewSh )
+ {
+ ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
+ size_t nRangeCount (pRangeList->size());
+ size_t nRangeIndex (0);
+ while (!bSubTotal && nRangeIndex < nRangeCount)
+ {
+ const ScRange* pRange = (*pRangeList)[nRangeIndex];
+ if( pRange )
+ {
+ SCTAB nTabEnd(pRange->aEnd.Tab());
+ SCTAB nTab(pRange->aStart.Tab());
+ while (!bSubTotal && nTab <= nTabEnd)
+ {
+ SCROW nRowEnd(pRange->aEnd.Row());
+ SCROW nRow(pRange->aStart.Row());
+ while (!bSubTotal && nRow <= nRowEnd)
+ {
+ if (pDoc->RowFiltered(nRow, nTab))
+ bSubTotal = sal_True;
+ else
+ ++nRow;
+ }
+ ++nTab;
+ }
+ }
+ ++nRangeIndex;
+ }
+
+ ScDBCollection* pDBCollection = pDoc->GetDBCollection();
+ sal_uInt16 nDBCount (pDBCollection->GetCount());
+ sal_uInt16 nDBIndex (0);
+ while (!bSubTotal && nDBIndex < nDBCount)
+ {
+ ScDBData* pDB = (*pDBCollection)[nDBIndex];
+ if (pDB && pDB->HasAutoFilter())
+ {
+ nRangeIndex = 0;
+ while (!bSubTotal && nRangeIndex < nRangeCount)
+ {
+ const ScRange* pRange = (*pRangeList)[nRangeIndex];
+ if( pRange )
+ {
+ ScRange aDBArea;
+ pDB->GetArea(aDBArea);
+ if (aDBArea.Intersects(*pRange))
+ bSubTotal = sal_True;
+ }
+ ++nRangeIndex;
+ }
+ }
+ ++nDBIndex;
+ }
+ }
+ return bSubTotal;
+}
+
+void ScInputWindow::Select()
+{
+ ScModule* pScMod = SC_MOD();
+ ToolBox::Select();
+
+ switch ( GetCurItemId() )
+ {
+ case SID_INPUT_FUNCTION:
+ {
+ //! new method at ScModule to query if function autopilot is open
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
+ {
+ pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
+ SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD );
+
+ // die Toolbox wird sowieso disabled, also braucht auch nicht umgeschaltet
+ // zu werden, egal ob's geklappt hat oder nicht
+// SetOkCancelMode();
+ }
+ }
+ break;
+
+ case SID_INPUT_CANCEL:
+ pScMod->InputCancelHandler();
+ SetSumAssignMode();
+ break;
+
+ case SID_INPUT_OK:
+ pScMod->InputEnterHandler();
+ SetSumAssignMode();
+ aTextWindow.Invalidate(); // sonst bleibt Selektion stehen
+ break;
+
+ case SID_INPUT_SUM:
+ {
+ ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
+ if ( pViewSh )
+ {
+ const ScMarkData& rMark = pViewSh->GetViewData()->GetMarkData();
+ if ( rMark.IsMarked() || rMark.IsMultiMarked() )
+ {
+ ScRangeList aMarkRangeList;
+ rMark.FillRangeListWithMarks( &aMarkRangeList, false );
+ ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
+
+ // check if one of the marked ranges is empty
+ bool bEmpty = false;
+ const size_t nCount = aMarkRangeList.size();
+ for ( size_t i = 0; i < nCount; ++i )
+ {
+ const ScRange aRange( *aMarkRangeList[i] );
+ if ( pDoc->IsBlockEmpty( aRange.aStart.Tab(),
+ aRange.aStart.Col(), aRange.aStart.Row(),
+ aRange.aEnd.Col(), aRange.aEnd.Row() ) )
+ {
+ bEmpty = true;
+ break;
+ }
+ }
+
+ if ( bEmpty )
+ {
+ ScRangeList aRangeList;
+ const sal_Bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
+ if ( bDataFound )
+ {
+ ScAddress aAddr = aRangeList.back()->aEnd;
+ aAddr.IncRow();
+ const sal_Bool bSubTotal( UseSubTotal( &aRangeList ) );
+ pViewSh->EnterAutoSum( aRangeList, bSubTotal, aAddr );
+ }
+ }
+ else
+ {
+ const sal_Bool bSubTotal( UseSubTotal( &aMarkRangeList ) );
+ for ( size_t i = 0; i < nCount; ++i )
+ {
+ const ScRange aRange( *aMarkRangeList[i] );
+ const bool bSetCursor = ( i == nCount - 1 ? true : false );
+ const bool bContinue = ( i != 0 ? true : false );
+ if ( !pViewSh->AutoSum( aRange, bSubTotal, bSetCursor, bContinue ) )
+ {
+ pViewSh->MarkRange( aRange, false, false );
+ pViewSh->SetCursor( aRange.aEnd.Col(), aRange.aEnd.Row() );
+ const ScRangeList aRangeList;
+ ScAddress aAddr = aRange.aEnd;
+ aAddr.IncRow();
+ const String aFormula = pViewSh->GetAutoSumFormula(
+ aRangeList, bSubTotal, aAddr );
+ SetFuncString( aFormula );
+ break;
+ }
+ }
+ }
+ }
+ else // nur in Eingabezeile einfuegen
+ {
+ ScRangeList aRangeList;
+ const sal_Bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
+ const sal_Bool bSubTotal( UseSubTotal( &aRangeList ) );
+ ScAddress aAddr = pViewSh->GetViewData()->GetCurPos();
+ const String aFormula = pViewSh->GetAutoSumFormula( aRangeList, bSubTotal, aAddr );
+ SetFuncString( aFormula );
+
+ if ( bDataFound && pScMod->IsEditMode() )
+ {
+ ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
+ if ( pHdl )
+ {
+ pHdl->InitRangeFinder( aFormula );
+
+ //! SetSelection am InputHandler ???
+ //! bSelIsRef setzen ???
+ const xub_StrLen nOpen = aFormula.Search('(');
+ const xub_StrLen nLen = aFormula.Len();
+ if ( nOpen != STRING_NOTFOUND && nLen > nOpen )
+ {
+ sal_uInt8 nAdd(1);
+ if (bSubTotal)
+ nAdd = 3;
+ ESelection aSel(0,nOpen+nAdd,0,nLen-1);
+ EditView* pTableView = pHdl->GetTableView();
+ if (pTableView)
+ pTableView->SetSelection(aSel);
+ EditView* pTopView = pHdl->GetTopView();
+ if (pTopView)
+ pTopView->SetSelection(aSel);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case SID_INPUT_EQUAL:
+ {
+ aTextWindow.StartEditEngine();
+ if ( pScMod->IsEditMode() ) // nicht, wenn z.B. geschuetzt
+ {
+ aTextWindow.GrabFocus();
+ aTextWindow.SetTextString( '=' );
+
+ EditView* pView = aTextWindow.GetEditView();
+ if (pView)
+ {
+ pView->SetSelection( ESelection(0,1, 0,1) );
+ pScMod->InputChanged(pView);
+ SetOkCancelMode();
+ pView->SetEditEngineUpdateMode(sal_True);
+ }
+ }
+ break;
+ }
+ }
+}
+
+void ScInputWindow::Resize()
+{
+ ToolBox::Resize();
+
+ long nWidth = GetSizePixel().Width();
+ long nLeft = aTextWindow.GetPosPixel().X();
+ Size aSize = aTextWindow.GetSizePixel();
+
+ aSize.Width() = Max( ((long)(nWidth - nLeft - 5)), (long)0 );
+ aTextWindow.SetSizePixel( aSize );
+ aTextWindow.Invalidate();
+}
+
+void ScInputWindow::SetFuncString( const String& rString, sal_Bool bDoEdit )
+{
+ //! new method at ScModule to query if function autopilot is open
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
+ aTextWindow.StartEditEngine();
+
+ ScModule* pScMod = SC_MOD();
+ if ( pScMod->IsEditMode() )
+ {
+ if ( bDoEdit )
+ aTextWindow.GrabFocus();
+ aTextWindow.SetTextString( rString );
+ EditView* pView = aTextWindow.GetEditView();
+ if (pView)
+ {
+ xub_StrLen nLen = rString.Len();
+
+ if ( nLen > 0 )
+ {
+ nLen--;
+ pView->SetSelection( ESelection( 0, nLen, 0, nLen ) );
+ }
+
+ pScMod->InputChanged(pView);
+ if ( bDoEdit )
+ SetOkCancelMode(); // nicht, wenn gleich hinterher Enter/Cancel
+
+ pView->SetEditEngineUpdateMode(sal_True);
+ }
+ }
+}
+
+void ScInputWindow::SetPosString( const String& rStr )
+{
+ aWndPos.SetPos( rStr );
+}
+
+void ScInputWindow::SetTextString( const String& rString )
+{
+ if (rString.Len() <= 32767)
+ aTextWindow.SetTextString(rString);
+ else
+ {
+ String aNew = rString;
+ aNew.Erase(32767);
+ aTextWindow.SetTextString(aNew);
+ }
+}
+
+void ScInputWindow::SetOkCancelMode()
+{
+ //! new method at ScModule to query if function autopilot is open
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
+
+ ScModule* pScMod = SC_MOD();
+ SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
+ if (!bIsOkCancelMode)
+ {
+ RemoveItem( 3 ); // SID_INPUT_SUM und SID_INPUT_EQUAL entfernen
+ RemoveItem( 3 );
+ InsertItem( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ), 0, 3 );
+ InsertItem( SID_INPUT_OK, IMAGE( SID_INPUT_OK ), 0, 4 );
+ SetItemText ( SID_INPUT_CANCEL, aTextCancel );
+ SetHelpId ( SID_INPUT_CANCEL, HID_INSWIN_CANCEL );
+ SetItemText ( SID_INPUT_OK, aTextOk );
+ SetHelpId ( SID_INPUT_OK, HID_INSWIN_OK );
+ bIsOkCancelMode = sal_True;
+ }
+}
+
+void ScInputWindow::SetSumAssignMode()
+{
+ //! new method at ScModule to query if function autopilot is open
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
+
+ ScModule* pScMod = SC_MOD();
+ SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
+ if (bIsOkCancelMode)
+ {
+ // SID_INPUT_CANCEL, und SID_INPUT_OK entfernen
+ RemoveItem( 3 );
+ RemoveItem( 3 );
+ InsertItem( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ), 0, 3 );
+ InsertItem( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ), 0, 4 );
+ SetItemText ( SID_INPUT_SUM, aTextSum );
+ SetHelpId ( SID_INPUT_SUM, HID_INSWIN_SUMME );
+ SetItemText ( SID_INPUT_EQUAL, aTextEqual );
+ SetHelpId ( SID_INPUT_EQUAL, HID_INSWIN_FUNC );
+ bIsOkCancelMode = false;
+
+ SetFormulaMode(false); // kein editieren -> keine Formel
+ }
+}
+
+void ScInputWindow::SetFormulaMode( sal_Bool bSet )
+{
+ aWndPos.SetFormulaMode(bSet);
+ aTextWindow.SetFormulaMode(bSet);
+}
+
+void ScInputWindow::SetText( const String& rString )
+{
+ ToolBox::SetText(rString);
+}
+
+String ScInputWindow::GetText() const
+{
+ return ToolBox::GetText();
+}
+
+sal_Bool ScInputWindow::IsInputActive()
+{
+ return aTextWindow.IsInputActive();
+}
+
+EditView* ScInputWindow::GetEditView()
+{
+ return aTextWindow.GetEditView();
+}
+
+void ScInputWindow::MakeDialogEditView()
+{
+ aTextWindow.MakeDialogEditView();
+}
+
+void ScInputWindow::StopEditEngine( sal_Bool bAll )
+{
+ aTextWindow.StopEditEngine( bAll );
+}
+
+void ScInputWindow::TextGrabFocus()
+{
+ aTextWindow.GrabFocus();
+}
+
+void ScInputWindow::TextInvalidate()
+{
+ aTextWindow.Invalidate();
+}
+
+void ScInputWindow::SwitchToTextWin()
+{
+ // used for shift-ctrl-F2
+
+ aTextWindow.StartEditEngine();
+ if ( SC_MOD()->IsEditMode() )
+ {
+ aTextWindow.GrabFocus();
+ EditView* pView = aTextWindow.GetEditView();
+ if (pView)
+ {
+ xub_StrLen nLen = pView->GetEditEngine()->GetTextLen(0);
+ ESelection aSel( 0, nLen, 0, nLen );
+ pView->SetSelection( aSel ); // set cursor to end of text
+ }
+ }
+}
+
+void ScInputWindow::PosGrabFocus()
+{
+ aWndPos.GrabFocus();
+}
+
+void ScInputWindow::EnableButtons( sal_Bool bEnable )
+{
+ // when enabling buttons, always also enable the input window itself
+ if ( bEnable && !IsEnabled() )
+ Enable();
+
+ EnableItem( SID_INPUT_FUNCTION, bEnable );
+ EnableItem( bIsOkCancelMode ? SID_INPUT_CANCEL : SID_INPUT_SUM, bEnable );
+ EnableItem( bIsOkCancelMode ? SID_INPUT_OK : SID_INPUT_EQUAL, bEnable );
+// Invalidate();
+}
+
+void ScInputWindow::StateChanged( StateChangedType nType )
+{
+ ToolBox::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW ) Resize();
+}
+
+void ScInputWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( rDCEvt.GetType() == DATACHANGED_SETTINGS && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ // update item images
+ ScModule* pScMod = SC_MOD();
+ SfxImageManager* pImgMgr = SfxImageManager::GetImageManager( pScMod );
+ // IMAGE macro uses pScMod, pImgMg
+
+ SetItemImage( SID_INPUT_FUNCTION, IMAGE( SID_INPUT_FUNCTION ) );
+ if ( bIsOkCancelMode )
+ {
+ SetItemImage( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ) );
+ SetItemImage( SID_INPUT_OK, IMAGE( SID_INPUT_OK ) );
+ }
+ else
+ {
+ SetItemImage( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ) );
+ SetItemImage( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ) );
+ }
+ }
+
+ ToolBox::DataChanged( rDCEvt );
+}
+
+//========================================================================
+// Eingabefenster
+//========================================================================
+
+ScTextWnd::ScTextWnd( Window* pParent )
+ : Window ( pParent, WinBits(WB_HIDE | WB_BORDER) ),
+ DragSourceHelper( this ),
+ pEditEngine ( NULL ),
+ pEditView ( NULL ),
+ bIsInsertMode( sal_True ),
+ bFormulaMode ( false ),
+ bInputMode ( false )
+{
+ EnableRTL( false ); // EditEngine can't be used with VCL EnableRTL
+
+ bIsRTL = GetSettings().GetLayoutRTL();
+
+ // always use application font, so a font with cjk chars can be installed
+ Font aAppFont = GetFont();
+ aTextFont = aAppFont;
+ aTextFont.SetSize( PixelToLogic( aAppFont.GetSize(), MAP_TWIP ) ); // AppFont ist in Pixeln
+
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+
+ Color aBgColor= rStyleSettings.GetWindowColor();
+ Color aTxtColor= rStyleSettings.GetWindowTextColor();
+
+ aTextFont.SetTransparent ( sal_True );
+ aTextFont.SetFillColor ( aBgColor );
+ //aTextFont.SetColor ( COL_FIELDTEXT );
+ aTextFont.SetColor (aTxtColor);
+ aTextFont.SetWeight ( WEIGHT_NORMAL );
+
+ Size aSize(1,TBX_WINDOW_HEIGHT);
+ Size aMinEditSize( Edit::GetMinimumEditSize() );
+ if( aMinEditSize.Height() > aSize.Height() )
+ aSize.Height() = aMinEditSize.Height();
+ SetSizePixel ( aSize );
+ SetBackground ( aBgColor );
+ SetLineColor ( COL_BLACK );
+ SetMapMode ( MAP_TWIP );
+ SetPointer ( POINTER_TEXT );
+}
+
+ScTextWnd::~ScTextWnd()
+{
+ while (!maAccTextDatas.empty()) {
+ maAccTextDatas.back()->Dispose();
+ }
+ delete pEditView;
+ delete pEditEngine;
+}
+
+void ScTextWnd::Paint( const Rectangle& rRec )
+{
+ if (pEditView)
+ pEditView->Paint( rRec );
+ else
+ {
+ SetFont( aTextFont );
+
+ long nDiff = GetOutputSizePixel().Height()
+ - LogicToPixel( Size( 0, GetTextHeight() ) ).Height();
+// if (nDiff<2) nDiff=2; // mind. 1 Pixel
+
+ long nStartPos = TEXT_STARTPOS;
+ if ( bIsRTL )
+ {
+ // right-align
+ nStartPos += GetOutputSizePixel().Width() - 2*TEXT_STARTPOS -
+ LogicToPixel( Size( GetTextWidth( aString ), 0 ) ).Width();
+
+ // LayoutMode isn't changed as long as ModifyRTLDefaults doesn't include SvxFrameDirectionItem
+ }
+
+ DrawText( PixelToLogic( Point( nStartPos, nDiff/2 ) ), aString );
+ }
+}
+
+void ScTextWnd::Resize()
+{
+ if (pEditView)
+ {
+ Size aSize = GetOutputSizePixel();
+ long nDiff = aSize.Height()
+ - LogicToPixel( Size( 0, GetTextHeight() ) ).Height();
+
+ aSize.Width() -= 2 * TEXT_STARTPOS - 1;
+
+ pEditView->SetOutputArea(
+ PixelToLogic( Rectangle( Point( TEXT_STARTPOS, (nDiff > 0) ? nDiff/2 : 1 ),
+ aSize ) ) );
+ }
+}
+
+void ScTextWnd::MouseMove( const MouseEvent& rMEvt )
+{
+ if (pEditView)
+ pEditView->MouseMove( rMEvt );
+}
+
+void ScTextWnd::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if (!HasFocus())
+ {
+ StartEditEngine();
+ if ( SC_MOD()->IsEditMode() )
+ GrabFocus();
+ }
+
+ if (pEditView)
+ {
+ pEditView->SetEditEngineUpdateMode( sal_True );
+ pEditView->MouseButtonDown( rMEvt );
+ }
+}
+
+void ScTextWnd::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if (pEditView)
+ if (pEditView->MouseButtonUp( rMEvt ))
+ {
+ if ( rMEvt.IsMiddle() &&
+ GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION )
+ {
+ // EditView may have pasted from selection
+ SC_MOD()->InputChanged( pEditView );
+ }
+ else
+ SC_MOD()->InputSelection( pEditView );
+ }
+}
+
+void ScTextWnd::Command( const CommandEvent& rCEvt )
+{
+ bInputMode = sal_True;
+ sal_uInt16 nCommand = rCEvt.GetCommand();
+ if ( pEditView /* && ( nCommand == COMMAND_STARTDRAG || nCommand == COMMAND_VOICE ) */ )
+ {
+ ScModule* pScMod = SC_MOD();
+ ScTabViewShell* pStartViewSh = ScTabViewShell::GetActiveViewShell();
+
+ // don't modify the font defaults here - the right defaults are
+ // already set in StartEditEngine when the EditEngine is created
+
+ // verhindern, dass die EditView beim View-Umschalten wegkommt
+ pScMod->SetInEditCommand( true );
+ pEditView->Command( rCEvt );
+ pScMod->SetInEditCommand( false );
+
+ // COMMAND_STARTDRAG heiss noch lange nicht, dass der Inhalt geaendert wurde
+ // darum in dem Fall kein InputChanged
+ //! erkennen, ob mit Move gedraggt wurde, oder Drag&Move irgendwie verbieten
+
+ if ( nCommand == COMMAND_STARTDRAG )
+ {
+ // ist auf eine andere View gedraggt worden?
+ ScTabViewShell* pEndViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pEndViewSh != pStartViewSh && pStartViewSh != NULL )
+ {
+ ScViewData* pViewData = pStartViewSh->GetViewData();
+ ScInputHandler* pHdl = pScMod->GetInputHdl( pStartViewSh );
+ if ( pHdl && pViewData->HasEditView( pViewData->GetActivePart() ) )
+ {
+ pHdl->CancelHandler();
+ pViewData->GetView()->ShowCursor(); // fehlt bei KillEditView, weil nicht aktiv
+ }
+ }
+ }
+ else if ( nCommand == COMMAND_CURSORPOS )
+ {
+ // don't call InputChanged for COMMAND_CURSORPOS
+ }
+ else if ( nCommand == COMMAND_INPUTLANGUAGECHANGE )
+ {
+ // #i55929# Font and font size state depends on input language if nothing is selected,
+ // so the slots have to be invalidated when the input language is changed.
+
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if (pViewFrm)
+ {
+ SfxBindings& rBindings = pViewFrm->GetBindings();
+ rBindings.Invalidate( SID_ATTR_CHAR_FONT );
+ rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
+ }
+ }
+ else
+ SC_MOD()->InputChanged( pEditView );
+ }
+ else
+ Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern...
+
+ bInputMode = false;
+}
+
+void ScTextWnd::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
+{
+ if ( pEditView )
+ {
+ CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True );
+ pEditView->Command( aDragEvent );
+
+ // handling of d&d to different view (CancelHandler) can't be done here,
+ // because the call returns before d&d is complete.
+ }
+}
+
+void ScTextWnd::KeyInput(const KeyEvent& rKEvt)
+{
+ bInputMode = sal_True;
+ if (!SC_MOD()->InputKeyEvent( rKEvt ))
+ {
+ sal_Bool bUsed = false;
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh )
+ bUsed = pViewSh->SfxKeyInput(rKEvt); // nur Acceleratoren, keine Eingabe
+ if (!bUsed)
+ Window::KeyInput( rKEvt );
+ }
+ bInputMode = false;
+}
+
+void ScTextWnd::GetFocus()
+{
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh )
+ pViewSh->SetFormShellAtTop( false ); // focus in input line -> FormShell no longer on top
+}
+
+void ScTextWnd::LoseFocus()
+{
+}
+
+String ScTextWnd::GetText() const
+{
+ // ueberladen, um per Testtool an den Text heranzukommen
+
+ if ( pEditEngine )
+ return pEditEngine->GetText();
+ else
+ return GetTextString();
+}
+
+void ScTextWnd::SetFormulaMode( sal_Bool bSet )
+{
+ if ( bSet != bFormulaMode )
+ {
+ bFormulaMode = bSet;
+ UpdateAutoCorrFlag();
+ }
+}
+
+void ScTextWnd::UpdateAutoCorrFlag()
+{
+ if ( pEditEngine )
+ {
+ sal_uLong nControl = pEditEngine->GetControlWord();
+ sal_uLong nOld = nControl;
+ if ( bFormulaMode )
+ nControl &= ~EE_CNTRL_AUTOCORRECT; // keine Autokorrektur in Formeln
+ else
+ nControl |= EE_CNTRL_AUTOCORRECT; // sonst schon
+ if ( nControl != nOld )
+ pEditEngine->SetControlWord( nControl );
+ }
+}
+
+void lcl_ExtendEditFontAttribs( SfxItemSet& rSet )
+{
+ const SfxPoolItem& rFontItem = rSet.Get( EE_CHAR_FONTINFO );
+ rSet.Put( rFontItem, EE_CHAR_FONTINFO_CJK );
+ rSet.Put( rFontItem, EE_CHAR_FONTINFO_CTL );
+ const SfxPoolItem& rHeightItem = rSet.Get( EE_CHAR_FONTHEIGHT );
+ rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CJK );
+ rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CTL );
+ const SfxPoolItem& rWeightItem = rSet.Get( EE_CHAR_WEIGHT );
+ rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CJK );
+ rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CTL );
+ const SfxPoolItem& rItalicItem = rSet.Get( EE_CHAR_ITALIC );
+ rSet.Put( rItalicItem, EE_CHAR_ITALIC_CJK );
+ rSet.Put( rItalicItem, EE_CHAR_ITALIC_CTL );
+ const SfxPoolItem& rLangItem = rSet.Get( EE_CHAR_LANGUAGE );
+ rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CJK );
+ rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CTL );
+}
+
+void lcl_ModifyRTLDefaults( SfxItemSet& rSet )
+{
+ rSet.Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) );
+
+ // always using rtl writing direction would break formulas
+ //rSet.Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) );
+
+ // PaperSize width is limited to USHRT_MAX in RTL mode (because of EditEngine's
+ // sal_uInt16 values in EditLine), so the text may be wrapped and line spacing must be
+ // increased to not see the beginning of the next line.
+ SvxLineSpacingItem aItem( SVX_LINESPACE_TWO_LINES, EE_PARA_SBL );
+ aItem.SetPropLineSpace( 200 );
+ rSet.Put( aItem );
+}
+
+void lcl_ModifyRTLVisArea( EditView* pEditView )
+{
+ Rectangle aVisArea = pEditView->GetVisArea();
+ Size aPaper = pEditView->GetEditEngine()->GetPaperSize();
+ long nDiff = aPaper.Width() - aVisArea.Right();
+ aVisArea.Left() += nDiff;
+ aVisArea.Right() += nDiff;
+ pEditView->SetVisArea(aVisArea);
+}
+
+void ScTextWnd::StartEditEngine()
+{
+ // Bei "eigener Modalitaet" (Doc-modale Dialoge) nicht aktivieren
+ SfxObjectShell* pObjSh = SfxObjectShell::Current();
+ if ( pObjSh && pObjSh->IsInModalMode() )
+ return;
+
+ if ( !pEditView || !pEditEngine )
+ {
+ ScFieldEditEngine* pNew;
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh )
+ {
+ const ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
+ pNew = new ScFieldEditEngine( pDoc->GetEnginePool(), pDoc->GetEditPool() );
+ }
+ else
+ pNew = new ScFieldEditEngine( EditEngine::CreatePool(), NULL, sal_True );
+ pNew->SetExecuteURL( false );
+ pEditEngine = pNew;
+
+ pEditEngine->SetUpdateMode( false );
+ pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
+ pEditEngine->SetWordDelimiters(
+ ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
+
+ UpdateAutoCorrFlag();
+
+ {
+ SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
+ pEditEngine->SetFontInfoInItemSet( *pSet, aTextFont );
+ lcl_ExtendEditFontAttribs( *pSet );
+ // turn off script spacing to match DrawText output
+ pSet->Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) );
+ if ( bIsRTL )
+ lcl_ModifyRTLDefaults( *pSet );
+ pEditEngine->SetDefaults( pSet );
+ }
+
+ // Wenn in der Zelle URL-Felder enthalten sind, muessen die auch in
+ // die Eingabezeile uebernommen werden, weil sonst die Positionen nicht stimmen.
+
+ sal_Bool bFilled = false;
+ ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
+ if ( pHdl ) //! Testen, ob's der richtige InputHdl ist?
+ bFilled = pHdl->GetTextAndFields( *pEditEngine );
+
+ pEditEngine->SetUpdateMode( sal_True );
+
+ // aString ist die Wahrheit...
+ if ( bFilled && pEditEngine->GetText() == aString )
+ Invalidate(); // Repaint fuer (hinterlegte) Felder
+ else
+ pEditEngine->SetText(aString); // dann wenigstens den richtigen Text
+
+ pEditView = new EditView( pEditEngine, this );
+ pEditView->SetInsertMode(bIsInsertMode);
+
+ // Text aus Clipboard wird als ASCII einzeilig uebernommen
+ sal_uLong n = pEditView->GetControlWord();
+ pEditView->SetControlWord( n | EV_CNTRL_SINGLELINEPASTE );
+
+ pEditEngine->InsertView( pEditView, EE_APPEND );
+
+ Resize();
+
+ if ( bIsRTL )
+ lcl_ModifyRTLVisArea( pEditView );
+
+ pEditEngine->SetModifyHdl(LINK(this, ScTextWnd, NotifyHdl));
+
+ if (!maAccTextDatas.empty())
+ maAccTextDatas.back()->StartEdit();
+
+ // as long as EditEngine and DrawText sometimes differ for CTL text,
+ // repaint now to have the EditEngine's version visible
+// SfxObjectShell* pObjSh = SfxObjectShell::Current();
+ if ( pObjSh && pObjSh->ISA(ScDocShell) )
+ {
+ ScDocument* pDoc = ((ScDocShell*)pObjSh)->GetDocument(); // any document
+ sal_uInt8 nScript = pDoc->GetStringScriptType( aString );
+ if ( nScript & SCRIPTTYPE_COMPLEX )
+ Invalidate();
+ }
+ }
+
+ SC_MOD()->SetInputMode( SC_INPUT_TOP );
+
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if (pViewFrm)
+ pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
+}
+
+IMPL_LINK(ScTextWnd, NotifyHdl, EENotify*, EMPTYARG)
+{
+ if (pEditView && !bInputMode)
+ {
+ ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
+
+ // Use the InputHandler's InOwnChange flag to prevent calling InputChanged
+ // while an InputHandler method is modifying the EditEngine content
+
+ if ( pHdl && !pHdl->IsInOwnChange() )
+ pHdl->InputChanged( pEditView, sal_True ); // #i20282# InputChanged must know if called from modify handler
+ }
+
+ return 0;
+}
+
+void ScTextWnd::StopEditEngine( sal_Bool bAll )
+{
+ if (pEditView)
+ {
+ if (!maAccTextDatas.empty())
+ maAccTextDatas.back()->EndEdit();
+
+ ScModule* pScMod = SC_MOD();
+
+ if (!bAll)
+ pScMod->InputSelection( pEditView );
+ aString = pEditEngine->GetText();
+ bIsInsertMode = pEditView->IsInsertMode();
+ sal_Bool bSelection = pEditView->HasSelection();
+ pEditEngine->SetModifyHdl(Link());
+ DELETEZ(pEditView);
+ DELETEZ(pEditEngine);
+
+ if ( pScMod->IsEditMode() && !bAll )
+ pScMod->SetInputMode(SC_INPUT_TABLE);
+
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if (pViewFrm)
+ pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
+
+ if (bSelection)
+ Invalidate(); // damit Selektion nicht stehenbleibt
+ }
+}
+
+void ScTextWnd::SetTextString( const String& rNewString )
+{
+ if ( rNewString != aString )
+ {
+ bInputMode = sal_True;
+
+ // Position der Aenderung suchen, nur Rest painten
+
+ if (!pEditEngine)
+ {
+ sal_Bool bPaintAll;
+ if ( bIsRTL )
+ bPaintAll = sal_True;
+ else
+ {
+ // test if CTL script type is involved
+ sal_uInt8 nOldScript = 0;
+ sal_uInt8 nNewScript = 0;
+ SfxObjectShell* pObjSh = SfxObjectShell::Current();
+ if ( pObjSh && pObjSh->ISA(ScDocShell) )
+ {
+ // any document can be used (used only for its break iterator)
+ ScDocument* pDoc = ((ScDocShell*)pObjSh)->GetDocument();
+ nOldScript = pDoc->GetStringScriptType( aString );
+ nNewScript = pDoc->GetStringScriptType( rNewString );
+ }
+ bPaintAll = ( nOldScript & SCRIPTTYPE_COMPLEX ) || ( nNewScript & SCRIPTTYPE_COMPLEX );
+ }
+
+ if ( bPaintAll )
+ {
+ // if CTL is involved, the whole text has to be redrawn
+ Invalidate();
+ }
+ else
+ {
+ long nTextSize = 0;
+ xub_StrLen nDifPos;
+ if (rNewString.Len() > aString.Len())
+ nDifPos = rNewString.Match(aString);
+ else
+ nDifPos = aString.Match(rNewString);
+
+ long nSize1 = GetTextWidth(aString);
+ long nSize2 = GetTextWidth(rNewString);
+ if ( nSize1>0 && nSize2>0 )
+ nTextSize = Max( nSize1, nSize2 );
+ else
+ nTextSize = GetOutputSize().Width(); // Ueberlauf
+
+ if (nDifPos == STRING_MATCH)
+ nDifPos = 0;
+
+ // -1 wegen Rundung und "A"
+ Point aLogicStart = PixelToLogic(Point(TEXT_STARTPOS-1,0));
+ long nStartPos = aLogicStart.X();
+ long nInvPos = nStartPos;
+ if (nDifPos)
+ nInvPos += GetTextWidth(aString,0,nDifPos);
+
+ sal_uInt16 nFlags = 0;
+ if ( nDifPos == aString.Len() ) // only new characters appended
+ nFlags = INVALIDATE_NOERASE; // then background is already clear
+
+ Invalidate( Rectangle( nInvPos, 0,
+ nStartPos+nTextSize, GetOutputSize().Height()-1 ),
+ nFlags );
+ }
+ }
+ else
+ {
+ pEditEngine->SetText(rNewString);
+ }
+
+ aString = rNewString;
+
+ if (!maAccTextDatas.empty())
+ maAccTextDatas.back()->TextChanged();
+
+ bInputMode = false;
+ }
+}
+
+const String& ScTextWnd::GetTextString() const
+{
+ return aString;
+}
+
+sal_Bool ScTextWnd::IsInputActive()
+{
+ return HasFocus();
+}
+
+EditView* ScTextWnd::GetEditView()
+{
+ return pEditView;
+}
+
+void ScTextWnd::MakeDialogEditView()
+{
+ if ( pEditView ) return;
+
+ ScFieldEditEngine* pNew;
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh )
+ {
+ const ScDocument* pDoc = pViewSh->GetViewData()->GetDocument();
+ pNew = new ScFieldEditEngine( pDoc->GetEnginePool(), pDoc->GetEditPool() );
+ }
+ else
+ pNew = new ScFieldEditEngine( EditEngine::CreatePool(), NULL, sal_True );
+ pNew->SetExecuteURL( false );
+ pEditEngine = pNew;
+
+ pEditEngine->SetUpdateMode( false );
+ pEditEngine->SetWordDelimiters( pEditEngine->GetWordDelimiters() += '=' );
+ pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
+
+ SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
+ pEditEngine->SetFontInfoInItemSet( *pSet, aTextFont );
+ lcl_ExtendEditFontAttribs( *pSet );
+ if ( bIsRTL )
+ lcl_ModifyRTLDefaults( *pSet );
+ pEditEngine->SetDefaults( pSet );
+ pEditEngine->SetUpdateMode( sal_True );
+
+ pEditView = new EditView( pEditEngine, this );
+ pEditEngine->InsertView( pEditView, EE_APPEND );
+
+ Resize();
+
+ if ( bIsRTL )
+ lcl_ModifyRTLVisArea( pEditView );
+
+ if (!maAccTextDatas.empty())
+ maAccTextDatas.back()->StartEdit();
+}
+
+void ScTextWnd::ImplInitSettings()
+{
+ bIsRTL = GetSettings().GetLayoutRTL();
+
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+
+ Color aBgColor= rStyleSettings.GetWindowColor();
+ Color aTxtColor= rStyleSettings.GetWindowTextColor();
+
+ aTextFont.SetFillColor ( aBgColor );
+ aTextFont.SetColor (aTxtColor);
+ SetBackground ( aBgColor );
+ Invalidate();
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ScTextWnd::CreateAccessible()
+{
+ return new ScAccessibleEditObject(GetAccessibleParentWindow()->GetAccessible(), NULL, this,
+ rtl::OUString(String(ScResId(STR_ACC_EDITLINE_NAME))),
+ rtl::OUString(String(ScResId(STR_ACC_EDITLINE_DESCR))), EditLine);
+}
+
+void ScTextWnd::InsertAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
+{
+ OSL_ENSURE( ::std::find( maAccTextDatas.begin(), maAccTextDatas.end(), &rTextData ) == maAccTextDatas.end(),
+ "ScTextWnd::InsertAccessibleTextData - passed object already registered" );
+ maAccTextDatas.push_back( &rTextData );
+}
+
+void ScTextWnd::RemoveAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
+{
+ AccTextDataVector::iterator aEnd = maAccTextDatas.end();
+ AccTextDataVector::iterator aIt = ::std::find( maAccTextDatas.begin(), aEnd, &rTextData );
+ OSL_ENSURE( aIt != aEnd, "ScTextWnd::RemoveAccessibleTextData - passed object not registered" );
+ if( aIt != aEnd )
+ maAccTextDatas.erase( aIt );
+}
+
+// -----------------------------------------------------------------------
+
+void ScTextWnd::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+ else
+ Window::DataChanged( rDCEvt );
+}
+
+
+//========================================================================
+// Positionsfenster
+//========================================================================
+
+ScPosWnd::ScPosWnd( Window* pParent ) :
+ ComboBox ( pParent, WinBits(WB_HIDE | WB_DROPDOWN) ),
+ pAccel ( NULL ),
+ nTipVisible ( 0 ),
+ bFormulaMode( false )
+{
+ Size aSize( GetTextWidth( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("GW99999:GW99999")) ),
+ GetTextHeight() );
+ aSize.Width() += 25; // ??
+ aSize.Height() = CalcWindowSizePixel(11); // Funktionen: 10 MRU + "andere..."
+ SetSizePixel( aSize );
+
+ FillRangeNames();
+
+ StartListening( *SFX_APP() ); // fuer Navigator-Bereichsnamen-Updates
+}
+
+ScPosWnd::~ScPosWnd()
+{
+ EndListening( *SFX_APP() );
+
+ HideTip();
+
+ delete pAccel;
+}
+
+void ScPosWnd::SetFormulaMode( sal_Bool bSet )
+{
+ if ( bSet != bFormulaMode )
+ {
+ bFormulaMode = bSet;
+
+ if ( bSet )
+ FillFunctions();
+ else
+ FillRangeNames();
+
+ HideTip();
+ }
+}
+
+void ScPosWnd::SetPos( const String& rPosStr )
+{
+ if ( aPosStr != rPosStr )
+ {
+ aPosStr = rPosStr;
+ SetText(aPosStr);
+ }
+}
+
+void ScPosWnd::FillRangeNames()
+{
+ Clear();
+
+ SfxObjectShell* pObjSh = SfxObjectShell::Current();
+ if ( pObjSh && pObjSh->ISA(ScDocShell) )
+ {
+ ScDocument* pDoc = ((ScDocShell*)pObjSh)->GetDocument();
+
+ // per Hand sortieren, weil Funktionen nicht sortiert werden:
+
+ ScRangeName* pRangeNames = pDoc->GetRangeName();
+ if (!pRangeNames->empty())
+ {
+ ScRange aDummy;
+ std::vector<const ScRangeData*> aSortArray;
+ ScRangeName::const_iterator itr = pRangeNames->begin(), itrEnd = pRangeNames->end();
+ for (; itr != itrEnd; ++itr)
+ {
+ if (itr->IsValidReference(aDummy))
+ aSortArray.push_back(&(*itr));
+ }
+
+ if (!aSortArray.empty())
+ {
+#ifndef ICC
+ size_t n = aSortArray.size();
+ qsort( (void*)&aSortArray[0], n, sizeof(ScRangeData*),
+ &ScRangeData_QsortNameCompare );
+#else
+ qsort( (void*)&aSortArray[0], n, sizeof(ScRangeData*),
+ ICCQsortNameCompare );
+#endif
+ for (size_t i = 0; i < n; ++i)
+ InsertEntry(aSortArray[i]->GetName());
+ }
+ }
+ }
+ SetText(aPosStr);
+}
+
+void ScPosWnd::FillFunctions()
+{
+ Clear();
+
+ String aFirstName;
+ const ScAppOptions& rOpt = SC_MOD()->GetAppOptions();
+ sal_uInt16 nMRUCount = rOpt.GetLRUFuncListCount();
+ const sal_uInt16* pMRUList = rOpt.GetLRUFuncList();
+ if (pMRUList)
+ {
+ const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
+ sal_uLong nListCount = pFuncList->GetCount();
+ for (sal_uInt16 i=0; i<nMRUCount; i++)
+ {
+ sal_uInt16 nId = pMRUList[i];
+ for (sal_uLong j=0; j<nListCount; j++)
+ {
+ const ScFuncDesc* pDesc = pFuncList->GetFunction( j );
+ if ( pDesc->nFIndex == nId && pDesc->pFuncName )
+ {
+ InsertEntry( *pDesc->pFuncName );
+ if (!aFirstName.Len())
+ aFirstName = *pDesc->pFuncName;
+ break; // nicht weitersuchen
+ }
+ }
+ }
+ }
+
+ //! Eintrag "Andere..." fuer Funktions-Autopilot wieder aufnehmen,
+ //! wenn der Funktions-Autopilot mit dem bisher eingegebenen Text arbeiten kann!
+
+// InsertEntry( ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) );
+
+ SetText(aFirstName);
+}
+
+void ScPosWnd::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( !bFormulaMode )
+ {
+ // muss die Liste der Bereichsnamen updgedated werden?
+
+ if ( rHint.ISA(SfxSimpleHint) )
+ {
+ sal_uLong nHintId = ((SfxSimpleHint&)rHint).GetId();
+ if ( nHintId == SC_HINT_AREAS_CHANGED || nHintId == SC_HINT_NAVIGATOR_UPDATEALL)
+ FillRangeNames();
+ }
+ else if ( rHint.ISA(SfxEventHint) )
+ {
+ sal_uLong nEventId = ((SfxEventHint&)rHint).GetEventId();
+ if ( nEventId == SFX_EVENT_ACTIVATEDOC )
+ FillRangeNames();
+ }
+ }
+}
+
+void ScPosWnd::HideTip()
+{
+ if ( nTipVisible )
+ {
+ Help::HideTip( nTipVisible );
+ nTipVisible = 0;
+ }
+}
+
+ScNameInputType lcl_GetInputType( const String& rText )
+{
+ ScNameInputType eRet = SC_NAME_INPUT_BAD_NAME; // the more general error
+
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh )
+ {
+ ScViewData* pViewData = pViewSh->GetViewData();
+ ScDocument* pDoc = pViewData->GetDocument();
+ SCTAB nTab = pViewData->GetTabNo();
+ formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
+
+ // test in same order as in SID_CURRENTCELL execute
+
+ ScRange aRange;
+ ScAddress aAddress;
+ ScRangeUtil aRangeUtil;
+ SCTAB nNameTab;
+ sal_Int32 nNumeric;
+
+ if ( aRange.Parse( rText, pDoc, eConv ) & SCA_VALID )
+ eRet = SC_NAME_INPUT_RANGE;
+ else if ( aAddress.Parse( rText, pDoc, eConv ) & SCA_VALID )
+ eRet = SC_NAME_INPUT_CELL;
+ else if ( aRangeUtil.MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_NAMES, eConv ) )
+ eRet = SC_NAME_INPUT_NAMEDRANGE;
+ else if ( aRangeUtil.MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_DBASE, eConv ) )
+ eRet = SC_NAME_INPUT_DATABASE;
+ else if ( ByteString( rText, RTL_TEXTENCODING_ASCII_US ).IsNumericAscii() &&
+ ( nNumeric = rText.ToInt32() ) > 0 && nNumeric <= MAXROW+1 )
+ eRet = SC_NAME_INPUT_ROW;
+ else if ( pDoc->GetTable( rText, nNameTab ) )
+ eRet = SC_NAME_INPUT_SHEET;
+ else if ( ScRangeData::IsNameValid( rText, pDoc ) ) // nothing found, create new range?
+ {
+ if ( pViewData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
+ eRet = SC_NAME_INPUT_DEFINE;
+ else
+ eRet = SC_NAME_INPUT_BAD_SELECTION;
+ }
+ else
+ eRet = SC_NAME_INPUT_BAD_NAME;
+ }
+
+ return eRet;
+}
+
+void ScPosWnd::Modify()
+{
+ ComboBox::Modify();
+
+ HideTip();
+
+ if ( !IsTravelSelect() && !bFormulaMode )
+ {
+ // determine the action that would be taken for the current input
+
+ ScNameInputType eType = lcl_GetInputType( GetText() ); // uses current view
+ sal_uInt16 nStrId = 0;
+ switch ( eType )
+ {
+ case SC_NAME_INPUT_CELL:
+ nStrId = STR_NAME_INPUT_CELL;
+ break;
+ case SC_NAME_INPUT_RANGE:
+ case SC_NAME_INPUT_NAMEDRANGE:
+ nStrId = STR_NAME_INPUT_RANGE; // named range or range reference
+ break;
+ case SC_NAME_INPUT_DATABASE:
+ nStrId = STR_NAME_INPUT_DBRANGE;
+ break;
+ case SC_NAME_INPUT_ROW:
+ nStrId = STR_NAME_INPUT_ROW;
+ break;
+ case SC_NAME_INPUT_SHEET:
+ nStrId = STR_NAME_INPUT_SHEET;
+ break;
+ case SC_NAME_INPUT_DEFINE:
+ nStrId = STR_NAME_INPUT_DEFINE;
+ break;
+ default:
+ // other cases (error): no tip help
+ break;
+ }
+
+ if ( nStrId )
+ {
+ // show the help tip at the text cursor position
+
+ Window* pWin = GetSubEdit();
+ if (!pWin)
+ pWin = this;
+ Point aPos;
+ Cursor* pCur = pWin->GetCursor();
+ if (pCur)
+ aPos = pWin->LogicToPixel( pCur->GetPos() );
+ aPos = pWin->OutputToScreenPixel( aPos );
+ Rectangle aRect( aPos, aPos );
+
+ String aText = ScGlobal::GetRscString( nStrId );
+ sal_uInt16 nAlign = QUICKHELP_LEFT|QUICKHELP_BOTTOM;
+ nTipVisible = Help::ShowTip(pWin, aRect, aText, nAlign);
+ }
+ }
+}
+
+void ScPosWnd::Select()
+{
+ ComboBox::Select(); // in VCL gibt GetText() erst danach den ausgewaehlten Eintrag
+
+ HideTip();
+
+ if (!IsTravelSelect())
+ DoEnter();
+}
+
+void ScPosWnd::DoEnter()
+{
+ String aText = GetText();
+ if ( aText.Len() )
+ {
+ if ( bFormulaMode )
+ {
+ ScModule* pScMod = SC_MOD();
+ if ( aText == ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) )
+ {
+ // Funktions-Autopilot
+ //! mit dem bisher eingegebenen Text weiterarbeiten !!!
+
+ //! new method at ScModule to query if function autopilot is open
+ SfxViewFrame* pViewFrm = SfxViewFrame::Current();
+ if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
+ pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
+ SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD );
+ }
+ else
+ {
+ ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
+ ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
+ if (pHdl)
+ pHdl->InsertFunction( aText );
+ }
+ }
+ else
+ {
+ // depending on the input, select something or create a new named range
+
+ ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
+ if ( pViewSh )
+ {
+ ScViewData* pViewData = pViewSh->GetViewData();
+ ScDocShell* pDocShell = pViewData->GetDocShell();
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+ ScNameInputType eType = lcl_GetInputType( aText );
+ if ( eType == SC_NAME_INPUT_BAD_NAME || eType == SC_NAME_INPUT_BAD_SELECTION )
+ {
+ sal_uInt16 nId = ( eType == SC_NAME_INPUT_BAD_NAME ) ? STR_NAME_ERROR_NAME : STR_NAME_ERROR_SELECTION;
+ pViewSh->ErrorMessage( nId );
+ }
+ else if ( eType == SC_NAME_INPUT_DEFINE )
+ {
+ ScRangeName* pNames = pDoc->GetRangeName();
+ ScRange aSelection;
+ if ( pNames && !pNames->findByName(aText) &&
+ (pViewData->GetSimpleArea( aSelection ) == SC_MARK_SIMPLE) )
+ {
+ ScRangeName aNewRanges( *pNames );
+ ScAddress aCursor( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() );
+ String aContent;
+ aSelection.Format( aContent, SCR_ABS_3D, pDoc, pDoc->GetAddressConvention() );
+ ScRangeData* pNew = new ScRangeData( pDoc, aText, aContent, aCursor );
+ if ( aNewRanges.insert(pNew) )
+ {
+ ScDocFunc aFunc(*pDocShell);
+ aFunc.ModifyRangeNames( aNewRanges );
+ pViewSh->UpdateInputHandler(true);
+ }
+ else
+ delete pNew; // shouldn't happen
+ }
+ }
+ else
+ {
+ // for all selection types, excecute the SID_CURRENTCELL slot.
+ if (eType == SC_NAME_INPUT_CELL || eType == SC_NAME_INPUT_RANGE)
+ {
+ // Note that SID_CURRENTCELL always expects address to
+ // be in Calc A1 format. Convert the text.
+ ScRange aRange(0,0,pViewData->GetTabNo());
+ aRange.ParseAny(aText, pDoc, pDoc->GetAddressConvention());
+ aRange.Format(aText, SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO);
+ }
+
+ SfxStringItem aPosItem( SID_CURRENTCELL, aText );
+ SfxBoolItem aUnmarkItem( FN_PARAM_1, sal_True ); // remove existing selection
+
+ pViewSh->GetViewData()->GetDispatcher().Execute( SID_CURRENTCELL,
+ SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD,
+ &aPosItem, &aUnmarkItem, 0L );
+ }
+ }
+ }
+ }
+ else
+ SetText( aPosStr );
+
+ ReleaseFocus_Impl();
+}
+
+long ScPosWnd::Notify( NotifyEvent& rNEvt )
+{
+ long nHandled = 0;
+
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
+
+ switch ( pKEvt->GetKeyCode().GetCode() )
+ {
+ case KEY_RETURN:
+ DoEnter();
+ nHandled = 1;
+ break;
+
+ case KEY_ESCAPE:
+ if (nTipVisible)
+ {
+ // escape when the tip help is shown: only hide the tip
+ HideTip();
+ }
+ else
+ {
+ if (!bFormulaMode)
+ SetText( aPosStr );
+ ReleaseFocus_Impl();
+ }
+ nHandled = 1;
+ break;
+ }
+ }
+
+ if ( !nHandled )
+ nHandled = ComboBox::Notify( rNEvt );
+
+ if ( rNEvt.GetType() == EVENT_LOSEFOCUS )
+ HideTip();
+
+ return nHandled;
+}
+
+void ScPosWnd::ReleaseFocus_Impl()
+{
+ HideTip();
+
+ SfxViewShell* pCurSh = SfxViewShell::Current();
+ ScInputHandler* pHdl = SC_MOD()->GetInputHdl( PTR_CAST( ScTabViewShell, pCurSh ) );
+ if ( pHdl && pHdl->IsTopMode() )
+ {
+ // Focus wieder in die Eingabezeile?
+
+ ScInputWindow* pInputWin = pHdl->GetInputWindow();
+ if (pInputWin)
+ {
+ pInputWin->TextGrabFocus();
+ return;
+ }
+ }
+
+ // Focus auf die aktive View
+
+ if ( pCurSh )
+ {
+ Window* pShellWnd = pCurSh->GetWindow();
+
+ if ( pShellWnd )
+ pShellWnd->GrabFocus();
+ }
+}
+
+
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */