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