1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "inputhdl.hxx"
21 #include "scitems.hxx"
22 #include <editeng/eeitem.hxx>
24 #include <sfx2/app.hxx>
25 #include <editeng/acorrcfg.hxx>
26 #include <svx/algitem.hxx>
27 #include <editeng/adjustitem.hxx>
28 #include <editeng/brushitem.hxx>
29 #include <svtools/colorcfg.hxx>
30 #include <editeng/colritem.hxx>
31 #include <editeng/editobj.hxx>
32 #include <editeng/editstat.hxx>
33 #include <editeng/editview.hxx>
34 #include <editeng/escapementitem.hxx>
35 #include <editeng/forbiddencharacterstable.hxx>
36 #include <editeng/langitem.hxx>
37 #include <editeng/svxacorr.hxx>
38 #include <editeng/unolingu.hxx>
39 #include <editeng/wghtitem.hxx>
40 #include <editeng/justifyitem.hxx>
41 #include <editeng/misspellrange.hxx>
42 #include <sfx2/bindings.hxx>
43 #include <sfx2/viewfrm.hxx>
44 #include <sfx2/dispatch.hxx>
45 #include <sfx2/docfile.hxx>
46 #include <sfx2/printer.hxx>
47 #include <svl/zforlist.hxx>
48 #include <unotools/localedatawrapper.hxx>
49 #include <vcl/help.hxx>
50 #include <vcl/cursor.hxx>
51 #include <vcl/settings.hxx>
52 #include <tools/urlobj.hxx>
53 #include <comphelper/string.hxx>
54 #include <formula/formulahelper.hxx>
56 #include "inputwin.hxx"
57 #include "tabvwsh.hxx"
60 #include "uiitems.hxx"
63 #include "globstr.hrc"
64 #include "patattr.hxx"
65 #include "viewdata.hxx"
66 #include "document.hxx"
67 #include "docpool.hxx"
68 #include "editutil.hxx"
69 #include "appoptio.hxx"
70 #include "docoptio.hxx"
71 #include "validat.hxx"
72 #include "userlist.hxx"
73 #include "rfindlst.hxx"
74 #include "inputopt.hxx"
75 #include "simpleformulacalc.hxx"
76 #include "compiler.hxx"
77 #include "editable.hxx"
78 #include "funcdesc.hxx"
79 #include "markdata.hxx"
80 #include "tokenarray.hxx"
81 #include <gridwin.hxx>
83 // Maximum Ranges in RangeFinder
84 #define RANGEFIND_MAX 32
86 using namespace formula
;
88 // STATIC DATA -----------------------------------------------------------
90 bool ScInputHandler::bOptLoaded
= false; // Evaluate App options
91 bool ScInputHandler::bAutoComplete
= false; // Is set in KeyInput
93 extern sal_uInt16 nEditAdjust
; //! Member of ViewData
97 // Formula data replacement character for a pair of parentheses at end of
98 // function name, to force sorting parentheses before all other characters.
99 // Collation may treat parentheses differently.
100 const sal_Unicode cParenthesesReplacement
= 0x0001;
102 sal_Unicode
lcl_getSheetSeparator(ScDocument
* pDoc
)
104 ScCompiler
aComp(pDoc
, ScAddress());
105 aComp
.SetGrammar(pDoc
->GetGrammar());
106 return aComp
.GetNativeAddressSymbol(ScCompiler::Convention::SHEET_SEPARATOR
);
109 ScTypedCaseStrSet::const_iterator
findText(
110 const ScTypedCaseStrSet
& rDataSet
, ScTypedCaseStrSet::const_iterator itPos
,
111 const OUString
& rStart
, OUString
& rResult
, bool bBack
)
113 if (bBack
) // Backwards
115 ScTypedCaseStrSet::const_reverse_iterator it
= rDataSet
.rbegin(), itEnd
= rDataSet
.rend();
116 if (itPos
!= rDataSet
.end())
118 size_t nPos
= std::distance(rDataSet
.begin(), itPos
);
119 size_t nRPos
= rDataSet
.size() - 1 - nPos
;
120 std::advance(it
, nRPos
);
124 for (; it
!= itEnd
; ++it
)
126 const ScTypedStrData
& rData
= *it
;
127 if (rData
.GetStringType() == ScTypedStrData::Value
)
131 if (!ScGlobal::GetpTransliteration()->isMatch(rStart
, rData
.GetString()))
135 rResult
= rData
.GetString();
136 return (++it
).base(); // convert the reverse iterator back to iterator.
141 ScTypedCaseStrSet::const_iterator it
= rDataSet
.begin(), itEnd
= rDataSet
.end();
142 if (itPos
!= rDataSet
.end())
148 for (; it
!= itEnd
; ++it
)
150 const ScTypedStrData
& rData
= *it
;
151 if (rData
.GetStringType() == ScTypedStrData::Value
)
155 if (!ScGlobal::GetpTransliteration()->isMatch(rStart
, rData
.GetString()))
159 rResult
= rData
.GetString();
164 return rDataSet
.end(); // no matching text found
167 OUString
getExactMatch(const ScTypedCaseStrSet
& rDataSet
, const OUString
& rString
)
169 ScTypedCaseStrSet::const_iterator it
= rDataSet
.begin(), itEnd
= rDataSet
.end();
170 for (; it
!= itEnd
; ++it
)
172 const ScTypedStrData
& rData
= *it
;
173 if (rData
.GetStringType() == ScTypedStrData::Value
)
176 if (!ScGlobal::GetpTransliteration()->isEqual(rData
.GetString(), rString
))
179 return rData
.GetString();
184 void removeChars(OUString
& rStr
, sal_Unicode c
)
186 OUStringBuffer
aBuf(rStr
);
187 for (sal_Int32 i
= 0, n
= aBuf
.getLength(); i
< n
; ++i
)
192 rStr
= aBuf
.makeStringAndClear();
197 void ScInputHandler::InitRangeFinder( const OUString
& rFormula
)
200 if ( !pActiveViewSh
|| !SC_MOD()->GetInputOptions().GetRangeFinder() )
202 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData().GetDocShell();
203 ScDocument
& rDoc
= pDocSh
->GetDocument();
204 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(&rDoc
);
206 OUString aDelimiters
= ScEditUtil::ModifyDelimiters(" !\"");
207 // delimiters (in addition to ScEditUtil): only characters that are
208 // allowed in formulas next to references and the quotation mark (so
209 // string constants can be skipped)
211 sal_Int32 nColon
= aDelimiters
.indexOf( ':' );
213 aDelimiters
= aDelimiters
.replaceAt( nColon
, 1, ""); // Delimiter without colon
214 sal_Int32 nDot
= aDelimiters
.indexOf(cSheetSep
);
216 aDelimiters
= aDelimiters
.replaceAt( nDot
, 1 , ""); // Delimiter without dot
218 const sal_Unicode
* pChar
= rFormula
.getStr();
219 sal_Int32 nLen
= rFormula
.getLength();
221 sal_Int32 nStart
= 0;
222 sal_uInt16 nCount
= 0;
224 while ( nPos
< nLen
&& nCount
< RANGEFIND_MAX
)
227 while ( nPos
<nLen
&& ScGlobal::UnicodeStrChr( aDelimiters
.getStr(), pChar
[nPos
] ) )
229 if ( pChar
[nPos
] == '"' ) // String
232 while (nPos
<nLen
&& pChar
[nPos
] != '"') // Skip until end
235 ++nPos
; // Separator or closing quote
238 // Text zwischen Trennern
241 while ( nPos
<nLen
&& !ScGlobal::UnicodeStrChr( aDelimiters
.getStr(), pChar
[nPos
] ) )
244 // for R1C1 '-' in R[-]... or C[-]... are not delimiters
245 // Nothing heroic here to ensure that there are '[]' around a negative
246 // integer. we need to clean up this code.
247 if( nPos
< nLen
&& nPos
> 0 &&
248 '-' == pChar
[nPos
] && '[' == pChar
[nPos
-1] &&
249 formula::FormulaGrammar::CONV_XL_R1C1
== rDoc
.GetAddressConvention() )
257 OUString aTest
= rFormula
.copy( nStart
, nPos
-nStart
);
258 const ScAddress::Details
aAddrDetails( &rDoc
, aCursorPos
);
259 sal_uInt16 nFlags
= aRange
.ParseAny( aTest
, &rDoc
, aAddrDetails
);
260 if ( nFlags
& SCA_VALID
)
262 // Set tables if not specified
263 if ( (nFlags
& SCA_TAB_3D
) == 0 )
264 aRange
.aStart
.SetTab( pActiveViewSh
->GetViewData().GetTabNo() );
265 if ( (nFlags
& SCA_TAB2_3D
) == 0 )
266 aRange
.aEnd
.SetTab( aRange
.aStart
.Tab() );
268 if ( ( nFlags
& ( SCA_VALID_COL2
| SCA_VALID_ROW2
| SCA_VALID_TAB2
) ) == 0 )
270 // #i73766# if a single ref was parsed, set the same "abs" flags for ref2,
271 // so Format doesn't output a double ref because of different flags.
272 sal_uInt16 nAbsFlags
= nFlags
& ( SCA_COL_ABSOLUTE
| SCA_ROW_ABSOLUTE
| SCA_TAB_ABSOLUTE
);
273 nFlags
|= nAbsFlags
<< 4;
278 pEngine
->SetUpdateMode( false );
279 pRangeFindList
= new ScRangeFindList( pDocSh
->GetTitle() );
282 ColorData nColorData
= pRangeFindList
->Insert( ScRangeFindData( aRange
, nFlags
, nStart
, nPos
) );
284 ESelection
aSel( 0, nStart
, 0, nPos
);
285 SfxItemSet
aSet( pEngine
->GetEmptyItemSet() );
286 aSet
.Put( SvxColorItem( Color( nColorData
),
288 pEngine
->QuickSetAttribs( aSet
, aSel
);
293 // Do not skip last separator; could be a quote (?)
298 pEngine
->SetUpdateMode( true );
300 pDocSh
->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER
) );
304 void ScInputHandler::SetDocumentDisposing( bool b
)
306 mbDocumentDisposing
= b
;
309 static void lcl_Replace( EditView
* pView
, const OUString
& rNewStr
, const ESelection
& rOldSel
)
313 ESelection aOldSel
= pView
->GetSelection();
314 if (aOldSel
.HasRange())
315 pView
->SetSelection( ESelection( aOldSel
.nEndPara
, aOldSel
.nEndPos
,
316 aOldSel
.nEndPara
, aOldSel
.nEndPos
) );
318 EditEngine
* pEngine
= pView
->GetEditEngine();
319 pEngine
->QuickInsertText( rNewStr
, rOldSel
);
321 // Dummy InsertText for Update and Paint
322 // To do that we need to cancel the selection from above (before QuickInsertText)
323 pView
->InsertText( EMPTY_OUSTRING
, false );
325 sal_Int32 nLen
= pEngine
->GetTextLen(0);
326 ESelection
aSel( 0, nLen
, 0, nLen
);
327 pView
->SetSelection( aSel
); // Set cursor to the end
331 void ScInputHandler::UpdateRange( sal_uInt16 nIndex
, const ScRange
& rNew
)
333 ScTabViewShell
* pDocView
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
334 if ( pDocView
&& pRangeFindList
&& nIndex
< pRangeFindList
->Count() )
336 ScRangeFindData
* pData
= pRangeFindList
->GetObject( nIndex
);
337 sal_Int32 nOldStart
= pData
->nSelStart
;
338 sal_Int32 nOldEnd
= pData
->nSelEnd
;
339 ColorData nNewColor
= pRangeFindList
->FindColor( rNew
, nIndex
);
341 ScRange aJustified
= rNew
;
342 aJustified
.Justify(); // Always display Ref in the Formula the right way
343 ScDocument
* pDoc
= pDocView
->GetViewData().GetDocument();
344 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
345 OUString
aNewStr(aJustified
.Format(pData
->nFlags
, pDoc
, aAddrDetails
));
346 ESelection
aOldSel( 0, nOldStart
, 0, nOldEnd
);
347 SfxItemSet
aSet( pEngine
->GetEmptyItemSet() );
351 lcl_Replace( pTopView
, aNewStr
, aOldSel
);
352 lcl_Replace( pTableView
, aNewStr
, aOldSel
);
353 aSet
.Put( SvxColorItem( Color( nNewColor
), EE_CHAR_COLOR
) );
354 pEngine
->QuickSetAttribs( aSet
, aOldSel
);
356 bInRangeUpdate
= true;
358 bInRangeUpdate
= false;
360 long nDiff
= aNewStr
.getLength() - (long)(nOldEnd
-nOldStart
);
363 pData
->nSelEnd
= pData
->nSelEnd
+ nDiff
;
364 pData
->nColorData
= nNewColor
;
366 sal_uInt16 nCount
= (sal_uInt16
) pRangeFindList
->Count();
367 for (sal_uInt16 i
=nIndex
+1; i
<nCount
; i
++)
369 ScRangeFindData
* pNext
= pRangeFindList
->GetObject( i
);
370 pNext
->nSelStart
= pNext
->nSelStart
+ nDiff
;
371 pNext
->nSelEnd
= pNext
->nSelEnd
+ nDiff
;
374 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
375 pActiveView
->ShowCursor( false, true );
379 OSL_FAIL("UpdateRange: we're missing something");
383 void ScInputHandler::DeleteRangeFinder()
385 ScTabViewShell
* pPaintView
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
386 if ( pRangeFindList
&& pPaintView
)
388 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData().GetDocShell();
389 pRangeFindList
->SetHidden(true);
390 pDocSh
->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER
) ); // Steal
391 DELETEZ(pRangeFindList
);
395 inline OUString
GetEditText(EditEngine
* pEng
)
397 return ScEditUtil::GetSpaceDelimitedString(*pEng
);
400 static void lcl_RemoveTabs(OUString
& rStr
)
402 removeChars(rStr
, '\t');
405 static void lcl_RemoveLineEnd(OUString
& rStr
)
407 rStr
= convertLineEnd(rStr
, LINEEND_LF
);
408 removeChars(rStr
, '\n');
411 static sal_Int32
lcl_MatchParenthesis( const OUString
& rStr
, sal_Int32 nPos
)
414 sal_Unicode c1
, c2
= 0;
455 sal_Int32 nLen
= rStr
.getLength();
456 const sal_Unicode
* p0
= rStr
.getStr();
457 const sal_Unicode
* p
;
458 const sal_Unicode
* p1
;
459 sal_uInt16 nQuotes
= 0;
460 if ( nPos
< nLen
/ 2 )
475 // Odd number of quotes that we find ourselves in a string
476 bool bLookInString
= ((nQuotes
% 2) != 0);
477 bool bInString
= bLookInString
;
479 p1
= (nDir
< 0 ? p0
: p0
+ nLen
) ;
480 sal_uInt16 nLevel
= 1;
481 while ( p
!= p1
&& nLevel
)
486 bInString
= !bInString
;
487 if ( bLookInString
&& !bInString
)
488 p
= p1
; // That's it then
490 else if ( bInString
== bLookInString
)
500 return (sal_Int32
) (p
- p0
);
503 ScInputHandler::ScInputHandler()
509 pFormulaData( NULL
),
510 pFormulaDataPara( NULL
),
511 pTipVisibleParent( NULL
),
513 pTipVisibleSecParent( NULL
),
518 eMode( SC_INPUT_NONE
),
523 bFormulaMode( false ),
524 bInRangeUpdate( false ),
525 bParenthesisShown( false ),
526 bCreatingFuncView( false ),
527 bInEnterHandler( false ),
528 bCommandErrorShown( false ),
529 bInOwnChange( false ),
531 bCellHasPercentFormat( false ),
532 bLastIsSymbol( false ),
533 mbDocumentDisposing(false),
535 eAttrAdjust( SVX_HOR_JUSTIFY_STANDARD
),
539 pLastPattern( NULL
),
540 pEditDefaults( NULL
),
543 pRangeFindList( NULL
),
546 // The InputHandler is constructed with the view, so SfxViewShell::Current
547 // doesn't have the right view yet. pActiveViewSh is updated in NotifyChange.
548 pActiveViewSh
= NULL
;
550 // Bindings (only still used for Invalidate) are retrieved if needed on demand
553 ScInputHandler::~ScInputHandler()
555 // If this is the application InputHandler, the dtor is called after SfxApplication::Main,
556 // thus we can't rely on any Sfx functions
557 if (!mbDocumentDisposing
) // inplace
558 EnterHandler(); // Finish input
560 if (SC_MOD()->GetRefInputHdl() == this)
561 SC_MOD()->SetRefInputHdl(NULL
);
563 if ( pInputWin
&& pInputWin
->GetInputHandler() == this )
564 pInputWin
->SetInputHandler( NULL
);
566 delete pRangeFindList
;
567 delete pEditDefaults
;
573 delete pFormulaDataPara
;
576 void ScInputHandler::SetRefScale( const Fraction
& rX
, const Fraction
& rY
)
578 if ( rX
!= aScaleX
|| rY
!= aScaleY
)
584 MapMode
aMode( MAP_100TH_MM
, Point(), aScaleX
, aScaleY
);
585 pEngine
->SetRefMapMode( aMode
);
590 void ScInputHandler::UpdateRefDevice()
595 bool bTextWysiwyg
= SC_MOD()->GetInputOptions().GetTextWysiwyg();
596 bool bInPlace
= pActiveViewSh
&& pActiveViewSh
->GetViewFrame()->GetFrame().IsInPlace();
597 EEControlBits nCtrl
= pEngine
->GetControlWord();
598 if ( bTextWysiwyg
|| bInPlace
)
599 nCtrl
|= EEControlBits::FORMAT100
; // EditEngine default: always format for 100%
601 nCtrl
&= ~EEControlBits::FORMAT100
; // when formatting for screen, use the actual MapMode
602 pEngine
->SetControlWord( nCtrl
);
603 if ( bTextWysiwyg
&& pActiveViewSh
)
604 pEngine
->SetRefDevice( pActiveViewSh
->GetViewData().GetDocument()->GetPrinter() );
606 pEngine
->SetRefDevice( NULL
);
608 MapMode
aMode( MAP_100TH_MM
, Point(), aScaleX
, aScaleY
);
609 pEngine
->SetRefMapMode( aMode
);
611 // SetRefDevice(NULL) uses VirtualDevice, SetRefMapMode forces creation of a local VDev,
612 // so the DigitLanguage can be safely modified (might use an own VDev instead of NULL).
613 if ( !( bTextWysiwyg
&& pActiveViewSh
) )
615 pEngine
->GetRefDevice()->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
619 void ScInputHandler::ImplCreateEditEngine()
625 ScDocument
& rDoc
= pActiveViewSh
->GetViewData().GetDocShell()->GetDocument();
626 pEngine
= new ScFieldEditEngine(&rDoc
, rDoc
.GetEnginePool(), rDoc
.GetEditPool());
629 pEngine
= new ScFieldEditEngine(NULL
, EditEngine::CreatePool(), NULL
, true);
630 pEngine
->SetWordDelimiters( ScEditUtil::ModifyDelimiters( pEngine
->GetWordDelimiters() ) );
631 UpdateRefDevice(); // also sets MapMode
632 pEngine
->SetPaperSize( Size( 1000000, 1000000 ) );
633 pEditDefaults
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
635 pEngine
->SetControlWord( pEngine
->GetControlWord() | EEControlBits::AUTOCORRECT
);
636 pEngine
->SetModifyHdl( LINK( this, ScInputHandler
, ModifyHdl
) );
639 // set the EditEngine so that it invalidates the view instead of direct
643 ScDocument
& rDoc
= pActiveViewSh
->GetViewData().GetDocShell()->GetDocument();
644 if (EditView
* pEditView
= pEngine
->GetActiveView())
645 pEditView
->setTiledRendering(rDoc
.GetDrawLayer()->isTiledRendering());
649 void ScInputHandler::UpdateAutoCorrFlag()
651 EEControlBits nCntrl
= pEngine
->GetControlWord();
652 EEControlBits nOld
= nCntrl
;
654 // Don't use pLastPattern here (may be invalid because of AutoStyle)
655 bool bDisable
= bLastIsSymbol
|| bFormulaMode
;
657 nCntrl
&= ~EEControlBits::AUTOCORRECT
;
659 nCntrl
|= EEControlBits::AUTOCORRECT
;
661 if ( nCntrl
!= nOld
)
662 pEngine
->SetControlWord(nCntrl
);
665 void ScInputHandler::UpdateSpellSettings( bool bFromStartTab
)
669 ScViewData
& rViewData
= pActiveViewSh
->GetViewData();
670 bool bOnlineSpell
= rViewData
.GetDocument()->GetDocOptions().IsAutoSpell();
672 // SetDefaultLanguage is independent of the language attributes,
673 // ScGlobal::GetEditDefaultLanguage is always used.
674 // It must be set every time in case the office language was changed.
676 pEngine
->SetDefaultLanguage( ScGlobal::GetEditDefaultLanguage() );
678 // if called for changed options, update flags only if already editing
679 // if called from StartTable, always update flags
681 if ( bFromStartTab
|| eMode
!= SC_INPUT_NONE
)
683 EEControlBits nCntrl
= pEngine
->GetControlWord();
684 EEControlBits nOld
= nCntrl
;
686 nCntrl
|= EEControlBits::ONLINESPELLING
;
688 nCntrl
&= ~EEControlBits::ONLINESPELLING
;
689 // No AutoCorrect for Symbol Font (EditEngine does no evaluate Default)
690 if ( pLastPattern
&& pLastPattern
->IsSymbolFont() )
691 nCntrl
&= ~EEControlBits::AUTOCORRECT
;
693 nCntrl
|= EEControlBits::AUTOCORRECT
;
694 if ( nCntrl
!= nOld
)
695 pEngine
->SetControlWord(nCntrl
);
697 ScDocument
* pDoc
= rViewData
.GetDocument();
698 pDoc
->ApplyAsianEditSettings( *pEngine
);
699 pEngine
->SetDefaultHorizontalTextDirection(
700 (EEHorizontalTextDirection
)pDoc
->GetEditTextDirection( rViewData
.GetTabNo() ) );
701 pEngine
->SetFirstWordCapitalization( false );
704 // Language is set separately, so the speller is needed only if online spelling is active
705 if ( bOnlineSpell
) {
706 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XSpellChecker1
> xXSpellChecker1( LinguMgr::GetSpellChecker() );
707 pEngine
->SetSpeller( xXSpellChecker1
);
710 bool bHyphen
= pLastPattern
&& static_cast<const SfxBoolItem
&>(pLastPattern
->GetItem(ATTR_HYPHENATE
)).GetValue();
712 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
713 pEngine
->SetHyphenator( xXHyphenator
);
718 // Function/Range names etc. as Tip help
720 // The other types are defined in ScDocument::GetFormulaEntries
721 void ScInputHandler::GetFormulaData()
725 ScDocument
& rDoc
= pActiveViewSh
->GetViewData().GetDocShell()->GetDocument();
728 pFormulaData
->clear();
731 pFormulaData
= new ScTypedCaseStrSet
;
734 if( pFormulaDataPara
)
735 pFormulaDataPara
->clear();
737 pFormulaDataPara
= new ScTypedCaseStrSet
;
739 const OUString
aParenthesesReplacement( cParenthesesReplacement
);
740 const ScFunctionList
* pFuncList
= ScGlobal::GetStarCalcFunctionList();
741 sal_uLong nListCount
= pFuncList
->GetCount();
742 for(sal_uLong i
=0;i
<nListCount
;i
++)
744 const ScFuncDesc
* pDesc
= pFuncList
->GetFunction( i
);
745 if ( pDesc
->pFuncName
)
747 const sal_Unicode
* pName
= pDesc
->pFuncName
->getStr();
748 const sal_Int32 nLen
= pDesc
->pFuncName
->getLength();
749 // fdo#75264 fill maFormulaChar with all characters used in formula names
750 for ( sal_Int32 j
= 0; j
< nLen
; j
++ )
752 sal_Unicode c
= pName
[ j
];
753 maFormulaChar
.insert( c
);
755 OUString aFuncName
= *pDesc
->pFuncName
+ aParenthesesReplacement
;
756 pFormulaData
->insert(ScTypedStrData(aFuncName
, 0.0, ScTypedStrData::Standard
));
757 pDesc
->initArgumentInfo();
758 OUString aEntry
= pDesc
->getSignature();
759 pFormulaDataPara
->insert(ScTypedStrData(aEntry
, 0.0, ScTypedStrData::Standard
));
762 miAutoPosFormula
= pFormulaData
->end();
763 rDoc
.GetFormulaEntries( *pFormulaData
);
764 rDoc
.GetFormulaEntries( *pFormulaDataPara
);
768 IMPL_LINK( ScInputHandler
, ShowHideTipVisibleParentListener
, VclWindowEvent
*, pEvent
)
770 if( pEvent
->GetId() == VCLEVENT_OBJECT_DYING
|| pEvent
->GetId() == VCLEVENT_WINDOW_HIDE
)
775 IMPL_LINK( ScInputHandler
, ShowHideTipVisibleSecParentListener
, VclWindowEvent
*, pEvent
)
777 if( pEvent
->GetId() == VCLEVENT_OBJECT_DYING
|| pEvent
->GetId() == VCLEVENT_WINDOW_HIDE
)
782 void ScInputHandler::HideTip()
786 if (pTipVisibleParent
)
787 pTipVisibleParent
->RemoveEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleParentListener
) );
788 Help::HideTip( nTipVisible
);
790 pTipVisibleParent
= NULL
;
794 void ScInputHandler::HideTipBelow()
796 if ( nTipVisibleSec
)
798 if (pTipVisibleSecParent
)
799 pTipVisibleSecParent
->RemoveEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleSecParentListener
) );
800 Help::HideTip( nTipVisibleSec
);
802 pTipVisibleSecParent
= NULL
;
807 void ScInputHandler::ShowArgumentsTip( OUString
& rSelText
)
809 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData().GetDocShell();
810 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
811 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(&pDocSh
->GetDocument());
812 FormulaHelper
aHelper(ScGlobal::GetStarCalcFunctionMgr());
817 sal_Int32 nLeftParentPos
= lcl_MatchParenthesis( rSelText
, rSelText
.getLength()-1 );
818 if( nLeftParentPos
!= -1 )
820 sal_Int32 nNextFStart
= aHelper
.GetFunctionStart( rSelText
, nLeftParentPos
, true);
821 const IFunctionDescription
* ppFDesc
;
822 ::std::vector
< OUString
> aArgs
;
823 if( aHelper
.GetNextFunc( rSelText
, false, nNextFStart
, NULL
, &ppFDesc
, &aArgs
) )
825 if( !ppFDesc
->getFunctionName().isEmpty() )
827 sal_Int32 nArgPos
= aHelper
.GetArgStart( rSelText
, nNextFStart
, 0 );
828 sal_uInt16 nArgs
= static_cast<sal_uInt16
>(ppFDesc
->getParameterCount());
829 OUString
aFuncName( ppFDesc
->getFunctionName() + "(");
831 ScTypedCaseStrSet::const_iterator it
=
832 findText(*pFormulaDataPara
, pFormulaDataPara
->end(), aFuncName
, aNew
, false);
833 if (it
!= pFormulaDataPara
->end())
836 sal_uInt16 nActive
= 0;
837 for( sal_uInt16 i
=0; i
< nArgs
; i
++ )
839 sal_Int32 nLength
= aArgs
[i
].getLength();
840 if( nArgPos
<= rSelText
.getLength()-1 )
849 sal_Int32 nCountSemicolon
= comphelper::string::getTokenCount(aNew
, cSep
) - 1;
850 sal_Int32 nCountDot
= comphelper::string::getTokenCount(aNew
, cSheetSep
) - 1;
851 sal_Int32 nStartPosition
= 0;
852 sal_Int32 nEndPosition
= 0;
854 if( !nCountSemicolon
)
856 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
858 sal_Unicode cNext
= aNew
[i
];
861 nStartPosition
= i
+1;
865 else if( !nCountDot
)
867 sal_uInt16 nCount
= 0;
868 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
870 sal_Unicode cNext
= aNew
[i
];
873 nStartPosition
= i
+1;
875 else if( cNext
== cSep
)
879 if( nCount
== nActive
)
883 nStartPosition
= nEndPosition
+1;
889 sal_uInt16 nCount
= 0;
890 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
892 sal_Unicode cNext
= aNew
[i
];
895 nStartPosition
= i
+1;
897 else if( cNext
== cSep
)
901 if( nCount
== nActive
)
905 nStartPosition
= nEndPosition
+1;
907 else if( cNext
== cSheetSep
)
914 if (nStartPosition
> 0)
917 aBuf
.append(aNew
.copy(0, nStartPosition
));
918 aBuf
.append(static_cast<sal_Unicode
>(0x25BA));
919 aBuf
.append(aNew
.copy(nStartPosition
));
920 aNew
= aBuf
.makeStringAndClear();
921 ShowTipBelow( aNew
);
927 ShowTipBelow( aNew
);
941 void ScInputHandler::ShowTipCursor()
945 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
947 if ( bFormulaMode
&& pActiveView
&& pFormulaDataPara
&& pEngine
->GetParagraphCount() == 1 )
949 OUString aParagraph
= pEngine
->GetText( 0 );
950 ESelection aSel
= pActiveView
->GetSelection();
953 if ( aParagraph
.getLength() < aSel
.nEndPos
)
956 if ( aSel
.nEndPos
> 0 )
958 OUString
aSelText( aParagraph
.copy( 0, aSel
.nEndPos
));
960 ShowArgumentsTip( aSelText
);
965 void ScInputHandler::ShowTip( const OUString
& rText
)
967 // aManualTip needs to be set afterwards from outside
969 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
973 pTipVisibleParent
= pActiveView
->GetWindow();
974 vcl::Cursor
* pCur
= pActiveView
->GetCursor();
976 aPos
= pTipVisibleParent
->LogicToPixel( pCur
->GetPos() );
977 aPos
= pTipVisibleParent
->OutputToScreenPixel( aPos
);
978 Rectangle
aRect( aPos
, aPos
);
980 QuickHelpFlags nAlign
= QuickHelpFlags::Left
|QuickHelpFlags::Bottom
;
981 nTipVisible
= Help::ShowTip(pTipVisibleParent
, aRect
, rText
, nAlign
);
982 pTipVisibleParent
->AddEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleParentListener
) );
986 void ScInputHandler::ShowTipBelow( const OUString
& rText
)
990 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
994 pTipVisibleSecParent
= pActiveView
->GetWindow();
995 vcl::Cursor
* pCur
= pActiveView
->GetCursor();
998 Point aLogicPos
= pCur
->GetPos();
999 aLogicPos
.Y() += pCur
->GetHeight();
1000 aPos
= pTipVisibleSecParent
->LogicToPixel( aLogicPos
);
1002 aPos
= pTipVisibleSecParent
->OutputToScreenPixel( aPos
);
1003 Rectangle
aRect( aPos
, aPos
);
1004 QuickHelpFlags nAlign
= QuickHelpFlags::Left
| QuickHelpFlags::Top
| QuickHelpFlags::NoEvadePointer
;
1005 nTipVisibleSec
= Help::ShowTip(pTipVisibleSecParent
, aRect
, rText
, nAlign
);
1006 pTipVisibleSecParent
->AddEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleSecParentListener
) );
1010 bool ScInputHandler::GetFuncName( OUString
& aStart
, OUString
& aResult
)
1012 if ( aStart
.isEmpty() )
1015 aStart
= ScGlobal::pCharClass
->uppercase( aStart
);
1016 sal_Int32 nPos
= aStart
.getLength() - 1;
1017 sal_Unicode c
= aStart
[ nPos
];
1018 // fdo#75264 use maFormulaChar to check if characters are used in function names
1019 ::std::set
< sal_Unicode
>::const_iterator p
= maFormulaChar
.find( c
);
1020 if ( p
== maFormulaChar
.end() )
1021 return false; // last character is not part of any function name, quit
1023 ::std::vector
<sal_Unicode
> aTemp
;
1024 aTemp
.push_back( c
);
1025 for(sal_Int32 i
= nPos
- 1; i
>= 0; --i
)
1028 p
= maFormulaChar
.find( c
);
1030 if (p
== maFormulaChar
.end())
1033 aTemp
.push_back( c
);
1036 ::std::vector
<sal_Unicode
>::reverse_iterator rIt
= aTemp
.rbegin();
1037 aResult
= OUString( *rIt
++ );
1038 while ( rIt
!= aTemp
.rend() )
1039 aResult
+= OUString( *rIt
++ );
1044 void ScInputHandler::UseFormulaData()
1046 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1048 // Formulas may only have 1 paragraph
1049 if ( pActiveView
&& pFormulaData
&& pEngine
->GetParagraphCount() == 1 )
1051 OUString aParagraph
= pEngine
->GetText( 0 );
1052 ESelection aSel
= pActiveView
->GetSelection();
1055 // Due to differences between table and input cell (e.g clipboard with line breaks),
1056 // the selection may not be in line with the EditEngine anymore.
1057 // Just return without any indication as to why.
1058 if ( aSel
.nEndPos
> aParagraph
.getLength() )
1061 if ( aParagraph
.getLength() > aSel
.nEndPos
&&
1062 ( ScGlobal::pCharClass
->isLetterNumeric( aParagraph
, aSel
.nEndPos
) ||
1063 aParagraph
[ aSel
.nEndPos
] == '_' ||
1064 aParagraph
[ aSel
.nEndPos
] == '.' ) )
1067 // Is the cursor at the end of a word?
1068 if ( aSel
.nEndPos
> 0 )
1070 OUString
aSelText( aParagraph
.copy( 0, aSel
.nEndPos
));
1073 if ( GetFuncName( aSelText
, aText
) )
1075 // function name is incomplete:
1076 // show first matching function name as tip above cell
1078 miAutoPosFormula
= pFormulaData
->end();
1079 miAutoPosFormula
= findText(*pFormulaData
, miAutoPosFormula
, aText
, aNew
, false);
1080 if (miAutoPosFormula
!= pFormulaData
->end())
1082 // check if partial function name is not Between quotes
1083 bool bBetweenQuotes
= false;
1084 for ( int n
= 0; n
< aSelText
.getLength(); n
++ )
1086 if ( aSelText
[ n
] == '"' )
1087 bBetweenQuotes
= !bBetweenQuotes
;
1089 if ( bBetweenQuotes
)
1090 return; // we're between quotes
1092 if (aNew
[aNew
.getLength()-1] == cParenthesesReplacement
)
1093 aNew
= aNew
.copy( 0, aNew
.getLength()-1) + "()";
1095 aAutoSearch
= aText
;
1100 // function name is complete:
1101 // show tip below the cell with function name and arguments of function
1102 ShowArgumentsTip( aSelText
);
1107 void ScInputHandler::NextFormulaEntry( bool bBack
)
1109 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1110 if ( pActiveView
&& pFormulaData
)
1113 ScTypedCaseStrSet::const_iterator itNew
= findText(*pFormulaData
, miAutoPosFormula
, aAutoSearch
, aNew
, bBack
);
1114 if (itNew
!= pFormulaData
->end())
1116 miAutoPosFormula
= itNew
;
1117 if (aNew
[aNew
.getLength()-1] == cParenthesesReplacement
)
1118 aNew
= aNew
.copy( 0, aNew
.getLength()-1) + "()";
1119 ShowTip(aNew
); // Display a quick help
1123 // For Tab we always call HideCursor first
1125 pActiveView
->ShowCursor();
1130 bool needToExtendSelection(const OUString
& rSelectedText
, const OUString
& rInsertText
)
1132 return !rInsertText
.startsWithIgnoreAsciiCase(rSelectedText
);
1135 void completeFunction( EditView
* pView
, const OUString
& rInsert
, bool& rParInserted
)
1139 ESelection aSel
= pView
->GetSelection();
1142 pView
->SetSelection(aSel
);
1143 pView
->SelectCurrentWord();
1145 // a dot and underscore are word separators so we need special
1146 // treatment for any formula containing a dot or underscore
1147 if(rInsert
.indexOf(".") != -1 || rInsert
.indexOf("_") != -1)
1149 // need to make sure that we replace also the part before the dot
1150 // go through the word to find the match with the insert string
1151 aSel
= pView
->GetSelection();
1152 ESelection aOldSelection
= aSel
;
1153 OUString aSelectedText
= pView
->GetSelected();
1154 if ( needToExtendSelection( aSelectedText
, rInsert
) )
1156 while(needToExtendSelection(aSelectedText
, rInsert
))
1158 assert(aSel
.nStartPos
> 0);
1160 aSel
.nEndPos
= aSel
.nStartPos
;
1161 pView
->SetSelection(aSel
);
1162 pView
->SelectCurrentWord();
1163 aSelectedText
= pView
->GetSelected();
1165 aSel
.nStartPos
= aSel
.nEndPos
- ( aSelectedText
.getLength() - 1 );
1169 aSel
.nStartPos
= aSel
.nEndPos
- aSelectedText
.getLength();
1171 aSel
.nEndPos
= aOldSelection
.nEndPos
;
1172 pView
->SetSelection(aSel
);
1175 OUString aInsStr
= rInsert
;
1176 sal_Int32 nInsLen
= aInsStr
.getLength();
1177 bool bDoParen
= ( nInsLen
> 1 && aInsStr
[nInsLen
-2] == '('
1178 && aInsStr
[nInsLen
-1] == ')' );
1181 // Do not insert parentheses after function names if there already are some
1182 // (e.g. if the function name was edited).
1183 ESelection aWordSel
= pView
->GetSelection();
1184 OUString aOld
= pView
->GetEditEngine()->GetText(0);
1186 // aWordSel.EndPos points one behind string if word at end
1187 if (aWordSel
.nEndPos
< aOld
.getLength())
1189 sal_Unicode cNext
= aOld
[aWordSel
.nEndPos
];
1193 aInsStr
= aInsStr
.copy( 0, nInsLen
- 2 ); // Skip parentheses
1198 pView
->InsertText( aInsStr
, false );
1200 if ( bDoParen
) // Put cursor between parentheses
1202 aSel
= pView
->GetSelection();
1205 pView
->SetSelection(aSel
);
1207 rParInserted
= true;
1214 void ScInputHandler::PasteFunctionData()
1216 if (pFormulaData
&& miAutoPosFormula
!= pFormulaData
->end())
1218 const ScTypedStrData
& rData
= *miAutoPosFormula
;
1219 OUString aInsert
= rData
.GetString();
1220 if (aInsert
[aInsert
.getLength()-1] == cParenthesesReplacement
)
1221 aInsert
= aInsert
.copy( 0, aInsert
.getLength()-1) + "()";
1222 bool bParInserted
= false;
1224 DataChanging(); // Cannot be new
1225 completeFunction( pTopView
, aInsert
, bParInserted
);
1226 completeFunction( pTableView
, aInsert
, bParInserted
);
1236 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1238 pActiveView
->ShowCursor();
1241 // Calculate selection and display as tip help
1242 static OUString
lcl_Calculate( const OUString
& rFormula
, ScDocument
* pDoc
, const ScAddress
&rPos
)
1244 //TODO: Merge with ScFormulaDlg::CalcValue and move into Document!
1245 // Quotation marks for Strings are only inserted here.
1247 if(rFormula
.isEmpty())
1250 boost::scoped_ptr
<ScSimpleFormulaCalculator
> pCalc( new ScSimpleFormulaCalculator( pDoc
, rPos
, rFormula
) );
1252 // FIXME: HACK! In order to not get a #REF! for ColRowNames, if a name is actually inserted as a Range
1253 // into the whole Formula, but is interpreted as a single cell reference when displaying it on its own
1254 bool bColRowName
= pCalc
->HasColRowName();
1257 // ColRowName in RPN code?
1258 if ( pCalc
->GetCode()->GetCodeLen() <= 1 )
1259 { // ==1: Single one is as a Parameter always a Range
1260 // ==0: It might be one, if ...
1261 OUStringBuffer aBraced
;
1262 aBraced
.append('(');
1263 aBraced
.append(rFormula
);
1264 aBraced
.append(')');
1265 pCalc
.reset( new ScSimpleFormulaCalculator( pDoc
, rPos
, aBraced
.makeStringAndClear() ) );
1268 bColRowName
= false;
1271 sal_uInt16 nErrCode
= pCalc
->GetErrCode();
1272 if ( nErrCode
!= 0 )
1273 return ScGlobal::GetErrorString(nErrCode
);
1275 SvNumberFormatter
& aFormatter
= *(pDoc
->GetFormatTable());
1277 if ( pCalc
->IsValue() )
1279 double n
= pCalc
->GetValue();
1280 sal_uLong nFormat
= aFormatter
.GetStandardFormat( n
, 0,
1281 pCalc
->GetFormatType(), ScGlobal::eLnge
);
1282 aFormatter
.GetInputLineString( n
, nFormat
, aValue
);
1283 //! display OutputString but insert InputLineString
1287 OUString aStr
= pCalc
->GetString().getString();
1288 sal_uLong nFormat
= aFormatter
.GetStandardFormat(
1289 pCalc
->GetFormatType(), ScGlobal::eLnge
);
1292 aFormatter
.GetOutputString( aStr
, nFormat
,
1296 aValue
= "\"" + aValue
+ "\"";
1297 //! Escape quotation marks in String??
1301 if ( bColRowName
|| (aTestRange
.Parse(rFormula
) & SCA_VALID
) )
1302 aValue
= aValue
+ " ...";
1307 void ScInputHandler::FormulaPreview()
1310 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1311 if ( pActiveView
&& pActiveViewSh
)
1313 OUString aPart
= pActiveView
->GetSelected();
1314 if (aPart
.isEmpty())
1315 aPart
= pEngine
->GetText(0);
1316 ScDocument
& rDoc
= pActiveViewSh
->GetViewData().GetDocShell()->GetDocument();
1317 aValue
= lcl_Calculate( aPart
, &rDoc
, aCursorPos
);
1320 if (!aValue
.isEmpty())
1322 ShowTip( aValue
); // Display as QuickHelp
1323 aManualTip
= aValue
; // Set after ShowTip
1325 miAutoPosFormula
= pFormulaData
->end();
1327 miAutoPosColumn
= pColumnData
->end();
1331 void ScInputHandler::PasteManualTip()
1333 // Three dots at the end -> Range reference -> do not insert
1334 // FIXME: Once we have matrix constants, we can change this
1335 sal_Int32 nTipLen
= aManualTip
.getLength();
1336 sal_uInt32
const nTipLen2(sal::static_int_cast
<sal_uInt32
>(nTipLen
));
1337 if ( nTipLen
&& ( nTipLen
< 3 || aManualTip
.copy( nTipLen2
-3 ) != "..." ) )
1339 DataChanging(); // Cannot be new
1341 OUString aInsert
= aManualTip
;
1342 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1343 if (!pActiveView
->HasSelection())
1345 // Nothing selected -> select everything
1346 sal_Int32 nOldLen
= pEngine
->GetTextLen(0);
1347 ESelection
aAllSel( 0, 0, 0, nOldLen
);
1349 pTopView
->SetSelection( aAllSel
);
1351 pTableView
->SetSelection( aAllSel
);
1354 ESelection aSel
= pActiveView
->GetSelection();
1356 OSL_ENSURE( !aSel
.nStartPara
&& !aSel
.nEndPara
, "Too many paragraphs in Formula" );
1357 if ( !aSel
.nStartPos
) // Selection from the start?
1359 if ( aSel
.nEndPos
== pEngine
->GetTextLen(0) )
1361 // Everything selected -> skip quotation marks
1362 if ( aInsert
[0] == '"' )
1363 aInsert
= aInsert
.copy(1);
1364 sal_Int32 nInsLen
= aInsert
.getLength();
1365 if ( aInsert
.endsWith("\"") )
1366 aInsert
= aInsert
.copy( 0, nInsLen
-1 );
1368 else if ( aSel
.nEndPos
)
1370 // Not everything selected -> do not overwrite equality sign
1371 //FIXME: Even double equality signs??
1374 pTopView
->SetSelection( aSel
);
1376 pTableView
->SetSelection( aSel
);
1380 pTopView
->InsertText( aInsert
, true );
1382 pTableView
->InsertText( aInsert
, true );
1390 void ScInputHandler::ResetAutoPar()
1395 void ScInputHandler::AutoParAdded()
1397 ++nAutoPar
; // Closing parenthesis can be overwritten
1400 bool ScInputHandler::CursorAtClosingPar()
1402 // Test if the cursor is before a closing parenthesis
1403 // Selection from SetReference has been removed before
1404 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1405 if ( pActiveView
&& !pActiveView
->HasSelection() && bFormulaMode
)
1407 ESelection aSel
= pActiveView
->GetSelection();
1408 sal_Int32 nPos
= aSel
.nStartPos
;
1409 OUString aFormula
= pEngine
->GetText(0);
1410 if ( nPos
< aFormula
.getLength() && aFormula
[nPos
] == ')' )
1416 void ScInputHandler::SkipClosingPar()
1418 // this is called when a ')' is typed and the cursor is before a ')'
1419 // that can be overwritten -> just set the cursor behind the ')'
1421 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1424 ESelection aSel
= pActiveView
->GetSelection();
1428 // this is in a formula (only one paragraph), so the selection
1429 // can be used directly for the TopView
1432 pTopView
->SetSelection( aSel
);
1434 pTableView
->SetSelection( aSel
);
1437 OSL_ENSURE(nAutoPar
, "SkipClosingPar: count is wrong");
1443 void ScInputHandler::GetColData()
1445 if ( pActiveViewSh
)
1447 ScDocument
& rDoc
= pActiveViewSh
->GetViewData().GetDocShell()->GetDocument();
1450 pColumnData
->clear();
1452 pColumnData
= new ScTypedCaseStrSet
;
1454 std::vector
<ScTypedStrData
> aEntries
;
1455 rDoc
.GetDataEntries(
1456 aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab(), true, aEntries
, true);
1457 if (!aEntries
.empty())
1458 pColumnData
->insert(aEntries
.begin(), aEntries
.end());
1460 miAutoPosColumn
= pColumnData
->end();
1464 void ScInputHandler::UseColData() // When typing
1466 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1467 if ( pActiveView
&& pColumnData
)
1469 // Only change when cursor is at the end
1470 ESelection aSel
= pActiveView
->GetSelection();
1473 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
1474 if ( aSel
.nEndPara
+1 == nParCnt
)
1476 sal_Int32 nParLen
= pEngine
->GetTextLen( aSel
.nEndPara
);
1477 if ( aSel
.nEndPos
== nParLen
)
1479 OUString aText
= GetEditText(pEngine
);
1480 if (!aText
.isEmpty())
1483 miAutoPosColumn
= pColumnData
->end();
1484 miAutoPosColumn
= findText(*pColumnData
, miAutoPosColumn
, aText
, aNew
, false);
1485 if (miAutoPosColumn
!= pColumnData
->end())
1487 // Strings can contain line endings (e.g. due to dBase import),
1488 // which would result in multiple paragraphs here, which is not desirable.
1489 //! Then GetExactMatch doesn't work either
1490 lcl_RemoveLineEnd( aNew
);
1492 // Keep paragraph, just append the rest
1493 //! Exact replacement in EnterHandler !!!
1494 // One Space between paragraphs:
1495 sal_Int32 nEdLen
= pEngine
->GetTextLen() + nParCnt
- 1;
1496 OUString aIns
= aNew
.copy(nEdLen
);
1498 // Selection must be "backwards", so the cursor stays behind the last
1500 ESelection
aSelection( aSel
.nEndPara
, aSel
.nEndPos
+ aIns
.getLength(),
1501 aSel
.nEndPara
, aSel
.nEndPos
);
1503 // When editing in input line, apply to both edit views
1506 pTableView
->InsertText( aIns
, false );
1507 pTableView
->SetSelection( aSelection
);
1511 pTopView
->InsertText( aIns
, false );
1512 pTopView
->SetSelection( aSelection
);
1515 aAutoSearch
= aText
; // To keep searching - nAutoPos is set
1517 if (aText
.getLength() == aNew
.getLength())
1519 // If the inserted text is found, consume TAB only if there's more coming
1521 ScTypedCaseStrSet::const_iterator itNextPos
=
1522 findText(*pColumnData
, miAutoPosColumn
, aText
, aDummy
, false);
1523 bUseTab
= itNextPos
!= pColumnData
->end();
1534 void ScInputHandler::NextAutoEntry( bool bBack
)
1536 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1537 if ( pActiveView
&& pColumnData
)
1539 if (miAutoPosColumn
!= pColumnData
->end() && !aAutoSearch
.isEmpty())
1541 // Is the selection still valid (could be changed via the mouse)?
1542 ESelection aSel
= pActiveView
->GetSelection();
1544 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
1545 if ( aSel
.nEndPara
+1 == nParCnt
&& aSel
.nStartPara
== aSel
.nEndPara
)
1547 OUString aText
= GetEditText(pEngine
);
1548 sal_Int32 nSelLen
= aSel
.nEndPos
- aSel
.nStartPos
;
1549 sal_Int32 nParLen
= pEngine
->GetTextLen( aSel
.nEndPara
);
1550 if ( aSel
.nEndPos
== nParLen
&& aText
.getLength() == aAutoSearch
.getLength() + nSelLen
)
1553 ScTypedCaseStrSet::const_iterator itNew
=
1554 findText(*pColumnData
, miAutoPosColumn
, aAutoSearch
, aNew
, bBack
);
1556 if (itNew
!= pColumnData
->end())
1559 miAutoPosColumn
= itNew
;
1560 bInOwnChange
= true; // disable ModifyHdl (reset below)
1562 lcl_RemoveLineEnd( aNew
);
1563 OUString aIns
= aNew
.copy(aAutoSearch
.getLength());
1565 // when editing in input line, apply to both edit views
1568 pTableView
->DeleteSelected();
1569 pTableView
->InsertText( aIns
, false );
1570 pTableView
->SetSelection( ESelection(
1571 aSel
.nEndPara
, aSel
.nStartPos
+ aIns
.getLength(),
1572 aSel
.nEndPara
, aSel
.nStartPos
) );
1576 pTopView
->DeleteSelected();
1577 pTopView
->InsertText( aIns
, false );
1578 pTopView
->SetSelection( ESelection(
1579 aSel
.nEndPara
, aSel
.nStartPos
+ aIns
.getLength(),
1580 aSel
.nEndPara
, aSel
.nStartPos
) );
1583 bInOwnChange
= false;
1590 // For Tab, HideCursor was always called first
1592 pActiveView
->ShowCursor();
1595 // Highlight parentheses
1596 void ScInputHandler::UpdateParenthesis()
1599 //TODO: Can we disable parentheses highlighting per parentheses?
1600 bool bFound
= false;
1601 if ( bFormulaMode
&& eMode
!= SC_INPUT_TOP
)
1603 if ( pTableView
&& !pTableView
->HasSelection() ) // Selection is always at the bottom
1605 ESelection aSel
= pTableView
->GetSelection();
1608 // Examine character left to the cursor
1609 sal_Int32 nPos
= aSel
.nStartPos
- 1;
1610 OUString aFormula
= pEngine
->GetText(0);
1611 sal_Unicode c
= aFormula
[nPos
];
1612 if ( c
== '(' || c
== ')' )
1614 sal_Int32 nOther
= lcl_MatchParenthesis( aFormula
, nPos
);
1617 SfxItemSet
aSet( pEngine
->GetEmptyItemSet() );
1618 aSet
.Put( SvxWeightItem( WEIGHT_BOLD
, EE_CHAR_WEIGHT
) );
1620 //! Distinguish if cell is already highlighted!!!!
1621 if (bParenthesisShown
)
1623 // Remove old highlighting
1624 sal_Int32 nCount
= pEngine
->GetParagraphCount();
1625 for (sal_Int32 i
=0; i
<nCount
; i
++)
1626 pEngine
->RemoveCharAttribs( i
, EE_CHAR_WEIGHT
);
1629 ESelection
aSelThis( 0,nPos
, 0,nPos
+1 );
1630 pEngine
->QuickSetAttribs( aSet
, aSelThis
);
1631 ESelection
aSelOther( 0,nOther
, 0,nOther
+1 );
1632 pEngine
->QuickSetAttribs( aSet
, aSelOther
);
1634 // Dummy InsertText for Update and Paint (selection is empty)
1635 pTableView
->InsertText( EMPTY_OUSTRING
, false );
1642 // mark parenthesis right of cursor if it will be overwritten (nAutoPar)
1643 // with different color (COL_LIGHTBLUE) ??
1647 // Remove old highlighting, if no new one is set
1648 if ( bParenthesisShown
&& !bFound
&& pTableView
)
1650 sal_Int32 nCount
= pEngine
->GetParagraphCount();
1651 for (sal_Int32 i
=0; i
<nCount
; i
++)
1652 pTableView
->RemoveCharAttribs( i
, EE_CHAR_WEIGHT
);
1655 bParenthesisShown
= bFound
;
1658 void ScInputHandler::ViewShellGone(ScTabViewShell
* pViewSh
) // Executed synchronously!
1660 if ( pViewSh
== pActiveViewSh
)
1664 pLastPattern
= NULL
;
1667 if ( pViewSh
== pRefViewSh
)
1669 //! The input from the EnterHandler does not arrive anymore
1670 // We end the EditMode anyways
1672 bFormulaMode
= false;
1674 SfxGetpApp()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
1675 SC_MOD()->SetRefInputHdl(NULL
);
1677 pInputWin
->SetFormulaMode(false);
1678 UpdateAutoCorrFlag();
1681 pActiveViewSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
1683 if ( pActiveViewSh
&& pActiveViewSh
== pViewSh
)
1685 OSL_FAIL("pActiveViewSh is gone");
1686 pActiveViewSh
= NULL
;
1689 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
1690 UpdateRefDevice(); // Don't keep old document's printer as RefDevice
1693 void ScInputHandler::UpdateActiveView()
1695 ImplCreateEditEngine();
1697 // #i20588# Don't rely on focus to find the active edit view. Instead, the
1698 // active pane at the start of editing is now stored (GetEditActivePart).
1699 // GetActiveWin (the currently active pane) fails for ref input across the
1700 // panes of a split view.
1702 vcl::Window
* pShellWin
= pActiveViewSh
?
1703 pActiveViewSh
->GetWindowByPos( pActiveViewSh
->GetViewData().GetEditActivePart() ) :
1706 sal_uInt16 nCount
= pEngine
->GetViewCount();
1709 pTableView
= pEngine
->GetView(0);
1710 for (sal_uInt16 i
=1; i
<nCount
; i
++)
1712 EditView
* pThis
= pEngine
->GetView(i
);
1713 vcl::Window
* pWin
= pThis
->GetWindow();
1714 if ( pWin
==pShellWin
)
1721 // setup the pTableView editeng for tiled rendering to get cursor and selections
1722 if (pActiveViewSh
&& pTableView
)
1724 ScDocShell
* pDocShell
= pActiveViewSh
->GetViewData().GetDocShell();
1725 ScDocument
& rDoc
= pDocShell
->GetDocument();
1726 if (rDoc
.GetDrawLayer()->isTiledRendering())
1728 ScDrawLayer
*pDrawLayer
= pDocShell
->GetDocument().GetDrawLayer();
1729 pTableView
->registerLibreOfficeKitCallback(pDrawLayer
->getLibreOfficeKitCallback(), pDrawLayer
->getLibreOfficeKitData());
1730 pTableView
->setTiledRendering(true);
1734 if (pInputWin
&& eMode
== SC_INPUT_TOP
)
1735 pTopView
= pInputWin
->GetEditView();
1740 void ScInputHandler::SetInputWindow( ScInputWindow
* pNew
)
1745 void ScInputHandler::StopInputWinEngine( bool bAll
)
1748 pInputWin
->StopEditEngine( bAll
);
1750 pTopView
= NULL
; // invalid now
1753 EditView
* ScInputHandler::GetActiveView()
1756 return pTopView
? pTopView
: pTableView
;
1759 void ScInputHandler::ForgetLastPattern()
1761 pLastPattern
= NULL
;
1762 if ( !pLastState
&& pActiveViewSh
)
1763 pActiveViewSh
->UpdateInputHandler( true ); // Get status again
1765 NotifyChange( pLastState
, true );
1768 void ScInputHandler::UpdateAdjust( sal_Unicode cTyped
)
1770 SvxAdjust eSvxAdjust
;
1771 switch (eAttrAdjust
)
1773 case SVX_HOR_JUSTIFY_STANDARD
:
1775 bool bNumber
= false;
1776 if (cTyped
) // Restarted
1777 bNumber
= (cTyped
>='0' && cTyped
<='9'); // Ony ciphers are numbers
1778 else if ( pActiveViewSh
)
1780 ScDocument
& rDoc
= pActiveViewSh
->GetViewData().GetDocShell()->GetDocument();
1781 bNumber
= ( rDoc
.GetCellType( aCursorPos
) == CELLTYPE_VALUE
);
1783 eSvxAdjust
= bNumber
? SVX_ADJUST_RIGHT
: SVX_ADJUST_LEFT
;
1786 case SVX_HOR_JUSTIFY_BLOCK
:
1787 eSvxAdjust
= SVX_ADJUST_BLOCK
;
1789 case SVX_HOR_JUSTIFY_CENTER
:
1790 eSvxAdjust
= SVX_ADJUST_CENTER
;
1792 case SVX_HOR_JUSTIFY_RIGHT
:
1793 eSvxAdjust
= SVX_ADJUST_RIGHT
;
1795 default: // SVX_HOR_JUSTIFY_LEFT
1796 eSvxAdjust
= SVX_ADJUST_LEFT
;
1800 bool bAsianVertical
= pLastPattern
&&
1801 static_cast<const SfxBoolItem
&>(pLastPattern
->GetItem( ATTR_STACKED
)).GetValue() &&
1802 static_cast<const SfxBoolItem
&>(pLastPattern
->GetItem( ATTR_VERTICAL_ASIAN
)).GetValue();
1803 if ( bAsianVertical
)
1805 // Always edit at top of cell -> LEFT when editing vertically
1806 eSvxAdjust
= SVX_ADJUST_LEFT
;
1809 pEditDefaults
->Put( SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
1810 pEngine
->SetDefaults( *pEditDefaults
);
1812 nEditAdjust
= sal::static_int_cast
<sal_uInt16
>(eSvxAdjust
); //! set at ViewData or with PostEditView
1814 pEngine
->SetVertical( bAsianVertical
);
1817 void ScInputHandler::RemoveAdjust()
1819 // Delete hard alignement attributes
1820 bool bUndo
= pEngine
->IsUndoEnabled();
1822 pEngine
->EnableUndo( false );
1824 // Non-default paragraph attributes (e.g. from clipboard)
1825 // must be turned into character attributes
1826 pEngine
->RemoveParaAttribs();
1829 pEngine
->EnableUndo( true );
1833 void ScInputHandler::RemoveRangeFinder()
1835 // Delete pRangeFindList and colors
1836 pEngine
->SetUpdateMode(false);
1837 sal_Int32 nCount
= pEngine
->GetParagraphCount(); // Could just have been inserted
1838 for (sal_Int32 i
=0; i
<nCount
; i
++)
1839 pEngine
->RemoveCharAttribs( i
, EE_CHAR_COLOR
);
1840 pEngine
->SetUpdateMode(true);
1842 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1843 pActiveView
->ShowCursor( false, true );
1845 DeleteRangeFinder(); // Deletes the list and the labels on the table
1848 bool ScInputHandler::StartTable( sal_Unicode cTyped
, bool bFromCommand
, bool bInputActivated
)
1850 bool bNewTable
= false;
1852 if (bModified
|| !ValidCol(aCursorPos
.Col()))
1857 ImplCreateEditEngine();
1861 ScDocument
& rDoc
= pActiveViewSh
->GetViewData().GetDocShell()->GetDocument();
1863 const ScMarkData
& rMark
= pActiveViewSh
->GetViewData().GetMarkData();
1864 ScEditableTester aTester
;
1865 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
1866 aTester
.TestSelection( &rDoc
, rMark
);
1868 aTester
.TestSelectedBlock(
1869 &rDoc
, aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Col(), aCursorPos
.Row(), rMark
);
1871 bool bStartInputMode
= true;
1873 if (!aTester
.IsEditable())
1876 // We allow read-only input mode activation regardless
1877 // whether it's part of an array or not or whether explicit cell
1878 // activation is requested (double-click or F2) or a click in input
1880 bool bShowError
= (!bInputActivated
|| aTester
.GetMessageId() != STR_PROTECTIONERR
) &&
1881 !pActiveViewSh
->GetViewData().GetDocShell()->IsReadOnly();
1884 eMode
= SC_INPUT_NONE
;
1885 StopInputWinEngine( true );
1886 UpdateFormulaMode();
1887 if ( pActiveViewSh
&& ( !bFromCommand
|| !bCommandErrorShown
) )
1889 // Prevent repeated error messages for the same cell from command events
1890 // (for keyboard events, multiple messages are wanted).
1891 // Set the flag before showing the error message because the command handler
1892 // for the next IME command may be called when showing the dialog.
1894 bCommandErrorShown
= true;
1896 pActiveViewSh
->GetActiveWin()->GrabFocus();
1897 pActiveViewSh
->ErrorMessage(aTester
.GetMessageId());
1899 bStartInputMode
= false;
1903 if (bStartInputMode
)
1905 // UpdateMode is enabled again in ScViewData::SetEditEngine (and not needed otherwise)
1906 pEngine
->SetUpdateMode( false );
1908 // Take over attributes in EditEngine
1909 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( aCursorPos
.Col(),
1912 if (pPattern
!= pLastPattern
)
1915 const SfxItemSet
& rAttrSet
= pPattern
->GetItemSet();
1916 const SfxPoolItem
* pItem
;
1918 if ( SfxItemState::SET
== rAttrSet
.GetItemState( ATTR_VALUE_FORMAT
, true, &pItem
) )
1920 sal_uLong nFormat
= static_cast<const SfxUInt32Item
*>(pItem
)->GetValue();
1921 bCellHasPercentFormat
= ( css::util::NumberFormat::PERCENT
==
1922 rDoc
.GetFormatTable()->GetType( nFormat
) );
1925 bCellHasPercentFormat
= false; // Default: no percent
1927 // Validity specified?
1928 if ( SfxItemState::SET
== rAttrSet
.GetItemState( ATTR_VALIDDATA
, true, &pItem
) )
1929 nValidation
= static_cast<const SfxUInt32Item
*>(pItem
)->GetValue();
1933 // EditEngine Defaults
1934 // In no case SetParaAttribs, because the EditEngine might already
1935 // be filled (for Edit cells).
1936 // SetParaAttribs would change the content.
1938 //! The SetDefaults is now (since MUST/src602
1939 //! EditEngine changes) implemented as a SetParaAttribs.
1942 pPattern
->FillEditItemSet( pEditDefaults
);
1943 pEngine
->SetDefaults( *pEditDefaults
);
1944 pLastPattern
= pPattern
;
1945 bLastIsSymbol
= pPattern
->IsSymbolFont();
1947 // Background color must be known for automatic font color.
1948 // For transparent cell background, the document background color must be used.
1950 Color aBackCol
= static_cast<const SvxBrushItem
&>(
1951 pPattern
->GetItem( ATTR_BACKGROUND
)).GetColor();
1952 ScModule
* pScMod
= SC_MOD();
1953 if ( aBackCol
.GetTransparency() > 0 ||
1954 Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1955 aBackCol
.SetColor( pScMod
->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
1956 pEngine
->SetBackgroundColor( aBackCol
);
1959 eAttrAdjust
= (SvxCellHorJustify
)static_cast<const SvxHorJustifyItem
&>(pPattern
->
1960 GetItem(ATTR_HOR_JUSTIFY
)).GetValue();
1961 if ( eAttrAdjust
== SVX_HOR_JUSTIFY_REPEAT
&&
1962 static_cast<const SfxBoolItem
&>(pPattern
->GetItem(ATTR_LINEBREAK
)).GetValue() )
1964 // #i31843# "repeat" with "line breaks" is treated as default alignement
1965 eAttrAdjust
= SVX_HOR_JUSTIFY_STANDARD
;
1969 // UpdateSpellSettings enables online spelling if needed
1970 // -> also call if attributes are unchanged
1971 UpdateSpellSettings( true ); // uses pLastPattern
1977 pEngine
->SetText(aCurrentText
);
1978 aStr
= aCurrentText
;
1980 aCurrentText
.clear();
1983 aStr
= GetEditText(pEngine
);
1985 if (aStr
.startsWith("{=") && aStr
.endsWith("}") ) // Matrix formula?
1987 aStr
= aStr
.copy(1, aStr
.getLength() -2);
1988 pEngine
->SetText(aStr
);
1990 pInputWin
->SetTextString(aStr
);
1993 UpdateAdjust( cTyped
);
1995 if ( bAutoComplete
)
1998 if ( !aStr
.isEmpty() && ( aStr
[0] == '=' || aStr
[0] == '+' || aStr
[0] == '-' ) &&
1999 !cTyped
&& !bCreatingFuncView
)
2000 InitRangeFinder(aStr
); // Formula is being edited -> RangeFinder
2002 bNewTable
= true; // -> PostEditView Call
2006 if (!bProtected
&& pInputWin
)
2007 pInputWin
->SetOkCancelMode();
2012 static void lcl_SetTopSelection( EditView
* pEditView
, ESelection
& rSel
)
2014 OSL_ENSURE( rSel
.nStartPara
==0 && rSel
.nEndPara
==0, "SetTopSelection: Para != 0" );
2016 EditEngine
* pEngine
= pEditView
->GetEditEngine();
2017 sal_Int32 nCount
= pEngine
->GetParagraphCount();
2020 sal_Int32 nParLen
= pEngine
->GetTextLen(rSel
.nStartPara
);
2021 while (rSel
.nStartPos
> nParLen
&& rSel
.nStartPara
+1 < nCount
)
2023 rSel
.nStartPos
-= nParLen
+ 1; // Including space from line break
2024 nParLen
= pEngine
->GetTextLen(++rSel
.nStartPara
);
2027 nParLen
= pEngine
->GetTextLen(rSel
.nEndPara
);
2028 while (rSel
.nEndPos
> nParLen
&& rSel
.nEndPara
+1 < nCount
)
2030 rSel
.nEndPos
-= nParLen
+ 1; // Including space from line break
2031 nParLen
= pEngine
->GetTextLen(++rSel
.nEndPara
);
2035 ESelection aSel
= pEditView
->GetSelection();
2037 if ( rSel
.nStartPara
!= aSel
.nStartPara
|| rSel
.nEndPara
!= aSel
.nEndPara
2038 || rSel
.nStartPos
!= aSel
.nStartPos
|| rSel
.nEndPos
!= aSel
.nEndPos
)
2039 pEditView
->SetSelection( rSel
);
2042 void ScInputHandler::SyncViews( EditView
* pSourceView
)
2046 bool bSelectionForTopView
= false;
2047 if (pTopView
&& pTopView
!= pSourceView
)
2048 bSelectionForTopView
= true;
2049 bool bSelectionForTableView
= false;
2050 if (pTableView
&& pTableView
!= pSourceView
)
2051 bSelectionForTableView
= true;
2052 if (bSelectionForTopView
|| bSelectionForTableView
)
2054 ESelection
aSel(pSourceView
->GetSelection());
2055 if (bSelectionForTopView
)
2056 pTopView
->SetSelection(aSel
);
2057 if (bSelectionForTableView
)
2058 lcl_SetTopSelection(pTableView
, aSel
);
2061 // Only sync selection from topView if we are actually editiing there
2062 else if (pTopView
&& pTableView
)
2064 ESelection
aSel(pTopView
->GetSelection());
2065 lcl_SetTopSelection( pTableView
, aSel
);
2069 IMPL_LINK_NOARG(ScInputHandler
, ModifyHdl
)
2071 if ( !bInOwnChange
&& ( eMode
==SC_INPUT_TYPE
|| eMode
==SC_INPUT_TABLE
) &&
2072 pEngine
&& pEngine
->GetUpdateMode() && pInputWin
)
2074 // Update input line from ModifyHdl for changes that are not
2075 // wrapped by DataChanging/DataChanged calls (like Drag&Drop)
2077 if ( pInputWin
->IsMultiLineInput() )
2078 aText
= ScEditUtil::GetMultilineString(*pEngine
);
2080 aText
= GetEditText(pEngine
);
2081 lcl_RemoveTabs(aText
);
2082 pInputWin
->SetTextString(aText
);
2088 * @return true means new view created
2090 bool ScInputHandler::DataChanging( sal_Unicode cTyped
, bool bFromCommand
)
2093 pActiveViewSh
->GetViewData().SetPasteMode( SC_PASTE_NONE
);
2094 bInOwnChange
= true; // disable ModifyHdl (reset in DataChanged)
2096 if ( eMode
== SC_INPUT_NONE
)
2097 return StartTable( cTyped
, bFromCommand
, false );
2102 void ScInputHandler::DataChanged( bool bFromTopNotify
, bool bSetModified
)
2104 ImplCreateEditEngine();
2106 if (eMode
==SC_INPUT_NONE
)
2107 eMode
= SC_INPUT_TYPE
;
2109 if ( eMode
== SC_INPUT_TOP
&& pTopView
&& !bFromTopNotify
)
2111 // table EditEngine is formatted below, input line needs formatting after paste
2112 // #i20282# not when called from the input line's modify handler
2113 pTopView
->GetEditEngine()->QuickFormatDoc( true );
2115 // #i23720# QuickFormatDoc hides the cursor, but can't show it again because it
2116 // can't safely access the EditEngine's current view, so the cursor has to be
2117 // shown again here.
2118 pTopView
->ShowCursor();
2125 if ( pRangeFindList
&& !bInRangeUpdate
)
2126 RemoveRangeFinder(); // Delete attributes and labels
2128 UpdateParenthesis(); // Highlight parentheses anew
2130 if (eMode
==SC_INPUT_TYPE
|| eMode
==SC_INPUT_TABLE
)
2133 if ( pInputWin
&& pInputWin
->IsMultiLineInput() )
2134 aText
= ScEditUtil::GetMultilineString(*pEngine
);
2136 aText
= GetEditText(pEngine
);
2137 lcl_RemoveTabs(aText
);
2140 pInputWin
->SetTextString( aText
);
2143 // If the cursor is before the end of a paragraph, parts are being pushed to
2144 // the right (independently from the eMode) -> Adapt View!
2145 // If the cursor is at the end, the StatusHandler of the ViewData is sufficient.
2147 // First make sure the status handler is called now if the cursor
2148 // is outside the visible area
2149 pEngine
->QuickFormatDoc();
2151 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2152 if (pActiveView
&& pActiveViewSh
)
2154 ScViewData
& rViewData
= pActiveViewSh
->GetViewData();
2156 bool bNeedGrow
= ( nEditAdjust
!= SVX_ADJUST_LEFT
); // Always right-aligned
2159 // Cursor before the end?
2160 ESelection aSel
= pActiveView
->GetSelection();
2162 bNeedGrow
= ( aSel
.nEndPos
!= pEngine
->GetTextLen(aSel
.nEndPara
) );
2166 bNeedGrow
= rViewData
.GetDocument()->IsLayoutRTL( rViewData
.GetTabNo() );
2170 // Adjust inplace view
2171 rViewData
.EditGrowY();
2172 rViewData
.EditGrowX();
2176 UpdateFormulaMode();
2177 bTextValid
= false; // Changes only in the EditEngine
2178 bInOwnChange
= false;
2181 void ScInputHandler::UpdateFormulaMode()
2183 SfxApplication
* pSfxApp
= SfxGetpApp();
2185 bool bIsFormula
= !bProtected
&& pEngine
->GetParagraphCount() == 1;
2188 const OUString
& rText
= pEngine
->GetText(0);
2189 bIsFormula
= !rText
.isEmpty() &&
2190 (rText
[0] == '=' || rText
[0] == '+' || rText
[0] == '-');
2197 bFormulaMode
= true;
2198 pRefViewSh
= pActiveViewSh
;
2199 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2200 SC_MOD()->SetRefInputHdl(this);
2202 pInputWin
->SetFormulaMode(true);
2204 if ( bAutoComplete
)
2207 UpdateParenthesis();
2208 UpdateAutoCorrFlag();
2216 bFormulaMode
= false;
2218 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2219 SC_MOD()->SetRefInputHdl(NULL
);
2221 pInputWin
->SetFormulaMode(false);
2222 UpdateAutoCorrFlag();
2227 void ScInputHandler::ShowRefFrame()
2229 // Modifying pActiveViewSh here would interfere with the bInEnterHandler / bRepeat
2230 // checks in NotifyChange, and lead to keeping the wrong value in pActiveViewSh.
2231 // A local variable is used instead.
2232 ScTabViewShell
* pVisibleSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
2233 if ( pRefViewSh
&& pRefViewSh
!= pVisibleSh
)
2235 bool bFound
= false;
2236 SfxViewFrame
* pRefFrame
= pRefViewSh
->GetViewFrame();
2237 SfxViewFrame
* pOneFrame
= SfxViewFrame::GetFirst();
2238 while ( pOneFrame
&& !bFound
)
2240 if ( pOneFrame
== pRefFrame
)
2242 pOneFrame
= SfxViewFrame::GetNext( *pOneFrame
);
2247 // We count on Activate working synchronously here
2248 // (pActiveViewSh is set while doing so)
2249 pRefViewSh
->SetActive(); // Appear and SetViewFrame
2251 // pLastState is set correctly in the NotifyChange from the Activate
2255 OSL_FAIL("ViewFrame for reference input is not here anymore");
2260 void ScInputHandler::RemoveSelection()
2262 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2266 ESelection aSel
= pActiveView
->GetSelection();
2267 aSel
.nStartPara
= aSel
.nEndPara
;
2268 aSel
.nStartPos
= aSel
.nEndPos
;
2270 pTableView
->SetSelection( aSel
);
2272 pTopView
->SetSelection( aSel
);
2275 void ScInputHandler::InvalidateAttribs()
2277 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
2280 SfxBindings
& rBindings
= pViewFrm
->GetBindings();
2282 rBindings
.Invalidate( SID_ATTR_CHAR_FONT
);
2283 rBindings
.Invalidate( SID_ATTR_CHAR_FONTHEIGHT
);
2284 rBindings
.Invalidate( SID_ATTR_CHAR_COLOR
);
2286 rBindings
.Invalidate( SID_ATTR_CHAR_WEIGHT
);
2287 rBindings
.Invalidate( SID_ATTR_CHAR_POSTURE
);
2288 rBindings
.Invalidate( SID_ATTR_CHAR_UNDERLINE
);
2289 rBindings
.Invalidate( SID_ULINE_VAL_NONE
);
2290 rBindings
.Invalidate( SID_ULINE_VAL_SINGLE
);
2291 rBindings
.Invalidate( SID_ULINE_VAL_DOUBLE
);
2292 rBindings
.Invalidate( SID_ULINE_VAL_DOTTED
);
2294 rBindings
.Invalidate( SID_HYPERLINK_GETLINK
);
2296 rBindings
.Invalidate( SID_ATTR_CHAR_KERNING
);
2297 rBindings
.Invalidate( SID_SET_SUPER_SCRIPT
);
2298 rBindings
.Invalidate( SID_SET_SUB_SCRIPT
);
2299 rBindings
.Invalidate( SID_ATTR_CHAR_STRIKEOUT
);
2300 rBindings
.Invalidate( SID_ATTR_CHAR_SHADOWED
);
2304 // --------------- public methods --------------------------------------------
2306 void ScInputHandler::SetMode( ScInputMode eNewMode
, const OUString
* pInitText
)
2308 if ( eMode
== eNewMode
)
2311 ImplCreateEditEngine();
2315 eMode
= SC_INPUT_NONE
;
2316 StopInputWinEngine( true );
2318 pActiveViewSh
->GetActiveWin()->GrabFocus();
2322 if (eNewMode
!= SC_INPUT_NONE
&& pActiveViewSh
)
2323 // Disable paste mode when edit mode starts.
2324 pActiveViewSh
->GetViewData().SetPasteMode( SC_PASTE_NONE
);
2326 bInOwnChange
= true; // disable ModifyHdl (reset below)
2328 ScInputMode eOldMode
= eMode
;
2330 if (eOldMode
== SC_INPUT_TOP
&& eNewMode
!= eOldMode
)
2331 StopInputWinEngine( false );
2333 if (eMode
==SC_INPUT_TOP
|| eMode
==SC_INPUT_TABLE
)
2335 if (eOldMode
== SC_INPUT_NONE
) // not if switching between modes
2337 if (StartTable(0, false, eMode
== SC_INPUT_TABLE
))
2340 pActiveViewSh
->GetViewData().GetDocShell()->PostEditView( pEngine
, aCursorPos
);
2346 pEngine
->SetText(*pInitText
);
2350 sal_Int32 nPara
= pEngine
->GetParagraphCount()-1;
2351 sal_Int32 nLen
= pEngine
->GetText(nPara
).getLength();
2352 sal_uInt16 nCount
= pEngine
->GetViewCount();
2354 for (sal_uInt16 i
=0; i
<nCount
; i
++)
2356 if ( eMode
== SC_INPUT_TABLE
&& eOldMode
== SC_INPUT_TOP
)
2362 pEngine
->GetView(i
)->
2363 SetSelection( ESelection( nPara
, nLen
, nPara
, nLen
) );
2365 pEngine
->GetView(i
)->ShowCursor(false);
2370 if (eMode
==SC_INPUT_TABLE
|| eMode
==SC_INPUT_TYPE
)
2373 pTableView
->SetEditEngineUpdateMode(true);
2378 pTopView
->SetEditEngineUpdateMode(true);
2381 if (eNewMode
!= eOldMode
)
2382 UpdateFormulaMode();
2384 bInOwnChange
= false;
2388 * @return true if rString only contains digits (no autocorrect then)
2390 static bool lcl_IsNumber(const OUString
& rString
)
2392 sal_Int32 nLen
= rString
.getLength();
2393 for (sal_Int32 i
=0; i
<nLen
; i
++)
2395 sal_Unicode c
= rString
[i
];
2396 if ( c
< '0' || c
> '9' )
2402 static void lcl_SelectionToEnd( EditView
* pView
)
2406 EditEngine
* pEngine
= pView
->GetEditEngine();
2407 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
2410 ESelection
aSel( nParCnt
-1, pEngine
->GetTextLen(nParCnt
-1) ); // empty selection, cursor at the end
2411 pView
->SetSelection( aSel
);
2415 void ScInputHandler::EnterHandler( sal_uInt8 nBlockMode
)
2417 // Macro calls for validity can cause a lot of problems, so inhibit
2418 // nested calls of EnterHandler().
2419 if (bInEnterHandler
) return;
2420 bInEnterHandler
= true;
2421 bInOwnChange
= true; // disable ModifyHdl (reset below)
2423 ImplCreateEditEngine();
2425 bool bMatrix
= ( nBlockMode
== SC_ENTER_MATRIX
);
2427 SfxApplication
* pSfxApp
= SfxGetpApp();
2428 EditTextObject
* pObject
= NULL
;
2429 ScPatternAttr
* pCellAttrs
= NULL
;
2430 bool bForget
= false; // Remove due to validity?
2432 OUString aString
= GetEditText(pEngine
);
2433 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2434 if (bModified
&& pActiveView
&& !aString
.isEmpty() && !lcl_IsNumber(aString
))
2436 if (pColumnData
&& miAutoPosColumn
!= pColumnData
->end())
2438 // #i47125# If AutoInput appended something, do the final AutoCorrect
2439 // with the cursor at the end of the input.
2440 lcl_SelectionToEnd(pTopView
);
2441 lcl_SelectionToEnd(pTableView
);
2444 vcl::Window
* pFrameWin
= pActiveViewSh
? pActiveViewSh
->GetFrameWin() : NULL
;
2447 pTopView
->CompleteAutoCorrect(); // CompleteAutoCorrect for both Views
2449 pTableView
->CompleteAutoCorrect(pFrameWin
);
2450 aString
= GetEditText(pEngine
);
2452 lcl_RemoveTabs(aString
);
2454 // Test if valid (always with simple string)
2455 if ( bModified
&& nValidation
&& pActiveViewSh
)
2457 ScDocument
* pDoc
= pActiveViewSh
->GetViewData().GetDocument();
2458 const ScValidationData
* pData
= pDoc
->GetValidationEntry( nValidation
);
2459 if (pData
&& pData
->HasErrMsg())
2461 // #i67990# don't use pLastPattern in EnterHandler
2462 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2463 bool bOk
= pData
->IsDataValid( aString
, *pPattern
, aCursorPos
);
2467 if ( pActiveViewSh
) // If it came from MouseButtonDown
2468 pActiveViewSh
->StopMarking(); // (the InfoBox consumes the MouseButtonUp)
2470 //FIXME: We still run into problems if the input is triggered by activating another View
2471 vcl::Window
* pParent
= Application::GetDefDialogParent();
2472 if ( pData
->DoError( pParent
, aString
, aCursorPos
) )
2473 bForget
= true; // Do not take over input
2478 // Check for input into DataPilot table
2479 if ( bModified
&& pActiveViewSh
&& !bForget
)
2481 ScDocument
* pDoc
= pActiveViewSh
->GetViewData().GetDocument();
2482 ScDPObject
* pDPObj
= pDoc
->GetDPAtCursor( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2485 // Any input within the DataPilot table is either a valid renaming
2486 // or an invalid action - normal cell input is always aborted
2487 pActiveViewSh
->DataPilotInput( aCursorPos
, aString
);
2492 std::vector
<editeng::MisspellRanges
> aMisspellRanges
;
2493 pEngine
->CompleteOnlineSpelling();
2494 bool bSpellErrors
= !bFormulaMode
&& pEngine
->HasOnlineSpellErrors();
2497 // #i3820# If the spell checker flags numerical input as error,
2498 // it still has to be treated as number, not EditEngine object.
2499 if ( pActiveViewSh
)
2501 ScDocument
* pDoc
= pActiveViewSh
->GetViewData().GetDocument();
2502 // #i67990# don't use pLastPattern in EnterHandler
2503 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2506 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
2507 // without conditional format, as in ScColumn::SetString
2508 sal_uInt32 nFormat
= pPattern
->GetNumberFormat( pFormatter
);
2510 if ( pFormatter
->IsNumberFormat( aString
, nFormat
, nVal
) )
2512 bSpellErrors
= false; // ignore the spelling errors
2518 // After RemoveAdjust, the EditView must not be repainted (has wrong font size etc).
2519 // SetUpdateMode must come after CompleteOnlineSpelling.
2520 // The view is hidden in any case below (Broadcast).
2521 pEngine
->SetUpdateMode( false );
2523 if ( bModified
&& !bForget
) // What is being entered (text/object)?
2525 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
2529 bool bUniformAttribs
= true;
2530 SfxItemSet aPara1Attribs
= pEngine
->GetAttribs(0, 0, pEngine
->GetTextLen(0));
2531 for (sal_Int32 nPara
= 1; nPara
< nParCnt
; ++nPara
)
2533 SfxItemSet aPara2Attribs
= pEngine
->GetAttribs(nPara
, 0, pEngine
->GetTextLen(nPara
));
2534 if (!(aPara1Attribs
== aPara2Attribs
))
2536 // Paragraph format different from that of the 1st paragraph.
2537 bUniformAttribs
= false;
2542 ESelection
aSel( 0, 0, nParCnt
-1, pEngine
->GetTextLen(nParCnt
-1) );
2543 SfxItemSet aOldAttribs
= pEngine
->GetAttribs( aSel
);
2544 const SfxPoolItem
* pItem
= NULL
;
2546 // Find common (cell) attributes before RemoveAdjust
2547 if ( pActiveViewSh
&& bUniformAttribs
)
2549 SfxItemSet
* pCommonAttrs
= NULL
;
2550 for (sal_uInt16 nId
= EE_CHAR_START
; nId
<= EE_CHAR_END
; nId
++)
2552 SfxItemState eState
= aOldAttribs
.GetItemState( nId
, false, &pItem
);
2553 if ( eState
== SfxItemState::SET
&&
2554 nId
!= EE_CHAR_ESCAPEMENT
&& nId
!= EE_CHAR_PAIRKERNING
&&
2555 nId
!= EE_CHAR_KERNING
&& nId
!= EE_CHAR_XMLATTRIBS
&&
2556 *pItem
!= pEditDefaults
->Get(nId
) )
2558 if ( !pCommonAttrs
)
2559 pCommonAttrs
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
2560 pCommonAttrs
->Put( *pItem
);
2566 ScDocument
* pDoc
= pActiveViewSh
->GetViewData().GetDocument();
2567 pCellAttrs
= new ScPatternAttr( pDoc
->GetPool() );
2568 pCellAttrs
->GetFromEditItemSet( pCommonAttrs
);
2569 delete pCommonAttrs
;
2573 // Clear ParaAttribs (including adjustment)
2576 bool bAttrib
= false; // Formatting present?
2578 // check if EditObject is needed
2583 for (sal_uInt16 nId
= EE_CHAR_START
; nId
<= EE_CHAR_END
&& !bAttrib
; nId
++)
2585 SfxItemState eState
= aOldAttribs
.GetItemState( nId
, false, &pItem
);
2586 if (eState
== SfxItemState::DONTCARE
)
2588 else if (eState
== SfxItemState::SET
)
2590 // Keep same items in EditEngine as in ScEditAttrTester
2591 if ( nId
== EE_CHAR_ESCAPEMENT
|| nId
== EE_CHAR_PAIRKERNING
||
2592 nId
== EE_CHAR_KERNING
|| nId
== EE_CHAR_XMLATTRIBS
)
2594 if ( *pItem
!= pEditDefaults
->Get(nId
) )
2601 SfxItemState eFieldState
= aOldAttribs
.GetItemState( EE_FEATURE_FIELD
, false );
2602 if ( eFieldState
== SfxItemState::DONTCARE
|| eFieldState
== SfxItemState::SET
)
2605 // Not converted characters?
2606 SfxItemState eConvState
= aOldAttribs
.GetItemState( EE_FEATURE_NOTCONV
, false );
2607 if ( eConvState
== SfxItemState::DONTCARE
|| eConvState
== SfxItemState::SET
)
2610 // Always recognize formulas as formulas
2611 // We still need the preceding test due to cell attributes
2615 pEngine
->GetAllMisspellRanges(aMisspellRanges
);
2622 pEngine
->ClearSpellErrors();
2623 pObject
= pEngine
->CreateTextObject();
2625 else if (bAutoComplete
) // Adjust Upper/Lower case
2627 // Perform case-matching only when the typed text is partial.
2628 if (pColumnData
&& aAutoSearch
.getLength() < aString
.getLength())
2629 aString
= getExactMatch(*pColumnData
, aString
);
2633 // Don't rely on ShowRefFrame switching the active view synchronously
2634 // execute the function directly on the correct view's bindings instead
2635 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2636 ScTabViewShell
* pExecuteSh
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
2644 pExecuteSh
->SetTabNo(aCursorPos
.Tab());
2645 pExecuteSh
->ActiveGrabFocus();
2648 bFormulaMode
= false;
2649 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2650 SC_MOD()->SetRefInputHdl(NULL
);
2652 pInputWin
->SetFormulaMode(false);
2653 UpdateAutoCorrFlag();
2655 pRefViewSh
= NULL
; // Also without FormulaMode due to FunctionsAutoPilot
2656 DeleteRangeFinder();
2659 bool bOldMod
= bModified
;
2663 eMode
= SC_INPUT_NONE
;
2664 StopInputWinEngine(true);
2666 // Text input (through number formats) or ApplySelectionPattern modify
2667 // the cell's attributes, so pLastPattern is no longer valid
2668 pLastPattern
= NULL
;
2670 if (bOldMod
&& !bProtected
&& !bForget
)
2672 // No typographic quotes in formulas
2673 if (aString
.startsWith("="))
2675 SvxAutoCorrect
* pAuto
= SvxAutoCorrCfg::Get().GetAutoCorrect();
2678 OUString
aReplace(pAuto
->GetStartDoubleQuote());
2679 if( aReplace
.isEmpty() )
2680 aReplace
= ScGlobal::pLocaleData
->getDoubleQuotationMarkStart();
2681 if( aReplace
!= "\"" )
2682 aString
= aString
.replaceAll( aReplace
, "\"" );
2684 aReplace
= OUString(pAuto
->GetEndDoubleQuote());
2685 if( aReplace
.isEmpty() )
2686 aReplace
= ScGlobal::pLocaleData
->getDoubleQuotationMarkEnd();
2687 if( aReplace
!= "\"" )
2688 aString
= aString
.replaceAll( aReplace
, "\"" );
2690 aReplace
= OUString(pAuto
->GetStartSingleQuote());
2691 if( aReplace
.isEmpty() )
2692 aReplace
= ScGlobal::pLocaleData
->getQuotationMarkStart();
2693 if( aReplace
!= "'" )
2694 aString
= aString
.replaceAll( aReplace
, "'" );
2696 aReplace
= OUString(pAuto
->GetEndSingleQuote());
2697 if( aReplace
.isEmpty() )
2698 aReplace
= ScGlobal::pLocaleData
->getQuotationMarkEnd();
2699 if( aReplace
!= "'" )
2700 aString
= aString
.replaceAll( aReplace
, "'");
2704 pSfxApp
->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW_NOPAINT
) );
2708 SfxBindings
& rBindings
= pExecuteSh
->GetViewFrame()->GetBindings();
2710 sal_uInt16 nId
= FID_INPUTLINE_ENTER
;
2711 if ( nBlockMode
== SC_ENTER_BLOCK
)
2712 nId
= FID_INPUTLINE_BLOCK
;
2713 else if ( nBlockMode
== SC_ENTER_MATRIX
)
2714 nId
= FID_INPUTLINE_MATRIX
;
2716 ScInputStatusItem
aItem( FID_INPUTLINE_STATUS
,
2717 aCursorPos
, aCursorPos
, aCursorPos
,
2720 if (!aMisspellRanges
.empty())
2721 aItem
.SetMisspellRanges(&aMisspellRanges
);
2723 const SfxPoolItem
* aArgs
[2];
2726 rBindings
.Execute( nId
, aArgs
);
2729 delete pLastState
; // pLastState still contains the old text
2733 pSfxApp
->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW
) );
2735 if ( bOldMod
&& pExecuteSh
&& pCellAttrs
&& !bForget
)
2737 // Combine with input?
2738 pExecuteSh
->ApplySelectionPattern( *pCellAttrs
, true, true );
2739 pExecuteSh
->AdjustBlockHeight();
2748 nFormSelStart
= nFormSelEnd
= 0;
2751 bInOwnChange
= false;
2752 bInEnterHandler
= false;
2755 void ScInputHandler::CancelHandler()
2757 bInOwnChange
= true; // Also without FormulaMode due to FunctionsAutoPilot
2759 ImplCreateEditEngine();
2763 // Don't rely on ShowRefFrame switching the active view synchronously
2764 // execute the function directly on the correct view's bindings instead
2765 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2766 ScTabViewShell
* pExecuteSh
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
2773 pExecuteSh
->SetTabNo(aCursorPos
.Tab());
2774 pExecuteSh
->ActiveGrabFocus();
2776 bFormulaMode
= false;
2777 SfxGetpApp()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2778 SC_MOD()->SetRefInputHdl(NULL
);
2780 pInputWin
->SetFormulaMode(false);
2781 UpdateAutoCorrFlag();
2783 pRefViewSh
= NULL
; // Also without FormulaMode due to FunctionsAutoPilot
2784 DeleteRangeFinder();
2787 eMode
= SC_INPUT_NONE
;
2788 StopInputWinEngine( true );
2790 pExecuteSh
->StopEditShell();
2792 aCursorPos
.Set(MAXCOL
+1,0,0); // Invalid flag
2793 pEngine
->SetText(OUString());
2795 if ( !pLastState
&& pExecuteSh
)
2796 pExecuteSh
->UpdateInputHandler( true ); // Update status again
2798 NotifyChange( pLastState
, true );
2800 nFormSelStart
= nFormSelEnd
= 0;
2803 bInOwnChange
= false;
2806 bool ScInputHandler::IsModalMode( SfxObjectShell
* pDocSh
)
2808 // References to unnamed document; that doesn't work
2809 return bFormulaMode
&& pRefViewSh
2810 && pRefViewSh
->GetViewData().GetDocument()->GetDocumentShell() != pDocSh
2811 && !pDocSh
->HasName();
2814 void ScInputHandler::AddRefEntry()
2816 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
2818 if (!pTableView
&& !pTopView
)
2819 return; // E.g. FillMode
2821 DataChanging(); // Cannot be new
2825 pTableView
->InsertText( OUString(cSep
), false );
2827 pTopView
->InsertText( OUString(cSep
), false );
2832 void ScInputHandler::SetReference( const ScRange
& rRef
, ScDocument
* pDoc
)
2836 bool bOtherDoc
= ( pRefViewSh
&&
2837 pRefViewSh
->GetViewData().GetDocument() != pDoc
);
2839 if (!pDoc
->GetDocumentShell()->HasName())
2841 // References to unnamed document; that doesn't work
2842 // SetReference should not be called, then
2847 if (!pTableView
&& !pTopView
)
2848 return; // E.g. FillMode
2850 // Never overwrite the "="!
2851 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2852 ESelection aSel
= pActiveView
->GetSelection();
2854 if ( aSel
.nStartPara
== 0 && aSel
.nStartPos
== 0 )
2857 DataChanging(); // Cannot be new
2859 // Turn around selection if backwards (TODO: Do we really need to do that?)
2862 ESelection aTabSel
= pTableView
->GetSelection();
2863 if (aTabSel
.nStartPos
> aTabSel
.nEndPos
&& aTabSel
.nStartPara
== aTabSel
.nEndPara
)
2866 pTableView
->SetSelection(aTabSel
);
2871 ESelection aTopSel
= pTopView
->GetSelection();
2872 if (aTopSel
.nStartPos
> aTopSel
.nEndPos
&& aTopSel
.nStartPara
== aTopSel
.nEndPara
)
2875 pTopView
->SetSelection(aTopSel
);
2879 // Create string from reference
2881 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
2884 // Reference to other document
2885 OSL_ENSURE(rRef
.aStart
.Tab()==rRef
.aEnd
.Tab(), "nStartTab!=nEndTab");
2887 OUString
aTmp(rRef
.Format(SCA_VALID
|SCA_TAB_3D
, pDoc
, aAddrDetails
)); // Always 3D
2889 SfxObjectShell
* pObjSh
= pDoc
->GetDocumentShell();
2890 // #i75893# convert escaped URL of the document to something user friendly
2891 OUString aFileName
= pObjSh
->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS
);
2893 switch(aAddrDetails
.eConv
)
2895 case formula::FormulaGrammar::CONV_XL_A1
:
2896 case formula::FormulaGrammar::CONV_XL_OOX
:
2897 case formula::FormulaGrammar::CONV_XL_R1C1
:
2899 aRefStr
+= aFileName
;
2902 case formula::FormulaGrammar::CONV_OOO
:
2905 aRefStr
+= aFileName
;
2913 if ( rRef
.aStart
.Tab() != aCursorPos
.Tab() ||
2914 rRef
.aStart
.Tab() != rRef
.aEnd
.Tab() )
2915 aRefStr
= rRef
.Format(SCA_VALID
|SCA_TAB_3D
, pDoc
, aAddrDetails
);
2917 aRefStr
= rRef
.Format(SCA_VALID
, pDoc
, aAddrDetails
);
2920 if (pTableView
|| pTopView
)
2923 pTableView
->InsertText( aRefStr
, true );
2925 pTopView
->InsertText( aRefStr
, true );
2933 void ScInputHandler::InsertFunction( const OUString
& rFuncName
, bool bAddPar
)
2935 if ( eMode
== SC_INPUT_NONE
)
2937 OSL_FAIL("InsertFunction, nicht im Eingabemodus");
2942 if (!pTableView
&& !pTopView
)
2943 return; // E.g. FillMode
2945 DataChanging(); // Cannot be new
2947 OUString aText
= rFuncName
;
2953 pTableView
->InsertText( aText
, false );
2956 ESelection aSel
= pTableView
->GetSelection();
2959 pTableView
->SetSelection(aSel
);
2964 pTopView
->InsertText( aText
, false );
2967 ESelection aSel
= pTopView
->GetSelection();
2970 pTopView
->SetSelection(aSel
);
2980 void ScInputHandler::ClearText()
2982 if ( eMode
== SC_INPUT_NONE
)
2984 OSL_FAIL("ClearText, nicht im Eingabemodus");
2989 if (!pTableView
&& !pTopView
)
2990 return; // E.g. FillMode
2992 DataChanging(); // Cannot be new
2997 pTableView
->GetEditEngine()->SetText( aEmpty
);
2998 pTableView
->SetSelection( ESelection(0,0, 0,0) );
3002 pTopView
->GetEditEngine()->SetText( aEmpty
);
3003 pTopView
->SetSelection( ESelection(0,0, 0,0) );
3009 bool ScInputHandler::KeyInput( const KeyEvent
& rKEvt
, bool bStartEdit
/* = false */ )
3013 bAutoComplete
= SC_MOD()->GetAppOptions().GetAutoComplete();
3017 vcl::KeyCode aCode
= rKEvt
.GetKeyCode();
3018 sal_uInt16 nModi
= aCode
.GetModifier();
3019 bool bShift
= aCode
.IsShift();
3020 bool bControl
= aCode
.IsMod1();
3021 bool bAlt
= aCode
.IsMod2();
3022 sal_uInt16 nCode
= aCode
.GetCode();
3023 sal_Unicode nChar
= rKEvt
.GetCharCode();
3025 if (bAlt
&& !bControl
&& nCode
!= KEY_RETURN
)
3026 // Alt-Return and Alt-Ctrl-* are accepted. Everything else with ALT are not.
3029 if (!bControl
&& nCode
== KEY_TAB
)
3031 // Normal TAB moves the cursor right.
3035 pActiveViewSh
->FindNextUnprot( bShift
);
3039 bool bInputLine
= ( eMode
==SC_INPUT_TOP
);
3043 bool bDoEnter
= false;
3048 if (bControl
&& !bShift
&& ( !bInputLine
|| ( pInputWin
&& pInputWin
->IsMultiLineInput() ) ) )
3050 else if (nModi
== 0 && nTipVisible
&& pFormulaData
&& miAutoPosFormula
!= pFormulaData
->end())
3052 PasteFunctionData();
3055 else if ( nModi
== 0 && nTipVisible
&& !aManualTip
.isEmpty() )
3062 sal_uInt8 nMode
= SC_ENTER_NORMAL
;
3063 if ( bShift
&& bControl
)
3064 nMode
= SC_ENTER_MATRIX
;
3066 nMode
= SC_ENTER_BLOCK
;
3067 EnterHandler( nMode
);
3070 pActiveViewSh
->MoveCursorEnter( bShift
&& !bControl
);
3076 if (bControl
&& !bAlt
)
3078 if (pFormulaData
&& nTipVisible
&& miAutoPosFormula
!= pFormulaData
->end())
3081 NextFormulaEntry( bShift
);
3084 else if (pColumnData
&& bUseTab
&& miAutoPosColumn
!= pColumnData
->end())
3086 // Iterate through AutoInput entries
3087 NextAutoEntry( bShift
);
3098 else if( nTipVisibleSec
)
3103 else if (eMode
!= SC_INPUT_NONE
)
3112 if ( !bShift
&& !bControl
&& !bAlt
&& eMode
== SC_INPUT_TABLE
)
3114 eMode
= SC_INPUT_TYPE
;
3120 // Only execute cursor keys if already in EditMode
3121 // E.g. due to Shift-Ctrl-PageDn (not defined as an accelerator)
3122 bool bCursorKey
= EditEngine::DoesKeyMoveCursor(rKEvt
);
3123 bool bInsKey
= ( nCode
== KEY_INSERT
&& !nModi
); // Treat Insert like Cursorkeys
3124 if ( !bUsed
&& !bSkip
&& ( bDoEnter
|| EditEngine::DoesKeyChangeText(rKEvt
) ||
3125 ( eMode
!= SC_INPUT_NONE
&& ( bCursorKey
|| bInsKey
) ) ) )
3137 bool bNewView
= DataChanging( nChar
);
3139 if (bProtected
) // Protected cell?
3140 bUsed
= true; // Don't forward KeyEvent
3141 else // Changes allowed
3143 if (bNewView
) // Create anew
3146 pActiveViewSh
->GetViewData().GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3148 if (eMode
==SC_INPUT_NONE
)
3149 if (pTableView
|| pTopView
)
3153 if ( bStartEdit
&& bCellHasPercentFormat
&& ((nChar
>= '0' && nChar
<= '9') || nChar
== '-') )
3158 pTableView
->GetEditEngine()->SetText( aStrLoP
);
3159 if ( !aStrLoP
.isEmpty() )
3160 pTableView
->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3162 // Don't call SetSelection if the string is empty anyway,
3163 // to avoid breaking the bInitial handling in ScViewData::EditGrowY
3167 pTopView
->GetEditEngine()->SetText( aStrLoP
);
3168 if ( !aStrLoP
.isEmpty() )
3169 pTopView
->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3175 if (pTableView
|| pTopView
)
3180 if( pTableView
->PostKeyEvent( KeyEvent( CHAR_CR
, vcl::KeyCode(KEY_RETURN
) ) ) )
3183 if( pTopView
->PostKeyEvent( KeyEvent( CHAR_CR
, vcl::KeyCode(KEY_RETURN
) ) ) )
3186 else if ( nAutoPar
&& nChar
== ')' && CursorAtClosingPar() )
3195 vcl::Window
* pFrameWin
= pActiveViewSh
? pActiveViewSh
->GetFrameWin() : NULL
;
3196 if ( pTableView
->PostKeyEvent( rKEvt
, pFrameWin
) )
3200 if ( pTopView
->PostKeyEvent( rKEvt
) )
3205 if ( bUsed
&& bAutoComplete
)
3209 miAutoPosFormula
= pFormulaData
->end(); // do not search further
3211 miAutoPosColumn
= pColumnData
->end();
3213 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
3214 if ( nChar
&& nChar
!= 8 && nChar
!= 127 && // no 'backspace', no 'delete'
3215 KeyFuncType::CUT
!= eFunc
) // and no 'CTRL-X'
3224 // When the selection is changed manually or an opening parenthesis
3225 // is typed, stop overwriting parentheses
3226 if ( bUsed
&& nChar
== '(' )
3229 if ( KEY_INSERT
== nCode
)
3231 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
3233 pViewFrm
->GetBindings().Invalidate( SID_ATTR_INSERT
);
3235 if( bUsed
&& bFormulaMode
&& ( bCursorKey
|| bInsKey
|| nCode
== KEY_DELETE
|| nCode
== KEY_BACKSPACE
) )
3241 // #i114511# don't count cursor keys as modification
3242 bool bSetModified
= !bCursorKey
;
3243 DataChanged(false, bSetModified
); // also calls UpdateParenthesis()
3244 InvalidateAttribs(); //! in DataChanged?
3248 if (pTopView
&& eMode
!= SC_INPUT_NONE
)
3254 bool ScInputHandler::InputCommand( const CommandEvent
& rCEvt
, bool bForce
)
3258 if ( rCEvt
.GetCommand() == CommandEventId::CursorPos
)
3260 // For CommandEventId::CursorPos, do as little as possible, because
3261 // with remote VCL, even a ShowCursor will generate another event.
3262 if ( eMode
!= SC_INPUT_NONE
)
3265 if (pTableView
|| pTopView
)
3268 pTableView
->Command( rCEvt
);
3269 else if (pTopView
) // call only once
3270 pTopView
->Command( rCEvt
);
3275 else if ( rCEvt
.GetCommand() == CommandEventId::QueryCharPosition
)
3277 if ( eMode
!= SC_INPUT_NONE
)
3280 if (pTableView
|| pTopView
)
3283 pTableView
->Command( rCEvt
);
3284 else if (pTopView
) // call only once
3285 pTopView
->Command( rCEvt
);
3292 if ( bForce
|| eMode
!= SC_INPUT_NONE
)
3296 bAutoComplete
= SC_MOD()->GetAppOptions().GetAutoComplete();
3310 bool bNewView
= DataChanging( 0, true );
3312 if (bProtected
) // cell protected
3313 bUsed
= true; // event is used
3314 else // changes allowed
3316 if (bNewView
) // create new edit view
3319 pActiveViewSh
->GetViewData().GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3321 if (eMode
==SC_INPUT_NONE
)
3322 if (pTableView
|| pTopView
)
3327 pTableView
->GetEditEngine()->SetText( aStrLoP
);
3328 pTableView
->SetSelection( ESelection(0,0, 0,0) );
3332 pTopView
->GetEditEngine()->SetText( aStrLoP
);
3333 pTopView
->SetSelection( ESelection(0,0, 0,0) );
3339 if (pTableView
|| pTopView
)
3342 pTableView
->Command( rCEvt
);
3344 pTopView
->Command( rCEvt
);
3348 if ( rCEvt
.GetCommand() == CommandEventId::EndExtTextInput
)
3350 // AutoInput after ext text input
3353 miAutoPosFormula
= pFormulaData
->end();
3355 miAutoPosColumn
= pColumnData
->end();
3364 DataChanged(); // calls UpdateParenthesis()
3365 InvalidateAttribs(); //! in DataChanged ?
3369 if (pTopView
&& eMode
!= SC_INPUT_NONE
)
3376 void ScInputHandler::NotifyChange( const ScInputHdlState
* pState
,
3377 bool bForce
, ScTabViewShell
* pSourceSh
,
3380 // If the call originates from a macro call in the EnterHandler,
3381 // return immediately and don't mess up the status
3382 if (bInEnterHandler
)
3385 bool bRepeat
= (pState
== pLastState
);
3386 if (!bRepeat
&& pState
&& pLastState
)
3387 bRepeat
= (*pState
== *pLastState
);
3388 if (bRepeat
&& !bForce
)
3391 bInOwnChange
= true; // disable ModifyHdl (reset below)
3393 if ( pState
&& !pLastState
) // Enable again
3396 bool bHadObject
= pLastState
&& pLastState
->GetEditData();
3398 //! Before EditEngine gets eventually created (so it gets the right pools)
3400 pActiveViewSh
= pSourceSh
;
3402 pActiveViewSh
= PTR_CAST(ScTabViewShell
, SfxViewShell::Current());
3404 ImplCreateEditEngine();
3406 if ( pState
!= pLastState
)
3409 pLastState
= pState
? new ScInputHdlState( *pState
) : NULL
;
3412 if ( pState
&& pActiveViewSh
)
3414 ScModule
* pScMod
= SC_MOD();
3419 // Also take foreign reference input into account here (e.g. FunctionsAutoPilot),
3420 // FormEditData, if we're switching from Help to Calc:
3421 if ( !bFormulaMode
&& !pScMod
->IsFormulaMode() && !pScMod
->GetFormEditData() )
3423 bool bIgnore
= false;
3426 if (pState
->GetPos() != aCursorPos
)
3437 const ScAddress
& rSPos
= pState
->GetStartPos();
3438 const ScAddress
& rEPos
= pState
->GetEndPos();
3439 const EditTextObject
* pData
= pState
->GetEditData();
3440 OUString aString
= pState
->GetString();
3441 bool bTxtMod
= false;
3442 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData().GetDocShell();
3443 ScDocument
& rDoc
= pDocSh
->GetDocument();
3445 aCursorPos
= pState
->GetPos();
3449 else if ( bHadObject
)
3451 else if ( bTextValid
)
3452 bTxtMod
= ( !aString
.equals(aCurrentText
) );
3454 bTxtMod
= ( !aString
.equals(GetEditText(pEngine
)) );
3456 if ( bTxtMod
|| bForce
)
3460 pEngine
->SetText( *pData
);
3461 if ( pInputWin
&& pInputWin
->IsMultiLineInput() )
3462 aString
= ScEditUtil::GetMultilineString(*pEngine
);
3464 aString
= GetEditText(pEngine
);
3465 lcl_RemoveTabs(aString
);
3467 aCurrentText
.clear();
3471 aCurrentText
= aString
;
3472 bTextValid
= true; //! To begin with remember as a string
3476 pInputWin
->SetTextString(aString
);
3479 if ( pInputWin
) // Named range input
3482 const ScAddress::Details
aAddrDetails( &rDoc
, aCursorPos
);
3484 // Is the range a name?
3486 if ( pActiveViewSh
)
3487 pActiveViewSh
->GetViewData().GetDocument()->
3488 GetRangeAtBlock( ScRange( rSPos
, rEPos
), &aPosStr
);
3490 if ( aPosStr
.isEmpty() ) // Not a name -> format
3492 sal_uInt16 nFlags
= 0;
3493 if( aAddrDetails
.eConv
== formula::FormulaGrammar::CONV_XL_R1C1
)
3494 nFlags
|= SCA_COL_ABSOLUTE
| SCA_ROW_ABSOLUTE
;
3495 if ( rSPos
!= rEPos
)
3497 ScRange
r(rSPos
, rEPos
);
3498 nFlags
|= (nFlags
<< 4);
3499 aPosStr
= r
.Format(SCA_VALID
| nFlags
, &rDoc
, aAddrDetails
);
3502 aPosStr
= aCursorPos
.Format(SCA_VALID
| nFlags
, &rDoc
, aAddrDetails
);
3505 // Disable the accessible VALUE_CHANGE event
3506 bool bIsSuppressed
= pInputWin
->IsAccessibilityEventsSuppressed(false);
3507 pInputWin
->SetAccessibilityEventsSuppressed(true);
3508 pInputWin
->SetPosString(aPosStr
);
3509 pInputWin
->SetAccessibilityEventsSuppressed(bIsSuppressed
);
3510 pInputWin
->SetSumAssignMode();
3514 SfxGetpApp()->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW
) );
3516 // As long as the content is not edited, turn off online spelling.
3517 // Online spelling is turned back on in StartTable, after setting
3518 // the right language from cell attributes.
3520 EEControlBits nCntrl
= pEngine
->GetControlWord();
3521 if ( nCntrl
& EEControlBits::ONLINESPELLING
)
3522 pEngine
->SetControlWord( nCntrl
& ~EEControlBits::ONLINESPELLING
);
3527 bCommandErrorShown
= false;
3534 // Do not enable if RefDialog is open
3535 if(!pScMod
->IsFormulaMode()&& !pScMod
->IsRefDialogOpen())
3537 if ( !pInputWin
->IsEnabled())
3539 pInputWin
->Enable();
3542 DELETEZ( pDelayTimer
);
3546 else if(pScMod
->IsRefDialogOpen())
3547 { // Because every document has its own InputWin,
3548 // we should start Timer again, because the input line may
3552 pDelayTimer
= new Timer
;
3553 pDelayTimer
->SetTimeout( 500 ); // 500 ms delay
3554 pDelayTimer
->SetTimeoutHdl( LINK( this, ScInputHandler
, DelayTimer
) );
3555 pDelayTimer
->Start();
3560 else // !pState || !pActiveViewSh
3564 pDelayTimer
= new Timer
;
3565 pDelayTimer
->SetTimeout( 500 ); // 500 ms delay
3566 pDelayTimer
->SetTimeoutHdl( LINK( this, ScInputHandler
, DelayTimer
) );
3567 pDelayTimer
->Start();
3573 bInOwnChange
= false;
3576 void ScInputHandler::UpdateCellAdjust( SvxCellHorJustify eJust
)
3578 eAttrAdjust
= eJust
;
3582 void ScInputHandler::ResetDelayTimer()
3584 if(pDelayTimer
!=NULL
)
3586 DELETEZ( pDelayTimer
);
3590 pInputWin
->Enable();
3595 IMPL_LINK_TYPED( ScInputHandler
, DelayTimer
, Timer
*, pTimer
, void )
3597 if ( pTimer
== pDelayTimer
)
3599 DELETEZ( pDelayTimer
);
3601 if ( NULL
== pLastState
|| SC_MOD()->IsFormulaMode() || SC_MOD()->IsRefDialogOpen())
3603 //! New method at ScModule to query if function autopilot is open
3604 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
3605 if ( pViewFrm
&& pViewFrm
->GetChildWindow( SID_OPENDLG_FUNCTION
) )
3609 pInputWin
->EnableButtons( false );
3610 pInputWin
->Disable();
3613 else if ( !bFormulaMode
) // Keep formula e.g. for help
3615 bInOwnChange
= true; // disable ModifyHdl (reset below)
3617 pActiveViewSh
= NULL
;
3618 pEngine
->SetText( EMPTY_OUSTRING
);
3621 pInputWin
->SetPosString( EMPTY_OUSTRING
);
3622 pInputWin
->SetTextString( EMPTY_OUSTRING
);
3623 pInputWin
->Disable();
3626 bInOwnChange
= false;
3632 void ScInputHandler::InputSelection( EditView
* pView
)
3636 UpdateParenthesis(); // Selection changed -> update parentheses highlighting
3638 // When the selection is changed manually, stop overwriting parentheses
3642 void ScInputHandler::InputChanged( EditView
* pView
, bool bFromNotify
)
3646 // #i20282# DataChanged needs to know if this is from the input line's modify handler
3647 bool bFromTopNotify
= ( bFromNotify
&& pView
== pTopView
);
3649 bool bNewView
= DataChanging(); //FIXME: Is this at all possible?
3650 aCurrentText
= pView
->GetEditEngine()->GetText(); // Also remember the string
3651 pEngine
->SetText( aCurrentText
);
3652 DataChanged( bFromTopNotify
);
3653 bTextValid
= true; // Is set to false in DataChanged
3655 if ( pActiveViewSh
)
3657 ScViewData
& rViewData
= pActiveViewSh
->GetViewData();
3659 rViewData
.GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3661 rViewData
.EditGrowY();
3662 rViewData
.EditGrowX();
3668 const OUString
& ScInputHandler::GetEditString()
3672 aCurrentText
= pEngine
->GetText(); // Always new from Engine
3676 return aCurrentText
;
3679 Size
ScInputHandler::GetTextSize()
3683 aSize
= Size( pEngine
->CalcTextWidth(), pEngine
->GetTextHeight() );
3688 bool ScInputHandler::GetTextAndFields( ScEditEngineDefaulter
& rDestEngine
)
3694 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
3695 SfxItemSet aSet
= pEngine
->GetAttribs( ESelection(0,0,nParCnt
,0) );
3696 SfxItemState eFieldState
= aSet
.GetItemState( EE_FEATURE_FIELD
, false );
3697 if ( eFieldState
== SfxItemState::DONTCARE
|| eFieldState
== SfxItemState::SET
)
3700 EditTextObject
* pObj
= pEngine
->CreateTextObject();
3701 rDestEngine
.SetText(*pObj
);
3704 // Delete attributes
3705 for (sal_Int32 i
=0; i
<nParCnt
; i
++)
3706 rDestEngine
.RemoveCharAttribs( i
);
3708 // Combine paragraphs
3709 while ( nParCnt
> 1 )
3711 sal_Int32 nLen
= rDestEngine
.GetTextLen( 0 );
3712 ESelection
aSel( 0,nLen
, 1,0 );
3713 rDestEngine
.QuickInsertText( OUString(' '), aSel
); // Replace line break with space
3724 * Methods for FunctionAutoPilot:
3725 * InputGetSelection, InputSetSelection, InputReplaceSelection, InputGetFormulaStr
3727 void ScInputHandler::InputGetSelection( sal_Int32
& rStart
, sal_Int32
& rEnd
)
3729 rStart
= nFormSelStart
;
3733 EditView
* ScInputHandler::GetFuncEditView()
3735 UpdateActiveView(); // Due to pTableView
3737 EditView
* pView
= NULL
;
3740 pInputWin
->MakeDialogEditView();
3741 pView
= pInputWin
->GetEditView();
3745 if ( eMode
!= SC_INPUT_TABLE
)
3747 bCreatingFuncView
= true; // Don't display RangeFinder
3748 SetMode( SC_INPUT_TABLE
);
3749 bCreatingFuncView
= false;
3751 pTableView
->GetEditEngine()->SetText( EMPTY_OUSTRING
);
3759 void ScInputHandler::InputSetSelection( sal_Int32 nStart
, sal_Int32 nEnd
)
3761 if ( nStart
<= nEnd
)
3763 nFormSelStart
= nStart
;
3768 nFormSelEnd
= nStart
;
3769 nFormSelStart
= nEnd
;
3772 EditView
* pView
= GetFuncEditView();
3774 pView
->SetSelection( ESelection(0,nStart
, 0,nEnd
) );
3779 void ScInputHandler::InputReplaceSelection( const OUString
& rStr
)
3782 pRefViewSh
= pActiveViewSh
;
3784 OSL_ENSURE(nFormSelEnd
>=nFormSelStart
,"Selection broken...");
3786 sal_Int32 nOldLen
= nFormSelEnd
- nFormSelStart
;
3787 sal_Int32 nNewLen
= rStr
.getLength();
3789 OUStringBuffer
aBuf(aFormText
);
3791 aBuf
.remove(nFormSelStart
, nOldLen
);
3793 aBuf
.insert(nFormSelStart
, rStr
);
3795 aFormText
= aBuf
.makeStringAndClear();
3797 nFormSelEnd
= nFormSelStart
+ nNewLen
;
3799 EditView
* pView
= GetFuncEditView();
3802 pView
->SetEditEngineUpdateMode( false );
3803 pView
->GetEditEngine()->SetText( aFormText
);
3804 pView
->SetSelection( ESelection(0,nFormSelStart
, 0,nFormSelEnd
) );
3805 pView
->SetEditEngineUpdateMode( true );
3810 void ScInputHandler::InputTurnOffWinEngine()
3812 bInOwnChange
= true; // disable ModifyHdl (reset below)
3814 eMode
= SC_INPUT_NONE
;
3815 /* TODO: it would be better if there was some way to reset the input bar
3816 * engine instead of deleting and having it recreate through
3817 * GetFuncEditView(), but first least invasively let this fix fdo#71667 and
3818 * fdo#72278 without reintroducing fdo#69971. */
3819 StopInputWinEngine(true);
3821 bInOwnChange
= false;
3827 ScInputHdlState::ScInputHdlState( const ScAddress
& rCurPos
,
3828 const ScAddress
& rStartPos
,
3829 const ScAddress
& rEndPos
,
3830 const OUString
& rString
,
3831 const EditTextObject
* pData
)
3832 : aCursorPos ( rCurPos
),
3833 aStartPos ( rStartPos
),
3834 aEndPos ( rEndPos
),
3835 aString ( rString
),
3836 pEditData ( pData
? pData
->Clone() : NULL
)
3840 ScInputHdlState::ScInputHdlState( const ScInputHdlState
& rCpy
)
3841 : pEditData ( NULL
)
3846 ScInputHdlState::~ScInputHdlState()
3851 bool ScInputHdlState::operator==( const ScInputHdlState
& r
) const
3853 return ( (aStartPos
== r
.aStartPos
)
3854 && (aEndPos
== r
.aEndPos
)
3855 && (aCursorPos
== r
.aCursorPos
)
3856 && (aString
== r
.aString
)
3857 && ScGlobal::EETextObjEqual( pEditData
, r
.pEditData
) );
3860 ScInputHdlState
& ScInputHdlState::operator=( const ScInputHdlState
& r
)
3864 aCursorPos
= r
.aCursorPos
;
3865 aStartPos
= r
.aStartPos
;
3866 aEndPos
= r
.aEndPos
;
3867 aString
= r
.aString
;
3868 pEditData
= r
.pEditData
? r
.pEditData
->Clone() : NULL
;
3873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */