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 <tools/urlobj.hxx>
52 #include <comphelper/string.hxx>
53 #include <formula/formulahelper.hxx>
55 #include "inputwin.hxx"
56 #include "tabvwsh.hxx"
59 #include "uiitems.hxx"
62 #include "globstr.hrc"
63 #include "patattr.hxx"
64 #include "viewdata.hxx"
65 #include "document.hxx"
66 #include "docpool.hxx"
67 #include "editutil.hxx"
68 #include "appoptio.hxx"
69 #include "docoptio.hxx"
70 #include "validat.hxx"
71 #include "userlist.hxx"
72 #include "rfindlst.hxx"
73 #include "inputopt.hxx"
74 #include "simpleformulacalc.hxx"
75 #include "compiler.hxx"
76 #include "editable.hxx"
77 #include "funcdesc.hxx"
78 #include "markdata.hxx"
79 #include "tokenarray.hxx"
81 // max. Ranges im RangeFinder
82 #define RANGEFIND_MAX 32
84 using namespace formula
;
86 // STATIC DATA -----------------------------------------------------------
88 bool ScInputHandler::bOptLoaded
= false; // App-Optionen ausgewertet
89 bool ScInputHandler::bAutoComplete
= false; // wird in KeyInput gesetzt
91 extern sal_uInt16 nEditAdjust
; //! Member an ViewData
95 // delimiters (in addition to ScEditUtil) needed for range finder:
96 // only characters that are allowed in formulas next to references
97 // and the quotation mark (so string constants can be skipped)
98 const sal_Char pMinDelimiters
[] = " !\"";
100 sal_Unicode
lcl_getSheetSeparator(ScDocument
* pDoc
)
102 ScCompiler
aComp(pDoc
, ScAddress());
103 aComp
.SetGrammar(pDoc
->GetGrammar());
104 return aComp
.GetNativeAddressSymbol(ScCompiler::Convention::SHEET_SEPARATOR
);
107 ScTypedCaseStrSet::const_iterator
findText(
108 const ScTypedCaseStrSet
& rDataSet
, ScTypedCaseStrSet::const_iterator itPos
,
109 const OUString
& rStart
, OUString
& rResult
, bool bBack
)
111 if (bBack
) // rueckwaerts
113 ScTypedCaseStrSet::const_reverse_iterator it
= rDataSet
.rbegin(), itEnd
= rDataSet
.rend();
114 if (itPos
!= rDataSet
.end())
116 size_t nPos
= std::distance(rDataSet
.begin(), itPos
);
117 size_t nRPos
= rDataSet
.size() - 1 - nPos
;
118 std::advance(it
, nRPos
);
122 for (; it
!= itEnd
; ++it
)
124 const ScTypedStrData
& rData
= *it
;
125 if (rData
.GetStringType() == ScTypedStrData::Value
)
129 if (!ScGlobal::GetpTransliteration()->isMatch(rStart
, rData
.GetString()))
133 rResult
= rData
.GetString();
134 return (++it
).base(); // convert the reverse iterator back to iterator.
139 ScTypedCaseStrSet::const_iterator it
= rDataSet
.begin(), itEnd
= rDataSet
.end();
140 if (itPos
!= rDataSet
.end())
146 for (; it
!= itEnd
; ++it
)
148 const ScTypedStrData
& rData
= *it
;
149 if (rData
.GetStringType() == ScTypedStrData::Value
)
153 if (!ScGlobal::GetpTransliteration()->isMatch(rStart
, rData
.GetString()))
157 rResult
= rData
.GetString();
162 return rDataSet
.end(); // no matching text found.
165 OUString
getExactMatch(const ScTypedCaseStrSet
& rDataSet
, const OUString
& rString
)
167 ScTypedCaseStrSet::const_iterator it
= rDataSet
.begin(), itEnd
= rDataSet
.end();
168 for (; it
!= itEnd
; ++it
)
170 const ScTypedStrData
& rData
= *it
;
171 if (rData
.GetStringType() == ScTypedStrData::Value
)
174 if (!ScGlobal::GetpTransliteration()->isEqual(rData
.GetString(), rString
))
177 return rData
.GetString();
182 void removeChars(OUString
& rStr
, sal_Unicode c
)
184 OUStringBuffer
aBuf(rStr
);
185 for (sal_Int32 i
= 0, n
= aBuf
.getLength(); i
< n
; ++i
)
190 rStr
= aBuf
.makeStringAndClear();
195 void ScInputHandler::InitRangeFinder( const OUString
& rFormula
)
198 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
199 ScDocument
* pDoc
= pDocSh
->GetDocument();
200 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(pDoc
);
202 if ( !pActiveViewSh
|| !SC_MOD()->GetInputOptions().GetRangeFinder() )
205 OUString aDelimiters
= ScEditUtil::ModifyDelimiters(
206 OUString::createFromAscii( pMinDelimiters
) );
208 sal_Int32 nColon
= aDelimiters
.indexOf( ':' );
210 aDelimiters
= aDelimiters
.replaceAt( nColon
, 1, ""); // Delimiter ohne Doppelpunkt
211 sal_Int32 nDot
= aDelimiters
.indexOf(cSheetSep
);
213 aDelimiters
= aDelimiters
.replaceAt( nDot
, 1 , ""); // Delimiter ohne Punkt
215 const sal_Unicode
* pChar
= rFormula
.getStr();
216 sal_Int32 nLen
= rFormula
.getLength();
218 sal_Int32 nStart
= 0;
219 sal_uInt16 nCount
= 0;
221 while ( nPos
< nLen
&& nCount
< RANGEFIND_MAX
)
223 // Trenner ueberlesen
224 while ( nPos
<nLen
&& ScGlobal::UnicodeStrChr( aDelimiters
.getStr(), pChar
[nPos
] ) )
226 if ( pChar
[nPos
] == '"' ) // String
229 while (nPos
<nLen
&& pChar
[nPos
] != '"') // bis zum Ende ueberlesen
232 ++nPos
; // Trennzeichen oder schliessender Quote
235 // Text zwischen Trennern
238 while ( nPos
<nLen
&& !ScGlobal::UnicodeStrChr( aDelimiters
.getStr(), pChar
[nPos
] ) )
241 // for R1C1 '-' in R[-]... or C[-]... are not delimiters
242 // Nothing heroic here to ensure that there are '[]' around a negative
243 // integer. we need to clean up this code.
244 if( nPos
< nLen
&& nPos
> 0 &&
245 '-' == pChar
[nPos
] && '[' == pChar
[nPos
-1] &&
247 formula::FormulaGrammar::CONV_XL_R1C1
== pDoc
->GetAddressConvention() )
255 OUString aTest
= rFormula
.copy( nStart
, nPos
-nStart
);
256 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
257 sal_uInt16 nFlags
= aRange
.ParseAny( aTest
, pDoc
, aAddrDetails
);
258 if ( nFlags
& SCA_VALID
)
260 // Tabelle setzen, wenn nicht angegeben
261 if ( (nFlags
& SCA_TAB_3D
) == 0 )
262 aRange
.aStart
.SetTab( pActiveViewSh
->GetViewData()->GetTabNo() );
263 if ( (nFlags
& SCA_TAB2_3D
) == 0 )
264 aRange
.aEnd
.SetTab( aRange
.aStart
.Tab() );
266 if ( ( nFlags
& ( SCA_VALID_COL2
| SCA_VALID_ROW2
| SCA_VALID_TAB2
) ) == 0 )
268 // #i73766# if a single ref was parsed, set the same "abs" flags for ref2,
269 // so Format doesn't output a double ref because of different flags.
270 sal_uInt16 nAbsFlags
= nFlags
& ( SCA_COL_ABSOLUTE
| SCA_ROW_ABSOLUTE
| SCA_TAB_ABSOLUTE
);
271 nFlags
|= nAbsFlags
<< 4;
276 pEngine
->SetUpdateMode( false );
277 pRangeFindList
= new ScRangeFindList( pDocSh
->GetTitle() );
280 pRangeFindList
->Insert( ScRangeFindData( aRange
, nFlags
, nStart
, nPos
) );
282 ESelection
aSel( 0, nStart
, 0, nPos
);
283 SfxItemSet
aSet( pEngine
->GetEmptyItemSet() );
284 aSet
.Put( SvxColorItem( Color( ScRangeFindList::GetColorName( nCount
) ),
286 pEngine
->QuickSetAttribs( aSet
, aSel
);
291 // letzten Trenner nicht ueberlesen, koennte ja ein Quote sein (?)
296 pEngine
->SetUpdateMode( true );
298 pDocSh
->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER
) );
302 static void lcl_Replace( EditView
* pView
, const OUString
& rNewStr
, const ESelection
& rOldSel
)
306 ESelection aOldSel
= pView
->GetSelection();
307 if (aOldSel
.HasRange())
308 pView
->SetSelection( ESelection( aOldSel
.nEndPara
, aOldSel
.nEndPos
,
309 aOldSel
.nEndPara
, aOldSel
.nEndPos
) );
311 EditEngine
* pEngine
= pView
->GetEditEngine();
312 pEngine
->QuickInsertText( rNewStr
, rOldSel
);
314 // Dummy-InsertText fuer Update und Paint
315 // dafuer muss oben die Selektion aufgehoben werden (vor QuickInsertText)
316 pView
->InsertText( EMPTY_OUSTRING
, false );
318 xub_StrLen nLen
= pEngine
->GetTextLen(0);
319 ESelection
aSel( 0, nLen
, 0, nLen
);
320 pView
->SetSelection( aSel
); // Cursor ans Ende
324 void ScInputHandler::UpdateRange( sal_uInt16 nIndex
, const ScRange
& rNew
)
326 ScTabViewShell
* pDocView
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
327 if ( pDocView
&& pRangeFindList
&& nIndex
< pRangeFindList
->Count() )
329 ScRangeFindData
* pData
= pRangeFindList
->GetObject( nIndex
);
330 xub_StrLen nOldStart
= pData
->nSelStart
;
331 xub_StrLen nOldEnd
= pData
->nSelEnd
;
333 ScRange aJustified
= rNew
;
334 aJustified
.Justify(); // Ref in der Formel immer richtigherum anzeigen
335 ScDocument
* pDoc
= pDocView
->GetViewData()->GetDocument();
336 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
337 OUString
aNewStr(aJustified
.Format(pData
->nFlags
, pDoc
, aAddrDetails
));
338 ESelection
aOldSel( 0, nOldStart
, 0, nOldEnd
);
342 lcl_Replace( pTopView
, aNewStr
, aOldSel
);
343 lcl_Replace( pTableView
, aNewStr
, aOldSel
);
345 bInRangeUpdate
= true;
347 bInRangeUpdate
= false;
349 long nDiff
= aNewStr
.getLength() - (long)(nOldEnd
-nOldStart
);
352 pData
->nSelEnd
= (xub_StrLen
)(pData
->nSelEnd
+ nDiff
);
354 sal_uInt16 nCount
= (sal_uInt16
) pRangeFindList
->Count();
355 for (sal_uInt16 i
=nIndex
+1; i
<nCount
; i
++)
357 ScRangeFindData
* pNext
= pRangeFindList
->GetObject( i
);
358 pNext
->nSelStart
= (xub_StrLen
)(pNext
->nSelStart
+ nDiff
);
359 pNext
->nSelEnd
= (xub_StrLen
)(pNext
->nSelEnd
+ nDiff
);
364 OSL_FAIL("UpdateRange: da fehlt was");
368 void ScInputHandler::DeleteRangeFinder()
370 ScTabViewShell
* pPaintView
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
371 if ( pRangeFindList
&& pPaintView
)
373 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
374 pRangeFindList
->SetHidden(true);
375 pDocSh
->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER
) ); // wegnehmen
376 DELETEZ(pRangeFindList
);
380 //==================================================================
382 inline OUString
GetEditText(EditEngine
* pEng
)
384 return ScEditUtil::GetSpaceDelimitedString(*pEng
);
387 static void lcl_RemoveTabs(OUString
& rStr
)
389 removeChars(rStr
, '\t');
392 static void lcl_RemoveLineEnd(OUString
& rStr
)
394 rStr
= convertLineEnd(rStr
, LINEEND_LF
);
395 removeChars(rStr
, '\n');
398 static sal_Int32
lcl_MatchParenthesis( const OUString
& rStr
, xub_StrLen nPos
)
401 sal_Unicode c1
, c2
= 0;
442 sal_Int32 nLen
= rStr
.getLength();
443 const sal_Unicode
* p0
= rStr
.getStr();
444 const sal_Unicode
* p
;
445 const sal_Unicode
* p1
;
446 sal_uInt16 nQuotes
= 0;
447 if ( nPos
< nLen
/ 2 )
462 // Odd number of quotes that we find ourselves in a string
463 bool bLookInString
= ((nQuotes
% 2) != 0);
464 bool bInString
= bLookInString
;
466 p1
= (nDir
< 0 ? p0
: p0
+ nLen
) ;
467 sal_uInt16 nLevel
= 1;
468 while ( p
!= p1
&& nLevel
)
473 bInString
= !bInString
;
474 if ( bLookInString
&& !bInString
)
475 p
= p1
; //That's it then
477 else if ( bInString
== bLookInString
)
487 return (sal_Int32
) (p
- p0
);
490 //==================================================================
492 ScInputHandler::ScInputHandler()
498 pFormulaData( NULL
),
499 pFormulaDataPara( NULL
),
500 pTipVisibleParent( NULL
),
502 pTipVisibleSecParent( NULL
),
507 eMode( SC_INPUT_NONE
),
512 bFormulaMode( false ),
513 bInRangeUpdate( false ),
514 bParenthesisShown( false ),
515 bCreatingFuncView( false ),
516 bInEnterHandler( false ),
517 bCommandErrorShown( false ),
518 bInOwnChange( false ),
520 bCellHasPercentFormat( false ),
521 bLastIsSymbol( false ),
523 eAttrAdjust( SVX_HOR_JUSTIFY_STANDARD
),
527 pLastPattern( NULL
),
528 pEditDefaults( NULL
),
531 pRangeFindList( NULL
)
533 // The InputHandler is constructed with the view, so SfxViewShell::Current
534 // doesn't have the right view yet. pActiveViewSh is updated in NotifyChange.
535 pActiveViewSh
= NULL
;
537 // Bindings (nur noch fuer Invalidate benutzt) werden bei Bedarf aktuell geholt
540 ScInputHandler::~ScInputHandler()
542 // Wenn dies der Applikations-InputHandler ist, wird der dtor erst nach SfxApplication::Main
543 // gerufen, darf sich also auf keine Sfx-Funktionen mehr verlassen
545 if ( !SFX_APP()->IsDowning() ) // inplace
546 EnterHandler(); // Eingabe noch abschliessen
548 if (SC_MOD()->GetRefInputHdl()==this)
549 SC_MOD()->SetRefInputHdl(NULL
);
551 if ( pInputWin
&& pInputWin
->GetInputHandler() == this )
552 pInputWin
->SetInputHandler( NULL
);
554 delete pRangeFindList
;
555 delete pEditDefaults
;
561 delete pFormulaDataPara
;
564 void ScInputHandler::SetRefScale( const Fraction
& rX
, const Fraction
& rY
)
566 if ( rX
!= aScaleX
|| rY
!= aScaleY
)
572 MapMode
aMode( MAP_100TH_MM
, Point(), aScaleX
, aScaleY
);
573 pEngine
->SetRefMapMode( aMode
);
578 void ScInputHandler::UpdateRefDevice()
583 bool bTextWysiwyg
= SC_MOD()->GetInputOptions().GetTextWysiwyg();
584 bool bInPlace
= pActiveViewSh
&& pActiveViewSh
->GetViewFrame()->GetFrame().IsInPlace();
585 sal_uLong nCtrl
= pEngine
->GetControlWord();
586 if ( bTextWysiwyg
|| bInPlace
)
587 nCtrl
|= EE_CNTRL_FORMAT100
; // EditEngine default: always format for 100%
589 nCtrl
&= ~EE_CNTRL_FORMAT100
; // when formatting for screen, use the actual MapMode
590 pEngine
->SetControlWord( nCtrl
);
591 if ( bTextWysiwyg
&& pActiveViewSh
)
592 pEngine
->SetRefDevice( pActiveViewSh
->GetViewData()->GetDocument()->GetPrinter() );
594 pEngine
->SetRefDevice( NULL
);
596 MapMode
aMode( MAP_100TH_MM
, Point(), aScaleX
, aScaleY
);
597 pEngine
->SetRefMapMode( aMode
);
599 // SetRefDevice(NULL) uses VirtualDevice, SetRefMapMode forces creation of a local VDev,
600 // so the DigitLanguage can be safely modified (might use an own VDev instead of NULL).
601 if ( !( bTextWysiwyg
&& pActiveViewSh
) )
603 pEngine
->GetRefDevice()->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
607 void ScInputHandler::ImplCreateEditEngine()
613 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
614 pEngine
= new ScFieldEditEngine(pDoc
, pDoc
->GetEnginePool(), pDoc
->GetEditPool());
617 pEngine
= new ScFieldEditEngine(NULL
, EditEngine::CreatePool(), NULL
, true);
618 pEngine
->SetWordDelimiters( ScEditUtil::ModifyDelimiters( pEngine
->GetWordDelimiters() ) );
619 UpdateRefDevice(); // also sets MapMode
620 pEngine
->SetPaperSize( Size( 1000000, 1000000 ) );
621 pEditDefaults
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
623 pEngine
->SetControlWord( pEngine
->GetControlWord() | EE_CNTRL_AUTOCORRECT
);
624 pEngine
->SetModifyHdl( LINK( this, ScInputHandler
, ModifyHdl
) );
628 void ScInputHandler::UpdateAutoCorrFlag()
630 sal_uLong nCntrl
= pEngine
->GetControlWord();
631 sal_uLong nOld
= nCntrl
;
633 // don't use pLastPattern here (may be invalid because of AutoStyle)
635 bool bDisable
= bLastIsSymbol
|| bFormulaMode
;
637 nCntrl
&= ~EE_CNTRL_AUTOCORRECT
;
639 nCntrl
|= EE_CNTRL_AUTOCORRECT
;
641 if ( nCntrl
!= nOld
)
642 pEngine
->SetControlWord(nCntrl
);
645 void ScInputHandler::UpdateSpellSettings( bool bFromStartTab
)
649 ScViewData
* pViewData
= pActiveViewSh
->GetViewData();
650 bool bOnlineSpell
= pViewData
->GetDocument()->GetDocOptions().IsAutoSpell();
652 // SetDefaultLanguage is independent of the language attributes,
653 // ScGlobal::GetEditDefaultLanguage is always used.
654 // It must be set every time in case the office language was changed.
656 pEngine
->SetDefaultLanguage( ScGlobal::GetEditDefaultLanguage() );
658 // if called for changed options, update flags only if already editing
659 // if called from StartTable, always update flags
661 if ( bFromStartTab
|| eMode
!= SC_INPUT_NONE
)
663 sal_uLong nCntrl
= pEngine
->GetControlWord();
664 sal_uLong nOld
= nCntrl
;
666 nCntrl
|= EE_CNTRL_ONLINESPELLING
;
668 nCntrl
&= ~EE_CNTRL_ONLINESPELLING
;
669 // kein AutoCorrect auf Symbol-Font (EditEngine wertet Default nicht aus)
670 if ( pLastPattern
&& pLastPattern
->IsSymbolFont() )
671 nCntrl
&= ~EE_CNTRL_AUTOCORRECT
;
673 nCntrl
|= EE_CNTRL_AUTOCORRECT
;
674 if ( nCntrl
!= nOld
)
675 pEngine
->SetControlWord(nCntrl
);
677 ScDocument
* pDoc
= pViewData
->GetDocument();
678 pDoc
->ApplyAsianEditSettings( *pEngine
);
679 pEngine
->SetDefaultHorizontalTextDirection(
680 (EEHorizontalTextDirection
)pDoc
->GetEditTextDirection( pViewData
->GetTabNo() ) );
681 pEngine
->SetFirstWordCapitalization( false );
684 // language is set separately, so the speller is needed only if online
685 // spelling is active
687 if ( bOnlineSpell
) {
688 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XSpellChecker1
> xXSpellChecker1( LinguMgr::GetSpellChecker() );
689 pEngine
->SetSpeller( xXSpellChecker1
);
692 bool bHyphen
= pLastPattern
&& ((const SfxBoolItem
&)pLastPattern
->GetItem(ATTR_HYPHENATE
)).GetValue();
694 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
695 pEngine
->SetHyphenator( xXHyphenator
);
701 // Funktionen/Bereichsnamen etc. als Tip-Hilfe
704 // die anderen Typen sind in ScDocument::GetFormulaEntries festgelegt
706 void ScInputHandler::GetFormulaData()
710 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
713 pFormulaData
->clear();
716 pFormulaData
= new ScTypedCaseStrSet
;
717 miAutoPosFormula
= pFormulaData
->end();
720 if( pFormulaDataPara
)
721 pFormulaDataPara
->clear();
723 pFormulaDataPara
= new ScTypedCaseStrSet
;
725 // MRU-Funktionen aus dem Funktions-Autopiloten
726 // wie in ScPosWnd::FillFunctions (inputwin.cxx)
728 const ScAppOptions
& rOpt
= SC_MOD()->GetAppOptions();
729 sal_uInt16 nMRUCount
= rOpt
.GetLRUFuncListCount();
730 const sal_uInt16
* pMRUList
= rOpt
.GetLRUFuncList();
731 const ScFunctionList
* pFuncList
= ScGlobal::GetStarCalcFunctionList();
732 sal_uLong nListCount
= pFuncList
->GetCount();
735 for (sal_uInt16 i
=0; i
<nMRUCount
; i
++)
737 sal_uInt16 nId
= pMRUList
[i
];
738 for (sal_uLong j
=0; j
<nListCount
; j
++)
740 const ScFuncDesc
* pDesc
= pFuncList
->GetFunction( j
);
741 if ( pDesc
->nFIndex
== nId
&& pDesc
->pFuncName
)
743 OUString aEntry
= *pDesc
->pFuncName
;
745 pFormulaData
->insert(ScTypedStrData(aEntry
, 0.0, ScTypedStrData::Standard
));
746 break; // nicht weitersuchen
751 for(sal_uLong i
=0;i
<nListCount
;i
++)
753 const ScFuncDesc
* pDesc
= pFuncList
->GetFunction( i
);
754 if ( pDesc
->pFuncName
)
756 pDesc
->initArgumentInfo();
757 OUString aEntry
= pDesc
->getSignature();
758 pFormulaDataPara
->insert(ScTypedStrData(aEntry
, 0.0, ScTypedStrData::Standard
));
761 pDoc
->GetFormulaEntries( *pFormulaData
);
762 pDoc
->GetFormulaEntries( *pFormulaDataPara
);
766 IMPL_LINK( ScInputHandler
, ShowHideTipVisibleParentListener
, VclWindowEvent
*, pEvent
)
768 if( pEvent
->GetId() == VCLEVENT_OBJECT_DYING
|| pEvent
->GetId() == VCLEVENT_WINDOW_HIDE
)
773 IMPL_LINK( ScInputHandler
, ShowHideTipVisibleSecParentListener
, VclWindowEvent
*, pEvent
)
775 if( pEvent
->GetId() == VCLEVENT_OBJECT_DYING
|| pEvent
->GetId() == VCLEVENT_WINDOW_HIDE
)
780 void ScInputHandler::HideTip()
784 if (pTipVisibleParent
)
785 pTipVisibleParent
->RemoveEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleParentListener
) );
786 Help::HideTip( nTipVisible
);
788 pTipVisibleParent
= NULL
;
790 aManualTip
= OUString();
792 void ScInputHandler::HideTipBelow()
794 if ( nTipVisibleSec
)
796 if (pTipVisibleSecParent
)
797 pTipVisibleSecParent
->RemoveEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleSecParentListener
) );
798 Help::HideTip( nTipVisibleSec
);
800 pTipVisibleSecParent
= NULL
;
802 aManualTip
= OUString();
805 void ScInputHandler::ShowTipCursor()
809 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
810 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
811 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
812 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(pDocSh
->GetDocument());
814 if ( bFormulaMode
&& pActiveView
&& pFormulaDataPara
&& pEngine
->GetParagraphCount() == 1 )
816 OUString aFormula
= pEngine
->GetText( 0 );
817 ESelection aSel
= pActiveView
->GetSelection();
821 if ( aFormula
.getLength() < aSel
.nEndPos
)
823 xub_StrLen nPos
= aSel
.nEndPos
;
824 OUString aSelText
= aFormula
.copy( 0, nPos
);
825 xub_StrLen nNextFStart
= 0;
826 xub_StrLen nNextFEnd
= 0;
827 xub_StrLen nArgPos
= 0;
828 const IFunctionDescription
* ppFDesc
;
829 ::std::vector
< OUString
> aArgs
;
832 FormulaHelper
aHelper(ScGlobal::GetStarCalcFunctionMgr());
837 sal_Int32 nLeftParentPos
= lcl_MatchParenthesis( aSelText
, aSelText
.getLength()-1 );
838 if( nLeftParentPos
!= -1 )
840 sal_Unicode c
= ( nLeftParentPos
> 0 ) ? aSelText
[ nLeftParentPos
-1 ] : 0;
841 if( !(comphelper::string::isalphaAscii(c
)) )
843 nNextFStart
= aHelper
.GetFunctionStart( aSelText
, nLeftParentPos
, true);
844 if( aHelper
.GetNextFunc( aSelText
, false, nNextFStart
, &nNextFEnd
, &ppFDesc
, &aArgs
) )
846 if( !ppFDesc
->getFunctionName().isEmpty() )
848 nArgPos
= aHelper
.GetArgStart( aSelText
, nNextFStart
, 0 );
849 nArgs
= static_cast<sal_uInt16
>(ppFDesc
->getParameterCount());
852 ScTypedCaseStrSet::const_iterator it
=
853 findText(*pFormulaDataPara
, pFormulaDataPara
->end(), ppFDesc
->getFunctionName(), aNew
, false);
854 if (it
!= pFormulaDataPara
->end())
857 sal_uInt16 nActive
= 0;
858 for( sal_uInt16 i
=0; i
< nArgs
; i
++ )
860 xub_StrLen nLength
= static_cast<xub_StrLen
>(aArgs
[i
].getLength());
861 if( nArgPos
<= aSelText
.getLength()-1 )
870 sal_Int32 nCountSemicolon
= comphelper::string::getTokenCount(aNew
, cSep
) - 1;
871 sal_Int32 nCountDot
= comphelper::string::getTokenCount(aNew
, cSheetSep
) - 1;
872 sal_Int32 nStartPosition
= 0;
873 sal_Int32 nEndPosition
= 0;
875 if( !nCountSemicolon
)
877 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
879 sal_Unicode cNext
= aNew
[i
];
882 nStartPosition
= i
+1;
886 else if( !nCountDot
)
888 sal_uInt16 nCount
= 0;
889 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
891 sal_Unicode cNext
= aNew
[i
];
894 nStartPosition
= i
+1;
896 else if( cNext
== cSep
)
900 if( nCount
== nActive
)
904 nStartPosition
= nEndPosition
+1;
910 sal_uInt16 nCount
= 0;
911 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
913 sal_Unicode cNext
= aNew
[i
];
916 nStartPosition
= i
+1;
918 else if( cNext
== cSep
)
922 if( nCount
== nActive
)
926 nStartPosition
= nEndPosition
+1;
928 else if( cNext
== cSheetSep
)
935 if (nStartPosition
> 0)
938 aBuf
.append(aNew
.copy(0, nStartPosition
));
939 aBuf
.append(static_cast<sal_Unicode
>(0x25BA));
940 aBuf
.append(aNew
.copy(nStartPosition
));
941 aNew
= aBuf
.makeStringAndClear();
942 ShowTipBelow( aNew
);
948 ShowTipBelow( aNew
);
957 sal_uInt16 nPosition
= 0;
958 OUString aText
= pEngine
->GetWord( 0, aSel
.nEndPos
-1 );
959 /* XXX: dubious, what is this condition supposed to exactly match? */
960 if (aSel
.nEndPos
<= aText
.getLength() && aText
[ aSel
.nEndPos
-1 ] == '=')
965 nPosition
= aText
.getLength()+1;
966 ScTypedCaseStrSet::const_iterator it
=
967 findText(*pFormulaDataPara
, pFormulaDataPara
->end(), aText
, aNew
, false);
968 if (it
!= pFormulaDataPara
->end())
970 if( nPosition
< aFormula
.getLength() && aFormula
[ nPosition
] =='(' )
972 ShowTipBelow( aNew
);
988 void ScInputHandler::ShowTip( const OUString
& rText
)
990 // aManualTip muss hinterher von aussen gesetzt werden
993 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
997 pTipVisibleParent
= pActiveView
->GetWindow();
998 Cursor
* pCur
= pActiveView
->GetCursor();
1000 aPos
= pTipVisibleParent
->LogicToPixel( pCur
->GetPos() );
1001 aPos
= pTipVisibleParent
->OutputToScreenPixel( aPos
);
1002 Rectangle
aRect( aPos
, aPos
);
1004 sal_uInt16 nAlign
= QUICKHELP_LEFT
|QUICKHELP_BOTTOM
;
1005 nTipVisible
= Help::ShowTip(pTipVisibleParent
, aRect
, rText
, nAlign
);
1006 pTipVisibleParent
->AddEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleParentListener
) );
1010 void ScInputHandler::ShowTipBelow( const OUString
& rText
)
1014 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1018 pTipVisibleSecParent
= pActiveView
->GetWindow();
1019 Cursor
* pCur
= pActiveView
->GetCursor();
1022 Point aLogicPos
= pCur
->GetPos();
1023 aLogicPos
.Y() += pCur
->GetHeight();
1024 aPos
= pTipVisibleSecParent
->LogicToPixel( aLogicPos
);
1026 aPos
= pTipVisibleSecParent
->OutputToScreenPixel( aPos
);
1027 Rectangle
aRect( aPos
, aPos
);
1028 sal_uInt16 nAlign
= QUICKHELP_LEFT
| QUICKHELP_TOP
| QUICKHELP_NOEVADEPOINTER
;
1029 nTipVisibleSec
= Help::ShowTip(pTipVisibleSecParent
, aRect
, rText
, nAlign
);
1030 pTipVisibleSecParent
->AddEventListener( LINK( this, ScInputHandler
, ShowHideTipVisibleSecParentListener
) );
1034 void ScInputHandler::UseFormulaData()
1036 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1037 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
1038 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
1039 const sal_Unicode cSheetSep
= lcl_getSheetSeparator(pDocSh
->GetDocument());
1041 // Formeln duerfen nur 1 Absatz haben
1042 if ( pActiveView
&& pFormulaData
&& pEngine
->GetParagraphCount() == 1 )
1044 OUString aTotal
= pEngine
->GetText( 0 );
1045 ESelection aSel
= pActiveView
->GetSelection();
1048 // Durch Differenzen zwischen Tabelle und Eingabezeile
1049 // (z.B. Clipboard mit Zeilenumbruechen) kann es sein, dass die Selektion
1050 // nicht mehr zur EditEngine passt. Dann halt kommentarlos abbrechen:
1052 if ( aSel
.nEndPos
> aTotal
.getLength() )
1055 // steht der Cursor am Ende eines Wortes?
1057 if ( aSel
.nEndPos
> 0 )
1059 xub_StrLen nPos
= aSel
.nEndPos
;
1060 OUString aFormula
= aTotal
.copy( 0, nPos
);;
1061 sal_Int32 nLeftParentPos
= 0;
1062 xub_StrLen nNextFStart
= 0;
1063 xub_StrLen nNextFEnd
= 0;
1064 xub_StrLen nArgPos
= 0;
1065 const IFunctionDescription
* ppFDesc
;
1066 ::std::vector
< OUString
> aArgs
;
1068 bool bFound
= false;
1070 OUString aText
= pEngine
->GetWord( 0, aSel
.nEndPos
-1 );
1071 if (!aText
.isEmpty())
1074 miAutoPosFormula
= pFormulaData
->end();
1075 miAutoPosFormula
= findText(*pFormulaData
, miAutoPosFormula
, aText
, aNew
, false);
1076 if (miAutoPosFormula
!= pFormulaData
->end())
1079 aAutoSearch
= aText
;
1082 FormulaHelper
aHelper(ScGlobal::GetStarCalcFunctionMgr());
1087 nLeftParentPos
= lcl_MatchParenthesis( aFormula
, aFormula
.getLength()-1 );
1088 if( nLeftParentPos
== -1 )
1091 // nLeftParentPos can be 0 if a parenthesis is inserted before the formula
1092 sal_Unicode c
= ( nLeftParentPos
> 0 ) ? aFormula
[ nLeftParentPos
-1 ] : 0;
1093 if( !(comphelper::string::isalphaAscii(c
)) )
1095 nNextFStart
= aHelper
.GetFunctionStart( aFormula
, nLeftParentPos
, true);
1096 if( aHelper
.GetNextFunc( aFormula
, false, nNextFStart
, &nNextFEnd
, &ppFDesc
, &aArgs
) )
1098 if( !ppFDesc
->getFunctionName().isEmpty() )
1100 nArgPos
= aHelper
.GetArgStart( aFormula
, nNextFStart
, 0 );
1101 nArgs
= static_cast<sal_uInt16
>(ppFDesc
->getParameterCount());
1104 ScTypedCaseStrSet::const_iterator it
=
1105 findText(*pFormulaDataPara
, pFormulaDataPara
->end(), ppFDesc
->getFunctionName(), aNew
, false);
1106 if (it
!= pFormulaDataPara
->end())
1109 sal_uInt16 nActive
= 0;
1110 for( sal_uInt16 i
=0; i
< nArgs
; i
++ )
1112 xub_StrLen nLength
= static_cast<xub_StrLen
>(aArgs
[i
].getLength());
1113 if( nArgPos
<= aFormula
.getLength()-1 )
1122 sal_Int32 nCountSemicolon
= comphelper::string::getTokenCount(aNew
, cSep
) - 1;
1123 sal_Int32 nCountDot
= comphelper::string::getTokenCount(aNew
, cSheetSep
) - 1;
1124 sal_Int32 nStartPosition
= 0;
1125 sal_Int32 nEndPosition
= 0;
1127 if( !nCountSemicolon
)
1129 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
1131 sal_Unicode cNext
= aNew
[i
];
1134 nStartPosition
= i
+1;
1138 else if( !nCountDot
)
1140 sal_uInt16 nCount
= 0;
1141 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
1143 sal_Unicode cNext
= aNew
[i
];
1146 nStartPosition
= i
+1;
1148 else if( cNext
== cSep
)
1152 if( nCount
== nActive
)
1156 nStartPosition
= nEndPosition
+1;
1162 sal_uInt16 nCount
= 0;
1163 for (sal_Int32 i
= 0; i
< aNew
.getLength(); ++i
)
1165 sal_Unicode cNext
= aNew
[i
];
1168 nStartPosition
= i
+1;
1170 else if( cNext
== cSep
)
1174 if( nCount
== nActive
)
1178 nStartPosition
= nEndPosition
+1;
1180 else if( cNext
== cSheetSep
)
1187 if (nStartPosition
> 0)
1189 OUStringBuffer aBuf
;
1190 aBuf
.append(aNew
.copy(0, nStartPosition
));
1191 aBuf
.append(static_cast<sal_Unicode
>(0x25BA));
1192 aBuf
.append(aNew
.copy(nStartPosition
));
1193 aNew
= aBuf
.makeStringAndClear();
1194 ShowTipBelow( aNew
);
1200 ShowTipBelow( aNew
);
1211 void ScInputHandler::NextFormulaEntry( bool bBack
)
1213 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1214 if ( pActiveView
&& pFormulaData
)
1217 ScTypedCaseStrSet::const_iterator itNew
= findText(*pFormulaData
, miAutoPosFormula
, aAutoSearch
, aNew
, bBack
);
1218 if (itNew
!= pFormulaData
->end())
1220 miAutoPosFormula
= itNew
;
1221 ShowTip(aNew
); // Display a quick help.
1225 // bei Tab wird vorher immer HideCursor gerufen
1228 pActiveView
->ShowCursor();
1231 static void lcl_CompleteFunction( EditView
* pView
, const OUString
& rInsert
, bool& rParInserted
)
1235 ESelection aSel
= pView
->GetSelection();
1238 pView
->SetSelection(aSel
);
1239 pView
->SelectCurrentWord();
1241 OUString aInsStr
= rInsert
;
1242 xub_StrLen nInsLen
= aInsStr
.getLength();
1243 bool bDoParen
= ( nInsLen
> 1 && aInsStr
[nInsLen
-2] == '('
1244 && aInsStr
[nInsLen
-1] == ')' );
1247 // Klammern hinter Funktionsnamen nicht einfuegen, wenn direkt dahinter
1248 // schon eine Klammer steht (z.B. wenn der Funktionsname geaendert wurde).
1250 ESelection aWordSel
= pView
->GetSelection();
1251 OUString aOld
= pView
->GetEditEngine()->GetText(0);
1252 // aWordSel.EndPos points one behind string if word at end.
1253 if (aWordSel
.nEndPos
< aOld
.getLength())
1255 sal_Unicode cNext
= aOld
[aWordSel
.nEndPos
];
1259 aInsStr
= aInsStr
.copy( 0, nInsLen
- 2 ); // Klammern weglassen
1264 pView
->InsertText( aInsStr
, false );
1266 if ( bDoParen
) // Cursor zwischen die Klammern setzen
1268 aSel
= pView
->GetSelection();
1271 pView
->SetSelection(aSel
);
1273 rParInserted
= true;
1278 void ScInputHandler::PasteFunctionData()
1280 if (pFormulaData
&& miAutoPosFormula
!= pFormulaData
->end())
1282 const ScTypedStrData
& rData
= *miAutoPosFormula
;
1283 const OUString
& aInsert
= rData
.GetString();
1284 bool bParInserted
= false;
1286 DataChanging(); // kann nicht neu sein
1287 lcl_CompleteFunction( pTopView
, aInsert
, bParInserted
);
1288 lcl_CompleteFunction( pTableView
, aInsert
, bParInserted
);
1298 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1300 pActiveView
->ShowCursor();
1304 // Selektion berechnen und als Tip-Hilfe anzeigen
1307 static OUString
lcl_Calculate( const OUString
& rFormula
, ScDocument
* pDoc
, const ScAddress
&rPos
)
1309 //! mit ScFormulaDlg::CalcValue zusammenfassen und ans Dokument verschieben !!!!
1310 //! (Anfuehrungszeichen bei Strings werden nur hier eingefuegt)
1312 if(rFormula
.isEmpty())
1315 boost::scoped_ptr
<ScSimpleFormulaCalculator
> pCalc( new ScSimpleFormulaCalculator( pDoc
, rPos
, rFormula
) );
1317 // HACK! um bei ColRowNames kein #REF! zu bekommen,
1318 // wenn ein Name eigentlich als Bereich in die Gesamt-Formel
1319 // eingefuegt wird, bei der Einzeldarstellung aber als
1320 // single-Zellbezug interpretiert wird
1321 bool bColRowName
= pCalc
->HasColRowName();
1324 // ColRowName im RPN-Code?
1325 if ( pCalc
->GetCode()->GetCodeLen() <= 1 )
1326 { // ==1: einzelner ist als Parameter immer Bereich
1327 // ==0: es waere vielleicht einer, wenn..
1328 OUStringBuffer aBraced
;
1329 aBraced
.append('(');
1330 aBraced
.append(rFormula
);
1331 aBraced
.append(')');
1332 pCalc
.reset( new ScSimpleFormulaCalculator( pDoc
, rPos
, aBraced
.makeStringAndClear() ) );
1335 bColRowName
= false;
1338 sal_uInt16 nErrCode
= pCalc
->GetErrCode();
1339 if ( nErrCode
!= 0 )
1340 return ScGlobal::GetErrorString(nErrCode
);
1342 SvNumberFormatter
& aFormatter
= *(pDoc
->GetFormatTable());
1344 if ( pCalc
->IsValue() )
1346 double n
= pCalc
->GetValue();
1347 sal_uLong nFormat
= aFormatter
.GetStandardFormat( n
, 0,
1348 pCalc
->GetFormatType(), ScGlobal::eLnge
);
1349 aFormatter
.GetInputLineString( n
, nFormat
, aValue
);
1350 //! display OutputString but insert InputLineString
1354 OUString aStr
= pCalc
->GetString().getString();
1355 sal_uLong nFormat
= aFormatter
.GetStandardFormat(
1356 pCalc
->GetFormatType(), ScGlobal::eLnge
);
1359 aFormatter
.GetOutputString( aStr
, nFormat
,
1363 aValue
= "\"" + aValue
+ "\"";
1364 //! Anfuehrungszeichen im String escapen ????
1368 if ( bColRowName
|| (aTestRange
.Parse(rFormula
) & SCA_VALID
) )
1369 aValue
= aValue
+ " ...";
1374 void ScInputHandler::FormulaPreview()
1377 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1378 if ( pActiveView
&& pActiveViewSh
)
1380 OUString aPart
= pActiveView
->GetSelected();
1381 if (aPart
.isEmpty())
1382 aPart
= pEngine
->GetText(0);
1383 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1384 aValue
= lcl_Calculate( aPart
, pDoc
, aCursorPos
);
1387 if (!aValue
.isEmpty())
1389 ShowTip( aValue
); // als QuickHelp anzeigen
1390 aManualTip
= aValue
; // nach ShowTip setzen
1392 miAutoPosFormula
= pFormulaData
->end();
1394 miAutoPosColumn
= pColumnData
->end();
1398 void ScInputHandler::PasteManualTip()
1400 // drei Punkte am Ende -> Bereichsreferenz -> nicht einfuegen
1401 // (wenn wir mal Matrix-Konstanten haben, kann das geaendert werden)
1403 sal_Int32 nTipLen
= aManualTip
.getLength();
1404 sal_uInt32
const nTipLen2(sal::static_int_cast
<sal_uInt32
>(nTipLen
));
1405 if ( nTipLen
&& ( nTipLen
< 3 || aManualTip
.copy( nTipLen2
-3 ) != "..." ) )
1407 DataChanging(); // kann nicht neu sein
1409 OUString aInsert
= aManualTip
;
1410 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1411 if (!pActiveView
->HasSelection())
1413 // nichts selektiert -> alles selektieren
1414 xub_StrLen nOldLen
= pEngine
->GetTextLen(0);
1415 ESelection
aAllSel( 0, 0, 0, nOldLen
);
1417 pTopView
->SetSelection( aAllSel
);
1419 pTableView
->SetSelection( aAllSel
);
1422 ESelection aSel
= pActiveView
->GetSelection();
1424 OSL_ENSURE( !aSel
.nStartPara
&& !aSel
.nEndPara
, "Zuviele Absaetze in Formel" );
1425 if ( !aSel
.nStartPos
) // Selektion ab Anfang?
1427 if ( aSel
.nEndPos
== pEngine
->GetTextLen(0) )
1429 // alles selektiert -> Anfuehrungszeichen weglassen
1430 if ( aInsert
[0] == '"' )
1431 aInsert
= aInsert
.copy(1);
1432 xub_StrLen nInsLen
= aInsert
.getLength();
1433 if ( aInsert
.endsWith("\"") )
1434 aInsert
= aInsert
.copy( 0, nInsLen
-1 );
1436 else if ( aSel
.nEndPos
)
1438 // nicht alles selektiert -> Gleichheitszeichen nicht ueberschreiben
1439 //! doppelte Gleichheitszeichen auch ???
1443 pTopView
->SetSelection( aSel
);
1445 pTableView
->SetSelection( aSel
);
1449 pTopView
->InsertText( aInsert
, true );
1451 pTableView
->InsertText( aInsert
, true );
1459 void ScInputHandler::ResetAutoPar()
1464 void ScInputHandler::AutoParAdded()
1466 ++nAutoPar
; // closing parenthesis can be overwritten
1469 bool ScInputHandler::CursorAtClosingPar()
1471 // test if the cursor is before a closing parenthesis
1473 // selection from SetReference has been removed before
1474 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1475 if ( pActiveView
&& !pActiveView
->HasSelection() && bFormulaMode
)
1477 ESelection aSel
= pActiveView
->GetSelection();
1478 xub_StrLen nPos
= aSel
.nStartPos
;
1479 OUString aFormula
= pEngine
->GetText(0);
1480 if ( nPos
< aFormula
.getLength() && aFormula
[nPos
] == ')' )
1486 void ScInputHandler::SkipClosingPar()
1488 // this is called when a ')' is typed and the cursor is before a ')'
1489 // that can be overwritten -> just set the cursor behind the ')'
1491 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1494 ESelection aSel
= pActiveView
->GetSelection();
1498 // this is in a formula (only one paragraph), so the selection
1499 // can be used directly for the TopView
1502 pTopView
->SetSelection( aSel
);
1504 pTableView
->SetSelection( aSel
);
1507 OSL_ENSURE(nAutoPar
, "SkipClosingPar: count is wrong");
1515 void ScInputHandler::GetColData()
1517 if ( pActiveViewSh
)
1519 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1522 pColumnData
->clear();
1525 pColumnData
= new ScTypedCaseStrSet
;
1526 miAutoPosColumn
= pColumnData
->end();
1529 std::vector
<ScTypedStrData
> aEntries
;
1530 pDoc
->GetDataEntries(
1531 aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab(), true, aEntries
, true);
1532 if (!aEntries
.empty())
1533 pColumnData
->insert(aEntries
.begin(), aEntries
.end());
1537 void ScInputHandler::UseColData() // beim Tippen
1539 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1540 if ( pActiveView
&& pColumnData
)
1542 // nur anpassen, wenn Cursor am Ende steht
1544 ESelection aSel
= pActiveView
->GetSelection();
1547 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
1548 if ( aSel
.nEndPara
+1 == nParCnt
)
1550 xub_StrLen nParLen
= pEngine
->GetTextLen( aSel
.nEndPara
);
1551 if ( aSel
.nEndPos
== nParLen
)
1553 OUString aText
= GetEditText(pEngine
);
1554 if (!aText
.isEmpty())
1557 miAutoPosColumn
= pColumnData
->end();
1558 miAutoPosColumn
= findText(*pColumnData
, miAutoPosColumn
, aText
, aNew
, false);
1559 if (miAutoPosColumn
!= pColumnData
->end())
1561 // durch dBase Import etc. koennen Umbrueche im String sein,
1562 // das wuerde hier mehrere Absaetze ergeben -> nicht gut
1563 //! GetExactMatch funktioniert dann auch nicht
1564 lcl_RemoveLineEnd( aNew
);
1566 // Absaetze beibehalten, nur den Rest anfuegen
1567 //! genaue Ersetzung im EnterHandler !!!
1569 // ein Space zwischen Absaetzen:
1570 sal_Int32 nEdLen
= pEngine
->GetTextLen() + nParCnt
- 1;
1571 OUString aIns
= aNew
.copy(nEdLen
);
1573 // selection must be "backwards", so the cursor stays behind the last
1575 ESelection
aSelection( aSel
.nEndPara
, aSel
.nEndPos
+ aIns
.getLength(),
1576 aSel
.nEndPara
, aSel
.nEndPos
);
1578 // when editing in input line, apply to both edit views
1581 pTableView
->InsertText( aIns
, false );
1582 pTableView
->SetSelection( aSelection
);
1586 pTopView
->InsertText( aIns
, false );
1587 pTopView
->SetSelection( aSelection
);
1590 aAutoSearch
= aText
; // zum Weitersuchen - nAutoPos ist gesetzt
1592 if (aText
.getLength() == aNew
.getLength())
1594 // Wenn der eingegebene Text gefunden wurde, TAB nur dann
1595 // verschlucken, wenn noch etwas kommt
1598 ScTypedCaseStrSet::const_iterator itNextPos
=
1599 findText(*pColumnData
, miAutoPosColumn
, aText
, aDummy
, false);
1600 bUseTab
= itNextPos
!= pColumnData
->end();
1611 void ScInputHandler::NextAutoEntry( bool bBack
)
1613 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1614 if ( pActiveView
&& pColumnData
)
1616 if (miAutoPosColumn
!= pColumnData
->end() && !aAutoSearch
.isEmpty())
1618 // stimmt die Selektion noch? (kann per Maus geaendert sein)
1620 ESelection aSel
= pActiveView
->GetSelection();
1622 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
1623 if ( aSel
.nEndPara
+1 == nParCnt
&& aSel
.nStartPara
== aSel
.nEndPara
)
1625 OUString aText
= GetEditText(pEngine
);
1626 xub_StrLen nSelLen
= aSel
.nEndPos
- aSel
.nStartPos
;
1627 xub_StrLen nParLen
= pEngine
->GetTextLen( aSel
.nEndPara
);
1628 if ( aSel
.nEndPos
== nParLen
&& aText
.getLength() == aAutoSearch
.getLength() + nSelLen
)
1631 ScTypedCaseStrSet::const_iterator itNew
=
1632 findText(*pColumnData
, miAutoPosColumn
, aAutoSearch
, aNew
, bBack
);
1634 if (itNew
!= pColumnData
->end())
1637 miAutoPosColumn
= itNew
;
1638 bInOwnChange
= true; // disable ModifyHdl (reset below)
1640 lcl_RemoveLineEnd( aNew
);
1641 OUString aIns
= aNew
.copy(aAutoSearch
.getLength());
1643 // when editing in input line, apply to both edit views
1646 pTableView
->DeleteSelected();
1647 pTableView
->InsertText( aIns
, false );
1648 pTableView
->SetSelection( ESelection(
1649 aSel
.nEndPara
, aSel
.nStartPos
+ aIns
.getLength(),
1650 aSel
.nEndPara
, aSel
.nStartPos
) );
1654 pTopView
->DeleteSelected();
1655 pTopView
->InsertText( aIns
, false );
1656 pTopView
->SetSelection( ESelection(
1657 aSel
.nEndPara
, aSel
.nStartPos
+ aIns
.getLength(),
1658 aSel
.nEndPara
, aSel
.nStartPos
) );
1661 bInOwnChange
= false;
1668 // bei Tab wird vorher immer HideCursor gerufen
1671 pActiveView
->ShowCursor();
1675 // Klammern hervorheben
1678 void ScInputHandler::UpdateParenthesis()
1682 //! Klammer-Hervorhebung einzeln abschaltbar ????
1684 bool bFound
= false;
1685 if ( bFormulaMode
&& eMode
!= SC_INPUT_TOP
)
1687 if ( pTableView
&& !pTableView
->HasSelection() ) // Selektion ist immer unten
1689 ESelection aSel
= pTableView
->GetSelection();
1692 // Das Zeichen links vom Cursor wird angeschaut
1694 xub_StrLen nPos
= aSel
.nStartPos
- 1;
1695 OUString aFormula
= pEngine
->GetText(0);
1696 sal_Unicode c
= aFormula
[nPos
];
1697 if ( c
== '(' || c
== ')' )
1699 sal_Int32 nOther
= lcl_MatchParenthesis( aFormula
, nPos
);
1702 SfxItemSet
aSet( pEngine
->GetEmptyItemSet() );
1703 aSet
.Put( SvxWeightItem( WEIGHT_BOLD
, EE_CHAR_WEIGHT
) );
1704 //! Unterscheidung, wenn die Zelle schon fett ist !!!!
1706 if (bParenthesisShown
)
1708 // alte Hervorhebung wegnehmen
1709 sal_Int32 nCount
= pEngine
->GetParagraphCount();
1710 for (sal_Int32 i
=0; i
<nCount
; i
++)
1711 pEngine
->QuickRemoveCharAttribs( i
, EE_CHAR_WEIGHT
);
1714 ESelection
aSelThis( 0,nPos
, 0,nPos
+1 );
1715 pEngine
->QuickSetAttribs( aSet
, aSelThis
);
1716 ESelection
aSelOther( 0,nOther
, 0,nOther
+1 );
1717 pEngine
->QuickSetAttribs( aSet
, aSelOther
);
1719 // Dummy-InsertText fuer Update und Paint (Selektion ist leer)
1720 pTableView
->InsertText( EMPTY_OUSTRING
, false );
1727 // mark parenthesis right of cursor if it will be overwritten (nAutoPar)
1728 // with different color (COL_LIGHTBLUE) ??
1732 // alte Hervorhebung wegnehmen, wenn keine neue gesetzt
1734 if ( bParenthesisShown
&& !bFound
&& pTableView
)
1736 sal_Int32 nCount
= pEngine
->GetParagraphCount();
1737 for (sal_Int32 i
=0; i
<nCount
; i
++)
1738 pTableView
->RemoveCharAttribs( i
, EE_CHAR_WEIGHT
);
1741 bParenthesisShown
= bFound
;
1744 void ScInputHandler::ViewShellGone(ScTabViewShell
* pViewSh
) // wird synchron aufgerufen!
1746 if ( pViewSh
== pActiveViewSh
)
1750 pLastPattern
= NULL
;
1753 if ( pViewSh
== pRefViewSh
)
1755 //! Die Eingabe kommt aus dem EnterHandler nicht mehr an
1756 // Trotzdem wird immerhin der Editmodus beendet
1759 bFormulaMode
= false;
1761 SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
1762 SC_MOD()->SetRefInputHdl(NULL
);
1764 pInputWin
->SetFormulaMode(false);
1765 UpdateAutoCorrFlag();
1768 pActiveViewSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
1770 if ( pActiveViewSh
&& pActiveViewSh
== pViewSh
)
1772 OSL_FAIL("pActiveViewSh weg");
1773 pActiveViewSh
= NULL
;
1776 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
1777 UpdateRefDevice(); // don't keep old document's printer as RefDevice
1780 void ScInputHandler::UpdateActiveView()
1782 ImplCreateEditEngine();
1784 // #i20588# Don't rely on focus to find the active edit view. Instead, the
1785 // active pane at the start of editing is now stored (GetEditActivePart).
1786 // GetActiveWin (the currently active pane) fails for ref input across the
1787 // panes of a split view.
1789 Window
* pShellWin
= pActiveViewSh
?
1790 pActiveViewSh
->GetWindowByPos( pActiveViewSh
->GetViewData()->GetEditActivePart() ) :
1793 sal_uInt16 nCount
= pEngine
->GetViewCount();
1796 pTableView
= pEngine
->GetView(0);
1797 for (sal_uInt16 i
=1; i
<nCount
; i
++)
1799 EditView
* pThis
= pEngine
->GetView(i
);
1800 Window
* pWin
= pThis
->GetWindow();
1801 if ( pWin
==pShellWin
)
1808 if (pInputWin
&& eMode
== SC_INPUT_TOP
)
1809 pTopView
= pInputWin
->GetEditView();
1814 void ScInputHandler::StopInputWinEngine( bool bAll
)
1817 pInputWin
->StopEditEngine( bAll
);
1819 pTopView
= NULL
; // invalid now
1822 EditView
* ScInputHandler::GetActiveView()
1825 return pTopView
? pTopView
: pTableView
;
1828 void ScInputHandler::ForgetLastPattern()
1830 pLastPattern
= NULL
;
1831 if ( !pLastState
&& pActiveViewSh
)
1832 pActiveViewSh
->UpdateInputHandler( true ); // Status neu holen
1834 NotifyChange( pLastState
, true );
1837 void ScInputHandler::UpdateAdjust( sal_Unicode cTyped
)
1839 SvxAdjust eSvxAdjust
;
1840 switch (eAttrAdjust
)
1842 case SVX_HOR_JUSTIFY_STANDARD
:
1844 bool bNumber
= false;
1845 if (cTyped
) // neu angefangen
1846 bNumber
= (cTyped
>='0' && cTyped
<='9'); // nur Ziffern sind Zahlen
1847 else if ( pActiveViewSh
)
1849 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1850 bNumber
= ( pDoc
->GetCellType( aCursorPos
) == CELLTYPE_VALUE
);
1852 eSvxAdjust
= bNumber
? SVX_ADJUST_RIGHT
: SVX_ADJUST_LEFT
;
1855 case SVX_HOR_JUSTIFY_BLOCK
:
1856 eSvxAdjust
= SVX_ADJUST_BLOCK
;
1858 case SVX_HOR_JUSTIFY_CENTER
:
1859 eSvxAdjust
= SVX_ADJUST_CENTER
;
1861 case SVX_HOR_JUSTIFY_RIGHT
:
1862 eSvxAdjust
= SVX_ADJUST_RIGHT
;
1864 default: // SVX_HOR_JUSTIFY_LEFT
1865 eSvxAdjust
= SVX_ADJUST_LEFT
;
1869 bool bAsianVertical
= pLastPattern
&&
1870 ((const SfxBoolItem
&)pLastPattern
->GetItem( ATTR_STACKED
)).GetValue() &&
1871 ((const SfxBoolItem
&)pLastPattern
->GetItem( ATTR_VERTICAL_ASIAN
)).GetValue();
1872 if ( bAsianVertical
)
1874 // always edit at top of cell -> LEFT when editing vertically
1875 eSvxAdjust
= SVX_ADJUST_LEFT
;
1878 pEditDefaults
->Put( SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
1879 pEngine
->SetDefaults( *pEditDefaults
);
1881 nEditAdjust
= sal::static_int_cast
<sal_uInt16
>(eSvxAdjust
); //! set at ViewData or with PostEditView
1883 pEngine
->SetVertical( bAsianVertical
);
1886 void ScInputHandler::RemoveAdjust()
1888 // harte Ausrichtungs-Attribute loeschen
1890 bool bUndo
= pEngine
->IsUndoEnabled();
1892 pEngine
->EnableUndo( false );
1894 // non-default paragraph attributes (e.g. from clipboard)
1895 // must be turned into character attributes
1896 pEngine
->RemoveParaAttribs();
1899 pEngine
->EnableUndo( true );
1903 void ScInputHandler::RemoveRangeFinder()
1905 // pRangeFindList und Farben loeschen
1907 pEngine
->SetUpdateMode(false);
1908 sal_Int32 nCount
= pEngine
->GetParagraphCount(); // koennte gerade neu eingefuegt worden sein
1909 for (sal_Int32 i
=0; i
<nCount
; i
++)
1910 pEngine
->QuickRemoveCharAttribs( i
, EE_CHAR_COLOR
);
1911 pEngine
->SetUpdateMode(true);
1913 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
1914 pActiveView
->ShowCursor( false, true );
1916 DeleteRangeFinder(); // loescht die Liste und die Markierungen auf der Tabelle
1919 bool ScInputHandler::StartTable( sal_Unicode cTyped
, bool bFromCommand
, bool bInputActivated
)
1921 bool bNewTable
= false;
1923 if (bModified
|| !ValidCol(aCursorPos
.Col()))
1928 ImplCreateEditEngine();
1932 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocShell()->GetDocument();
1934 const ScMarkData
& rMark
= pActiveViewSh
->GetViewData()->GetMarkData();
1935 ScEditableTester aTester
;
1936 if ( rMark
.IsMarked() || rMark
.IsMultiMarked() )
1937 aTester
.TestSelection( pDoc
, rMark
);
1939 aTester
.TestSelectedBlock(
1940 pDoc
, aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Col(), aCursorPos
.Row(), rMark
);
1942 bool bStartInputMode
= true;
1944 if (!aTester
.IsEditable())
1947 // We allow read-only input mode activation regardless
1948 // whether it's part of an array or not or whether explicit cell
1949 // activation is requested (double-click or F2) or a click in input
1951 bool bShowError
= (!bInputActivated
|| aTester
.GetMessageId() != STR_PROTECTIONERR
) &&
1952 !pActiveViewSh
->GetViewData()->GetDocShell()->IsReadOnly();
1955 eMode
= SC_INPUT_NONE
;
1956 StopInputWinEngine( true );
1957 UpdateFormulaMode();
1958 if ( pActiveViewSh
&& ( !bFromCommand
|| !bCommandErrorShown
) )
1960 // Prevent repeated error messages for the same cell from command events
1961 // (for keyboard events, multiple messages are wanted).
1962 // Set the flag before showing the error message because the command handler
1963 // for the next IME command may be called when showing the dialog.
1965 bCommandErrorShown
= true;
1967 pActiveViewSh
->GetActiveWin()->GrabFocus();
1968 pActiveViewSh
->ErrorMessage(aTester
.GetMessageId());
1970 bStartInputMode
= false;
1974 if (bStartInputMode
)
1976 // UpdateMode is enabled again in ScViewData::SetEditEngine (and not needed otherwise)
1977 pEngine
->SetUpdateMode( false );
1979 // Attribute in EditEngine uebernehmen
1981 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(),
1984 if (pPattern
!= pLastPattern
)
1988 const SfxItemSet
& rAttrSet
= pPattern
->GetItemSet();
1989 const SfxPoolItem
* pItem
;
1991 if ( SFX_ITEM_SET
== rAttrSet
.GetItemState( ATTR_VALUE_FORMAT
, true, &pItem
) )
1993 sal_uLong nFormat
= ((const SfxUInt32Item
*)pItem
)->GetValue();
1994 bCellHasPercentFormat
= ( NUMBERFORMAT_PERCENT
==
1995 pDoc
->GetFormatTable()->GetType( nFormat
) );
1998 bCellHasPercentFormat
= false; // Default: kein Prozent
2000 // Gueltigkeit angegeben?
2002 if ( SFX_ITEM_SET
== rAttrSet
.GetItemState( ATTR_VALIDDATA
, true, &pItem
) )
2003 nValidation
= ((const SfxUInt32Item
*)pItem
)->GetValue();
2007 // EditEngine Defaults
2009 // Hier auf keinen Fall SetParaAttribs, weil die EditEngine evtl.
2010 // schon gefuellt ist (bei Edit-Zellen).
2011 // SetParaAttribs wuerde dann den Inhalt aendern
2013 //! The SetDefaults is now (since MUST/src602
2014 //! EditEngine changes) implemented as a SetParaAttribs.
2017 pPattern
->FillEditItemSet( pEditDefaults
);
2018 pEngine
->SetDefaults( *pEditDefaults
);
2019 pLastPattern
= pPattern
;
2020 bLastIsSymbol
= pPattern
->IsSymbolFont();
2022 // Background color must be known for automatic font color.
2023 // For transparent cell background, the document background color must be used.
2025 Color aBackCol
= ((const SvxBrushItem
&)
2026 pPattern
->GetItem( ATTR_BACKGROUND
)).GetColor();
2027 ScModule
* pScMod
= SC_MOD();
2028 if ( aBackCol
.GetTransparency() > 0 ||
2029 Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
2030 aBackCol
.SetColor( pScMod
->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
2031 pEngine
->SetBackgroundColor( aBackCol
);
2035 eAttrAdjust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)pPattern
->
2036 GetItem(ATTR_HOR_JUSTIFY
)).GetValue();
2037 if ( eAttrAdjust
== SVX_HOR_JUSTIFY_REPEAT
&&
2038 static_cast<const SfxBoolItem
&>(pPattern
->GetItem(ATTR_LINEBREAK
)).GetValue() )
2040 // #i31843# "repeat" with "line breaks" is treated as default alignment
2041 eAttrAdjust
= SVX_HOR_JUSTIFY_STANDARD
;
2045 // UpdateSpellSettings enables online spelling if needed
2046 // -> also call if attributes are unchanged
2048 UpdateSpellSettings( true ); // uses pLastPattern
2050 // Edit-Engine fuellen
2055 pEngine
->SetText(aCurrentText
);
2056 aStr
= aCurrentText
;
2058 aCurrentText
= OUString();
2061 aStr
= GetEditText(pEngine
);
2063 if (aStr
.startsWith("{=") && aStr
.endsWith("}") ) // Matrix-Formel ?
2065 aStr
= aStr
.copy(1, aStr
.getLength() -2);
2066 pEngine
->SetText(aStr
);
2068 pInputWin
->SetTextString(aStr
);
2071 UpdateAdjust( cTyped
);
2073 if ( bAutoComplete
)
2076 if ( !aStr
.isEmpty() && ( aStr
[0] == '=' || aStr
[0] == '+' || aStr
[0] == '-' ) &&
2077 !cTyped
&& !bCreatingFuncView
)
2078 InitRangeFinder(aStr
); // Formel wird editiert -> RangeFinder
2080 bNewTable
= true; // -> PostEditView-Aufruf
2084 if (!bProtected
&& pInputWin
)
2085 pInputWin
->SetOkCancelMode();
2090 static void lcl_SetTopSelection( EditView
* pEditView
, ESelection
& rSel
)
2092 OSL_ENSURE( rSel
.nStartPara
==0 && rSel
.nEndPara
==0, "SetTopSelection: Para != 0" );
2094 EditEngine
* pEngine
= pEditView
->GetEditEngine();
2095 sal_Int32 nCount
= pEngine
->GetParagraphCount();
2098 xub_StrLen nParLen
= pEngine
->GetTextLen(rSel
.nStartPara
);
2099 while (rSel
.nStartPos
> nParLen
&& rSel
.nStartPara
+1 < nCount
)
2101 rSel
.nStartPos
-= nParLen
+ 1; // incl. Leerzeichen vom Umbruch
2102 nParLen
= pEngine
->GetTextLen(++rSel
.nStartPara
);
2105 nParLen
= pEngine
->GetTextLen(rSel
.nEndPara
);
2106 while (rSel
.nEndPos
> nParLen
&& rSel
.nEndPara
+1 < nCount
)
2108 rSel
.nEndPos
-= nParLen
+ 1; // incl. Leerzeichen vom Umbruch
2109 nParLen
= pEngine
->GetTextLen(++rSel
.nEndPara
);
2113 ESelection aSel
= pEditView
->GetSelection();
2115 if ( rSel
.nStartPara
!= aSel
.nStartPara
|| rSel
.nEndPara
!= aSel
.nEndPara
2116 || rSel
.nStartPos
!= aSel
.nStartPos
|| rSel
.nEndPos
!= aSel
.nEndPos
)
2117 pEditView
->SetSelection( rSel
);
2120 void ScInputHandler::SyncViews( EditView
* pSourceView
)
2124 bool bSelectionForTopView
= false;
2125 if (pTopView
&& pTopView
!= pSourceView
)
2126 bSelectionForTopView
= true;
2127 bool bSelectionForTableView
= false;
2128 if (pTableView
&& pTableView
!= pSourceView
)
2129 bSelectionForTableView
= true;
2130 if (bSelectionForTopView
|| bSelectionForTableView
)
2132 ESelection
aSel(pSourceView
->GetSelection());
2133 if (bSelectionForTopView
)
2134 pTopView
->SetSelection(aSel
);
2135 if (bSelectionForTableView
)
2136 lcl_SetTopSelection(pTableView
, aSel
);
2139 // Only sync selection from topView if we are actually editiing there
2140 else if (pTopView
&& pTableView
)
2142 ESelection
aSel(pTopView
->GetSelection());
2143 lcl_SetTopSelection( pTableView
, aSel
);
2147 IMPL_LINK_NOARG(ScInputHandler
, ModifyHdl
)
2149 if ( !bInOwnChange
&& ( eMode
==SC_INPUT_TYPE
|| eMode
==SC_INPUT_TABLE
) &&
2150 pEngine
&& pEngine
->GetUpdateMode() && pInputWin
)
2152 // update input line from ModifyHdl for changes that are not
2153 // wrapped by DataChanging/DataChanged calls (like Drag&Drop)
2156 if ( pInputWin
->IsMultiLineInput() )
2157 aText
= ScEditUtil::GetMultilineString(*pEngine
);
2159 aText
= GetEditText(pEngine
);
2160 lcl_RemoveTabs(aText
);
2161 pInputWin
->SetTextString(aText
);
2166 bool ScInputHandler::DataChanging( sal_Unicode cTyped
, bool bFromCommand
) // return true = new view created
2169 pActiveViewSh
->GetViewData()->SetPasteMode( SC_PASTE_NONE
);
2170 bInOwnChange
= true; // disable ModifyHdl (reset in DataChanged)
2172 if ( eMode
== SC_INPUT_NONE
)
2173 return StartTable( cTyped
, bFromCommand
, false );
2178 void ScInputHandler::DataChanged( bool bFromTopNotify
, bool bSetModified
)
2180 ImplCreateEditEngine();
2182 if (eMode
==SC_INPUT_NONE
)
2183 eMode
= SC_INPUT_TYPE
;
2185 if ( eMode
== SC_INPUT_TOP
&& pTopView
&& !bFromTopNotify
)
2187 // table EditEngine is formatted below, input line needs formatting after paste
2188 // #i20282# not when called from the input line's modify handler
2189 pTopView
->GetEditEngine()->QuickFormatDoc( true );
2191 // #i23720# QuickFormatDoc hides the cursor, but can't show it again because it
2192 // can't safely access the EditEngine's current view, so the cursor has to be
2193 // shown again here.
2194 pTopView
->ShowCursor();
2201 if ( pRangeFindList
&& !bInRangeUpdate
)
2202 RemoveRangeFinder(); // Attribute und Markierung loeschen
2204 UpdateParenthesis(); // Hervorhebung der Klammern neu
2206 if (eMode
==SC_INPUT_TYPE
|| eMode
==SC_INPUT_TABLE
)
2209 if ( pInputWin
&& pInputWin
->IsMultiLineInput() )
2210 aText
= ScEditUtil::GetMultilineString(*pEngine
);
2212 aText
= GetEditText(pEngine
);
2213 lcl_RemoveTabs(aText
);
2216 pInputWin
->SetTextString( aText
);
2219 // wenn der Cursor vor dem Absatzende steht, werden Teile rechts rausgeschoben
2220 // (unabhaengig von eMode) -> View anpassen!
2221 // wenn der Cursor am Ende steht, reicht der Status-Handler an der ViewData
2223 // first make sure the status handler is called now if the cursor
2224 // is outside the visible area
2225 pEngine
->QuickFormatDoc();
2227 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2228 if (pActiveView
&& pActiveViewSh
)
2230 ScViewData
* pViewData
= pActiveViewSh
->GetViewData();
2232 bool bNeedGrow
= ( nEditAdjust
!= SVX_ADJUST_LEFT
); // rechtsbuendig immer
2235 // Cursor vor dem Ende?
2236 ESelection aSel
= pActiveView
->GetSelection();
2238 bNeedGrow
= ( aSel
.nEndPos
!= pEngine
->GetTextLen(aSel
.nEndPara
) );
2242 bNeedGrow
= pViewData
->GetDocument()->IsLayoutRTL( pViewData
->GetTabNo() );
2246 // adjust inplace view
2247 pViewData
->EditGrowY();
2248 pViewData
->EditGrowX();
2252 UpdateFormulaMode();
2253 bTextValid
= false; // Aenderungen sind nur in der Edit-Engine
2254 bInOwnChange
= false;
2257 void ScInputHandler::UpdateFormulaMode()
2259 SfxApplication
* pSfxApp
= SFX_APP();
2261 bool bIsFormula
= !bProtected
&& pEngine
->GetParagraphCount() == 1;
2264 const OUString
& rText
= pEngine
->GetText(0);
2265 bIsFormula
= !rText
.isEmpty() &&
2266 (rText
[0] == '=' || rText
[0] == '+' || rText
[0] == '-');
2273 bFormulaMode
= true;
2274 pRefViewSh
= pActiveViewSh
;
2275 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2276 SC_MOD()->SetRefInputHdl(this);
2278 pInputWin
->SetFormulaMode(true);
2280 if ( bAutoComplete
)
2283 UpdateParenthesis();
2284 UpdateAutoCorrFlag();
2292 bFormulaMode
= false;
2294 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2295 SC_MOD()->SetRefInputHdl(NULL
);
2297 pInputWin
->SetFormulaMode(false);
2298 UpdateAutoCorrFlag();
2303 void ScInputHandler::ShowRefFrame()
2305 // Modifying pActiveViewSh here would interfere with the bInEnterHandler / bRepeat
2306 // checks in NotifyChange, and lead to keeping the wrong value in pActiveViewSh.
2307 // A local variable is used instead.
2308 ScTabViewShell
* pVisibleSh
= PTR_CAST( ScTabViewShell
, SfxViewShell::Current() );
2309 if ( pRefViewSh
&& pRefViewSh
!= pVisibleSh
)
2311 bool bFound
= false;
2312 SfxViewFrame
* pRefFrame
= pRefViewSh
->GetViewFrame();
2313 SfxViewFrame
* pOneFrame
= SfxViewFrame::GetFirst();
2314 while ( pOneFrame
&& !bFound
)
2316 if ( pOneFrame
== pRefFrame
)
2318 pOneFrame
= SfxViewFrame::GetNext( *pOneFrame
);
2323 // Hier wird sich darauf verlassen, dass Activate synchron funktioniert
2324 // (dabei wird pActiveViewSh umgesetzt)
2326 pRefViewSh
->SetActive(); // Appear und SetViewFrame
2328 // pLastState wird im NotifyChange aus dem Activate richtig gesetzt
2332 OSL_FAIL("ViewFrame fuer Referenzeingabe ist nicht mehr da");
2337 void ScInputHandler::RemoveSelection()
2339 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2343 ESelection aSel
= pActiveView
->GetSelection();
2344 aSel
.nStartPara
= aSel
.nEndPara
;
2345 aSel
.nStartPos
= aSel
.nEndPos
;
2347 pTableView
->SetSelection( aSel
);
2349 pTopView
->SetSelection( aSel
);
2352 void ScInputHandler::InvalidateAttribs()
2354 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
2357 SfxBindings
& rBindings
= pViewFrm
->GetBindings();
2359 rBindings
.Invalidate( SID_ATTR_CHAR_FONT
);
2360 rBindings
.Invalidate( SID_ATTR_CHAR_FONTHEIGHT
);
2361 rBindings
.Invalidate( SID_ATTR_CHAR_COLOR
);
2363 rBindings
.Invalidate( SID_ATTR_CHAR_WEIGHT
);
2364 rBindings
.Invalidate( SID_ATTR_CHAR_POSTURE
);
2365 rBindings
.Invalidate( SID_ATTR_CHAR_UNDERLINE
);
2366 rBindings
.Invalidate( SID_ULINE_VAL_NONE
);
2367 rBindings
.Invalidate( SID_ULINE_VAL_SINGLE
);
2368 rBindings
.Invalidate( SID_ULINE_VAL_DOUBLE
);
2369 rBindings
.Invalidate( SID_ULINE_VAL_DOTTED
);
2371 rBindings
.Invalidate( SID_HYPERLINK_GETLINK
);
2373 rBindings
.Invalidate( SID_ATTR_CHAR_KERNING
);
2374 rBindings
.Invalidate( SID_SET_SUPER_SCRIPT
);
2375 rBindings
.Invalidate( SID_SET_SUB_SCRIPT
);
2376 rBindings
.Invalidate( SID_ATTR_CHAR_STRIKEOUT
);
2377 rBindings
.Invalidate( SID_ATTR_CHAR_SHADOWED
);
2382 // --------------- public Methoden --------------------------------------------
2385 void ScInputHandler::SetMode( ScInputMode eNewMode
)
2387 if ( eMode
== eNewMode
)
2390 ImplCreateEditEngine();
2394 eMode
= SC_INPUT_NONE
;
2395 StopInputWinEngine( true );
2397 pActiveViewSh
->GetActiveWin()->GrabFocus();
2401 if (eNewMode
!= SC_INPUT_NONE
&& pActiveViewSh
)
2402 // Disable paste mode when edit mode starts.
2403 pActiveViewSh
->GetViewData()->SetPasteMode( SC_PASTE_NONE
);
2405 bInOwnChange
= true; // disable ModifyHdl (reset below)
2407 ScInputMode eOldMode
= eMode
;
2409 if (eOldMode
== SC_INPUT_TOP
&& eNewMode
!= eOldMode
)
2410 StopInputWinEngine( false );
2412 if (eMode
==SC_INPUT_TOP
|| eMode
==SC_INPUT_TABLE
)
2414 if (eOldMode
== SC_INPUT_NONE
) // not when switching between modes
2416 if (StartTable(0, false, eMode
== SC_INPUT_TABLE
))
2419 pActiveViewSh
->GetViewData()->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
2423 sal_Int32 nPara
= pEngine
->GetParagraphCount()-1;
2424 sal_Int32 nLen
= pEngine
->GetText(nPara
).getLength();
2425 sal_uInt16 nCount
= pEngine
->GetViewCount();
2427 for (sal_uInt16 i
=0; i
<nCount
; i
++)
2429 if ( eMode
== SC_INPUT_TABLE
&& eOldMode
== SC_INPUT_TOP
)
2435 pEngine
->GetView(i
)->
2436 SetSelection( ESelection( nPara
, nLen
, nPara
, nLen
) );
2438 pEngine
->GetView(i
)->ShowCursor(false);
2443 if (eMode
==SC_INPUT_TABLE
|| eMode
==SC_INPUT_TYPE
)
2446 pTableView
->SetEditEngineUpdateMode(true);
2451 pTopView
->SetEditEngineUpdateMode(true);
2454 if (eNewMode
!= eOldMode
)
2455 UpdateFormulaMode();
2457 bInOwnChange
= false;
2460 //----------------------------------------------------------------------------------------
2462 // lcl_IsNumber - true, wenn nur Ziffern (dann keine Autokorrektur)
2464 static bool lcl_IsNumber(const OUString
& rString
)
2466 sal_Int32 nLen
= rString
.getLength();
2467 for (sal_Int32 i
=0; i
<nLen
; i
++)
2469 sal_Unicode c
= rString
[i
];
2470 if ( c
< '0' || c
> '9' )
2476 static void lcl_SelectionToEnd( EditView
* pView
)
2480 EditEngine
* pEngine
= pView
->GetEditEngine();
2481 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
2484 ESelection
aSel( nParCnt
-1, pEngine
->GetTextLen(nParCnt
-1) ); // empty selection, cursor at the end
2485 pView
->SetSelection( aSel
);
2489 void ScInputHandler::EnterHandler( sal_uInt8 nBlockMode
)
2491 // Bei Makro-Aufrufen fuer Gueltigkeit kann Tod und Teufel passieren,
2492 // darum dafuer sorgen, dass EnterHandler nicht verschachtelt gerufen wird:
2494 if (bInEnterHandler
) return;
2495 bInEnterHandler
= true;
2496 bInOwnChange
= true; // disable ModifyHdl (reset below)
2498 ImplCreateEditEngine();
2500 bool bMatrix
= ( nBlockMode
== SC_ENTER_MATRIX
);
2502 SfxApplication
* pSfxApp
= SFX_APP();
2503 EditTextObject
* pObject
= NULL
;
2504 ScPatternAttr
* pCellAttrs
= NULL
;
2505 bool bForget
= false; // wegen Gueltigkeit streichen ?
2507 OUString aString
= GetEditText(pEngine
);
2508 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2509 if (bModified
&& pActiveView
&& !aString
.isEmpty() && !lcl_IsNumber(aString
))
2511 if (pColumnData
&& miAutoPosColumn
!= pColumnData
->end())
2513 // #i47125# If AutoInput appended something, do the final AutoCorrect
2514 // with the cursor at the end of the input.
2516 lcl_SelectionToEnd(pTopView
);
2517 lcl_SelectionToEnd(pTableView
);
2520 Window
* pFrameWin
= pActiveViewSh
? pActiveViewSh
->GetFrameWin() : NULL
;
2523 pTopView
->CompleteAutoCorrect(); // CompleteAutoCorrect fuer beide Views
2525 pTableView
->CompleteAutoCorrect(pFrameWin
);
2526 aString
= GetEditText(pEngine
);
2528 lcl_RemoveTabs(aString
);
2530 // Test, ob zulaessig (immer mit einfachem String)
2532 if ( bModified
&& nValidation
&& pActiveViewSh
)
2534 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2535 const ScValidationData
* pData
= pDoc
->GetValidationEntry( nValidation
);
2536 if (pData
&& pData
->HasErrMsg())
2538 // #i67990# don't use pLastPattern in EnterHandler
2539 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2540 bool bOk
= pData
->IsDataValid( aString
, *pPattern
, aCursorPos
);
2544 if ( pActiveViewSh
) // falls aus MouseButtonDown gekommen
2545 pActiveViewSh
->StopMarking(); // (die InfoBox verschluckt das MouseButtonUp)
2547 //! es gibt noch Probleme, wenn die Eingabe durch Aktivieren einer
2548 //! anderen View ausgeloest wurde
2550 Window
* pParent
= Application::GetDefDialogParent();
2551 if ( pData
->DoError( pParent
, aString
, aCursorPos
) )
2552 bForget
= true; // Eingabe nicht uebernehmen
2557 // check for input into DataPilot table
2559 if ( bModified
&& pActiveViewSh
&& !bForget
)
2561 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2562 ScDPObject
* pDPObj
= pDoc
->GetDPAtCursor( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2565 // any input within the DataPilot table is either a valid renaming
2566 // or an invalid action - normal cell input is always aborted
2568 pActiveViewSh
->DataPilotInput( aCursorPos
, aString
);
2573 std::vector
<editeng::MisspellRanges
> aMisspellRanges
;
2574 pEngine
->CompleteOnlineSpelling();
2575 bool bSpellErrors
= !bFormulaMode
&& pEngine
->HasOnlineSpellErrors();
2578 // #i3820# If the spell checker flags numerical input as error,
2579 // it still has to be treated as number, not EditEngine object.
2581 if ( pActiveViewSh
)
2583 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2584 // #i67990# don't use pLastPattern in EnterHandler
2585 const ScPatternAttr
* pPattern
= pDoc
->GetPattern( aCursorPos
.Col(), aCursorPos
.Row(), aCursorPos
.Tab() );
2588 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
2589 // without conditional format, as in ScColumn::SetString
2590 sal_uInt32 nFormat
= pPattern
->GetNumberFormat( pFormatter
);
2592 if ( pFormatter
->IsNumberFormat( aString
, nFormat
, nVal
) )
2594 bSpellErrors
= false; // ignore the spelling errors
2600 // After RemoveAdjust, the EditView must not be repainted (has wrong font size etc).
2601 // SetUpdateMode must come after CompleteOnlineSpelling.
2602 // The view is hidden in any case below (Broadcast).
2603 pEngine
->SetUpdateMode( false );
2605 if ( bModified
&& !bForget
) // was wird eingeben (Text/Objekt) ?
2607 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
2611 bool bUniformAttribs
= true;
2612 SfxItemSet aPara1Attribs
= pEngine
->GetAttribs(0, 0, pEngine
->GetTextLen(0));
2613 for (sal_Int32 nPara
= 1; nPara
< nParCnt
; ++nPara
)
2615 SfxItemSet aPara2Attribs
= pEngine
->GetAttribs(nPara
, 0, pEngine
->GetTextLen(nPara
));
2616 if (!(aPara1Attribs
== aPara2Attribs
))
2618 // paragraph format different from that of the 1st paragraph.
2619 bUniformAttribs
= false;
2624 ESelection
aSel( 0, 0, nParCnt
-1, pEngine
->GetTextLen(nParCnt
-1) );
2625 SfxItemSet aOldAttribs
= pEngine
->GetAttribs( aSel
);
2626 const SfxPoolItem
* pItem
= NULL
;
2628 // find common (cell) attributes before RemoveAdjust
2630 if ( pActiveViewSh
&& bUniformAttribs
)
2632 SfxItemSet
* pCommonAttrs
= NULL
;
2633 for (sal_uInt16 nId
= EE_CHAR_START
; nId
<= EE_CHAR_END
; nId
++)
2635 SfxItemState eState
= aOldAttribs
.GetItemState( nId
, false, &pItem
);
2636 if ( eState
== SFX_ITEM_SET
&&
2637 nId
!= EE_CHAR_ESCAPEMENT
&& nId
!= EE_CHAR_PAIRKERNING
&&
2638 nId
!= EE_CHAR_KERNING
&& nId
!= EE_CHAR_XMLATTRIBS
&&
2639 *pItem
!= pEditDefaults
->Get(nId
) )
2641 if ( !pCommonAttrs
)
2642 pCommonAttrs
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
2643 pCommonAttrs
->Put( *pItem
);
2649 ScDocument
* pDoc
= pActiveViewSh
->GetViewData()->GetDocument();
2650 pCellAttrs
= new ScPatternAttr( pDoc
->GetPool() );
2651 pCellAttrs
->GetFromEditItemSet( pCommonAttrs
);
2652 delete pCommonAttrs
;
2656 // clear ParaAttribs (including adjustment)
2660 bool bAttrib
= false; // Formatierung vorhanden ?
2661 // check if EditObject is needed
2667 for (sal_uInt16 nId
= EE_CHAR_START
; nId
<= EE_CHAR_END
&& !bAttrib
; nId
++)
2669 SfxItemState eState
= aOldAttribs
.GetItemState( nId
, false, &pItem
);
2670 if (eState
== SFX_ITEM_DONTCARE
)
2672 else if (eState
== SFX_ITEM_SET
)
2674 // keep same items in EditEngine as in ScEditAttrTester
2675 if ( nId
== EE_CHAR_ESCAPEMENT
|| nId
== EE_CHAR_PAIRKERNING
||
2676 nId
== EE_CHAR_KERNING
|| nId
== EE_CHAR_XMLATTRIBS
)
2678 if ( *pItem
!= pEditDefaults
->Get(nId
) )
2684 // Feldbefehle enthalten?
2686 SfxItemState eFieldState
= aOldAttribs
.GetItemState( EE_FEATURE_FIELD
, false );
2687 if ( eFieldState
== SFX_ITEM_DONTCARE
|| eFieldState
== SFX_ITEM_SET
)
2690 // not converted characters?
2692 SfxItemState eConvState
= aOldAttribs
.GetItemState( EE_FEATURE_NOTCONV
, false );
2693 if ( eConvState
== SFX_ITEM_DONTCARE
|| eConvState
== SFX_ITEM_SET
)
2696 // Formeln immer als Formeln erkennen (#38309#)
2697 // (der Test vorher ist trotzdem noetig wegen Zell-Attributen)
2701 pEngine
->GetAllMisspellRanges(aMisspellRanges
);
2708 pEngine
->ClearSpellErrors();
2709 pObject
= pEngine
->CreateTextObject();
2711 else if (bAutoComplete
) // Gross-/Kleinschreibung anpassen
2713 // Perform case-matching only when the typed text is partial.
2714 if (pColumnData
&& aAutoSearch
.getLength() < aString
.getLength())
2715 aString
= getExactMatch(*pColumnData
, aString
);
2719 // don't rely on ShowRefFrame switching the active view synchronously
2720 // execute the function directly on the correct view's bindings instead
2721 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2722 ScTabViewShell
* pExecuteSh
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
2730 pExecuteSh
->SetTabNo(aCursorPos
.Tab());
2731 pExecuteSh
->ActiveGrabFocus();
2734 bFormulaMode
= false;
2735 pSfxApp
->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2736 SC_MOD()->SetRefInputHdl(NULL
);
2738 pInputWin
->SetFormulaMode(false);
2739 UpdateAutoCorrFlag();
2741 pRefViewSh
= NULL
; // auch ohne FormulaMode wegen Funktions-AP
2742 DeleteRangeFinder();
2745 bool bOldMod
= bModified
;
2749 eMode
= SC_INPUT_NONE
;
2750 StopInputWinEngine(true);
2752 // Text input (through number formats) or ApplySelectionPattern modify
2753 // the cell's attributes, so pLastPattern is no longer valid
2754 pLastPattern
= NULL
;
2756 if (bOldMod
&& !bProtected
&& !bForget
)
2758 // keine typographische Anfuehrungszeichen in Formeln
2760 if (aString
.startsWith("="))
2762 SvxAutoCorrect
* pAuto
= SvxAutoCorrCfg::Get().GetAutoCorrect();
2765 OUString
aReplace(pAuto
->GetStartDoubleQuote());
2766 if( aReplace
.isEmpty() )
2767 aReplace
= ScGlobal::pLocaleData
->getDoubleQuotationMarkStart();
2768 if( aReplace
!= "\"" )
2769 aString
= aString
.replaceAll( aReplace
, "\"" );
2771 aReplace
= OUString(pAuto
->GetEndDoubleQuote());
2772 if( aReplace
.isEmpty() )
2773 aReplace
= ScGlobal::pLocaleData
->getDoubleQuotationMarkEnd();
2774 if( aReplace
!= "\"" )
2775 aString
= aString
.replaceAll( aReplace
, "\"" );
2777 aReplace
= OUString(pAuto
->GetStartSingleQuote());
2778 if( aReplace
.isEmpty() )
2779 aReplace
= ScGlobal::pLocaleData
->getQuotationMarkStart();
2780 if( aReplace
!= "'" )
2781 aString
= aString
.replaceAll( aReplace
, "'" );
2783 aReplace
= OUString(pAuto
->GetEndSingleQuote());
2784 if( aReplace
.isEmpty() )
2785 aReplace
= ScGlobal::pLocaleData
->getQuotationMarkEnd();
2786 if( aReplace
!= "'" )
2787 aString
= aString
.replaceAll( aReplace
, "'");
2791 pSfxApp
->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW_NOPAINT
) );
2795 SfxBindings
& rBindings
= pExecuteSh
->GetViewFrame()->GetBindings();
2797 sal_uInt16 nId
= FID_INPUTLINE_ENTER
;
2798 if ( nBlockMode
== SC_ENTER_BLOCK
)
2799 nId
= FID_INPUTLINE_BLOCK
;
2800 else if ( nBlockMode
== SC_ENTER_MATRIX
)
2801 nId
= FID_INPUTLINE_MATRIX
;
2803 ScInputStatusItem
aItem( FID_INPUTLINE_STATUS
,
2804 aCursorPos
, aCursorPos
, aCursorPos
,
2807 if (!aMisspellRanges
.empty())
2808 aItem
.SetMisspellRanges(&aMisspellRanges
);
2810 const SfxPoolItem
* aArgs
[2];
2813 rBindings
.Execute( nId
, aArgs
);
2816 delete pLastState
; // pLastState enthaelt noch den alten Text
2820 pSfxApp
->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW
) );
2822 if ( bOldMod
&& pExecuteSh
&& pCellAttrs
&& !bForget
)
2824 // mit Eingabe zusammenfassen ?
2825 pExecuteSh
->ApplySelectionPattern( *pCellAttrs
, true, true );
2826 pExecuteSh
->AdjustBlockHeight();
2835 nFormSelStart
= nFormSelEnd
= 0;
2836 aFormText
= OUString();
2838 bInOwnChange
= false;
2839 bInEnterHandler
= false;
2842 void ScInputHandler::CancelHandler()
2844 bInOwnChange
= true; // disable ModifyHdl (reset below)
2846 ImplCreateEditEngine();
2850 // don't rely on ShowRefFrame switching the active view synchronously
2851 // execute the function directly on the correct view's bindings instead
2852 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2853 ScTabViewShell
* pExecuteSh
= pRefViewSh
? pRefViewSh
: pActiveViewSh
;
2860 pExecuteSh
->SetTabNo(aCursorPos
.Tab());
2861 pExecuteSh
->ActiveGrabFocus();
2863 bFormulaMode
= false;
2864 SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED
) );
2865 SC_MOD()->SetRefInputHdl(NULL
);
2867 pInputWin
->SetFormulaMode(false);
2868 UpdateAutoCorrFlag();
2870 pRefViewSh
= NULL
; // auch ohne FormulaMode wegen Funktions-AP
2871 DeleteRangeFinder();
2874 eMode
= SC_INPUT_NONE
;
2875 StopInputWinEngine( true );
2877 pExecuteSh
->StopEditShell();
2879 aCursorPos
.Set(MAXCOL
+1,0,0); // Flag, dass ungueltig
2880 pEngine
->SetText(OUString());
2882 if ( !pLastState
&& pExecuteSh
)
2883 pExecuteSh
->UpdateInputHandler( true ); // Status neu holen
2885 NotifyChange( pLastState
, true );
2887 nFormSelStart
= nFormSelEnd
= 0;
2888 aFormText
= OUString();
2890 bInOwnChange
= false;
2893 bool ScInputHandler::IsModalMode( SfxObjectShell
* pDocSh
)
2895 // Referenzen auf unbenanntes Dokument gehen nicht
2897 return bFormulaMode
&& pRefViewSh
2898 && pRefViewSh
->GetViewData()->GetDocument()->GetDocumentShell() != pDocSh
2899 && !pDocSh
->HasName();
2902 void ScInputHandler::AddRefEntry()
2904 const sal_Unicode cSep
= ScCompiler::GetNativeSymbolChar(ocSep
);
2906 if (!pTableView
&& !pTopView
)
2907 return; // z.B. FillMode
2909 DataChanging(); // kann nicht neu sein
2913 pTableView
->InsertText( OUString(cSep
), false );
2915 pTopView
->InsertText( OUString(cSep
), false );
2920 void ScInputHandler::SetReference( const ScRange
& rRef
, ScDocument
* pDoc
)
2924 bool bOtherDoc
= ( pRefViewSh
&&
2925 pRefViewSh
->GetViewData()->GetDocument() != pDoc
);
2927 if (!pDoc
->GetDocumentShell()->HasName())
2929 // Referenzen auf unbenanntes Dokument gehen nicht
2930 // (SetReference sollte dann auch nicht gerufen werden)
2936 if (!pTableView
&& !pTopView
)
2937 return; // z.B. FillMode
2939 // nie das "=" ueberschreiben!
2940 EditView
* pActiveView
= pTopView
? pTopView
: pTableView
;
2941 ESelection aSel
= pActiveView
->GetSelection();
2943 if ( aSel
.nStartPara
== 0 && aSel
.nStartPos
== 0 )
2946 DataChanging(); // kann nicht neu sein
2948 // Selektion umdrehen, falls rueckwaerts (noetig ???)
2952 ESelection aTabSel
= pTableView
->GetSelection();
2953 if (aTabSel
.nStartPos
> aTabSel
.nEndPos
&& aTabSel
.nStartPara
== aTabSel
.nEndPara
)
2956 pTableView
->SetSelection(aTabSel
);
2961 ESelection aTopSel
= pTopView
->GetSelection();
2962 if (aTopSel
.nStartPos
> aTopSel
.nEndPos
&& aTopSel
.nStartPara
== aTopSel
.nEndPara
)
2965 pTopView
->SetSelection(aTopSel
);
2969 // String aus Referenz erzeugen
2972 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
2975 // Referenz auf anderes Dokument
2977 OSL_ENSURE(rRef
.aStart
.Tab()==rRef
.aEnd
.Tab(), "nStartTab!=nEndTab");
2979 OUString
aTmp(rRef
.Format(SCA_VALID
|SCA_TAB_3D
, pDoc
, aAddrDetails
)); // immer 3d
2981 SfxObjectShell
* pObjSh
= pDoc
->GetDocumentShell();
2982 // #i75893# convert escaped URL of the document to something user friendly
2983 OUString aFileName
= pObjSh
->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS
);
2986 aRefStr
+= aFileName
;
2992 if ( ( rRef
.aStart
.Tab() != aCursorPos
.Tab() ||
2993 rRef
.aStart
.Tab() != rRef
.aEnd
.Tab() ) && pDoc
)
2994 aRefStr
= rRef
.Format(SCA_VALID
|SCA_TAB_3D
, pDoc
, aAddrDetails
);
2996 aRefStr
= rRef
.Format(SCA_VALID
, pDoc
, aAddrDetails
);
2999 if (pTableView
|| pTopView
)
3002 pTableView
->InsertText( aRefStr
, true );
3004 pTopView
->InsertText( aRefStr
, true );
3012 void ScInputHandler::InsertFunction( const OUString
& rFuncName
, bool bAddPar
)
3014 if ( eMode
== SC_INPUT_NONE
)
3016 OSL_FAIL("InsertFunction, nicht im Eingabemodus");
3021 if (!pTableView
&& !pTopView
)
3022 return; // z.B. FillMode
3024 DataChanging(); // kann nicht neu sein
3026 OUString aText
= rFuncName
;
3032 pTableView
->InsertText( aText
, false );
3035 ESelection aSel
= pTableView
->GetSelection();
3038 pTableView
->SetSelection(aSel
);
3043 pTopView
->InsertText( aText
, false );
3046 ESelection aSel
= pTopView
->GetSelection();
3049 pTopView
->SetSelection(aSel
);
3059 void ScInputHandler::ClearText()
3061 if ( eMode
== SC_INPUT_NONE
)
3063 OSL_FAIL("ClearText, nicht im Eingabemodus");
3068 if (!pTableView
&& !pTopView
)
3069 return; // z.B. FillMode
3071 DataChanging(); // darf nicht neu sein
3076 pTableView
->GetEditEngine()->SetText( aEmpty
);
3077 pTableView
->SetSelection( ESelection(0,0, 0,0) );
3081 pTopView
->GetEditEngine()->SetText( aEmpty
);
3082 pTopView
->SetSelection( ESelection(0,0, 0,0) );
3088 bool ScInputHandler::KeyInput( const KeyEvent
& rKEvt
, bool bStartEdit
/* = false */ )
3092 bAutoComplete
= SC_MOD()->GetAppOptions().GetAutoComplete();
3096 KeyCode aCode
= rKEvt
.GetKeyCode();
3097 sal_uInt16 nModi
= aCode
.GetModifier();
3098 bool bShift
= aCode
.IsShift();
3099 bool bControl
= aCode
.IsMod1();
3100 bool bAlt
= aCode
.IsMod2();
3101 sal_uInt16 nCode
= aCode
.GetCode();
3102 sal_Unicode nChar
= rKEvt
.GetCharCode();
3104 if (bAlt
&& !bControl
&& nCode
!= KEY_RETURN
)
3105 // Alt-Return and Alt-Ctrl-* are accepted. Everything else with ALT are not.
3108 if (!bControl
&& nCode
== KEY_TAB
)
3110 // Normal TAB moves the cursor right.
3114 pActiveViewSh
->FindNextUnprot( bShift
);
3118 bool bInputLine
= ( eMode
==SC_INPUT_TOP
);
3122 bool bDoEnter
= false;
3127 if (bControl
&& !bShift
&& ( !bInputLine
|| ( pInputWin
&& pInputWin
->IsMultiLineInput() ) ) )
3129 else if (nModi
== 0 && nTipVisible
&& pFormulaData
&& miAutoPosFormula
!= pFormulaData
->end())
3131 PasteFunctionData();
3134 else if ( nModi
== 0 && nTipVisible
&& !aManualTip
.isEmpty() )
3141 sal_uInt8 nMode
= SC_ENTER_NORMAL
;
3142 if ( bShift
&& bControl
)
3143 nMode
= SC_ENTER_MATRIX
;
3145 nMode
= SC_ENTER_BLOCK
;
3146 EnterHandler( nMode
);
3149 pActiveViewSh
->MoveCursorEnter( bShift
&& !bControl
);
3155 if (bControl
&& !bAlt
)
3157 if (pFormulaData
&& nTipVisible
&& miAutoPosFormula
!= pFormulaData
->end())
3161 NextFormulaEntry( bShift
);
3164 else if (pColumnData
&& bUseTab
&& miAutoPosColumn
!= pColumnData
->end())
3166 // in den Eintraegen der AutoEingabe blaettern
3168 NextAutoEntry( bShift
);
3179 else if( nTipVisibleSec
)
3184 else if (eMode
!= SC_INPUT_NONE
)
3193 if ( !bShift
&& !bControl
&& !bAlt
&& eMode
== SC_INPUT_TABLE
)
3195 eMode
= SC_INPUT_TYPE
;
3201 // Cursortasten nur ausfuehren, wenn schon im Edit-Modus
3202 // z.B. wegen Shift-Ctrl-PageDn (ist nicht als Accelerator definiert)
3204 bool bCursorKey
= EditEngine::DoesKeyMoveCursor(rKEvt
);
3205 bool bInsKey
= ( nCode
== KEY_INSERT
&& !nModi
); // Insert wie Cursortasten behandeln
3206 if ( !bUsed
&& !bSkip
&& ( bDoEnter
|| EditEngine::DoesKeyChangeText(rKEvt
) ||
3207 ( eMode
!= SC_INPUT_NONE
&& ( bCursorKey
|| bInsKey
) ) ) )
3219 bool bNewView
= DataChanging( nChar
);
3221 if (bProtected
) // Zelle geschuetzt?
3222 bUsed
= true; // Key-Event nicht weiterleiten
3223 else // Aenderungen erlaubt
3225 if (bNewView
) // neu anlegen
3228 pActiveViewSh
->GetViewData()->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3230 if (eMode
==SC_INPUT_NONE
)
3231 if (pTableView
|| pTopView
)
3235 if ( bStartEdit
&& bCellHasPercentFormat
&& ((nChar
>= '0' && nChar
<= '9') || nChar
== '-') )
3240 pTableView
->GetEditEngine()->SetText( aStrLoP
);
3241 if ( !aStrLoP
.isEmpty() )
3242 pTableView
->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3244 // don't call SetSelection if the string is empty anyway,
3245 // to avoid breaking the bInitial handling in ScViewData::EditGrowY
3249 pTopView
->GetEditEngine()->SetText( aStrLoP
);
3250 if ( !aStrLoP
.isEmpty() )
3251 pTopView
->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3257 if (pTableView
|| pTopView
)
3262 if( pTableView
->PostKeyEvent( KeyEvent( CHAR_CR
, KeyCode(KEY_RETURN
) ) ) )
3265 if( pTopView
->PostKeyEvent( KeyEvent( CHAR_CR
, KeyCode(KEY_RETURN
) ) ) )
3268 else if ( nAutoPar
&& nChar
== ')' && CursorAtClosingPar() )
3277 Window
* pFrameWin
= pActiveViewSh
? pActiveViewSh
->GetFrameWin() : NULL
;
3278 if ( pTableView
->PostKeyEvent( rKEvt
, pFrameWin
) )
3282 if ( pTopView
->PostKeyEvent( rKEvt
) )
3288 if ( bUsed
&& bAutoComplete
)
3292 miAutoPosFormula
= pFormulaData
->end(); // do not search further
3294 miAutoPosColumn
= pColumnData
->end();
3296 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
3297 if ( nChar
&& nChar
!= 8 && nChar
!= 127 && // no 'backspace', no 'delete'
3298 KEYFUNC_CUT
!= eFunc
) // and no 'CTRL-X'
3307 // when the selection is changed manually or an opening parenthesis
3308 // is typed, stop overwriting parentheses
3309 if ( bUsed
&& nChar
== '(' )
3312 if ( KEY_INSERT
== nCode
)
3314 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
3316 pViewFrm
->GetBindings().Invalidate( SID_ATTR_INSERT
);
3318 if( bUsed
&& bFormulaMode
&& ( bCursorKey
|| bInsKey
|| nCode
== KEY_DELETE
|| nCode
== KEY_BACKSPACE
) )
3324 // #i114511# don't count cursor keys as modification
3325 sal_Bool bSetModified
= !bCursorKey
;
3326 DataChanged(sal_False
, bSetModified
); // also calls UpdateParenthesis()
3327 InvalidateAttribs(); //! in DataChanged ?
3331 if (pTopView
&& eMode
!= SC_INPUT_NONE
)
3337 bool ScInputHandler::InputCommand( const CommandEvent
& rCEvt
, bool bForce
)
3341 if ( rCEvt
.GetCommand() == COMMAND_CURSORPOS
)
3343 // for COMMAND_CURSORPOS, do as little as possible, because
3344 // with remote VCL, even a ShowCursor will generate another event.
3345 if ( eMode
!= SC_INPUT_NONE
)
3348 if (pTableView
|| pTopView
)
3351 pTableView
->Command( rCEvt
);
3352 else if (pTopView
) // call only once
3353 pTopView
->Command( rCEvt
);
3358 else if ( rCEvt
.GetCommand() == COMMAND_QUERYCHARPOSITION
)
3360 if ( eMode
!= SC_INPUT_NONE
)
3363 if (pTableView
|| pTopView
)
3366 pTableView
->Command( rCEvt
);
3367 else if (pTopView
) // call only once
3368 pTopView
->Command( rCEvt
);
3375 if ( bForce
|| eMode
!= SC_INPUT_NONE
)
3379 bAutoComplete
= SC_MOD()->GetAppOptions().GetAutoComplete();
3393 bool bNewView
= DataChanging( 0, true );
3395 if (bProtected
) // cell protected
3396 bUsed
= true; // event is used
3397 else // changes allowed
3399 if (bNewView
) // create new edit view
3402 pActiveViewSh
->GetViewData()->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3404 if (eMode
==SC_INPUT_NONE
)
3405 if (pTableView
|| pTopView
)
3410 pTableView
->GetEditEngine()->SetText( aStrLoP
);
3411 pTableView
->SetSelection( ESelection(0,0, 0,0) );
3415 pTopView
->GetEditEngine()->SetText( aStrLoP
);
3416 pTopView
->SetSelection( ESelection(0,0, 0,0) );
3422 if (pTableView
|| pTopView
)
3425 pTableView
->Command( rCEvt
);
3427 pTopView
->Command( rCEvt
);
3431 if ( rCEvt
.GetCommand() == COMMAND_ENDEXTTEXTINPUT
)
3433 // AutoInput after ext text input
3436 miAutoPosFormula
= pFormulaData
->end();
3438 miAutoPosColumn
= pColumnData
->end();
3447 DataChanged(); // calls UpdateParenthesis()
3448 InvalidateAttribs(); //! in DataChanged ?
3452 if (pTopView
&& eMode
!= SC_INPUT_NONE
)
3459 void ScInputHandler::NotifyChange( const ScInputHdlState
* pState
,
3460 bool bForce
, ScTabViewShell
* pSourceSh
,
3463 // Wenn der Aufruf aus einem Makro-Aufruf im EnterHandler kommt,
3464 // gleich abbrechen und nicht den Status durcheinander bringen
3465 if (bInEnterHandler
)
3468 bool bRepeat
= (pState
== pLastState
);
3469 if (!bRepeat
&& pState
&& pLastState
)
3470 bRepeat
= (*pState
== *pLastState
);
3471 if (bRepeat
&& !bForce
)
3474 bInOwnChange
= true; // disable ModifyHdl (reset below)
3476 if ( pState
&& !pLastState
) // wieder enablen
3479 bool bHadObject
= pLastState
&& pLastState
->GetEditData();
3481 //! Before EditEngine gets eventually created (so it gets the right pools)
3483 pActiveViewSh
= pSourceSh
;
3485 pActiveViewSh
= PTR_CAST(ScTabViewShell
, SfxViewShell::Current());
3487 ImplCreateEditEngine();
3489 if ( pState
!= pLastState
)
3492 pLastState
= pState
? new ScInputHdlState( *pState
) : NULL
;
3495 if ( pState
&& pActiveViewSh
)
3497 ScModule
* pScMod
= SC_MOD();
3502 // hier auch fremde Referenzeingabe beruecksichtigen (z.B. Funktions-AP),
3503 // FormEditData falls gerade von der Hilfe auf Calc umgeschaltet wird:
3505 if ( !bFormulaMode
&& !pScMod
->IsFormulaMode() && !pScMod
->GetFormEditData() )
3507 bool bIgnore
= false;
3510 if (pState
->GetPos() != aCursorPos
)
3521 const ScAddress
& rSPos
= pState
->GetStartPos();
3522 const ScAddress
& rEPos
= pState
->GetEndPos();
3523 const EditTextObject
* pData
= pState
->GetEditData();
3524 OUString aString
= pState
->GetString();
3525 bool bTxtMod
= false;
3526 ScDocShell
* pDocSh
= pActiveViewSh
->GetViewData()->GetDocShell();
3527 ScDocument
* pDoc
= pDocSh
->GetDocument();
3529 aCursorPos
= pState
->GetPos();
3533 else if ( bHadObject
)
3535 else if ( bTextValid
)
3536 bTxtMod
= ( !aString
.equals(aCurrentText
) );
3538 bTxtMod
= ( !aString
.equals(GetEditText(pEngine
)) );
3540 if ( bTxtMod
|| bForce
)
3544 pEngine
->SetText( *pData
);
3545 if ( pInputWin
&& pInputWin
->IsMultiLineInput() )
3546 aString
= ScEditUtil::GetMultilineString(*pEngine
);
3548 aString
= GetEditText(pEngine
);
3549 lcl_RemoveTabs(aString
);
3551 aCurrentText
= OUString();
3555 aCurrentText
= aString
;
3556 bTextValid
= true; //! erst nur als String merken
3560 pInputWin
->SetTextString(aString
);
3563 if ( pInputWin
) // Bereichsanzeige
3566 const ScAddress::Details
aAddrDetails( pDoc
, aCursorPos
);
3568 // Ist der Bereich ein Name?
3569 //! per Timer suchen ???
3571 if ( pActiveViewSh
)
3572 pActiveViewSh
->GetViewData()->GetDocument()->
3573 GetRangeAtBlock( ScRange( rSPos
, rEPos
), &aPosStr
);
3575 if ( aPosStr
.isEmpty() ) // kein Name -> formatieren
3577 sal_uInt16 nFlags
= 0;
3578 if( aAddrDetails
.eConv
== formula::FormulaGrammar::CONV_XL_R1C1
)
3579 nFlags
|= SCA_COL_ABSOLUTE
| SCA_ROW_ABSOLUTE
;
3580 if ( rSPos
!= rEPos
)
3582 ScRange
r(rSPos
, rEPos
);
3583 nFlags
|= (nFlags
<< 4);
3584 aPosStr
= r
.Format(SCA_VALID
| nFlags
, pDoc
, aAddrDetails
);
3587 aPosStr
= aCursorPos
.Format(SCA_VALID
| nFlags
, pDoc
, aAddrDetails
);
3590 // Disable the accessible VALUE_CHANGE event
3591 bool bIsSuppressed
= pInputWin
->IsAccessibilityEventsSuppressed(false);
3592 pInputWin
->SetAccessibilityEventsSuppressed(true);
3593 pInputWin
->SetPosString(aPosStr
);
3594 pInputWin
->SetAccessibilityEventsSuppressed(bIsSuppressed
);
3595 pInputWin
->SetSumAssignMode();
3599 SFX_APP()->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW
) );
3601 // As long as the content is not edited, turn off online spelling.
3602 // Online spelling is turned back on in StartTable, after setting
3603 // the right language from cell attributes.
3605 sal_uLong nCntrl
= pEngine
->GetControlWord();
3606 if ( nCntrl
& EE_CNTRL_ONLINESPELLING
)
3607 pEngine
->SetControlWord( nCntrl
& ~EE_CNTRL_ONLINESPELLING
);
3612 bCommandErrorShown
= false;
3619 if(!pScMod
->IsFormulaMode()&& !pScMod
->IsRefDialogOpen()) //BugID 54702
3620 { //Wenn RefDialog offen, dann nicht enablen
3621 if ( !pInputWin
->IsEnabled())
3623 pInputWin
->Enable();
3626 DELETEZ( pDelayTimer
);
3630 else if(pScMod
->IsRefDialogOpen())
3631 { // Da jedes Dokument eigenes InputWin hat, sollte
3632 if ( !pDelayTimer
) // nochmals Timer gestartet werden, da sonst Ein-
3633 { // gabezeile evt. noch aktiv ist.
3634 pDelayTimer
= new Timer
;
3635 pDelayTimer
->SetTimeout( 500 ); // 100ms Verzoegerung
3636 pDelayTimer
->SetTimeoutHdl( LINK( this, ScInputHandler
, DelayTimer
) );
3637 pDelayTimer
->Start();
3642 else // !pState || !pActiveViewSh
3646 pDelayTimer
= new Timer
;
3647 pDelayTimer
->SetTimeout( 500 ); // 100ms Verzoegerung
3648 pDelayTimer
->SetTimeoutHdl( LINK( this, ScInputHandler
, DelayTimer
) );
3649 pDelayTimer
->Start();
3655 bInOwnChange
= false;
3658 void ScInputHandler::UpdateCellAdjust( SvxCellHorJustify eJust
)
3660 eAttrAdjust
= eJust
;
3664 void ScInputHandler::ResetDelayTimer()
3666 if(pDelayTimer
!=NULL
)
3668 DELETEZ( pDelayTimer
);
3672 pInputWin
->Enable();
3677 IMPL_LINK( ScInputHandler
, DelayTimer
, Timer
*, pTimer
)
3679 if ( pTimer
== pDelayTimer
)
3681 DELETEZ( pDelayTimer
);
3683 if ( NULL
== pLastState
|| SC_MOD()->IsFormulaMode() || SC_MOD()->IsRefDialogOpen())
3685 //! new method at ScModule to query if function autopilot is open
3687 SfxViewFrame
* pViewFrm
= SfxViewFrame::Current();
3688 if ( pViewFrm
&& pViewFrm
->GetChildWindow( SID_OPENDLG_FUNCTION
) )
3692 pInputWin
->EnableButtons( false );
3693 pInputWin
->Disable();
3696 else if ( !bFormulaMode
) // Formel auch z.B. bei Hilfe behalten
3698 bInOwnChange
= true; // disable ModifyHdl (reset below)
3700 pActiveViewSh
= NULL
;
3701 pEngine
->SetText( EMPTY_OUSTRING
);
3704 pInputWin
->SetPosString( EMPTY_OUSTRING
);
3705 pInputWin
->SetTextString( EMPTY_OUSTRING
);
3706 pInputWin
->Disable();
3709 bInOwnChange
= false;
3716 void ScInputHandler::InputSelection( EditView
* pView
)
3720 UpdateParenthesis(); // Selektion geaendert -> Klammer-Hervorhebung neu
3722 // when the selection is changed manually, stop overwriting parentheses
3726 void ScInputHandler::InputChanged( EditView
* pView
, bool bFromNotify
)
3730 // #i20282# DataChanged needs to know if this is from the input line's modify handler
3731 bool bFromTopNotify
= ( bFromNotify
&& pView
== pTopView
);
3733 bool bNewView
= DataChanging(); //! kann das hier ueberhaupt sein?
3734 aCurrentText
= pView
->GetEditEngine()->GetText(); // auch den String merken
3735 pEngine
->SetText( aCurrentText
);
3736 DataChanged( bFromTopNotify
);
3737 bTextValid
= true; // wird in DataChanged auf false gesetzt
3739 if ( pActiveViewSh
)
3741 ScViewData
* pViewData
= pActiveViewSh
->GetViewData();
3743 pViewData
->GetDocShell()->PostEditView( pEngine
, aCursorPos
);
3745 pViewData
->EditGrowY();
3746 pViewData
->EditGrowX();
3752 const OUString
& ScInputHandler::GetEditString()
3756 aCurrentText
= pEngine
->GetText(); // immer neu aus Engine
3760 return aCurrentText
;
3763 Size
ScInputHandler::GetTextSize()
3767 aSize
= Size( pEngine
->CalcTextWidth(), pEngine
->GetTextHeight() );
3772 bool ScInputHandler::GetTextAndFields( ScEditEngineDefaulter
& rDestEngine
)
3777 // Feldbefehle enthalten?
3779 sal_Int32 nParCnt
= pEngine
->GetParagraphCount();
3780 SfxItemSet aSet
= pEngine
->GetAttribs( ESelection(0,0,nParCnt
,0) );
3781 SfxItemState eFieldState
= aSet
.GetItemState( EE_FEATURE_FIELD
, false );
3782 if ( eFieldState
== SFX_ITEM_DONTCARE
|| eFieldState
== SFX_ITEM_SET
)
3786 EditTextObject
* pObj
= pEngine
->CreateTextObject();
3787 rDestEngine
.SetText(*pObj
);
3790 // Attribute loeschen
3792 for (sal_Int32 i
=0; i
<nParCnt
; i
++)
3793 rDestEngine
.QuickRemoveCharAttribs( i
);
3795 // Absaetze zusammenfassen
3797 while ( nParCnt
> 1 )
3799 xub_StrLen nLen
= rDestEngine
.GetTextLen( 0 );
3800 ESelection
aSel( 0,nLen
, 1,0 );
3801 rDestEngine
.QuickInsertText( OUString(' '), aSel
); // Umbruch durch Space ersetzen
3811 //------------------------------------------------------------------------
3812 // Methoden fuer FunktionsAutopiloten:
3813 // InputGetSelection, InputSetSelection, InputReplaceSelection, InputGetFormulaStr
3814 //------------------------------------------------------------------------
3816 void ScInputHandler::InputGetSelection( xub_StrLen
& rStart
, xub_StrLen
& rEnd
)
3818 rStart
= nFormSelStart
;
3822 //------------------------------------------------------------------------
3824 EditView
* ScInputHandler::GetFuncEditView()
3826 UpdateActiveView(); // wegen pTableView
3828 EditView
* pView
= NULL
;
3831 pInputWin
->MakeDialogEditView();
3832 pView
= pInputWin
->GetEditView();
3836 if ( eMode
!= SC_INPUT_TABLE
)
3838 bCreatingFuncView
= true; // RangeFinder nicht anzeigen
3839 SetMode( SC_INPUT_TABLE
);
3840 bCreatingFuncView
= false;
3842 pTableView
->GetEditEngine()->SetText( EMPTY_OUSTRING
);
3850 //------------------------------------------------------------------------
3852 void ScInputHandler::InputSetSelection( xub_StrLen nStart
, xub_StrLen nEnd
)
3854 if ( nStart
<= nEnd
)
3856 nFormSelStart
= nStart
;
3861 nFormSelEnd
= nStart
;
3862 nFormSelStart
= nEnd
;
3865 EditView
* pView
= GetFuncEditView();
3867 pView
->SetSelection( ESelection(0,nStart
, 0,nEnd
) );
3872 //------------------------------------------------------------------------
3874 void ScInputHandler::InputReplaceSelection( const OUString
& rStr
)
3877 pRefViewSh
= pActiveViewSh
;
3879 OSL_ENSURE(nFormSelEnd
>=nFormSelStart
,"Selektion kaputt...");
3881 sal_Int32 nOldLen
= nFormSelEnd
- nFormSelStart
;
3882 sal_Int32 nNewLen
= rStr
.getLength();
3884 OUStringBuffer
aBuf(aFormText
);
3886 aBuf
.remove(nFormSelStart
, nOldLen
);
3888 aBuf
.insert(nFormSelStart
, rStr
);
3890 aFormText
= aBuf
.makeStringAndClear();
3892 nFormSelEnd
= nFormSelStart
+ nNewLen
;
3894 EditView
* pView
= GetFuncEditView();
3897 pView
->SetEditEngineUpdateMode( false );
3898 pView
->GetEditEngine()->SetText( aFormText
);
3899 pView
->SetSelection( ESelection(0,nFormSelStart
, 0,nFormSelEnd
) );
3900 pView
->SetEditEngineUpdateMode( true );
3905 void ScInputHandler::InputTurnOffWinEngine()
3907 bInOwnChange
= true; // disable ModifyHdl (reset below)
3909 eMode
= SC_INPUT_NONE
;
3910 /* TODO: it would be better if there was some way to reset the input bar
3911 * engine instead of deleting and having it recreate through
3912 * GetFuncEditView(), but first least invasively let this fix fdo#71667 and
3913 * fdo#72278 without reintroducing fdo#69971. */
3914 StopInputWinEngine(true);
3916 bInOwnChange
= false;
3919 //========================================================================
3921 //========================================================================
3923 ScInputHdlState::ScInputHdlState( const ScAddress
& rCurPos
,
3924 const ScAddress
& rStartPos
,
3925 const ScAddress
& rEndPos
,
3926 const OUString
& rString
,
3927 const EditTextObject
* pData
)
3928 : aCursorPos ( rCurPos
),
3929 aStartPos ( rStartPos
),
3930 aEndPos ( rEndPos
),
3931 aString ( rString
),
3932 pEditData ( pData
? pData
->Clone() : NULL
)
3936 //------------------------------------------------------------------------
3938 ScInputHdlState::ScInputHdlState( const ScInputHdlState
& rCpy
)
3939 : pEditData ( NULL
)
3944 //------------------------------------------------------------------------
3946 ScInputHdlState::~ScInputHdlState()
3951 //------------------------------------------------------------------------
3953 int ScInputHdlState::operator==( const ScInputHdlState
& r
) const
3955 return ( (aStartPos
== r
.aStartPos
)
3956 && (aEndPos
== r
.aEndPos
)
3957 && (aCursorPos
== r
.aCursorPos
)
3958 && (aString
== r
.aString
)
3959 && ScGlobal::EETextObjEqual( pEditData
, r
.pEditData
) );
3962 //------------------------------------------------------------------------
3964 ScInputHdlState
& ScInputHdlState::operator=( const ScInputHdlState
& r
)
3968 aCursorPos
= r
.aCursorPos
;
3969 aStartPos
= r
.aStartPos
;
3970 aEndPos
= r
.aEndPos
;
3971 aString
= r
.aString
;
3972 pEditData
= r
.pEditData
? r
.pEditData
->Clone() : NULL
;
3977 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */