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 // Delimiters (in addition to ScEditUtil) needed for range finder:
98 // only characters that are allowed in formulas next to references
99 // and the quotation mark (so string constants can be skipped)
100 const sal_Char pMinDelimiters
[] = " !\"";
102 // Formula data replacement character for a pair of parentheses at end of
103 // function name, to force sorting parentheses before all other characters.
104 // Collation may treat parentheses differently.
105 const sal_Unicode cParenthesesReplacement
= 0x0001;
107 sal_Unicode
lcl_getSheetSeparator(ScDocument
* pDoc
)
109 ScCompiler
aComp(pDoc
, ScAddress());
110 aComp
.SetGrammar(pDoc
->GetGrammar());
111 return aComp
.GetNativeAddressSymbol(ScCompiler::Convention::SHEET_SEPARATOR
);
114 ScTypedCaseStrSet::const_iterator
findText(
115 const ScTypedCaseStrSet
& rDataSet
, ScTypedCaseStrSet::const_iterator itPos
,
116 const OUString
& rStart
, OUString
& rResult
, bool bBack
)
118 if (bBack
) // Backwards
120 ScTypedCaseStrSet::const_reverse_iterator it
= rDataSet
.rbegin(), itEnd
= rDataSet
.rend();
121 if (itPos
!= rDataSet
.end())
123 size_t nPos
= std::distance(rDataSet
.begin(), itPos
);
124 size_t nRPos
= rDataSet
.size() - 1 - nPos
;
125 std::advance(it
, nRPos
);
129 for (; it
!= itEnd
; ++it
)
131 const ScTypedStrData
& rData
= *it
;
132 if (rData
.GetStringType() == ScTypedStrData::Value
)
136 if (!ScGlobal::GetpTransliteration()->isMatch(rStart
, rData
.GetString()))
140 rResult
= rData
.GetString();
141 return (++it
).base(); // convert the reverse iterator back to iterator.
146 ScTypedCaseStrSet::const_iterator it
= rDataSet
.begin(), itEnd
= rDataSet
.end();
147 if (itPos
!= rDataSet
.end())
153 for (; it
!= itEnd
; ++it
)
155 const ScTypedStrData
& rData
= *it
;
156 if (rData
.GetStringType() == ScTypedStrData::Value
)
160 if (!ScGlobal::GetpTransliteration()->isMatch(rStart
, rData
.GetString()))
164 rResult
= rData
.GetString();
169 return rDataSet
.end(); // no matching text found
172 OUString
getExactMatch(const ScTypedCaseStrSet
& rDataSet
, const OUString
& rString
)
174 ScTypedCaseStrSet::const_iterator it
= rDataSet
.begin(), itEnd
= rDataSet
.end();
175 for (; it
!= itEnd
; ++it
)
177 const ScTypedStrData
& rData
= *it
;
178 if (rData
.GetStringType() == ScTypedStrData::Value
)
181 if (!ScGlobal::GetpTransliteration()->isEqual(rData
.GetString(), rString
))
184 return rData
.GetString();
189 void removeChars(OUString
& rStr
, sal_Unicode c
)
191 OUStringBuffer
aBuf(rStr
);
192 for (sal_Int32 i
= 0, n
= aBuf
.getLength(); i
< n
; ++i
)
197 rStr
= aBuf
.makeStringAndClear();
202 void ScInputHandler::InitRangeFinder( const OUString
& rFormula
)
205 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
206 ScDocument
* pDoc
= pDocSh
->GetDocument();
207 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(pDoc
);
209 if ( !pActiveViewSh
|| !SC_MOD()->GetInputOptions().GetRangeFinder() )
212 OUString aDelimiters
= ScEditUtil::ModifyDelimiters(
213 OUString::createFromAscii( pMinDelimiters
) );
215 sal_Int32 nColon
= aDelimiters
.indexOf( ':' );
217 aDelimiters
= aDelimiters
.replaceAt( nColon
, 1, ""); // Delimiter without colon
218 sal_Int32 nDot
= aDelimiters
.indexOf(cSheetSep
);
220 aDelimiters
= aDelimiters
.replaceAt( nDot
, 1 , ""); // Delimiter without dot
222 const sal_Unicode
* pChar
= rFormula
.getStr();
223 sal_Int32 nLen
= rFormula
.getLength();
225 sal_Int32 nStart
= 0;
226 sal_uInt16 nCount
= 0;
228 while ( nPos
< nLen
&& nCount
< RANGEFIND_MAX
)
231 while ( nPos
<nLen
&& ScGlobal::UnicodeStrChr( aDelimiters
.getStr(), pChar
[nPos
] ) )
233 if ( pChar
[nPos
] == '"' ) // String
236 while (nPos
<nLen
&& pChar
[nPos
] != '"') // Skip until end
239 ++nPos
; // Separator or closing quote
242 // Text zwischen Trennern
245 while ( nPos
<nLen
&& !ScGlobal::UnicodeStrChr( aDelimiters
.getStr(), pChar
[nPos
] ) )
248 // for R1C1 '-' in R[-]... or C[-]... are not delimiters
249 // Nothing heroic here to ensure that there are '[]' around a negative
250 // integer. we need to clean up this code.
251 if( nPos
< nLen
&& nPos
> 0 &&
252 '-' == pChar
[nPos
] && '[' == pChar
[nPos
-1] &&
253 formula::FormulaGrammar::CONV_XL_R1C1
== pDoc
->GetAddressConvention() )
261 OUString aTest
= rFormula
.copy( nStart
, nPos
-nStart
);
262 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
263 sal_uInt16 nFlags
= aRange
.ParseAny( aTest
, pDoc
, aAddrDetails
);
264 if ( nFlags
& SCA_VALID
)
266 // Set tables if not specified
267 if ( (nFlags
& SCA_TAB_3D
) == 0 )
268 aRange
.aStart
.SetTab( pActiveViewSh
->GetViewData()->GetTabNo() );
269 if ( (nFlags
& SCA_TAB2_3D
) == 0 )
270 aRange
.aEnd
.SetTab( aRange
.aStart
.Tab() );
272 if ( ( nFlags
& ( SCA_VALID_COL2
| SCA_VALID_ROW2
| SCA_VALID_TAB2
) ) == 0 )
274 // #i73766# if a single ref was parsed, set the same "abs" flags for ref2,
275 // so Format doesn't output a double ref because of different flags.
276 sal_uInt16 nAbsFlags
= nFlags
& ( SCA_COL_ABSOLUTE
| SCA_ROW_ABSOLUTE
| SCA_TAB_ABSOLUTE
);
277 nFlags
|= nAbsFlags
<< 4;
282 pEngine
->SetUpdateMode( false );
283 pRangeFindList
= new ScRangeFindList( pDocSh
->GetTitle() );
286 ColorData nColorData
= pRangeFindList
->Insert( ScRangeFindData( aRange
, nFlags
, nStart
, nPos
) );
288 ESelection
aSel( 0, nStart
, 0, nPos
);
289 SfxItemSet
aSet( pEngine
->GetEmptyItemSet() );
290 aSet
.Put( SvxColorItem( Color( nColorData
),
292 pEngine
->QuickSetAttribs( aSet
, aSel
);
297 // Do not skip last separator; could be a quote (?)
302 pEngine
->SetUpdateMode( true );
304 pDocSh
->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER
) );
308 void ScInputHandler::SetDocumentDisposing( bool b
)
310 mbDocumentDisposing
= b
;
313 static void lcl_Replace( EditView
* pView
, const OUString
& rNewStr
, const ESelection
& rOldSel
)
317 ESelection aOldSel
= pView
->GetSelection();
318 if (aOldSel
.HasRange())
319 pView
->SetSelection( ESelection( aOldSel
.nEndPara
, aOldSel
.nEndPos
,
320 aOldSel
.nEndPara
, aOldSel
.nEndPos
) );
322 EditEngine
* pEngine
= pView
->GetEditEngine();
323 pEngine
->QuickInsertText( rNewStr
, rOldSel
);
325 // Dummy InsertText for Update and Paint
326 // To do that we need to cancel the selection from above (before QuickInsertText)
327 pView
->InsertText( EMPTY_OUSTRING
, false );
329 sal_Int32 nLen
= pEngine
->GetTextLen(0);
330 ESelection
aSel( 0, nLen
, 0, nLen
);
331 pView
->SetSelection( aSel
); // Set cursor to the end
335 void ScInputHandler::UpdateRange( sal_uInt16 nIndex
, const ScRange
& rNew
)
337 ScTabViewShell
* pDocView
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
338 if ( pDocView
&& pRangeFindList
&& nIndex
< pRangeFindList
->Count() )
340 ScRangeFindData
* pData
= pRangeFindList
->GetObject( nIndex
);
341 sal_Int32 nOldStart
= pData
->nSelStart
;
342 sal_Int32 nOldEnd
= pData
->nSelEnd
;
344 ScRange aJustified
= rNew
;
345 aJustified
.Justify(); // Always display Ref in the Formula the right way
346 ScDocument
* pDoc
= pDocView
->GetViewData()->GetDocument();
347 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
348 OUString
aNewStr(aJustified
.Format(pData
->nFlags
, pDoc
, aAddrDetails
));
349 ESelection
aOldSel( 0, nOldStart
, 0, nOldEnd
);
353 lcl_Replace( pTopView
, aNewStr
, aOldSel
);
354 lcl_Replace( pTableView
, aNewStr
, aOldSel
);
356 bInRangeUpdate
= true;
358 bInRangeUpdate
= false;
360 long nDiff
= aNewStr
.getLength() - (long)(nOldEnd
-nOldStart
);
363 pData
->nSelEnd
= pData
->nSelEnd
+ nDiff
;
365 sal_uInt16 nCount
= (sal_uInt16
) pRangeFindList
->Count();
366 for (sal_uInt16 i
=nIndex
+1; i
<nCount
; i
++)
368 ScRangeFindData
* pNext
= pRangeFindList
->GetObject( i
);
369 pNext
->nSelStart
= pNext
->nSelStart
+ nDiff
;
370 pNext
->nSelEnd
= pNext
->nSelEnd
+ nDiff
;
375 OSL_FAIL("UpdateRange: we're missing something");
379 void ScInputHandler::DeleteRangeFinder()
381 ScTabViewShell
* pPaintView
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
382 if ( pRangeFindList
&& pPaintView
)
384 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
385 pRangeFindList
->SetHidden(true);
386 pDocSh
->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER
) ); // Steal
387 DELETEZ(pRangeFindList
);
391 inline OUString
GetEditText(EditEngine
* pEng
)
393 return ScEditUtil::GetSpaceDelimitedString(*pEng
);
396 static void lcl_RemoveTabs(OUString
& rStr
)
398 removeChars(rStr
, '\t');
401 static void lcl_RemoveLineEnd(OUString
& rStr
)
403 rStr
= convertLineEnd(rStr
, LINEEND_LF
);
404 removeChars(rStr
, '\n');
407 static sal_Int32
lcl_MatchParenthesis( const OUString
& rStr
, sal_Int32 nPos
)
410 sal_Unicode c1
, c2
= 0;
451 sal_Int32 nLen
= rStr
.getLength();
452 const sal_Unicode
* p0
= rStr
.getStr();
453 const sal_Unicode
* p
;
454 const sal_Unicode
* p1
;
455 sal_uInt16 nQuotes
= 0;
456 if ( nPos
< nLen
/ 2 )
471 // Odd number of quotes that we find ourselves in a string
472 bool bLookInString
= ((nQuotes
% 2) != 0);
473 bool bInString
= bLookInString
;
475 p1
= (nDir
< 0 ? p0
: p0
+ nLen
) ;
476 sal_uInt16 nLevel
= 1;
477 while ( p
!= p1
&& nLevel
)
482 bInString
= !bInString
;
483 if ( bLookInString
&& !bInString
)
484 p
= p1
; // That's it then
486 else if ( bInString
== bLookInString
)
496 return (sal_Int32
) (p
- p0
);
499 ScInputHandler::ScInputHandler()
505 pFormulaData( NULL
),
506 pFormulaDataPara( NULL
),
507 pTipVisibleParent( NULL
),
509 pTipVisibleSecParent( NULL
),
514 eMode( SC_INPUT_NONE
),
519 bFormulaMode( false ),
520 bInRangeUpdate( false ),
521 bParenthesisShown( false ),
522 bCreatingFuncView( false ),
523 bInEnterHandler( false ),
524 bCommandErrorShown( false ),
525 bInOwnChange( false ),
527 bCellHasPercentFormat( false ),
528 bLastIsSymbol( false ),
529 mbDocumentDisposing(false),
531 eAttrAdjust( SVX_HOR_JUSTIFY_STANDARD
),
535 pLastPattern( NULL
),
536 pEditDefaults( NULL
),
539 pRangeFindList( NULL
),
542 // The InputHandler is constructed with the view, so SfxViewShell::Current
543 // doesn't have the right view yet. pActiveViewSh is updated in NotifyChange.
544 pActiveViewSh
= NULL
;
546 // Bindings (only still used for Invalidate) are retrieved if needed on demand
549 ScInputHandler::~ScInputHandler()
551 // If this is the application InputHandler, the dtor is called after SfxApplication::Main,
552 // thus we can't rely on any Sfx functions
553 if (!mbDocumentDisposing
) // inplace
554 EnterHandler(); // Finish input
556 if (SC_MOD()->GetRefInputHdl() == this)
557 SC_MOD()->SetRefInputHdl(NULL
);
559 if ( pInputWin
&& pInputWin
->GetInputHandler() == this )
560 pInputWin
->SetInputHandler( NULL
);
562 delete pRangeFindList
;
563 delete pEditDefaults
;
569 delete pFormulaDataPara
;
572 void ScInputHandler::SetRefScale( const Fraction
& rX
, const Fraction
& rY
)
574 if ( rX
!= aScaleX
|| rY
!= aScaleY
)
580 MapMode
aMode( MAP_100TH_MM
, Point(), aScaleX
, aScaleY
);
581 pEngine
->SetRefMapMode( aMode
);
586 void ScInputHandler::UpdateRefDevice()
591 bool bTextWysiwyg
= SC_MOD()->GetInputOptions().GetTextWysiwyg();
592 bool bInPlace
= pActiveViewSh
&& pActiveViewSh
->GetViewFrame()->GetFrame().IsInPlace();
593 sal_uLong nCtrl
= pEngine
->GetControlWord();
594 if ( bTextWysiwyg
|| bInPlace
)
595 nCtrl
|= EE_CNTRL_FORMAT100
; // EditEngine default: always format for 100%
597 nCtrl
&= ~EE_CNTRL_FORMAT100
; // when formatting for screen, use the actual MapMode
598 pEngine
->SetControlWord( nCtrl
);
599 if ( bTextWysiwyg
&& pActiveViewSh
)
600 pEngine
->SetRefDevice( pActiveViewSh
->GetViewData()->GetDocument()->GetPrinter() );
602 pEngine
->SetRefDevice( NULL
);
604 MapMode
aMode( MAP_100TH_MM
, Point(), aScaleX
, aScaleY
);
605 pEngine
->SetRefMapMode( aMode
);
607 // SetRefDevice(NULL) uses VirtualDevice, SetRefMapMode forces creation of a local VDev,
608 // so the DigitLanguage can be safely modified (might use an own VDev instead of NULL).
609 if ( !( bTextWysiwyg
&& pActiveViewSh
) )
611 pEngine
->GetRefDevice()->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
615 void ScInputHandler::ImplCreateEditEngine()
621 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
622 pEngine
= new ScFieldEditEngine(pDoc
, pDoc
->GetEnginePool(), pDoc
->GetEditPool());
625 pEngine
= new ScFieldEditEngine(NULL
, EditEngine::CreatePool(), NULL
, true);
626 pEngine
->SetWordDelimiters( ScEditUtil::ModifyDelimiters( pEngine
->GetWordDelimiters() ) );
627 UpdateRefDevice(); // also sets MapMode
628 pEngine
->SetPaperSize( Size( 1000000, 1000000 ) );
629 pEditDefaults
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
631 pEngine
->SetControlWord( pEngine
->GetControlWord() | EE_CNTRL_AUTOCORRECT
);
632 pEngine
->SetModifyHdl( LINK( this, ScInputHandler
, ModifyHdl
) );
636 void ScInputHandler::UpdateAutoCorrFlag()
638 sal_uLong nCntrl
= pEngine
->GetControlWord();
639 sal_uLong nOld
= nCntrl
;
641 // Don't use pLastPattern here (may be invalid because of AutoStyle)
642 bool bDisable
= bLastIsSymbol
|| bFormulaMode
;
644 nCntrl
&= ~EE_CNTRL_AUTOCORRECT
;
646 nCntrl
|= EE_CNTRL_AUTOCORRECT
;
648 if ( nCntrl
!= nOld
)
649 pEngine
->SetControlWord(nCntrl
);
652 void ScInputHandler::UpdateSpellSettings( bool bFromStartTab
)
656 ScViewData
* pViewData
= pActiveViewSh
->GetViewData();
657 bool bOnlineSpell
= pViewData
->GetDocument()->GetDocOptions().IsAutoSpell();
659 // SetDefaultLanguage is independent of the language attributes,
660 // ScGlobal::GetEditDefaultLanguage is always used.
661 // It must be set every time in case the office language was changed.
663 pEngine
->SetDefaultLanguage( ScGlobal::GetEditDefaultLanguage() );
665 // if called for changed options, update flags only if already editing
666 // if called from StartTable, always update flags
668 if ( bFromStartTab
|| eMode
!= SC_INPUT_NONE
)
670 sal_uLong nCntrl
= pEngine
->GetControlWord();
671 sal_uLong nOld
= nCntrl
;
673 nCntrl
|= EE_CNTRL_ONLINESPELLING
;
675 nCntrl
&= ~EE_CNTRL_ONLINESPELLING
;
676 // No AutoCorrect for Symbol Font (EditEngine does no evaluate Default)
677 if ( pLastPattern
&& pLastPattern
->IsSymbolFont() )
678 nCntrl
&= ~EE_CNTRL_AUTOCORRECT
;
680 nCntrl
|= EE_CNTRL_AUTOCORRECT
;
681 if ( nCntrl
!= nOld
)
682 pEngine
->SetControlWord(nCntrl
);
684 ScDocument
* pDoc
= pViewData
->GetDocument();
685 pDoc
->ApplyAsianEditSettings( *pEngine
);
686 pEngine
->SetDefaultHorizontalTextDirection(
687 (EEHorizontalTextDirection
)pDoc
->GetEditTextDirection( pViewData
->GetTabNo() ) );
688 pEngine
->SetFirstWordCapitalization( false );
691 // Language is set separately, so the speller is needed only if online spelling is active
692 if ( bOnlineSpell
) {
693 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XSpellChecker1
> xXSpellChecker1( LinguMgr::GetSpellChecker() );
694 pEngine
->SetSpeller( xXSpellChecker1
);
697 bool bHyphen
= pLastPattern
&& ((const SfxBoolItem
&)pLastPattern
->GetItem(ATTR_HYPHENATE
)).GetValue();
699 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
700 pEngine
->SetHyphenator( xXHyphenator
);
706 // Function/Range names etc. as Tip help
709 // The other types are defined in ScDocument::GetFormulaEntries
710 void ScInputHandler::GetFormulaData()
714 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
717 pFormulaData
->clear();
720 pFormulaData
= new ScTypedCaseStrSet
;
723 if( pFormulaDataPara
)
724 pFormulaDataPara
->clear();
726 pFormulaDataPara
= new ScTypedCaseStrSet
;
728 const OUString
aParenthesesReplacement( cParenthesesReplacement
);
729 const ScFunctionList
* pFuncList
= ScGlobal::GetStarCalcFunctionList();
730 sal_uLong nListCount
= pFuncList
->GetCount();
731 for(sal_uLong i
=0;i
<nListCount
;i
++)
733 const ScFuncDesc
* pDesc
= pFuncList
->GetFunction( i
);
734 if ( pDesc
->pFuncName
)
736 const sal_Unicode
* pName
= pDesc
->pFuncName
->getStr();
737 const sal_Int32 nLen
= pDesc
->pFuncName
->getLength();
738 // fdo#75264 fill maFormulaChar with all characters used in formula names
739 for ( sal_Int32 j
= 0; j
< nLen
; j
++ )
741 sal_Unicode c
= pName
[ j
];
742 maFormulaChar
.insert( c
);
744 OUString aFuncName
= *pDesc
->pFuncName
+ aParenthesesReplacement
;
745 pFormulaData
->insert(ScTypedStrData(aFuncName
, 0.0, ScTypedStrData::Standard
));
746 pDesc
->initArgumentInfo();
747 OUString aEntry
= pDesc
->getSignature();
748 pFormulaDataPara
->insert(ScTypedStrData(aEntry
, 0.0, ScTypedStrData::Standard
));
751 miAutoPosFormula
= pFormulaData
->end();
752 pDoc
->GetFormulaEntries( *pFormulaData
);
753 pDoc
->GetFormulaEntries( *pFormulaDataPara
);
757 IMPL_LINK( ScInputHandler
, ShowHideTipVisibleParentListener
, VclWindowEvent
*, pEvent
)
759 if( pEvent
->GetId() == VCLEVENT_OBJECT_DYING
|| pEvent
->GetId() == VCLEVENT_WINDOW_HIDE
)
764 IMPL_LINK( ScInputHandler
, ShowHideTipVisibleSecParentListener
, VclWindowEvent
*, pEvent
)
766 if( pEvent
->GetId() == VCLEVENT_OBJECT_DYING
|| pEvent
->GetId() == VCLEVENT_WINDOW_HIDE
)
771 void ScInputHandler::HideTip()
775 if (pTipVisibleParent
)
776 pTipVisibleParent
->RemoveEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleParentListener
) );
777 Help::HideTip( nTipVisible
);
779 pTipVisibleParent
= NULL
;
781 aManualTip
= OUString();
783 void ScInputHandler::HideTipBelow()
785 if ( nTipVisibleSec
)
787 if (pTipVisibleSecParent
)
788 pTipVisibleSecParent
->RemoveEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleSecParentListener
) );
789 Help::HideTip( nTipVisibleSec
);
791 pTipVisibleSecParent
= NULL
;
793 aManualTip
= OUString();
796 void ScInputHandler::ShowArgumentsTip( const OUString
& rParagraph
, OUString
& rSelText
, const ESelection
& rSel
,
799 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
800 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
801 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(pDocSh
->GetDocument());
802 FormulaHelper
aHelper(ScGlobal::GetStarCalcFunctionMgr());
807 sal_Int32 nLeftParentPos
= lcl_MatchParenthesis( rSelText
, rSelText
.getLength()-1 );
808 if( nLeftParentPos
!= -1 )
810 sal_Int32 nNextFStart
= aHelper
.GetFunctionStart( rSelText
, nLeftParentPos
, true);
811 const IFunctionDescription
* ppFDesc
;
812 ::std::vector
< OUString
> aArgs
;
813 if( aHelper
.GetNextFunc( rSelText
, false, nNextFStart
, NULL
, &ppFDesc
, &aArgs
) )
815 if( !ppFDesc
->getFunctionName().isEmpty() )
817 sal_Int32 nArgPos
= aHelper
.GetArgStart( rSelText
, nNextFStart
, 0 );
818 sal_uInt16 nArgs
= static_cast<sal_uInt16
>(ppFDesc
->getParameterCount());
819 OUString
aFuncName( ppFDesc
->getFunctionName() + "(");
821 ScTypedCaseStrSet::const_iterator it
=
822 findText(*pFormulaDataPara
, pFormulaDataPara
->end(), aFuncName
, aNew
, false);
823 if (it
!= pFormulaDataPara
->end())
826 sal_uInt16 nActive
= 0;
827 for( sal_uInt16 i
=0; i
< nArgs
; i
++ )
829 sal_Int32 nLength
= aArgs
[i
].getLength();
830 if( nArgPos
<= rSelText
.getLength()-1 )
839 sal_Int32 nCountSemicolon
= comphelper::string::getTokenCount(aNew
, cSep
) - 1;
840 sal_Int32 nCountDot
= comphelper::string::getTokenCount(aNew
, cSheetSep
) - 1;
841 sal_Int32 nStartPosition
= 0;
842 sal_Int32 nEndPosition
= 0;
844 if( !nCountSemicolon
)
846 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
848 sal_Unicode cNext
= aNew
[i
];
851 nStartPosition
= i
+1;
855 else if( !nCountDot
)
857 sal_uInt16 nCount
= 0;
858 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
860 sal_Unicode cNext
= aNew
[i
];
863 nStartPosition
= i
+1;
865 else if( cNext
== cSep
)
869 if( nCount
== nActive
)
873 nStartPosition
= nEndPosition
+1;
879 sal_uInt16 nCount
= 0;
880 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
882 sal_Unicode cNext
= aNew
[i
];
885 nStartPosition
= i
+1;
887 else if( cNext
== cSep
)
891 if( nCount
== nActive
)
895 nStartPosition
= nEndPosition
+1;
897 else if( cNext
== cSheetSep
)
904 if (nStartPosition
> 0)
907 aBuf
.append(aNew
.copy(0, nStartPosition
));
908 aBuf
.append(static_cast<sal_Unicode
>(0x25BA));
909 aBuf
.append(aNew
.copy(nStartPosition
));
910 aNew
= aBuf
.makeStringAndClear();
911 ShowTipBelow( aNew
);
917 ShowTipBelow( aNew
);
924 else if (bTryFirstSel
)
926 sal_Int32 nPosition
= 0;
927 OUString aText
= pEngine
->GetWord( 0, rSel
.nEndPos
-1 );
928 /* XXX: dubious, what is this condition supposed to exactly match? */
929 if (rSel
.nEndPos
<= aText
.getLength() && aText
[ rSel
.nEndPos
-1 ] == '=')
934 nPosition
= aText
.getLength()+1;
935 ScTypedCaseStrSet::const_iterator it
=
936 findText(*pFormulaDataPara
, pFormulaDataPara
->end(), aText
, aNew
, false);
937 if (it
!= pFormulaDataPara
->end())
939 if( nPosition
< rParagraph
.getLength() && rParagraph
[ nPosition
] =='(' )
941 ShowTipBelow( aNew
);
959 void ScInputHandler::ShowTipCursor()
963 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
965 if ( bFormulaMode
&& pActiveView
&& pFormulaDataPara
&& pEngine
->GetParagraphCount() == 1 )
967 OUString aParagraph
= pEngine
->GetText( 0 );
968 ESelection aSel
= pActiveView
->GetSelection();
971 if ( aParagraph
.getLength() < aSel
.nEndPos
)
974 if ( aSel
.nEndPos
> 0 )
976 OUString
aSelText( aParagraph
.copy( 0, aSel
.nEndPos
));
978 ShowArgumentsTip( aParagraph
, aSelText
, aSel
, true);
983 void ScInputHandler::ShowTip( const OUString
& rText
)
985 // aManualTip needs to be set afterwards from outside
987 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
991 pTipVisibleParent
= pActiveView
->GetWindow();
992 Cursor
* pCur
= pActiveView
->GetCursor();
994 aPos
= pTipVisibleParent
->LogicToPixel( pCur
->GetPos() );
995 aPos
= pTipVisibleParent
->OutputToScreenPixel( aPos
);
996 Rectangle
aRect( aPos
, aPos
);
998 sal_uInt16 nAlign
= QUICKHELP_LEFT
|QUICKHELP_BOTTOM
;
999 nTipVisible
= Help::ShowTip(pTipVisibleParent
, aRect
, rText
, nAlign
);
1000 pTipVisibleParent
->AddEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleParentListener
) );
1004 void ScInputHandler::ShowTipBelow( const OUString
& rText
)
1008 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1012 pTipVisibleSecParent
= pActiveView
->GetWindow();
1013 Cursor
* pCur
= pActiveView
->GetCursor();
1016 Point aLogicPos
= pCur
->GetPos();
1017 aLogicPos
.Y() += pCur
->GetHeight();
1018 aPos
= pTipVisibleSecParent
->LogicToPixel( aLogicPos
);
1020 aPos
= pTipVisibleSecParent
->OutputToScreenPixel( aPos
);
1021 Rectangle
aRect( aPos
, aPos
);
1022 sal_uInt16 nAlign
= QUICKHELP_LEFT
| QUICKHELP_TOP
| QUICKHELP_NOEVADEPOINTER
;
1023 nTipVisibleSec
= Help::ShowTip(pTipVisibleSecParent
, aRect
, rText
, nAlign
);
1024 pTipVisibleSecParent
->AddEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleSecParentListener
) );
1028 bool ScInputHandler::GetFuncName( OUString
& aStart
, OUString
& aResult
)
1030 if ( aStart
.isEmpty() )
1033 aStart
= ScGlobal::pCharClass
->uppercase( aStart
);
1034 sal_Int32 nPos
= aStart
.getLength() - 1;
1035 sal_Unicode c
= aStart
[ nPos
];
1036 // fdo#75264 use maFormulaChar to check if characters are used in function names
1037 ::std::set
< sal_Unicode
>::const_iterator p
= maFormulaChar
.find( c
);
1038 if ( p
== maFormulaChar
.end() )
1039 return false; // last character is not part of any function name, quit
1041 ::std::vector
<sal_Unicode
> aTemp
;
1042 while ( nPos
>= 0 && p
!= maFormulaChar
.end() )
1044 aTemp
.push_back( c
);
1045 c
= aStart
[ --nPos
];
1046 p
= maFormulaChar
.find( c
);
1049 ::std::vector
<sal_Unicode
>::reverse_iterator rIt
= aTemp
.rbegin();
1050 aResult
= OUString( *rIt
++ );
1051 while ( rIt
!= aTemp
.rend() )
1052 aResult
+= OUString( *rIt
++ );
1057 void ScInputHandler::UseFormulaData()
1059 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1061 // Formulas may only have 1 paragraph
1062 if ( pActiveView
&& pFormulaData
&& pEngine
->GetParagraphCount() == 1 )
1064 OUString aParagraph
= pEngine
->GetText( 0 );
1065 ESelection aSel
= pActiveView
->GetSelection();
1068 // Due to differences between table and input cell (e.g clipboard with line breaks),
1069 // the selection may not be in line with the EditEngine anymore.
1070 // Just return without any indication as to why.
1071 if ( aSel
.nEndPos
> aParagraph
.getLength() )
1074 // Is the cursor at the end of a word?
1075 if ( aSel
.nEndPos
> 0 )
1077 OUString
aSelText( aParagraph
.copy( 0, aSel
.nEndPos
));
1080 if ( GetFuncName( aSelText
, aText
) )
1082 // function name is incomplete:
1083 // show first matching function name as tip above cell
1085 miAutoPosFormula
= pFormulaData
->end();
1086 miAutoPosFormula
= findText(*pFormulaData
, miAutoPosFormula
, aText
, aNew
, false);
1087 if (miAutoPosFormula
!= pFormulaData
->end())
1089 if (aNew
[aNew
.getLength()-1] == cParenthesesReplacement
)
1090 aNew
= aNew
.copy( 0, aNew
.getLength()-1) + "()";
1092 aAutoSearch
= aText
;
1097 // function name is complete:
1098 // show tip below the cell with function name and arguments of function
1099 ShowArgumentsTip( aParagraph
, aSelText
, aSel
, false);
1104 void ScInputHandler::NextFormulaEntry( bool bBack
)
1106 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1107 if ( pActiveView
&& pFormulaData
)
1110 ScTypedCaseStrSet::const_iterator itNew
= findText(*pFormulaData
, miAutoPosFormula
, aAutoSearch
, aNew
, bBack
);
1111 if (itNew
!= pFormulaData
->end())
1113 miAutoPosFormula
= itNew
;
1114 if (aNew
[aNew
.getLength()-1] == cParenthesesReplacement
)
1115 aNew
= aNew
.copy( 0, aNew
.getLength()-1) + "()";
1116 ShowTip(aNew
); // Display a quick help
1120 // For Tab we always call HideCursor first
1122 pActiveView
->ShowCursor();
1127 bool needToExtendSelection(const OUString
& rSelectedText
, const OUString
& rInsertText
)
1129 SAL_DEBUG(rSelectedText
);
1130 return !rInsertText
.startsWithIgnoreAsciiCase(rSelectedText
);
1133 void completeFunction( EditView
* pView
, const OUString
& rInsert
, bool& rParInserted
)
1137 ESelection aSel
= pView
->GetSelection();
1140 pView
->SetSelection(aSel
);
1141 pView
->SelectCurrentWord();
1143 // a dot and underscore are word separators so we need special
1144 // treatment for any formula containing a dot or underscore
1145 if(rInsert
.indexOf(".") != -1 || rInsert
.indexOf("_") != -1)
1147 // need to make sure that we replace also the part before the dot
1148 // go through the word to find the match with the insert string
1149 aSel
= pView
->GetSelection();
1150 ESelection aOldSelection
= aSel
;
1151 OUString aSelectedText
= pView
->GetSelected();
1152 if ( needToExtendSelection( aSelectedText
, rInsert
) )
1154 while(needToExtendSelection(aSelectedText
, rInsert
))
1156 assert(aSel
.nStartPos
> 0);
1158 aSel
.nEndPos
= aSel
.nStartPos
;
1159 pView
->SetSelection(aSel
);
1160 pView
->SelectCurrentWord();
1161 aSelectedText
= pView
->GetSelected();
1163 aSel
.nStartPos
= aSel
.nEndPos
- ( aSelectedText
.getLength() - 1 );
1167 aSel
.nStartPos
= aSel
.nEndPos
- aSelectedText
.getLength();
1169 aSel
.nEndPos
= aOldSelection
.nEndPos
;
1170 pView
->SetSelection(aSel
);
1173 OUString aInsStr
= rInsert
;
1174 sal_Int32 nInsLen
= aInsStr
.getLength();
1175 bool bDoParen
= ( nInsLen
> 1 && aInsStr
[nInsLen
-2] == '('
1176 && aInsStr
[nInsLen
-1] == ')' );
1179 // Do not insert parentheses after function names if there already are some
1180 // (e.g. if the function name was edited).
1181 ESelection aWordSel
= pView
->GetSelection();
1182 OUString aOld
= pView
->GetEditEngine()->GetText(0);
1184 // aWordSel.EndPos points one behind string if word at end
1185 if (aWordSel
.nEndPos
< aOld
.getLength())
1187 sal_Unicode cNext
= aOld
[aWordSel
.nEndPos
];
1191 aInsStr
= aInsStr
.copy( 0, nInsLen
- 2 ); // Skip parentheses
1196 pView
->InsertText( aInsStr
, false );
1198 if ( bDoParen
) // Put cursor between parentheses
1200 aSel
= pView
->GetSelection();
1203 pView
->SetSelection(aSel
);
1205 rParInserted
= true;
1212 void ScInputHandler::PasteFunctionData()
1214 if (pFormulaData
&& miAutoPosFormula
!= pFormulaData
->end())
1216 const ScTypedStrData
& rData
= *miAutoPosFormula
;
1217 OUString aInsert
= rData
.GetString();
1218 if (aInsert
[aInsert
.getLength()-1] == cParenthesesReplacement
)
1219 aInsert
= aInsert
.copy( 0, aInsert
.getLength()-1) + "()";
1220 bool bParInserted
= false;
1222 DataChanging(); // Cannot be new
1223 completeFunction( pTopView
, aInsert
, bParInserted
);
1224 completeFunction( pTableView
, aInsert
, bParInserted
);
1234 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1236 pActiveView
->ShowCursor();
1240 // Calculate selection and display as tip help
1241 static OUString
lcl_Calculate( const OUString
& rFormula
, ScDocument
* pDoc
, const ScAddress
&rPos
)
1243 //TODO: Merge with ScFormulaDlg::CalcValue and move into Document!
1244 // Quotation marks for Strings are only inserted here.
1246 if(rFormula
.isEmpty())
1249 boost::scoped_ptr
<ScSimpleFormulaCalculator
> pCalc( new ScSimpleFormulaCalculator( pDoc
, rPos
, rFormula
) );
1251 // FIXME: HACK! In order to not get a #REF! for ColRowNames, if a name is actually inserted as a Range
1252 // into the whole Formula, but is interpreted as a single cell reference when displaying it on its own
1253 bool bColRowName
= pCalc
->HasColRowName();
1256 // ColRowName in RPN code?
1257 if ( pCalc
->GetCode()->GetCodeLen() <= 1 )
1258 { // ==1: Single one is as a Parameter always a Range
1259 // ==0: It might be one, if ...
1260 OUStringBuffer aBraced
;
1261 aBraced
.append('(');
1262 aBraced
.append(rFormula
);
1263 aBraced
.append(')');
1264 pCalc
.reset( new ScSimpleFormulaCalculator( pDoc
, rPos
, aBraced
.makeStringAndClear() ) );
1267 bColRowName
= false;
1270 sal_uInt16 nErrCode
= pCalc
->GetErrCode();
1271 if ( nErrCode
!= 0 )
1272 return ScGlobal::GetErrorString(nErrCode
);
1274 SvNumberFormatter
& aFormatter
= *(pDoc
->GetFormatTable());
1276 if ( pCalc
->IsValue() )
1278 double n
= pCalc
->GetValue();
1279 sal_uLong nFormat
= aFormatter
.GetStandardFormat( n
, 0,
1280 pCalc
->GetFormatType(), ScGlobal::eLnge
);
1281 aFormatter
.GetInputLineString( n
, nFormat
, aValue
);
1282 //! display OutputString but insert InputLineString
1286 OUString aStr
= pCalc
->GetString().getString();
1287 sal_uLong nFormat
= aFormatter
.GetStandardFormat(
1288 pCalc
->GetFormatType(), ScGlobal::eLnge
);
1291 aFormatter
.GetOutputString( aStr
, nFormat
,
1295 aValue
= "\"" + aValue
+ "\"";
1296 //! Escape quotation marks in String??
1300 if ( bColRowName
|| (aTestRange
.Parse(rFormula
) & SCA_VALID
) )
1301 aValue
= aValue
+ " ...";
1306 void ScInputHandler::FormulaPreview()
1309 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1310 if ( pActiveView
&& pActiveViewSh
)
1312 OUString aPart
= pActiveView
->GetSelected();
1313 if (aPart
.isEmpty())
1314 aPart
= pEngine
->GetText(0);
1315 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1316 aValue
= lcl_Calculate( aPart
, pDoc
, aCursorPos
);
1319 if (!aValue
.isEmpty())
1321 ShowTip( aValue
); // Display as QuickHelp
1322 aManualTip
= aValue
; // Set after ShowTip
1324 miAutoPosFormula
= pFormulaData
->end();
1326 miAutoPosColumn
= pColumnData
->end();
1330 void ScInputHandler::PasteManualTip()
1332 // Three dots at the end -> Range reference -> do not insert
1333 // FIXME: Once we have matrix constants, we can change this
1334 sal_Int32 nTipLen
= aManualTip
.getLength();
1335 sal_uInt32
const nTipLen2(sal::static_int_cast
<sal_uInt32
>(nTipLen
));
1336 if ( nTipLen
&& ( nTipLen
< 3 || aManualTip
.copy( nTipLen2
-3 ) != "..." ) )
1338 DataChanging(); // Cannot be new
1340 OUString aInsert
= aManualTip
;
1341 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1342 if (!pActiveView
->HasSelection())
1344 // Nothing selected -> select everything
1345 sal_Int32 nOldLen
= pEngine
->GetTextLen(0);
1346 ESelection
aAllSel( 0, 0, 0, nOldLen
);
1348 pTopView
->SetSelection( aAllSel
);
1350 pTableView
->SetSelection( aAllSel
);
1353 ESelection aSel
= pActiveView
->GetSelection();
1355 OSL_ENSURE( !aSel
.nStartPara
&& !aSel
.nEndPara
, "Too many paragraphs in Formula" );
1356 if ( !aSel
.nStartPos
) // Selection from the start?
1358 if ( aSel
.nEndPos
== pEngine
->GetTextLen(0) )
1360 // Everything selected -> skip quotation marks
1361 if ( aInsert
[0] == '"' )
1362 aInsert
= aInsert
.copy(1);
1363 sal_Int32 nInsLen
= aInsert
.getLength();
1364 if ( aInsert
.endsWith("\"") )
1365 aInsert
= aInsert
.copy( 0, nInsLen
-1 );
1367 else if ( aSel
.nEndPos
)
1369 // Not everything selected -> do not overwrite equality sign
1370 //FIXME: Even double equality signs??
1373 pTopView
->SetSelection( aSel
);
1375 pTableView
->SetSelection( aSel
);
1379 pTopView
->InsertText( aInsert
, true );
1381 pTableView
->InsertText( aInsert
, true );
1389 void ScInputHandler::ResetAutoPar()
1394 void ScInputHandler::AutoParAdded()
1396 ++nAutoPar
; // Closing parenthesis can be overwritten
1399 bool ScInputHandler::CursorAtClosingPar()
1401 // Test if the cursor is before a closing parenthesis
1402 // Selection from SetReference has been removed before
1403 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1404 if ( pActiveView
&& !pActiveView
->HasSelection() && bFormulaMode
)
1406 ESelection aSel
= pActiveView
->GetSelection();
1407 sal_Int32 nPos
= aSel
.nStartPos
;
1408 OUString aFormula
= pEngine
->GetText(0);
1409 if ( nPos
< aFormula
.getLength() && aFormula
[nPos
] == ')' )
1415 void ScInputHandler::SkipClosingPar()
1417 // this is called when a ')' is typed and the cursor is before a ')'
1418 // that can be overwritten -> just set the cursor behind the ')'
1420 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1423 ESelection aSel
= pActiveView
->GetSelection();
1427 // this is in a formula (only one paragraph), so the selection
1428 // can be used directly for the TopView
1431 pTopView
->SetSelection( aSel
);
1433 pTableView
->SetSelection( aSel
);
1436 OSL_ENSURE(nAutoPar
, "SkipClosingPar: count is wrong");
1443 void ScInputHandler::GetColData()
1445 if ( pActiveViewSh
)
1447 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1450 pColumnData
->clear();
1452 pColumnData
= new ScTypedCaseStrSet
;
1454 std::vector
<ScTypedStrData
> aEntries
;
1455 pDoc
->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();
1596 // Highlight parentheses
1597 void ScInputHandler::UpdateParenthesis()
1600 //TODO: Can we disable parentheses highlighting per paranthesis?
1601 bool bFound
= false;
1602 if ( bFormulaMode
&& eMode
!= SC_INPUT_TOP
)
1604 if ( pTableView
&& !pTableView
->HasSelection() ) // Selection is always at the bottom
1606 ESelection aSel
= pTableView
->GetSelection();
1609 // Examine character left to the cursor
1610 sal_Int32 nPos
= aSel
.nStartPos
- 1;
1611 OUString aFormula
= pEngine
->GetText(0);
1612 sal_Unicode c
= aFormula
[nPos
];
1613 if ( c
== '(' || c
== ')' )
1615 sal_Int32 nOther
= lcl_MatchParenthesis( aFormula
, nPos
);
1618 SfxItemSet
aSet( pEngine
->GetEmptyItemSet() );
1619 aSet
.Put( SvxWeightItem( WEIGHT_BOLD
, EE_CHAR_WEIGHT
) );
1621 //! Distinguish if cell is already highlighted!!!!
1622 if (bParenthesisShown
)
1624 // Remove old highlighting
1625 sal_Int32 nCount
= pEngine
->GetParagraphCount();
1626 for (sal_Int32 i
=0; i
<nCount
; i
++)
1627 pEngine
->QuickRemoveCharAttribs( i
, EE_CHAR_WEIGHT
);
1630 ESelection
aSelThis( 0,nPos
, 0,nPos
+1 );
1631 pEngine
->QuickSetAttribs( aSet
, aSelThis
);
1632 ESelection
aSelOther( 0,nOther
, 0,nOther
+1 );
1633 pEngine
->QuickSetAttribs( aSet
, aSelOther
);
1635 // Dummy InsertText for Update and Paint (selection is empty)
1636 pTableView
->InsertText( EMPTY_OUSTRING
, false );
1643 // mark parenthesis right of cursor if it will be overwritten (nAutoPar)
1644 // with different color (COL_LIGHTBLUE) ??
1648 // Remove old highlighting, if no new one is set
1649 if ( bParenthesisShown
&& !bFound
&& pTableView
)
1651 sal_Int32 nCount
= pEngine
->GetParagraphCount();
1652 for (sal_Int32 i
=0; i
<nCount
; i
++)
1653 pTableView
->RemoveCharAttribs( i
, EE_CHAR_WEIGHT
);
1656 bParenthesisShown
= bFound
;
1659 void ScInputHandler::ViewShellGone(ScTabViewShell
* pViewSh
) // Executed synchronously!
1661 if ( pViewSh
== pActiveViewSh
)
1665 pLastPattern
= NULL
;
1668 if ( pViewSh
== pRefViewSh
)
1670 //! The input from the EnterHandler does not arrive anymore
1671 // We end the EditMode anyways
1673 bFormulaMode
= false;
1675 SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
1676 SC_MOD()->SetRefInputHdl(NULL
);
1678 pInputWin
->SetFormulaMode(false);
1679 UpdateAutoCorrFlag();
1682 pActiveViewSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
1684 if ( pActiveViewSh
&& pActiveViewSh
== pViewSh
)
1686 OSL_FAIL("pActiveViewSh is gone");
1687 pActiveViewSh
= NULL
;
1690 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
1691 UpdateRefDevice(); // Don't keep old document's printer as RefDevice
1694 void ScInputHandler::UpdateActiveView()
1696 ImplCreateEditEngine();
1698 // #i20588# Don't rely on focus to find the active edit view. Instead, the
1699 // active pane at the start of editing is now stored (GetEditActivePart).
1700 // GetActiveWin (the currently active pane) fails for ref input across the
1701 // panes of a split view.
1703 Window
* pShellWin
= pActiveViewSh
?
1704 pActiveViewSh
->GetWindowByPos( pActiveViewSh
->GetViewData()->GetEditActivePart() ) :
1707 sal_uInt16 nCount
= pEngine
->GetViewCount();
1710 pTableView
= pEngine
->GetView(0);
1711 for (sal_uInt16 i
=1; i
<nCount
; i
++)
1713 EditView
* pThis
= pEngine
->GetView(i
);
1714 Window
* pWin
= pThis
->GetWindow();
1715 if ( pWin
==pShellWin
)
1722 if (pInputWin
&& eMode
== SC_INPUT_TOP
)
1723 pTopView
= pInputWin
->GetEditView();
1728 void ScInputHandler::StopInputWinEngine( bool bAll
)
1731 pInputWin
->StopEditEngine( bAll
);
1733 pTopView
= NULL
; // invalid now
1736 EditView
* ScInputHandler::GetActiveView()
1739 return pTopView
? pTopView
: pTableView
;
1742 void ScInputHandler::ForgetLastPattern()
1744 pLastPattern
= NULL
;
1745 if ( !pLastState
&& pActiveViewSh
)
1746 pActiveViewSh
->UpdateInputHandler( true ); // Get status again
1748 NotifyChange( pLastState
, true );
1751 void ScInputHandler::UpdateAdjust( sal_Unicode cTyped
)
1753 SvxAdjust eSvxAdjust
;
1754 switch (eAttrAdjust
)
1756 case SVX_HOR_JUSTIFY_STANDARD
:
1758 bool bNumber
= false;
1759 if (cTyped
) // Restarted
1760 bNumber
= (cTyped
>='0' && cTyped
<='9'); // Ony ciphers are numbers
1761 else if ( pActiveViewSh
)
1763 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1764 bNumber
= ( pDoc
->GetCellType( aCursorPos
) == CELLTYPE_VALUE
);
1766 eSvxAdjust
= bNumber
? SVX_ADJUST_RIGHT
: SVX_ADJUST_LEFT
;
1769 case SVX_HOR_JUSTIFY_BLOCK
:
1770 eSvxAdjust
= SVX_ADJUST_BLOCK
;
1772 case SVX_HOR_JUSTIFY_CENTER
:
1773 eSvxAdjust
= SVX_ADJUST_CENTER
;
1775 case SVX_HOR_JUSTIFY_RIGHT
:
1776 eSvxAdjust
= SVX_ADJUST_RIGHT
;
1778 default: // SVX_HOR_JUSTIFY_LEFT
1779 eSvxAdjust
= SVX_ADJUST_LEFT
;
1783 bool bAsianVertical
= pLastPattern
&&
1784 ((const SfxBoolItem
&)pLastPattern
->GetItem( ATTR_STACKED
)).GetValue() &&
1785 ((const SfxBoolItem
&)pLastPattern
->GetItem( ATTR_VERTICAL_ASIAN
)).GetValue();
1786 if ( bAsianVertical
)
1788 // Always edit at top of cell -> LEFT when editing vertically
1789 eSvxAdjust
= SVX_ADJUST_LEFT
;
1792 pEditDefaults
->Put( SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
1793 pEngine
->SetDefaults( *pEditDefaults
);
1795 nEditAdjust
= sal::static_int_cast
<sal_uInt16
>(eSvxAdjust
); //! set at ViewData or with PostEditView
1797 pEngine
->SetVertical( bAsianVertical
);
1800 void ScInputHandler::RemoveAdjust()
1802 // Delete hard alignement attributes
1803 bool bUndo
= pEngine
->IsUndoEnabled();
1805 pEngine
->EnableUndo( false );
1807 // Non-default paragraph attributes (e.g. from clipboard)
1808 // must be turned into character attributes
1809 pEngine
->RemoveParaAttribs();
1812 pEngine
->EnableUndo( true );
1816 void ScInputHandler::RemoveRangeFinder()
1818 // Delete pRangeFindList and colors
1819 pEngine
->SetUpdateMode(false);
1820 sal_Int32 nCount
= pEngine
->GetParagraphCount(); // Could just have been inserted
1821 for (sal_Int32 i
=0; i
<nCount
; i
++)
1822 pEngine
->QuickRemoveCharAttribs( i
, EE_CHAR_COLOR
);
1823 pEngine
->SetUpdateMode(true);
1825 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1826 pActiveView
->ShowCursor( false, true );
1828 DeleteRangeFinder(); // Deletes the list and the labels on the table
1831 bool ScInputHandler::StartTable( sal_Unicode cTyped
, bool bFromCommand
, bool bInputActivated
)
1833 bool bNewTable
= false;
1835 if (bModified
|| !ValidCol(aCursorPos
.Col()))
1840 ImplCreateEditEngine();
1844 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1846 const ScMarkData
& rMark
= pActiveViewSh
->GetViewData()->GetMarkData();
1847 ScEditableTester aTester
;
1848 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
1849 aTester
.TestSelection( pDoc
, rMark
);
1851 aTester
.TestSelectedBlock(
1852 pDoc
, aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Col(), aCursorPos
.Row(), rMark
);
1854 bool bStartInputMode
= true;
1856 if (!aTester
.IsEditable())
1859 // We allow read-only input mode activation regardless
1860 // whether it's part of an array or not or whether explicit cell
1861 // activation is requested (double-click or F2) or a click in input
1863 bool bShowError
= (!bInputActivated
|| aTester
.GetMessageId() != STR_PROTECTIONERR
) &&
1864 !pActiveViewSh
->GetViewData()->GetDocShell()->IsReadOnly();
1867 eMode
= SC_INPUT_NONE
;
1868 StopInputWinEngine( true );
1869 UpdateFormulaMode();
1870 if ( pActiveViewSh
&& ( !bFromCommand
|| !bCommandErrorShown
) )
1872 // Prevent repeated error messages for the same cell from command events
1873 // (for keyboard events, multiple messages are wanted).
1874 // Set the flag before showing the error message because the command handler
1875 // for the next IME command may be called when showing the dialog.
1877 bCommandErrorShown
= true;
1879 pActiveViewSh
->GetActiveWin()->GrabFocus();
1880 pActiveViewSh
->ErrorMessage(aTester
.GetMessageId());
1882 bStartInputMode
= false;
1886 if (bStartInputMode
)
1888 // UpdateMode is enabled again in ScViewData::SetEditEngine (and not needed otherwise)
1889 pEngine
->SetUpdateMode( false );
1891 // Take over attributes in EditEngine
1892 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(),
1895 if (pPattern
!= pLastPattern
)
1898 const SfxItemSet
& rAttrSet
= pPattern
->GetItemSet();
1899 const SfxPoolItem
* pItem
;
1901 if ( SFX_ITEM_SET
== rAttrSet
.GetItemState( ATTR_VALUE_FORMAT
, true, &pItem
) )
1903 sal_uLong nFormat
= ((const SfxUInt32Item
*)pItem
)->GetValue();
1904 bCellHasPercentFormat
= ( NUMBERFORMAT_PERCENT
==
1905 pDoc
->GetFormatTable()->GetType( nFormat
) );
1908 bCellHasPercentFormat
= false; // Default: no percent
1910 // Validity specified?
1911 if ( SFX_ITEM_SET
== rAttrSet
.GetItemState( ATTR_VALIDDATA
, true, &pItem
) )
1912 nValidation
= ((const SfxUInt32Item
*)pItem
)->GetValue();
1916 // EditEngine Defaults
1917 // In no case SetParaAttribs, because the EditEngine might already
1918 // be filled (for Edit cells).
1919 // SetParaAttribs would change the content.
1921 //! The SetDefaults is now (since MUST/src602
1922 //! EditEngine changes) implemented as a SetParaAttribs.
1925 pPattern
->FillEditItemSet( pEditDefaults
);
1926 pEngine
->SetDefaults( *pEditDefaults
);
1927 pLastPattern
= pPattern
;
1928 bLastIsSymbol
= pPattern
->IsSymbolFont();
1930 // Background color must be known for automatic font color.
1931 // For transparent cell background, the document background color must be used.
1933 Color aBackCol
= ((const SvxBrushItem
&)
1934 pPattern
->GetItem( ATTR_BACKGROUND
)).GetColor();
1935 ScModule
* pScMod
= SC_MOD();
1936 if ( aBackCol
.GetTransparency() > 0 ||
1937 Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1938 aBackCol
.SetColor( pScMod
->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
1939 pEngine
->SetBackgroundColor( aBackCol
);
1942 eAttrAdjust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)pPattern
->
1943 GetItem(ATTR_HOR_JUSTIFY
)).GetValue();
1944 if ( eAttrAdjust
== SVX_HOR_JUSTIFY_REPEAT
&&
1945 static_cast<const SfxBoolItem
&>(pPattern
->GetItem(ATTR_LINEBREAK
)).GetValue() )
1947 // #i31843# "repeat" with "line breaks" is treated as default alignement
1948 eAttrAdjust
= SVX_HOR_JUSTIFY_STANDARD
;
1952 // UpdateSpellSettings enables online spelling if needed
1953 // -> also call if attributes are unchanged
1954 UpdateSpellSettings( true ); // uses pLastPattern
1960 pEngine
->SetText(aCurrentText
);
1961 aStr
= aCurrentText
;
1963 aCurrentText
= OUString();
1966 aStr
= GetEditText(pEngine
);
1968 if (aStr
.startsWith("{=") && aStr
.endsWith("}") ) // Matrix formula?
1970 aStr
= aStr
.copy(1, aStr
.getLength() -2);
1971 pEngine
->SetText(aStr
);
1973 pInputWin
->SetTextString(aStr
);
1976 UpdateAdjust( cTyped
);
1978 if ( bAutoComplete
)
1981 if ( !aStr
.isEmpty() && ( aStr
[0] == '=' || aStr
[0] == '+' || aStr
[0] == '-' ) &&
1982 !cTyped
&& !bCreatingFuncView
)
1983 InitRangeFinder(aStr
); // Formula is being edited -> RangeFinder
1985 bNewTable
= true; // -> PostEditView Call
1989 if (!bProtected
&& pInputWin
)
1990 pInputWin
->SetOkCancelMode();
1995 static void lcl_SetTopSelection( EditView
* pEditView
, ESelection
& rSel
)
1997 OSL_ENSURE( rSel
.nStartPara
==0 && rSel
.nEndPara
==0, "SetTopSelection: Para != 0" );
1999 EditEngine
* pEngine
= pEditView
->GetEditEngine();
2000 sal_Int32 nCount
= pEngine
->GetParagraphCount();
2003 sal_Int32 nParLen
= pEngine
->GetTextLen(rSel
.nStartPara
);
2004 while (rSel
.nStartPos
> nParLen
&& rSel
.nStartPara
+1 < nCount
)
2006 rSel
.nStartPos
-= nParLen
+ 1; // Including space from line break
2007 nParLen
= pEngine
->GetTextLen(++rSel
.nStartPara
);
2010 nParLen
= pEngine
->GetTextLen(rSel
.nEndPara
);
2011 while (rSel
.nEndPos
> nParLen
&& rSel
.nEndPara
+1 < nCount
)
2013 rSel
.nEndPos
-= nParLen
+ 1; // Including space from line break
2014 nParLen
= pEngine
->GetTextLen(++rSel
.nEndPara
);
2018 ESelection aSel
= pEditView
->GetSelection();
2020 if ( rSel
.nStartPara
!= aSel
.nStartPara
|| rSel
.nEndPara
!= aSel
.nEndPara
2021 || rSel
.nStartPos
!= aSel
.nStartPos
|| rSel
.nEndPos
!= aSel
.nEndPos
)
2022 pEditView
->SetSelection( rSel
);
2025 void ScInputHandler::SyncViews( EditView
* pSourceView
)
2029 bool bSelectionForTopView
= false;
2030 if (pTopView
&& pTopView
!= pSourceView
)
2031 bSelectionForTopView
= true;
2032 bool bSelectionForTableView
= false;
2033 if (pTableView
&& pTableView
!= pSourceView
)
2034 bSelectionForTableView
= true;
2035 if (bSelectionForTopView
|| bSelectionForTableView
)
2037 ESelection
aSel(pSourceView
->GetSelection());
2038 if (bSelectionForTopView
)
2039 pTopView
->SetSelection(aSel
);
2040 if (bSelectionForTableView
)
2041 lcl_SetTopSelection(pTableView
, aSel
);
2044 // Only sync selection from topView if we are actually editiing there
2045 else if (pTopView
&& pTableView
)
2047 ESelection
aSel(pTopView
->GetSelection());
2048 lcl_SetTopSelection( pTableView
, aSel
);
2052 IMPL_LINK_NOARG(ScInputHandler
, ModifyHdl
)
2054 if ( !bInOwnChange
&& ( eMode
==SC_INPUT_TYPE
|| eMode
==SC_INPUT_TABLE
) &&
2055 pEngine
&& pEngine
->GetUpdateMode() && pInputWin
)
2057 // Update input line from ModifyHdl for changes that are not
2058 // wrapped by DataChanging/DataChanged calls (like Drag&Drop)
2060 if ( pInputWin
->IsMultiLineInput() )
2061 aText
= ScEditUtil::GetMultilineString(*pEngine
);
2063 aText
= GetEditText(pEngine
);
2064 lcl_RemoveTabs(aText
);
2065 pInputWin
->SetTextString(aText
);
2071 * @return true means new view created
2073 bool ScInputHandler::DataChanging( sal_Unicode cTyped
, bool bFromCommand
)
2076 pActiveViewSh
->GetViewData()->SetPasteMode( SC_PASTE_NONE
);
2077 bInOwnChange
= true; // disable ModifyHdl (reset in DataChanged)
2079 if ( eMode
== SC_INPUT_NONE
)
2080 return StartTable( cTyped
, bFromCommand
, false );
2085 void ScInputHandler::DataChanged( bool bFromTopNotify
, bool bSetModified
)
2087 ImplCreateEditEngine();
2089 if (eMode
==SC_INPUT_NONE
)
2090 eMode
= SC_INPUT_TYPE
;
2092 if ( eMode
== SC_INPUT_TOP
&& pTopView
&& !bFromTopNotify
)
2094 // table EditEngine is formatted below, input line needs formatting after paste
2095 // #i20282# not when called from the input line's modify handler
2096 pTopView
->GetEditEngine()->QuickFormatDoc( true );
2098 // #i23720# QuickFormatDoc hides the cursor, but can't show it again because it
2099 // can't safely access the EditEngine's current view, so the cursor has to be
2100 // shown again here.
2101 pTopView
->ShowCursor();
2108 if ( pRangeFindList
&& !bInRangeUpdate
)
2109 RemoveRangeFinder(); // Delete attributes and labels
2111 UpdateParenthesis(); // Highlight parentheses anew
2113 if (eMode
==SC_INPUT_TYPE
|| eMode
==SC_INPUT_TABLE
)
2116 if ( pInputWin
&& pInputWin
->IsMultiLineInput() )
2117 aText
= ScEditUtil::GetMultilineString(*pEngine
);
2119 aText
= GetEditText(pEngine
);
2120 lcl_RemoveTabs(aText
);
2123 pInputWin
->SetTextString( aText
);
2126 // If the cursor is before the end of a paragraph, parts are being pushed to
2127 // the right (independently from the eMode) -> Adapt View!
2128 // If the cursor is at the end, the StatusHandler of the ViewData is sufficient.
2130 // First make sure the status handler is called now if the cursor
2131 // is outside the visible area
2132 pEngine
->QuickFormatDoc();
2134 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2135 if (pActiveView
&& pActiveViewSh
)
2137 ScViewData
* pViewData
= pActiveViewSh
->GetViewData();
2139 bool bNeedGrow
= ( nEditAdjust
!= SVX_ADJUST_LEFT
); // Always right-aligned
2142 // Cursor before the end?
2143 ESelection aSel
= pActiveView
->GetSelection();
2145 bNeedGrow
= ( aSel
.nEndPos
!= pEngine
->GetTextLen(aSel
.nEndPara
) );
2149 bNeedGrow
= pViewData
->GetDocument()->IsLayoutRTL( pViewData
->GetTabNo() );
2153 // Adjust inplace view
2154 pViewData
->EditGrowY();
2155 pViewData
->EditGrowX();
2159 UpdateFormulaMode();
2160 bTextValid
= false; // Changes only in the EditEngine
2161 bInOwnChange
= false;
2164 void ScInputHandler::UpdateFormulaMode()
2166 SfxApplication
* pSfxApp
= SFX_APP();
2168 bool bIsFormula
= !bProtected
&& pEngine
->GetParagraphCount() == 1;
2171 const OUString
& rText
= pEngine
->GetText(0);
2172 bIsFormula
= !rText
.isEmpty() &&
2173 (rText
[0] == '=' || rText
[0] == '+' || rText
[0] == '-');
2180 bFormulaMode
= true;
2181 pRefViewSh
= pActiveViewSh
;
2182 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2183 SC_MOD()->SetRefInputHdl(this);
2185 pInputWin
->SetFormulaMode(true);
2187 if ( bAutoComplete
)
2190 UpdateParenthesis();
2191 UpdateAutoCorrFlag();
2199 bFormulaMode
= false;
2201 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2202 SC_MOD()->SetRefInputHdl(NULL
);
2204 pInputWin
->SetFormulaMode(false);
2205 UpdateAutoCorrFlag();
2210 void ScInputHandler::ShowRefFrame()
2212 // Modifying pActiveViewSh here would interfere with the bInEnterHandler / bRepeat
2213 // checks in NotifyChange, and lead to keeping the wrong value in pActiveViewSh.
2214 // A local variable is used instead.
2215 ScTabViewShell
* pVisibleSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
2216 if ( pRefViewSh
&& pRefViewSh
!= pVisibleSh
)
2218 bool bFound
= false;
2219 SfxViewFrame
* pRefFrame
= pRefViewSh
->GetViewFrame();
2220 SfxViewFrame
* pOneFrame
= SfxViewFrame::GetFirst();
2221 while ( pOneFrame
&& !bFound
)
2223 if ( pOneFrame
== pRefFrame
)
2225 pOneFrame
= SfxViewFrame::GetNext( *pOneFrame
);
2230 // We count on Activate working synchronously here
2231 // (pActiveViewSh is set while doing so)
2232 pRefViewSh
->SetActive(); // Appear and SetViewFrame
2234 // pLastState is set correctly in the NotifyChange from the Activate
2238 OSL_FAIL("ViewFrame for reference input is not here anymore");
2243 void ScInputHandler::RemoveSelection()
2245 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2249 ESelection aSel
= pActiveView
->GetSelection();
2250 aSel
.nStartPara
= aSel
.nEndPara
;
2251 aSel
.nStartPos
= aSel
.nEndPos
;
2253 pTableView
->SetSelection( aSel
);
2255 pTopView
->SetSelection( aSel
);
2258 void ScInputHandler::InvalidateAttribs()
2260 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
2263 SfxBindings
& rBindings
= pViewFrm
->GetBindings();
2265 rBindings
.Invalidate( SID_ATTR_CHAR_FONT
);
2266 rBindings
.Invalidate( SID_ATTR_CHAR_FONTHEIGHT
);
2267 rBindings
.Invalidate( SID_ATTR_CHAR_COLOR
);
2269 rBindings
.Invalidate( SID_ATTR_CHAR_WEIGHT
);
2270 rBindings
.Invalidate( SID_ATTR_CHAR_POSTURE
);
2271 rBindings
.Invalidate( SID_ATTR_CHAR_UNDERLINE
);
2272 rBindings
.Invalidate( SID_ULINE_VAL_NONE
);
2273 rBindings
.Invalidate( SID_ULINE_VAL_SINGLE
);
2274 rBindings
.Invalidate( SID_ULINE_VAL_DOUBLE
);
2275 rBindings
.Invalidate( SID_ULINE_VAL_DOTTED
);
2277 rBindings
.Invalidate( SID_HYPERLINK_GETLINK
);
2279 rBindings
.Invalidate( SID_ATTR_CHAR_KERNING
);
2280 rBindings
.Invalidate( SID_SET_SUPER_SCRIPT
);
2281 rBindings
.Invalidate( SID_SET_SUB_SCRIPT
);
2282 rBindings
.Invalidate( SID_ATTR_CHAR_STRIKEOUT
);
2283 rBindings
.Invalidate( SID_ATTR_CHAR_SHADOWED
);
2288 // --------------- public methods --------------------------------------------
2291 void ScInputHandler::SetMode( ScInputMode eNewMode
, const OUString
* pInitText
)
2293 if ( eMode
== eNewMode
)
2296 ImplCreateEditEngine();
2300 eMode
= SC_INPUT_NONE
;
2301 StopInputWinEngine( true );
2303 pActiveViewSh
->GetActiveWin()->GrabFocus();
2307 if (eNewMode
!= SC_INPUT_NONE
&& pActiveViewSh
)
2308 // Disable paste mode when edit mode starts.
2309 pActiveViewSh
->GetViewData()->SetPasteMode( SC_PASTE_NONE
);
2311 bInOwnChange
= true; // disable ModifyHdl (reset below)
2313 ScInputMode eOldMode
= eMode
;
2315 if (eOldMode
== SC_INPUT_TOP
&& eNewMode
!= eOldMode
)
2316 StopInputWinEngine( false );
2318 if (eMode
==SC_INPUT_TOP
|| eMode
==SC_INPUT_TABLE
)
2320 if (eOldMode
== SC_INPUT_NONE
) // not if switching between modes
2322 if (StartTable(0, false, eMode
== SC_INPUT_TABLE
))
2325 pActiveViewSh
->GetViewData()->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
2331 pEngine
->SetText(*pInitText
);
2335 sal_Int32 nPara
= pEngine
->GetParagraphCount()-1;
2336 sal_Int32 nLen
= pEngine
->GetText(nPara
).getLength();
2337 sal_uInt16 nCount
= pEngine
->GetViewCount();
2339 for (sal_uInt16 i
=0; i
<nCount
; i
++)
2341 if ( eMode
== SC_INPUT_TABLE
&& eOldMode
== SC_INPUT_TOP
)
2347 pEngine
->GetView(i
)->
2348 SetSelection( ESelection( nPara
, nLen
, nPara
, nLen
) );
2350 pEngine
->GetView(i
)->ShowCursor(false);
2355 if (eMode
==SC_INPUT_TABLE
|| eMode
==SC_INPUT_TYPE
)
2358 pTableView
->SetEditEngineUpdateMode(true);
2363 pTopView
->SetEditEngineUpdateMode(true);
2366 if (eNewMode
!= eOldMode
)
2367 UpdateFormulaMode();
2369 bInOwnChange
= false;
2373 * @return true if rString only contains digits (no autocorrect then)
2375 static bool lcl_IsNumber(const OUString
& rString
)
2377 sal_Int32 nLen
= rString
.getLength();
2378 for (sal_Int32 i
=0; i
<nLen
; i
++)
2380 sal_Unicode c
= rString
[i
];
2381 if ( c
< '0' || c
> '9' )
2387 static void lcl_SelectionToEnd( EditView
* pView
)
2391 EditEngine
* pEngine
= pView
->GetEditEngine();
2392 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
2395 ESelection
aSel( nParCnt
-1, pEngine
->GetTextLen(nParCnt
-1) ); // empty selection, cursor at the end
2396 pView
->SetSelection( aSel
);
2400 void ScInputHandler::EnterHandler( sal_uInt8 nBlockMode
)
2402 // Macro calls for validity can cause a lot of problems, so inhibit
2403 // nested calls of EnterHandler().
2404 if (bInEnterHandler
) return;
2405 bInEnterHandler
= true;
2406 bInOwnChange
= true; // disable ModifyHdl (reset below)
2408 ImplCreateEditEngine();
2410 bool bMatrix
= ( nBlockMode
== SC_ENTER_MATRIX
);
2412 SfxApplication
* pSfxApp
= SFX_APP();
2413 EditTextObject
* pObject
= NULL
;
2414 ScPatternAttr
* pCellAttrs
= NULL
;
2415 bool bForget
= false; // Remove due to validity?
2417 OUString aString
= GetEditText(pEngine
);
2418 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2419 if (bModified
&& pActiveView
&& !aString
.isEmpty() && !lcl_IsNumber(aString
))
2421 if (pColumnData
&& miAutoPosColumn
!= pColumnData
->end())
2423 // #i47125# If AutoInput appended something, do the final AutoCorrect
2424 // with the cursor at the end of the input.
2425 lcl_SelectionToEnd(pTopView
);
2426 lcl_SelectionToEnd(pTableView
);
2429 Window
* pFrameWin
= pActiveViewSh
? pActiveViewSh
->GetFrameWin() : NULL
;
2432 pTopView
->CompleteAutoCorrect(); // CompleteAutoCorrect for both Views
2434 pTableView
->CompleteAutoCorrect(pFrameWin
);
2435 aString
= GetEditText(pEngine
);
2437 lcl_RemoveTabs(aString
);
2439 // Test if valid (always with simple string)
2440 if ( bModified
&& nValidation
&& pActiveViewSh
)
2442 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2443 const ScValidationData
* pData
= pDoc
->GetValidationEntry( nValidation
);
2444 if (pData
&& pData
->HasErrMsg())
2446 // #i67990# don't use pLastPattern in EnterHandler
2447 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2448 bool bOk
= pData
->IsDataValid( aString
, *pPattern
, aCursorPos
);
2452 if ( pActiveViewSh
) // If it came from MouseButtonDown
2453 pActiveViewSh
->StopMarking(); // (the InfoBox consumes the MouseButtonUp)
2455 //FIXME: We still run into problems if the input is triggered by activating another View
2456 Window
* pParent
= Application::GetDefDialogParent();
2457 if ( pData
->DoError( pParent
, aString
, aCursorPos
) )
2458 bForget
= true; // Do not take over input
2463 // Check for input into DataPilot table
2464 if ( bModified
&& pActiveViewSh
&& !bForget
)
2466 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2467 ScDPObject
* pDPObj
= pDoc
->GetDPAtCursor( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2470 // Any input within the DataPilot table is either a valid renaming
2471 // or an invalid action - normal cell input is always aborted
2472 pActiveViewSh
->DataPilotInput( aCursorPos
, aString
);
2477 std::vector
<editeng::MisspellRanges
> aMisspellRanges
;
2478 pEngine
->CompleteOnlineSpelling();
2479 bool bSpellErrors
= !bFormulaMode
&& pEngine
->HasOnlineSpellErrors();
2482 // #i3820# If the spell checker flags numerical input as error,
2483 // it still has to be treated as number, not EditEngine object.
2484 if ( pActiveViewSh
)
2486 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2487 // #i67990# don't use pLastPattern in EnterHandler
2488 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2491 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
2492 // without conditional format, as in ScColumn::SetString
2493 sal_uInt32 nFormat
= pPattern
->GetNumberFormat( pFormatter
);
2495 if ( pFormatter
->IsNumberFormat( aString
, nFormat
, nVal
) )
2497 bSpellErrors
= false; // ignore the spelling errors
2503 // After RemoveAdjust, the EditView must not be repainted (has wrong font size etc).
2504 // SetUpdateMode must come after CompleteOnlineSpelling.
2505 // The view is hidden in any case below (Broadcast).
2506 pEngine
->SetUpdateMode( false );
2508 if ( bModified
&& !bForget
) // What is being entered (text/object)?
2510 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
2514 bool bUniformAttribs
= true;
2515 SfxItemSet aPara1Attribs
= pEngine
->GetAttribs(0, 0, pEngine
->GetTextLen(0));
2516 for (sal_Int32 nPara
= 1; nPara
< nParCnt
; ++nPara
)
2518 SfxItemSet aPara2Attribs
= pEngine
->GetAttribs(nPara
, 0, pEngine
->GetTextLen(nPara
));
2519 if (!(aPara1Attribs
== aPara2Attribs
))
2521 // Paragraph format different from that of the 1st paragraph.
2522 bUniformAttribs
= false;
2527 ESelection
aSel( 0, 0, nParCnt
-1, pEngine
->GetTextLen(nParCnt
-1) );
2528 SfxItemSet aOldAttribs
= pEngine
->GetAttribs( aSel
);
2529 const SfxPoolItem
* pItem
= NULL
;
2531 // Find common (cell) attributes before RemoveAdjust
2532 if ( pActiveViewSh
&& bUniformAttribs
)
2534 SfxItemSet
* pCommonAttrs
= NULL
;
2535 for (sal_uInt16 nId
= EE_CHAR_START
; nId
<= EE_CHAR_END
; nId
++)
2537 SfxItemState eState
= aOldAttribs
.GetItemState( nId
, false, &pItem
);
2538 if ( eState
== SFX_ITEM_SET
&&
2539 nId
!= EE_CHAR_ESCAPEMENT
&& nId
!= EE_CHAR_PAIRKERNING
&&
2540 nId
!= EE_CHAR_KERNING
&& nId
!= EE_CHAR_XMLATTRIBS
&&
2541 *pItem
!= pEditDefaults
->Get(nId
) )
2543 if ( !pCommonAttrs
)
2544 pCommonAttrs
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
2545 pCommonAttrs
->Put( *pItem
);
2551 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2552 pCellAttrs
= new ScPatternAttr( pDoc
->GetPool() );
2553 pCellAttrs
->GetFromEditItemSet( pCommonAttrs
);
2554 delete pCommonAttrs
;
2558 // Clear ParaAttribs (including adjustment)
2561 bool bAttrib
= false; // Formatting present?
2563 // check if EditObject is needed
2568 for (sal_uInt16 nId
= EE_CHAR_START
; nId
<= EE_CHAR_END
&& !bAttrib
; nId
++)
2570 SfxItemState eState
= aOldAttribs
.GetItemState( nId
, false, &pItem
);
2571 if (eState
== SFX_ITEM_DONTCARE
)
2573 else if (eState
== SFX_ITEM_SET
)
2575 // Keep same items in EditEngine as in ScEditAttrTester
2576 if ( nId
== EE_CHAR_ESCAPEMENT
|| nId
== EE_CHAR_PAIRKERNING
||
2577 nId
== EE_CHAR_KERNING
|| nId
== EE_CHAR_XMLATTRIBS
)
2579 if ( *pItem
!= pEditDefaults
->Get(nId
) )
2586 SfxItemState eFieldState
= aOldAttribs
.GetItemState( EE_FEATURE_FIELD
, false );
2587 if ( eFieldState
== SFX_ITEM_DONTCARE
|| eFieldState
== SFX_ITEM_SET
)
2590 // Not converted characters?
2591 SfxItemState eConvState
= aOldAttribs
.GetItemState( EE_FEATURE_NOTCONV
, false );
2592 if ( eConvState
== SFX_ITEM_DONTCARE
|| eConvState
== SFX_ITEM_SET
)
2595 // Always recognize formulas as formulas
2596 // We still need the preceding test due to cell attributes
2600 pEngine
->GetAllMisspellRanges(aMisspellRanges
);
2607 pEngine
->ClearSpellErrors();
2608 pObject
= pEngine
->CreateTextObject();
2610 else if (bAutoComplete
) // Adjust Upper/Lower case
2612 // Perform case-matching only when the typed text is partial.
2613 if (pColumnData
&& aAutoSearch
.getLength() < aString
.getLength())
2614 aString
= getExactMatch(*pColumnData
, aString
);
2618 // Don't rely on ShowRefFrame switching the active view synchronously
2619 // execute the function directly on the correct view's bindings instead
2620 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2621 ScTabViewShell
* pExecuteSh
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
2629 pExecuteSh
->SetTabNo(aCursorPos
.Tab());
2630 pExecuteSh
->ActiveGrabFocus();
2633 bFormulaMode
= false;
2634 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2635 SC_MOD()->SetRefInputHdl(NULL
);
2637 pInputWin
->SetFormulaMode(false);
2638 UpdateAutoCorrFlag();
2640 pRefViewSh
= NULL
; // Also without FormulaMode due to FunctionsAutoPilot
2641 DeleteRangeFinder();
2644 bool bOldMod
= bModified
;
2648 eMode
= SC_INPUT_NONE
;
2649 StopInputWinEngine(true);
2651 // Text input (through number formats) or ApplySelectionPattern modify
2652 // the cell's attributes, so pLastPattern is no longer valid
2653 pLastPattern
= NULL
;
2655 if (bOldMod
&& !bProtected
&& !bForget
)
2657 // No typographic quotes in formulas
2658 if (aString
.startsWith("="))
2660 SvxAutoCorrect
* pAuto
= SvxAutoCorrCfg::Get().GetAutoCorrect();
2663 OUString
aReplace(pAuto
->GetStartDoubleQuote());
2664 if( aReplace
.isEmpty() )
2665 aReplace
= ScGlobal::pLocaleData
->getDoubleQuotationMarkStart();
2666 if( aReplace
!= "\"" )
2667 aString
= aString
.replaceAll( aReplace
, "\"" );
2669 aReplace
= OUString(pAuto
->GetEndDoubleQuote());
2670 if( aReplace
.isEmpty() )
2671 aReplace
= ScGlobal::pLocaleData
->getDoubleQuotationMarkEnd();
2672 if( aReplace
!= "\"" )
2673 aString
= aString
.replaceAll( aReplace
, "\"" );
2675 aReplace
= OUString(pAuto
->GetStartSingleQuote());
2676 if( aReplace
.isEmpty() )
2677 aReplace
= ScGlobal::pLocaleData
->getQuotationMarkStart();
2678 if( aReplace
!= "'" )
2679 aString
= aString
.replaceAll( aReplace
, "'" );
2681 aReplace
= OUString(pAuto
->GetEndSingleQuote());
2682 if( aReplace
.isEmpty() )
2683 aReplace
= ScGlobal::pLocaleData
->getQuotationMarkEnd();
2684 if( aReplace
!= "'" )
2685 aString
= aString
.replaceAll( aReplace
, "'");
2689 pSfxApp
->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW_NOPAINT
) );
2693 SfxBindings
& rBindings
= pExecuteSh
->GetViewFrame()->GetBindings();
2695 sal_uInt16 nId
= FID_INPUTLINE_ENTER
;
2696 if ( nBlockMode
== SC_ENTER_BLOCK
)
2697 nId
= FID_INPUTLINE_BLOCK
;
2698 else if ( nBlockMode
== SC_ENTER_MATRIX
)
2699 nId
= FID_INPUTLINE_MATRIX
;
2701 ScInputStatusItem
aItem( FID_INPUTLINE_STATUS
,
2702 aCursorPos
, aCursorPos
, aCursorPos
,
2705 if (!aMisspellRanges
.empty())
2706 aItem
.SetMisspellRanges(&aMisspellRanges
);
2708 const SfxPoolItem
* aArgs
[2];
2711 rBindings
.Execute( nId
, aArgs
);
2714 delete pLastState
; // pLastState still contains the old text
2718 pSfxApp
->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW
) );
2720 if ( bOldMod
&& pExecuteSh
&& pCellAttrs
&& !bForget
)
2722 // Combine with input?
2723 pExecuteSh
->ApplySelectionPattern( *pCellAttrs
, true, true );
2724 pExecuteSh
->AdjustBlockHeight();
2733 nFormSelStart
= nFormSelEnd
= 0;
2734 aFormText
= OUString();
2736 bInOwnChange
= false;
2737 bInEnterHandler
= false;
2740 void ScInputHandler::CancelHandler()
2742 bInOwnChange
= true; // Also without FormulaMode due to FunctionsAutoPilot
2744 ImplCreateEditEngine();
2748 // Don't rely on ShowRefFrame switching the active view synchronously
2749 // execute the function directly on the correct view's bindings instead
2750 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2751 ScTabViewShell
* pExecuteSh
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
2758 pExecuteSh
->SetTabNo(aCursorPos
.Tab());
2759 pExecuteSh
->ActiveGrabFocus();
2761 bFormulaMode
= false;
2762 SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2763 SC_MOD()->SetRefInputHdl(NULL
);
2765 pInputWin
->SetFormulaMode(false);
2766 UpdateAutoCorrFlag();
2768 pRefViewSh
= NULL
; // Also without FormulaMode due to FunctionsAutoPilot
2769 DeleteRangeFinder();
2772 eMode
= SC_INPUT_NONE
;
2773 StopInputWinEngine( true );
2775 pExecuteSh
->StopEditShell();
2777 aCursorPos
.Set(MAXCOL
+1,0,0); // Invalid flag
2778 pEngine
->SetText(OUString());
2780 if ( !pLastState
&& pExecuteSh
)
2781 pExecuteSh
->UpdateInputHandler( true ); // Update status again
2783 NotifyChange( pLastState
, true );
2785 nFormSelStart
= nFormSelEnd
= 0;
2786 aFormText
= OUString();
2788 bInOwnChange
= false;
2791 bool ScInputHandler::IsModalMode( SfxObjectShell
* pDocSh
)
2793 // References to unnamed document; that doesn't work
2794 return bFormulaMode
&& pRefViewSh
2795 && pRefViewSh
->GetViewData()->GetDocument()->GetDocumentShell() != pDocSh
2796 && !pDocSh
->HasName();
2799 void ScInputHandler::AddRefEntry()
2801 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
2803 if (!pTableView
&& !pTopView
)
2804 return; // E.g. FillMode
2806 DataChanging(); // Cannot be new
2810 pTableView
->InsertText( OUString(cSep
), false );
2812 pTopView
->InsertText( OUString(cSep
), false );
2817 void ScInputHandler::SetReference( const ScRange
& rRef
, ScDocument
* pDoc
)
2821 bool bOtherDoc
= ( pRefViewSh
&&
2822 pRefViewSh
->GetViewData()->GetDocument() != pDoc
);
2824 if (!pDoc
->GetDocumentShell()->HasName())
2826 // References to unnamed document; that doesn't work
2827 // SetReference should not be called, then
2832 if (!pTableView
&& !pTopView
)
2833 return; // E.g. FillMode
2835 // Never overwrite the "="!
2836 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2837 ESelection aSel
= pActiveView
->GetSelection();
2839 if ( aSel
.nStartPara
== 0 && aSel
.nStartPos
== 0 )
2842 DataChanging(); // Cannot be new
2844 // Turn around selection if backwards (TODO: Do we really need to do that?)
2847 ESelection aTabSel
= pTableView
->GetSelection();
2848 if (aTabSel
.nStartPos
> aTabSel
.nEndPos
&& aTabSel
.nStartPara
== aTabSel
.nEndPara
)
2851 pTableView
->SetSelection(aTabSel
);
2856 ESelection aTopSel
= pTopView
->GetSelection();
2857 if (aTopSel
.nStartPos
> aTopSel
.nEndPos
&& aTopSel
.nStartPara
== aTopSel
.nEndPara
)
2860 pTopView
->SetSelection(aTopSel
);
2864 // Create string from reference
2866 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
2869 // Reference to other document
2870 OSL_ENSURE(rRef
.aStart
.Tab()==rRef
.aEnd
.Tab(), "nStartTab!=nEndTab");
2872 OUString
aTmp(rRef
.Format(SCA_VALID
|SCA_TAB_3D
, pDoc
, aAddrDetails
)); // Always 3D
2874 SfxObjectShell
* pObjSh
= pDoc
->GetDocumentShell();
2875 // #i75893# convert escaped URL of the document to something user friendly
2876 OUString aFileName
= pObjSh
->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS
);
2878 switch(aAddrDetails
.eConv
)
2880 case formula::FormulaGrammar::CONV_XL_A1
:
2881 case formula::FormulaGrammar::CONV_XL_OOX
:
2882 case formula::FormulaGrammar::CONV_XL_R1C1
:
2884 aRefStr
+= aFileName
;
2887 case formula::FormulaGrammar::CONV_OOO
:
2890 aRefStr
+= aFileName
;
2898 if ( rRef
.aStart
.Tab() != aCursorPos
.Tab() ||
2899 rRef
.aStart
.Tab() != rRef
.aEnd
.Tab() )
2900 aRefStr
= rRef
.Format(SCA_VALID
|SCA_TAB_3D
, pDoc
, aAddrDetails
);
2902 aRefStr
= rRef
.Format(SCA_VALID
, pDoc
, aAddrDetails
);
2905 if (pTableView
|| pTopView
)
2908 pTableView
->InsertText( aRefStr
, true );
2910 pTopView
->InsertText( aRefStr
, true );
2918 void ScInputHandler::InsertFunction( const OUString
& rFuncName
, bool bAddPar
)
2920 if ( eMode
== SC_INPUT_NONE
)
2922 OSL_FAIL("InsertFunction, nicht im Eingabemodus");
2927 if (!pTableView
&& !pTopView
)
2928 return; // E.g. FillMode
2930 DataChanging(); // Cannot be new
2932 OUString aText
= rFuncName
;
2938 pTableView
->InsertText( aText
, false );
2941 ESelection aSel
= pTableView
->GetSelection();
2944 pTableView
->SetSelection(aSel
);
2949 pTopView
->InsertText( aText
, false );
2952 ESelection aSel
= pTopView
->GetSelection();
2955 pTopView
->SetSelection(aSel
);
2965 void ScInputHandler::ClearText()
2967 if ( eMode
== SC_INPUT_NONE
)
2969 OSL_FAIL("ClearText, nicht im Eingabemodus");
2974 if (!pTableView
&& !pTopView
)
2975 return; // E.g. FillMode
2977 DataChanging(); // Cannot be new
2982 pTableView
->GetEditEngine()->SetText( aEmpty
);
2983 pTableView
->SetSelection( ESelection(0,0, 0,0) );
2987 pTopView
->GetEditEngine()->SetText( aEmpty
);
2988 pTopView
->SetSelection( ESelection(0,0, 0,0) );
2994 bool ScInputHandler::KeyInput( const KeyEvent
& rKEvt
, bool bStartEdit
/* = false */ )
2998 bAutoComplete
= SC_MOD()->GetAppOptions().GetAutoComplete();
3002 KeyCode aCode
= rKEvt
.GetKeyCode();
3003 sal_uInt16 nModi
= aCode
.GetModifier();
3004 bool bShift
= aCode
.IsShift();
3005 bool bControl
= aCode
.IsMod1();
3006 bool bAlt
= aCode
.IsMod2();
3007 sal_uInt16 nCode
= aCode
.GetCode();
3008 sal_Unicode nChar
= rKEvt
.GetCharCode();
3010 if (bAlt
&& !bControl
&& nCode
!= KEY_RETURN
)
3011 // Alt-Return and Alt-Ctrl-* are accepted. Everything else with ALT are not.
3014 if (!bControl
&& nCode
== KEY_TAB
)
3016 // Normal TAB moves the cursor right.
3020 pActiveViewSh
->FindNextUnprot( bShift
);
3024 bool bInputLine
= ( eMode
==SC_INPUT_TOP
);
3028 bool bDoEnter
= false;
3033 if (bControl
&& !bShift
&& ( !bInputLine
|| ( pInputWin
&& pInputWin
->IsMultiLineInput() ) ) )
3035 else if (nModi
== 0 && nTipVisible
&& pFormulaData
&& miAutoPosFormula
!= pFormulaData
->end())
3037 PasteFunctionData();
3040 else if ( nModi
== 0 && nTipVisible
&& !aManualTip
.isEmpty() )
3047 sal_uInt8 nMode
= SC_ENTER_NORMAL
;
3048 if ( bShift
&& bControl
)
3049 nMode
= SC_ENTER_MATRIX
;
3051 nMode
= SC_ENTER_BLOCK
;
3052 EnterHandler( nMode
);
3055 pActiveViewSh
->MoveCursorEnter( bShift
&& !bControl
);
3061 if (bControl
&& !bAlt
)
3063 if (pFormulaData
&& nTipVisible
&& miAutoPosFormula
!= pFormulaData
->end())
3066 NextFormulaEntry( bShift
);
3069 else if (pColumnData
&& bUseTab
&& miAutoPosColumn
!= pColumnData
->end())
3071 // Iterate through AutoInput entries
3072 NextAutoEntry( bShift
);
3083 else if( nTipVisibleSec
)
3088 else if (eMode
!= SC_INPUT_NONE
)
3097 if ( !bShift
&& !bControl
&& !bAlt
&& eMode
== SC_INPUT_TABLE
)
3099 eMode
= SC_INPUT_TYPE
;
3105 // Only execute cursor keys if already in EditMode
3106 // E.g. due to Shift-Ctrl-PageDn (not defined as an accelerator)
3107 bool bCursorKey
= EditEngine::DoesKeyMoveCursor(rKEvt
);
3108 bool bInsKey
= ( nCode
== KEY_INSERT
&& !nModi
); // Treat Insert like Cursorkeys
3109 if ( !bUsed
&& !bSkip
&& ( bDoEnter
|| EditEngine::DoesKeyChangeText(rKEvt
) ||
3110 ( eMode
!= SC_INPUT_NONE
&& ( bCursorKey
|| bInsKey
) ) ) )
3122 bool bNewView
= DataChanging( nChar
);
3124 if (bProtected
) // Protected cell?
3125 bUsed
= true; // Don't forward KeyEvent
3126 else // Changes allowed
3128 if (bNewView
) // Create anew
3131 pActiveViewSh
->GetViewData()->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3133 if (eMode
==SC_INPUT_NONE
)
3134 if (pTableView
|| pTopView
)
3138 if ( bStartEdit
&& bCellHasPercentFormat
&& ((nChar
>= '0' && nChar
<= '9') || nChar
== '-') )
3143 pTableView
->GetEditEngine()->SetText( aStrLoP
);
3144 if ( !aStrLoP
.isEmpty() )
3145 pTableView
->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3147 // Don't call SetSelection if the string is empty anyway,
3148 // to avoid breaking the bInitial handling in ScViewData::EditGrowY
3152 pTopView
->GetEditEngine()->SetText( aStrLoP
);
3153 if ( !aStrLoP
.isEmpty() )
3154 pTopView
->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3160 if (pTableView
|| pTopView
)
3165 if( pTableView
->PostKeyEvent( KeyEvent( CHAR_CR
, KeyCode(KEY_RETURN
) ) ) )
3168 if( pTopView
->PostKeyEvent( KeyEvent( CHAR_CR
, KeyCode(KEY_RETURN
) ) ) )
3171 else if ( nAutoPar
&& nChar
== ')' && CursorAtClosingPar() )
3180 Window
* pFrameWin
= pActiveViewSh
? pActiveViewSh
->GetFrameWin() : NULL
;
3181 if ( pTableView
->PostKeyEvent( rKEvt
, pFrameWin
) )
3185 if ( pTopView
->PostKeyEvent( rKEvt
) )
3190 if ( bUsed
&& bAutoComplete
)
3194 miAutoPosFormula
= pFormulaData
->end(); // do not search further
3196 miAutoPosColumn
= pColumnData
->end();
3198 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
3199 if ( nChar
&& nChar
!= 8 && nChar
!= 127 && // no 'backspace', no 'delete'
3200 KEYFUNC_CUT
!= eFunc
) // and no 'CTRL-X'
3209 // When the selection is changed manually or an opening parenthesis
3210 // is typed, stop overwriting parentheses
3211 if ( bUsed
&& nChar
== '(' )
3214 if ( KEY_INSERT
== nCode
)
3216 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
3218 pViewFrm
->GetBindings().Invalidate( SID_ATTR_INSERT
);
3220 if( bUsed
&& bFormulaMode
&& ( bCursorKey
|| bInsKey
|| nCode
== KEY_DELETE
|| nCode
== KEY_BACKSPACE
) )
3226 // #i114511# don't count cursor keys as modification
3227 bool bSetModified
= !bCursorKey
;
3228 DataChanged(false, bSetModified
); // also calls UpdateParenthesis()
3229 InvalidateAttribs(); //! in DataChanged?
3233 if (pTopView
&& eMode
!= SC_INPUT_NONE
)
3239 bool ScInputHandler::InputCommand( const CommandEvent
& rCEvt
, bool bForce
)
3243 if ( rCEvt
.GetCommand() == COMMAND_CURSORPOS
)
3245 // For COMMAND_CURSORPOS, do as little as possible, because
3246 // with remote VCL, even a ShowCursor will generate another event.
3247 if ( eMode
!= SC_INPUT_NONE
)
3250 if (pTableView
|| pTopView
)
3253 pTableView
->Command( rCEvt
);
3254 else if (pTopView
) // call only once
3255 pTopView
->Command( rCEvt
);
3260 else if ( rCEvt
.GetCommand() == COMMAND_QUERYCHARPOSITION
)
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
);
3277 if ( bForce
|| eMode
!= SC_INPUT_NONE
)
3281 bAutoComplete
= SC_MOD()->GetAppOptions().GetAutoComplete();
3295 bool bNewView
= DataChanging( 0, true );
3297 if (bProtected
) // cell protected
3298 bUsed
= true; // event is used
3299 else // changes allowed
3301 if (bNewView
) // create new edit view
3304 pActiveViewSh
->GetViewData()->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3306 if (eMode
==SC_INPUT_NONE
)
3307 if (pTableView
|| pTopView
)
3312 pTableView
->GetEditEngine()->SetText( aStrLoP
);
3313 pTableView
->SetSelection( ESelection(0,0, 0,0) );
3317 pTopView
->GetEditEngine()->SetText( aStrLoP
);
3318 pTopView
->SetSelection( ESelection(0,0, 0,0) );
3324 if (pTableView
|| pTopView
)
3327 pTableView
->Command( rCEvt
);
3329 pTopView
->Command( rCEvt
);
3333 if ( rCEvt
.GetCommand() == COMMAND_ENDEXTTEXTINPUT
)
3335 // AutoInput after ext text input
3338 miAutoPosFormula
= pFormulaData
->end();
3340 miAutoPosColumn
= pColumnData
->end();
3349 DataChanged(); // calls UpdateParenthesis()
3350 InvalidateAttribs(); //! in DataChanged ?
3354 if (pTopView
&& eMode
!= SC_INPUT_NONE
)
3361 void ScInputHandler::NotifyChange( const ScInputHdlState
* pState
,
3362 bool bForce
, ScTabViewShell
* pSourceSh
,
3365 // If the call originates from a macro call in the EnterHandler,
3366 // return immediately and don't mess up the status
3367 if (bInEnterHandler
)
3370 bool bRepeat
= (pState
== pLastState
);
3371 if (!bRepeat
&& pState
&& pLastState
)
3372 bRepeat
= (*pState
== *pLastState
);
3373 if (bRepeat
&& !bForce
)
3376 bInOwnChange
= true; // disable ModifyHdl (reset below)
3378 if ( pState
&& !pLastState
) // Enable again
3381 bool bHadObject
= pLastState
&& pLastState
->GetEditData();
3383 //! Before EditEngine gets eventually created (so it gets the right pools)
3385 pActiveViewSh
= pSourceSh
;
3387 pActiveViewSh
= PTR_CAST(ScTabViewShell
, SfxViewShell::Current());
3389 ImplCreateEditEngine();
3391 if ( pState
!= pLastState
)
3394 pLastState
= pState
? new ScInputHdlState( *pState
) : NULL
;
3397 if ( pState
&& pActiveViewSh
)
3399 ScModule
* pScMod
= SC_MOD();
3404 // Also take foreign reference input into account here (e.g. FunctionsAutoPilot),
3405 // FormEditData, if we're switching from Help to Calc:
3406 if ( !bFormulaMode
&& !pScMod
->IsFormulaMode() && !pScMod
->GetFormEditData() )
3408 bool bIgnore
= false;
3411 if (pState
->GetPos() != aCursorPos
)
3422 const ScAddress
& rSPos
= pState
->GetStartPos();
3423 const ScAddress
& rEPos
= pState
->GetEndPos();
3424 const EditTextObject
* pData
= pState
->GetEditData();
3425 OUString aString
= pState
->GetString();
3426 bool bTxtMod
= false;
3427 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
3428 ScDocument
* pDoc
= pDocSh
->GetDocument();
3430 aCursorPos
= pState
->GetPos();
3434 else if ( bHadObject
)
3436 else if ( bTextValid
)
3437 bTxtMod
= ( !aString
.equals(aCurrentText
) );
3439 bTxtMod
= ( !aString
.equals(GetEditText(pEngine
)) );
3441 if ( bTxtMod
|| bForce
)
3445 pEngine
->SetText( *pData
);
3446 if ( pInputWin
&& pInputWin
->IsMultiLineInput() )
3447 aString
= ScEditUtil::GetMultilineString(*pEngine
);
3449 aString
= GetEditText(pEngine
);
3450 lcl_RemoveTabs(aString
);
3452 aCurrentText
= OUString();
3456 aCurrentText
= aString
;
3457 bTextValid
= true; //! To begin with remember as a string
3461 pInputWin
->SetTextString(aString
);
3464 if ( pInputWin
) // Named range input
3467 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
3469 // Is the range a name?
3471 if ( pActiveViewSh
)
3472 pActiveViewSh
->GetViewData()->GetDocument()->
3473 GetRangeAtBlock( ScRange( rSPos
, rEPos
), &aPosStr
);
3475 if ( aPosStr
.isEmpty() ) // Not a name -> format
3477 sal_uInt16 nFlags
= 0;
3478 if( aAddrDetails
.eConv
== formula::FormulaGrammar::CONV_XL_R1C1
)
3479 nFlags
|= SCA_COL_ABSOLUTE
| SCA_ROW_ABSOLUTE
;
3480 if ( rSPos
!= rEPos
)
3482 ScRange
r(rSPos
, rEPos
);
3483 nFlags
|= (nFlags
<< 4);
3484 aPosStr
= r
.Format(SCA_VALID
| nFlags
, pDoc
, aAddrDetails
);
3487 aPosStr
= aCursorPos
.Format(SCA_VALID
| nFlags
, pDoc
, aAddrDetails
);
3490 // Disable the accessible VALUE_CHANGE event
3491 bool bIsSuppressed
= pInputWin
->IsAccessibilityEventsSuppressed(false);
3492 pInputWin
->SetAccessibilityEventsSuppressed(true);
3493 pInputWin
->SetPosString(aPosStr
);
3494 pInputWin
->SetAccessibilityEventsSuppressed(bIsSuppressed
);
3495 pInputWin
->SetSumAssignMode();
3499 SFX_APP()->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW
) );
3501 // As long as the content is not edited, turn off online spelling.
3502 // Online spelling is turned back on in StartTable, after setting
3503 // the right language from cell attributes.
3505 sal_uLong nCntrl
= pEngine
->GetControlWord();
3506 if ( nCntrl
& EE_CNTRL_ONLINESPELLING
)
3507 pEngine
->SetControlWord( nCntrl
& ~EE_CNTRL_ONLINESPELLING
);
3512 bCommandErrorShown
= false;
3519 // Do not enable if RefDialog is open
3520 if(!pScMod
->IsFormulaMode()&& !pScMod
->IsRefDialogOpen())
3522 if ( !pInputWin
->IsEnabled())
3524 pInputWin
->Enable();
3527 DELETEZ( pDelayTimer
);
3531 else if(pScMod
->IsRefDialogOpen())
3532 { // Because every document has its own InputWin,
3533 // we should start Timer again, because the input line may
3537 pDelayTimer
= new Timer
;
3538 pDelayTimer
->SetTimeout( 500 ); // 500 ms delay
3539 pDelayTimer
->SetTimeoutHdl( LINK( this, ScInputHandler
, DelayTimer
) );
3540 pDelayTimer
->Start();
3545 else // !pState || !pActiveViewSh
3549 pDelayTimer
= new Timer
;
3550 pDelayTimer
->SetTimeout( 500 ); // 500 ms delay
3551 pDelayTimer
->SetTimeoutHdl( LINK( this, ScInputHandler
, DelayTimer
) );
3552 pDelayTimer
->Start();
3558 bInOwnChange
= false;
3561 void ScInputHandler::UpdateCellAdjust( SvxCellHorJustify eJust
)
3563 eAttrAdjust
= eJust
;
3567 void ScInputHandler::ResetDelayTimer()
3569 if(pDelayTimer
!=NULL
)
3571 DELETEZ( pDelayTimer
);
3575 pInputWin
->Enable();
3580 IMPL_LINK( ScInputHandler
, DelayTimer
, Timer
*, pTimer
)
3582 if ( pTimer
== pDelayTimer
)
3584 DELETEZ( pDelayTimer
);
3586 if ( NULL
== pLastState
|| SC_MOD()->IsFormulaMode() || SC_MOD()->IsRefDialogOpen())
3588 //! New method at ScModule to query if function autopilot is open
3589 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
3590 if ( pViewFrm
&& pViewFrm
->GetChildWindow( SID_OPENDLG_FUNCTION
) )
3594 pInputWin
->EnableButtons( false );
3595 pInputWin
->Disable();
3598 else if ( !bFormulaMode
) // Keep formula e.g. for help
3600 bInOwnChange
= true; // disable ModifyHdl (reset below)
3602 pActiveViewSh
= NULL
;
3603 pEngine
->SetText( EMPTY_OUSTRING
);
3606 pInputWin
->SetPosString( EMPTY_OUSTRING
);
3607 pInputWin
->SetTextString( EMPTY_OUSTRING
);
3608 pInputWin
->Disable();
3611 bInOwnChange
= false;
3618 void ScInputHandler::InputSelection( EditView
* pView
)
3622 UpdateParenthesis(); // Selection changed -> update parentheses highlighting
3624 // When the selection is changed manually, stop overwriting parentheses
3628 void ScInputHandler::InputChanged( EditView
* pView
, bool bFromNotify
)
3632 // #i20282# DataChanged needs to know if this is from the input line's modify handler
3633 bool bFromTopNotify
= ( bFromNotify
&& pView
== pTopView
);
3635 bool bNewView
= DataChanging(); //FIXME: Is this at all possible?
3636 aCurrentText
= pView
->GetEditEngine()->GetText(); // Also remember the string
3637 pEngine
->SetText( aCurrentText
);
3638 DataChanged( bFromTopNotify
);
3639 bTextValid
= true; // Is set to false in DataChanged
3641 if ( pActiveViewSh
)
3643 ScViewData
* pViewData
= pActiveViewSh
->GetViewData();
3645 pViewData
->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3647 pViewData
->EditGrowY();
3648 pViewData
->EditGrowX();
3654 const OUString
& ScInputHandler::GetEditString()
3658 aCurrentText
= pEngine
->GetText(); // Always new from Engine
3662 return aCurrentText
;
3665 Size
ScInputHandler::GetTextSize()
3669 aSize
= Size( pEngine
->CalcTextWidth(), pEngine
->GetTextHeight() );
3674 bool ScInputHandler::GetTextAndFields( ScEditEngineDefaulter
& rDestEngine
)
3680 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
3681 SfxItemSet aSet
= pEngine
->GetAttribs( ESelection(0,0,nParCnt
,0) );
3682 SfxItemState eFieldState
= aSet
.GetItemState( EE_FEATURE_FIELD
, false );
3683 if ( eFieldState
== SFX_ITEM_DONTCARE
|| eFieldState
== SFX_ITEM_SET
)
3686 EditTextObject
* pObj
= pEngine
->CreateTextObject();
3687 rDestEngine
.SetText(*pObj
);
3690 // Delete attributes
3691 for (sal_Int32 i
=0; i
<nParCnt
; i
++)
3692 rDestEngine
.QuickRemoveCharAttribs( i
);
3694 // Combine paragraphs
3695 while ( nParCnt
> 1 )
3697 sal_Int32 nLen
= rDestEngine
.GetTextLen( 0 );
3698 ESelection
aSel( 0,nLen
, 1,0 );
3699 rDestEngine
.QuickInsertText( OUString(' '), aSel
); // Replace line break with space
3711 * Methods for FunctionAutoPilot:
3712 * InputGetSelection, InputSetSelection, InputReplaceSelection, InputGetFormulaStr
3714 void ScInputHandler::InputGetSelection( sal_Int32
& rStart
, sal_Int32
& rEnd
)
3716 rStart
= nFormSelStart
;
3720 EditView
* ScInputHandler::GetFuncEditView()
3722 UpdateActiveView(); // Due to pTableView
3724 EditView
* pView
= NULL
;
3727 pInputWin
->MakeDialogEditView();
3728 pView
= pInputWin
->GetEditView();
3732 if ( eMode
!= SC_INPUT_TABLE
)
3734 bCreatingFuncView
= true; // Don't display RangeFinder
3735 SetMode( SC_INPUT_TABLE
);
3736 bCreatingFuncView
= false;
3738 pTableView
->GetEditEngine()->SetText( EMPTY_OUSTRING
);
3746 void ScInputHandler::InputSetSelection( sal_Int32 nStart
, sal_Int32 nEnd
)
3748 if ( nStart
<= nEnd
)
3750 nFormSelStart
= nStart
;
3755 nFormSelEnd
= nStart
;
3756 nFormSelStart
= nEnd
;
3759 EditView
* pView
= GetFuncEditView();
3761 pView
->SetSelection( ESelection(0,nStart
, 0,nEnd
) );
3766 void ScInputHandler::InputReplaceSelection( const OUString
& rStr
)
3769 pRefViewSh
= pActiveViewSh
;
3771 OSL_ENSURE(nFormSelEnd
>=nFormSelStart
,"Selection broken...");
3773 sal_Int32 nOldLen
= nFormSelEnd
- nFormSelStart
;
3774 sal_Int32 nNewLen
= rStr
.getLength();
3776 OUStringBuffer
aBuf(aFormText
);
3778 aBuf
.remove(nFormSelStart
, nOldLen
);
3780 aBuf
.insert(nFormSelStart
, rStr
);
3782 aFormText
= aBuf
.makeStringAndClear();
3784 nFormSelEnd
= nFormSelStart
+ nNewLen
;
3786 EditView
* pView
= GetFuncEditView();
3789 pView
->SetEditEngineUpdateMode( false );
3790 pView
->GetEditEngine()->SetText( aFormText
);
3791 pView
->SetSelection( ESelection(0,nFormSelStart
, 0,nFormSelEnd
) );
3792 pView
->SetEditEngineUpdateMode( true );
3797 void ScInputHandler::InputTurnOffWinEngine()
3799 bInOwnChange
= true; // disable ModifyHdl (reset below)
3801 eMode
= SC_INPUT_NONE
;
3802 /* TODO: it would be better if there was some way to reset the input bar
3803 * engine instead of deleting and having it recreate through
3804 * GetFuncEditView(), but first least invasively let this fix fdo#71667 and
3805 * fdo#72278 without reintroducing fdo#69971. */
3806 StopInputWinEngine(true);
3808 bInOwnChange
= false;
3815 ScInputHdlState::ScInputHdlState( const ScAddress
& rCurPos
,
3816 const ScAddress
& rStartPos
,
3817 const ScAddress
& rEndPos
,
3818 const OUString
& rString
,
3819 const EditTextObject
* pData
)
3820 : aCursorPos ( rCurPos
),
3821 aStartPos ( rStartPos
),
3822 aEndPos ( rEndPos
),
3823 aString ( rString
),
3824 pEditData ( pData
? pData
->Clone() : NULL
)
3828 ScInputHdlState::ScInputHdlState( const ScInputHdlState
& rCpy
)
3829 : pEditData ( NULL
)
3834 ScInputHdlState::~ScInputHdlState()
3839 bool ScInputHdlState::operator==( const ScInputHdlState
& r
) const
3841 return ( (aStartPos
== r
.aStartPos
)
3842 && (aEndPos
== r
.aEndPos
)
3843 && (aCursorPos
== r
.aCursorPos
)
3844 && (aString
== r
.aString
)
3845 && ScGlobal::EETextObjEqual( pEditData
, r
.pEditData
) );
3848 ScInputHdlState
& ScInputHdlState::operator=( const ScInputHdlState
& r
)
3852 aCursorPos
= r
.aCursorPos
;
3853 aStartPos
= r
.aStartPos
;
3854 aEndPos
= r
.aEndPos
;
3855 aString
= r
.aString
;
3856 pEditData
= r
.pEditData
? r
.pEditData
->Clone() : NULL
;
3861 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */