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