Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / app / inputhdl.cxx
blob0c6bbc51a1cbbf478df2d684444d8f83d9e7e387
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
57 #include "docsh.hxx"
58 #include "scmod.hxx"
59 #include "uiitems.hxx"
60 #include "global.hxx"
61 #include "sc.hrc"
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
93 namespace {
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);
119 ++it;
122 for (; it != itEnd; ++it)
124 const ScTypedStrData& rData = *it;
125 if (rData.GetStringType() == ScTypedStrData::Value)
126 // skip values.
127 continue;
129 if (!ScGlobal::GetpTransliteration()->isMatch(rStart, rData.GetString()))
130 // not a match.
131 continue;
133 rResult = rData.GetString();
134 return (++it).base(); // convert the reverse iterator back to iterator.
137 else // vorwaerts
139 ScTypedCaseStrSet::const_iterator it = rDataSet.begin(), itEnd = rDataSet.end();
140 if (itPos != rDataSet.end())
142 it = itPos;
143 ++it;
146 for (; it != itEnd; ++it)
148 const ScTypedStrData& rData = *it;
149 if (rData.GetStringType() == ScTypedStrData::Value)
150 // skip values.
151 continue;
153 if (!ScGlobal::GetpTransliteration()->isMatch(rStart, rData.GetString()))
154 // not a match.
155 continue;
157 rResult = rData.GetString();
158 return it;
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)
172 continue;
174 if (!ScGlobal::GetpTransliteration()->isEqual(rData.GetString(), rString))
175 continue;
177 return rData.GetString();
179 return rString;
182 void removeChars(OUString& rStr, sal_Unicode c)
184 OUStringBuffer aBuf(rStr);
185 for (sal_Int32 i = 0, n = aBuf.getLength(); i < n; ++i)
187 if (aBuf[i] == c)
188 aBuf[i] = ' ';
190 rStr = aBuf.makeStringAndClear();
195 void ScInputHandler::InitRangeFinder( const OUString& rFormula )
197 DeleteRangeFinder();
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() )
203 return;
205 OUString aDelimiters = ScEditUtil::ModifyDelimiters(
206 OUString::createFromAscii( pMinDelimiters ) );
208 sal_Int32 nColon = aDelimiters.indexOf( ':' );
209 if ( nColon != -1 )
210 aDelimiters = aDelimiters.replaceAt( nColon, 1, ""); // Delimiter ohne Doppelpunkt
211 sal_Int32 nDot = aDelimiters.indexOf(cSheetSep);
212 if ( nDot != -1 )
213 aDelimiters = aDelimiters.replaceAt( nDot, 1 , ""); // Delimiter ohne Punkt
215 const sal_Unicode* pChar = rFormula.getStr();
216 sal_Int32 nLen = rFormula.getLength();
217 sal_Int32 nPos = 0;
218 sal_Int32 nStart = 0;
219 sal_uInt16 nCount = 0;
220 ScRange aRange;
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
228 ++nPos;
229 while (nPos<nLen && pChar[nPos] != '"') // bis zum Ende ueberlesen
230 ++nPos;
232 ++nPos; // Trennzeichen oder schliessender Quote
235 // Text zwischen Trennern
236 nStart = nPos;
237 handle_r1c1:
238 while ( nPos<nLen && !ScGlobal::UnicodeStrChr( aDelimiters.getStr(), pChar[nPos] ) )
239 ++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] &&
246 NULL != pDoc &&
247 formula::FormulaGrammar::CONV_XL_R1C1 == pDoc->GetAddressConvention() )
249 nPos++;
250 goto handle_r1c1;
253 if ( nPos > nStart )
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;
274 if (!nCount)
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 ) ),
285 EE_CHAR_COLOR ) );
286 pEngine->QuickSetAttribs( aSet, aSel );
287 ++nCount;
291 // letzten Trenner nicht ueberlesen, koennte ja ein Quote sein (?)
294 if (nCount)
296 pEngine->SetUpdateMode( true );
298 pDocSh->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER ) );
302 static void lcl_Replace( EditView* pView, const OUString& rNewStr, const ESelection& rOldSel )
304 if ( pView )
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 );
340 DataChanging();
342 lcl_Replace( pTopView, aNewStr, aOldSel );
343 lcl_Replace( pTableView, aNewStr, aOldSel );
345 bInRangeUpdate = true;
346 DataChanged();
347 bInRangeUpdate = false;
349 long nDiff = aNewStr.getLength() - (long)(nOldEnd-nOldStart);
351 pData->aRef = rNew;
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);
362 else
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 )
400 int nDir;
401 sal_Unicode c1, c2 = 0;
402 c1 = rStr[nPos];
403 switch ( c1 )
405 case '(' :
406 c2 = ')';
407 nDir = 1;
408 break;
409 case ')' :
410 c2 = '(';
411 nDir = -1;
412 break;
413 case '<' :
414 c2 = '>';
415 nDir = 1;
416 break;
417 case '>' :
418 c2 = '<';
419 nDir = -1;
420 break;
421 case '{' :
422 c2 = '}';
423 nDir = 1;
424 break;
425 case '}' :
426 c2 = '{';
427 nDir = -1;
428 break;
429 case '[' :
430 c2 = ']';
431 nDir = 1;
432 break;
433 case ']' :
434 c2 = '[';
435 nDir = -1;
436 break;
437 default:
438 nDir = 0;
440 if ( !nDir )
441 return -1;
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 )
449 p = p0;
450 p1 = p0 + nPos;
452 else
454 p = p0 + nPos;
455 p1 = p0 + nLen;
457 while ( p < p1 )
459 if ( *p++ == '\"' )
460 nQuotes++;
462 // Odd number of quotes that we find ourselves in a string
463 bool bLookInString = ((nQuotes % 2) != 0);
464 bool bInString = bLookInString;
465 p = p0 + nPos;
466 p1 = (nDir < 0 ? p0 : p0 + nLen) ;
467 sal_uInt16 nLevel = 1;
468 while ( p != p1 && nLevel )
470 p += nDir;
471 if ( *p == '\"' )
473 bInString = !bInString;
474 if ( bLookInString && !bInString )
475 p = p1; //That's it then
477 else if ( bInString == bLookInString )
479 if ( *p == c1 )
480 nLevel++;
481 else if ( *p == c2 )
482 nLevel--;
485 if ( nLevel )
486 return -1;
487 return (sal_Int32) (p - p0);
490 //==================================================================
492 ScInputHandler::ScInputHandler()
493 : pInputWin( NULL ),
494 pEngine( NULL ),
495 pTableView( NULL ),
496 pTopView( NULL ),
497 pColumnData( NULL ),
498 pFormulaData( NULL ),
499 pFormulaDataPara( NULL ),
500 pTipVisibleParent( NULL ),
501 nTipVisible( 0 ),
502 pTipVisibleSecParent( NULL ),
503 nTipVisibleSec( 0 ),
504 nFormSelStart( 0 ),
505 nFormSelEnd( 0 ),
506 nAutoPar( 0 ),
507 eMode( SC_INPUT_NONE ),
508 bUseTab( false ),
509 bTextValid( true ),
510 bModified( false ),
511 bSelIsRef( false ),
512 bFormulaMode( false ),
513 bInRangeUpdate( false ),
514 bParenthesisShown( false ),
515 bCreatingFuncView( false ),
516 bInEnterHandler( false ),
517 bCommandErrorShown( false ),
518 bInOwnChange( false ),
519 bProtected( false ),
520 bCellHasPercentFormat( false ),
521 bLastIsSymbol( false ),
522 nValidation( 0 ),
523 eAttrAdjust( SVX_HOR_JUSTIFY_STANDARD ),
524 aScaleX( 1,1 ),
525 aScaleY( 1,1 ),
526 pRefViewSh( NULL ),
527 pLastPattern( NULL ),
528 pEditDefaults( NULL ),
529 pLastState( NULL ),
530 pDelayTimer( 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;
556 delete pEngine;
557 delete pLastState;
558 delete pDelayTimer;
559 delete pColumnData;
560 delete pFormulaData;
561 delete pFormulaDataPara;
564 void ScInputHandler::SetRefScale( const Fraction& rX, const Fraction& rY )
566 if ( rX != aScaleX || rY != aScaleY )
568 aScaleX = rX;
569 aScaleY = rY;
570 if (pEngine)
572 MapMode aMode( MAP_100TH_MM, Point(), aScaleX, aScaleY );
573 pEngine->SetRefMapMode( aMode );
578 void ScInputHandler::UpdateRefDevice()
580 if (!pEngine)
581 return;
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%
588 else
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() );
593 else
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()
609 if ( !pEngine )
611 if ( pActiveViewSh )
613 ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocShell()->GetDocument();
614 pEngine = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
616 else
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;
636 if ( bDisable )
637 nCntrl &= ~EE_CNTRL_AUTOCORRECT;
638 else
639 nCntrl |= EE_CNTRL_AUTOCORRECT;
641 if ( nCntrl != nOld )
642 pEngine->SetControlWord(nCntrl);
645 void ScInputHandler::UpdateSpellSettings( bool bFromStartTab )
647 if ( pActiveViewSh )
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;
665 if( bOnlineSpell )
666 nCntrl |= EE_CNTRL_ONLINESPELLING;
667 else
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;
672 else
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();
693 if ( bHyphen ) {
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()
708 if ( pActiveViewSh )
710 ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocShell()->GetDocument();
712 if ( pFormulaData )
713 pFormulaData->clear();
714 else
716 pFormulaData = new ScTypedCaseStrSet;
717 miAutoPosFormula = pFormulaData->end();
720 if( pFormulaDataPara )
721 pFormulaDataPara->clear();
722 else
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();
733 if (pMRUList)
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;
744 aEntry += "()";
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 )
769 HideTip();
770 return 0;
773 IMPL_LINK( ScInputHandler, ShowHideTipVisibleSecParentListener, VclWindowEvent*, pEvent )
775 if( pEvent->GetId() == VCLEVENT_OBJECT_DYING || pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
776 HideTipBelow();
777 return 0;
780 void ScInputHandler::HideTip()
782 if ( nTipVisible )
784 if (pTipVisibleParent)
785 pTipVisibleParent->RemoveEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleParentListener ) );
786 Help::HideTip( nTipVisible );
787 nTipVisible = 0;
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 );
799 nTipVisibleSec = 0;
800 pTipVisibleSecParent = NULL;
802 aManualTip = OUString();
805 void ScInputHandler::ShowTipCursor()
807 HideTip();
808 HideTipBelow();
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();
818 aSel.Adjust();
819 if( aSel.nEndPos )
821 if ( aFormula.getLength() < aSel.nEndPos )
822 return;
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;
830 sal_uInt16 nArgs;
831 bool bFound = false;
832 FormulaHelper aHelper(ScGlobal::GetStarCalcFunctionMgr());
834 while( !bFound )
836 aSelText += ")";
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)) )
842 continue;
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());
851 OUString aNew;
852 ScTypedCaseStrSet::const_iterator it =
853 findText(*pFormulaDataPara, pFormulaDataPara->end(), ppFDesc->getFunctionName(), aNew, false);
854 if (it != pFormulaDataPara->end())
856 bool bFlag = false;
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 )
863 nActive = i+1;
864 bFlag = true;
866 nArgPos+=nLength+1;
868 if( bFlag )
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];
880 if( cNext == '(' )
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];
892 if( cNext == '(' )
894 nStartPosition = i+1;
896 else if( cNext == cSep )
898 nCount ++;
899 nEndPosition = i;
900 if( nCount == nActive )
902 break;
904 nStartPosition = nEndPosition+1;
908 else
910 sal_uInt16 nCount = 0;
911 for (sal_Int32 i = 0; i < aNew.getLength(); ++i)
913 sal_Unicode cNext = aNew[i];
914 if( cNext == '(' )
916 nStartPosition = i+1;
918 else if( cNext == cSep )
920 nCount ++;
921 nEndPosition = i;
922 if( nCount == nActive )
924 break;
926 nStartPosition = nEndPosition+1;
928 else if( cNext == cSheetSep )
930 continue;
935 if (nStartPosition > 0)
937 OUStringBuffer aBuf;
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 );
943 bFound = true;
946 else
948 ShowTipBelow( aNew );
949 bFound = true;
955 else
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 ] == '=')
962 break;
964 OUString aNew;
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 );
973 bFound = true;
975 else
976 break;
978 else
980 break;
988 void ScInputHandler::ShowTip( const OUString& rText )
990 // aManualTip muss hinterher von aussen gesetzt werden
991 HideTip();
993 EditView* pActiveView = pTopView ? pTopView : pTableView;
994 if (pActiveView)
996 Point aPos;
997 pTipVisibleParent = pActiveView->GetWindow();
998 Cursor* pCur = pActiveView->GetCursor();
999 if (pCur)
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 )
1012 HideTipBelow();
1014 EditView* pActiveView = pTopView ? pTopView : pTableView;
1015 if ( pActiveView )
1017 Point aPos;
1018 pTipVisibleSecParent = pActiveView->GetWindow();
1019 Cursor* pCur = pActiveView->GetCursor();
1020 if ( pCur )
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();
1046 aSel.Adjust();
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() )
1053 return;
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;
1067 sal_uInt16 nArgs;
1068 bool bFound = false;
1070 OUString aText = pEngine->GetWord( 0, aSel.nEndPos-1 );
1071 if (!aText.isEmpty())
1073 OUString aNew;
1074 miAutoPosFormula = pFormulaData->end();
1075 miAutoPosFormula = findText(*pFormulaData, miAutoPosFormula, aText, aNew, false);
1076 if (miAutoPosFormula != pFormulaData->end())
1078 ShowTip( aNew );
1079 aAutoSearch = aText;
1082 FormulaHelper aHelper(ScGlobal::GetStarCalcFunctionMgr());
1084 while( !bFound )
1086 aFormula += ")";
1087 nLeftParentPos = lcl_MatchParenthesis( aFormula, aFormula.getLength()-1 );
1088 if( nLeftParentPos == -1 )
1089 break;
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)) )
1094 continue;
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());
1103 OUString aNew;
1104 ScTypedCaseStrSet::const_iterator it =
1105 findText(*pFormulaDataPara, pFormulaDataPara->end(), ppFDesc->getFunctionName(), aNew, false);
1106 if (it != pFormulaDataPara->end())
1108 bool bFlag = false;
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 )
1115 nActive = i+1;
1116 bFlag = true;
1118 nArgPos+=nLength+1;
1120 if( bFlag )
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];
1132 if( cNext == '(' )
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];
1144 if( cNext == '(' )
1146 nStartPosition = i+1;
1148 else if( cNext == cSep )
1150 nCount ++;
1151 nEndPosition = i;
1152 if( nCount == nActive )
1154 break;
1156 nStartPosition = nEndPosition+1;
1160 else
1162 sal_uInt16 nCount = 0;
1163 for (sal_Int32 i = 0; i < aNew.getLength(); ++i)
1165 sal_Unicode cNext = aNew[i];
1166 if( cNext == '(' )
1168 nStartPosition = i+1;
1170 else if( cNext == cSep )
1172 nCount ++;
1173 nEndPosition = i;
1174 if( nCount == nActive )
1176 break;
1178 nStartPosition = nEndPosition+1;
1180 else if( cNext == cSheetSep )
1182 continue;
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 );
1195 bFound = true;
1198 else
1200 ShowTipBelow( aNew );
1201 bFound = true;
1211 void ScInputHandler::NextFormulaEntry( bool bBack )
1213 EditView* pActiveView = pTopView ? pTopView : pTableView;
1214 if ( pActiveView && pFormulaData )
1216 OUString aNew;
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
1227 if (pActiveView)
1228 pActiveView->ShowCursor();
1231 static void lcl_CompleteFunction( EditView* pView, const OUString& rInsert, bool& rParInserted )
1233 if (pView)
1235 ESelection aSel = pView->GetSelection();
1236 --aSel.nStartPos;
1237 --aSel.nEndPos;
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] == ')' );
1245 if ( bDoParen )
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];
1256 if ( cNext == '(' )
1258 bDoParen = false;
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();
1269 --aSel.nStartPos;
1270 --aSel.nEndPos;
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 );
1289 DataChanged();
1290 ShowTipCursor();
1292 if (bParInserted)
1293 AutoParAdded();
1296 HideTip();
1298 EditView* pActiveView = pTopView ? pTopView : pTableView;
1299 if (pActiveView)
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())
1313 return OUString();
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();
1322 if ( bColRowName )
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() ) );
1334 else
1335 bColRowName = false;
1338 sal_uInt16 nErrCode = pCalc->GetErrCode();
1339 if ( nErrCode != 0 )
1340 return ScGlobal::GetErrorString(nErrCode);
1342 SvNumberFormatter& aFormatter = *(pDoc->GetFormatTable());
1343 OUString aValue;
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
1352 else
1354 OUString aStr = pCalc->GetString().getString();
1355 sal_uLong nFormat = aFormatter.GetStandardFormat(
1356 pCalc->GetFormatType(), ScGlobal::eLnge);
1358 Color* pColor;
1359 aFormatter.GetOutputString( aStr, nFormat,
1360 aValue, &pColor );
1363 aValue = "\"" + aValue + "\"";
1364 //! Anfuehrungszeichen im String escapen ????
1367 ScRange aTestRange;
1368 if ( bColRowName || (aTestRange.Parse(rFormula) & SCA_VALID) )
1369 aValue = aValue + " ...";
1371 return aValue;
1374 void ScInputHandler::FormulaPreview()
1376 OUString aValue;
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
1391 if (pFormulaData)
1392 miAutoPosFormula = pFormulaData->end();
1393 if (pColumnData)
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 );
1416 if ( pTopView )
1417 pTopView->SetSelection( aAllSel );
1418 if ( pTableView )
1419 pTableView->SetSelection( aAllSel );
1422 ESelection aSel = pActiveView->GetSelection();
1423 aSel.Adjust();
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 ???
1441 aSel.nStartPos = 1;
1442 if ( pTopView )
1443 pTopView->SetSelection( aSel );
1444 if ( pTableView )
1445 pTableView->SetSelection( aSel );
1448 if ( pTopView )
1449 pTopView->InsertText( aInsert, true );
1450 if ( pTableView )
1451 pTableView->InsertText( aInsert, true );
1453 DataChanged();
1456 HideTip();
1459 void ScInputHandler::ResetAutoPar()
1461 nAutoPar = 0;
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] == ')' )
1481 return true;
1483 return false;
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;
1492 if (pActiveView)
1494 ESelection aSel = pActiveView->GetSelection();
1495 ++aSel.nStartPos;
1496 ++aSel.nEndPos;
1498 // this is in a formula (only one paragraph), so the selection
1499 // can be used directly for the TopView
1501 if ( pTopView )
1502 pTopView->SetSelection( aSel );
1503 if ( pTableView )
1504 pTableView->SetSelection( aSel );
1507 OSL_ENSURE(nAutoPar, "SkipClosingPar: count is wrong");
1508 --nAutoPar;
1512 // Auto-Eingabe
1515 void ScInputHandler::GetColData()
1517 if ( pActiveViewSh )
1519 ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocShell()->GetDocument();
1521 if ( pColumnData )
1522 pColumnData->clear();
1523 else
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();
1545 aSel.Adjust();
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())
1556 OUString aNew;
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
1574 // typed character
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
1579 if ( pTableView )
1581 pTableView->InsertText( aIns, false );
1582 pTableView->SetSelection( aSelection );
1584 if ( pTopView )
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
1597 OUString aDummy;
1598 ScTypedCaseStrSet::const_iterator itNextPos =
1599 findText(*pColumnData, miAutoPosColumn, aText, aDummy, false);
1600 bUseTab = itNextPos != pColumnData->end();
1602 else
1603 bUseTab = true;
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();
1621 aSel.Adjust();
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 )
1630 OUString aNew;
1631 ScTypedCaseStrSet::const_iterator itNew =
1632 findText(*pColumnData, miAutoPosColumn, aAutoSearch, aNew, bBack);
1634 if (itNew != pColumnData->end())
1636 // match found!
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
1644 if ( pTableView )
1646 pTableView->DeleteSelected();
1647 pTableView->InsertText( aIns, false );
1648 pTableView->SetSelection( ESelection(
1649 aSel.nEndPara, aSel.nStartPos + aIns.getLength(),
1650 aSel.nEndPara, aSel.nStartPos ) );
1652 if ( pTopView )
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
1670 if (pActiveView)
1671 pActiveView->ShowCursor();
1675 // Klammern hervorheben
1678 void ScInputHandler::UpdateParenthesis()
1680 // Klammern suchen
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();
1690 if (aSel.nStartPos)
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 );
1700 if ( nOther != -1 )
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 );
1722 bFound = true;
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 )
1748 delete pLastState;
1749 pLastState = NULL;
1750 pLastPattern = NULL;
1753 if ( pViewSh == pRefViewSh )
1755 //! Die Eingabe kommt aus dem EnterHandler nicht mehr an
1756 // Trotzdem wird immerhin der Editmodus beendet
1758 EnterHandler();
1759 bFormulaMode = false;
1760 pRefViewSh = NULL;
1761 SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
1762 SC_MOD()->SetRefInputHdl(NULL);
1763 if (pInputWin)
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() ) :
1791 NULL;
1793 sal_uInt16 nCount = pEngine->GetViewCount();
1794 if (nCount > 0)
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 )
1802 pTableView = pThis;
1805 else
1806 pTableView = NULL;
1808 if (pInputWin && eMode == SC_INPUT_TOP )
1809 pTopView = pInputWin->GetEditView();
1810 else
1811 pTopView = NULL;
1814 void ScInputHandler::StopInputWinEngine( bool bAll )
1816 if (pInputWin)
1817 pInputWin->StopEditEngine( bAll );
1819 pTopView = NULL; // invalid now
1822 EditView* ScInputHandler::GetActiveView()
1824 UpdateActiveView();
1825 return pTopView ? pTopView : pTableView;
1828 void ScInputHandler::ForgetLastPattern()
1830 pLastPattern = NULL;
1831 if ( !pLastState && pActiveViewSh )
1832 pActiveViewSh->UpdateInputHandler( true ); // Status neu holen
1833 else
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;
1854 break;
1855 case SVX_HOR_JUSTIFY_BLOCK:
1856 eSvxAdjust = SVX_ADJUST_BLOCK;
1857 break;
1858 case SVX_HOR_JUSTIFY_CENTER:
1859 eSvxAdjust = SVX_ADJUST_CENTER;
1860 break;
1861 case SVX_HOR_JUSTIFY_RIGHT:
1862 eSvxAdjust = SVX_ADJUST_RIGHT;
1863 break;
1864 default: // SVX_HOR_JUSTIFY_LEFT
1865 eSvxAdjust = SVX_ADJUST_LEFT;
1866 break;
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();
1891 if ( bUndo )
1892 pEngine->EnableUndo( false );
1894 // non-default paragraph attributes (e.g. from clipboard)
1895 // must be turned into character attributes
1896 pEngine->RemoveParaAttribs();
1898 if ( bUndo )
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()))
1924 return false;
1926 if (pActiveViewSh)
1928 ImplCreateEditEngine();
1929 UpdateActiveView();
1930 SyncViews();
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 );
1938 else
1939 aTester.TestSelectedBlock(
1940 pDoc, aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Col(), aCursorPos.Row(), rMark );
1942 bool bStartInputMode = true;
1944 if (!aTester.IsEditable())
1946 bProtected = true;
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
1950 // line.
1951 bool bShowError = (!bInputActivated || aTester.GetMessageId() != STR_PROTECTIONERR) &&
1952 !pActiveViewSh->GetViewData()->GetDocShell()->IsReadOnly();
1953 if (bShowError)
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.
1964 if ( bFromCommand )
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(),
1982 aCursorPos.Row(),
1983 aCursorPos.Tab() );
1984 if (pPattern != pLastPattern)
1986 // Prozent-Format?
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 ) );
1997 else
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();
2004 else
2005 nValidation = 0;
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.
2015 //! Any problems?
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 );
2033 // Ausrichtung
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
2052 OUString aStr;
2053 if (bTextValid)
2055 pEngine->SetText(aCurrentText);
2056 aStr = aCurrentText;
2057 bTextValid = false;
2058 aCurrentText = OUString();
2060 else
2061 aStr = GetEditText(pEngine);
2063 if (aStr.startsWith("{=") && aStr.endsWith("}") ) // Matrix-Formel ?
2065 aStr = aStr.copy(1, aStr.getLength() -2);
2066 pEngine->SetText(aStr);
2067 if ( pInputWin )
2068 pInputWin->SetTextString(aStr);
2071 UpdateAdjust( cTyped );
2073 if ( bAutoComplete )
2074 GetColData();
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();
2087 return bNewTable;
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();
2096 if (nCount > 1)
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 )
2122 if (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)
2155 OUString aText;
2156 if ( pInputWin->IsMultiLineInput() )
2157 aText = ScEditUtil::GetMultilineString(*pEngine);
2158 else
2159 aText = GetEditText(pEngine);
2160 lcl_RemoveTabs(aText);
2161 pInputWin->SetTextString(aText);
2163 return 0;
2166 bool ScInputHandler::DataChanging( sal_Unicode cTyped, bool bFromCommand ) // return true = new view created
2168 if (pActiveViewSh)
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 );
2174 else
2175 return 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();
2197 if (bSetModified)
2198 bModified = true;
2199 bSelIsRef = false;
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)
2208 OUString aText;
2209 if ( pInputWin && pInputWin->IsMultiLineInput() )
2210 aText = ScEditUtil::GetMultilineString(*pEngine);
2211 else
2212 aText = GetEditText(pEngine);
2213 lcl_RemoveTabs(aText);
2215 if ( pInputWin )
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
2233 if (!bNeedGrow)
2235 // Cursor vor dem Ende?
2236 ESelection aSel = pActiveView->GetSelection();
2237 aSel.Adjust();
2238 bNeedGrow = ( aSel.nEndPos != pEngine->GetTextLen(aSel.nEndPara) );
2240 if (!bNeedGrow)
2242 bNeedGrow = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() );
2244 if (bNeedGrow)
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;
2262 if (bIsFormula)
2264 const OUString& rText = pEngine->GetText(0);
2265 bIsFormula = !rText.isEmpty() &&
2266 (rText[0] == '=' || rText[0] == '+' || rText[0] == '-');
2269 if ( bIsFormula )
2271 if (!bFormulaMode)
2273 bFormulaMode = true;
2274 pRefViewSh = pActiveViewSh;
2275 pSfxApp->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2276 SC_MOD()->SetRefInputHdl(this);
2277 if (pInputWin)
2278 pInputWin->SetFormulaMode(true);
2280 if ( bAutoComplete )
2281 GetFormulaData();
2283 UpdateParenthesis();
2284 UpdateAutoCorrFlag();
2287 else // ausschalten
2289 if (bFormulaMode)
2291 ShowRefFrame();
2292 bFormulaMode = false;
2293 pRefViewSh = NULL;
2294 pSfxApp->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2295 SC_MOD()->SetRefInputHdl(NULL);
2296 if (pInputWin)
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 )
2317 bFound = true;
2318 pOneFrame = SfxViewFrame::GetNext( *pOneFrame );
2321 if (bFound)
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
2330 else
2332 OSL_FAIL("ViewFrame fuer Referenzeingabe ist nicht mehr da");
2337 void ScInputHandler::RemoveSelection()
2339 EditView* pActiveView = pTopView ? pTopView : pTableView;
2340 if (!pActiveView)
2341 return;
2343 ESelection aSel = pActiveView->GetSelection();
2344 aSel.nStartPara = aSel.nEndPara;
2345 aSel.nStartPos = aSel.nEndPos;
2346 if (pTableView)
2347 pTableView->SetSelection( aSel );
2348 if (pTopView)
2349 pTopView->SetSelection( aSel );
2352 void ScInputHandler::InvalidateAttribs()
2354 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
2355 if (pViewFrm)
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 )
2388 return;
2390 ImplCreateEditEngine();
2392 if (bProtected)
2394 eMode = SC_INPUT_NONE;
2395 StopInputWinEngine( true );
2396 if (pActiveViewSh)
2397 pActiveViewSh->GetActiveWin()->GrabFocus();
2398 return;
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;
2408 eMode = eNewMode;
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))
2418 if (pActiveViewSh)
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 )
2431 // Selektion bleibt
2433 else
2435 pEngine->GetView(i)->
2436 SetSelection( ESelection( nPara, nLen, nPara, nLen ) );
2438 pEngine->GetView(i)->ShowCursor(false);
2442 UpdateActiveView();
2443 if (eMode==SC_INPUT_TABLE || eMode==SC_INPUT_TYPE)
2445 if (pTableView)
2446 pTableView->SetEditEngineUpdateMode(true);
2448 else
2450 if (pTopView)
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' )
2471 return false;
2473 return true;
2476 static void lcl_SelectionToEnd( EditView* pView )
2478 if ( pView )
2480 EditEngine* pEngine = pView->GetEditEngine();
2481 sal_Int32 nParCnt = pEngine->GetParagraphCount();
2482 if ( nParCnt == 0 )
2483 nParCnt = 1;
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;
2522 if (pTopView)
2523 pTopView->CompleteAutoCorrect(); // CompleteAutoCorrect fuer beide Views
2524 if (pTableView)
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 );
2542 if (!bOk)
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() );
2563 if ( pDPObj )
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 );
2569 bForget = true;
2573 std::vector<editeng::MisspellRanges> aMisspellRanges;
2574 pEngine->CompleteOnlineSpelling();
2575 bool bSpellErrors = !bFormulaMode && pEngine->HasOnlineSpellErrors();
2576 if ( bSpellErrors )
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() );
2586 if (pPattern)
2588 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2589 // without conditional format, as in ScColumn::SetString
2590 sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
2591 double nVal;
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();
2608 if ( nParCnt == 0 )
2609 nParCnt = 1;
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;
2620 break;
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 );
2647 if ( pCommonAttrs )
2649 ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocument();
2650 pCellAttrs = new ScPatternAttr( pDoc->GetPool() );
2651 pCellAttrs->GetFromEditItemSet( pCommonAttrs );
2652 delete pCommonAttrs;
2656 // clear ParaAttribs (including adjustment)
2658 RemoveAdjust();
2660 bool bAttrib = false; // Formatierung vorhanden ?
2661 // check if EditObject is needed
2663 if (nParCnt > 1)
2664 bAttrib = true;
2665 else
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)
2671 bAttrib = true;
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) )
2679 bAttrib = true;
2684 // Feldbefehle enthalten?
2686 SfxItemState eFieldState = aOldAttribs.GetItemState( EE_FEATURE_FIELD, false );
2687 if ( eFieldState == SFX_ITEM_DONTCARE || eFieldState == SFX_ITEM_SET )
2688 bAttrib = true;
2690 // not converted characters?
2692 SfxItemState eConvState = aOldAttribs.GetItemState( EE_FEATURE_NOTCONV, false );
2693 if ( eConvState == SFX_ITEM_DONTCARE || eConvState == SFX_ITEM_SET )
2694 bAttrib = true;
2696 // Formeln immer als Formeln erkennen (#38309#)
2697 // (der Test vorher ist trotzdem noetig wegen Zell-Attributen)
2700 if (bSpellErrors)
2701 pEngine->GetAllMisspellRanges(aMisspellRanges);
2703 if (bMatrix)
2704 bAttrib = false;
2706 if (bAttrib)
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;
2724 if (bFormulaMode)
2726 ShowRefFrame();
2728 if (pExecuteSh)
2730 pExecuteSh->SetTabNo(aCursorPos.Tab());
2731 pExecuteSh->ActiveGrabFocus();
2734 bFormulaMode = false;
2735 pSfxApp->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2736 SC_MOD()->SetRefInputHdl(NULL);
2737 if (pInputWin)
2738 pInputWin->SetFormulaMode(false);
2739 UpdateAutoCorrFlag();
2741 pRefViewSh = NULL; // auch ohne FormulaMode wegen Funktions-AP
2742 DeleteRangeFinder();
2743 ResetAutoPar();
2745 bool bOldMod = bModified;
2747 bModified = false;
2748 bSelIsRef = false;
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();
2763 if ( pAuto )
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 ) );
2793 if ( pExecuteSh )
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,
2805 aString, pObject );
2807 if (!aMisspellRanges.empty())
2808 aItem.SetMisspellRanges(&aMisspellRanges);
2810 const SfxPoolItem* aArgs[2];
2811 aArgs[0] = &aItem;
2812 aArgs[1] = NULL;
2813 rBindings.Execute( nId, aArgs );
2816 delete pLastState; // pLastState enthaelt noch den alten Text
2817 pLastState = NULL;
2819 else
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();
2829 delete pCellAttrs;
2830 delete pObject;
2832 HideTip();
2833 HideTipBelow();
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();
2848 bModified = false;
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;
2855 if (bFormulaMode)
2857 ShowRefFrame();
2858 if (pExecuteSh)
2860 pExecuteSh->SetTabNo(aCursorPos.Tab());
2861 pExecuteSh->ActiveGrabFocus();
2863 bFormulaMode = false;
2864 SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2865 SC_MOD()->SetRefInputHdl(NULL);
2866 if (pInputWin)
2867 pInputWin->SetFormulaMode(false);
2868 UpdateAutoCorrFlag();
2870 pRefViewSh = NULL; // auch ohne FormulaMode wegen Funktions-AP
2871 DeleteRangeFinder();
2872 ResetAutoPar();
2874 eMode = SC_INPUT_NONE;
2875 StopInputWinEngine( true );
2876 if (pExecuteSh)
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
2884 else
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);
2905 UpdateActiveView();
2906 if (!pTableView && !pTopView)
2907 return; // z.B. FillMode
2909 DataChanging(); // kann nicht neu sein
2911 RemoveSelection();
2912 if (pTableView)
2913 pTableView->InsertText( OUString(cSep), false );
2914 if (pTopView)
2915 pTopView->InsertText( OUString(cSep), false );
2917 DataChanged();
2920 void ScInputHandler::SetReference( const ScRange& rRef, ScDocument* pDoc )
2922 HideTip();
2924 bool bOtherDoc = ( pRefViewSh &&
2925 pRefViewSh->GetViewData()->GetDocument() != pDoc );
2926 if (bOtherDoc)
2927 if (!pDoc->GetDocumentShell()->HasName())
2929 // Referenzen auf unbenanntes Dokument gehen nicht
2930 // (SetReference sollte dann auch nicht gerufen werden)
2932 return;
2935 UpdateActiveView();
2936 if (!pTableView && !pTopView)
2937 return; // z.B. FillMode
2939 // nie das "=" ueberschreiben!
2940 EditView* pActiveView = pTopView ? pTopView : pTableView;
2941 ESelection aSel = pActiveView->GetSelection();
2942 aSel.Adjust();
2943 if ( aSel.nStartPara == 0 && aSel.nStartPos == 0 )
2944 return;
2946 DataChanging(); // kann nicht neu sein
2948 // Selektion umdrehen, falls rueckwaerts (noetig ???)
2950 if (pTableView)
2952 ESelection aTabSel = pTableView->GetSelection();
2953 if (aTabSel.nStartPos > aTabSel.nEndPos && aTabSel.nStartPara == aTabSel.nEndPara)
2955 aTabSel.Adjust();
2956 pTableView->SetSelection(aTabSel);
2959 if (pTopView)
2961 ESelection aTopSel = pTopView->GetSelection();
2962 if (aTopSel.nStartPos > aTopSel.nEndPos && aTopSel.nStartPara == aTopSel.nEndPara)
2964 aTopSel.Adjust();
2965 pTopView->SetSelection(aTopSel);
2969 // String aus Referenz erzeugen
2971 OUString aRefStr;
2972 const ScAddress::Details aAddrDetails( pDoc, aCursorPos );
2973 if (bOtherDoc)
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 );
2985 aRefStr = "\'";
2986 aRefStr += aFileName;
2987 aRefStr += "'#";
2988 aRefStr += aTmp;
2990 else
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);
2995 else
2996 aRefStr = rRef.Format(SCA_VALID, pDoc, aAddrDetails);
2999 if (pTableView || pTopView)
3001 if (pTableView)
3002 pTableView->InsertText( aRefStr, true );
3003 if (pTopView)
3004 pTopView->InsertText( aRefStr, true );
3006 DataChanged();
3009 bSelIsRef = true;
3012 void ScInputHandler::InsertFunction( const OUString& rFuncName, bool bAddPar )
3014 if ( eMode == SC_INPUT_NONE )
3016 OSL_FAIL("InsertFunction, nicht im Eingabemodus");
3017 return;
3020 UpdateActiveView();
3021 if (!pTableView && !pTopView)
3022 return; // z.B. FillMode
3024 DataChanging(); // kann nicht neu sein
3026 OUString aText = rFuncName;
3027 if (bAddPar)
3028 aText += "()";
3030 if (pTableView)
3032 pTableView->InsertText( aText, false );
3033 if (bAddPar)
3035 ESelection aSel = pTableView->GetSelection();
3036 --aSel.nStartPos;
3037 --aSel.nEndPos;
3038 pTableView->SetSelection(aSel);
3041 if (pTopView)
3043 pTopView->InsertText( aText, false );
3044 if (bAddPar)
3046 ESelection aSel = pTopView->GetSelection();
3047 --aSel.nStartPos;
3048 --aSel.nEndPos;
3049 pTopView->SetSelection(aSel);
3053 DataChanged();
3055 if (bAddPar)
3056 AutoParAdded();
3059 void ScInputHandler::ClearText()
3061 if ( eMode == SC_INPUT_NONE )
3063 OSL_FAIL("ClearText, nicht im Eingabemodus");
3064 return;
3067 UpdateActiveView();
3068 if (!pTableView && !pTopView)
3069 return; // z.B. FillMode
3071 DataChanging(); // darf nicht neu sein
3073 OUString aEmpty;
3074 if (pTableView)
3076 pTableView->GetEditEngine()->SetText( aEmpty );
3077 pTableView->SetSelection( ESelection(0,0, 0,0) );
3079 if (pTopView)
3081 pTopView->GetEditEngine()->SetText( aEmpty );
3082 pTopView->SetSelection( ESelection(0,0, 0,0) );
3085 DataChanged();
3088 bool ScInputHandler::KeyInput( const KeyEvent& rKEvt, bool bStartEdit /* = false */ )
3090 if (!bOptLoaded)
3092 bAutoComplete = SC_MOD()->GetAppOptions().GetAutoComplete();
3093 bOptLoaded = true;
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.
3106 return false;
3108 if (!bControl && nCode == KEY_TAB)
3110 // Normal TAB moves the cursor right.
3111 EnterHandler();
3113 if (pActiveViewSh)
3114 pActiveViewSh->FindNextUnprot( bShift );
3115 return true;
3118 bool bInputLine = ( eMode==SC_INPUT_TOP );
3120 bool bUsed = false;
3121 bool bSkip = false;
3122 bool bDoEnter = false;
3124 switch ( nCode )
3126 case KEY_RETURN:
3127 if (bControl && !bShift && ( !bInputLine || ( pInputWin && pInputWin->IsMultiLineInput() ) ) )
3128 bDoEnter = true;
3129 else if (nModi == 0 && nTipVisible && pFormulaData && miAutoPosFormula != pFormulaData->end())
3131 PasteFunctionData();
3132 bUsed = true;
3134 else if ( nModi == 0 && nTipVisible && !aManualTip.isEmpty() )
3136 PasteManualTip();
3137 bUsed = true;
3139 else
3141 sal_uInt8 nMode = SC_ENTER_NORMAL;
3142 if ( bShift && bControl )
3143 nMode = SC_ENTER_MATRIX;
3144 else if ( bAlt )
3145 nMode = SC_ENTER_BLOCK;
3146 EnterHandler( nMode );
3148 if (pActiveViewSh)
3149 pActiveViewSh->MoveCursorEnter( bShift && !bControl );
3151 bUsed = true;
3153 break;
3154 case KEY_TAB:
3155 if (bControl && !bAlt)
3157 if (pFormulaData && nTipVisible && miAutoPosFormula != pFormulaData->end())
3159 // blaettern
3161 NextFormulaEntry( bShift );
3162 bUsed = true;
3164 else if (pColumnData && bUseTab && miAutoPosColumn != pColumnData->end())
3166 // in den Eintraegen der AutoEingabe blaettern
3168 NextAutoEntry( bShift );
3169 bUsed = true;
3172 break;
3173 case KEY_ESCAPE:
3174 if ( nTipVisible )
3176 HideTip();
3177 bUsed = true;
3179 else if( nTipVisibleSec )
3181 HideTipBelow();
3182 bUsed = true;
3184 else if (eMode != SC_INPUT_NONE)
3186 CancelHandler();
3187 bUsed = true;
3189 else
3190 bSkip = true;
3191 break;
3192 case KEY_F2:
3193 if ( !bShift && !bControl && !bAlt && eMode == SC_INPUT_TABLE )
3195 eMode = SC_INPUT_TYPE;
3196 bUsed = true;
3198 break;
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 ) ) ) )
3209 HideTip();
3210 HideTipBelow();
3212 if (bSelIsRef)
3214 RemoveSelection();
3215 bSelIsRef = false;
3218 UpdateActiveView();
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
3227 if (pActiveViewSh)
3228 pActiveViewSh->GetViewData()->GetDocShell()->PostEditView( pEngine, aCursorPos );
3229 UpdateActiveView();
3230 if (eMode==SC_INPUT_NONE)
3231 if (pTableView || pTopView)
3233 OUString aStrLoP;
3235 if ( bStartEdit && bCellHasPercentFormat && ((nChar >= '0' && nChar <= '9') || nChar == '-') )
3236 aStrLoP = "%";
3238 if (pTableView)
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
3247 if (pTopView)
3249 pTopView->GetEditEngine()->SetText( aStrLoP );
3250 if ( !aStrLoP.isEmpty() )
3251 pTopView->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3254 SyncViews();
3257 if (pTableView || pTopView)
3259 if (bDoEnter)
3261 if (pTableView)
3262 if( pTableView->PostKeyEvent( KeyEvent( CHAR_CR, KeyCode(KEY_RETURN) ) ) )
3263 bUsed = true;
3264 if (pTopView)
3265 if( pTopView->PostKeyEvent( KeyEvent( CHAR_CR, KeyCode(KEY_RETURN) ) ) )
3266 bUsed = true;
3268 else if ( nAutoPar && nChar == ')' && CursorAtClosingPar() )
3270 SkipClosingPar();
3271 bUsed = true;
3273 else
3275 if (pTableView)
3277 Window* pFrameWin = pActiveViewSh ? pActiveViewSh->GetFrameWin() : NULL;
3278 if ( pTableView->PostKeyEvent( rKEvt, pFrameWin ) )
3279 bUsed = true;
3281 if (pTopView)
3282 if ( pTopView->PostKeyEvent( rKEvt ) )
3283 bUsed = true;
3286 // Auto-Eingabe:
3288 if ( bUsed && bAutoComplete )
3290 bUseTab = false;
3291 if (pFormulaData)
3292 miAutoPosFormula = pFormulaData->end(); // do not search further
3293 if (pColumnData)
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'
3300 if (bFormulaMode)
3301 UseFormulaData();
3302 else
3303 UseColData();
3307 // when the selection is changed manually or an opening parenthesis
3308 // is typed, stop overwriting parentheses
3309 if ( bUsed && nChar == '(' )
3310 ResetAutoPar();
3312 if ( KEY_INSERT == nCode )
3314 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
3315 if (pViewFrm)
3316 pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
3318 if( bUsed && bFormulaMode && ( bCursorKey || bInsKey || nCode == KEY_DELETE || nCode == KEY_BACKSPACE ) )
3320 ShowTipCursor();
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)
3332 SyncViews();
3334 return bUsed;
3337 bool ScInputHandler::InputCommand( const CommandEvent& rCEvt, bool bForce )
3339 bool bUsed = false;
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 )
3347 UpdateActiveView();
3348 if (pTableView || pTopView)
3350 if (pTableView)
3351 pTableView->Command( rCEvt );
3352 else if (pTopView) // call only once
3353 pTopView->Command( rCEvt );
3354 bUsed = true;
3358 else if ( rCEvt.GetCommand() == COMMAND_QUERYCHARPOSITION )
3360 if ( eMode != SC_INPUT_NONE )
3362 UpdateActiveView();
3363 if (pTableView || pTopView)
3365 if (pTableView)
3366 pTableView->Command( rCEvt );
3367 else if (pTopView) // call only once
3368 pTopView->Command( rCEvt );
3369 bUsed = true;
3373 else
3375 if ( bForce || eMode != SC_INPUT_NONE )
3377 if (!bOptLoaded)
3379 bAutoComplete = SC_MOD()->GetAppOptions().GetAutoComplete();
3380 bOptLoaded = true;
3383 HideTip();
3384 HideTipBelow();
3386 if ( bSelIsRef )
3388 RemoveSelection();
3389 bSelIsRef = false;
3392 UpdateActiveView();
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
3401 if (pActiveViewSh)
3402 pActiveViewSh->GetViewData()->GetDocShell()->PostEditView( pEngine, aCursorPos );
3403 UpdateActiveView();
3404 if (eMode==SC_INPUT_NONE)
3405 if (pTableView || pTopView)
3407 OUString aStrLoP;
3408 if (pTableView)
3410 pTableView->GetEditEngine()->SetText( aStrLoP );
3411 pTableView->SetSelection( ESelection(0,0, 0,0) );
3413 if (pTopView)
3415 pTopView->GetEditEngine()->SetText( aStrLoP );
3416 pTopView->SetSelection( ESelection(0,0, 0,0) );
3419 SyncViews();
3422 if (pTableView || pTopView)
3424 if (pTableView)
3425 pTableView->Command( rCEvt );
3426 if (pTopView)
3427 pTopView->Command( rCEvt );
3429 bUsed = true;
3431 if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
3433 // AutoInput after ext text input
3435 if (pFormulaData)
3436 miAutoPosFormula = pFormulaData->end();
3437 if (pColumnData)
3438 miAutoPosColumn = pColumnData->end();
3440 if (bFormulaMode)
3441 UseFormulaData();
3442 else
3443 UseColData();
3447 DataChanged(); // calls UpdateParenthesis()
3448 InvalidateAttribs(); //! in DataChanged ?
3452 if (pTopView && eMode != SC_INPUT_NONE)
3453 SyncViews();
3456 return bUsed;
3459 void ScInputHandler::NotifyChange( const ScInputHdlState* pState,
3460 bool bForce, ScTabViewShell* pSourceSh,
3461 bool bStopEditing)
3463 // Wenn der Aufruf aus einem Makro-Aufruf im EnterHandler kommt,
3464 // gleich abbrechen und nicht den Status durcheinander bringen
3465 if (bInEnterHandler)
3466 return;
3468 bool bRepeat = (pState == pLastState);
3469 if (!bRepeat && pState && pLastState)
3470 bRepeat = (*pState == *pLastState);
3471 if (bRepeat && !bForce)
3472 return;
3474 bInOwnChange = true; // disable ModifyHdl (reset below)
3476 if ( pState && !pLastState ) // wieder enablen
3477 bForce = true;
3479 bool bHadObject = pLastState && pLastState->GetEditData();
3481 //! Before EditEngine gets eventually created (so it gets the right pools)
3482 if ( pSourceSh )
3483 pActiveViewSh = pSourceSh;
3484 else
3485 pActiveViewSh = PTR_CAST(ScTabViewShell, SfxViewShell::Current());
3487 ImplCreateEditEngine();
3489 if ( pState != pLastState )
3491 delete pLastState;
3492 pLastState = pState ? new ScInputHdlState( *pState ) : NULL;
3495 if ( pState && pActiveViewSh )
3497 ScModule* pScMod = SC_MOD();
3499 if ( pState )
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;
3508 if ( bModified )
3510 if (pState->GetPos() != aCursorPos)
3512 if (!bProtected)
3513 EnterHandler();
3515 else
3516 bIgnore = true;
3519 if ( !bIgnore )
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();
3531 if ( pData )
3532 bTxtMod = true;
3533 else if ( bHadObject )
3534 bTxtMod = true;
3535 else if ( bTextValid )
3536 bTxtMod = ( !aString.equals(aCurrentText) );
3537 else
3538 bTxtMod = ( !aString.equals(GetEditText(pEngine)) );
3540 if ( bTxtMod || bForce )
3542 if (pData)
3544 pEngine->SetText( *pData );
3545 if ( pInputWin && pInputWin->IsMultiLineInput() )
3546 aString = ScEditUtil::GetMultilineString(*pEngine);
3547 else
3548 aString = GetEditText(pEngine);
3549 lcl_RemoveTabs(aString);
3550 bTextValid = false;
3551 aCurrentText = OUString();
3553 else
3555 aCurrentText = aString;
3556 bTextValid = true; //! erst nur als String merken
3559 if ( pInputWin )
3560 pInputWin->SetTextString(aString);
3563 if ( pInputWin ) // Bereichsanzeige
3565 OUString aPosStr;
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);
3586 else
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();
3598 if (bStopEditing)
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 );
3609 bModified = false;
3610 bSelIsRef = false;
3611 bProtected = false;
3612 bCommandErrorShown = false;
3617 if ( pInputWin)
3619 if(!pScMod->IsFormulaMode()&& !pScMod->IsRefDialogOpen()) //BugID 54702
3620 { //Wenn RefDialog offen, dann nicht enablen
3621 if ( !pInputWin->IsEnabled())
3623 pInputWin->Enable();
3624 if(pDelayTimer )
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
3644 if ( !pDelayTimer )
3646 pDelayTimer = new Timer;
3647 pDelayTimer->SetTimeout( 500 ); // 100ms Verzoegerung
3648 pDelayTimer->SetTimeoutHdl( LINK( this, ScInputHandler, DelayTimer ) );
3649 pDelayTimer->Start();
3653 HideTip();
3654 HideTipBelow();
3655 bInOwnChange = false;
3658 void ScInputHandler::UpdateCellAdjust( SvxCellHorJustify eJust )
3660 eAttrAdjust = eJust;
3661 UpdateAdjust( 0 );
3664 void ScInputHandler::ResetDelayTimer()
3666 if(pDelayTimer!=NULL)
3668 DELETEZ( pDelayTimer );
3670 if ( pInputWin)
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 ) )
3690 if ( pInputWin)
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 );
3702 if ( pInputWin )
3704 pInputWin->SetPosString( EMPTY_OUSTRING );
3705 pInputWin->SetTextString( EMPTY_OUSTRING );
3706 pInputWin->Disable();
3709 bInOwnChange = false;
3713 return 0;
3716 void ScInputHandler::InputSelection( EditView* pView )
3718 SyncViews( pView );
3719 ShowTipCursor();
3720 UpdateParenthesis(); // Selektion geaendert -> Klammer-Hervorhebung neu
3722 // when the selection is changed manually, stop overwriting parentheses
3723 ResetAutoPar();
3726 void ScInputHandler::InputChanged( EditView* pView, bool bFromNotify )
3728 UpdateActiveView();
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();
3742 if ( bNewView )
3743 pViewData->GetDocShell()->PostEditView( pEngine, aCursorPos );
3745 pViewData->EditGrowY();
3746 pViewData->EditGrowX();
3749 SyncViews( pView );
3752 const OUString& ScInputHandler::GetEditString()
3754 if (pEngine)
3756 aCurrentText = pEngine->GetText(); // immer neu aus Engine
3757 bTextValid = true;
3760 return aCurrentText;
3763 Size ScInputHandler::GetTextSize()
3765 Size aSize;
3766 if ( pEngine )
3767 aSize = Size( pEngine->CalcTextWidth(), pEngine->GetTextHeight() );
3769 return aSize;
3772 bool ScInputHandler::GetTextAndFields( ScEditEngineDefaulter& rDestEngine )
3774 bool bRet = false;
3775 if (pEngine)
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 )
3784 // Inhalt kopieren
3786 EditTextObject* pObj = pEngine->CreateTextObject();
3787 rDestEngine.SetText(*pObj);
3788 delete 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
3802 --nParCnt;
3805 bRet = true;
3808 return bRet;
3811 //------------------------------------------------------------------------
3812 // Methoden fuer FunktionsAutopiloten:
3813 // InputGetSelection, InputSetSelection, InputReplaceSelection, InputGetFormulaStr
3814 //------------------------------------------------------------------------
3816 void ScInputHandler::InputGetSelection( xub_StrLen& rStart, xub_StrLen& rEnd )
3818 rStart = nFormSelStart;
3819 rEnd = nFormSelEnd;
3822 //------------------------------------------------------------------------
3824 EditView* ScInputHandler::GetFuncEditView()
3826 UpdateActiveView(); // wegen pTableView
3828 EditView* pView = NULL;
3829 if ( pInputWin )
3831 pInputWin->MakeDialogEditView();
3832 pView = pInputWin->GetEditView();
3834 else
3836 if ( eMode != SC_INPUT_TABLE )
3838 bCreatingFuncView = true; // RangeFinder nicht anzeigen
3839 SetMode( SC_INPUT_TABLE );
3840 bCreatingFuncView = false;
3841 if ( pTableView )
3842 pTableView->GetEditEngine()->SetText( EMPTY_OUSTRING );
3844 pView = pTableView;
3847 return pView;
3850 //------------------------------------------------------------------------
3852 void ScInputHandler::InputSetSelection( xub_StrLen nStart, xub_StrLen nEnd )
3854 if ( nStart <= nEnd )
3856 nFormSelStart = nStart;
3857 nFormSelEnd = nEnd;
3859 else
3861 nFormSelEnd = nStart;
3862 nFormSelStart = nEnd;
3865 EditView* pView = GetFuncEditView();
3866 if (pView)
3867 pView->SetSelection( ESelection(0,nStart, 0,nEnd) );
3869 bModified = true;
3872 //------------------------------------------------------------------------
3874 void ScInputHandler::InputReplaceSelection( const OUString& rStr )
3876 if (!pRefViewSh)
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);
3885 if (nOldLen)
3886 aBuf.remove(nFormSelStart, nOldLen);
3887 if (nNewLen)
3888 aBuf.insert(nFormSelStart, rStr);
3890 aFormText = aBuf.makeStringAndClear();
3892 nFormSelEnd = nFormSelStart + nNewLen;
3894 EditView* pView = GetFuncEditView();
3895 if (pView)
3897 pView->SetEditEngineUpdateMode( false );
3898 pView->GetEditEngine()->SetText( aFormText );
3899 pView->SetSelection( ESelection(0,nFormSelStart, 0,nFormSelEnd) );
3900 pView->SetEditEngineUpdateMode( true );
3902 bModified = 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 //========================================================================
3920 // ScInputHdlState
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 )
3941 *this = rCpy;
3944 //------------------------------------------------------------------------
3946 ScInputHdlState::~ScInputHdlState()
3948 delete pEditData;
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 )
3966 delete pEditData;
3968 aCursorPos = r.aCursorPos;
3969 aStartPos = r.aStartPos;
3970 aEndPos = r.aEndPos;
3971 aString = r.aString;
3972 pEditData = r.pEditData ? r.pEditData->Clone() : NULL;
3974 return *this;
3977 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */