1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: inputhdl.cxx,v $
10 * $Revision: 1.77.32.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 //------------------------------------------------------------------
36 #include "scitems.hxx"
37 #include <svx/eeitem.hxx>
39 #include <sfx2/app.hxx>
40 #include <svx/acorrcfg.hxx>
41 #include <svx/algitem.hxx>
42 #include <svx/adjitem.hxx>
43 #include <svx/brshitem.hxx>
44 #include <svtools/colorcfg.hxx>
45 #include <svx/colritem.hxx>
46 #include <svx/editobj.hxx>
47 #include <svx/editstat.hxx>
48 #include <svx/editview.hxx>
49 #include <svx/escpitem.hxx>
50 #include <svx/forbiddencharacterstable.hxx>
51 #include <svx/langitem.hxx>
52 #include <svx/svxacorr.hxx>
53 #include <svx/unolingu.hxx>
54 #include <svx/wghtitem.hxx>
55 #include <sfx2/bindings.hxx>
56 #include <sfx2/viewfrm.hxx>
57 #include <sfx2/dispatch.hxx>
58 #include <sfx2/docfile.hxx>
59 #include <sfx2/printer.hxx>
60 #include <svtools/zforlist.hxx>
61 #include <vcl/sound.hxx>
62 #include <unotools/localedatawrapper.hxx>
63 #include <vcl/help.hxx>
64 #include <vcl/cursor.hxx>
65 #include <tools/urlobj.hxx>
66 #include <formula/formulahelper.hxx>
68 #include "inputwin.hxx"
69 #include "tabvwsh.hxx"
72 #include "uiitems.hxx"
75 #include "globstr.hrc"
76 #include "patattr.hxx"
77 #include "viewdata.hxx"
78 #include "document.hxx"
79 #include "docpool.hxx"
80 #include "editutil.hxx"
81 #include "collect.hxx"
82 #include "appoptio.hxx"
83 #include "docoptio.hxx"
84 #include "validat.hxx"
85 #include "userlist.hxx"
86 #include "rfindlst.hxx"
87 #include "inputopt.hxx"
88 #include "cell.hxx" // fuer Formel-Preview
89 #include "compiler.hxx" // fuer Formel-Preview
90 #include "editable.hxx"
91 #include "funcdesc.hxx"
94 #include "inputhdl.hxx"
96 // max. Ranges im RangeFinder
97 #define RANGEFIND_MAX 32
99 using namespace formula
;
101 // STATIC DATA -----------------------------------------------------------
103 BOOL
ScInputHandler::bOptLoaded
= FALSE
; // App-Optionen ausgewertet
104 BOOL
ScInputHandler::bAutoComplete
= FALSE
; // wird in KeyInput gesetzt
106 // delimiters (in addition to ScEditUtil) needed for range finder:
107 // only characters that are allowed in formulas next to references
108 // and the quotation mark (so string constants can be skipped)
110 static const sal_Char __FAR_DATA pMinDelimiters
[] = " !\"";
112 extern USHORT nEditAdjust
; //! Member an ViewData
114 //==================================================================
116 static sal_Unicode
lcl_getSheetSeparator(ScDocument
* pDoc
)
118 ScCompiler
aComp(pDoc
, ScAddress());
119 aComp
.SetGrammar(pDoc
->GetGrammar());
120 return aComp
.GetNativeAddressSymbol(ScCompiler::Convention::SHEET_SEPARATOR
);
123 void ScInputHandler::InitRangeFinder( const String
& rFormula
)
126 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
127 ScDocument
* pDoc
= pDocSh
->GetDocument();
128 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(pDoc
);
130 if ( !pActiveViewSh
|| !SC_MOD()->GetInputOptions().GetRangeFinder() )
133 // String aDelimiters = pEngine->GetWordDelimiters();
134 String aDelimiters
= ScEditUtil::ModifyDelimiters(
135 String::CreateFromAscii( pMinDelimiters
) );
137 xub_StrLen nColon
= aDelimiters
.Search(':');
138 if ( nColon
!= STRING_NOTFOUND
)
139 aDelimiters
.Erase( nColon
, 1 ); // Delimiter ohne Doppelpunkt
140 xub_StrLen nDot
= aDelimiters
.Search(cSheetSep
);
141 if ( nDot
!= STRING_NOTFOUND
)
142 aDelimiters
.Erase( nDot
, 1 ); // Delimiter ohne Punkt
144 const sal_Unicode
* pChar
= rFormula
.GetBuffer();
145 xub_StrLen nLen
= rFormula
.Len();
147 xub_StrLen nStart
= 0;
150 while ( nPos
< nLen
&& nCount
< RANGEFIND_MAX
)
152 // Trenner ueberlesen
153 while ( nPos
<nLen
&& ScGlobal::UnicodeStrChr( aDelimiters
.GetBuffer(), pChar
[nPos
] ) )
155 if ( pChar
[nPos
] == '"' ) // String
158 while (nPos
<nLen
&& pChar
[nPos
] != '"') // bis zum Ende ueberlesen
161 ++nPos
; // Trennzeichen oder schliessender Quote
164 // Text zwischen Trennern
167 while ( nPos
<nLen
&& !ScGlobal::UnicodeStrChr( aDelimiters
.GetBuffer(), pChar
[nPos
] ) )
170 // for R1C1 '-' in R[-]... or C[-]... are not delimiters
171 // Nothing heroic here to ensure that there are '[]' around a negative
172 // integer. we need to clean up this code.
173 if( nPos
< nLen
&& nPos
> 0 &&
174 '-' == pChar
[nPos
] && '[' == pChar
[nPos
-1] &&
176 formula::FormulaGrammar::CONV_XL_R1C1
== pDoc
->GetAddressConvention() )
184 String aTest
= rFormula
.Copy( nStart
, nPos
-nStart
);
185 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
186 USHORT nFlags
= aRange
.ParseAny( aTest
, pDoc
, aAddrDetails
);
187 if ( nFlags
& SCA_VALID
)
189 // Tabelle setzen, wenn nicht angegeben
190 if ( (nFlags
& SCA_TAB_3D
) == 0 )
191 aRange
.aStart
.SetTab( pActiveViewSh
->GetViewData()->GetTabNo() );
192 if ( (nFlags
& SCA_TAB2_3D
) == 0 )
193 aRange
.aEnd
.SetTab( aRange
.aStart
.Tab() );
197 pEngine
->SetUpdateMode( FALSE
);
198 pRangeFindList
= new ScRangeFindList( pDocSh
->GetTitle() );
201 ScRangeFindData
* pNew
= new ScRangeFindData( aRange
, nFlags
, nStart
, nPos
);
202 pRangeFindList
->Insert( pNew
);
204 ESelection
aSel( 0, nStart
, 0, nPos
);
205 SfxItemSet
aSet( pEngine
->GetEmptyItemSet() );
206 aSet
.Put( SvxColorItem( Color( ScRangeFindList::GetColorName( nCount
) ),
208 pEngine
->QuickSetAttribs( aSet
, aSel
);
213 // letzten Trenner nicht ueberlesen, koennte ja ein Quote sein (?)
218 pEngine
->SetUpdateMode( TRUE
);
220 pDocSh
->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER
) );
224 void lcl_Replace( EditView
* pView
, const String
& rNewStr
, const ESelection
& rOldSel
)
228 ESelection aOldSel
= pView
->GetSelection();
229 if (aOldSel
.HasRange())
230 pView
->SetSelection( ESelection( aOldSel
.nEndPara
, aOldSel
.nEndPos
,
231 aOldSel
.nEndPara
, aOldSel
.nEndPos
) );
233 EditEngine
* pEngine
= pView
->GetEditEngine();
234 pEngine
->QuickInsertText( rNewStr
, rOldSel
);
236 // Dummy-InsertText fuer Update und Paint
237 // dafuer muss oben die Selektion aufgehoben werden (vor QuickInsertText)
238 pView
->InsertText( EMPTY_STRING
, FALSE
);
240 xub_StrLen nLen
= pEngine
->GetTextLen(0);
241 ESelection
aSel( 0, nLen
, 0, nLen
);
242 pView
->SetSelection( aSel
); // Cursor ans Ende
246 void ScInputHandler::UpdateRange( USHORT nIndex
, const ScRange
& rNew
)
248 ScTabViewShell
* pDocView
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
249 if ( pDocView
&& pRangeFindList
&& nIndex
< pRangeFindList
->Count() )
251 ScRangeFindData
* pData
= pRangeFindList
->GetObject( nIndex
);
252 xub_StrLen nOldStart
= pData
->nSelStart
;
253 xub_StrLen nOldEnd
= pData
->nSelEnd
;
255 ScRange aJustified
= rNew
;
256 aJustified
.Justify(); // Ref in der Formel immer richtigherum anzeigen
258 ScDocument
* pDoc
= pDocView
->GetViewData()->GetDocument();
259 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
260 aJustified
.Format( aNewStr
, pData
->nFlags
, pDoc
, aAddrDetails
);
261 ESelection
aOldSel( 0, nOldStart
, 0, nOldEnd
);
265 lcl_Replace( pTopView
, aNewStr
, aOldSel
);
266 lcl_Replace( pTableView
, aNewStr
, aOldSel
);
268 bInRangeUpdate
= TRUE
;
270 bInRangeUpdate
= FALSE
;
272 long nDiff
= aNewStr
.Len() - (long)(nOldEnd
-nOldStart
);
275 pData
->nSelEnd
= (xub_StrLen
)(pData
->nSelEnd
+ nDiff
);
277 USHORT nCount
= (USHORT
) pRangeFindList
->Count();
278 for (USHORT i
=nIndex
+1; i
<nCount
; i
++)
280 ScRangeFindData
* pNext
= pRangeFindList
->GetObject( i
);
281 pNext
->nSelStart
= (xub_StrLen
)(pNext
->nSelStart
+ nDiff
);
282 pNext
->nSelEnd
= (xub_StrLen
)(pNext
->nSelEnd
+ nDiff
);
287 DBG_ERROR("UpdateRange: da fehlt was");
291 void ScInputHandler::DeleteRangeFinder()
293 ScTabViewShell
* pPaintView
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
294 if ( pRangeFindList
&& pPaintView
)
296 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
297 pRangeFindList
->SetHidden(TRUE
);
298 pDocSh
->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER
) ); // wegnehmen
299 DELETEZ(pRangeFindList
);
303 //==================================================================
305 inline String
GetEditText(EditEngine
* pEng
)
307 return ScEditUtil::GetSpaceDelimitedString(*pEng
);
310 void lcl_RemoveTabs(String
& rStr
)
313 while ( (nPos
=rStr
.Search('\t')) != STRING_NOTFOUND
)
314 rStr
.SetChar( nPos
, ' ' );
317 void lcl_RemoveLineEnd(String
& rStr
)
319 rStr
.ConvertLineEnd(LINEEND_LF
);
321 while ( (nPos
=rStr
.Search('\n')) != STRING_NOTFOUND
)
322 rStr
.SetChar( nPos
, ' ' );
325 xub_StrLen
lcl_MatchParenthesis( const String
& rStr
, xub_StrLen nPos
)
328 sal_Unicode c1
, c2
= 0;
329 c1
= rStr
.GetChar( nPos
);
368 return STRING_NOTFOUND
;
369 xub_StrLen nLen
= rStr
.Len();
370 const sal_Unicode
* p0
= rStr
.GetBuffer();
371 register const sal_Unicode
* p
;
372 const sal_Unicode
* p1
;
374 if ( nPos
< nLen
/ 2 )
389 // Odd number of quotes that we find ourselves in a string
390 BOOL bLookInString
= ((nQuotes
% 2) != 0);
391 BOOL bInString
= bLookInString
;
393 p1
= (nDir
< 0 ? p0
: p0
+ nLen
) ;
395 while ( p
!= p1
&& nLevel
)
400 bInString
= !bInString
;
401 if ( bLookInString
&& !bInString
)
402 p
= p1
; //That's it then
404 else if ( bInString
== bLookInString
)
413 return STRING_NOTFOUND
;
414 return (xub_StrLen
) (p
- p0
);
417 //==================================================================
419 ScInputHandler::ScInputHandler()
425 pFormulaData( NULL
),
426 pFormulaDataPara( NULL
),
429 nAutoPos( SCPOS_INVALID
),
435 eMode( SC_INPUT_NONE
),
438 bFormulaMode( FALSE
),
439 bInRangeUpdate( FALSE
),
440 bParenthesisShown( FALSE
),
441 bCreatingFuncView( FALSE
),
442 bInEnterHandler( FALSE
),
443 bCommandErrorShown( FALSE
),
444 bInOwnChange( FALSE
),
446 bCellHasPercentFormat( FALSE
),
448 eAttrAdjust( SVX_HOR_JUSTIFY_STANDARD
),
452 pLastPattern( NULL
),
453 pEditDefaults( NULL
),
454 bLastIsSymbol( FALSE
),
457 pRangeFindList( NULL
)
459 // The InputHandler is constructed with the view, so SfxViewShell::Current
460 // doesn't have the right view yet. pActiveViewSh is updated in NotifyChange.
461 pActiveViewSh
= NULL
;
463 // Bindings (nur noch fuer Invalidate benutzt) werden bei Bedarf aktuell geholt
466 __EXPORT
ScInputHandler::~ScInputHandler()
468 // Wenn dies der Applikations-InputHandler ist, wird der dtor erst nach SfxApplication::Main
469 // gerufen, darf sich also auf keine Sfx-Funktionen mehr verlassen
471 if ( !SFX_APP()->IsDowning() ) // inplace
472 EnterHandler(); // Eingabe noch abschliessen
474 if (SC_MOD()->GetRefInputHdl()==this)
475 SC_MOD()->SetRefInputHdl(NULL
);
477 if ( pInputWin
&& pInputWin
->GetInputHandler() == this )
478 pInputWin
->SetInputHandler( NULL
);
480 delete pRangeFindList
;
481 delete pEditDefaults
;
487 delete pFormulaDataPara
;
490 void ScInputHandler::SetRefScale( const Fraction
& rX
, const Fraction
& rY
)
492 if ( rX
!= aScaleX
|| rY
!= aScaleY
)
498 MapMode
aMode( MAP_100TH_MM
, Point(), aScaleX
, aScaleY
);
499 pEngine
->SetRefMapMode( aMode
);
504 void ScInputHandler::UpdateRefDevice()
509 BOOL bTextWysiwyg
= SC_MOD()->GetInputOptions().GetTextWysiwyg();
510 if ( bTextWysiwyg
&& pActiveViewSh
)
511 pEngine
->SetRefDevice( pActiveViewSh
->GetViewData()->GetDocument()->GetPrinter() );
513 pEngine
->SetRefDevice( NULL
);
515 MapMode
aMode( MAP_100TH_MM
, Point(), aScaleX
, aScaleY
);
516 pEngine
->SetRefMapMode( aMode
);
518 // SetRefDevice(NULL) uses VirtualDevice, SetRefMapMode forces creation of a local VDev,
519 // so the DigitLanguage can be safely modified (might use an own VDev instead of NULL).
520 if ( !( bTextWysiwyg
&& pActiveViewSh
) )
522 pEngine
->GetRefDevice()->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
526 void ScInputHandler::ImplCreateEditEngine()
532 const ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
533 pEngine
= new ScFieldEditEngine( pDoc
->GetEnginePool(), pDoc
->GetEditPool() );
536 pEngine
= new ScFieldEditEngine( EditEngine::CreatePool(), NULL
, TRUE
);
537 pEngine
->SetWordDelimiters( ScEditUtil::ModifyDelimiters( pEngine
->GetWordDelimiters() ) );
538 UpdateRefDevice(); // also sets MapMode
539 pEngine
->SetPaperSize( Size( 1000000, 1000000 ) );
540 pEditDefaults
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
542 pEngine
->SetControlWord( pEngine
->GetControlWord() | EE_CNTRL_AUTOCORRECT
);
543 pEngine
->SetModifyHdl( LINK( this, ScInputHandler
, ModifyHdl
) );
547 void ScInputHandler::UpdateAutoCorrFlag()
549 ULONG nCntrl
= pEngine
->GetControlWord();
552 // don't use pLastPattern here (may be invalid because of AutoStyle)
554 BOOL bDisable
= bLastIsSymbol
|| bFormulaMode
;
556 nCntrl
&= ~EE_CNTRL_AUTOCORRECT
;
558 nCntrl
|= EE_CNTRL_AUTOCORRECT
;
560 if ( nCntrl
!= nOld
)
561 pEngine
->SetControlWord(nCntrl
);
564 void ScInputHandler::UpdateSpellSettings( BOOL bFromStartTab
)
568 ScViewData
* pViewData
= pActiveViewSh
->GetViewData();
569 BOOL bOnlineSpell
= pViewData
->GetDocument()->GetDocOptions().IsAutoSpell();
571 // SetDefaultLanguage is independent of the language attributes,
572 // ScGlobal::GetEditDefaultLanguage is always used.
573 // It must be set every time in case the office language was changed.
575 pEngine
->SetDefaultLanguage( ScGlobal::GetEditDefaultLanguage() );
577 // if called for changed options, update flags only if already editing
578 // if called from StartTable, always update flags
580 if ( bFromStartTab
|| eMode
!= SC_INPUT_NONE
)
582 ULONG nCntrl
= pEngine
->GetControlWord();
585 nCntrl
|= EE_CNTRL_ONLINESPELLING
;
587 nCntrl
&= ~EE_CNTRL_ONLINESPELLING
;
588 // kein AutoCorrect auf Symbol-Font (EditEngine wertet Default nicht aus)
589 if ( pLastPattern
&& pLastPattern
->IsSymbolFont() )
590 nCntrl
&= ~EE_CNTRL_AUTOCORRECT
;
592 nCntrl
|= EE_CNTRL_AUTOCORRECT
;
593 if ( nCntrl
!= nOld
)
594 pEngine
->SetControlWord(nCntrl
);
596 ScDocument
* pDoc
= pViewData
->GetDocument();
597 pEngine
->SetForbiddenCharsTable( pDoc
->GetForbiddenCharacters() );
598 pEngine
->SetAsianCompressionMode( pDoc
->GetAsianCompression() );
599 pEngine
->SetKernAsianPunctuation( pDoc
->GetAsianKerning() );
600 pEngine
->SetDefaultHorizontalTextDirection(
601 (EEHorizontalTextDirection
)pDoc
->GetEditTextDirection( pViewData
->GetTabNo() ) );
602 pEngine
->SetFirstWordCapitalization( FALSE
);
605 // language is set separately, so the speller is needed only if online
606 // spelling is active
608 if ( bOnlineSpell
) {
609 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XSpellChecker1
> xXSpellChecker1( LinguMgr::GetSpellChecker() );
610 pEngine
->SetSpeller( xXSpellChecker1
);
613 BOOL bHyphen
= pLastPattern
&& ((const SfxBoolItem
&)pLastPattern
->GetItem(ATTR_HYPHENATE
)).GetValue();
615 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
616 pEngine
->SetHyphenator( xXHyphenator
);
622 // Funktionen/Bereichsnamen etc. als Tip-Hilfe
625 #define SC_STRTYPE_FUNCTIONS 1
626 // die anderen Typen sind in ScDocument::GetFormulaEntries festgelegt
628 void ScInputHandler::GetFormulaData()
632 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
635 pFormulaData
->FreeAll();
637 pFormulaData
= new TypedScStrCollection
;
639 if( pFormulaDataPara
)
640 pFormulaDataPara
->FreeAll();
642 pFormulaDataPara
= new TypedScStrCollection
;
644 // MRU-Funktionen aus dem Funktions-Autopiloten
645 // wie in ScPosWnd::FillFunctions (inputwin.cxx)
647 const ScAppOptions
& rOpt
= SC_MOD()->GetAppOptions();
648 USHORT nMRUCount
= rOpt
.GetLRUFuncListCount();
649 const USHORT
* pMRUList
= rOpt
.GetLRUFuncList();
650 const ScFunctionList
* pFuncList
= ScGlobal::GetStarCalcFunctionList();
651 ULONG nListCount
= pFuncList
->GetCount();
654 for (USHORT i
=0; i
<nMRUCount
; i
++)
656 USHORT nId
= pMRUList
[i
];
657 for (ULONG j
=0; j
<nListCount
; j
++)
659 const ScFuncDesc
* pDesc
= pFuncList
->GetFunction( j
);
660 if ( pDesc
->nFIndex
== nId
&& pDesc
->pFuncName
)
662 String aEntry
= *pDesc
->pFuncName
;
663 aEntry
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
664 TypedStrData
* pData
= new TypedStrData( aEntry
, 0.0, SC_STRTYPE_FUNCTIONS
);
665 if (!pFormulaData
->Insert(pData
))
667 break; // nicht weitersuchen
672 for(ULONG i
=0;i
<nListCount
;i
++)
674 const ScFuncDesc
* pDesc
= pFuncList
->GetFunction( i
);
675 if ( pDesc
->pFuncName
)
677 pDesc
->initArgumentInfo();
678 String aEntry
= pDesc
->GetSignature();
679 TypedStrData
* pData
= new TypedStrData( aEntry
, 0.0, SC_STRTYPE_FUNCTIONS
);
680 if (!pFormulaDataPara
->Insert(pData
))
684 pDoc
->GetFormulaEntries( *pFormulaData
);
685 pDoc
->GetFormulaEntries( *pFormulaDataPara
);
689 void ScInputHandler::HideTip()
693 Help::HideTip( nTipVisible
);
698 void ScInputHandler::HideTipBelow()
700 if ( nTipVisibleSec
)
702 Help::HideTip( nTipVisibleSec
);
708 void ScInputHandler::ShowTipCursor()
712 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
713 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
714 const sal_Unicode cSep
= ScCompiler::GetNativeSymbol(ocSep
).GetChar(0);
715 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(pDocSh
->GetDocument());
717 if ( bFormulaMode
&& pActiveView
&& pFormulaDataPara
&& pEngine
->GetParagraphCount() == 1 )
719 String aFormula
= pEngine
->GetText( (USHORT
) 0 );
720 ESelection aSel
= pActiveView
->GetSelection();
722 xub_StrLen nLeftParentPos
= 0;
725 if ( aFormula
.Len() < aSel
.nEndPos
)
727 xub_StrLen nPos
= aSel
.nEndPos
;
728 String aSelText
= aFormula
.Copy( 0, nPos
);
729 xub_StrLen nNextFStart
= 0;
730 xub_StrLen nNextFEnd
= 0;
731 xub_StrLen nArgPos
= 0;
732 const IFunctionDescription
* ppFDesc
;
733 ::std::vector
< ::rtl::OUString
> aArgs
;
736 FormulaHelper
aHelper(ScGlobal::GetStarCalcFunctionMgr());
740 aSelText
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
741 nLeftParentPos
= lcl_MatchParenthesis( aSelText
, aSelText
.Len()-1 );
742 if( nLeftParentPos
!= STRING_NOTFOUND
)
744 sal_Unicode c
= ( nLeftParentPos
> 0 ) ? aSelText
.GetChar( nLeftParentPos
-1 ) : 0;
745 if( !((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z' )) )
747 nNextFStart
= aHelper
.GetFunctionStart( aSelText
, nLeftParentPos
, TRUE
);
748 if( aHelper
.GetNextFunc( aSelText
, FALSE
, nNextFStart
, &nNextFEnd
, &ppFDesc
, &aArgs
) )
750 if( ppFDesc
->getFunctionName().getLength() )
752 nArgPos
= aHelper
.GetArgStart( aSelText
, nNextFStart
, 0 );
753 nArgs
= static_cast<USHORT
>(ppFDesc
->getParameterCount());
757 USHORT nCountSemicolon
= 0;
758 USHORT nCountDot
= 0;
759 USHORT nStartPosition
= 0;
760 USHORT nEndPosition
= 0;
763 USHORT nParAutoPos
= SCPOS_INVALID
;
764 if( pFormulaDataPara
->FindText( ppFDesc
->getFunctionName(), aNew
, nParAutoPos
, FALSE
) )
766 for( USHORT i
=0; i
< nArgs
; i
++ )
768 xub_StrLen nLength
= static_cast<xub_StrLen
>(aArgs
[i
].getLength());
769 if( nArgPos
<= aSelText
.Len()-1 )
778 nCountSemicolon
= aNew
.GetTokenCount(cSep
)-1;
779 nCountDot
= aNew
.GetTokenCount(cSheetSep
)-1;
781 if( !nCountSemicolon
)
783 for( USHORT i
= 0; i
< aNew
.Len(); i
++ )
785 sal_Unicode cNext
= aNew
.GetChar( i
);
788 nStartPosition
= i
+1;
792 else if( !nCountDot
)
794 for( USHORT i
= 0; i
< aNew
.Len(); i
++ )
796 sal_Unicode cNext
= aNew
.GetChar( i
);
799 nStartPosition
= i
+1;
801 else if( cNext
== cSep
)
805 if( nCount
== nActive
)
809 nStartPosition
= nEndPosition
+1;
815 for( USHORT i
= 0; i
< aNew
.Len(); i
++ )
817 sal_Unicode cNext
= aNew
.GetChar( i
);
820 nStartPosition
= i
+1;
822 else if( cNext
== cSep
)
826 if( nCount
== nActive
)
830 nStartPosition
= nEndPosition
+1;
832 else if( cNext
== cSheetSep
)
841 aNew
.Insert( 0x25BA, nStartPosition
);
842 ShowTipBelow( aNew
);
848 ShowTipBelow( aNew
);
857 USHORT nPosition
= 0;
858 String aText
= pEngine
->GetWord( 0, aSel
.nEndPos
-1 );
859 if( aText
.GetChar( aSel
.nEndPos
-1 ) == '=' )
864 USHORT nParAutoPos
= SCPOS_INVALID
;
865 nPosition
= aText
.Len()+1;
866 if( pFormulaDataPara
->FindText( aText
, aNew
, nParAutoPos
, FALSE
) )
868 if( aFormula
.GetChar( nPosition
) =='(' )
870 ShowTipBelow( aNew
);
886 void ScInputHandler::ShowTip( const String
& rText
)
888 // aManualTip muss hinterher von aussen gesetzt werden
891 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
895 Window
* pWin
= pActiveView
->GetWindow();
896 Cursor
* pCur
= pActiveView
->GetCursor();
898 aPos
= pWin
->LogicToPixel( pCur
->GetPos() );
899 aPos
= pWin
->OutputToScreenPixel( aPos
);
900 Rectangle
aRect( aPos
, aPos
);
902 USHORT nAlign
= QUICKHELP_LEFT
|QUICKHELP_BOTTOM
;
903 nTipVisible
= Help::ShowTip(pWin
, aRect
, rText
, nAlign
);
907 void ScInputHandler::ShowTipBelow( const String
& rText
)
911 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
915 Window
* pWin
= pActiveView
->GetWindow();
916 Cursor
* pCur
= pActiveView
->GetCursor();
919 Point aLogicPos
= pCur
->GetPos();
920 aLogicPos
.Y() += pCur
->GetHeight();
921 aPos
= pWin
->LogicToPixel( aLogicPos
);
923 aPos
= pWin
->OutputToScreenPixel( aPos
);
924 Rectangle
aRect( aPos
, aPos
);
925 USHORT nAlign
= QUICKHELP_LEFT
| QUICKHELP_TOP
;
926 nTipVisibleSec
= Help::ShowTip(pWin
, aRect
, rText
, nAlign
);
930 void ScInputHandler::UseFormulaData()
932 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
933 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
934 const sal_Unicode cSep
= ScCompiler::GetNativeSymbol(ocSep
).GetChar(0);
935 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(pDocSh
->GetDocument());
937 // Formeln duerfen nur 1 Absatz haben
938 if ( pActiveView
&& pFormulaData
&& pEngine
->GetParagraphCount() == 1 )
940 String aTotal
= pEngine
->GetText( (USHORT
) 0 );
941 ESelection aSel
= pActiveView
->GetSelection();
944 // #59348# Durch Differenzen zwischen Tabelle und Eingabezeile
945 // (z.B. Clipboard mit Zeilenumbruechen) kann es sein, dass die Selektion
946 // nicht mehr zur EditEngine passt. Dann halt kommentarlos abbrechen:
948 if ( aSel
.nEndPos
> aTotal
.Len() )
951 // steht der Cursor am Ende eines Wortes?
953 if ( aSel
.nEndPos
> 0 )
955 xub_StrLen nPos
= aSel
.nEndPos
;
956 String aFormula
= aTotal
.Copy( 0, nPos
);;
957 xub_StrLen nLeftParentPos
= 0;
958 xub_StrLen nNextFStart
= 0;
959 xub_StrLen nNextFEnd
= 0;
960 xub_StrLen nArgPos
= 0;
961 const IFunctionDescription
* ppFDesc
;
962 ::std::vector
< ::rtl::OUString
> aArgs
;
966 String aText
= pEngine
->GetWord( 0, aSel
.nEndPos
-1 );
970 nAutoPos
= SCPOS_INVALID
;
971 if ( pFormulaData
->FindText( aText
, aNew
, nAutoPos
, FALSE
) )
977 FormulaHelper
aHelper(ScGlobal::GetStarCalcFunctionMgr());
981 aFormula
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
982 nLeftParentPos
= lcl_MatchParenthesis( aFormula
, aFormula
.Len()-1 );
983 if( nLeftParentPos
== STRING_NOTFOUND
)
986 // #160063# nLeftParentPos can be 0 if a parenthesis is inserted before the formula
987 sal_Unicode c
= ( nLeftParentPos
> 0 ) ? aFormula
.GetChar( nLeftParentPos
-1 ) : 0;
988 if( !((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z') ) )
990 nNextFStart
= aHelper
.GetFunctionStart( aFormula
, nLeftParentPos
, TRUE
);
991 if( aHelper
.GetNextFunc( aFormula
, FALSE
, nNextFStart
, &nNextFEnd
, &ppFDesc
, &aArgs
) )
993 if( ppFDesc
->getFunctionName().getLength() )
995 nArgPos
= aHelper
.GetArgStart( aFormula
, nNextFStart
, 0 );
996 nArgs
= static_cast<USHORT
>(ppFDesc
->getParameterCount());
1000 USHORT nCountSemicolon
= 0;
1001 USHORT nCountDot
= 0;
1002 USHORT nStartPosition
= 0;
1003 USHORT nEndPosition
= 0;
1006 USHORT nParAutoPos
= SCPOS_INVALID
;
1007 if( pFormulaDataPara
->FindText( ppFDesc
->getFunctionName(), aNew
, nParAutoPos
, FALSE
) )
1009 for( USHORT i
=0; i
< nArgs
; i
++ )
1011 xub_StrLen nLength
= static_cast<xub_StrLen
>(aArgs
[i
].getLength());
1012 if( nArgPos
<= aFormula
.Len()-1 )
1021 nCountSemicolon
= aNew
.GetTokenCount(cSep
)-1;
1022 nCountDot
= aNew
.GetTokenCount(cSheetSep
)-1;
1024 if( !nCountSemicolon
)
1026 for( USHORT i
= 0; i
< aNew
.Len(); i
++ )
1028 sal_Unicode cNext
= aNew
.GetChar( i
);
1031 nStartPosition
= i
+1;
1035 else if( !nCountDot
)
1037 for( USHORT i
= 0; i
< aNew
.Len(); i
++ )
1039 sal_Unicode cNext
= aNew
.GetChar( i
);
1042 nStartPosition
= i
+1;
1044 else if( cNext
== cSep
)
1048 if( nCount
== nActive
)
1052 nStartPosition
= nEndPosition
+1;
1058 for( USHORT i
= 0; i
< aNew
.Len(); i
++ )
1060 sal_Unicode cNext
= aNew
.GetChar( i
);
1063 nStartPosition
= i
+1;
1065 else if( cNext
== cSep
)
1069 if( nCount
== nActive
)
1073 nStartPosition
= nEndPosition
+1;
1075 else if( cNext
== cSheetSep
)
1082 if( nStartPosition
)
1084 aNew
.Insert( 0x25BA, nStartPosition
);
1085 ShowTipBelow( aNew
);
1091 ShowTipBelow( aNew
);
1102 void ScInputHandler::NextFormulaEntry( BOOL bBack
)
1104 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1105 if ( pActiveView
&& pFormulaData
)
1108 if ( pFormulaData
->FindText( aAutoSearch
, aNew
, nAutoPos
, bBack
) )
1109 ShowTip( aNew
); // als QuickHelp anzeigen
1112 // bei Tab wird vorher immer HideCursor gerufen
1115 pActiveView
->ShowCursor();
1118 void lcl_CompleteFunction( EditView
* pView
, const String
& rInsert
, BOOL
& rParInserted
)
1122 ESelection aSel
= pView
->GetSelection();
1125 pView
->SetSelection(aSel
);
1126 pView
->SelectCurrentWord();
1128 String aInsStr
= rInsert
;
1129 xub_StrLen nInsLen
= aInsStr
.Len();
1130 BOOL bDoParen
= ( nInsLen
> 1 && aInsStr
.GetChar(nInsLen
-2) == '('
1131 && aInsStr
.GetChar(nInsLen
-1) == ')' );
1134 // Klammern hinter Funktionsnamen nicht einfuegen, wenn direkt dahinter
1135 // schon eine Klammer steht (z.B. wenn der Funktionsname geaendert wurde,
1138 ESelection aWordSel
= pView
->GetSelection();
1139 String aOld
= pView
->GetEditEngine()->GetText((USHORT
)0);
1140 sal_Unicode cNext
= aOld
.GetChar(aWordSel
.nEndPos
);
1144 aInsStr
.Erase( nInsLen
- 2 ); // Klammern weglassen
1148 pView
->InsertText( aInsStr
, FALSE
);
1150 if ( bDoParen
) // Cursor zwischen die Klammern setzen
1152 aSel
= pView
->GetSelection();
1155 pView
->SetSelection(aSel
);
1157 rParInserted
= TRUE
;
1162 void ScInputHandler::PasteFunctionData()
1164 if ( pFormulaData
&& nAutoPos
!= SCPOS_INVALID
)
1166 TypedStrData
* pData
= (*pFormulaData
)[nAutoPos
];
1169 String aInsert
= pData
->GetString();
1170 BOOL bParInserted
= FALSE
;
1172 DataChanging(); // kann nicht neu sein
1173 lcl_CompleteFunction( pTopView
, aInsert
, bParInserted
);
1174 lcl_CompleteFunction( pTableView
, aInsert
, bParInserted
);
1185 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1187 pActiveView
->ShowCursor();
1191 // Selektion berechnen und als Tip-Hilfe anzeigen
1194 String
lcl_Calculate( const String
& rFormula
, ScDocument
* pDoc
, const ScAddress
&rPos
)
1196 //! mit ScFormulaDlg::CalcValue zusammenfassen und ans Dokument verschieben !!!!
1197 //! (Anfuehrungszeichen bei Strings werden nur hier eingefuegt)
1203 ScFormulaCell
* pCell
= new ScFormulaCell( pDoc
, rPos
, rFormula
);
1205 // #35521# HACK! um bei ColRowNames kein #REF! zu bekommen,
1206 // wenn ein Name eigentlich als Bereich in die Gesamt-Formel
1207 // eingefuegt wird, bei der Einzeldarstellung aber als
1208 // single-Zellbezug interpretiert wird
1209 BOOL bColRowName
= pCell
->HasColRowName();
1212 // ColRowName im RPN-Code?
1213 if ( pCell
->GetCode()->GetCodeLen() <= 1 )
1214 { // ==1: einzelner ist als Parameter immer Bereich
1215 // ==0: es waere vielleicht einer, wenn..
1216 String
aBraced( '(' );
1217 aBraced
+= rFormula
;
1220 pCell
= new ScFormulaCell( pDoc
, rPos
, aBraced
);
1223 bColRowName
= FALSE
;
1226 USHORT nErrCode
= pCell
->GetErrCode();
1227 if ( nErrCode
== 0 )
1229 SvNumberFormatter
& aFormatter
= *(pDoc
->GetFormatTable());
1231 if ( pCell
->IsValue() )
1233 double n
= pCell
->GetValue();
1234 ULONG nFormat
= aFormatter
.GetStandardFormat( n
, 0,
1235 pCell
->GetFormatType(), ScGlobal::eLnge
);
1236 aFormatter
.GetInputLineString( n
, nFormat
, aValue
);
1237 //! display OutputString but insert InputLineString
1243 pCell
->GetString( aStr
);
1244 ULONG nFormat
= aFormatter
.GetStandardFormat(
1245 pCell
->GetFormatType(), ScGlobal::eLnge
);
1246 aFormatter
.GetOutputString( aStr
, nFormat
,
1249 aValue
.Insert('"',0); // in Anfuehrungszeichen
1251 //! Anfuehrungszeichen im String escapen ????
1255 if ( bColRowName
|| (aTestRange
.Parse(rFormula
) & SCA_VALID
) )
1256 aValue
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " ..." )); // Bereich
1259 aValue
= ScGlobal::GetErrorString(nErrCode
);
1266 void ScInputHandler::FormulaPreview()
1269 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1270 if ( pActiveView
&& pActiveViewSh
)
1272 String aPart
= pActiveView
->GetSelected();
1274 aPart
= pEngine
->GetText((USHORT
)0);
1275 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1276 aValue
= lcl_Calculate( aPart
, pDoc
, aCursorPos
);
1281 ShowTip( aValue
); // als QuickHelp anzeigen
1282 aManualTip
= aValue
; // nach ShowTip setzen
1283 nAutoPos
= SCPOS_INVALID
; // Formel-Autocomplete aufheben
1287 void ScInputHandler::PasteManualTip()
1289 // drei Punkte am Ende -> Bereichsreferenz -> nicht einfuegen
1290 // (wenn wir mal Matrix-Konstanten haben, kann das geaendert werden)
1292 xub_StrLen nTipLen
= aManualTip
.Len();
1293 if ( nTipLen
&& ( nTipLen
< 3 || !aManualTip
.Copy( nTipLen
-3 ).EqualsAscii("...") ) )
1295 DataChanging(); // kann nicht neu sein
1297 String aInsert
= aManualTip
;
1298 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1299 if (!pActiveView
->HasSelection())
1301 // nichts selektiert -> alles selektieren
1302 xub_StrLen nOldLen
= pEngine
->GetTextLen(0);
1303 ESelection
aAllSel( 0, 0, 0, nOldLen
);
1305 pTopView
->SetSelection( aAllSel
);
1307 pTableView
->SetSelection( aAllSel
);
1310 ESelection aSel
= pActiveView
->GetSelection();
1312 DBG_ASSERT( !aSel
.nStartPara
&& !aSel
.nEndPara
, "Zuviele Absaetze in Formel" );
1313 if ( !aSel
.nStartPos
) // Selektion ab Anfang?
1315 if ( aSel
.nEndPos
== pEngine
->GetTextLen(0) )
1317 // alles selektiert -> Anfuehrungszeichen weglassen
1318 if ( aInsert
.GetChar(0) == '"' )
1320 xub_StrLen nInsLen
= aInsert
.Len();
1321 if ( nInsLen
&& aInsert
.GetChar(nInsLen
-1) == '"' )
1322 aInsert
.Erase( nInsLen
-1 );
1324 else if ( aSel
.nEndPos
)
1326 // nicht alles selektiert -> Gleichheitszeichen nicht ueberschreiben
1327 //! doppelte Gleichheitszeichen auch ???
1331 pTopView
->SetSelection( aSel
);
1333 pTableView
->SetSelection( aSel
);
1337 pTopView
->InsertText( aInsert
, TRUE
);
1339 pTableView
->InsertText( aInsert
, TRUE
);
1347 void ScInputHandler::ResetAutoPar()
1352 void ScInputHandler::AutoParAdded()
1354 ++nAutoPar
; // closing parenthesis can be overwritten
1357 BOOL
ScInputHandler::CursorAtClosingPar()
1359 // test if the cursor is before a closing parenthesis
1361 // selection from SetReference has been removed before
1362 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1363 if ( pActiveView
&& !pActiveView
->HasSelection() && bFormulaMode
)
1365 ESelection aSel
= pActiveView
->GetSelection();
1366 xub_StrLen nPos
= aSel
.nStartPos
;
1367 String aFormula
= pEngine
->GetText((USHORT
)0);
1368 if ( nPos
< aFormula
.Len() && aFormula
.GetChar(nPos
) == ')' )
1374 void ScInputHandler::SkipClosingPar()
1376 // this is called when a ')' is typed and the cursor is before a ')'
1377 // that can be overwritten -> just set the cursor behind the ')'
1379 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1382 ESelection aSel
= pActiveView
->GetSelection();
1386 // this is in a formula (only one paragraph), so the selection
1387 // can be used directly for the TopView
1390 pTopView
->SetSelection( aSel
);
1392 pTableView
->SetSelection( aSel
);
1395 DBG_ASSERT(nAutoPar
, "SkipClosingPar: count is wrong");
1403 void ScInputHandler::GetColData()
1405 if ( pActiveViewSh
)
1407 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1410 pColumnData
->FreeAll();
1413 pColumnData
= new TypedScStrCollection
;
1414 pColumnData
->SetCaseSensitive( TRUE
); // equal strings are handled in FindText
1417 pDoc
->GetDataEntries( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab(),
1418 *pColumnData
, TRUE
);
1422 void ScInputHandler::UseColData() // beim Tippen
1424 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1425 if ( pActiveView
&& pColumnData
)
1427 // nur anpassen, wenn Cursor am Ende steht
1429 ESelection aSel
= pActiveView
->GetSelection();
1432 USHORT nParCnt
= pEngine
->GetParagraphCount();
1433 if ( aSel
.nEndPara
+1 == nParCnt
)
1435 xub_StrLen nParLen
= pEngine
->GetTextLen( aSel
.nEndPara
);
1436 if ( aSel
.nEndPos
== nParLen
)
1438 String aText
= GetEditText(pEngine
);
1442 nAutoPos
= SCPOS_INVALID
; // nix
1443 if ( pColumnData
->FindText( aText
, aNew
, nAutoPos
, FALSE
) )
1445 // #45434# durch dBase Import etc. koennen Umbrueche im String sein,
1446 // das wuerde hier mehrere Absaetze ergeben -> nicht gut
1447 //! GetExactMatch funktioniert dann auch nicht
1448 lcl_RemoveLineEnd( aNew
);
1450 // Absaetze beibehalten, nur den Rest anfuegen
1451 //! genaue Ersetzung im EnterHandler !!!
1453 // ein Space zwischen Absaetzen:
1454 ULONG nEdLen
= pEngine
->GetTextLen() + nParCnt
- 1;
1455 String aIns
= aNew
.Copy( (xub_StrLen
)nEdLen
);
1457 // selection must be "backwards", so the cursor stays behind the last
1459 ESelection
aSelection( aSel
.nEndPara
, aSel
.nEndPos
+ aIns
.Len(),
1460 aSel
.nEndPara
, aSel
.nEndPos
);
1462 // when editing in input line, apply to both edit views
1465 pTableView
->InsertText( aIns
, FALSE
);
1466 pTableView
->SetSelection( aSelection
);
1470 pTopView
->InsertText( aIns
, FALSE
);
1471 pTopView
->SetSelection( aSelection
);
1474 aAutoSearch
= aText
; // zum Weitersuchen - nAutoPos ist gesetzt
1476 if ( aText
.Len() == aNew
.Len() )
1478 // Wenn der eingegebene Text gefunden wurde, TAB nur dann
1479 // verschlucken, wenn noch etwas kommt
1482 USHORT nNextPos
= nAutoPos
;
1483 bUseTab
= pColumnData
->FindText( aText
, aDummy
, nNextPos
, FALSE
);
1494 void ScInputHandler::NextAutoEntry( BOOL bBack
)
1496 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1497 if ( pActiveView
&& pColumnData
)
1499 if ( nAutoPos
!= SCPOS_INVALID
&& aAutoSearch
.Len() )
1501 // stimmt die Selektion noch? (kann per Maus geaendert sein)
1503 ESelection aSel
= pActiveView
->GetSelection();
1505 USHORT nParCnt
= pEngine
->GetParagraphCount();
1506 if ( aSel
.nEndPara
+1 == nParCnt
&& aSel
.nStartPara
== aSel
.nEndPara
)
1508 String aText
= GetEditText(pEngine
);
1509 xub_StrLen nSelLen
= aSel
.nEndPos
- aSel
.nStartPos
;
1510 xub_StrLen nParLen
= pEngine
->GetTextLen( aSel
.nEndPara
);
1511 if ( aSel
.nEndPos
== nParLen
&& aText
.Len() == aAutoSearch
.Len() + nSelLen
)
1514 if ( pColumnData
->FindText( aAutoSearch
, aNew
, nAutoPos
, bBack
) )
1516 bInOwnChange
= TRUE
; // disable ModifyHdl (reset below)
1518 lcl_RemoveLineEnd( aNew
);
1519 String aIns
= aNew
.Copy( aAutoSearch
.Len() );
1521 // when editing in input line, apply to both edit views
1524 pTableView
->DeleteSelected();
1525 pTableView
->InsertText( aIns
, FALSE
);
1526 pTableView
->SetSelection( ESelection(
1527 aSel
.nEndPara
, aSel
.nStartPos
+ aIns
.Len(),
1528 aSel
.nEndPara
, aSel
.nStartPos
) );
1532 pTopView
->DeleteSelected();
1533 pTopView
->InsertText( aIns
, FALSE
);
1534 pTopView
->SetSelection( ESelection(
1535 aSel
.nEndPara
, aSel
.nStartPos
+ aIns
.Len(),
1536 aSel
.nEndPara
, aSel
.nStartPos
) );
1539 bInOwnChange
= FALSE
;
1552 // bei Tab wird vorher immer HideCursor gerufen
1555 pActiveView
->ShowCursor();
1559 // Klammern hervorheben
1562 void ScInputHandler::UpdateParenthesis()
1566 //! Klammer-Hervorhebung einzeln abschaltbar ????
1568 BOOL bFound
= FALSE
;
1569 if ( bFormulaMode
&& eMode
!= SC_INPUT_TOP
)
1571 if ( pTableView
&& !pTableView
->HasSelection() ) // Selektion ist immer unten
1573 ESelection aSel
= pTableView
->GetSelection();
1576 // Das Zeichen links vom Cursor wird angeschaut
1578 xub_StrLen nPos
= aSel
.nStartPos
- 1;
1579 String aFormula
= pEngine
->GetText((USHORT
)0);
1580 sal_Unicode c
= aFormula
.GetChar(nPos
);
1581 if ( c
== '(' || c
== ')' )
1583 xub_StrLen nOther
= lcl_MatchParenthesis( aFormula
, nPos
);
1584 if ( nOther
!= STRING_NOTFOUND
)
1586 SfxItemSet
aSet( pEngine
->GetEmptyItemSet() );
1587 aSet
.Put( SvxWeightItem( WEIGHT_BOLD
, EE_CHAR_WEIGHT
) );
1588 //! Unterscheidung, wenn die Zelle schon fett ist !!!!
1590 if (bParenthesisShown
)
1592 // alte Hervorhebung wegnehmen
1593 USHORT nCount
= pEngine
->GetParagraphCount();
1594 for (USHORT i
=0; i
<nCount
; i
++)
1595 pEngine
->QuickRemoveCharAttribs( i
, EE_CHAR_WEIGHT
);
1598 ESelection
aSelThis( 0,nPos
, 0,nPos
+1 );
1599 pEngine
->QuickSetAttribs( aSet
, aSelThis
);
1600 ESelection
aSelOther( 0,nOther
, 0,nOther
+1 );
1601 pEngine
->QuickSetAttribs( aSet
, aSelOther
);
1603 // Dummy-InsertText fuer Update und Paint (Selektion ist leer)
1604 pTableView
->InsertText( EMPTY_STRING
, FALSE
);
1611 // mark parenthesis right of cursor if it will be overwritten (nAutoPar)
1612 // with different color (COL_LIGHTBLUE) ??
1616 // alte Hervorhebung wegnehmen, wenn keine neue gesetzt
1618 if ( bParenthesisShown
&& !bFound
&& pTableView
)
1620 USHORT nCount
= pEngine
->GetParagraphCount();
1621 for (USHORT i
=0; i
<nCount
; i
++)
1622 pTableView
->RemoveCharAttribs( i
, EE_CHAR_WEIGHT
);
1625 bParenthesisShown
= bFound
;
1628 void ScInputHandler::ViewShellGone(ScTabViewShell
* pViewSh
) // wird synchron aufgerufen!
1630 if ( pViewSh
== pActiveViewSh
)
1634 pLastPattern
= NULL
;
1637 if ( pViewSh
== pRefViewSh
)
1639 //! Die Eingabe kommt aus dem EnterHandler nicht mehr an
1640 // Trotzdem wird immerhin der Editmodus beendet
1643 bFormulaMode
= FALSE
;
1645 SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
1646 SC_MOD()->SetRefInputHdl(NULL
);
1648 pInputWin
->SetFormulaMode(FALSE
);
1649 UpdateAutoCorrFlag();
1652 pActiveViewSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
1654 if ( pActiveViewSh
&& pActiveViewSh
== pViewSh
)
1656 DBG_ERROR("pActiveViewSh weg");
1657 pActiveViewSh
= NULL
;
1660 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
1661 UpdateRefDevice(); // don't keep old document's printer as RefDevice
1664 void ScInputHandler::UpdateActiveView()
1666 ImplCreateEditEngine();
1668 // #i20588# Don't rely on focus to find the active edit view. Instead, the
1669 // active pane at the start of editing is now stored (GetEditActivePart).
1670 // GetActiveWin (the currently active pane) fails for ref input across the
1671 // panes of a split view.
1673 Window
* pShellWin
= pActiveViewSh
?
1674 pActiveViewSh
->GetWindowByPos( pActiveViewSh
->GetViewData()->GetEditActivePart() ) :
1677 USHORT nCount
= pEngine
->GetViewCount();
1680 pTableView
= pEngine
->GetView(0);
1681 for (USHORT i
=1; i
<nCount
; i
++)
1683 EditView
* pThis
= pEngine
->GetView(i
);
1684 Window
* pWin
= pThis
->GetWindow();
1685 if ( pWin
==pShellWin
)
1693 pTopView
= pInputWin
->GetEditView();
1698 void ScInputHandler::StopInputWinEngine( BOOL bAll
)
1701 pInputWin
->StopEditEngine( bAll
);
1703 pTopView
= NULL
; // invalid now
1706 EditView
* ScInputHandler::GetActiveView()
1709 return pTopView
? pTopView
: pTableView
;
1712 void ScInputHandler::ForgetLastPattern()
1714 pLastPattern
= NULL
;
1715 if ( !pLastState
&& pActiveViewSh
)
1716 pActiveViewSh
->UpdateInputHandler( TRUE
); // Status neu holen
1718 NotifyChange( pLastState
, TRUE
);
1721 void ScInputHandler::UpdateAdjust( sal_Unicode cTyped
)
1723 SvxAdjust eSvxAdjust
;
1724 switch (eAttrAdjust
)
1726 case SVX_HOR_JUSTIFY_STANDARD
:
1728 BOOL bNumber
= FALSE
;
1729 if (cTyped
) // neu angefangen
1730 bNumber
= (cTyped
>='0' && cTyped
<='9'); // nur Ziffern sind Zahlen
1731 else if ( pActiveViewSh
)
1733 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1734 bNumber
= ( pDoc
->GetCellType( aCursorPos
) == CELLTYPE_VALUE
);
1736 eSvxAdjust
= bNumber
? SVX_ADJUST_RIGHT
: SVX_ADJUST_LEFT
;
1739 case SVX_HOR_JUSTIFY_BLOCK
:
1740 eSvxAdjust
= SVX_ADJUST_BLOCK
;
1742 case SVX_HOR_JUSTIFY_CENTER
:
1743 eSvxAdjust
= SVX_ADJUST_CENTER
;
1745 case SVX_HOR_JUSTIFY_RIGHT
:
1746 eSvxAdjust
= SVX_ADJUST_RIGHT
;
1748 default: // SVX_HOR_JUSTIFY_LEFT
1749 eSvxAdjust
= SVX_ADJUST_LEFT
;
1753 BOOL bAsianVertical
= pLastPattern
&&
1754 ((const SfxBoolItem
&)pLastPattern
->GetItem( ATTR_STACKED
)).GetValue() &&
1755 ((const SfxBoolItem
&)pLastPattern
->GetItem( ATTR_VERTICAL_ASIAN
)).GetValue();
1756 if ( bAsianVertical
)
1758 // always edit at top of cell -> LEFT when editing vertically
1759 eSvxAdjust
= SVX_ADJUST_LEFT
;
1762 pEditDefaults
->Put( SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
1763 pEngine
->SetDefaults( *pEditDefaults
);
1765 nEditAdjust
= sal::static_int_cast
<USHORT
>(eSvxAdjust
); //! set at ViewData or with PostEditView
1767 pEngine
->SetVertical( bAsianVertical
);
1770 void ScInputHandler::RemoveAdjust()
1772 // harte Ausrichtungs-Attribute loeschen
1774 BOOL bUndo
= pEngine
->IsUndoEnabled();
1776 pEngine
->EnableUndo( FALSE
);
1778 // RemoveParaAttribs removes all paragraph attributes, including EE_PARA_JUST
1780 BOOL bChange
= FALSE
;
1781 USHORT nCount
= pEngine
->GetParagraphCount();
1782 for (USHORT i
=0; i
<nCount
; i
++)
1784 const SfxItemSet
& rOld
= pEngine
->GetParaAttribs( i
);
1785 if ( rOld
.GetItemState( EE_PARA_JUST
) == SFX_ITEM_SET
)
1787 SfxItemSet
aNew( rOld
);
1788 aNew
.ClearItem( EE_PARA_JUST
);
1789 pEngine
->SetParaAttribs( i
, aNew
);
1795 // #89403# non-default paragraph attributes (e.g. from clipboard)
1796 // must be turned into character attributes
1797 pEngine
->RemoveParaAttribs();
1800 pEngine
->EnableUndo( TRUE
);
1802 // ER 31.08.00 Only called in EnterHandler, don't change view anymore.
1806 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1807 pActiveView
->ShowCursor( FALSE
, TRUE
);
1812 void ScInputHandler::RemoveRangeFinder()
1814 // pRangeFindList und Farben loeschen
1816 pEngine
->SetUpdateMode(FALSE
);
1817 USHORT nCount
= pEngine
->GetParagraphCount(); // koennte gerade neu eingefuegt worden sein
1818 for (USHORT i
=0; i
<nCount
; i
++)
1819 pEngine
->QuickRemoveCharAttribs( i
, EE_CHAR_COLOR
);
1820 pEngine
->SetUpdateMode(TRUE
);
1822 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1823 pActiveView
->ShowCursor( FALSE
, TRUE
);
1825 DeleteRangeFinder(); // loescht die Liste und die Markierungen auf der Tabelle
1828 BOOL
ScInputHandler::StartTable( sal_Unicode cTyped
, BOOL bFromCommand
)
1830 // returns TRUE if a new edit mode was started
1832 BOOL bNewTable
= FALSE
;
1834 if (!bModified
&& ValidCol(aCursorPos
.Col()))
1838 ImplCreateEditEngine();
1842 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1844 const ScMarkData
& rMark
= pActiveViewSh
->GetViewData()->GetMarkData();
1845 ScEditableTester aTester
;
1846 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
1847 aTester
.TestSelection( pDoc
, rMark
);
1849 aTester
.TestSelectedBlock( pDoc
, aCursorPos
.Col(),aCursorPos
.Row(),
1850 aCursorPos
.Col(),aCursorPos
.Row(), rMark
);
1851 if ( aTester
.IsEditable() )
1853 // UpdateMode is enabled again in ScViewData::SetEditEngine (and not needed otherwise)
1854 pEngine
->SetUpdateMode( FALSE
);
1856 // Attribute in EditEngine uebernehmen
1858 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(),
1861 if (pPattern
!= pLastPattern
)
1865 const SfxItemSet
& rAttrSet
= pPattern
->GetItemSet();
1866 const SfxPoolItem
* pItem
;
1868 if ( SFX_ITEM_SET
== rAttrSet
.GetItemState( ATTR_VALUE_FORMAT
, TRUE
, &pItem
) )
1870 ULONG nFormat
= ((const SfxUInt32Item
*)pItem
)->GetValue();
1871 bCellHasPercentFormat
= ( NUMBERFORMAT_PERCENT
==
1872 pDoc
->GetFormatTable()->GetType( nFormat
) );
1875 bCellHasPercentFormat
= FALSE
; // Default: kein Prozent
1877 // Gueltigkeit angegeben?
1879 if ( SFX_ITEM_SET
== rAttrSet
.GetItemState( ATTR_VALIDDATA
, TRUE
, &pItem
) )
1880 nValidation
= ((const SfxUInt32Item
*)pItem
)->GetValue();
1884 // EditEngine Defaults
1886 // Hier auf keinen Fall SetParaAttribs, weil die EditEngine evtl.
1887 // schon gefuellt ist (bei Edit-Zellen).
1888 // SetParaAttribs wuerde dann den Inhalt aendern
1890 //! ER 30.08.00 The SetDefaults is now (since MUST/src602
1891 //! EditEngine changes) implemented as a SetParaAttribs.
1894 pPattern
->FillEditItemSet( pEditDefaults
);
1895 pEngine
->SetDefaults( *pEditDefaults
);
1896 pLastPattern
= pPattern
;
1897 bLastIsSymbol
= pPattern
->IsSymbolFont();
1899 // Background color must be known for automatic font color.
1900 // For transparent cell background, the document background color must be used.
1902 Color aBackCol
= ((const SvxBrushItem
&)
1903 pPattern
->GetItem( ATTR_BACKGROUND
)).GetColor();
1904 ScModule
* pScMod
= SC_MOD();
1905 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
1906 if ( aBackCol
.GetTransparency() > 0 ||
1907 Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1908 aBackCol
.SetColor( pScMod
->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
1909 pEngine
->SetBackgroundColor( aBackCol
);
1913 eAttrAdjust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)pPattern
->
1914 GetItem(ATTR_HOR_JUSTIFY
)).GetValue();
1915 if ( eAttrAdjust
== SVX_HOR_JUSTIFY_REPEAT
&&
1916 static_cast<const SfxBoolItem
&>(pPattern
->GetItem(ATTR_LINEBREAK
)).GetValue() )
1918 // #i31843# "repeat" with "line breaks" is treated as default alignment
1919 eAttrAdjust
= SVX_HOR_JUSTIFY_STANDARD
;
1923 // UpdateSpellSettings enables online spelling if needed
1924 // -> also call if attributes are unchanged
1926 UpdateSpellSettings( TRUE
); // uses pLastPattern
1928 // Edit-Engine fuellen
1933 pEngine
->SetText(aCurrentText
);
1934 aStr
= aCurrentText
;
1936 aCurrentText
.Erase();
1939 aStr
= GetEditText(pEngine
);
1941 if (aStr
.Len() > 3 && // Matrix-Formel ?
1942 aStr
.GetChar(0) == '{' &&
1943 aStr
.GetChar(1) == '=' &&
1944 aStr
.GetChar(aStr
.Len()-1) == '}')
1947 aStr
.Erase(aStr
.Len()-1,1);
1948 pEngine
->SetText(aStr
);
1950 pInputWin
->SetTextString(aStr
);
1953 UpdateAdjust( cTyped
);
1955 if ( bAutoComplete
)
1958 if ( ( aStr
.GetChar(0) == '=' || aStr
.GetChar(0) == '+' || aStr
.GetChar(0) == '-' ) &&
1959 !cTyped
&& !bCreatingFuncView
)
1960 InitRangeFinder(aStr
); // Formel wird editiert -> RangeFinder
1962 bNewTable
= TRUE
; // -> PostEditView-Aufruf
1967 eMode
= SC_INPUT_NONE
;
1968 StopInputWinEngine( TRUE
);
1969 UpdateFormulaMode();
1970 if ( pActiveViewSh
&& ( !bFromCommand
|| !bCommandErrorShown
) )
1972 // #97673# Prevent repeated error messages for the same cell from command events
1973 // (for keyboard events, multiple messages are wanted).
1974 // Set the flag before showing the error message because the command handler
1975 // for the next IME command may be called when showing the dialog.
1977 bCommandErrorShown
= TRUE
;
1979 pActiveViewSh
->GetActiveWin()->GrabFocus();
1980 pActiveViewSh
->ErrorMessage(aTester
.GetMessageId());
1985 if (!bProtected
&& pInputWin
)
1986 pInputWin
->SetOkCancelMode();
1992 void lcl_SetTopSelection( EditView
* pEditView
, ESelection
& rSel
)
1994 DBG_ASSERT( rSel
.nStartPara
==0 && rSel
.nEndPara
==0, "SetTopSelection: Para != 0" );
1996 EditEngine
* pEngine
= pEditView
->GetEditEngine();
1997 USHORT nCount
= pEngine
->GetParagraphCount();
2000 xub_StrLen nParLen
= pEngine
->GetTextLen(rSel
.nStartPara
);
2001 while (rSel
.nStartPos
> nParLen
&& rSel
.nStartPara
+1 < nCount
)
2003 rSel
.nStartPos
-= nParLen
+ 1; // incl. Leerzeichen vom Umbruch
2004 nParLen
= pEngine
->GetTextLen(++rSel
.nStartPara
);
2007 nParLen
= pEngine
->GetTextLen(rSel
.nEndPara
);
2008 while (rSel
.nEndPos
> nParLen
&& rSel
.nEndPara
+1 < nCount
)
2010 rSel
.nEndPos
-= nParLen
+ 1; // incl. Leerzeichen vom Umbruch
2011 nParLen
= pEngine
->GetTextLen(++rSel
.nEndPara
);
2015 ESelection aSel
= pEditView
->GetSelection();
2017 if ( rSel
.nStartPara
!= aSel
.nStartPara
|| rSel
.nEndPara
!= aSel
.nEndPara
2018 || rSel
.nStartPos
!= aSel
.nStartPos
|| rSel
.nEndPos
!= aSel
.nEndPos
)
2019 pEditView
->SetSelection( rSel
);
2022 void ScInputHandler::SyncViews( EditView
* pSourceView
)
2028 aSel
= pSourceView
->GetSelection();
2029 if (pTopView
&& pTopView
!= pSourceView
)
2030 pTopView
->SetSelection( aSel
);
2031 if (pTableView
&& pTableView
!= pSourceView
)
2032 lcl_SetTopSelection( pTableView
, aSel
);
2034 else if (pTopView
&& pTableView
)
2036 aSel
= pTopView
->GetSelection();
2037 lcl_SetTopSelection( pTableView
, aSel
);
2041 IMPL_LINK( ScInputHandler
, ModifyHdl
, void *, EMPTYARG
)
2043 if ( !bInOwnChange
&& ( eMode
==SC_INPUT_TYPE
|| eMode
==SC_INPUT_TABLE
) &&
2044 pEngine
&& pEngine
->GetUpdateMode() && pInputWin
)
2046 // #102745# update input line from ModifyHdl for changes that are not
2047 // wrapped by DataChanging/DataChanged calls (like Drag&Drop)
2049 String aText
= GetEditText(pEngine
);
2050 lcl_RemoveTabs(aText
);
2051 pInputWin
->SetTextString(aText
);
2056 BOOL
ScInputHandler::DataChanging( sal_Unicode cTyped
, BOOL bFromCommand
) // return TRUE = new view created
2058 pActiveViewSh
->GetViewData()->SetPasteMode( SC_PASTE_NONE
);
2059 bInOwnChange
= TRUE
; // disable ModifyHdl (reset in DataChanged)
2061 if ( eMode
== SC_INPUT_NONE
)
2062 return StartTable( cTyped
, bFromCommand
);
2067 void ScInputHandler::DataChanged( BOOL bFromTopNotify
)
2069 ImplCreateEditEngine();
2071 if (eMode
==SC_INPUT_NONE
)
2072 eMode
= SC_INPUT_TYPE
;
2074 if ( eMode
== SC_INPUT_TOP
&& pTopView
&& !bFromTopNotify
)
2076 // table EditEngine is formatted below, input line needs formatting after paste
2077 // #i20282# not when called from the input line's modify handler
2078 pTopView
->GetEditEngine()->QuickFormatDoc( TRUE
);
2080 // #i23720# QuickFormatDoc hides the cursor, but can't show it again because it
2081 // can't safely access the EditEngine's current view, so the cursor has to be
2082 // shown again here.
2083 pTopView
->ShowCursor();
2089 if ( pRangeFindList
&& !bInRangeUpdate
)
2090 RemoveRangeFinder(); // Attribute und Markierung loeschen
2092 UpdateParenthesis(); // Hervorhebung der Klammern neu
2094 // ER 31.08.00 New SetDefaults sets ParaAttribs, don't clear them away ...
2095 // RemoveAdjust(); // #40255# harte Ausrichtungs-Attribute loeschen
2097 if (eMode
==SC_INPUT_TYPE
|| eMode
==SC_INPUT_TABLE
)
2099 String aText
= GetEditText(pEngine
);
2100 lcl_RemoveTabs(aText
);
2103 pInputWin
->SetTextString(aText
);
2106 // wenn der Cursor vor dem Absatzende steht, werden Teile rechts rausgeschoben
2107 // (unabhaengig von eMode) -> View anpassen!
2108 // wenn der Cursor am Ende steht, reicht der Status-Handler an der ViewData
2110 // #93767# first make sure the status handler is called now if the cursor
2111 // is outside the visible area
2112 pEngine
->QuickFormatDoc();
2114 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2115 if (pActiveView
&& pActiveViewSh
)
2117 ScViewData
* pViewData
= pActiveViewSh
->GetViewData();
2119 BOOL bNeedGrow
= ( nEditAdjust
!= SVX_ADJUST_LEFT
); // rechtsbuendig immer
2122 // Cursor vor dem Ende?
2123 ESelection aSel
= pActiveView
->GetSelection();
2125 bNeedGrow
= ( aSel
.nEndPos
!= pEngine
->GetTextLen(aSel
.nEndPara
) );
2129 bNeedGrow
= pViewData
->GetDocument()->IsLayoutRTL( pViewData
->GetTabNo() );
2133 // adjust inplace view
2134 pViewData
->EditGrowY();
2135 pViewData
->EditGrowX();
2139 UpdateFormulaMode();
2140 bTextValid
= FALSE
; // Aenderungen sind nur in der Edit-Engine
2141 bInOwnChange
= FALSE
;
2144 void ScInputHandler::UpdateFormulaMode()
2146 SfxApplication
* pSfxApp
= SFX_APP();
2148 if ( pEngine
->GetParagraphCount() == 1 &&
2149 ( pEngine
->GetText((USHORT
)0).GetChar(0) == '=' ||
2150 pEngine
->GetText((USHORT
)0).GetChar(0) == '+' ||
2151 pEngine
->GetText((USHORT
)0).GetChar(0) == '-' ) &&
2156 bFormulaMode
= TRUE
;
2157 pRefViewSh
= pActiveViewSh
;
2158 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2159 SC_MOD()->SetRefInputHdl(this);
2161 pInputWin
->SetFormulaMode(TRUE
);
2163 if ( bAutoComplete
)
2166 UpdateParenthesis();
2167 UpdateAutoCorrFlag();
2175 bFormulaMode
= FALSE
;
2177 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2178 SC_MOD()->SetRefInputHdl(NULL
);
2180 pInputWin
->SetFormulaMode(FALSE
);
2181 UpdateAutoCorrFlag();
2186 void ScInputHandler::ShowRefFrame()
2188 // #123169# Modifying pActiveViewSh here would interfere with the bInEnterHandler / bRepeat
2189 // checks in NotifyChange, and lead to keeping the wrong value in pActiveViewSh.
2190 // A local variable is used instead.
2191 ScTabViewShell
* pVisibleSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
2192 if ( pRefViewSh
&& pRefViewSh
!= pVisibleSh
)
2194 BOOL bFound
= FALSE
;
2195 SfxViewFrame
* pRefFrame
= pRefViewSh
->GetViewFrame();
2196 SfxViewFrame
* pOneFrame
= SfxViewFrame::GetFirst();
2197 while ( pOneFrame
&& !bFound
)
2199 if ( pOneFrame
== pRefFrame
)
2201 pOneFrame
= SfxViewFrame::GetNext( *pOneFrame
);
2206 // Hier wird sich darauf verlassen, dass Activate synchron funktioniert
2207 // (dabei wird pActiveViewSh umgesetzt)
2209 pRefViewSh
->SetActive(); // Appear und SetViewFrame
2211 // pLastState wird im NotifyChange aus dem Activate richtig gesetzt
2215 DBG_ERROR("ViewFrame fuer Referenzeingabe ist nicht mehr da");
2220 void ScInputHandler::RemoveSelection()
2222 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2226 ESelection aSel
= pActiveView
->GetSelection();
2227 aSel
.nStartPara
= aSel
.nEndPara
;
2228 aSel
.nStartPos
= aSel
.nEndPos
;
2230 pTableView
->SetSelection( aSel
);
2232 pTopView
->SetSelection( aSel
);
2235 void ScInputHandler::InvalidateAttribs()
2237 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
2240 SfxBindings
& rBindings
= pViewFrm
->GetBindings();
2242 rBindings
.Invalidate( SID_ATTR_CHAR_FONT
);
2243 rBindings
.Invalidate( SID_ATTR_CHAR_FONTHEIGHT
);
2244 rBindings
.Invalidate( SID_ATTR_CHAR_COLOR
);
2246 rBindings
.Invalidate( SID_ATTR_CHAR_WEIGHT
);
2247 rBindings
.Invalidate( SID_ATTR_CHAR_POSTURE
);
2248 rBindings
.Invalidate( SID_ATTR_CHAR_UNDERLINE
);
2249 rBindings
.Invalidate( SID_ULINE_VAL_NONE
);
2250 rBindings
.Invalidate( SID_ULINE_VAL_SINGLE
);
2251 rBindings
.Invalidate( SID_ULINE_VAL_DOUBLE
);
2252 rBindings
.Invalidate( SID_ULINE_VAL_DOTTED
);
2254 rBindings
.Invalidate( SID_HYPERLINK_GETLINK
);
2260 // --------------- public Methoden --------------------------------------------
2263 void ScInputHandler::SetMode( ScInputMode eNewMode
)
2265 if ( eMode
== eNewMode
)
2268 ImplCreateEditEngine();
2272 eMode
= SC_INPUT_NONE
;
2273 StopInputWinEngine( TRUE
);
2275 pActiveViewSh
->GetActiveWin()->GrabFocus();
2279 bInOwnChange
= TRUE
; // disable ModifyHdl (reset below)
2281 ScInputMode eOldMode
= eMode
;
2283 if (eOldMode
== SC_INPUT_TOP
&& eNewMode
!= eOldMode
)
2284 StopInputWinEngine( FALSE
);
2286 if (eMode
==SC_INPUT_TOP
|| eMode
==SC_INPUT_TABLE
)
2288 if (eOldMode
== SC_INPUT_NONE
) // not when switching between modes
2290 if (StartTable(0, FALSE
)) // 0 = look at existing document content for text or number
2293 pActiveViewSh
->GetViewData()->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
2297 USHORT nPara
= pEngine
->GetParagraphCount()-1;
2298 xub_StrLen nLen
= pEngine
->GetText(nPara
).Len();
2299 USHORT nCount
= pEngine
->GetViewCount();
2301 for (USHORT i
=0; i
<nCount
; i
++)
2303 if ( eMode
== SC_INPUT_TABLE
&& eOldMode
== SC_INPUT_TOP
)
2309 pEngine
->GetView(i
)->
2310 SetSelection( ESelection( nPara
, nLen
, nPara
, nLen
) );
2312 pEngine
->GetView(i
)->ShowCursor(FALSE
);
2317 if (eMode
==SC_INPUT_TABLE
|| eMode
==SC_INPUT_TYPE
)
2320 pTableView
->SetEditEngineUpdateMode(TRUE
);
2325 pTopView
->SetEditEngineUpdateMode(TRUE
);
2328 if (eNewMode
!= eOldMode
)
2329 UpdateFormulaMode();
2331 bInOwnChange
= FALSE
;
2334 //----------------------------------------------------------------------------------------
2336 // lcl_IsNumber - TRUE, wenn nur Ziffern (dann keine Autokorrektur)
2338 BOOL
lcl_IsNumber(const String
& rString
)
2340 xub_StrLen nLen
= rString
.Len();
2341 for (xub_StrLen i
=0; i
<nLen
; i
++)
2343 sal_Unicode c
= rString
.GetChar(i
);
2344 if ( c
< '0' || c
> '9' )
2350 void lcl_SelectionToEnd( EditView
* pView
)
2354 EditEngine
* pEngine
= pView
->GetEditEngine();
2355 USHORT nParCnt
= pEngine
->GetParagraphCount();
2358 ESelection
aSel( nParCnt
-1, pEngine
->GetTextLen(nParCnt
-1) ); // empty selection, cursor at the end
2359 pView
->SetSelection( aSel
);
2363 void ScInputHandler::EnterHandler( BYTE nBlockMode
)
2365 // #62806# Bei Makro-Aufrufen fuer Gueltigkeit kann Tod und Teufel passieren,
2366 // darum dafuer sorgen, dass EnterHandler nicht verschachtelt gerufen wird:
2368 if (bInEnterHandler
) return;
2369 bInEnterHandler
= TRUE
;
2370 bInOwnChange
= TRUE
; // disable ModifyHdl (reset below)
2372 ImplCreateEditEngine();
2374 BOOL bMatrix
= ( nBlockMode
== SC_ENTER_MATRIX
);
2376 SfxApplication
* pSfxApp
= SFX_APP();
2377 EditTextObject
* pObject
= NULL
;
2378 ScPatternAttr
* pCellAttrs
= NULL
;
2379 BOOL bAttrib
= FALSE
; // Formatierung vorhanden ?
2380 BOOL bForget
= FALSE
; // wegen Gueltigkeit streichen ?
2382 String aString
= GetEditText(pEngine
);
2383 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2384 if (bModified
&& pActiveView
&& aString
.Len() && !lcl_IsNumber(aString
))
2386 if ( pColumnData
&& nAutoPos
!= SCPOS_INVALID
)
2388 // #i47125# If AutoInput appended something, do the final AutoCorrect
2389 // with the cursor at the end of the input.
2391 lcl_SelectionToEnd(pTopView
);
2392 lcl_SelectionToEnd(pTableView
);
2395 Window
* pFrameWin
= pActiveViewSh
? pActiveViewSh
->GetFrameWin() : NULL
;
2398 pTopView
->CompleteAutoCorrect(); // #59759# CompleteAutoCorrect fuer beide Views
2400 pTableView
->CompleteAutoCorrect(pFrameWin
);
2401 aString
= GetEditText(pEngine
);
2403 lcl_RemoveTabs(aString
);
2405 // Test, ob zulaessig (immer mit einfachem String)
2407 if ( bModified
&& nValidation
&& pActiveViewSh
)
2409 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2410 const ScValidationData
* pData
= pDoc
->GetValidationEntry( nValidation
);
2411 if (pData
&& pData
->HasErrMsg())
2413 // #i67990# don't use pLastPattern in EnterHandler
2414 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2415 BOOL bOk
= pData
->IsDataValid( aString
, *pPattern
, aCursorPos
);
2419 if ( pActiveViewSh
) // falls aus MouseButtonDown gekommen
2420 pActiveViewSh
->StopMarking(); // (die InfoBox verschluckt das MouseButtonUp)
2422 //! es gibt noch Probleme, wenn die Eingabe durch Aktivieren einer
2423 //! anderen View ausgeloest wurde
2425 Window
* pParent
= Application::GetDefDialogParent();
2426 if ( pData
->DoError( pParent
, aString
, aCursorPos
) )
2427 bForget
= TRUE
; // Eingabe nicht uebernehmen
2432 // check for input into DataPilot table
2434 if ( bModified
&& pActiveViewSh
&& !bForget
)
2436 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2437 ScDPObject
* pDPObj
= pDoc
->GetDPAtCursor( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2440 // any input within the DataPilot table is either a valid renaming
2441 // or an invalid action - normal cell input is always aborted
2443 pActiveViewSh
->DataPilotInput( aCursorPos
, aString
);
2448 pEngine
->CompleteOnlineSpelling();
2449 BOOL bSpellErrors
= !bFormulaMode
&& pEngine
->HasOnlineSpellErrors();
2452 // #i3820# If the spell checker flags numerical input as error,
2453 // it still has to be treated as number, not EditEngine object.
2455 if ( pActiveViewSh
)
2457 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2458 // #i67990# don't use pLastPattern in EnterHandler
2459 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2460 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
2461 // without conditional format, as in ScColumn::SetString
2462 sal_uInt32 nFormat
= pPattern
->GetNumberFormat( pFormatter
);
2464 if ( pFormatter
->IsNumberFormat( aString
, nFormat
, nVal
) )
2466 bSpellErrors
= FALSE
; // ignore the spelling errors
2471 // After RemoveAdjust, the EditView must not be repainted (has wrong font size etc).
2472 // SetUpdateMode must come after CompleteOnlineSpelling.
2473 // The view is hidden in any case below (Broadcast).
2474 pEngine
->SetUpdateMode( FALSE
);
2476 if ( bModified
&& !bForget
) // was wird eingeben (Text/Objekt) ?
2478 USHORT nParCnt
= pEngine
->GetParagraphCount();
2482 bool bUniformAttribs
= true;
2483 SfxItemSet aPara1Attribs
= pEngine
->GetAttribs(0, 0, pEngine
->GetTextLen(0));
2484 for (USHORT nPara
= 1; nPara
< nParCnt
; ++nPara
)
2486 SfxItemSet aPara2Attribs
= pEngine
->GetAttribs(nPara
, 0, pEngine
->GetTextLen(nPara
));
2487 if (!(aPara1Attribs
== aPara2Attribs
))
2489 // paragraph format different from that of the 1st paragraph.
2490 bUniformAttribs
= false;
2495 ESelection
aSel( 0, 0, nParCnt
-1, pEngine
->GetTextLen(nParCnt
-1) );
2496 SfxItemSet aOldAttribs
= pEngine
->GetAttribs( aSel
);
2497 const SfxPoolItem
* pItem
= NULL
;
2499 // find common (cell) attributes before RemoveAdjust
2501 if ( pActiveViewSh
&& bUniformAttribs
)
2503 SfxItemSet
* pCommonAttrs
= NULL
;
2504 for (USHORT nId
= EE_CHAR_START
; nId
<= EE_CHAR_END
; nId
++)
2506 SfxItemState eState
= aOldAttribs
.GetItemState( nId
, FALSE
, &pItem
);
2507 if ( eState
== SFX_ITEM_SET
&&
2508 nId
!= EE_CHAR_ESCAPEMENT
&& nId
!= EE_CHAR_PAIRKERNING
&&
2509 nId
!= EE_CHAR_KERNING
&& nId
!= EE_CHAR_XMLATTRIBS
&&
2510 *pItem
!= pEditDefaults
->Get(nId
) )
2512 if ( !pCommonAttrs
)
2513 pCommonAttrs
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
2514 pCommonAttrs
->Put( *pItem
);
2520 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2521 pCellAttrs
= new ScPatternAttr( pDoc
->GetPool() );
2522 pCellAttrs
->GetFromEditItemSet( pCommonAttrs
);
2523 delete pCommonAttrs
;
2527 // clear ParaAttribs (including adjustment)
2531 // check if EditObject is needed
2533 if ( bSpellErrors
|| nParCnt
> 1 )
2537 for (USHORT nId
= EE_CHAR_START
; nId
<= EE_CHAR_END
&& !bAttrib
; nId
++)
2539 SfxItemState eState
= aOldAttribs
.GetItemState( nId
, FALSE
, &pItem
);
2540 if (eState
== SFX_ITEM_DONTCARE
)
2542 else if (eState
== SFX_ITEM_SET
)
2544 // keep same items in EditEngine as in ScEditAttrTester
2545 if ( nId
== EE_CHAR_ESCAPEMENT
|| nId
== EE_CHAR_PAIRKERNING
||
2546 nId
== EE_CHAR_KERNING
|| nId
== EE_CHAR_XMLATTRIBS
)
2548 if ( *pItem
!= pEditDefaults
->Get(nId
) )
2554 // Feldbefehle enthalten?
2556 SfxItemState eFieldState
= aOldAttribs
.GetItemState( EE_FEATURE_FIELD
, FALSE
);
2557 if ( eFieldState
== SFX_ITEM_DONTCARE
|| eFieldState
== SFX_ITEM_SET
)
2560 // not converted characters?
2562 SfxItemState eConvState
= aOldAttribs
.GetItemState( EE_FEATURE_NOTCONV
, FALSE
);
2563 if ( eConvState
== SFX_ITEM_DONTCARE
|| eConvState
== SFX_ITEM_SET
)
2566 // Formeln immer als Formeln erkennen (#38309#)
2567 // (der Test vorher ist trotzdem noetig wegen Zell-Attributen)
2575 ULONG nCtrl
= pEngine
->GetControlWord();
2576 ULONG nWantBig
= bSpellErrors
? EE_CNTRL_ALLOWBIGOBJS
: 0;
2577 if ( ( nCtrl
& EE_CNTRL_ALLOWBIGOBJS
) != nWantBig
)
2578 pEngine
->SetControlWord( (nCtrl
& ~EE_CNTRL_ALLOWBIGOBJS
) | nWantBig
);
2579 pObject
= pEngine
->CreateTextObject();
2583 // don't rely on ShowRefFrame switching the active view synchronously
2584 // execute the function directly on the correct view's bindings instead
2585 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2586 ScTabViewShell
* pExecuteSh
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
2594 pExecuteSh
->SetTabNo(aCursorPos
.Tab());
2595 pExecuteSh
->ActiveGrabFocus();
2598 bFormulaMode
= FALSE
;
2599 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2600 SC_MOD()->SetRefInputHdl(NULL
);
2602 pInputWin
->SetFormulaMode(FALSE
);
2603 UpdateAutoCorrFlag();
2605 pRefViewSh
= NULL
; // auch ohne FormulaMode wegen Funktions-AP
2606 DeleteRangeFinder();
2609 BOOL bOldMod
= bModified
;
2613 eMode
= SC_INPUT_NONE
;
2614 StopInputWinEngine( TRUE
);
2616 // #123344# Text input (through number formats) or ApplySelectionPattern modify
2617 // the cell's attributes, so pLastPattern is no longer valid
2618 pLastPattern
= NULL
;
2620 if (bOldMod
&& !bProtected
&& !bForget
)
2622 // keine typographische Anfuehrungszeichen in Formeln
2624 if ( aString
.GetChar(0) == '=' )
2626 SvxAutoCorrect
* pAuto
= SvxAutoCorrCfg::Get()->GetAutoCorrect();
2629 sal_Unicode cReplace
= pAuto
->GetStartDoubleQuote();
2631 cReplace
= ScGlobal::pLocaleData
->getDoubleQuotationMarkStart().GetChar(0);
2632 if ( cReplace
!= '"' )
2633 aString
.SearchAndReplaceAll( cReplace
, '"' );
2635 cReplace
= pAuto
->GetEndDoubleQuote();
2637 cReplace
= ScGlobal::pLocaleData
->getDoubleQuotationMarkEnd().GetChar(0);
2638 if ( cReplace
!= '"' )
2639 aString
.SearchAndReplaceAll( cReplace
, '"' );
2641 cReplace
= pAuto
->GetStartSingleQuote();
2643 cReplace
= ScGlobal::pLocaleData
->getQuotationMarkStart().GetChar(0);
2644 if ( cReplace
!= '\'' )
2645 aString
.SearchAndReplaceAll( cReplace
, '\'' );
2647 cReplace
= pAuto
->GetEndSingleQuote();
2649 cReplace
= ScGlobal::pLocaleData
->getQuotationMarkEnd().GetChar(0);
2650 if ( cReplace
!= '\'' )
2651 aString
.SearchAndReplaceAll( cReplace
, '\'' );
2655 pSfxApp
->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW_NOPAINT
) );
2659 SfxBindings
& rBindings
= pExecuteSh
->GetViewFrame()->GetBindings();
2661 USHORT nId
= FID_INPUTLINE_ENTER
;
2662 if ( nBlockMode
== SC_ENTER_BLOCK
)
2663 nId
= FID_INPUTLINE_BLOCK
;
2664 else if ( nBlockMode
== SC_ENTER_MATRIX
)
2665 nId
= FID_INPUTLINE_MATRIX
;
2667 ScInputStatusItem
aItem( FID_INPUTLINE_STATUS
,
2668 aCursorPos
, aCursorPos
, aCursorPos
,
2670 const SfxPoolItem
* aArgs
[2];
2673 rBindings
.Execute( nId
, aArgs
);
2676 delete pLastState
; // pLastState enthaelt noch den alten Text
2680 pSfxApp
->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW
) );
2682 if ( bOldMod
&& pExecuteSh
&& pCellAttrs
&& !bForget
)
2684 // mit Eingabe zusammenfassen ?
2685 pExecuteSh
->ApplySelectionPattern( *pCellAttrs
, TRUE
, TRUE
);
2686 pExecuteSh
->AdjustBlockHeight();
2694 nFormSelStart
= nFormSelEnd
= 0;
2697 bInOwnChange
= FALSE
;
2698 bInEnterHandler
= FALSE
;
2701 void ScInputHandler::CancelHandler()
2703 bInOwnChange
= TRUE
; // disable ModifyHdl (reset below)
2705 ImplCreateEditEngine();
2709 // don't rely on ShowRefFrame switching the active view synchronously
2710 // execute the function directly on the correct view's bindings instead
2711 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2712 ScTabViewShell
* pExecuteSh
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
2719 pExecuteSh
->SetTabNo(aCursorPos
.Tab());
2720 pExecuteSh
->ActiveGrabFocus();
2722 bFormulaMode
= FALSE
;
2723 SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2724 SC_MOD()->SetRefInputHdl(NULL
);
2726 pInputWin
->SetFormulaMode(FALSE
);
2727 UpdateAutoCorrFlag();
2729 pRefViewSh
= NULL
; // auch ohne FormulaMode wegen Funktions-AP
2730 DeleteRangeFinder();
2733 eMode
= SC_INPUT_NONE
;
2734 StopInputWinEngine( TRUE
);
2736 pExecuteSh
->StopEditShell();
2738 aCursorPos
.Set(MAXCOL
+1,0,0); // Flag, dass ungueltig
2739 pEngine
->SetText(String());
2741 if ( !pLastState
&& pExecuteSh
)
2742 pExecuteSh
->UpdateInputHandler( TRUE
); // Status neu holen
2744 NotifyChange( pLastState
, TRUE
);
2746 nFormSelStart
= nFormSelEnd
= 0;
2749 bInOwnChange
= FALSE
;
2752 BOOL
ScInputHandler::IsModalMode( SfxObjectShell
* pDocSh
)
2754 // Referenzen auf unbenanntes Dokument gehen nicht
2756 return bFormulaMode
&& pRefViewSh
2757 && pRefViewSh
->GetViewData()->GetDocument()->GetDocumentShell() != pDocSh
2758 && !pDocSh
->HasName();
2761 void ScInputHandler::AddRefEntry()
2763 const sal_Unicode cSep
= ScCompiler::GetNativeSymbol(ocSep
).GetChar(0);
2765 if (!pTableView
&& !pTopView
)
2766 return; // z.B. FillMode
2768 DataChanging(); // kann nicht neu sein
2772 pTableView
->InsertText( cSep
, FALSE
);
2774 pTopView
->InsertText( cSep
, FALSE
);
2779 void ScInputHandler::SetReference( const ScRange
& rRef
, ScDocument
* pDoc
)
2783 BOOL bOtherDoc
= ( pRefViewSh
&&
2784 pRefViewSh
->GetViewData()->GetDocument() != pDoc
);
2786 if (!pDoc
->GetDocumentShell()->HasName())
2788 // Referenzen auf unbenanntes Dokument gehen nicht
2789 // (SetReference sollte dann auch nicht gerufen werden)
2795 if (!pTableView
&& !pTopView
)
2796 return; // z.B. FillMode
2798 // nie das "=" ueberschreiben!
2799 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2800 ESelection aSel
= pActiveView
->GetSelection();
2802 if ( aSel
.nStartPara
== 0 && aSel
.nStartPos
== 0 )
2805 DataChanging(); // kann nicht neu sein
2807 // Selektion umdrehen, falls rueckwaerts (noetig ???)
2811 ESelection aTabSel
= pTableView
->GetSelection();
2812 if (aTabSel
.nStartPos
> aTabSel
.nEndPos
&& aTabSel
.nStartPara
== aTabSel
.nEndPara
)
2815 pTableView
->SetSelection(aTabSel
);
2820 ESelection aTopSel
= pTopView
->GetSelection();
2821 if (aTopSel
.nStartPos
> aTopSel
.nEndPos
&& aTopSel
.nStartPara
== aTopSel
.nEndPara
)
2824 pTopView
->SetSelection(aTopSel
);
2828 // String aus Referenz erzeugen
2831 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
2834 // Referenz auf anderes Dokument
2836 DBG_ASSERT(rRef
.aStart
.Tab()==rRef
.aEnd
.Tab(), "nStartTab!=nEndTab");
2839 rRef
.Format( aTmp
, SCA_VALID
|SCA_TAB_3D
, pDoc
, aAddrDetails
); // immer 3d
2841 SfxObjectShell
* pObjSh
= pDoc
->GetDocumentShell();
2842 // #i75893# convert escaped URL of the document to something user friendly
2843 // String aFileName = pObjSh->GetMedium()->GetName();
2844 String aFileName
= pObjSh
->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS
);
2847 aRefStr
+= aFileName
;
2848 aRefStr
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "'#" ));
2853 if ( ( rRef
.aStart
.Tab() != aCursorPos
.Tab() ||
2854 rRef
.aStart
.Tab() != rRef
.aEnd
.Tab() ) && pDoc
)
2855 rRef
.Format( aRefStr
, SCA_VALID
|SCA_TAB_3D
, pDoc
, aAddrDetails
);
2857 rRef
.Format( aRefStr
, SCA_VALID
, pDoc
, aAddrDetails
);
2860 if (pTableView
|| pTopView
)
2863 pTableView
->InsertText( aRefStr
, TRUE
);
2865 pTopView
->InsertText( aRefStr
, TRUE
);
2873 void ScInputHandler::InsertFunction( const String
& rFuncName
, BOOL bAddPar
)
2875 if ( eMode
== SC_INPUT_NONE
)
2877 DBG_ERROR("InsertFunction, nicht im Eingabemodus");
2882 if (!pTableView
&& !pTopView
)
2883 return; // z.B. FillMode
2885 DataChanging(); // kann nicht neu sein
2887 String aText
= rFuncName
;
2889 aText
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
2893 pTableView
->InsertText( aText
, FALSE
);
2896 ESelection aSel
= pTableView
->GetSelection();
2899 pTableView
->SetSelection(aSel
);
2904 pTopView
->InsertText( aText
, FALSE
);
2907 ESelection aSel
= pTopView
->GetSelection();
2910 pTopView
->SetSelection(aSel
);
2920 void ScInputHandler::ClearText()
2922 if ( eMode
== SC_INPUT_NONE
)
2924 DBG_ERROR("ClearText, nicht im Eingabemodus");
2929 if (!pTableView
&& !pTopView
)
2930 return; // z.B. FillMode
2932 DataChanging(); // darf nicht neu sein
2937 pTableView
->GetEditEngine()->SetText( aEmpty
);
2938 pTableView
->SetSelection( ESelection(0,0, 0,0) );
2942 pTopView
->GetEditEngine()->SetText( aEmpty
);
2943 pTopView
->SetSelection( ESelection(0,0, 0,0) );
2949 BOOL
ScInputHandler::KeyInput( const KeyEvent
& rKEvt
, BOOL bStartEdit
/* = FALSE */ )
2953 bAutoComplete
= SC_MOD()->GetAppOptions().GetAutoComplete();
2957 KeyCode aCode
= rKEvt
.GetKeyCode();
2958 USHORT nModi
= aCode
.GetModifier();
2959 BOOL bShift
= aCode
.IsShift();
2960 BOOL bControl
= aCode
.IsMod1();
2961 BOOL bAlt
= aCode
.IsMod2();
2962 USHORT nCode
= aCode
.GetCode();
2963 sal_Unicode nChar
= rKEvt
.GetCharCode();
2965 // Alt-Return is accepted, everything else with ALT, or CTRL-TAB are not:
2966 if (( bAlt
&& !bControl
&& nCode
!= KEY_RETURN
) ||
2967 ( bControl
&& aCode
.GetCode() == KEY_TAB
))
2970 BOOL bInputLine
= ( eMode
==SC_INPUT_TOP
);
2974 BOOL bDoEnter
= FALSE
;
2979 if (bControl
&& !bShift
&& !bInputLine
)
2981 else if ( nModi
== 0 && nTipVisible
&& pFormulaData
&& nAutoPos
!= SCPOS_INVALID
)
2983 PasteFunctionData();
2986 else if ( nModi
== 0 && nTipVisible
&& aManualTip
.Len() )
2993 BYTE nMode
= SC_ENTER_NORMAL
;
2994 if ( bShift
&& bControl
)
2995 nMode
= SC_ENTER_MATRIX
;
2997 nMode
= SC_ENTER_BLOCK
;
2998 EnterHandler( nMode
);
3001 pActiveViewSh
->MoveCursorEnter( bShift
&& !bControl
);
3007 if (!bControl
&& !bAlt
)
3009 if ( pFormulaData
&& nTipVisible
&& nAutoPos
!= SCPOS_INVALID
)
3013 NextFormulaEntry( bShift
);
3015 else if ( pColumnData
&& bUseTab
&& nAutoPos
!= SCPOS_INVALID
)
3017 // in den Eintraegen der AutoEingabe blaettern
3019 NextAutoEntry( bShift
);
3025 // TabKeyInput gibt auf manchen Rechnern unter W95 Stackueberlaeufe,
3026 // darum direkter Aufruf:
3028 pActiveViewSh
->FindNextUnprot( bShift
);
3039 else if( nTipVisibleSec
)
3044 else if (eMode
!= SC_INPUT_NONE
)
3053 if ( !bShift
&& !bControl
&& !bAlt
&& eMode
== SC_INPUT_TABLE
)
3055 eMode
= SC_INPUT_TYPE
;
3061 // Cursortasten nur ausfuehren, wenn schon im Edit-Modus
3062 // z.B. wegen Shift-Ctrl-PageDn (ist nicht als Accelerator definiert)
3064 BOOL bCursorKey
= EditEngine::DoesKeyMoveCursor(rKEvt
);
3065 BOOL bInsKey
= ( nCode
== KEY_INSERT
&& !nModi
); // Insert wie Cursortasten behandeln
3066 if ( !bUsed
&& !bSkip
&& ( bDoEnter
|| EditEngine::DoesKeyChangeText(rKEvt
) ||
3067 ( eMode
!= SC_INPUT_NONE
&& ( bCursorKey
|| bInsKey
) ) ) )
3079 BOOL bNewView
= DataChanging( nChar
);
3081 if (bProtected
) // Zelle geschuetzt?
3082 bUsed
= TRUE
; // Key-Event nicht weiterleiten
3083 else // Aenderungen erlaubt
3085 if (bNewView
) // neu anlegen
3088 pActiveViewSh
->GetViewData()->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3090 if (eMode
==SC_INPUT_NONE
)
3091 if (pTableView
|| pTopView
)
3095 if ( bStartEdit
&& bCellHasPercentFormat
&& ((nChar
>= '0' && nChar
<= '9') || nChar
== '-') )
3100 pTableView
->GetEditEngine()->SetText( aStrLoP
);
3101 if ( aStrLoP
.Len() )
3102 pTableView
->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3104 // don't call SetSelection if the string is empty anyway,
3105 // to avoid breaking the bInitial handling in ScViewData::EditGrowY
3109 pTopView
->GetEditEngine()->SetText( aStrLoP
);
3110 if ( aStrLoP
.Len() )
3111 pTopView
->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3117 if (pTableView
|| pTopView
)
3119 // pActiveView->SetEditEngineUpdateMode(TRUE); //! gibt Muell !!!!
3124 if( pTableView
->PostKeyEvent( KeyEvent( CHAR_CR
, KeyCode(KEY_RETURN
) ) ) )
3127 if( pTopView
->PostKeyEvent( KeyEvent( CHAR_CR
, KeyCode(KEY_RETURN
) ) ) )
3130 else if ( nAutoPar
&& nChar
== ')' && CursorAtClosingPar() )
3139 Window
* pFrameWin
= pActiveViewSh
? pActiveViewSh
->GetFrameWin() : NULL
;
3140 if ( pTableView
->PostKeyEvent( rKEvt
, pFrameWin
) )
3144 if ( pTopView
->PostKeyEvent( rKEvt
) )
3150 if ( bUsed
&& bAutoComplete
)
3153 nAutoPos
= SCPOS_INVALID
; // do not search further
3155 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
3156 if ( nChar
&& nChar
!= 8 && nChar
!= 127 && // no 'backspace', no 'delete'
3157 KEYFUNC_CUT
!= eFunc
) // and no 'CTRL-X'
3166 // when the selection is changed manually or an opening parenthesis
3167 // is typed, stop overwriting parentheses
3168 if ( bUsed
&& nChar
== '(' )
3171 if ( KEY_INSERT
== nCode
)
3173 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
3175 pViewFrm
->GetBindings().Invalidate( SID_ATTR_INSERT
);
3177 if( bUsed
&& bFormulaMode
&& ( bCursorKey
|| bInsKey
|| nCode
== KEY_DELETE
|| nCode
== KEY_BACKSPACE
) )
3183 DataChanged(); // ruft auch UpdateParenthesis()
3184 InvalidateAttribs(); //! in DataChanged ?
3188 if (pTopView
&& eMode
!= SC_INPUT_NONE
)
3194 BOOL
ScInputHandler::InputCommand( const CommandEvent
& rCEvt
, BOOL bForce
)
3198 if ( rCEvt
.GetCommand() == COMMAND_CURSORPOS
)
3200 // #90346# for COMMAND_CURSORPOS, do as little as possible, because
3201 // with remote VCL, even a ShowCursor will generate another event.
3202 if ( eMode
!= SC_INPUT_NONE
)
3205 if (pTableView
|| pTopView
)
3208 pTableView
->Command( rCEvt
);
3209 else if (pTopView
) // call only once
3210 pTopView
->Command( rCEvt
);
3217 if ( bForce
|| eMode
!= SC_INPUT_NONE
)
3221 bAutoComplete
= SC_MOD()->GetAppOptions().GetAutoComplete();
3235 BOOL bNewView
= DataChanging( 0, TRUE
);
3237 if (bProtected
) // cell protected
3238 bUsed
= TRUE
; // event is used
3239 else // changes allowed
3241 if (bNewView
) // create new edit view
3244 pActiveViewSh
->GetViewData()->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3246 if (eMode
==SC_INPUT_NONE
)
3247 if (pTableView
|| pTopView
)
3252 pTableView
->GetEditEngine()->SetText( aStrLoP
);
3253 pTableView
->SetSelection( ESelection(0,0, 0,0) );
3257 pTopView
->GetEditEngine()->SetText( aStrLoP
);
3258 pTopView
->SetSelection( ESelection(0,0, 0,0) );
3264 if (pTableView
|| pTopView
)
3267 pTableView
->Command( rCEvt
);
3269 pTopView
->Command( rCEvt
);
3273 if ( rCEvt
.GetCommand() == COMMAND_ENDEXTTEXTINPUT
)
3275 // AutoInput after ext text input
3277 nAutoPos
= SCPOS_INVALID
;
3285 DataChanged(); // calls UpdateParenthesis()
3286 InvalidateAttribs(); //! in DataChanged ?
3290 if (pTopView
&& eMode
!= SC_INPUT_NONE
)
3297 void ScInputHandler::NotifyChange( const ScInputHdlState
* pState
,
3298 BOOL bForce
, ScTabViewShell
* pSourceSh
,
3301 // #62806# Wenn der Aufruf aus einem Makro-Aufruf im EnterHandler kommt,
3302 // gleich abbrechen und nicht den Status durcheinander bringen
3303 if (bInEnterHandler
)
3306 BOOL bRepeat
= (pState
== pLastState
);
3307 if (!bRepeat
&& pState
&& pLastState
)
3308 bRepeat
= sal::static_int_cast
<BOOL
>(*pState
== *pLastState
);
3309 if (bRepeat
&& !bForce
)
3312 bInOwnChange
= TRUE
; // disable ModifyHdl (reset below)
3314 if ( pState
&& !pLastState
) // wieder enablen
3317 BOOL bHadObject
= pLastState
&& pLastState
->GetEditData();
3319 //! Before EditEngine gets eventually created (so it gets the right pools)
3321 pActiveViewSh
= pSourceSh
;
3323 pActiveViewSh
= PTR_CAST(ScTabViewShell
, SfxViewShell::Current());
3325 ImplCreateEditEngine();
3327 if ( pState
!= pLastState
)
3330 pLastState
= pState
? new ScInputHdlState( *pState
) : NULL
;
3333 if ( pState
&& pActiveViewSh
)
3335 ScModule
* pScMod
= SC_MOD();
3339 BOOL bIgnore
= FALSE
;
3341 // hier auch fremde Referenzeingabe beruecksichtigen (z.B. Funktions-AP),
3342 // FormEditData falls gerade von der Hilfe auf Calc umgeschaltet wird:
3344 if ( !bFormulaMode
&& !pScMod
->IsFormulaMode() && !pScMod
->GetFormEditData() )
3348 if (pState
->GetPos() != aCursorPos
)
3357 if ( !bIgnore
/* || bRepeat */ )
3359 const ScAddress
& rSPos
= pState
->GetStartPos();
3360 const ScAddress
& rEPos
= pState
->GetEndPos();
3361 const EditTextObject
* pData
= pState
->GetEditData();
3362 String aString
= pState
->GetString();
3363 BOOL bTxtMod
= FALSE
;
3364 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
3365 ScDocument
* pDoc
= pDocSh
->GetDocument();
3367 aCursorPos
= pState
->GetPos();
3369 if ( pData
/* || bRepeat */ )
3371 else if ( bHadObject
)
3373 else if ( bTextValid
)
3374 bTxtMod
= ( aString
!= aCurrentText
);
3376 bTxtMod
= ( aString
!= GetEditText(pEngine
) );
3378 if ( bTxtMod
|| bForce
)
3382 pEngine
->SetText( *pData
);
3383 aString
= GetEditText(pEngine
);
3384 lcl_RemoveTabs(aString
);
3386 aCurrentText
.Erase();
3390 aCurrentText
= aString
;
3391 bTextValid
= TRUE
; //! erst nur als String merken
3395 pInputWin
->SetTextString(aString
);
3398 if ( pInputWin
) // Bereichsanzeige
3401 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
3403 // Ist der Bereich ein Name?
3404 //! per Timer suchen ???
3406 if ( pActiveViewSh
)
3407 pActiveViewSh
->GetViewData()->GetDocument()->
3408 GetRangeAtBlock( ScRange( rSPos
, rEPos
), &aPosStr
);
3410 if ( !aPosStr
.Len() ) // kein Name -> formatieren
3413 if( aAddrDetails
.eConv
== formula::FormulaGrammar::CONV_XL_R1C1
)
3414 nFlags
|= SCA_COL_ABSOLUTE
| SCA_ROW_ABSOLUTE
;
3415 if ( rSPos
!= rEPos
)
3417 ScRange
r(rSPos
, rEPos
);
3418 nFlags
|= (nFlags
<< 4);
3419 r
.Format( aPosStr
, SCA_VALID
| nFlags
, pDoc
, aAddrDetails
);
3422 aCursorPos
.Format( aPosStr
, SCA_VALID
| nFlags
, pDoc
, aAddrDetails
);
3425 pInputWin
->SetPosString(aPosStr
);
3426 pInputWin
->SetSumAssignMode();
3430 SFX_APP()->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW
) );
3432 // As long as the content is not edited, turn off online spelling.
3433 // Online spelling is turned back on in StartTable, after setting
3434 // the right language from cell attributes.
3436 ULONG nCntrl
= pEngine
->GetControlWord();
3437 if ( nCntrl
& EE_CNTRL_ONLINESPELLING
)
3438 pEngine
->SetControlWord( nCntrl
& ~EE_CNTRL_ONLINESPELLING
);
3443 bCommandErrorShown
= FALSE
;
3448 // bProtected = FALSE;
3452 if(!pScMod
->IsFormulaMode()&& !pScMod
->IsRefDialogOpen()) //BugID 54702
3453 { //Wenn RefDialog offen, dann nicht enablen
3454 if ( !pInputWin
->IsEnabled())
3456 pInputWin
->Enable();
3459 DELETEZ( pDelayTimer
);
3463 else if(pScMod
->IsRefDialogOpen())
3464 { // Da jedes Dokument eigenes InputWin hat, sollte
3465 if ( !pDelayTimer
) // nochmals Timer gestartet werden, da sonst Ein-
3466 { // gabezeile evt. noch aktiv ist.
3467 pDelayTimer
= new Timer
;
3468 pDelayTimer
->SetTimeout( 500 ); // 100ms Verzoegerung
3469 pDelayTimer
->SetTimeoutHdl( LINK( this, ScInputHandler
, DelayTimer
) );
3470 pDelayTimer
->Start();
3475 else // !pState || !pActiveViewSh
3479 pDelayTimer
= new Timer
;
3480 pDelayTimer
->SetTimeout( 500 ); // 100ms Verzoegerung
3481 pDelayTimer
->SetTimeoutHdl( LINK( this, ScInputHandler
, DelayTimer
) );
3482 pDelayTimer
->Start();
3488 bInOwnChange
= FALSE
;
3491 void ScInputHandler::UpdateCellAdjust( SvxCellHorJustify eJust
)
3493 eAttrAdjust
= eJust
;
3497 void ScInputHandler::ResetDelayTimer()
3499 if(pDelayTimer
!=NULL
)
3501 DELETEZ( pDelayTimer
);
3505 pInputWin
->Enable();
3510 IMPL_LINK( ScInputHandler
, DelayTimer
, Timer
*, pTimer
)
3512 if ( pTimer
== pDelayTimer
)
3514 DELETEZ( pDelayTimer
);
3516 if ( NULL
== pLastState
|| SC_MOD()->IsFormulaMode() || SC_MOD()->IsRefDialogOpen())
3518 //! new method at ScModule to query if function autopilot is open
3520 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
3521 if ( pViewFrm
&& pViewFrm
->GetChildWindow( SID_OPENDLG_FUNCTION
) )
3525 pInputWin
->EnableButtons( FALSE
);
3526 pInputWin
->Disable();
3529 else if ( !bFormulaMode
) // #39210# Formel auch z.B. bei Hilfe behalten
3531 bInOwnChange
= TRUE
; // disable ModifyHdl (reset below)
3533 pActiveViewSh
= NULL
;
3534 pEngine
->SetText( EMPTY_STRING
);
3537 pInputWin
->SetPosString( EMPTY_STRING
);
3538 pInputWin
->SetTextString( EMPTY_STRING
);
3539 pInputWin
->Disable();
3542 bInOwnChange
= FALSE
;
3549 void ScInputHandler::InputSelection( EditView
* pView
)
3553 UpdateParenthesis(); // Selektion geaendert -> Klammer-Hervorhebung neu
3555 // when the selection is changed manually, stop overwriting parentheses
3559 void ScInputHandler::InputChanged( EditView
* pView
, BOOL bFromNotify
)
3561 ESelection aSelection
= pView
->GetSelection();
3565 // #i20282# DataChanged needs to know if this is from the input line's modify handler
3566 BOOL bFromTopNotify
= ( bFromNotify
&& pView
== pTopView
);
3568 BOOL bNewView
= DataChanging(); //! kann das hier ueberhaupt sein?
3569 aCurrentText
= pView
->GetEditEngine()->GetText(); // auch den String merken
3570 pEngine
->SetText( aCurrentText
);
3571 DataChanged( bFromTopNotify
);
3572 bTextValid
= TRUE
; // wird in DataChanged auf FALSE gesetzt
3574 if ( pActiveViewSh
)
3576 ScViewData
* pViewData
= pActiveViewSh
->GetViewData();
3578 pViewData
->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3580 pViewData
->EditGrowY();
3581 pViewData
->EditGrowX();
3587 const String
& ScInputHandler::GetEditString()
3591 aCurrentText
= pEngine
->GetText(); // immer neu aus Engine
3595 return aCurrentText
;
3598 Size
ScInputHandler::GetTextSize()
3602 aSize
= Size( pEngine
->CalcTextWidth(), pEngine
->GetTextHeight() );
3607 BOOL
ScInputHandler::GetTextAndFields( ScEditEngineDefaulter
& rDestEngine
)
3612 // Feldbefehle enthalten?
3614 USHORT nParCnt
= pEngine
->GetParagraphCount();
3615 SfxItemSet aSet
= pEngine
->GetAttribs( ESelection(0,0,nParCnt
,0) );
3616 SfxItemState eFieldState
= aSet
.GetItemState( EE_FEATURE_FIELD
, FALSE
);
3617 if ( eFieldState
== SFX_ITEM_DONTCARE
|| eFieldState
== SFX_ITEM_SET
)
3621 EditTextObject
* pObj
= pEngine
->CreateTextObject();
3622 rDestEngine
.SetText(*pObj
);
3625 // Attribute loeschen
3627 for (USHORT i
=0; i
<nParCnt
; i
++)
3628 rDestEngine
.QuickRemoveCharAttribs( i
);
3630 // Absaetze zusammenfassen
3632 while ( nParCnt
> 1 )
3634 xub_StrLen nLen
= rDestEngine
.GetTextLen( (USHORT
)0 );
3635 ESelection
aSel( 0,nLen
, 1,0 );
3636 rDestEngine
.QuickInsertText( ' ', aSel
); // Umbruch durch Space ersetzen
3647 //------------------------------------------------------------------------
3648 // Methoden fuer FunktionsAutopiloten:
3649 // InputGetSelection, InputSetSelection, InputReplaceSelection, InputGetFormulaStr
3650 //------------------------------------------------------------------------
3652 void ScInputHandler::InputGetSelection( xub_StrLen
& rStart
, xub_StrLen
& rEnd
)
3654 rStart
= nFormSelStart
;
3658 //------------------------------------------------------------------------
3660 EditView
* ScInputHandler::GetFuncEditView()
3662 UpdateActiveView(); // wegen pTableView
3664 EditView
* pView
= NULL
;
3667 pInputWin
->MakeDialogEditView();
3668 pView
= pInputWin
->GetEditView();
3672 if ( eMode
!= SC_INPUT_TABLE
)
3674 bCreatingFuncView
= TRUE
; // RangeFinder nicht anzeigen
3675 SetMode( SC_INPUT_TABLE
);
3676 bCreatingFuncView
= FALSE
;
3678 pTableView
->GetEditEngine()->SetText( EMPTY_STRING
);
3686 //------------------------------------------------------------------------
3688 void ScInputHandler::InputSetSelection( xub_StrLen nStart
, xub_StrLen nEnd
)
3690 if ( nStart
<= nEnd
)
3692 nFormSelStart
= nStart
;
3697 nFormSelEnd
= nStart
;
3698 nFormSelStart
= nEnd
;
3701 EditView
* pView
= GetFuncEditView();
3703 pView
->SetSelection( ESelection(0,nStart
, 0,nEnd
) );
3708 //------------------------------------------------------------------------
3710 void ScInputHandler::InputReplaceSelection( const String
& rStr
)
3713 pRefViewSh
= pActiveViewSh
;
3715 DBG_ASSERT(nFormSelEnd
>=nFormSelStart
,"Selektion kaputt...");
3717 xub_StrLen nOldLen
= nFormSelEnd
-nFormSelStart
;
3718 xub_StrLen nNewLen
= rStr
.Len();
3720 aFormText
.Erase( nFormSelStart
, nOldLen
);
3722 aFormText
.Insert( rStr
, nFormSelStart
);
3723 nFormSelEnd
= nFormSelStart
+ nNewLen
;
3725 EditView
* pView
= GetFuncEditView();
3728 pView
->SetEditEngineUpdateMode( FALSE
);
3729 // pView->InsertText( rStr, TRUE );
3730 pView
->GetEditEngine()->SetText( aFormText
);
3731 pView
->SetSelection( ESelection(0,nFormSelStart
, 0,nFormSelEnd
) );
3732 pView
->SetEditEngineUpdateMode( TRUE
);
3737 //------------------------------------------------------------------------
3739 String
ScInputHandler::InputGetFormulaStr()
3741 return aFormText
; //! eigene Membervariable?
3744 //========================================================================
3746 //========================================================================
3748 ScInputHdlState::ScInputHdlState( const ScAddress
& rCurPos
,
3749 const ScAddress
& rStartPos
,
3750 const ScAddress
& rEndPos
,
3751 const String
& rString
,
3752 const EditTextObject
* pData
)
3753 : aCursorPos ( rCurPos
),
3754 aStartPos ( rStartPos
),
3755 aEndPos ( rEndPos
),
3756 aString ( rString
),
3757 pEditData ( pData
? pData
->Clone() : NULL
)
3761 //------------------------------------------------------------------------
3763 ScInputHdlState::ScInputHdlState( const ScInputHdlState
& rCpy
)
3764 : pEditData ( NULL
)
3769 //------------------------------------------------------------------------
3771 ScInputHdlState::~ScInputHdlState()
3776 //------------------------------------------------------------------------
3778 int ScInputHdlState::operator==( const ScInputHdlState
& r
) const
3780 return ( (aStartPos
== r
.aStartPos
)
3781 && (aEndPos
== r
.aEndPos
)
3782 && (aCursorPos
== r
.aCursorPos
)
3783 && (aString
== r
.aString
)
3784 && ScGlobal::EETextObjEqual( pEditData
, r
.pEditData
) );
3787 //------------------------------------------------------------------------
3789 ScInputHdlState
& ScInputHdlState::operator=( const ScInputHdlState
& r
)
3793 aCursorPos
= r
.aCursorPos
;
3794 aStartPos
= r
.aStartPos
;
3795 aEndPos
= r
.aEndPos
;
3796 aString
= r
.aString
;
3797 pEditData
= r
.pEditData
? r
.pEditData
->Clone() : NULL
;