xref: /trunk/main/sc/source/ui/app/inputhdl.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 //------------------------------------------------------------------
32 
33 #include "scitems.hxx"
34 #include <editeng/eeitem.hxx>
35 
36 #include <sfx2/app.hxx>
37 #include <editeng/acorrcfg.hxx>
38 #include <svx/algitem.hxx>
39 #include <editeng/adjitem.hxx>
40 #include <editeng/brshitem.hxx>
41 #include <svtools/colorcfg.hxx>
42 #include <editeng/colritem.hxx>
43 #include <editeng/editobj.hxx>
44 #include <editeng/editstat.hxx>
45 #include <editeng/editview.hxx>
46 #include <editeng/escpitem.hxx>
47 #include <editeng/forbiddencharacterstable.hxx>
48 #include <editeng/langitem.hxx>
49 #include <editeng/svxacorr.hxx>
50 #include <editeng/unolingu.hxx>
51 #include <editeng/wghtitem.hxx>
52 #include <sfx2/bindings.hxx>
53 #include <sfx2/viewfrm.hxx>
54 #include <sfx2/dispatch.hxx>
55 #include <sfx2/docfile.hxx>
56 #include <sfx2/printer.hxx>
57 #include <svl/zforlist.hxx>
58 #include <vcl/sound.hxx>
59 #include <unotools/localedatawrapper.hxx>
60 #include <vcl/help.hxx>
61 #include <vcl/cursor.hxx>
62 #include <tools/urlobj.hxx>
63 #include <formula/formulahelper.hxx>
64 
65 #include "inputwin.hxx"
66 #include "tabvwsh.hxx"
67 #include "docsh.hxx"
68 #include "scmod.hxx"
69 #include "uiitems.hxx"
70 #include "global.hxx"
71 #include "sc.hrc"
72 #include "globstr.hrc"
73 #include "patattr.hxx"
74 #include "viewdata.hxx"
75 #include "document.hxx"
76 #include "docpool.hxx"
77 #include "editutil.hxx"
78 #include "collect.hxx"
79 #include "appoptio.hxx"
80 #include "docoptio.hxx"
81 #include "validat.hxx"
82 #include "userlist.hxx"
83 #include "rfindlst.hxx"
84 #include "inputopt.hxx"
85 #include "cell.hxx"             // fuer Formel-Preview
86 #include "compiler.hxx"         // fuer Formel-Preview
87 #include "editable.hxx"
88 #include "funcdesc.hxx"
89 
90 #define _INPUTHDL_CXX
91 #include "inputhdl.hxx"
92 
93 //  max. Ranges im RangeFinder
94 #define RANGEFIND_MAX   32
95 
96 using namespace formula;
97 
98 // STATIC DATA -----------------------------------------------------------
99 
100 sal_Bool ScInputHandler::bOptLoaded = sal_False;            // App-Optionen ausgewertet
101 sal_Bool ScInputHandler::bAutoComplete = sal_False;         // wird in KeyInput gesetzt
102 
103 //  delimiters (in addition to ScEditUtil) needed for range finder:
104 //  only characters that are allowed in formulas next to references
105 //  and the quotation mark (so string constants can be skipped)
106 
107 static const sal_Char __FAR_DATA pMinDelimiters[] = " !\"";
108 
109 extern sal_uInt16 nEditAdjust;      //! Member an ViewData
110 
111 //==================================================================
112 
113 static sal_Unicode lcl_getSheetSeparator(ScDocument* pDoc)
114 {
115     ScCompiler aComp(pDoc, ScAddress());
116     aComp.SetGrammar(pDoc->GetGrammar());
117     return aComp.GetNativeAddressSymbol(ScCompiler::Convention::SHEET_SEPARATOR);
118 }
119 
120 void ScInputHandler::InitRangeFinder( const String& rFormula )
121 {
122     DeleteRangeFinder();
123     ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell();
124     ScDocument* pDoc = pDocSh->GetDocument();
125     const sal_Unicode cSheetSep = lcl_getSheetSeparator(pDoc);
126 
127     if ( !pActiveViewSh || !SC_MOD()->GetInputOptions().GetRangeFinder() )
128         return;
129 
130 //  String aDelimiters = pEngine->GetWordDelimiters();
131     String aDelimiters = ScEditUtil::ModifyDelimiters(
132                             String::CreateFromAscii( pMinDelimiters ) );
133 
134     xub_StrLen nColon = aDelimiters.Search(':');
135     if ( nColon != STRING_NOTFOUND )
136         aDelimiters.Erase( nColon, 1 );             // Delimiter ohne Doppelpunkt
137     xub_StrLen nDot = aDelimiters.Search(cSheetSep);
138     if ( nDot != STRING_NOTFOUND )
139         aDelimiters.Erase( nDot, 1 );               // Delimiter ohne Punkt
140 
141     const sal_Unicode* pChar = rFormula.GetBuffer();
142     xub_StrLen nLen = rFormula.Len();
143     xub_StrLen nPos = 0;
144     xub_StrLen nStart = 0;
145     sal_uInt16 nCount = 0;
146     ScRange aRange;
147     while ( nPos < nLen && nCount < RANGEFIND_MAX )
148     {
149         //  Trenner ueberlesen
150         while ( nPos<nLen && ScGlobal::UnicodeStrChr( aDelimiters.GetBuffer(), pChar[nPos] ) )
151         {
152             if ( pChar[nPos] == '"' )                       // String
153             {
154                 ++nPos;
155                 while (nPos<nLen && pChar[nPos] != '"')     // bis zum Ende ueberlesen
156                     ++nPos;
157             }
158             ++nPos;                     // Trennzeichen oder schliessender Quote
159         }
160 
161         //  Text zwischen Trennern
162         nStart = nPos;
163 handle_r1c1:
164         while ( nPos<nLen && !ScGlobal::UnicodeStrChr( aDelimiters.GetBuffer(), pChar[nPos] ) )
165             ++nPos;
166 
167         // for R1C1 '-' in R[-]... or C[-]... are not delimiters
168         // Nothing heroic here to ensure that there are '[]' around a negative
169         // integer.  we need to clean up this code.
170         if( nPos < nLen && nPos > 0 &&
171             '-' == pChar[nPos] && '[' == pChar[nPos-1] &&
172             NULL != pDoc &&
173             formula::FormulaGrammar::CONV_XL_R1C1 == pDoc->GetAddressConvention() )
174         {
175             nPos++;
176             goto handle_r1c1;
177         }
178 
179         if ( nPos > nStart )
180         {
181             String aTest = rFormula.Copy( nStart, nPos-nStart );
182             const ScAddress::Details aAddrDetails( pDoc, aCursorPos );
183             sal_uInt16 nFlags = aRange.ParseAny( aTest, pDoc, aAddrDetails );
184             if ( nFlags & SCA_VALID )
185             {
186                 //  Tabelle setzen, wenn nicht angegeben
187                 if ( (nFlags & SCA_TAB_3D) == 0 )
188                     aRange.aStart.SetTab( pActiveViewSh->GetViewData()->GetTabNo() );
189                 if ( (nFlags & SCA_TAB2_3D) == 0 )
190                     aRange.aEnd.SetTab( aRange.aStart.Tab() );
191 
192                 if ( ( nFlags & ( SCA_VALID_COL2 | SCA_VALID_ROW2 | SCA_VALID_TAB2 ) ) == 0 )
193                 {
194                     // #i73766# if a single ref was parsed, set the same "abs" flags for ref2,
195                     // so Format doesn't output a double ref because of different flags.
196                     sal_uInt16 nAbsFlags = nFlags & ( SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB_ABSOLUTE );
197                     nFlags |= nAbsFlags << 4;
198                 }
199 
200                 if (!nCount)
201                 {
202                     pEngine->SetUpdateMode( sal_False );
203                     pRangeFindList = new ScRangeFindList( pDocSh->GetTitle() );
204                 }
205 
206                 ScRangeFindData* pNew = new ScRangeFindData( aRange, nFlags, nStart, nPos );
207                 pRangeFindList->Insert( pNew );
208 
209                 ESelection aSel( 0, nStart, 0, nPos );
210                 SfxItemSet aSet( pEngine->GetEmptyItemSet() );
211                 aSet.Put( SvxColorItem( Color( ScRangeFindList::GetColorName( nCount ) ),
212                             EE_CHAR_COLOR ) );
213                 pEngine->QuickSetAttribs( aSet, aSel );
214                 ++nCount;
215             }
216         }
217 
218         //  letzten Trenner nicht ueberlesen, koennte ja ein Quote sein (?)
219     }
220 
221     if (nCount)
222     {
223         pEngine->SetUpdateMode( sal_True );
224 
225         pDocSh->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER ) );
226     }
227 }
228 
229 void lcl_Replace( EditView* pView, const String& rNewStr, const ESelection& rOldSel )
230 {
231     if ( pView )
232     {
233         ESelection aOldSel = pView->GetSelection();
234         if (aOldSel.HasRange())
235             pView->SetSelection( ESelection( aOldSel.nEndPara, aOldSel.nEndPos,
236                                              aOldSel.nEndPara, aOldSel.nEndPos ) );
237 
238         EditEngine* pEngine = pView->GetEditEngine();
239         pEngine->QuickInsertText( rNewStr, rOldSel );
240 
241         //  Dummy-InsertText fuer Update und Paint
242         //  dafuer muss oben die Selektion aufgehoben werden (vor QuickInsertText)
243         pView->InsertText( EMPTY_STRING, sal_False );
244 
245         xub_StrLen nLen = pEngine->GetTextLen(0);
246         ESelection aSel( 0, nLen, 0, nLen );
247         pView->SetSelection( aSel );                // Cursor ans Ende
248     }
249 }
250 
251 void ScInputHandler::UpdateRange( sal_uInt16 nIndex, const ScRange& rNew )
252 {
253     ScTabViewShell* pDocView = pRefViewSh ? pRefViewSh : pActiveViewSh;
254     if ( pDocView && pRangeFindList && nIndex < pRangeFindList->Count() )
255     {
256         ScRangeFindData* pData = pRangeFindList->GetObject( nIndex );
257         xub_StrLen nOldStart = pData->nSelStart;
258         xub_StrLen nOldEnd = pData->nSelEnd;
259 
260         ScRange aJustified = rNew;
261         aJustified.Justify();           // Ref in der Formel immer richtigherum anzeigen
262         String aNewStr;
263         ScDocument* pDoc = pDocView->GetViewData()->GetDocument();
264         const ScAddress::Details aAddrDetails( pDoc, aCursorPos );
265         aJustified.Format( aNewStr, pData->nFlags, pDoc, aAddrDetails );
266         ESelection aOldSel( 0, nOldStart, 0, nOldEnd );
267 
268         DataChanging();
269 
270         lcl_Replace( pTopView, aNewStr, aOldSel );
271         lcl_Replace( pTableView, aNewStr, aOldSel );
272 
273         bInRangeUpdate = sal_True;
274         DataChanged();
275         bInRangeUpdate = sal_False;
276 
277         long nDiff = aNewStr.Len() - (long)(nOldEnd-nOldStart);
278 
279         pData->aRef = rNew;
280         pData->nSelEnd = (xub_StrLen)(pData->nSelEnd + nDiff);
281 
282         sal_uInt16 nCount = (sal_uInt16) pRangeFindList->Count();
283         for (sal_uInt16 i=nIndex+1; i<nCount; i++)
284         {
285             ScRangeFindData* pNext = pRangeFindList->GetObject( i );
286             pNext->nSelStart = (xub_StrLen)(pNext->nSelStart + nDiff);
287             pNext->nSelEnd   = (xub_StrLen)(pNext->nSelEnd   + nDiff);
288         }
289     }
290     else
291     {
292         DBG_ERROR("UpdateRange: da fehlt was");
293     }
294 }
295 
296 void ScInputHandler::DeleteRangeFinder()
297 {
298     ScTabViewShell* pPaintView = pRefViewSh ? pRefViewSh : pActiveViewSh;
299     if ( pRangeFindList && pPaintView )
300     {
301         ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell();
302         pRangeFindList->SetHidden(sal_True);
303         pDocSh->Broadcast( SfxSimpleHint( SC_HINT_SHOWRANGEFINDER ) );  // wegnehmen
304         DELETEZ(pRangeFindList);
305     }
306 }
307 
308 //==================================================================
309 
310 inline String GetEditText(EditEngine* pEng)
311 {
312     return ScEditUtil::GetSpaceDelimitedString(*pEng);
313 }
314 
315 void lcl_RemoveTabs(String& rStr)
316 {
317     xub_StrLen nPos;
318     while ( (nPos=rStr.Search('\t')) != STRING_NOTFOUND )
319         rStr.SetChar( nPos, ' ' );
320 }
321 
322 void lcl_RemoveLineEnd(String& rStr)
323 {
324     rStr.ConvertLineEnd(LINEEND_LF);
325     xub_StrLen nPos;
326     while ( (nPos=rStr.Search('\n')) != STRING_NOTFOUND )
327         rStr.SetChar( nPos, ' ' );
328 }
329 
330 xub_StrLen lcl_MatchParenthesis( const String& rStr, xub_StrLen nPos )
331 {
332     int nDir;
333     sal_Unicode c1, c2 = 0;
334     c1 = rStr.GetChar( nPos );
335     switch ( c1 )
336     {
337     case '(' :
338         c2 = ')';
339         nDir = 1;
340         break;
341     case ')' :
342         c2 = '(';
343         nDir = -1;
344         break;
345     case '<' :
346         c2 = '>';
347         nDir = 1;
348         break;
349     case '>' :
350         c2 = '<';
351         nDir = -1;
352         break;
353     case '{' :
354         c2 = '}';
355         nDir = 1;
356         break;
357     case '}' :
358         c2 = '{';
359         nDir = -1;
360         break;
361     case '[' :
362         c2 = ']';
363         nDir = 1;
364         break;
365     case ']' :
366         c2 = '[';
367         nDir = -1;
368         break;
369     default:
370         nDir = 0;
371     }
372     if ( !nDir )
373         return STRING_NOTFOUND;
374     xub_StrLen nLen = rStr.Len();
375     const sal_Unicode* p0 = rStr.GetBuffer();
376     register const sal_Unicode* p;
377     const sal_Unicode* p1;
378     sal_uInt16 nQuotes = 0;
379     if ( nPos < nLen / 2 )
380     {
381         p = p0;
382         p1 = p0 + nPos;
383     }
384     else
385     {
386         p = p0 + nPos;
387         p1 = p0 + nLen;
388     }
389     while ( p < p1 )
390     {
391         if ( *p++ == '\"' )
392             nQuotes++;
393     }
394     // Odd number of quotes that we find ourselves in a string
395     sal_Bool bLookInString = ((nQuotes % 2) != 0);
396     sal_Bool bInString = bLookInString;
397     p = p0 + nPos;
398     p1 = (nDir < 0 ? p0 : p0 + nLen) ;
399     sal_uInt16 nLevel = 1;
400     while ( p != p1 && nLevel )
401     {
402         p += nDir;
403         if ( *p == '\"' )
404         {
405             bInString = !bInString;
406             if ( bLookInString && !bInString )
407                 p = p1;     //That's it then
408         }
409         else if ( bInString == bLookInString )
410         {
411             if ( *p == c1 )
412                 nLevel++;
413             else if ( *p == c2 )
414                 nLevel--;
415         }
416     }
417     if ( nLevel )
418         return STRING_NOTFOUND;
419     return (xub_StrLen) (p - p0);
420 }
421 
422 //==================================================================
423 
424 ScInputHandler::ScInputHandler()
425     :   pInputWin( NULL ),
426         pEngine( NULL ),
427         pTableView( NULL ),
428         pTopView( NULL ),
429         pColumnData( NULL ),
430         pFormulaData( NULL ),
431         pFormulaDataPara( NULL ),
432         pTipVisibleParent( NULL ),
433         nTipVisible( 0 ),
434         pTipVisibleSecParent( NULL ),
435         nTipVisibleSec( 0 ),
436         nAutoPos( SCPOS_INVALID ),
437         bUseTab( sal_False ),
438         bTextValid( sal_True ),
439         nFormSelStart( 0 ),
440         nFormSelEnd( 0 ),
441         nAutoPar( 0 ),
442         eMode( SC_INPUT_NONE ),
443         bModified( sal_False ),
444         bSelIsRef( sal_False ),
445         bFormulaMode( sal_False ),
446         bInRangeUpdate( sal_False ),
447         bParenthesisShown( sal_False ),
448         bCreatingFuncView( sal_False ),
449         bInEnterHandler( sal_False ),
450         bCommandErrorShown( sal_False ),
451         bInOwnChange( sal_False ),
452         bProtected( sal_False ),
453         bCellHasPercentFormat( sal_False ),
454         nValidation( 0 ),
455         eAttrAdjust( SVX_HOR_JUSTIFY_STANDARD ),
456         aScaleX( 1,1 ),
457         aScaleY( 1,1 ),
458         pRefViewSh( NULL ),
459         pLastPattern( NULL ),
460         pEditDefaults( NULL ),
461         bLastIsSymbol( sal_False ),
462         pLastState( NULL ),
463         pDelayTimer( NULL ),
464         pRangeFindList( NULL )
465 {
466     //  The InputHandler is constructed with the view, so SfxViewShell::Current
467     //  doesn't have the right view yet. pActiveViewSh is updated in NotifyChange.
468     pActiveViewSh = NULL;
469 
470     //  Bindings (nur noch fuer Invalidate benutzt) werden bei Bedarf aktuell geholt
471 }
472 
473 __EXPORT ScInputHandler::~ScInputHandler()
474 {
475     //  Wenn dies der Applikations-InputHandler ist, wird der dtor erst nach SfxApplication::Main
476     //  gerufen, darf sich also auf keine Sfx-Funktionen mehr verlassen
477 
478     if ( !SFX_APP()->IsDowning() )          // inplace
479         EnterHandler();                     // Eingabe noch abschliessen
480 
481     if (SC_MOD()->GetRefInputHdl()==this)
482         SC_MOD()->SetRefInputHdl(NULL);
483 
484     if ( pInputWin && pInputWin->GetInputHandler() == this )
485         pInputWin->SetInputHandler( NULL );
486 
487     delete pRangeFindList;
488     delete pEditDefaults;
489     delete pEngine;
490     delete pLastState;
491     delete pDelayTimer;
492     delete pColumnData;
493     delete pFormulaData;
494     delete pFormulaDataPara;
495 }
496 
497 void ScInputHandler::SetRefScale( const Fraction& rX, const Fraction& rY )
498 {
499     if ( rX != aScaleX || rY != aScaleY )
500     {
501         aScaleX = rX;
502         aScaleY = rY;
503         if (pEngine)
504         {
505             MapMode aMode( MAP_100TH_MM, Point(), aScaleX, aScaleY );
506             pEngine->SetRefMapMode( aMode );
507         }
508     }
509 }
510 
511 void ScInputHandler::UpdateRefDevice()
512 {
513     if (!pEngine)
514         return;
515 
516     sal_Bool bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
517     bool bInPlace = pActiveViewSh && pActiveViewSh->GetViewFrame()->GetFrame().IsInPlace();
518     sal_uInt32 nCtrl = pEngine->GetControlWord();
519     if ( bTextWysiwyg || bInPlace )
520         nCtrl |= EE_CNTRL_FORMAT100;    // EditEngine default: always format for 100%
521     else
522         nCtrl &= ~EE_CNTRL_FORMAT100;   // when formatting for screen, use the actual MapMode
523     pEngine->SetControlWord( nCtrl );
524     if ( bTextWysiwyg && pActiveViewSh )
525         pEngine->SetRefDevice( pActiveViewSh->GetViewData()->GetDocument()->GetPrinter() );
526     else
527         pEngine->SetRefDevice( NULL );
528 
529     MapMode aMode( MAP_100TH_MM, Point(), aScaleX, aScaleY );
530     pEngine->SetRefMapMode( aMode );
531 
532     //  SetRefDevice(NULL) uses VirtualDevice, SetRefMapMode forces creation of a local VDev,
533     //  so the DigitLanguage can be safely modified (might use an own VDev instead of NULL).
534     if ( !( bTextWysiwyg && pActiveViewSh ) )
535     {
536         pEngine->GetRefDevice()->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() );
537     }
538 }
539 
540 void ScInputHandler::ImplCreateEditEngine()
541 {
542     if ( !pEngine )
543     {
544         if ( pActiveViewSh )
545         {
546             const ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocShell()->GetDocument();
547             pEngine = new ScFieldEditEngine( pDoc->GetEnginePool(), pDoc->GetEditPool() );
548         }
549         else
550             pEngine = new ScFieldEditEngine( EditEngine::CreatePool(), NULL, sal_True );
551         pEngine->SetWordDelimiters( ScEditUtil::ModifyDelimiters( pEngine->GetWordDelimiters() ) );
552         UpdateRefDevice();      // also sets MapMode
553         pEngine->SetPaperSize( Size( 1000000, 1000000 ) );
554         pEditDefaults = new SfxItemSet( pEngine->GetEmptyItemSet() );
555 
556         pEngine->SetControlWord( pEngine->GetControlWord() | EE_CNTRL_AUTOCORRECT );
557         pEngine->SetModifyHdl( LINK( this, ScInputHandler, ModifyHdl ) );
558     }
559 }
560 
561 void ScInputHandler::UpdateAutoCorrFlag()
562 {
563     sal_uLong nCntrl = pEngine->GetControlWord();
564     sal_uLong nOld = nCntrl;
565 
566     //  don't use pLastPattern here (may be invalid because of AutoStyle)
567 
568     sal_Bool bDisable = bLastIsSymbol || bFormulaMode;
569     if ( bDisable )
570         nCntrl &= ~EE_CNTRL_AUTOCORRECT;
571     else
572         nCntrl |= EE_CNTRL_AUTOCORRECT;
573 
574     if ( nCntrl != nOld )
575         pEngine->SetControlWord(nCntrl);
576 }
577 
578 void ScInputHandler::UpdateSpellSettings( sal_Bool bFromStartTab )
579 {
580     if ( pActiveViewSh )
581     {
582         ScViewData* pViewData = pActiveViewSh->GetViewData();
583         sal_Bool bOnlineSpell = pViewData->GetDocument()->GetDocOptions().IsAutoSpell();
584 
585         //  SetDefaultLanguage is independent of the language attributes,
586         //  ScGlobal::GetEditDefaultLanguage is always used.
587         //  It must be set every time in case the office language was changed.
588 
589         pEngine->SetDefaultLanguage( ScGlobal::GetEditDefaultLanguage() );
590 
591         //  if called for changed options, update flags only if already editing
592         //  if called from StartTable, always update flags
593 
594         if ( bFromStartTab || eMode != SC_INPUT_NONE )
595         {
596             sal_uLong nCntrl = pEngine->GetControlWord();
597             sal_uLong nOld = nCntrl;
598             if( bOnlineSpell )
599                 nCntrl |= EE_CNTRL_ONLINESPELLING;
600             else
601                 nCntrl &= ~EE_CNTRL_ONLINESPELLING;
602             // kein AutoCorrect auf Symbol-Font (EditEngine wertet Default nicht aus)
603             if ( pLastPattern && pLastPattern->IsSymbolFont() )
604                 nCntrl &= ~EE_CNTRL_AUTOCORRECT;
605             else
606                 nCntrl |= EE_CNTRL_AUTOCORRECT;
607             if ( nCntrl != nOld )
608                 pEngine->SetControlWord(nCntrl);
609 
610             ScDocument* pDoc = pViewData->GetDocument();
611             pDoc->ApplyAsianEditSettings( *pEngine );
612             pEngine->SetDefaultHorizontalTextDirection(
613                 (EEHorizontalTextDirection)pDoc->GetEditTextDirection( pViewData->GetTabNo() ) );
614             pEngine->SetFirstWordCapitalization( sal_False );
615         }
616 
617         //  language is set separately, so the speller is needed only if online
618         //  spelling is active
619 
620         if ( bOnlineSpell ) {
621             com::sun::star::uno::Reference<com::sun::star::linguistic2::XSpellChecker1> xXSpellChecker1( LinguMgr::GetSpellChecker() );
622             pEngine->SetSpeller( xXSpellChecker1 );
623         }
624 
625         sal_Bool bHyphen = pLastPattern && ((const SfxBoolItem&)pLastPattern->GetItem(ATTR_HYPHENATE)).GetValue();
626         if ( bHyphen ) {
627             com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
628             pEngine->SetHyphenator( xXHyphenator );
629         }
630     }
631 }
632 
633 //
634 //      Funktionen/Bereichsnamen etc. als Tip-Hilfe
635 //
636 
637 #define SC_STRTYPE_FUNCTIONS    1
638 //  die anderen Typen sind in ScDocument::GetFormulaEntries festgelegt
639 
640 void ScInputHandler::GetFormulaData()
641 {
642     if ( pActiveViewSh )
643     {
644         ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocShell()->GetDocument();
645 
646         if ( pFormulaData )
647             pFormulaData->FreeAll();
648         else
649             pFormulaData = new TypedScStrCollection;
650 
651         if( pFormulaDataPara )
652             pFormulaDataPara->FreeAll();
653         else
654             pFormulaDataPara = new TypedScStrCollection;
655 
656         //      MRU-Funktionen aus dem Funktions-Autopiloten
657         //      wie in ScPosWnd::FillFunctions (inputwin.cxx)
658 
659         const ScAppOptions& rOpt = SC_MOD()->GetAppOptions();
660         sal_uInt16 nMRUCount = rOpt.GetLRUFuncListCount();
661         const sal_uInt16* pMRUList = rOpt.GetLRUFuncList();
662         const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
663         sal_uLong nListCount = pFuncList->GetCount();
664         if (pMRUList)
665         {
666             for (sal_uInt16 i=0; i<nMRUCount; i++)
667             {
668                 sal_uInt16 nId = pMRUList[i];
669                 for (sal_uLong j=0; j<nListCount; j++)
670                 {
671                     const ScFuncDesc* pDesc = pFuncList->GetFunction( j );
672                     if ( pDesc->nFIndex == nId && pDesc->pFuncName )
673                     {
674                         String aEntry = *pDesc->pFuncName;
675                         aEntry.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
676                         TypedStrData* pData = new TypedStrData( aEntry, 0.0, SC_STRTYPE_FUNCTIONS );
677                         if (!pFormulaData->Insert(pData))
678                             delete pData;
679                         break;                  // nicht weitersuchen
680                     }
681                 }
682             }
683         }
684         for(sal_uLong i=0;i<nListCount;i++)
685         {
686             const ScFuncDesc* pDesc = pFuncList->GetFunction( i );
687             if ( pDesc->pFuncName )
688             {
689                 pDesc->initArgumentInfo();
690                 String aEntry = pDesc->GetSignature();
691                 TypedStrData* pData = new TypedStrData( aEntry, 0.0, SC_STRTYPE_FUNCTIONS );
692                 if (!pFormulaDataPara->Insert(pData))
693                     delete pData;
694             }
695         }
696         pDoc->GetFormulaEntries( *pFormulaData );
697         pDoc->GetFormulaEntries( *pFormulaDataPara );
698     }
699 }
700 
701 IMPL_LINK( ScInputHandler, ShowHideTipVisibleParentListener, VclWindowEvent*, pEvent )
702 {
703     if( pEvent->GetId() == VCLEVENT_OBJECT_DYING || pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
704         HideTip();
705     return 0;
706 }
707 
708 IMPL_LINK( ScInputHandler, ShowHideTipVisibleSecParentListener, VclWindowEvent*, pEvent )
709 {
710     if( pEvent->GetId() == VCLEVENT_OBJECT_DYING || pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
711         HideTipBelow();
712     return 0;
713 }
714 
715 void ScInputHandler::HideTip()
716 {
717     if ( nTipVisible )
718     {
719         if (pTipVisibleParent)
720             pTipVisibleParent->RemoveEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleParentListener ) );
721         Help::HideTip( nTipVisible );
722         nTipVisible = 0;
723         pTipVisibleParent = NULL;
724     }
725     aManualTip.Erase();
726 }
727 void ScInputHandler::HideTipBelow()
728 {
729     if ( nTipVisibleSec )
730     {
731         if (pTipVisibleSecParent)
732             pTipVisibleSecParent->RemoveEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleSecParentListener ) );
733         Help::HideTip( nTipVisibleSec );
734         nTipVisibleSec = 0;
735         pTipVisibleSecParent = NULL;
736     }
737     aManualTip.Erase();
738 }
739 
740 void ScInputHandler::ShowTipCursor()
741 {
742     HideTip();
743     HideTipBelow();
744     EditView* pActiveView = pTopView ? pTopView : pTableView;
745     ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell();
746     const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
747     const sal_Unicode cSheetSep = lcl_getSheetSeparator(pDocSh->GetDocument());
748 
749     if ( bFormulaMode && pActiveView && pFormulaDataPara && pEngine->GetParagraphCount() == 1 )
750     {
751         String aFormula = pEngine->GetText( (sal_uInt16) 0 );
752         ESelection aSel = pActiveView->GetSelection();
753         aSel.Adjust();
754         xub_StrLen  nLeftParentPos = 0;
755         if( aSel.nEndPos )
756         {
757             if ( aFormula.Len() < aSel.nEndPos )
758                 return;
759             xub_StrLen nPos = aSel.nEndPos;
760             String  aSelText = aFormula.Copy( 0, nPos );
761             xub_StrLen  nNextFStart = 0;
762             xub_StrLen  nNextFEnd = 0;
763             xub_StrLen  nArgPos = 0;
764             const IFunctionDescription* ppFDesc;
765             ::std::vector< ::rtl::OUString> aArgs;
766             sal_uInt16      nArgs;
767             sal_Bool  bFound = sal_False;
768             FormulaHelper aHelper(ScGlobal::GetStarCalcFunctionMgr());
769 
770             while( !bFound )
771             {
772                 aSelText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
773                 nLeftParentPos = lcl_MatchParenthesis( aSelText, aSelText.Len()-1 );
774                 if( nLeftParentPos != STRING_NOTFOUND )
775                 {
776                     sal_Unicode c = ( nLeftParentPos > 0 ) ? aSelText.GetChar( nLeftParentPos-1 ) : 0;
777                     if( !((c >= 'A' && c<= 'Z') || (c>= 'a' && c<= 'z' )) )
778                         continue;
779                     nNextFStart = aHelper.GetFunctionStart( aSelText, nLeftParentPos, sal_True);
780                     if( aHelper.GetNextFunc( aSelText, sal_False, nNextFStart, &nNextFEnd, &ppFDesc, &aArgs ) )
781                     {
782                         if( ppFDesc->getFunctionName().getLength() )
783                         {
784                             nArgPos = aHelper.GetArgStart( aSelText, nNextFStart, 0 );
785                             nArgs = static_cast<sal_uInt16>(ppFDesc->getParameterCount());
786 
787                             sal_uInt16 nActive = 0;
788                             sal_uInt16 nCount = 0;
789                             sal_uInt16 nCountSemicolon = 0;
790                             sal_uInt16 nCountDot = 0;
791                             sal_uInt16 nStartPosition = 0;
792                             sal_uInt16 nEndPosition = 0;
793                             sal_Bool   bFlag = sal_False;
794                             String aNew;
795                             sal_uInt16 nParAutoPos = SCPOS_INVALID;
796                             if( pFormulaDataPara->FindText( ppFDesc->getFunctionName(), aNew, nParAutoPos, sal_False ) )
797                             {
798                                 for( sal_uInt16 i=0; i < nArgs; i++ )
799                                 {
800                                     xub_StrLen nLength = static_cast<xub_StrLen>(aArgs[i].getLength());
801                                     if( nArgPos <= aSelText.Len()-1 )
802                                     {
803                                         nActive = i+1;
804                                         bFlag = sal_True;
805                                     }
806                                     nArgPos+=nLength+1;
807                                 }
808                                 if( bFlag )
809                                 {
810                                     nCountSemicolon = aNew.GetTokenCount(cSep)-1;
811                                     nCountDot = aNew.GetTokenCount(cSheetSep)-1;
812 
813                                     if( !nCountSemicolon )
814                                     {
815                                         for( sal_uInt16 i = 0; i < aNew.Len(); i++ )
816                                         {
817                                             sal_Unicode cNext = aNew.GetChar( i );
818                                             if( cNext == '(' )
819                                             {
820                                                 nStartPosition = i+1;
821                                             }
822                                         }
823                                     }
824                                     else if( !nCountDot )
825                                     {
826                                         for( sal_uInt16 i = 0; i < aNew.Len(); i++ )
827                                         {
828                                             sal_Unicode cNext = aNew.GetChar( i );
829                                             if( cNext == '(' )
830                                             {
831                                                 nStartPosition = i+1;
832                                             }
833                                             else if( cNext == cSep )
834                                             {
835                                                 nCount ++;
836                                                 nEndPosition = i;
837                                                 if( nCount == nActive )
838                                                 {
839                                                     break;
840                                                 }
841                                                 nStartPosition = nEndPosition+1;
842                                             }
843                                         }
844                                     }
845                                     else
846                                     {
847                                         for( sal_uInt16 i = 0; i < aNew.Len(); i++ )
848                                         {
849                                             sal_Unicode cNext = aNew.GetChar( i );
850                                             if( cNext == '(' )
851                                             {
852                                                 nStartPosition = i+1;
853                                             }
854                                             else if( cNext == cSep )
855                                             {
856                                                 nCount ++;
857                                                 nEndPosition = i;
858                                                 if( nCount == nActive )
859                                                 {
860                                                     break;
861                                                 }
862                                                 nStartPosition = nEndPosition+1;
863                                             }
864                                             else if( cNext == cSheetSep )
865                                             {
866                                                 continue;
867                                             }
868                                         }
869                                     }
870 
871                                     if( nStartPosition )
872                                     {
873                                         aNew.Insert( 0x25BA, nStartPosition );
874                                         ShowTipBelow( aNew );
875                                         bFound = sal_True;
876                                     }
877                                 }
878                                 else
879                                 {
880                                     ShowTipBelow( aNew );
881                                     bFound = sal_True;
882                                 }
883                             }
884                         }
885                     }
886                 }
887                 else
888                 {
889                     sal_uInt16 nPosition = 0;
890                     String aText = pEngine->GetWord( 0, aSel.nEndPos-1 );
891                     if( aText.GetChar( aSel.nEndPos-1 ) == '=' )
892                     {
893                         break;
894                     }
895                     String aNew;
896                     sal_uInt16 nParAutoPos = SCPOS_INVALID;
897                     nPosition = aText.Len()+1;
898                     if( pFormulaDataPara->FindText( aText, aNew, nParAutoPos, sal_False ) )
899                     {
900                         if( aFormula.GetChar( nPosition ) =='(' )
901                         {
902                             ShowTipBelow( aNew );
903                             bFound = sal_True;
904                         }
905                         else
906                             break;
907                     }
908                     else
909                     {
910                         break;
911                     }
912                 }
913             }
914         }
915     }
916 }
917 
918 void ScInputHandler::ShowTip( const String& rText )
919 {
920     //  aManualTip muss hinterher von aussen gesetzt werden
921     HideTip();
922 
923     EditView* pActiveView = pTopView ? pTopView : pTableView;
924     if (pActiveView)
925     {
926         Point aPos;
927         pTipVisibleParent = pActiveView->GetWindow();
928         Cursor* pCur = pActiveView->GetCursor();
929         if (pCur)
930             aPos = pTipVisibleParent->LogicToPixel( pCur->GetPos() );
931         aPos = pTipVisibleParent->OutputToScreenPixel( aPos );
932         Rectangle aRect( aPos, aPos );
933 
934         sal_uInt16 nAlign = QUICKHELP_LEFT|QUICKHELP_BOTTOM;
935         nTipVisible = Help::ShowTip(pTipVisibleParent, aRect, rText, nAlign);
936         pTipVisibleParent->AddEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleParentListener ) );
937     }
938 }
939 
940 void ScInputHandler::ShowTipBelow( const String& rText )
941 {
942     HideTipBelow();
943 
944     EditView* pActiveView = pTopView ? pTopView : pTableView;
945     if ( pActiveView )
946     {
947         Point aPos;
948         pTipVisibleSecParent = pActiveView->GetWindow();
949         Cursor* pCur = pActiveView->GetCursor();
950         if ( pCur )
951         {
952             Point aLogicPos = pCur->GetPos();
953             aLogicPos.Y() += pCur->GetHeight();
954             aPos = pTipVisibleSecParent->LogicToPixel( aLogicPos );
955         }
956         aPos = pTipVisibleSecParent->OutputToScreenPixel( aPos );
957         Rectangle aRect( aPos, aPos );
958         sal_uInt16 nAlign = QUICKHELP_LEFT | QUICKHELP_TOP | QUICKHELP_NOEVADEPOINTER;
959         nTipVisibleSec = Help::ShowTip(pTipVisibleSecParent, aRect, rText, nAlign);
960         pTipVisibleSecParent->AddEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleSecParentListener ) );
961     }
962 }
963 
964 void ScInputHandler::UseFormulaData()
965 {
966     EditView* pActiveView = pTopView ? pTopView : pTableView;
967     ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell();
968     const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
969     const sal_Unicode cSheetSep = lcl_getSheetSeparator(pDocSh->GetDocument());
970 
971     //  Formeln duerfen nur 1 Absatz haben
972     if ( pActiveView && pFormulaData && pEngine->GetParagraphCount() == 1 )
973     {
974         String aTotal = pEngine->GetText( (sal_uInt16) 0 );
975         ESelection aSel = pActiveView->GetSelection();
976         aSel.Adjust();
977 
978         //  #59348# Durch Differenzen zwischen Tabelle und Eingabezeile
979         //  (z.B. Clipboard mit Zeilenumbruechen) kann es sein, dass die Selektion
980         //  nicht mehr zur EditEngine passt. Dann halt kommentarlos abbrechen:
981 
982         if ( aSel.nEndPos > aTotal.Len() )
983             return;
984 
985         //  steht der Cursor am Ende eines Wortes?
986 
987         if ( aSel.nEndPos > 0 )
988         {
989             xub_StrLen nPos = aSel.nEndPos;
990             String  aFormula = aTotal.Copy( 0, nPos );;
991             xub_StrLen  nLeftParentPos = 0;
992             xub_StrLen  nNextFStart = 0;
993             xub_StrLen  nNextFEnd = 0;
994             xub_StrLen  nArgPos = 0;
995             const IFunctionDescription* ppFDesc;
996             ::std::vector< ::rtl::OUString> aArgs;
997             sal_uInt16      nArgs;
998             sal_Bool  bFound = sal_False;
999 
1000             String aText = pEngine->GetWord( 0, aSel.nEndPos-1 );
1001             if ( aText.Len() )
1002             {
1003                 String aNew;
1004                 nAutoPos = SCPOS_INVALID;
1005                 if ( pFormulaData->FindText( aText, aNew, nAutoPos, sal_False ) )
1006                 {
1007                     ShowTip( aNew );
1008                     aAutoSearch = aText;
1009                 }
1010             }
1011             FormulaHelper aHelper(ScGlobal::GetStarCalcFunctionMgr());
1012 
1013             while( !bFound )
1014             {
1015                 aFormula.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) );
1016                 nLeftParentPos = lcl_MatchParenthesis( aFormula, aFormula.Len()-1 );
1017                 if( nLeftParentPos == STRING_NOTFOUND )
1018                     break;
1019 
1020                 // #160063# nLeftParentPos can be 0 if a parenthesis is inserted before the formula
1021                 sal_Unicode c = ( nLeftParentPos > 0 ) ? aFormula.GetChar( nLeftParentPos-1 ) : 0;
1022                 if( !((c >= 'A' && c<= 'Z') || (c>= 'a' && c<= 'z') ) )
1023                     continue;
1024                 nNextFStart = aHelper.GetFunctionStart( aFormula, nLeftParentPos, sal_True);
1025                 if( aHelper.GetNextFunc( aFormula, sal_False, nNextFStart, &nNextFEnd, &ppFDesc, &aArgs ) )
1026                 {
1027                     if( ppFDesc->getFunctionName().getLength() )
1028                     {
1029                         nArgPos = aHelper.GetArgStart( aFormula, nNextFStart, 0 );
1030                         nArgs = static_cast<sal_uInt16>(ppFDesc->getParameterCount());
1031 
1032                         sal_uInt16 nActive = 0;
1033                         sal_uInt16 nCount = 0;
1034                         sal_uInt16 nCountSemicolon = 0;
1035                         sal_uInt16 nCountDot = 0;
1036                         sal_uInt16 nStartPosition = 0;
1037                         sal_uInt16 nEndPosition = 0;
1038                         sal_Bool   bFlag = sal_False;
1039                         String aNew;
1040                         sal_uInt16 nParAutoPos = SCPOS_INVALID;
1041                         if( pFormulaDataPara->FindText( ppFDesc->getFunctionName(), aNew, nParAutoPos, sal_False ) )
1042                         {
1043                             for( sal_uInt16 i=0; i < nArgs; i++ )
1044                             {
1045                                 xub_StrLen nLength = static_cast<xub_StrLen>(aArgs[i].getLength());
1046                                 if( nArgPos <= aFormula.Len()-1 )
1047                                 {
1048                                     nActive = i+1;
1049                                     bFlag = sal_True;
1050                                 }
1051                                 nArgPos+=nLength+1;
1052                             }
1053                             if( bFlag )
1054                             {
1055                                 nCountSemicolon = aNew.GetTokenCount(cSep)-1;
1056                                 nCountDot = aNew.GetTokenCount(cSheetSep)-1;
1057 
1058                                if( !nCountSemicolon )
1059                                {
1060                                     for( sal_uInt16 i = 0; i < aNew.Len(); i++ )
1061                                     {
1062                                         sal_Unicode cNext = aNew.GetChar( i );
1063                                         if( cNext == '(' )
1064                                         {
1065                                             nStartPosition = i+1;
1066                                         }
1067                                     }
1068                                 }
1069                                 else if( !nCountDot )
1070                                 {
1071                                     for( sal_uInt16 i = 0; i < aNew.Len(); i++ )
1072                                     {
1073                                         sal_Unicode cNext = aNew.GetChar( i );
1074                                         if( cNext == '(' )
1075                                         {
1076                                             nStartPosition = i+1;
1077                                         }
1078                                         else if( cNext == cSep )
1079                                         {
1080                                             nCount ++;
1081                                             nEndPosition = i;
1082                                             if( nCount == nActive )
1083                                             {
1084                                                 break;
1085                                             }
1086                                             nStartPosition = nEndPosition+1;
1087                                         }
1088                                     }
1089                                 }
1090                                 else
1091                                 {
1092                                     for( sal_uInt16 i = 0; i < aNew.Len(); i++ )
1093                                     {
1094                                         sal_Unicode cNext = aNew.GetChar( i );
1095                                         if( cNext == '(' )
1096                                         {
1097                                             nStartPosition = i+1;
1098                                         }
1099                                         else if( cNext == cSep )
1100                                         {
1101                                             nCount ++;
1102                                             nEndPosition = i;
1103                                             if( nCount == nActive )
1104                                             {
1105                                                 break;
1106                                             }
1107                                             nStartPosition = nEndPosition+1;
1108                                         }
1109                                         else if( cNext == cSheetSep )
1110                                         {
1111                                             continue;
1112                                         }
1113                                     }
1114                                 }
1115 
1116                                 if( nStartPosition )
1117                                 {
1118                                     aNew.Insert( 0x25BA, nStartPosition );
1119                                     ShowTipBelow( aNew );
1120                                     bFound = sal_True;
1121                                 }
1122                             }
1123                             else
1124                             {
1125                                 ShowTipBelow( aNew );
1126                                 bFound = sal_True;
1127                             }
1128                         }
1129                     }
1130                 }
1131             }
1132         }
1133     }
1134 }
1135 
1136 void ScInputHandler::NextFormulaEntry( sal_Bool bBack )
1137 {
1138     EditView* pActiveView = pTopView ? pTopView : pTableView;
1139     if ( pActiveView && pFormulaData )
1140     {
1141         String aNew;
1142         if ( pFormulaData->FindText( aAutoSearch, aNew, nAutoPos, bBack ) )
1143             ShowTip( aNew );        //  als QuickHelp anzeigen
1144     }
1145 
1146     //  bei Tab wird vorher immer HideCursor gerufen
1147 
1148     if (pActiveView)
1149         pActiveView->ShowCursor();
1150 }
1151 
1152 void lcl_CompleteFunction( EditView* pView, const String& rInsert, sal_Bool& rParInserted )
1153 {
1154     if (pView)
1155     {
1156         ESelection aSel = pView->GetSelection();
1157         --aSel.nStartPos;
1158         --aSel.nEndPos;
1159         pView->SetSelection(aSel);
1160         pView->SelectCurrentWord();
1161 
1162         String aInsStr = rInsert;
1163         xub_StrLen nInsLen = aInsStr.Len();
1164         sal_Bool bDoParen = ( nInsLen > 1 && aInsStr.GetChar(nInsLen-2) == '('
1165                                       && aInsStr.GetChar(nInsLen-1) == ')' );
1166         if ( bDoParen )
1167         {
1168             //  Klammern hinter Funktionsnamen nicht einfuegen, wenn direkt dahinter
1169             //  schon eine Klammer steht (z.B. wenn der Funktionsname geaendert wurde,
1170             //  #39393#).
1171 
1172             ESelection aWordSel = pView->GetSelection();
1173             String aOld = pView->GetEditEngine()->GetText((sal_uInt16)0);
1174             sal_Unicode cNext = aOld.GetChar(aWordSel.nEndPos);
1175             if ( cNext == '(' )
1176             {
1177                 bDoParen = sal_False;
1178                 aInsStr.Erase( nInsLen - 2 );   // Klammern weglassen
1179             }
1180         }
1181 
1182         pView->InsertText( aInsStr, sal_False );
1183 
1184         if ( bDoParen )                         // Cursor zwischen die Klammern setzen
1185         {
1186             aSel = pView->GetSelection();
1187             --aSel.nStartPos;
1188             --aSel.nEndPos;
1189             pView->SetSelection(aSel);
1190 
1191             rParInserted = sal_True;
1192         }
1193     }
1194 }
1195 
1196 void ScInputHandler::PasteFunctionData()
1197 {
1198     if ( pFormulaData && nAutoPos != SCPOS_INVALID )
1199     {
1200         TypedStrData* pData = (*pFormulaData)[nAutoPos];
1201         if (pData)
1202         {
1203             String aInsert = pData->GetString();
1204             sal_Bool bParInserted = sal_False;
1205 
1206             DataChanging();                         // kann nicht neu sein
1207             lcl_CompleteFunction( pTopView, aInsert, bParInserted );
1208             lcl_CompleteFunction( pTableView, aInsert, bParInserted );
1209             DataChanged();
1210             ShowTipCursor();
1211 
1212             if (bParInserted)
1213                 AutoParAdded();
1214         }
1215     }
1216 
1217     HideTip();
1218 
1219     EditView* pActiveView = pTopView ? pTopView : pTableView;
1220     if (pActiveView)
1221         pActiveView->ShowCursor();
1222 }
1223 
1224 //
1225 //      Selektion berechnen und als Tip-Hilfe anzeigen
1226 //
1227 
1228 String lcl_Calculate( const String& rFormula, ScDocument* pDoc, const ScAddress &rPos )
1229 {
1230     //!     mit ScFormulaDlg::CalcValue zusammenfassen und ans Dokument verschieben !!!!
1231     //!     (Anfuehrungszeichen bei Strings werden nur hier eingefuegt)
1232 
1233     String aValue;
1234 
1235     if (rFormula.Len())
1236     {
1237         ScFormulaCell* pCell = new ScFormulaCell( pDoc, rPos, rFormula );
1238 
1239         // #35521# HACK! um bei ColRowNames kein #REF! zu bekommen,
1240         // wenn ein Name eigentlich als Bereich in die Gesamt-Formel
1241         // eingefuegt wird, bei der Einzeldarstellung aber als
1242         // single-Zellbezug interpretiert wird
1243         sal_Bool bColRowName = pCell->HasColRowName();
1244         if ( bColRowName )
1245         {
1246             // ColRowName im RPN-Code?
1247             if ( pCell->GetCode()->GetCodeLen() <= 1 )
1248             {   // ==1: einzelner ist als Parameter immer Bereich
1249                 // ==0: es waere vielleicht einer, wenn..
1250                 String aBraced( '(' );
1251                 aBraced += rFormula;
1252                 aBraced += ')';
1253                 delete pCell;
1254                 pCell = new ScFormulaCell( pDoc, rPos, aBraced );
1255             }
1256             else
1257                 bColRowName = sal_False;
1258         }
1259 
1260         sal_uInt16 nErrCode = pCell->GetErrCode();
1261         if ( nErrCode == 0 )
1262         {
1263             SvNumberFormatter& aFormatter = *(pDoc->GetFormatTable());
1264             Color* pColor;
1265             if ( pCell->IsValue() )
1266             {
1267                 double n = pCell->GetValue();
1268                 sal_uLong nFormat = aFormatter.GetStandardFormat( n, 0,
1269                                 pCell->GetFormatType(), ScGlobal::eLnge );
1270                 aFormatter.GetInputLineString( n, nFormat, aValue );
1271                 //! display OutputString but insert InputLineString
1272             }
1273             else
1274             {
1275                 String aStr;
1276 
1277                 pCell->GetString( aStr );
1278                 sal_uLong nFormat = aFormatter.GetStandardFormat(
1279                                 pCell->GetFormatType(), ScGlobal::eLnge);
1280                 aFormatter.GetOutputString( aStr, nFormat,
1281                                             aValue, &pColor );
1282 
1283                 aValue.Insert('"',0);   // in Anfuehrungszeichen
1284                 aValue+='"';
1285                 //! Anfuehrungszeichen im String escapen ????
1286             }
1287 
1288             ScRange aTestRange;
1289             if ( bColRowName || (aTestRange.Parse(rFormula) & SCA_VALID) )
1290                 aValue.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " ..." ));       // Bereich
1291         }
1292         else
1293             aValue = ScGlobal::GetErrorString(nErrCode);
1294         delete pCell;
1295     }
1296 
1297     return aValue;
1298 }
1299 
1300 void ScInputHandler::FormulaPreview()
1301 {
1302     String aValue;
1303     EditView* pActiveView = pTopView ? pTopView : pTableView;
1304     if ( pActiveView && pActiveViewSh )
1305     {
1306         String aPart = pActiveView->GetSelected();
1307         if (!aPart.Len())
1308             aPart = pEngine->GetText((sal_uInt16)0);
1309         ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocShell()->GetDocument();
1310         aValue = lcl_Calculate( aPart, pDoc, aCursorPos );
1311     }
1312 
1313     if (aValue.Len())
1314     {
1315         ShowTip( aValue );          //  als QuickHelp anzeigen
1316         aManualTip = aValue;        //  nach ShowTip setzen
1317         nAutoPos = SCPOS_INVALID;   //  Formel-Autocomplete aufheben
1318     }
1319 }
1320 
1321 void ScInputHandler::PasteManualTip()
1322 {
1323     //  drei Punkte am Ende -> Bereichsreferenz -> nicht einfuegen
1324     //  (wenn wir mal Matrix-Konstanten haben, kann das geaendert werden)
1325 
1326     xub_StrLen nTipLen = aManualTip.Len();
1327     if ( nTipLen && ( nTipLen < 3 || !aManualTip.Copy( nTipLen-3 ).EqualsAscii("...") ) )
1328     {
1329         DataChanging();                                     // kann nicht neu sein
1330 
1331         String aInsert = aManualTip;
1332         EditView* pActiveView = pTopView ? pTopView : pTableView;
1333         if (!pActiveView->HasSelection())
1334         {
1335             //  nichts selektiert -> alles selektieren
1336             xub_StrLen nOldLen = pEngine->GetTextLen(0);
1337             ESelection aAllSel( 0, 0, 0, nOldLen );
1338             if ( pTopView )
1339                 pTopView->SetSelection( aAllSel );
1340             if ( pTableView )
1341                 pTableView->SetSelection( aAllSel );
1342         }
1343 
1344         ESelection aSel = pActiveView->GetSelection();
1345         aSel.Adjust();
1346         DBG_ASSERT( !aSel.nStartPara && !aSel.nEndPara, "Zuviele Absaetze in Formel" );
1347         if ( !aSel.nStartPos )  // Selektion ab Anfang?
1348         {
1349             if ( aSel.nEndPos == pEngine->GetTextLen(0) )
1350             {
1351                 //  alles selektiert -> Anfuehrungszeichen weglassen
1352                 if ( aInsert.GetChar(0) == '"' )
1353                     aInsert.Erase(0,1);
1354                 xub_StrLen nInsLen = aInsert.Len();
1355                 if ( nInsLen && aInsert.GetChar(nInsLen-1) == '"' )
1356                     aInsert.Erase( nInsLen-1 );
1357             }
1358             else if ( aSel.nEndPos )
1359             {
1360                 //  nicht alles selektiert -> Gleichheitszeichen nicht ueberschreiben
1361                 //! doppelte Gleichheitszeichen auch ???
1362 
1363                 aSel.nStartPos = 1;
1364                 if ( pTopView )
1365                     pTopView->SetSelection( aSel );
1366                 if ( pTableView )
1367                     pTableView->SetSelection( aSel );
1368             }
1369         }
1370         if ( pTopView )
1371             pTopView->InsertText( aInsert, sal_True );
1372         if ( pTableView )
1373             pTableView->InsertText( aInsert, sal_True );
1374 
1375         DataChanged();
1376     }
1377 
1378     HideTip();
1379 }
1380 
1381 void ScInputHandler::ResetAutoPar()
1382 {
1383     nAutoPar = 0;
1384 }
1385 
1386 void ScInputHandler::AutoParAdded()
1387 {
1388     ++nAutoPar;     //  closing parenthesis can be overwritten
1389 }
1390 
1391 sal_Bool ScInputHandler::CursorAtClosingPar()
1392 {
1393     //  test if the cursor is before a closing parenthesis
1394 
1395     //  selection from SetReference has been removed before
1396     EditView* pActiveView = pTopView ? pTopView : pTableView;
1397     if ( pActiveView && !pActiveView->HasSelection() && bFormulaMode )
1398     {
1399         ESelection aSel = pActiveView->GetSelection();
1400         xub_StrLen nPos = aSel.nStartPos;
1401         String aFormula = pEngine->GetText((sal_uInt16)0);
1402         if ( nPos < aFormula.Len() && aFormula.GetChar(nPos) == ')' )
1403             return sal_True;
1404     }
1405     return sal_False;
1406 }
1407 
1408 void ScInputHandler::SkipClosingPar()
1409 {
1410     //  this is called when a ')' is typed and the cursor is before a ')'
1411     //  that can be overwritten -> just set the cursor behind the ')'
1412 
1413     EditView* pActiveView = pTopView ? pTopView : pTableView;
1414     if (pActiveView)
1415     {
1416         ESelection aSel = pActiveView->GetSelection();
1417         ++aSel.nStartPos;
1418         ++aSel.nEndPos;
1419 
1420         //  this is in a formula (only one paragraph), so the selection
1421         //  can be used directly for the TopView
1422 
1423         if ( pTopView )
1424             pTopView->SetSelection( aSel );
1425         if ( pTableView )
1426             pTableView->SetSelection( aSel );
1427     }
1428 
1429     DBG_ASSERT(nAutoPar, "SkipClosingPar: count is wrong");
1430     --nAutoPar;
1431 }
1432 
1433 //
1434 //      Auto-Eingabe
1435 //
1436 
1437 void ScInputHandler::GetColData()
1438 {
1439     if ( pActiveViewSh )
1440     {
1441         ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocShell()->GetDocument();
1442 
1443         if ( pColumnData )
1444             pColumnData->FreeAll();
1445         else
1446         {
1447             pColumnData = new TypedScStrCollection;
1448             pColumnData->SetCaseSensitive( sal_True );      // equal strings are handled in FindText
1449         }
1450 
1451         pDoc->GetDataEntries( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(),
1452                                 *pColumnData, sal_True );
1453     }
1454 }
1455 
1456 void ScInputHandler::UseColData()           // beim Tippen
1457 {
1458     EditView* pActiveView = pTopView ? pTopView : pTableView;
1459     if ( pActiveView && pColumnData )
1460     {
1461         //  nur anpassen, wenn Cursor am Ende steht
1462 
1463         ESelection aSel = pActiveView->GetSelection();
1464         aSel.Adjust();
1465 
1466         sal_uInt16 nParCnt = pEngine->GetParagraphCount();
1467         if ( aSel.nEndPara+1 == nParCnt )
1468         {
1469             xub_StrLen nParLen = pEngine->GetTextLen( aSel.nEndPara );
1470             if ( aSel.nEndPos == nParLen )
1471             {
1472                 String aText = GetEditText(pEngine);
1473                 if (aText.Len())
1474                 {
1475                     String aNew;
1476                     nAutoPos = SCPOS_INVALID;   // nix
1477                     if ( pColumnData->FindText( aText, aNew, nAutoPos, sal_False ) )
1478                     {
1479                         //  #45434# durch dBase Import etc. koennen Umbrueche im String sein,
1480                         //  das wuerde hier mehrere Absaetze ergeben -> nicht gut
1481                         //! GetExactMatch funktioniert dann auch nicht
1482                         lcl_RemoveLineEnd( aNew );
1483 
1484                         //  Absaetze beibehalten, nur den Rest anfuegen
1485                         //! genaue Ersetzung im EnterHandler !!!
1486 
1487                         // ein Space zwischen Absaetzen:
1488                         sal_uLong nEdLen = pEngine->GetTextLen() + nParCnt - 1;
1489                         String aIns = aNew.Copy( (xub_StrLen)nEdLen );
1490 
1491                         //  selection must be "backwards", so the cursor stays behind the last
1492                         //  typed character
1493                         ESelection aSelection( aSel.nEndPara, aSel.nEndPos + aIns.Len(),
1494                                                aSel.nEndPara, aSel.nEndPos );
1495 
1496                         //  when editing in input line, apply to both edit views
1497                         if ( pTableView )
1498                         {
1499                             pTableView->InsertText( aIns, sal_False );
1500                             pTableView->SetSelection( aSelection );
1501                         }
1502                         if ( pTopView )
1503                         {
1504                             pTopView->InsertText( aIns, sal_False );
1505                             pTopView->SetSelection( aSelection );
1506                         }
1507 
1508                         aAutoSearch = aText;    // zum Weitersuchen - nAutoPos ist gesetzt
1509 
1510                         if ( aText.Len() == aNew.Len() )
1511                         {
1512                             //  Wenn der eingegebene Text gefunden wurde, TAB nur dann
1513                             //  verschlucken, wenn noch etwas kommt
1514 
1515                             String aDummy;
1516                             sal_uInt16 nNextPos = nAutoPos;
1517                             bUseTab = pColumnData->FindText( aText, aDummy, nNextPos, sal_False );
1518                         }
1519                         else
1520                             bUseTab = sal_True;
1521                     }
1522                 }
1523             }
1524         }
1525     }
1526 }
1527 
1528 void ScInputHandler::NextAutoEntry( sal_Bool bBack )
1529 {
1530     EditView* pActiveView = pTopView ? pTopView : pTableView;
1531     if ( pActiveView && pColumnData )
1532     {
1533         if ( nAutoPos != SCPOS_INVALID && aAutoSearch.Len() )
1534         {
1535             //  stimmt die Selektion noch? (kann per Maus geaendert sein)
1536 
1537             ESelection aSel = pActiveView->GetSelection();
1538             aSel.Adjust();
1539             sal_uInt16 nParCnt = pEngine->GetParagraphCount();
1540             if ( aSel.nEndPara+1 == nParCnt && aSel.nStartPara == aSel.nEndPara )
1541             {
1542                 String aText = GetEditText(pEngine);
1543                 xub_StrLen nSelLen = aSel.nEndPos - aSel.nStartPos;
1544                 xub_StrLen nParLen = pEngine->GetTextLen( aSel.nEndPara );
1545                 if ( aSel.nEndPos == nParLen && aText.Len() == aAutoSearch.Len() + nSelLen )
1546                 {
1547                     String aNew;
1548                     if ( pColumnData->FindText( aAutoSearch, aNew, nAutoPos, bBack ) )
1549                     {
1550                         bInOwnChange = sal_True;        // disable ModifyHdl (reset below)
1551 
1552                         lcl_RemoveLineEnd( aNew );
1553                         String aIns = aNew.Copy( aAutoSearch.Len() );
1554 
1555                         //  when editing in input line, apply to both edit views
1556                         if ( pTableView )
1557                         {
1558                             pTableView->DeleteSelected();
1559                             pTableView->InsertText( aIns, sal_False );
1560                             pTableView->SetSelection( ESelection(
1561                                                         aSel.nEndPara, aSel.nStartPos + aIns.Len(),
1562                                                         aSel.nEndPara, aSel.nStartPos ) );
1563                         }
1564                         if ( pTopView )
1565                         {
1566                             pTopView->DeleteSelected();
1567                             pTopView->InsertText( aIns, sal_False );
1568                             pTopView->SetSelection( ESelection(
1569                                                         aSel.nEndPara, aSel.nStartPos + aIns.Len(),
1570                                                         aSel.nEndPara, aSel.nStartPos ) );
1571                         }
1572 
1573                         bInOwnChange = sal_False;
1574                     }
1575                     else
1576                     {
1577                         // mehr gibts nicht
1578 
1579                         Sound::Beep();
1580                     }
1581                 }
1582             }
1583         }
1584     }
1585 
1586     //  bei Tab wird vorher immer HideCursor gerufen
1587 
1588     if (pActiveView)
1589         pActiveView->ShowCursor();
1590 }
1591 
1592 //
1593 //      Klammern hervorheben
1594 //
1595 
1596 void ScInputHandler::UpdateParenthesis()
1597 {
1598     //  Klammern suchen
1599 
1600     //! Klammer-Hervorhebung einzeln abschaltbar ????
1601 
1602     sal_Bool bFound = sal_False;
1603     if ( bFormulaMode && eMode != SC_INPUT_TOP )
1604     {
1605         if ( pTableView && !pTableView->HasSelection() )        // Selektion ist immer unten
1606         {
1607             ESelection aSel = pTableView->GetSelection();
1608             if (aSel.nStartPos)
1609             {
1610                 //  Das Zeichen links vom Cursor wird angeschaut
1611 
1612                 xub_StrLen nPos = aSel.nStartPos - 1;
1613                 String aFormula = pEngine->GetText((sal_uInt16)0);
1614                 sal_Unicode c = aFormula.GetChar(nPos);
1615                 if ( c == '(' || c == ')' )
1616                 {
1617                     xub_StrLen nOther = lcl_MatchParenthesis( aFormula, nPos );
1618                     if ( nOther != STRING_NOTFOUND )
1619                     {
1620                         SfxItemSet aSet( pEngine->GetEmptyItemSet() );
1621                         aSet.Put( SvxWeightItem( WEIGHT_BOLD, EE_CHAR_WEIGHT ) );
1622                         //! Unterscheidung, wenn die Zelle schon fett ist !!!!
1623 
1624                         if (bParenthesisShown)
1625                         {
1626                             //  alte Hervorhebung wegnehmen
1627                             sal_uInt16 nCount = pEngine->GetParagraphCount();
1628                             for (sal_uInt16 i=0; i<nCount; i++)
1629                                 pEngine->QuickRemoveCharAttribs( i, EE_CHAR_WEIGHT );
1630                         }
1631 
1632                         ESelection aSelThis( 0,nPos, 0,nPos+1 );
1633                         pEngine->QuickSetAttribs( aSet, aSelThis );
1634                         ESelection aSelOther( 0,nOther, 0,nOther+1 );
1635                         pEngine->QuickSetAttribs( aSet, aSelOther );
1636 
1637                         //  Dummy-InsertText fuer Update und Paint (Selektion ist leer)
1638                         pTableView->InsertText( EMPTY_STRING, sal_False );
1639 
1640                         bFound = sal_True;
1641                     }
1642                 }
1643             }
1644 
1645             //  mark parenthesis right of cursor if it will be overwritten (nAutoPar)
1646             //  with different color (COL_LIGHTBLUE) ??
1647         }
1648     }
1649 
1650     //  alte Hervorhebung wegnehmen, wenn keine neue gesetzt
1651 
1652     if ( bParenthesisShown && !bFound && pTableView )
1653     {
1654         sal_uInt16 nCount = pEngine->GetParagraphCount();
1655         for (sal_uInt16 i=0; i<nCount; i++)
1656             pTableView->RemoveCharAttribs( i, EE_CHAR_WEIGHT );
1657     }
1658 
1659     bParenthesisShown = bFound;
1660 }
1661 
1662 void ScInputHandler::ViewShellGone(ScTabViewShell* pViewSh)     // wird synchron aufgerufen!
1663 {
1664     if ( pViewSh == pActiveViewSh )
1665     {
1666         delete pLastState;
1667         pLastState = NULL;
1668         pLastPattern = NULL;
1669     }
1670 
1671     if ( pViewSh == pRefViewSh )
1672     {
1673         //! Die Eingabe kommt aus dem EnterHandler nicht mehr an
1674         //  Trotzdem wird immerhin der Editmodus beendet
1675 
1676         EnterHandler();
1677         bFormulaMode = sal_False;
1678         pRefViewSh = NULL;
1679         SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
1680         SC_MOD()->SetRefInputHdl(NULL);
1681         if (pInputWin)
1682             pInputWin->SetFormulaMode(sal_False);
1683         UpdateAutoCorrFlag();
1684     }
1685 
1686     pActiveViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
1687 
1688     if ( pActiveViewSh && pActiveViewSh == pViewSh )
1689     {
1690         DBG_ERROR("pActiveViewSh weg");
1691         pActiveViewSh = NULL;
1692     }
1693 
1694     if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
1695         UpdateRefDevice();      // don't keep old document's printer as RefDevice
1696 }
1697 
1698 void ScInputHandler::UpdateActiveView()
1699 {
1700     ImplCreateEditEngine();
1701 
1702     // #i20588# Don't rely on focus to find the active edit view. Instead, the
1703     // active pane at the start of editing is now stored (GetEditActivePart).
1704     // GetActiveWin (the currently active pane) fails for ref input across the
1705     // panes of a split view.
1706 
1707     Window* pShellWin = pActiveViewSh ?
1708                 pActiveViewSh->GetWindowByPos( pActiveViewSh->GetViewData()->GetEditActivePart() ) :
1709                 NULL;
1710 
1711     sal_uInt16 nCount = pEngine->GetViewCount();
1712     if (nCount > 0)
1713     {
1714         pTableView = pEngine->GetView(0);
1715         for (sal_uInt16 i=1; i<nCount; i++)
1716         {
1717             EditView* pThis = pEngine->GetView(i);
1718             Window* pWin = pThis->GetWindow();
1719             if ( pWin==pShellWin )
1720                 pTableView = pThis;
1721         }
1722     }
1723     else
1724         pTableView = NULL;
1725 
1726     if (pInputWin)
1727         pTopView = pInputWin->GetEditView();
1728     else
1729         pTopView = NULL;
1730 }
1731 
1732 void ScInputHandler::StopInputWinEngine( sal_Bool bAll )
1733 {
1734     if (pInputWin)
1735         pInputWin->StopEditEngine( bAll );
1736 
1737     pTopView = NULL;        // invalid now
1738 }
1739 
1740 EditView* ScInputHandler::GetActiveView()
1741 {
1742     UpdateActiveView();
1743     return pTopView ? pTopView : pTableView;
1744 }
1745 
1746 void ScInputHandler::ForgetLastPattern()
1747 {
1748     pLastPattern = NULL;
1749     if ( !pLastState && pActiveViewSh )
1750         pActiveViewSh->UpdateInputHandler( sal_True );      // Status neu holen
1751     else
1752         NotifyChange( pLastState, sal_True );
1753 }
1754 
1755 void ScInputHandler::UpdateAdjust( sal_Unicode cTyped )
1756 {
1757     SvxAdjust eSvxAdjust;
1758     switch (eAttrAdjust)
1759     {
1760         case SVX_HOR_JUSTIFY_STANDARD:
1761             {
1762                 sal_Bool bNumber = sal_False;
1763                 if (cTyped)                                     // neu angefangen
1764                     bNumber = (cTyped>='0' && cTyped<='9');     // nur Ziffern sind Zahlen
1765                 else if ( pActiveViewSh )
1766                 {
1767                     ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocShell()->GetDocument();
1768                     bNumber = ( pDoc->GetCellType( aCursorPos ) == CELLTYPE_VALUE );
1769                 }
1770                 eSvxAdjust = bNumber ? SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT;
1771             }
1772             break;
1773         case SVX_HOR_JUSTIFY_BLOCK:
1774             eSvxAdjust = SVX_ADJUST_BLOCK;
1775             break;
1776         case SVX_HOR_JUSTIFY_CENTER:
1777             eSvxAdjust = SVX_ADJUST_CENTER;
1778             break;
1779         case SVX_HOR_JUSTIFY_RIGHT:
1780             eSvxAdjust = SVX_ADJUST_RIGHT;
1781             break;
1782         default:    // SVX_HOR_JUSTIFY_LEFT
1783             eSvxAdjust = SVX_ADJUST_LEFT;
1784             break;
1785     }
1786 
1787     sal_Bool bAsianVertical = pLastPattern &&
1788         ((const SfxBoolItem&)pLastPattern->GetItem( ATTR_STACKED )).GetValue() &&
1789         ((const SfxBoolItem&)pLastPattern->GetItem( ATTR_VERTICAL_ASIAN )).GetValue();
1790     if ( bAsianVertical )
1791     {
1792         //  always edit at top of cell -> LEFT when editing vertically
1793         eSvxAdjust = SVX_ADJUST_LEFT;
1794     }
1795 
1796     pEditDefaults->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
1797     pEngine->SetDefaults( *pEditDefaults );
1798 
1799     nEditAdjust = sal::static_int_cast<sal_uInt16>(eSvxAdjust);     //! set at ViewData or with PostEditView
1800 
1801     pEngine->SetVertical( bAsianVertical );
1802 }
1803 
1804 void ScInputHandler::RemoveAdjust()
1805 {
1806     //  harte Ausrichtungs-Attribute loeschen
1807 
1808     sal_Bool bUndo = pEngine->IsUndoEnabled();
1809     if ( bUndo )
1810         pEngine->EnableUndo( sal_False );
1811 
1812     //  RemoveParaAttribs removes all paragraph attributes, including EE_PARA_JUST
1813 #if 0
1814     sal_Bool bChange = sal_False;
1815     sal_uInt16 nCount = pEngine->GetParagraphCount();
1816     for (sal_uInt16 i=0; i<nCount; i++)
1817     {
1818         const SfxItemSet& rOld = pEngine->GetParaAttribs( i );
1819         if ( rOld.GetItemState( EE_PARA_JUST ) == SFX_ITEM_SET )
1820         {
1821             SfxItemSet aNew( rOld );
1822             aNew.ClearItem( EE_PARA_JUST );
1823             pEngine->SetParaAttribs( i, aNew );
1824             bChange = sal_True;
1825         }
1826     }
1827 #endif
1828 
1829     //  #89403# non-default paragraph attributes (e.g. from clipboard)
1830     //  must be turned into character attributes
1831     pEngine->RemoveParaAttribs();
1832 
1833     if ( bUndo )
1834         pEngine->EnableUndo( sal_True );
1835 
1836     // ER 31.08.00  Only called in EnterHandler, don't change view anymore.
1837 #if 0
1838     if (bChange)
1839     {
1840         EditView* pActiveView = pTopView ? pTopView : pTableView;
1841         pActiveView->ShowCursor( sal_False, sal_True );
1842     }
1843 #endif
1844 }
1845 
1846 void ScInputHandler::RemoveRangeFinder()
1847 {
1848     //  pRangeFindList und Farben loeschen
1849 
1850     pEngine->SetUpdateMode(sal_False);
1851     sal_uInt16 nCount = pEngine->GetParagraphCount();   // koennte gerade neu eingefuegt worden sein
1852     for (sal_uInt16 i=0; i<nCount; i++)
1853         pEngine->QuickRemoveCharAttribs( i, EE_CHAR_COLOR );
1854     pEngine->SetUpdateMode(sal_True);
1855 
1856     EditView* pActiveView = pTopView ? pTopView : pTableView;
1857     pActiveView->ShowCursor( sal_False, sal_True );
1858 
1859     DeleteRangeFinder();        // loescht die Liste und die Markierungen auf der Tabelle
1860 }
1861 
1862 sal_Bool ScInputHandler::StartTable( sal_Unicode cTyped, sal_Bool bFromCommand )
1863 {
1864     // returns sal_True if a new edit mode was started
1865 
1866     sal_Bool bNewTable = sal_False;
1867 
1868     if (!bModified && ValidCol(aCursorPos.Col()))
1869     {
1870         if (pActiveViewSh)
1871         {
1872             ImplCreateEditEngine();
1873             UpdateActiveView();
1874             SyncViews();
1875 
1876             ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocShell()->GetDocument();
1877 
1878             const ScMarkData& rMark = pActiveViewSh->GetViewData()->GetMarkData();
1879             ScEditableTester aTester;
1880             if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1881                 aTester.TestSelection( pDoc, rMark );
1882             else
1883                 aTester.TestSelectedBlock( pDoc, aCursorPos.Col(),aCursorPos.Row(),
1884                                                  aCursorPos.Col(),aCursorPos.Row(), rMark );
1885             if ( aTester.IsEditable() )
1886             {
1887                 // UpdateMode is enabled again in ScViewData::SetEditEngine (and not needed otherwise)
1888                 pEngine->SetUpdateMode( sal_False );
1889 
1890                 //  Attribute in EditEngine uebernehmen
1891 
1892                 const ScPatternAttr* pPattern = pDoc->GetPattern( aCursorPos.Col(),
1893                                                                   aCursorPos.Row(),
1894                                                                   aCursorPos.Tab() );
1895                 if (pPattern != pLastPattern)
1896                 {
1897                     //  Prozent-Format?
1898 
1899                     const SfxItemSet& rAttrSet = pPattern->GetItemSet();
1900                     const SfxPoolItem* pItem;
1901 
1902                     if ( SFX_ITEM_SET == rAttrSet.GetItemState( ATTR_VALUE_FORMAT, sal_True, &pItem ) )
1903                     {
1904                         sal_uLong nFormat = ((const SfxUInt32Item*)pItem)->GetValue();
1905                         bCellHasPercentFormat = ( NUMBERFORMAT_PERCENT ==
1906                                                   pDoc->GetFormatTable()->GetType( nFormat ) );
1907                     }
1908                     else
1909                         bCellHasPercentFormat = sal_False; // Default: kein Prozent
1910 
1911                     //  Gueltigkeit angegeben?
1912 
1913                     if ( SFX_ITEM_SET == rAttrSet.GetItemState( ATTR_VALIDDATA, sal_True, &pItem ) )
1914                         nValidation = ((const SfxUInt32Item*)pItem)->GetValue();
1915                     else
1916                         nValidation = 0;
1917 
1918                     //  EditEngine Defaults
1919 
1920                     //  Hier auf keinen Fall SetParaAttribs, weil die EditEngine evtl.
1921                     //  schon gefuellt ist (bei Edit-Zellen).
1922                     //  SetParaAttribs wuerde dann den Inhalt aendern
1923 
1924                     //! ER 30.08.00  The SetDefaults is now (since MUST/src602
1925                     //! EditEngine changes) implemented as a SetParaAttribs.
1926                     //! Any problems?
1927 
1928                     pPattern->FillEditItemSet( pEditDefaults );
1929                     pEngine->SetDefaults( *pEditDefaults );
1930                     pLastPattern = pPattern;
1931                     bLastIsSymbol = pPattern->IsSymbolFont();
1932 
1933                     //  Background color must be known for automatic font color.
1934                     //  For transparent cell background, the document background color must be used.
1935 
1936                     Color aBackCol = ((const SvxBrushItem&)
1937                                     pPattern->GetItem( ATTR_BACKGROUND )).GetColor();
1938                     ScModule* pScMod = SC_MOD();
1939                     //  #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
1940                     if ( aBackCol.GetTransparency() > 0 ||
1941                             Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
1942                         aBackCol.SetColor( pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
1943                     pEngine->SetBackgroundColor( aBackCol );
1944 
1945                     //  Ausrichtung
1946 
1947                     eAttrAdjust = (SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
1948                                     GetItem(ATTR_HOR_JUSTIFY)).GetValue();
1949                     if ( eAttrAdjust == SVX_HOR_JUSTIFY_REPEAT &&
1950                          static_cast<const SfxBoolItem&>(pPattern->GetItem(ATTR_LINEBREAK)).GetValue() )
1951                     {
1952                         // #i31843# "repeat" with "line breaks" is treated as default alignment
1953                         eAttrAdjust = SVX_HOR_JUSTIFY_STANDARD;
1954                     }
1955                 }
1956 
1957                 //  UpdateSpellSettings enables online spelling if needed
1958                 //  -> also call if attributes are unchanged
1959 
1960                 UpdateSpellSettings( sal_True );    // uses pLastPattern
1961 
1962                 //  Edit-Engine fuellen
1963 
1964                 String aStr;
1965                 if (bTextValid)
1966                 {
1967                     pEngine->SetText(aCurrentText);
1968                     aStr = aCurrentText;
1969                     bTextValid = sal_False;
1970                     aCurrentText.Erase();
1971                 }
1972                 else
1973                     aStr = GetEditText(pEngine);
1974 
1975                 if (aStr.Len() > 3 &&                   // Matrix-Formel ?
1976                     aStr.GetChar(0) == '{' &&
1977                     aStr.GetChar(1) == '=' &&
1978                     aStr.GetChar(aStr.Len()-1) == '}')
1979                 {
1980                     aStr.Erase(0,1);
1981                     aStr.Erase(aStr.Len()-1,1);
1982                     pEngine->SetText(aStr);
1983                     if ( pInputWin )
1984                         pInputWin->SetTextString(aStr);
1985                 }
1986 
1987                 UpdateAdjust( cTyped );
1988 
1989                 if ( bAutoComplete )
1990                     GetColData();
1991 
1992                 if ( ( aStr.GetChar(0) == '=' || aStr.GetChar(0) == '+' || aStr.GetChar(0) == '-' ) &&
1993                      !cTyped && !bCreatingFuncView )
1994                     InitRangeFinder(aStr);              // Formel wird editiert -> RangeFinder
1995 
1996                 bNewTable = sal_True;       //  -> PostEditView-Aufruf
1997             }
1998             else
1999             {
2000                 bProtected = sal_True;
2001                 eMode = SC_INPUT_NONE;
2002                 StopInputWinEngine( sal_True );
2003                 UpdateFormulaMode();
2004                 if ( pActiveViewSh && ( !bFromCommand || !bCommandErrorShown ) )
2005                 {
2006                     //  #97673# Prevent repeated error messages for the same cell from command events
2007                     //  (for keyboard events, multiple messages are wanted).
2008                     //  Set the flag before showing the error message because the command handler
2009                     //  for the next IME command may be called when showing the dialog.
2010                     if ( bFromCommand )
2011                         bCommandErrorShown = sal_True;
2012 
2013                     pActiveViewSh->GetActiveWin()->GrabFocus();
2014                     pActiveViewSh->ErrorMessage(aTester.GetMessageId());
2015                 }
2016             }
2017         }
2018 
2019         if (!bProtected && pInputWin)
2020             pInputWin->SetOkCancelMode();
2021     }
2022 
2023     return bNewTable;
2024 }
2025 
2026 void lcl_SetTopSelection( EditView* pEditView, ESelection& rSel )
2027 {
2028     DBG_ASSERT( rSel.nStartPara==0 && rSel.nEndPara==0, "SetTopSelection: Para != 0" );
2029 
2030     EditEngine* pEngine = pEditView->GetEditEngine();
2031     sal_uInt16 nCount = pEngine->GetParagraphCount();
2032     if (nCount > 1)
2033     {
2034         xub_StrLen nParLen = pEngine->GetTextLen(rSel.nStartPara);
2035         while (rSel.nStartPos > nParLen && rSel.nStartPara+1 < nCount)
2036         {
2037             rSel.nStartPos -= nParLen + 1;          // incl. Leerzeichen vom Umbruch
2038             nParLen = pEngine->GetTextLen(++rSel.nStartPara);
2039         }
2040 
2041         nParLen = pEngine->GetTextLen(rSel.nEndPara);
2042         while (rSel.nEndPos > nParLen && rSel.nEndPara+1 < nCount)
2043         {
2044             rSel.nEndPos -= nParLen + 1;            // incl. Leerzeichen vom Umbruch
2045             nParLen = pEngine->GetTextLen(++rSel.nEndPara);
2046         }
2047     }
2048 
2049     ESelection aSel = pEditView->GetSelection();
2050 
2051     if (   rSel.nStartPara != aSel.nStartPara || rSel.nEndPara != aSel.nEndPara
2052         || rSel.nStartPos  != aSel.nStartPos  || rSel.nEndPos  != aSel.nEndPos )
2053         pEditView->SetSelection( rSel );
2054 }
2055 
2056 void ScInputHandler::SyncViews( EditView* pSourceView )
2057 {
2058     ESelection aSel;
2059 
2060     if (pSourceView)
2061     {
2062         aSel = pSourceView->GetSelection();
2063         if (pTopView && pTopView != pSourceView)
2064             pTopView->SetSelection( aSel );
2065         if (pTableView && pTableView != pSourceView)
2066             lcl_SetTopSelection( pTableView, aSel );
2067     }
2068     else if (pTopView && pTableView)
2069     {
2070         aSel = pTopView->GetSelection();
2071         lcl_SetTopSelection( pTableView, aSel );
2072     }
2073 }
2074 
2075 IMPL_LINK( ScInputHandler, ModifyHdl, void *, EMPTYARG )
2076 {
2077     if ( !bInOwnChange && ( eMode==SC_INPUT_TYPE || eMode==SC_INPUT_TABLE ) &&
2078          pEngine && pEngine->GetUpdateMode() && pInputWin )
2079     {
2080         //  #102745# update input line from ModifyHdl for changes that are not
2081         //  wrapped by DataChanging/DataChanged calls (like Drag&Drop)
2082 
2083         String aText = GetEditText(pEngine);
2084         lcl_RemoveTabs(aText);
2085         pInputWin->SetTextString(aText);
2086     }
2087     return 0;
2088 }
2089 
2090 sal_Bool ScInputHandler::DataChanging( sal_Unicode cTyped, sal_Bool bFromCommand )      // return sal_True = new view created
2091 {
2092     bInOwnChange = sal_True;                // disable ModifyHdl (reset in DataChanged)
2093 
2094     if ( eMode == SC_INPUT_NONE )
2095         return StartTable( cTyped, bFromCommand );
2096     else
2097         return sal_False;
2098 }
2099 
2100 void ScInputHandler::DataChanged( sal_Bool bFromTopNotify, sal_Bool bSetModified )
2101 {
2102     ImplCreateEditEngine();
2103 
2104     if (eMode==SC_INPUT_NONE)
2105         eMode = SC_INPUT_TYPE;
2106 
2107     if ( eMode == SC_INPUT_TOP && pTopView && !bFromTopNotify )
2108     {
2109         //  table EditEngine is formatted below, input line needs formatting after paste
2110         //  #i20282# not when called from the input line's modify handler
2111         pTopView->GetEditEngine()->QuickFormatDoc( sal_True );
2112 
2113         //  #i23720# QuickFormatDoc hides the cursor, but can't show it again because it
2114         //  can't safely access the EditEngine's current view, so the cursor has to be
2115         //  shown again here.
2116         pTopView->ShowCursor();
2117     }
2118 
2119     if (bSetModified)
2120         bModified = sal_True;
2121     bSelIsRef = sal_False;
2122 
2123     if ( pRangeFindList && !bInRangeUpdate )
2124         RemoveRangeFinder();                    // Attribute und Markierung loeschen
2125 
2126     UpdateParenthesis();    //  Hervorhebung der Klammern neu
2127 
2128     // ER 31.08.00  New SetDefaults sets ParaAttribs, don't clear them away ...
2129 //  RemoveAdjust();     //  #40255# harte Ausrichtungs-Attribute loeschen
2130 
2131     if (eMode==SC_INPUT_TYPE || eMode==SC_INPUT_TABLE)
2132     {
2133         String aText = GetEditText(pEngine);
2134         lcl_RemoveTabs(aText);
2135 
2136         if ( pInputWin )
2137             pInputWin->SetTextString(aText);
2138     }
2139 
2140         //  wenn der Cursor vor dem Absatzende steht, werden Teile rechts rausgeschoben
2141         //  (unabhaengig von eMode)     -> View anpassen!
2142         //  wenn der Cursor am Ende steht, reicht der Status-Handler an der ViewData
2143 
2144     //  #93767# first make sure the status handler is called now if the cursor
2145     //  is outside the visible area
2146     pEngine->QuickFormatDoc();
2147 
2148     EditView* pActiveView = pTopView ? pTopView : pTableView;
2149     if (pActiveView && pActiveViewSh)
2150     {
2151         ScViewData* pViewData = pActiveViewSh->GetViewData();
2152 
2153         sal_Bool bNeedGrow = ( nEditAdjust != SVX_ADJUST_LEFT );        // rechtsbuendig immer
2154         if (!bNeedGrow)
2155         {
2156                 //  Cursor vor dem Ende?
2157             ESelection aSel = pActiveView->GetSelection();
2158             aSel.Adjust();
2159             bNeedGrow = ( aSel.nEndPos != pEngine->GetTextLen(aSel.nEndPara) );
2160         }
2161         if (!bNeedGrow)
2162         {
2163             bNeedGrow = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() );
2164         }
2165         if (bNeedGrow)
2166         {
2167             // adjust inplace view
2168             pViewData->EditGrowY();
2169             pViewData->EditGrowX();
2170         }
2171     }
2172 
2173     UpdateFormulaMode();
2174     bTextValid = sal_False;         // Aenderungen sind nur in der Edit-Engine
2175     bInOwnChange = sal_False;
2176 }
2177 
2178 void ScInputHandler::UpdateFormulaMode()
2179 {
2180     SfxApplication* pSfxApp = SFX_APP();
2181 
2182     if ( pEngine->GetParagraphCount() == 1 &&
2183          ( pEngine->GetText((sal_uInt16)0).GetChar(0) == '=' ||
2184            pEngine->GetText((sal_uInt16)0).GetChar(0) == '+' ||
2185            pEngine->GetText((sal_uInt16)0).GetChar(0) == '-' ) &&
2186          !bProtected )
2187     {
2188         if (!bFormulaMode)
2189         {
2190             bFormulaMode = sal_True;
2191             pRefViewSh = pActiveViewSh;
2192             pSfxApp->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2193             SC_MOD()->SetRefInputHdl(this);
2194             if (pInputWin)
2195                 pInputWin->SetFormulaMode(sal_True);
2196 
2197             if ( bAutoComplete )
2198                 GetFormulaData();
2199 
2200             UpdateParenthesis();
2201             UpdateAutoCorrFlag();
2202         }
2203     }
2204     else        // ausschalten
2205     {
2206         if (bFormulaMode)
2207         {
2208             ShowRefFrame();
2209             bFormulaMode = sal_False;
2210             pRefViewSh = NULL;
2211             pSfxApp->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2212             SC_MOD()->SetRefInputHdl(NULL);
2213             if (pInputWin)
2214                 pInputWin->SetFormulaMode(sal_False);
2215             UpdateAutoCorrFlag();
2216         }
2217     }
2218 }
2219 
2220 void ScInputHandler::ShowRefFrame()
2221 {
2222     // #123169# Modifying pActiveViewSh here would interfere with the bInEnterHandler / bRepeat
2223     // checks in NotifyChange, and lead to keeping the wrong value in pActiveViewSh.
2224     // A local variable is used instead.
2225     ScTabViewShell* pVisibleSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
2226     if ( pRefViewSh && pRefViewSh != pVisibleSh )
2227     {
2228         sal_Bool bFound = sal_False;
2229         SfxViewFrame* pRefFrame = pRefViewSh->GetViewFrame();
2230         SfxViewFrame* pOneFrame = SfxViewFrame::GetFirst();
2231         while ( pOneFrame && !bFound )
2232         {
2233             if ( pOneFrame == pRefFrame )
2234                 bFound = sal_True;
2235             pOneFrame = SfxViewFrame::GetNext( *pOneFrame );
2236         }
2237 
2238         if (bFound)
2239         {
2240             //  Hier wird sich darauf verlassen, dass Activate synchron funktioniert
2241             //  (dabei wird pActiveViewSh umgesetzt)
2242 
2243             pRefViewSh->SetActive();    // Appear und SetViewFrame
2244 
2245             //  pLastState wird im NotifyChange aus dem Activate richtig gesetzt
2246         }
2247         else
2248         {
2249             DBG_ERROR("ViewFrame fuer Referenzeingabe ist nicht mehr da");
2250         }
2251     }
2252 }
2253 
2254 void ScInputHandler::RemoveSelection()
2255 {
2256     EditView* pActiveView = pTopView ? pTopView : pTableView;
2257     if (!pActiveView)
2258         return;
2259 
2260     ESelection aSel = pActiveView->GetSelection();
2261     aSel.nStartPara = aSel.nEndPara;
2262     aSel.nStartPos  = aSel.nEndPos;
2263     if (pTableView)
2264         pTableView->SetSelection( aSel );
2265     if (pTopView)
2266         pTopView->SetSelection( aSel );
2267 }
2268 
2269 void ScInputHandler::InvalidateAttribs()
2270 {
2271     SfxViewFrame* pViewFrm = SfxViewFrame::Current();
2272     if (pViewFrm)
2273     {
2274         SfxBindings& rBindings = pViewFrm->GetBindings();
2275 
2276         rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2277         rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2278         rBindings.Invalidate( SID_ATTR_CHAR_COLOR );
2279 
2280         rBindings.Invalidate( SID_ATTR_CHAR_WEIGHT );
2281         rBindings.Invalidate( SID_ATTR_CHAR_POSTURE );
2282         rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE );
2283         rBindings.Invalidate( SID_ULINE_VAL_NONE );
2284         rBindings.Invalidate( SID_ULINE_VAL_SINGLE );
2285         rBindings.Invalidate( SID_ULINE_VAL_DOUBLE );
2286         rBindings.Invalidate( SID_ULINE_VAL_DOTTED );
2287 
2288         rBindings.Invalidate( SID_HYPERLINK_GETLINK );
2289     }
2290 }
2291 
2292 
2293 //
2294 //      --------------- public Methoden --------------------------------------------
2295 //
2296 
2297 void ScInputHandler::SetMode( ScInputMode eNewMode )
2298 {
2299     if ( eMode == eNewMode )
2300         return;
2301 
2302     ImplCreateEditEngine();
2303 
2304     if (bProtected)
2305     {
2306         eMode = SC_INPUT_NONE;
2307         StopInputWinEngine( sal_True );
2308         if (pActiveViewSh)
2309             pActiveViewSh->GetActiveWin()->GrabFocus();
2310         return;
2311     }
2312 
2313     bInOwnChange = sal_True;                // disable ModifyHdl (reset below)
2314 
2315     ScInputMode eOldMode = eMode;
2316     eMode = eNewMode;
2317     if (eOldMode == SC_INPUT_TOP && eNewMode != eOldMode)
2318         StopInputWinEngine( sal_False );
2319 
2320     if (eMode==SC_INPUT_TOP || eMode==SC_INPUT_TABLE)
2321     {
2322         if (eOldMode == SC_INPUT_NONE)      // not when switching between modes
2323         {
2324             if (StartTable(0, sal_False))       // 0 = look at existing document content for text or number
2325             {
2326                 if (pActiveViewSh)
2327                     pActiveViewSh->GetViewData()->GetDocShell()->PostEditView( pEngine, aCursorPos );
2328             }
2329         }
2330 
2331         sal_uInt16 nPara    = pEngine->GetParagraphCount()-1;
2332         xub_StrLen nLen = pEngine->GetText(nPara).Len();
2333         sal_uInt16 nCount   = pEngine->GetViewCount();
2334 
2335         for (sal_uInt16 i=0; i<nCount; i++)
2336         {
2337             if ( eMode == SC_INPUT_TABLE && eOldMode == SC_INPUT_TOP )
2338             {
2339                 //  Selektion bleibt
2340             }
2341             else
2342             {
2343                 pEngine->GetView(i)->
2344                     SetSelection( ESelection( nPara, nLen, nPara, nLen ) );
2345             }
2346             pEngine->GetView(i)->ShowCursor(sal_False);
2347         }
2348     }
2349 
2350     UpdateActiveView();
2351     if (eMode==SC_INPUT_TABLE || eMode==SC_INPUT_TYPE)
2352     {
2353         if (pTableView)
2354             pTableView->SetEditEngineUpdateMode(sal_True);
2355     }
2356     else
2357     {
2358         if (pTopView)
2359             pTopView->SetEditEngineUpdateMode(sal_True);
2360     }
2361 
2362     if (eNewMode != eOldMode)
2363         UpdateFormulaMode();
2364 
2365     bInOwnChange = sal_False;
2366 }
2367 
2368 //----------------------------------------------------------------------------------------
2369 
2370 //  lcl_IsNumber - sal_True, wenn nur Ziffern (dann keine Autokorrektur)
2371 
2372 sal_Bool lcl_IsNumber(const String& rString)
2373 {
2374     xub_StrLen nLen = rString.Len();
2375     for (xub_StrLen i=0; i<nLen; i++)
2376     {
2377         sal_Unicode c = rString.GetChar(i);
2378         if ( c < '0' || c > '9' )
2379             return sal_False;
2380     }
2381     return sal_True;
2382 }
2383 
2384 void lcl_SelectionToEnd( EditView* pView )
2385 {
2386     if ( pView )
2387     {
2388         EditEngine* pEngine = pView->GetEditEngine();
2389         sal_uInt16 nParCnt = pEngine->GetParagraphCount();
2390         if ( nParCnt == 0 )
2391             nParCnt = 1;
2392         ESelection aSel( nParCnt-1, pEngine->GetTextLen(nParCnt-1) );   // empty selection, cursor at the end
2393         pView->SetSelection( aSel );
2394     }
2395 }
2396 
2397 void ScInputHandler::EnterHandler( sal_uInt8 nBlockMode )
2398 {
2399     //  #62806# Bei Makro-Aufrufen fuer Gueltigkeit kann Tod und Teufel passieren,
2400     //  darum dafuer sorgen, dass EnterHandler nicht verschachtelt gerufen wird:
2401 
2402     if (bInEnterHandler) return;
2403     bInEnterHandler = sal_True;
2404     bInOwnChange = sal_True;                // disable ModifyHdl (reset below)
2405 
2406     ImplCreateEditEngine();
2407 
2408     sal_Bool bMatrix = ( nBlockMode == SC_ENTER_MATRIX );
2409 
2410     SfxApplication* pSfxApp     = SFX_APP();
2411     EditTextObject* pObject     = NULL;
2412     ScPatternAttr*  pCellAttrs  = NULL;
2413     sal_Bool            bAttrib     = sal_False;    // Formatierung vorhanden ?
2414     sal_Bool            bForget     = sal_False;    // wegen Gueltigkeit streichen ?
2415 
2416     String aString = GetEditText(pEngine);
2417     EditView* pActiveView = pTopView ? pTopView : pTableView;
2418     if (bModified && pActiveView && aString.Len() && !lcl_IsNumber(aString))
2419     {
2420         if ( pColumnData && nAutoPos != SCPOS_INVALID )
2421         {
2422             // #i47125# If AutoInput appended something, do the final AutoCorrect
2423             // with the cursor at the end of the input.
2424 
2425             lcl_SelectionToEnd(pTopView);
2426             lcl_SelectionToEnd(pTableView);
2427         }
2428 
2429         if (pTopView)
2430             pTopView->CompleteAutoCorrect();    // #59759# CompleteAutoCorrect fuer beide Views
2431         if (pTableView)
2432             pTableView->CompleteAutoCorrect();
2433         aString = GetEditText(pEngine);
2434     }
2435     lcl_RemoveTabs(aString);
2436 
2437     //  Test, ob zulaessig (immer mit einfachem String)
2438 
2439     if ( bModified && nValidation && pActiveViewSh )
2440     {
2441         ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocument();
2442         const ScValidationData* pData = pDoc->GetValidationEntry( nValidation );
2443         if (pData && pData->HasErrMsg())
2444         {
2445             // #i67990# don't use pLastPattern in EnterHandler
2446             const ScPatternAttr* pPattern = pDoc->GetPattern( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab() );
2447             sal_Bool bOk = pData->IsDataValid( aString, *pPattern, aCursorPos );
2448 
2449             if (!bOk)
2450             {
2451                 if ( pActiveViewSh )                // falls aus MouseButtonDown gekommen
2452                     pActiveViewSh->StopMarking();   // (die InfoBox verschluckt das MouseButtonUp)
2453 
2454                     //! es gibt noch Probleme, wenn die Eingabe durch Aktivieren einer
2455                     //! anderen View ausgeloest wurde
2456 
2457                 Window* pParent = Application::GetDefDialogParent();
2458                 if ( pData->DoError( pParent, aString, aCursorPos ) )
2459                     bForget = sal_True;                 // Eingabe nicht uebernehmen
2460             }
2461         }
2462     }
2463 
2464     // check for input into DataPilot table
2465 
2466     if ( bModified && pActiveViewSh && !bForget )
2467     {
2468         ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocument();
2469         ScDPObject* pDPObj = pDoc->GetDPAtCursor( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab() );
2470         if ( pDPObj )
2471         {
2472             // any input within the DataPilot table is either a valid renaming
2473             // or an invalid action - normal cell input is always aborted
2474 
2475             pActiveViewSh->DataPilotInput( aCursorPos, aString );
2476             bForget = sal_True;
2477         }
2478     }
2479 
2480     pEngine->CompleteOnlineSpelling();
2481     sal_Bool bSpellErrors = !bFormulaMode && pEngine->HasOnlineSpellErrors();
2482     if ( bSpellErrors )
2483     {
2484         //  #i3820# If the spell checker flags numerical input as error,
2485         //  it still has to be treated as number, not EditEngine object.
2486 
2487         if ( pActiveViewSh )
2488         {
2489             ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocument();
2490             // #i67990# don't use pLastPattern in EnterHandler
2491             const ScPatternAttr* pPattern = pDoc->GetPattern( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab() );
2492             SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2493             // without conditional format, as in ScColumn::SetString
2494             sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
2495             double nVal;
2496             if ( pFormatter->IsNumberFormat( aString, nFormat, nVal ) )
2497             {
2498                 bSpellErrors = sal_False;       // ignore the spelling errors
2499             }
2500         }
2501     }
2502 
2503     //  After RemoveAdjust, the EditView must not be repainted (has wrong font size etc).
2504     //  SetUpdateMode must come after CompleteOnlineSpelling.
2505     //  The view is hidden in any case below (Broadcast).
2506     pEngine->SetUpdateMode( sal_False );
2507 
2508     if ( bModified && !bForget )            // was wird eingeben (Text/Objekt) ?
2509     {
2510         sal_uInt16 nParCnt = pEngine->GetParagraphCount();
2511         if ( nParCnt == 0 )
2512             nParCnt = 1;
2513         ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) );
2514         SfxItemSet aOldAttribs = pEngine->GetAttribs( aSel );
2515         const SfxPoolItem* pItem = NULL;
2516 
2517         //  find common (cell) attributes before RemoveAdjust
2518 
2519         if ( pActiveViewSh )
2520         {
2521             SfxItemSet* pCommonAttrs = NULL;
2522             for (sal_uInt16 nId = EE_CHAR_START; nId <= EE_CHAR_END; nId++)
2523             {
2524                 SfxItemState eState = aOldAttribs.GetItemState( nId, sal_False, &pItem );
2525                 if ( eState == SFX_ITEM_SET &&
2526                         nId != EE_CHAR_ESCAPEMENT && nId != EE_CHAR_PAIRKERNING &&
2527                         nId != EE_CHAR_KERNING && nId != EE_CHAR_XMLATTRIBS &&
2528                             *pItem != pEditDefaults->Get(nId) )
2529                 {
2530                     if ( !pCommonAttrs )
2531                         pCommonAttrs = new SfxItemSet( pEngine->GetEmptyItemSet() );
2532                     pCommonAttrs->Put( *pItem );
2533                 }
2534             }
2535 
2536             if ( pCommonAttrs )
2537             {
2538                 ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocument();
2539                 pCellAttrs = new ScPatternAttr( pDoc->GetPool() );
2540                 pCellAttrs->GetFromEditItemSet( pCommonAttrs );
2541                 delete pCommonAttrs;
2542             }
2543         }
2544 
2545         //  clear ParaAttribs (including adjustment)
2546 
2547         RemoveAdjust();
2548 
2549         //  check if EditObject is needed
2550 
2551         if ( bSpellErrors || nParCnt > 1 )
2552             bAttrib = sal_True;
2553         else
2554         {
2555             for (sal_uInt16 nId = EE_CHAR_START; nId <= EE_CHAR_END && !bAttrib; nId++)
2556             {
2557                 SfxItemState eState = aOldAttribs.GetItemState( nId, sal_False, &pItem );
2558                 if (eState == SFX_ITEM_DONTCARE)
2559                     bAttrib = sal_True;
2560                 else if (eState == SFX_ITEM_SET)
2561                 {
2562                     //  keep same items in EditEngine as in ScEditAttrTester
2563                     if ( nId == EE_CHAR_ESCAPEMENT || nId == EE_CHAR_PAIRKERNING ||
2564                          nId == EE_CHAR_KERNING || nId == EE_CHAR_XMLATTRIBS )
2565                     {
2566                         if ( *pItem != pEditDefaults->Get(nId) )
2567                             bAttrib = sal_True;
2568                     }
2569                 }
2570             }
2571 
2572             //  Feldbefehle enthalten?
2573 
2574             SfxItemState eFieldState = aOldAttribs.GetItemState( EE_FEATURE_FIELD, sal_False );
2575             if ( eFieldState == SFX_ITEM_DONTCARE || eFieldState == SFX_ITEM_SET )
2576                 bAttrib = sal_True;
2577 
2578             //  not converted characters?
2579 
2580             SfxItemState eConvState = aOldAttribs.GetItemState( EE_FEATURE_NOTCONV, sal_False );
2581             if ( eConvState == SFX_ITEM_DONTCARE || eConvState == SFX_ITEM_SET )
2582                 bAttrib = sal_True;
2583 
2584             //  Formeln immer als Formeln erkennen (#38309#)
2585             //  (der Test vorher ist trotzdem noetig wegen Zell-Attributen)
2586         }
2587 
2588         if (bMatrix)
2589             bAttrib = sal_False;
2590 
2591         if (bAttrib)
2592         {
2593             sal_uLong nCtrl = pEngine->GetControlWord();
2594             sal_uLong nWantBig = bSpellErrors ? EE_CNTRL_ALLOWBIGOBJS : 0;
2595             if ( ( nCtrl & EE_CNTRL_ALLOWBIGOBJS ) != nWantBig )
2596                 pEngine->SetControlWord( (nCtrl & ~EE_CNTRL_ALLOWBIGOBJS) | nWantBig );
2597             pObject = pEngine->CreateTextObject();
2598         }
2599         else if (bAutoComplete)         // Gross-/Kleinschreibung anpassen
2600         {
2601             if (pColumnData)
2602                 pColumnData->GetExactMatch( aString );
2603 
2604             //! effizienter in der Liste suchen (ScUserList, nur einmal ToUpper)
2605 
2606             sal_uInt16 nIndex;
2607             ScUserListData* pData = ScGlobal::GetUserList()->GetData(aString);
2608             if ( pData && pData->GetSubIndex( aString, nIndex ) )
2609                 aString = pData->GetSubStr( nIndex );
2610         }
2611     }
2612 
2613     //  don't rely on ShowRefFrame switching the active view synchronously
2614     //  execute the function directly on the correct view's bindings instead
2615     //  pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2616     ScTabViewShell* pExecuteSh = pRefViewSh ? pRefViewSh : pActiveViewSh;
2617 
2618     if (bFormulaMode)
2619     {
2620         ShowRefFrame();
2621 
2622         if (pExecuteSh)
2623         {
2624             pExecuteSh->SetTabNo(aCursorPos.Tab());
2625             pExecuteSh->ActiveGrabFocus();
2626         }
2627 
2628         bFormulaMode = sal_False;
2629         pSfxApp->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2630         SC_MOD()->SetRefInputHdl(NULL);
2631         if (pInputWin)
2632             pInputWin->SetFormulaMode(sal_False);
2633         UpdateAutoCorrFlag();
2634     }
2635     pRefViewSh = NULL;          // auch ohne FormulaMode wegen Funktions-AP
2636     DeleteRangeFinder();
2637     ResetAutoPar();
2638 
2639     sal_Bool bOldMod = bModified;
2640 
2641     bModified = sal_False;
2642     bSelIsRef = sal_False;
2643     eMode     = SC_INPUT_NONE;
2644     StopInputWinEngine( sal_True );
2645 
2646     // #123344# Text input (through number formats) or ApplySelectionPattern modify
2647     // the cell's attributes, so pLastPattern is no longer valid
2648     pLastPattern = NULL;
2649 
2650     if (bOldMod && !bProtected && !bForget)
2651     {
2652         //  keine typographische Anfuehrungszeichen in Formeln
2653 
2654         if ( aString.GetChar(0) == '=' )
2655         {
2656             SvxAutoCorrect* pAuto = SvxAutoCorrCfg::Get()->GetAutoCorrect();
2657             if ( pAuto )
2658             {
2659                 sal_Unicode cReplace = pAuto->GetStartDoubleQuote();
2660                 if( !cReplace )
2661                     cReplace = ScGlobal::pLocaleData->getDoubleQuotationMarkStart().GetChar(0);
2662                 if ( cReplace != '"' )
2663                     aString.SearchAndReplaceAll( cReplace, '"' );
2664 
2665                 cReplace = pAuto->GetEndDoubleQuote();
2666                 if( !cReplace )
2667                     cReplace = ScGlobal::pLocaleData->getDoubleQuotationMarkEnd().GetChar(0);
2668                 if ( cReplace != '"' )
2669                     aString.SearchAndReplaceAll( cReplace, '"' );
2670 
2671                 cReplace = pAuto->GetStartSingleQuote();
2672                 if( !cReplace )
2673                     cReplace = ScGlobal::pLocaleData->getQuotationMarkStart().GetChar(0);
2674                 if ( cReplace != '\'' )
2675                     aString.SearchAndReplaceAll( cReplace, '\'' );
2676 
2677                 cReplace = pAuto->GetEndSingleQuote();
2678                 if( !cReplace )
2679                     cReplace = ScGlobal::pLocaleData->getQuotationMarkEnd().GetChar(0);
2680                 if ( cReplace != '\'' )
2681                     aString.SearchAndReplaceAll( cReplace, '\'' );
2682             }
2683         }
2684 
2685         pSfxApp->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW_NOPAINT ) );
2686 
2687         if ( pExecuteSh )
2688         {
2689             SfxBindings& rBindings = pExecuteSh->GetViewFrame()->GetBindings();
2690 
2691             sal_uInt16 nId = FID_INPUTLINE_ENTER;
2692             if ( nBlockMode == SC_ENTER_BLOCK )
2693                 nId = FID_INPUTLINE_BLOCK;
2694             else if ( nBlockMode == SC_ENTER_MATRIX )
2695                 nId = FID_INPUTLINE_MATRIX;
2696 
2697             ScInputStatusItem aItem( FID_INPUTLINE_STATUS,
2698                                      aCursorPos, aCursorPos, aCursorPos,
2699                                      aString, pObject );
2700             const SfxPoolItem* aArgs[2];
2701             aArgs[0] = &aItem;
2702             aArgs[1] = NULL;
2703             rBindings.Execute( nId, aArgs );
2704         }
2705 
2706         delete pLastState;      // pLastState enthaelt noch den alten Text
2707         pLastState = NULL;
2708     }
2709     else
2710         pSfxApp->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) );
2711 
2712     if ( bOldMod && pExecuteSh && pCellAttrs && !bForget )
2713     {
2714         //  mit Eingabe zusammenfassen ?
2715         pExecuteSh->ApplySelectionPattern( *pCellAttrs, sal_True, sal_True );
2716         pExecuteSh->AdjustBlockHeight();
2717     }
2718 
2719     delete pCellAttrs;
2720     delete pObject;
2721 
2722     HideTip();
2723     HideTipBelow();
2724 
2725     nFormSelStart = nFormSelEnd = 0;
2726     aFormText.Erase();
2727 
2728     bInOwnChange = sal_False;
2729     bInEnterHandler = sal_False;
2730 }
2731 
2732 void ScInputHandler::CancelHandler()
2733 {
2734     bInOwnChange = sal_True;                // disable ModifyHdl (reset below)
2735 
2736     ImplCreateEditEngine();
2737 
2738     bModified = sal_False;
2739 
2740     //  don't rely on ShowRefFrame switching the active view synchronously
2741     //  execute the function directly on the correct view's bindings instead
2742     //  pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2743     ScTabViewShell* pExecuteSh = pRefViewSh ? pRefViewSh : pActiveViewSh;
2744 
2745     if (bFormulaMode)
2746     {
2747         ShowRefFrame();
2748         if (pExecuteSh)
2749         {
2750             pExecuteSh->SetTabNo(aCursorPos.Tab());
2751             pExecuteSh->ActiveGrabFocus();
2752         }
2753         bFormulaMode = sal_False;
2754         SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2755         SC_MOD()->SetRefInputHdl(NULL);
2756         if (pInputWin)
2757             pInputWin->SetFormulaMode(sal_False);
2758         UpdateAutoCorrFlag();
2759     }
2760     pRefViewSh = NULL;          // auch ohne FormulaMode wegen Funktions-AP
2761     DeleteRangeFinder();
2762     ResetAutoPar();
2763 
2764     eMode = SC_INPUT_NONE;
2765     StopInputWinEngine( sal_True );
2766     if (pExecuteSh)
2767         pExecuteSh->StopEditShell();
2768 
2769     aCursorPos.Set(MAXCOL+1,0,0);       // Flag, dass ungueltig
2770     pEngine->SetText(String());
2771 
2772     if ( !pLastState && pExecuteSh )
2773         pExecuteSh->UpdateInputHandler( sal_True );     // Status neu holen
2774     else
2775         NotifyChange( pLastState, sal_True );
2776 
2777     nFormSelStart = nFormSelEnd = 0;
2778     aFormText.Erase();
2779 
2780     bInOwnChange = sal_False;
2781 }
2782 
2783 sal_Bool ScInputHandler::IsModalMode( SfxObjectShell* pDocSh )
2784 {
2785     //  Referenzen auf unbenanntes Dokument gehen nicht
2786 
2787     return bFormulaMode && pRefViewSh
2788             && pRefViewSh->GetViewData()->GetDocument()->GetDocumentShell() != pDocSh
2789             && !pDocSh->HasName();
2790 }
2791 
2792 void ScInputHandler::AddRefEntry()
2793 {
2794     const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
2795     UpdateActiveView();
2796     if (!pTableView && !pTopView)
2797         return;                             // z.B. FillMode
2798 
2799     DataChanging();                         // kann nicht neu sein
2800 
2801     RemoveSelection();
2802     if (pTableView)
2803         pTableView->InsertText( cSep, sal_False );
2804     if (pTopView)
2805         pTopView->InsertText( cSep, sal_False );
2806 
2807     DataChanged();
2808 }
2809 
2810 void ScInputHandler::SetReference( const ScRange& rRef, ScDocument* pDoc )
2811 {
2812     HideTip();
2813 
2814     sal_Bool bOtherDoc = ( pRefViewSh &&
2815                         pRefViewSh->GetViewData()->GetDocument() != pDoc );
2816     if (bOtherDoc)
2817         if (!pDoc->GetDocumentShell()->HasName())
2818         {
2819             //  Referenzen auf unbenanntes Dokument gehen nicht
2820             //  (SetReference sollte dann auch nicht gerufen werden)
2821 
2822             return;
2823         }
2824 
2825     UpdateActiveView();
2826     if (!pTableView && !pTopView)
2827         return;                             // z.B. FillMode
2828 
2829     //  nie das "=" ueberschreiben!
2830     EditView* pActiveView = pTopView ? pTopView : pTableView;
2831     ESelection aSel = pActiveView->GetSelection();
2832     aSel.Adjust();
2833     if ( aSel.nStartPara == 0 && aSel.nStartPos == 0 )
2834         return;
2835 
2836     DataChanging();                         // kann nicht neu sein
2837 
2838             //  Selektion umdrehen, falls rueckwaerts (noetig ???)
2839 
2840     if (pTableView)
2841     {
2842         ESelection aTabSel = pTableView->GetSelection();
2843         if (aTabSel.nStartPos > aTabSel.nEndPos && aTabSel.nStartPara == aTabSel.nEndPara)
2844         {
2845             aTabSel.Adjust();
2846             pTableView->SetSelection(aTabSel);
2847         }
2848     }
2849     if (pTopView)
2850     {
2851         ESelection aTopSel = pTopView->GetSelection();
2852         if (aTopSel.nStartPos > aTopSel.nEndPos && aTopSel.nStartPara == aTopSel.nEndPara)
2853         {
2854             aTopSel.Adjust();
2855             pTopView->SetSelection(aTopSel);
2856         }
2857     }
2858 
2859     //  String aus Referenz erzeugen
2860 
2861     String aRefStr;
2862     const ScAddress::Details aAddrDetails( pDoc, aCursorPos );
2863     if (bOtherDoc)
2864     {
2865         //  Referenz auf anderes Dokument
2866 
2867         DBG_ASSERT(rRef.aStart.Tab()==rRef.aEnd.Tab(), "nStartTab!=nEndTab");
2868 
2869         String aTmp;
2870         rRef.Format( aTmp, SCA_VALID|SCA_TAB_3D, pDoc, aAddrDetails );      // immer 3d
2871 
2872         SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
2873         // #i75893# convert escaped URL of the document to something user friendly
2874 //       String aFileName = pObjSh->GetMedium()->GetName();
2875         String aFileName = pObjSh->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
2876 
2877         aRefStr = '\'';
2878         aRefStr += aFileName;
2879         aRefStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "'#" ));
2880         aRefStr += aTmp;
2881     }
2882     else
2883     {
2884         if ( ( rRef.aStart.Tab() != aCursorPos.Tab() ||
2885                 rRef.aStart.Tab() != rRef.aEnd.Tab() ) && pDoc )
2886             rRef.Format( aRefStr, SCA_VALID|SCA_TAB_3D, pDoc, aAddrDetails );
2887         else
2888             rRef.Format( aRefStr, SCA_VALID, pDoc, aAddrDetails );
2889     }
2890 
2891     if (pTableView || pTopView)
2892     {
2893         if (pTableView)
2894             pTableView->InsertText( aRefStr, sal_True );
2895         if (pTopView)
2896             pTopView->InsertText( aRefStr, sal_True );
2897 
2898         DataChanged();
2899     }
2900 
2901     bSelIsRef = sal_True;
2902 }
2903 
2904 void ScInputHandler::InsertFunction( const String& rFuncName, sal_Bool bAddPar )
2905 {
2906     if ( eMode == SC_INPUT_NONE )
2907     {
2908         DBG_ERROR("InsertFunction, nicht im Eingabemodus");
2909         return;
2910     }
2911 
2912     UpdateActiveView();
2913     if (!pTableView && !pTopView)
2914         return;                             // z.B. FillMode
2915 
2916     DataChanging();                         // kann nicht neu sein
2917 
2918     String aText = rFuncName;
2919     if (bAddPar)
2920         aText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
2921 
2922     if (pTableView)
2923     {
2924         pTableView->InsertText( aText, sal_False );
2925         if (bAddPar)
2926         {
2927             ESelection aSel = pTableView->GetSelection();
2928             --aSel.nStartPos;
2929             --aSel.nEndPos;
2930             pTableView->SetSelection(aSel);
2931         }
2932     }
2933     if (pTopView)
2934     {
2935         pTopView->InsertText( aText, sal_False );
2936         if (bAddPar)
2937         {
2938             ESelection aSel = pTopView->GetSelection();
2939             --aSel.nStartPos;
2940             --aSel.nEndPos;
2941             pTopView->SetSelection(aSel);
2942         }
2943     }
2944 
2945     DataChanged();
2946 
2947     if (bAddPar)
2948         AutoParAdded();
2949 }
2950 
2951 void ScInputHandler::ClearText()
2952 {
2953     if ( eMode == SC_INPUT_NONE )
2954     {
2955         DBG_ERROR("ClearText, nicht im Eingabemodus");
2956         return;
2957     }
2958 
2959     UpdateActiveView();
2960     if (!pTableView && !pTopView)
2961         return;                             // z.B. FillMode
2962 
2963     DataChanging();                         // darf nicht neu sein
2964 
2965     String aEmpty;
2966     if (pTableView)
2967     {
2968         pTableView->GetEditEngine()->SetText( aEmpty );
2969         pTableView->SetSelection( ESelection(0,0, 0,0) );
2970     }
2971     if (pTopView)
2972     {
2973         pTopView->GetEditEngine()->SetText( aEmpty );
2974         pTopView->SetSelection( ESelection(0,0, 0,0) );
2975     }
2976 
2977     DataChanged();
2978 }
2979 
2980 sal_Bool ScInputHandler::KeyInput( const KeyEvent& rKEvt, sal_Bool bStartEdit /* = sal_False */ )
2981 {
2982     if (!bOptLoaded)
2983     {
2984         bAutoComplete = SC_MOD()->GetAppOptions().GetAutoComplete();
2985         bOptLoaded = sal_True;
2986     }
2987 
2988     KeyCode aCode = rKEvt.GetKeyCode();
2989     sal_uInt16 nModi  = aCode.GetModifier();
2990     sal_Bool bShift   = aCode.IsShift();
2991     sal_Bool bControl = aCode.IsMod1();
2992     sal_Bool bAlt     = aCode.IsMod2();
2993     sal_uInt16 nCode  = aCode.GetCode();
2994     sal_Unicode nChar = rKEvt.GetCharCode();
2995 
2996     //  Alt-Return is accepted, everything else with ALT, or CTRL-TAB are not:
2997     if (( bAlt && !bControl && nCode != KEY_RETURN ) ||
2998             ( bControl && aCode.GetCode() == KEY_TAB ))
2999         return sal_False;
3000 
3001     sal_Bool bInputLine = ( eMode==SC_INPUT_TOP );
3002 
3003     sal_Bool bUsed = sal_False;
3004     sal_Bool bSkip = sal_False;
3005     sal_Bool bDoEnter = sal_False;
3006 
3007     switch ( nCode )
3008     {
3009         case KEY_RETURN:
3010             if (bControl && !bShift && !bInputLine)
3011                 bDoEnter = sal_True;
3012             else if ( nModi == 0 && nTipVisible && pFormulaData && nAutoPos != SCPOS_INVALID )
3013             {
3014                 PasteFunctionData();
3015                 bUsed = sal_True;
3016             }
3017             else if ( nModi == 0 && nTipVisible && aManualTip.Len() )
3018             {
3019                 PasteManualTip();
3020                 bUsed = sal_True;
3021             }
3022             else
3023             {
3024                 sal_uInt8 nMode = SC_ENTER_NORMAL;
3025                 if ( bShift && bControl )
3026                     nMode = SC_ENTER_MATRIX;
3027                 else if ( bAlt )
3028                     nMode = SC_ENTER_BLOCK;
3029                 EnterHandler( nMode );
3030 
3031                 if (pActiveViewSh)
3032                     pActiveViewSh->MoveCursorEnter( bShift && !bControl );
3033 
3034                 bUsed = sal_True;
3035             }
3036             break;
3037         case KEY_TAB:
3038             if (!bControl && !bAlt)
3039             {
3040                 if ( pFormulaData && nTipVisible && nAutoPos != SCPOS_INVALID )
3041                 {
3042                     //  blaettern
3043 
3044                     NextFormulaEntry( bShift );
3045                 }
3046                 else if ( pColumnData && bUseTab && nAutoPos != SCPOS_INVALID )
3047                 {
3048                     //  in den Eintraegen der AutoEingabe blaettern
3049 
3050                     NextAutoEntry( bShift );
3051                 }
3052                 else
3053                 {
3054                     EnterHandler();
3055 
3056                     //  TabKeyInput gibt auf manchen Rechnern unter W95 Stackueberlaeufe,
3057                     //  darum direkter Aufruf:
3058                     if (pActiveViewSh)
3059                         pActiveViewSh->FindNextUnprot( bShift );
3060                 }
3061                 bUsed = sal_True;
3062             }
3063             break;
3064         case KEY_ESCAPE:
3065             if ( nTipVisible )
3066             {
3067                 HideTip();
3068                 bUsed = sal_True;
3069             }
3070             else if( nTipVisibleSec )
3071             {
3072                 HideTipBelow();
3073                 bUsed = sal_True;
3074             }
3075             else if (eMode != SC_INPUT_NONE)
3076             {
3077                 CancelHandler();
3078                 bUsed = sal_True;
3079             }
3080             else
3081                 bSkip = sal_True;
3082             break;
3083         case KEY_F2:
3084             if ( !bShift && !bControl && !bAlt && eMode == SC_INPUT_TABLE )
3085             {
3086                 eMode = SC_INPUT_TYPE;
3087                 bUsed = sal_True;
3088             }
3089             break;
3090     }
3091 
3092     //  Cursortasten nur ausfuehren, wenn schon im Edit-Modus
3093     //  z.B. wegen Shift-Ctrl-PageDn (ist nicht als Accelerator definiert)
3094 
3095     sal_Bool bCursorKey = EditEngine::DoesKeyMoveCursor(rKEvt);
3096     sal_Bool bInsKey = ( nCode == KEY_INSERT && !nModi );   // Insert wie Cursortasten behandeln
3097     if ( !bUsed && !bSkip && ( bDoEnter || EditEngine::DoesKeyChangeText(rKEvt) ||
3098                     ( eMode != SC_INPUT_NONE && ( bCursorKey || bInsKey ) ) ) )
3099     {
3100         HideTip();
3101         HideTipBelow();
3102 
3103         if (bSelIsRef)
3104         {
3105             RemoveSelection();
3106             bSelIsRef = sal_False;
3107         }
3108 
3109         UpdateActiveView();
3110         sal_Bool bNewView = DataChanging( nChar );
3111 
3112         if (bProtected)                             // Zelle geschuetzt?
3113             bUsed = sal_True;                           // Key-Event nicht weiterleiten
3114         else                                        // Aenderungen erlaubt
3115         {
3116             if (bNewView )                          // neu anlegen
3117             {
3118                 if (pActiveViewSh)
3119                     pActiveViewSh->GetViewData()->GetDocShell()->PostEditView( pEngine, aCursorPos );
3120                 UpdateActiveView();
3121                 if (eMode==SC_INPUT_NONE)
3122                     if (pTableView || pTopView)
3123                     {
3124                         String aStrLoP;
3125 
3126                         if ( bStartEdit && bCellHasPercentFormat && ((nChar >= '0' && nChar <= '9') || nChar == '-') )
3127                             aStrLoP = '%';
3128 
3129                         if (pTableView)
3130                         {
3131                             pTableView->GetEditEngine()->SetText( aStrLoP );
3132                             if ( aStrLoP.Len() )
3133                                 pTableView->SetSelection( ESelection(0,0, 0,0) );   // before the '%'
3134 
3135                             // don't call SetSelection if the string is empty anyway,
3136                             // to avoid breaking the bInitial handling in ScViewData::EditGrowY
3137                         }
3138                         if (pTopView)
3139                         {
3140                             pTopView->GetEditEngine()->SetText( aStrLoP );
3141                             if ( aStrLoP.Len() )
3142                                 pTopView->SetSelection( ESelection(0,0, 0,0) );     // before the '%'
3143                         }
3144                     }
3145                 SyncViews();
3146             }
3147 
3148             if (pTableView || pTopView)
3149             {
3150 //              pActiveView->SetEditEngineUpdateMode(sal_True);         //! gibt Muell !!!!
3151 
3152                 if (bDoEnter)
3153                 {
3154                     if (pTableView)
3155                         if( pTableView->PostKeyEvent( KeyEvent( CHAR_CR, KeyCode(KEY_RETURN) ) ) )
3156                             bUsed = sal_True;
3157                     if (pTopView)
3158                         if( pTopView->PostKeyEvent( KeyEvent( CHAR_CR, KeyCode(KEY_RETURN) ) ) )
3159                             bUsed = sal_True;
3160                 }
3161                 else if ( nAutoPar && nChar == ')' && CursorAtClosingPar() )
3162                 {
3163                     SkipClosingPar();
3164                     bUsed = sal_True;
3165                 }
3166                 else
3167                 {
3168                     if (pTableView)
3169                         if ( pTableView->PostKeyEvent( rKEvt ) )
3170                             bUsed = sal_True;
3171                     if (pTopView)
3172                         if ( pTopView->PostKeyEvent( rKEvt ) )
3173                             bUsed = sal_True;
3174                 }
3175 
3176                 //  Auto-Eingabe:
3177 
3178                 if ( bUsed && bAutoComplete )
3179                 {
3180                     bUseTab = sal_False;
3181                     nAutoPos = SCPOS_INVALID;                       // do not search further
3182 
3183                     KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
3184                     if ( nChar && nChar != 8 && nChar != 127 &&     // no 'backspace', no 'delete'
3185                          KEYFUNC_CUT != eFunc)                      // and no 'CTRL-X'
3186                     {
3187                         if (bFormulaMode)
3188                             UseFormulaData();
3189                         else
3190                             UseColData();
3191                     }
3192                 }
3193 
3194                 //  when the selection is changed manually or an opening parenthesis
3195                 //  is typed, stop overwriting parentheses
3196                 if ( bUsed && nChar == '(' )
3197                     ResetAutoPar();
3198 
3199                 if ( KEY_INSERT == nCode )
3200                 {
3201                     SfxViewFrame* pViewFrm = SfxViewFrame::Current();
3202                     if (pViewFrm)
3203                         pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
3204                 }
3205                 if( bUsed && bFormulaMode && ( bCursorKey || bInsKey || nCode == KEY_DELETE || nCode == KEY_BACKSPACE ) )
3206                 {
3207                     ShowTipCursor();
3208                 }
3209             }
3210 
3211             // #i114511# don't count cursor keys as modification
3212             sal_Bool bSetModified = !bCursorKey;
3213             DataChanged(sal_False, bSetModified);  // also calls UpdateParenthesis()
3214             InvalidateAttribs();        //! in DataChanged ?
3215         }
3216     }
3217 
3218     if (pTopView && eMode != SC_INPUT_NONE)
3219         SyncViews();
3220 
3221     return bUsed;
3222 }
3223 
3224 sal_Bool ScInputHandler::InputCommand( const CommandEvent& rCEvt, sal_Bool bForce )
3225 {
3226     sal_Bool bUsed = sal_False;
3227 
3228     if ( rCEvt.GetCommand() == COMMAND_CURSORPOS )
3229     {
3230         //  #90346# for COMMAND_CURSORPOS, do as little as possible, because
3231         //  with remote VCL, even a ShowCursor will generate another event.
3232         if ( eMode != SC_INPUT_NONE )
3233         {
3234             UpdateActiveView();
3235             if (pTableView || pTopView)
3236             {
3237                 if (pTableView)
3238                     pTableView->Command( rCEvt );
3239                 else if (pTopView)                      // call only once
3240                     pTopView->Command( rCEvt );
3241                 bUsed = sal_True;
3242             }
3243         }
3244     }
3245     else
3246     {
3247         if ( bForce || eMode != SC_INPUT_NONE )
3248         {
3249             if (!bOptLoaded)
3250             {
3251                 bAutoComplete = SC_MOD()->GetAppOptions().GetAutoComplete();
3252                 bOptLoaded = sal_True;
3253             }
3254 
3255             HideTip();
3256             HideTipBelow();
3257 
3258             if ( bSelIsRef )
3259             {
3260                 RemoveSelection();
3261                 bSelIsRef = sal_False;
3262             }
3263 
3264             UpdateActiveView();
3265             sal_Bool bNewView = DataChanging( 0, sal_True );
3266 
3267             if (bProtected)                             // cell protected
3268                 bUsed = sal_True;                           // event is used
3269             else                                        // changes allowed
3270             {
3271                 if (bNewView)                           // create new edit view
3272                 {
3273                     if (pActiveViewSh)
3274                         pActiveViewSh->GetViewData()->GetDocShell()->PostEditView( pEngine, aCursorPos );
3275                     UpdateActiveView();
3276                     if (eMode==SC_INPUT_NONE)
3277                         if (pTableView || pTopView)
3278                         {
3279                             String aStrLoP;
3280                             if (pTableView)
3281                             {
3282                                 pTableView->GetEditEngine()->SetText( aStrLoP );
3283                                 pTableView->SetSelection( ESelection(0,0, 0,0) );
3284                             }
3285                             if (pTopView)
3286                             {
3287                                 pTopView->GetEditEngine()->SetText( aStrLoP );
3288                                 pTopView->SetSelection( ESelection(0,0, 0,0) );
3289                             }
3290                         }
3291                     SyncViews();
3292                 }
3293 
3294                 if (pTableView || pTopView)
3295                 {
3296                     if (pTableView)
3297                         pTableView->Command( rCEvt );
3298                     if (pTopView)
3299                         pTopView->Command( rCEvt );
3300 
3301                     bUsed = sal_True;
3302 
3303                     if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
3304                     {
3305                         //  AutoInput after ext text input
3306 
3307                         nAutoPos = SCPOS_INVALID;
3308                         if (bFormulaMode)
3309                             UseFormulaData();
3310                         else
3311                             UseColData();
3312                     }
3313                 }
3314 
3315                 DataChanged();              //  calls UpdateParenthesis()
3316                 InvalidateAttribs();        //! in DataChanged ?
3317             }
3318         }
3319 
3320         if (pTopView && eMode != SC_INPUT_NONE)
3321             SyncViews();
3322     }
3323 
3324     return bUsed;
3325 }
3326 
3327 void ScInputHandler::NotifyChange( const ScInputHdlState* pState,
3328                                    sal_Bool bForce, ScTabViewShell* pSourceSh,
3329                                    sal_Bool bStopEditing)
3330 {
3331     //  #62806# Wenn der Aufruf aus einem Makro-Aufruf im EnterHandler kommt,
3332     //  gleich abbrechen und nicht den Status durcheinander bringen
3333     if (bInEnterHandler)
3334         return;
3335 
3336     sal_Bool bRepeat = (pState == pLastState);
3337     if (!bRepeat && pState && pLastState)
3338         bRepeat = sal::static_int_cast<sal_Bool>(*pState == *pLastState);
3339     if (bRepeat && !bForce)
3340         return;
3341 
3342     bInOwnChange = sal_True;                // disable ModifyHdl (reset below)
3343 
3344     if ( pState && !pLastState )        // wieder enablen
3345         bForce = sal_True;
3346 
3347     sal_Bool bHadObject = pLastState && pLastState->GetEditData();
3348 
3349     //! Before EditEngine gets eventually created (so it gets the right pools)
3350     if ( pSourceSh )
3351         pActiveViewSh = pSourceSh;
3352     else
3353         pActiveViewSh = PTR_CAST(ScTabViewShell, SfxViewShell::Current());
3354 
3355     ImplCreateEditEngine();
3356 
3357     if ( pState != pLastState )
3358     {
3359         delete pLastState;
3360         pLastState = pState ? new ScInputHdlState( *pState ) : NULL;
3361     }
3362 
3363     if ( pState && pActiveViewSh )
3364     {
3365         ScModule* pScMod = SC_MOD();
3366 
3367         if ( pState )
3368         {
3369             sal_Bool bIgnore = sal_False;
3370 
3371             //  hier auch fremde Referenzeingabe beruecksichtigen (z.B. Funktions-AP),
3372             //  FormEditData falls gerade von der Hilfe auf Calc umgeschaltet wird:
3373 
3374             if ( !bFormulaMode && !pScMod->IsFormulaMode() && !pScMod->GetFormEditData() )
3375             {
3376                 if ( bModified )
3377                 {
3378                     if (pState->GetPos() != aCursorPos)
3379                     {
3380                         if (!bProtected)
3381                             EnterHandler();
3382                     }
3383                     else
3384                         bIgnore = sal_True;
3385                 }
3386 
3387                 if ( !bIgnore /* || bRepeat */ )
3388                 {
3389                     const ScAddress&        rSPos   = pState->GetStartPos();
3390                     const ScAddress&        rEPos   = pState->GetEndPos();
3391                     const EditTextObject*   pData   = pState->GetEditData();
3392                     String                  aString = pState->GetString();
3393                     sal_Bool                    bTxtMod = sal_False;
3394                     ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell();
3395                     ScDocument* pDoc = pDocSh->GetDocument();
3396 
3397                     aCursorPos  = pState->GetPos();
3398 
3399                     if ( pData /* || bRepeat */ )
3400                         bTxtMod = sal_True;
3401                     else if ( bHadObject )
3402                         bTxtMod = sal_True;
3403                     else if ( bTextValid )
3404                         bTxtMod = ( aString != aCurrentText );
3405                     else
3406                         bTxtMod = ( aString != GetEditText(pEngine) );
3407 
3408                     if ( bTxtMod || bForce )
3409                     {
3410                         if (pData)
3411                         {
3412                             pEngine->SetText( *pData );
3413                             aString = GetEditText(pEngine);
3414                             lcl_RemoveTabs(aString);
3415                             bTextValid = sal_False;
3416                             aCurrentText.Erase();
3417                         }
3418                         else
3419                         {
3420                             aCurrentText = aString;
3421                             bTextValid = sal_True;              //! erst nur als String merken
3422                         }
3423 
3424                         if ( pInputWin )
3425                             pInputWin->SetTextString(aString);
3426                     }
3427 
3428                     if ( pInputWin )                        // Bereichsanzeige
3429                     {
3430                         String aPosStr;
3431                         const ScAddress::Details aAddrDetails( pDoc, aCursorPos );
3432 
3433                         //  Ist der Bereich ein Name?
3434                         //! per Timer suchen ???
3435 
3436                         if ( pActiveViewSh )
3437                             pActiveViewSh->GetViewData()->GetDocument()->
3438                                 GetRangeAtBlock( ScRange( rSPos, rEPos ), &aPosStr );
3439 
3440                         if ( !aPosStr.Len() )           // kein Name -> formatieren
3441                         {
3442                             sal_uInt16 nFlags = 0;
3443                             if( aAddrDetails.eConv == formula::FormulaGrammar::CONV_XL_R1C1 )
3444                                 nFlags |= SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE;
3445                             if ( rSPos != rEPos )
3446                             {
3447                                 ScRange r(rSPos, rEPos);
3448                                 nFlags |= (nFlags << 4);
3449                                 r.Format( aPosStr, SCA_VALID | nFlags, pDoc, aAddrDetails );
3450                             }
3451                             else
3452                                 aCursorPos.Format( aPosStr, SCA_VALID | nFlags, pDoc, aAddrDetails );
3453                         }
3454                         //IAccessibility2 Implementation 2009-----
3455                         // Disable the accessible VALUE_CHANGE event
3456                         sal_Bool bIsSuppressed = pInputWin->IsAccessibilityEventsSuppressed(sal_False);
3457                         pInputWin->SetAccessibilityEventsSuppressed(sal_True);
3458                         pInputWin->SetPosString(aPosStr);
3459                         pInputWin->SetAccessibilityEventsSuppressed(bIsSuppressed);
3460                         //-----IAccessibility2 Implementation 2009
3461                         pInputWin->SetSumAssignMode();
3462                     }
3463 
3464                     if (bStopEditing)
3465                         SFX_APP()->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) );
3466 
3467                     //  As long as the content is not edited, turn off online spelling.
3468                     //  Online spelling is turned back on in StartTable, after setting
3469                     //  the right language from cell attributes.
3470 
3471                     sal_uLong nCntrl = pEngine->GetControlWord();
3472                     if ( nCntrl & EE_CNTRL_ONLINESPELLING )
3473                         pEngine->SetControlWord( nCntrl & ~EE_CNTRL_ONLINESPELLING );
3474 
3475                     bModified = sal_False;
3476                     bSelIsRef = sal_False;
3477                     bProtected = sal_False;
3478                     bCommandErrorShown = sal_False;
3479                 }
3480             }
3481         }
3482 
3483 //      bProtected = sal_False;
3484 
3485         if ( pInputWin)
3486         {
3487             if(!pScMod->IsFormulaMode()&& !pScMod->IsRefDialogOpen())   //BugID 54702
3488             {                                                           //Wenn RefDialog offen, dann nicht enablen
3489                 if ( !pInputWin->IsEnabled())
3490                 {
3491                     pInputWin->Enable();
3492                     if(pDelayTimer )
3493                     {
3494                         DELETEZ( pDelayTimer );
3495                     }
3496                 }
3497             }
3498             else if(pScMod->IsRefDialogOpen())
3499             {                                   // Da jedes Dokument eigenes InputWin hat, sollte
3500                 if ( !pDelayTimer )             // nochmals Timer gestartet werden, da sonst Ein-
3501                 {                               // gabezeile evt. noch aktiv ist.
3502                     pDelayTimer = new Timer;
3503                     pDelayTimer->SetTimeout( 500 ); // 100ms Verzoegerung
3504                     pDelayTimer->SetTimeoutHdl( LINK( this, ScInputHandler, DelayTimer ) );
3505                     pDelayTimer->Start();
3506                 }
3507             }
3508         }
3509     }
3510     else // !pState || !pActiveViewSh
3511     {
3512         if ( !pDelayTimer )
3513         {
3514             pDelayTimer = new Timer;
3515             pDelayTimer->SetTimeout( 500 ); // 100ms Verzoegerung
3516             pDelayTimer->SetTimeoutHdl( LINK( this, ScInputHandler, DelayTimer ) );
3517             pDelayTimer->Start();
3518         }
3519     }
3520 
3521     HideTip();
3522     HideTipBelow();
3523     bInOwnChange = sal_False;
3524 }
3525 
3526 void ScInputHandler::UpdateCellAdjust( SvxCellHorJustify eJust )
3527 {
3528     eAttrAdjust = eJust;
3529     UpdateAdjust( 0 );
3530 }
3531 
3532 void ScInputHandler::ResetDelayTimer()
3533 {
3534     if(pDelayTimer!=NULL)
3535     {
3536         DELETEZ( pDelayTimer );
3537 
3538         if ( pInputWin)
3539         {
3540             pInputWin->Enable();
3541         }
3542     }
3543 }
3544 
3545 IMPL_LINK( ScInputHandler, DelayTimer, Timer*, pTimer )
3546 {
3547     if ( pTimer == pDelayTimer )
3548     {
3549         DELETEZ( pDelayTimer );
3550 
3551         if ( NULL == pLastState || SC_MOD()->IsFormulaMode() || SC_MOD()->IsRefDialogOpen())
3552         {
3553             //! new method at ScModule to query if function autopilot is open
3554 
3555             SfxViewFrame* pViewFrm = SfxViewFrame::Current();
3556             if ( pViewFrm && pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
3557             {
3558                 if ( pInputWin)
3559                 {
3560                     pInputWin->EnableButtons( sal_False );
3561                     pInputWin->Disable();
3562                 }
3563             }
3564             else if ( !bFormulaMode )   // #39210# Formel auch z.B. bei Hilfe behalten
3565             {
3566                 bInOwnChange = sal_True;    // disable ModifyHdl (reset below)
3567 
3568                 pActiveViewSh = NULL;
3569                 pEngine->SetText( EMPTY_STRING );
3570                 if ( pInputWin )
3571                 {
3572                     pInputWin->SetPosString( EMPTY_STRING );
3573                     pInputWin->SetTextString( EMPTY_STRING );
3574                     pInputWin->Disable();
3575                 }
3576 
3577                 bInOwnChange = sal_False;
3578             }
3579         }
3580     }
3581     return 0;
3582 }
3583 
3584 void ScInputHandler::InputSelection( EditView* pView )
3585 {
3586     SyncViews( pView );
3587     ShowTipCursor();
3588     UpdateParenthesis();    //  Selektion geaendert -> Klammer-Hervorhebung neu
3589 
3590     //  when the selection is changed manually, stop overwriting parentheses
3591     ResetAutoPar();
3592 }
3593 
3594 void ScInputHandler::InputChanged( EditView* pView, sal_Bool bFromNotify )
3595 {
3596     ESelection aSelection = pView->GetSelection();
3597 
3598     UpdateActiveView();
3599 
3600     // #i20282# DataChanged needs to know if this is from the input line's modify handler
3601     sal_Bool bFromTopNotify = ( bFromNotify && pView == pTopView );
3602 
3603     sal_Bool bNewView = DataChanging();                     //! kann das hier ueberhaupt sein?
3604     aCurrentText = pView->GetEditEngine()->GetText();   // auch den String merken
3605     pEngine->SetText( aCurrentText );
3606     DataChanged( bFromTopNotify );
3607     bTextValid = sal_True;      // wird in DataChanged auf sal_False gesetzt
3608 
3609     if ( pActiveViewSh )
3610     {
3611         ScViewData* pViewData = pActiveViewSh->GetViewData();
3612         if ( bNewView )
3613             pViewData->GetDocShell()->PostEditView( pEngine, aCursorPos );
3614 
3615         pViewData->EditGrowY();
3616         pViewData->EditGrowX();
3617     }
3618 
3619     SyncViews( pView );
3620 }
3621 
3622 const String& ScInputHandler::GetEditString()
3623 {
3624     if (pEngine)
3625     {
3626         aCurrentText = pEngine->GetText();      // immer neu aus Engine
3627         bTextValid = sal_True;
3628     }
3629 
3630     return aCurrentText;
3631 }
3632 
3633 Size ScInputHandler::GetTextSize()
3634 {
3635     Size aSize;
3636     if ( pEngine )
3637         aSize = Size( pEngine->CalcTextWidth(), pEngine->GetTextHeight() );
3638 
3639     return aSize;
3640 }
3641 
3642 sal_Bool ScInputHandler::GetTextAndFields( ScEditEngineDefaulter& rDestEngine )
3643 {
3644     sal_Bool bRet = sal_False;
3645     if (pEngine)
3646     {
3647         //  Feldbefehle enthalten?
3648 
3649         sal_uInt16 nParCnt = pEngine->GetParagraphCount();
3650         SfxItemSet aSet = pEngine->GetAttribs( ESelection(0,0,nParCnt,0) );
3651         SfxItemState eFieldState = aSet.GetItemState( EE_FEATURE_FIELD, sal_False );
3652         if ( eFieldState == SFX_ITEM_DONTCARE || eFieldState == SFX_ITEM_SET )
3653         {
3654             //  Inhalt kopieren
3655 
3656             EditTextObject* pObj = pEngine->CreateTextObject();
3657             rDestEngine.SetText(*pObj);
3658             delete pObj;
3659 
3660             //  Attribute loeschen
3661 
3662             for (sal_uInt16 i=0; i<nParCnt; i++)
3663                 rDestEngine.QuickRemoveCharAttribs( i );
3664 
3665             //  Absaetze zusammenfassen
3666 
3667             while ( nParCnt > 1 )
3668             {
3669                 xub_StrLen nLen = rDestEngine.GetTextLen( (sal_uInt16)0 );
3670                 ESelection aSel( 0,nLen, 1,0 );
3671                 rDestEngine.QuickInsertText( ' ', aSel );       // Umbruch durch Space ersetzen
3672                 --nParCnt;
3673             }
3674 
3675             bRet = sal_True;
3676         }
3677     }
3678     return bRet;
3679 }
3680 
3681 
3682 //------------------------------------------------------------------------
3683 // Methoden fuer FunktionsAutopiloten:
3684 // InputGetSelection, InputSetSelection, InputReplaceSelection, InputGetFormulaStr
3685 //------------------------------------------------------------------------
3686 
3687 void ScInputHandler::InputGetSelection( xub_StrLen& rStart, xub_StrLen& rEnd )
3688 {
3689     rStart = nFormSelStart;
3690     rEnd = nFormSelEnd;
3691 }
3692 
3693 //------------------------------------------------------------------------
3694 
3695 EditView* ScInputHandler::GetFuncEditView()
3696 {
3697     UpdateActiveView();     // wegen pTableView
3698 
3699     EditView* pView = NULL;
3700     if ( pInputWin )
3701     {
3702         pInputWin->MakeDialogEditView();
3703         pView = pInputWin->GetEditView();
3704     }
3705     else
3706     {
3707         if ( eMode != SC_INPUT_TABLE )
3708         {
3709             bCreatingFuncView = sal_True;       // RangeFinder nicht anzeigen
3710             SetMode( SC_INPUT_TABLE );
3711             bCreatingFuncView = sal_False;
3712             if ( pTableView )
3713                 pTableView->GetEditEngine()->SetText( EMPTY_STRING );
3714         }
3715         pView = pTableView;
3716     }
3717 
3718     return pView;
3719 }
3720 
3721 //------------------------------------------------------------------------
3722 
3723 void ScInputHandler::InputSetSelection( xub_StrLen nStart, xub_StrLen nEnd )
3724 {
3725     if ( nStart <= nEnd )
3726     {
3727         nFormSelStart = nStart;
3728         nFormSelEnd = nEnd;
3729     }
3730     else
3731     {
3732         nFormSelEnd = nStart;
3733         nFormSelStart = nEnd;
3734     }
3735 
3736     EditView* pView = GetFuncEditView();
3737     if (pView)
3738         pView->SetSelection( ESelection(0,nStart, 0,nEnd) );
3739 
3740     bModified = sal_True;
3741 }
3742 
3743 //------------------------------------------------------------------------
3744 
3745 void ScInputHandler::InputReplaceSelection( const String& rStr )
3746 {
3747     if (!pRefViewSh)
3748         pRefViewSh = pActiveViewSh;
3749 
3750     DBG_ASSERT(nFormSelEnd>=nFormSelStart,"Selektion kaputt...");
3751 
3752     xub_StrLen nOldLen = nFormSelEnd-nFormSelStart;
3753     xub_StrLen nNewLen = rStr.Len();
3754     if (nOldLen)
3755         aFormText.Erase( nFormSelStart, nOldLen );
3756     if (nNewLen)
3757         aFormText.Insert( rStr, nFormSelStart );
3758     nFormSelEnd = nFormSelStart + nNewLen;
3759 
3760     EditView* pView = GetFuncEditView();
3761     if (pView)
3762     {
3763         pView->SetEditEngineUpdateMode( sal_False );
3764 //      pView->InsertText( rStr, sal_True );
3765         pView->GetEditEngine()->SetText( aFormText );
3766         pView->SetSelection( ESelection(0,nFormSelStart, 0,nFormSelEnd) );
3767         pView->SetEditEngineUpdateMode( sal_True );
3768     }
3769     bModified = sal_True;
3770 }
3771 
3772 //------------------------------------------------------------------------
3773 
3774 String ScInputHandler::InputGetFormulaStr()
3775 {
3776     return aFormText;   //! eigene Membervariable?
3777 }
3778 
3779 //========================================================================
3780 //  ScInputHdlState
3781 //========================================================================
3782 
3783 ScInputHdlState::ScInputHdlState( const ScAddress& rCurPos,
3784                                   const ScAddress& rStartPos,
3785                                   const ScAddress& rEndPos,
3786                                   const String& rString,
3787                                   const EditTextObject* pData )
3788     :   aCursorPos  ( rCurPos ),
3789         aStartPos   ( rStartPos ),
3790         aEndPos     ( rEndPos ),
3791         aString     ( rString ),
3792         pEditData   ( pData ? pData->Clone() : NULL )
3793 {
3794 }
3795 
3796 //------------------------------------------------------------------------
3797 
3798 ScInputHdlState::ScInputHdlState( const ScInputHdlState& rCpy )
3799     :   pEditData   ( NULL )
3800 {
3801     *this = rCpy;
3802 }
3803 
3804 //------------------------------------------------------------------------
3805 
3806 ScInputHdlState::~ScInputHdlState()
3807 {
3808     delete pEditData;
3809 }
3810 
3811 //------------------------------------------------------------------------
3812 
3813 int ScInputHdlState::operator==( const ScInputHdlState& r ) const
3814 {
3815     return (    (aStartPos  == r.aStartPos)
3816              && (aEndPos    == r.aEndPos)
3817              && (aCursorPos == r.aCursorPos)
3818              && (aString    == r.aString)
3819              && ScGlobal::EETextObjEqual( pEditData, r.pEditData ) );
3820 }
3821 
3822 //------------------------------------------------------------------------
3823 
3824 ScInputHdlState& ScInputHdlState::operator=( const ScInputHdlState& r )
3825 {
3826     delete pEditData;
3827 
3828     aCursorPos  = r.aCursorPos;
3829     aStartPos   = r.aStartPos;
3830     aEndPos     = r.aEndPos;
3831     aString     = r.aString;
3832     pEditData   = r.pEditData ? r.pEditData->Clone() : NULL;
3833 
3834     return *this;
3835 }
3836 
3837 
3838 
3839 
3840