xref: /AOO41X/main/sc/source/ui/app/inputhdl.cxx (revision 4d7c9de063a797b8b4f3d45e3561e82ad1f8ef1f)
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 
lcl_getSheetSeparator(ScDocument * pDoc)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 
InitRangeFinder(const String & rFormula)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 
lcl_Replace(EditView * pView,const String & rNewStr,const ESelection & rOldSel)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 
UpdateRange(sal_uInt16 nIndex,const ScRange & rNew)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 
DeleteRangeFinder()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 
GetEditText(EditEngine * pEng)306 inline String GetEditText(EditEngine* pEng)
307 {
308     return ScEditUtil::GetSpaceDelimitedString(*pEng);
309 }
310 
lcl_RemoveTabs(String & rStr)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 
lcl_RemoveLineEnd(String & rStr)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 
lcl_MatchParenthesis(const String & rStr,xub_StrLen nPos)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 
ScInputHandler()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 
~ScInputHandler()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 
SetRefScale(const Fraction & rX,const Fraction & rY)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 
UpdateRefDevice()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 
ImplCreateEditEngine()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 
UpdateAutoCorrFlag()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 
UpdateSpellSettings(sal_Bool bFromStartTab)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 
GetFormulaData()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 
IMPL_LINK(ScInputHandler,ShowHideTipVisibleParentListener,VclWindowEvent *,pEvent)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 
IMPL_LINK(ScInputHandler,ShowHideTipVisibleSecParentListener,VclWindowEvent *,pEvent)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 
HideTip()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 }
HideTipBelow()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 
ShowTipCursor()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 
ShowTip(const String & rText)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 
ShowTipBelow(const String & rText)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 
UseFormulaData()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 
NextFormulaEntry(sal_Bool bBack)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 
lcl_CompleteFunction(EditView * pView,const String & rInsert,sal_Bool & rParInserted)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 
PasteFunctionData()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 
lcl_Calculate(const String & rFormula,ScDocument * pDoc,const ScAddress & rPos)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 
FormulaPreview()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 
PasteManualTip()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 
ResetAutoPar()1377 void ScInputHandler::ResetAutoPar()
1378 {
1379     nAutoPar = 0;
1380 }
1381 
AutoParAdded()1382 void ScInputHandler::AutoParAdded()
1383 {
1384     ++nAutoPar;     //  closing parenthesis can be overwritten
1385 }
1386 
CursorAtClosingPar()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 
SkipClosingPar()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 
GetColData()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 
UseColData()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 
NextAutoEntry(sal_Bool bBack)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 
UpdateParenthesis()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 
ViewShellGone(ScTabViewShell * pViewSh)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 
UpdateActiveView()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 
StopInputWinEngine(sal_Bool bAll)1728 void ScInputHandler::StopInputWinEngine( sal_Bool bAll )
1729 {
1730     if (pInputWin)
1731         pInputWin->StopEditEngine( bAll );
1732 
1733     pTopView = NULL;        // invalid now
1734 }
1735 
GetActiveView()1736 EditView* ScInputHandler::GetActiveView()
1737 {
1738     UpdateActiveView();
1739     return pTopView ? pTopView : pTableView;
1740 }
1741 
ForgetLastPattern()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 
UpdateAdjust(sal_Unicode cTyped)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 
RemoveAdjust()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 
RemoveRangeFinder()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 
StartTable(sal_Unicode cTyped,sal_Bool bFromCommand)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 
lcl_SetTopSelection(EditView * pEditView,ESelection & rSel)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 
SyncViews(EditView * pSourceView)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 
IMPL_LINK(ScInputHandler,ModifyHdl,void *,EMPTYARG)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 
DataChanging(sal_Unicode cTyped,sal_Bool bFromCommand)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 
DataChanged(sal_Bool bFromTopNotify,sal_Bool bSetModified)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 
UpdateFormulaMode()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 
ShowRefFrame()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 
RemoveSelection()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 
InvalidateAttribs()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         rBindings.Invalidate( SID_ATTR_CHAR_KERNING );
2287         rBindings.Invalidate( SID_SET_SUPER_SCRIPT );
2288         rBindings.Invalidate( SID_SET_SUB_SCRIPT );
2289         rBindings.Invalidate( SID_ATTR_CHAR_STRIKEOUT );
2290         rBindings.Invalidate( SID_ATTR_CHAR_SHADOWED );
2291     }
2292 }
2293 
2294 
2295 //
2296 //      --------------- public Methoden --------------------------------------------
2297 //
2298 
SetMode(ScInputMode eNewMode)2299 void ScInputHandler::SetMode( ScInputMode eNewMode )
2300 {
2301     if ( eMode == eNewMode )
2302         return;
2303 
2304     ImplCreateEditEngine();
2305 
2306     if (bProtected)
2307     {
2308         eMode = SC_INPUT_NONE;
2309         StopInputWinEngine( sal_True );
2310         if (pActiveViewSh)
2311             pActiveViewSh->GetActiveWin()->GrabFocus();
2312         return;
2313     }
2314 
2315     bInOwnChange = sal_True;                // disable ModifyHdl (reset below)
2316 
2317     ScInputMode eOldMode = eMode;
2318     eMode = eNewMode;
2319     if (eOldMode == SC_INPUT_TOP && eNewMode != eOldMode)
2320         StopInputWinEngine( sal_False );
2321 
2322     if (eMode==SC_INPUT_TOP || eMode==SC_INPUT_TABLE)
2323     {
2324         if (eOldMode == SC_INPUT_NONE)      // not when switching between modes
2325         {
2326             if (StartTable(0, sal_False))       // 0 = look at existing document content for text or number
2327             {
2328                 if (pActiveViewSh)
2329                     pActiveViewSh->GetViewData()->GetDocShell()->PostEditView( pEngine, aCursorPos );
2330             }
2331         }
2332 
2333         sal_uInt16 nPara    = pEngine->GetParagraphCount()-1;
2334         xub_StrLen nLen = pEngine->GetText(nPara).Len();
2335         sal_uInt16 nCount   = pEngine->GetViewCount();
2336 
2337         for (sal_uInt16 i=0; i<nCount; i++)
2338         {
2339             if ( eMode == SC_INPUT_TABLE && eOldMode == SC_INPUT_TOP )
2340             {
2341                 //  Selektion bleibt
2342             }
2343             else
2344             {
2345                 pEngine->GetView(i)->
2346                     SetSelection( ESelection( nPara, nLen, nPara, nLen ) );
2347             }
2348             pEngine->GetView(i)->ShowCursor(sal_False);
2349         }
2350     }
2351 
2352     UpdateActiveView();
2353     if (eMode==SC_INPUT_TABLE || eMode==SC_INPUT_TYPE)
2354     {
2355         if (pTableView)
2356             pTableView->SetEditEngineUpdateMode(sal_True);
2357     }
2358     else
2359     {
2360         if (pTopView)
2361             pTopView->SetEditEngineUpdateMode(sal_True);
2362     }
2363 
2364     if (eNewMode != eOldMode)
2365         UpdateFormulaMode();
2366 
2367     bInOwnChange = sal_False;
2368 }
2369 
2370 //----------------------------------------------------------------------------------------
2371 
2372 //  lcl_IsNumber - sal_True, wenn nur Ziffern (dann keine Autokorrektur)
2373 
lcl_IsNumber(const String & rString)2374 sal_Bool lcl_IsNumber(const String& rString)
2375 {
2376     xub_StrLen nLen = rString.Len();
2377     for (xub_StrLen i=0; i<nLen; i++)
2378     {
2379         sal_Unicode c = rString.GetChar(i);
2380         if ( c < '0' || c > '9' )
2381             return sal_False;
2382     }
2383     return sal_True;
2384 }
2385 
lcl_SelectionToEnd(EditView * pView)2386 void lcl_SelectionToEnd( EditView* pView )
2387 {
2388     if ( pView )
2389     {
2390         EditEngine* pEngine = pView->GetEditEngine();
2391         sal_uInt16 nParCnt = pEngine->GetParagraphCount();
2392         if ( nParCnt == 0 )
2393             nParCnt = 1;
2394         ESelection aSel( nParCnt-1, pEngine->GetTextLen(nParCnt-1) );   // empty selection, cursor at the end
2395         pView->SetSelection( aSel );
2396     }
2397 }
2398 
EnterHandler(sal_uInt8 nBlockMode)2399 void ScInputHandler::EnterHandler( sal_uInt8 nBlockMode )
2400 {
2401     //  #62806# Bei Makro-Aufrufen fuer Gueltigkeit kann Tod und Teufel passieren,
2402     //  darum dafuer sorgen, dass EnterHandler nicht verschachtelt gerufen wird:
2403 
2404     if (bInEnterHandler) return;
2405     bInEnterHandler = sal_True;
2406     bInOwnChange = sal_True;                // disable ModifyHdl (reset below)
2407 
2408     ImplCreateEditEngine();
2409 
2410     sal_Bool bMatrix = ( nBlockMode == SC_ENTER_MATRIX );
2411 
2412     SfxApplication* pSfxApp     = SFX_APP();
2413     EditTextObject* pObject     = NULL;
2414     ScPatternAttr*  pCellAttrs  = NULL;
2415     sal_Bool            bAttrib     = sal_False;    // Formatierung vorhanden ?
2416     sal_Bool            bForget     = sal_False;    // wegen Gueltigkeit streichen ?
2417 
2418     String aString = GetEditText(pEngine);
2419     EditView* pActiveView = pTopView ? pTopView : pTableView;
2420     if (bModified && pActiveView && aString.Len() && !lcl_IsNumber(aString))
2421     {
2422         if ( pColumnData && nAutoPos != SCPOS_INVALID )
2423         {
2424             // #i47125# If AutoInput appended something, do the final AutoCorrect
2425             // with the cursor at the end of the input.
2426 
2427             lcl_SelectionToEnd(pTopView);
2428             lcl_SelectionToEnd(pTableView);
2429         }
2430 
2431         if (pTopView)
2432             pTopView->CompleteAutoCorrect();    // #59759# CompleteAutoCorrect fuer beide Views
2433         if (pTableView)
2434             pTableView->CompleteAutoCorrect();
2435         aString = GetEditText(pEngine);
2436     }
2437     lcl_RemoveTabs(aString);
2438 
2439     //  Test, ob zulaessig (immer mit einfachem String)
2440 
2441     if ( bModified && nValidation && pActiveViewSh )
2442     {
2443         ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocument();
2444         const ScValidationData* pData = pDoc->GetValidationEntry( nValidation );
2445         if (pData && pData->HasErrMsg())
2446         {
2447             // #i67990# don't use pLastPattern in EnterHandler
2448             const ScPatternAttr* pPattern = pDoc->GetPattern( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab() );
2449             sal_Bool bOk = pData->IsDataValid( aString, *pPattern, aCursorPos );
2450 
2451             if (!bOk)
2452             {
2453                 if ( pActiveViewSh )                // falls aus MouseButtonDown gekommen
2454                     pActiveViewSh->StopMarking();   // (die InfoBox verschluckt das MouseButtonUp)
2455 
2456                     //! es gibt noch Probleme, wenn die Eingabe durch Aktivieren einer
2457                     //! anderen View ausgeloest wurde
2458 
2459                 Window* pParent = Application::GetDefDialogParent();
2460                 if ( pData->DoError( pParent, aString, aCursorPos ) )
2461                     bForget = sal_True;                 // Eingabe nicht uebernehmen
2462             }
2463         }
2464     }
2465 
2466     // check for input into DataPilot table
2467 
2468     if ( bModified && pActiveViewSh && !bForget )
2469     {
2470         ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocument();
2471         ScDPObject* pDPObj = pDoc->GetDPAtCursor( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab() );
2472         if ( pDPObj )
2473         {
2474             // any input within the DataPilot table is either a valid renaming
2475             // or an invalid action - normal cell input is always aborted
2476 
2477             pActiveViewSh->DataPilotInput( aCursorPos, aString );
2478             bForget = sal_True;
2479         }
2480     }
2481 
2482     pEngine->CompleteOnlineSpelling();
2483     sal_Bool bSpellErrors = !bFormulaMode && pEngine->HasOnlineSpellErrors();
2484     if ( bSpellErrors )
2485     {
2486         //  #i3820# If the spell checker flags numerical input as error,
2487         //  it still has to be treated as number, not EditEngine object.
2488 
2489         if ( pActiveViewSh )
2490         {
2491             ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocument();
2492             // #i67990# don't use pLastPattern in EnterHandler
2493             const ScPatternAttr* pPattern = pDoc->GetPattern( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab() );
2494             SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
2495             // without conditional format, as in ScColumn::SetString
2496             sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
2497             double nVal;
2498             if ( pFormatter->IsNumberFormat( aString, nFormat, nVal ) )
2499             {
2500                 bSpellErrors = sal_False;       // ignore the spelling errors
2501             }
2502         }
2503     }
2504 
2505     //  After RemoveAdjust, the EditView must not be repainted (has wrong font size etc).
2506     //  SetUpdateMode must come after CompleteOnlineSpelling.
2507     //  The view is hidden in any case below (Broadcast).
2508     pEngine->SetUpdateMode( sal_False );
2509 
2510     if ( bModified && !bForget )            // was wird eingeben (Text/Objekt) ?
2511     {
2512         sal_uInt16 nParCnt = pEngine->GetParagraphCount();
2513         if ( nParCnt == 0 )
2514             nParCnt = 1;
2515         ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) );
2516         SfxItemSet aOldAttribs = pEngine->GetAttribs( aSel );
2517         const SfxPoolItem* pItem = NULL;
2518 
2519         //  find common (cell) attributes before RemoveAdjust
2520 
2521         if ( pActiveViewSh )
2522         {
2523             SfxItemSet* pCommonAttrs = NULL;
2524             for (sal_uInt16 nId = EE_CHAR_START; nId <= EE_CHAR_END; nId++)
2525             {
2526                 SfxItemState eState = aOldAttribs.GetItemState( nId, sal_False, &pItem );
2527                 if ( eState == SFX_ITEM_SET &&
2528                         nId != EE_CHAR_ESCAPEMENT && nId != EE_CHAR_PAIRKERNING &&
2529                         nId != EE_CHAR_KERNING && nId != EE_CHAR_XMLATTRIBS &&
2530                             *pItem != pEditDefaults->Get(nId) )
2531                 {
2532                     if ( !pCommonAttrs )
2533                         pCommonAttrs = new SfxItemSet( pEngine->GetEmptyItemSet() );
2534                     pCommonAttrs->Put( *pItem );
2535                 }
2536             }
2537 
2538             if ( pCommonAttrs )
2539             {
2540                 ScDocument* pDoc = pActiveViewSh->GetViewData()->GetDocument();
2541                 pCellAttrs = new ScPatternAttr( pDoc->GetPool() );
2542                 pCellAttrs->GetFromEditItemSet( pCommonAttrs );
2543                 delete pCommonAttrs;
2544             }
2545         }
2546 
2547         //  clear ParaAttribs (including adjustment)
2548 
2549         RemoveAdjust();
2550 
2551         //  check if EditObject is needed
2552 
2553         if ( bSpellErrors || nParCnt > 1 )
2554             bAttrib = sal_True;
2555         else
2556         {
2557             for (sal_uInt16 nId = EE_CHAR_START; nId <= EE_CHAR_END && !bAttrib; nId++)
2558             {
2559                 SfxItemState eState = aOldAttribs.GetItemState( nId, sal_False, &pItem );
2560                 if (eState == SFX_ITEM_DONTCARE)
2561                     bAttrib = sal_True;
2562                 else if (eState == SFX_ITEM_SET)
2563                 {
2564                     //  keep same items in EditEngine as in ScEditAttrTester
2565                     if ( nId == EE_CHAR_ESCAPEMENT || nId == EE_CHAR_PAIRKERNING ||
2566                          nId == EE_CHAR_KERNING || nId == EE_CHAR_XMLATTRIBS )
2567                     {
2568                         if ( *pItem != pEditDefaults->Get(nId) )
2569                             bAttrib = sal_True;
2570                     }
2571                 }
2572             }
2573 
2574             //  Feldbefehle enthalten?
2575 
2576             SfxItemState eFieldState = aOldAttribs.GetItemState( EE_FEATURE_FIELD, sal_False );
2577             if ( eFieldState == SFX_ITEM_DONTCARE || eFieldState == SFX_ITEM_SET )
2578                 bAttrib = sal_True;
2579 
2580             //  not converted characters?
2581 
2582             SfxItemState eConvState = aOldAttribs.GetItemState( EE_FEATURE_NOTCONV, sal_False );
2583             if ( eConvState == SFX_ITEM_DONTCARE || eConvState == SFX_ITEM_SET )
2584                 bAttrib = sal_True;
2585 
2586             //  Formeln immer als Formeln erkennen (#38309#)
2587             //  (der Test vorher ist trotzdem noetig wegen Zell-Attributen)
2588         }
2589 
2590         if (bMatrix)
2591             bAttrib = sal_False;
2592 
2593         if (bAttrib)
2594         {
2595             sal_uLong nCtrl = pEngine->GetControlWord();
2596             sal_uLong nWantBig = bSpellErrors ? EE_CNTRL_ALLOWBIGOBJS : 0;
2597             if ( ( nCtrl & EE_CNTRL_ALLOWBIGOBJS ) != nWantBig )
2598                 pEngine->SetControlWord( (nCtrl & ~EE_CNTRL_ALLOWBIGOBJS) | nWantBig );
2599             pObject = pEngine->CreateTextObject();
2600         }
2601         else if (bAutoComplete)         // Gross-/Kleinschreibung anpassen
2602         {
2603             if (pColumnData)
2604                 pColumnData->GetExactMatch( aString );
2605 
2606             //! effizienter in der Liste suchen (ScUserList, nur einmal ToUpper)
2607 
2608             sal_uInt16 nIndex;
2609             ScUserListData* pData = ScGlobal::GetUserList()->GetData(aString);
2610             if ( pData && pData->GetSubIndex( aString, nIndex ) )
2611                 aString = pData->GetSubStr( nIndex );
2612         }
2613     }
2614 
2615     //  don't rely on ShowRefFrame switching the active view synchronously
2616     //  execute the function directly on the correct view's bindings instead
2617     //  pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2618     ScTabViewShell* pExecuteSh = pRefViewSh ? pRefViewSh : pActiveViewSh;
2619 
2620     if (bFormulaMode)
2621     {
2622         ShowRefFrame();
2623 
2624         if (pExecuteSh)
2625         {
2626             pExecuteSh->SetTabNo(aCursorPos.Tab());
2627             pExecuteSh->ActiveGrabFocus();
2628         }
2629 
2630         bFormulaMode = sal_False;
2631         pSfxApp->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2632         SC_MOD()->SetRefInputHdl(NULL);
2633         if (pInputWin)
2634             pInputWin->SetFormulaMode(sal_False);
2635         UpdateAutoCorrFlag();
2636     }
2637     pRefViewSh = NULL;          // auch ohne FormulaMode wegen Funktions-AP
2638     DeleteRangeFinder();
2639     ResetAutoPar();
2640 
2641     sal_Bool bOldMod = bModified;
2642 
2643     bModified = sal_False;
2644     bSelIsRef = sal_False;
2645     eMode     = SC_INPUT_NONE;
2646     StopInputWinEngine( sal_True );
2647 
2648     // #123344# Text input (through number formats) or ApplySelectionPattern modify
2649     // the cell's attributes, so pLastPattern is no longer valid
2650     pLastPattern = NULL;
2651 
2652     if (bOldMod && !bProtected && !bForget)
2653     {
2654         //  keine typographische Anfuehrungszeichen in Formeln
2655 
2656         if ( aString.GetChar(0) == '=' )
2657         {
2658             SvxAutoCorrect* pAuto = SvxAutoCorrCfg::Get()->GetAutoCorrect();
2659             if ( pAuto )
2660             {
2661                 sal_Unicode cReplace = pAuto->GetStartDoubleQuote();
2662                 if( !cReplace )
2663                     cReplace = ScGlobal::pLocaleData->getDoubleQuotationMarkStart().GetChar(0);
2664                 if ( cReplace != '"' )
2665                     aString.SearchAndReplaceAll( cReplace, '"' );
2666 
2667                 cReplace = pAuto->GetEndDoubleQuote();
2668                 if( !cReplace )
2669                     cReplace = ScGlobal::pLocaleData->getDoubleQuotationMarkEnd().GetChar(0);
2670                 if ( cReplace != '"' )
2671                     aString.SearchAndReplaceAll( cReplace, '"' );
2672 
2673                 cReplace = pAuto->GetStartSingleQuote();
2674                 if( !cReplace )
2675                     cReplace = ScGlobal::pLocaleData->getQuotationMarkStart().GetChar(0);
2676                 if ( cReplace != '\'' )
2677                     aString.SearchAndReplaceAll( cReplace, '\'' );
2678 
2679                 cReplace = pAuto->GetEndSingleQuote();
2680                 if( !cReplace )
2681                     cReplace = ScGlobal::pLocaleData->getQuotationMarkEnd().GetChar(0);
2682                 if ( cReplace != '\'' )
2683                     aString.SearchAndReplaceAll( cReplace, '\'' );
2684             }
2685         }
2686 
2687         pSfxApp->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW_NOPAINT ) );
2688 
2689         if ( pExecuteSh )
2690         {
2691             SfxBindings& rBindings = pExecuteSh->GetViewFrame()->GetBindings();
2692 
2693             sal_uInt16 nId = FID_INPUTLINE_ENTER;
2694             if ( nBlockMode == SC_ENTER_BLOCK )
2695                 nId = FID_INPUTLINE_BLOCK;
2696             else if ( nBlockMode == SC_ENTER_MATRIX )
2697                 nId = FID_INPUTLINE_MATRIX;
2698 
2699             ScInputStatusItem aItem( FID_INPUTLINE_STATUS,
2700                                      aCursorPos, aCursorPos, aCursorPos,
2701                                      aString, pObject );
2702             const SfxPoolItem* aArgs[2];
2703             aArgs[0] = &aItem;
2704             aArgs[1] = NULL;
2705             rBindings.Execute( nId, aArgs );
2706         }
2707 
2708         delete pLastState;      // pLastState enthaelt noch den alten Text
2709         pLastState = NULL;
2710     }
2711     else
2712         pSfxApp->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) );
2713 
2714     if ( bOldMod && pExecuteSh && pCellAttrs && !bForget )
2715     {
2716         //  mit Eingabe zusammenfassen ?
2717         pExecuteSh->ApplySelectionPattern( *pCellAttrs, sal_True, sal_True );
2718         pExecuteSh->AdjustBlockHeight();
2719     }
2720 
2721     delete pCellAttrs;
2722     delete pObject;
2723 
2724     HideTip();
2725     HideTipBelow();
2726 
2727     nFormSelStart = nFormSelEnd = 0;
2728     aFormText.Erase();
2729 
2730     bInOwnChange = sal_False;
2731     bInEnterHandler = sal_False;
2732 }
2733 
CancelHandler()2734 void ScInputHandler::CancelHandler()
2735 {
2736     bInOwnChange = sal_True;                // disable ModifyHdl (reset below)
2737 
2738     ImplCreateEditEngine();
2739 
2740     bModified = sal_False;
2741 
2742     //  don't rely on ShowRefFrame switching the active view synchronously
2743     //  execute the function directly on the correct view's bindings instead
2744     //  pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
2745     ScTabViewShell* pExecuteSh = pRefViewSh ? pRefViewSh : pActiveViewSh;
2746 
2747     if (bFormulaMode)
2748     {
2749         ShowRefFrame();
2750         if (pExecuteSh)
2751         {
2752             pExecuteSh->SetTabNo(aCursorPos.Tab());
2753             pExecuteSh->ActiveGrabFocus();
2754         }
2755         bFormulaMode = sal_False;
2756         SFX_APP()->Broadcast( SfxSimpleHint( FID_REFMODECHANGED ) );
2757         SC_MOD()->SetRefInputHdl(NULL);
2758         if (pInputWin)
2759             pInputWin->SetFormulaMode(sal_False);
2760         UpdateAutoCorrFlag();
2761     }
2762     pRefViewSh = NULL;          // auch ohne FormulaMode wegen Funktions-AP
2763     DeleteRangeFinder();
2764     ResetAutoPar();
2765 
2766     eMode = SC_INPUT_NONE;
2767     StopInputWinEngine( sal_True );
2768     if (pExecuteSh)
2769         pExecuteSh->StopEditShell();
2770 
2771     aCursorPos.Set(MAXCOL+1,0,0);       // Flag, dass ungueltig
2772     pEngine->SetText(String());
2773 
2774     if ( !pLastState && pExecuteSh )
2775         pExecuteSh->UpdateInputHandler( sal_True );     // Status neu holen
2776     else
2777         NotifyChange( pLastState, sal_True );
2778 
2779     nFormSelStart = nFormSelEnd = 0;
2780     aFormText.Erase();
2781 
2782     bInOwnChange = sal_False;
2783 }
2784 
IsModalMode(SfxObjectShell * pDocSh)2785 sal_Bool ScInputHandler::IsModalMode( SfxObjectShell* pDocSh )
2786 {
2787     //  Referenzen auf unbenanntes Dokument gehen nicht
2788 
2789     return bFormulaMode && pRefViewSh
2790             && pRefViewSh->GetViewData()->GetDocument()->GetDocumentShell() != pDocSh
2791             && !pDocSh->HasName();
2792 }
2793 
AddRefEntry()2794 void ScInputHandler::AddRefEntry()
2795 {
2796     const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
2797     UpdateActiveView();
2798     if (!pTableView && !pTopView)
2799         return;                             // z.B. FillMode
2800 
2801     DataChanging();                         // kann nicht neu sein
2802 
2803     RemoveSelection();
2804     if (pTableView)
2805         pTableView->InsertText( cSep, sal_False );
2806     if (pTopView)
2807         pTopView->InsertText( cSep, sal_False );
2808 
2809     DataChanged();
2810 }
2811 
SetReference(const ScRange & rRef,ScDocument * pDoc)2812 void ScInputHandler::SetReference( const ScRange& rRef, ScDocument* pDoc )
2813 {
2814     HideTip();
2815 
2816     sal_Bool bOtherDoc = ( pRefViewSh &&
2817                         pRefViewSh->GetViewData()->GetDocument() != pDoc );
2818     if (bOtherDoc)
2819         if (!pDoc->GetDocumentShell()->HasName())
2820         {
2821             //  Referenzen auf unbenanntes Dokument gehen nicht
2822             //  (SetReference sollte dann auch nicht gerufen werden)
2823 
2824             return;
2825         }
2826 
2827     UpdateActiveView();
2828     if (!pTableView && !pTopView)
2829         return;                             // z.B. FillMode
2830 
2831     //  nie das "=" ueberschreiben!
2832     EditView* pActiveView = pTopView ? pTopView : pTableView;
2833     ESelection aSel = pActiveView->GetSelection();
2834     aSel.Adjust();
2835     if ( aSel.nStartPara == 0 && aSel.nStartPos == 0 )
2836         return;
2837 
2838     DataChanging();                         // kann nicht neu sein
2839 
2840             //  Selektion umdrehen, falls rueckwaerts (noetig ???)
2841 
2842     if (pTableView)
2843     {
2844         ESelection aTabSel = pTableView->GetSelection();
2845         if (aTabSel.nStartPos > aTabSel.nEndPos && aTabSel.nStartPara == aTabSel.nEndPara)
2846         {
2847             aTabSel.Adjust();
2848             pTableView->SetSelection(aTabSel);
2849         }
2850     }
2851     if (pTopView)
2852     {
2853         ESelection aTopSel = pTopView->GetSelection();
2854         if (aTopSel.nStartPos > aTopSel.nEndPos && aTopSel.nStartPara == aTopSel.nEndPara)
2855         {
2856             aTopSel.Adjust();
2857             pTopView->SetSelection(aTopSel);
2858         }
2859     }
2860 
2861     //  String aus Referenz erzeugen
2862 
2863     String aRefStr;
2864     const ScAddress::Details aAddrDetails( pDoc, aCursorPos );
2865     if (bOtherDoc)
2866     {
2867         //  Referenz auf anderes Dokument
2868 
2869         DBG_ASSERT(rRef.aStart.Tab()==rRef.aEnd.Tab(), "nStartTab!=nEndTab");
2870 
2871         String aTmp;
2872         rRef.Format( aTmp, SCA_VALID|SCA_TAB_3D, pDoc, aAddrDetails );      // immer 3d
2873 
2874         SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
2875         // #i75893# convert escaped URL of the document to something user friendly
2876 //       String aFileName = pObjSh->GetMedium()->GetName();
2877         String aFileName = pObjSh->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
2878 
2879         aRefStr = '\'';
2880         aRefStr += aFileName;
2881         aRefStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "'#" ));
2882         aRefStr += aTmp;
2883     }
2884     else
2885     {
2886         if ( ( rRef.aStart.Tab() != aCursorPos.Tab() ||
2887                 rRef.aStart.Tab() != rRef.aEnd.Tab() ) && pDoc )
2888             rRef.Format( aRefStr, SCA_VALID|SCA_TAB_3D, pDoc, aAddrDetails );
2889         else
2890             rRef.Format( aRefStr, SCA_VALID, pDoc, aAddrDetails );
2891     }
2892 
2893     if (pTableView || pTopView)
2894     {
2895         if (pTableView)
2896             pTableView->InsertText( aRefStr, sal_True );
2897         if (pTopView)
2898             pTopView->InsertText( aRefStr, sal_True );
2899 
2900         DataChanged();
2901     }
2902 
2903     bSelIsRef = sal_True;
2904 }
2905 
InsertFunction(const String & rFuncName,sal_Bool bAddPar)2906 void ScInputHandler::InsertFunction( const String& rFuncName, sal_Bool bAddPar )
2907 {
2908     if ( eMode == SC_INPUT_NONE )
2909     {
2910         DBG_ERROR("InsertFunction, nicht im Eingabemodus");
2911         return;
2912     }
2913 
2914     UpdateActiveView();
2915     if (!pTableView && !pTopView)
2916         return;                             // z.B. FillMode
2917 
2918     DataChanging();                         // kann nicht neu sein
2919 
2920     String aText = rFuncName;
2921     if (bAddPar)
2922         aText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
2923 
2924     if (pTableView)
2925     {
2926         pTableView->InsertText( aText, sal_False );
2927         if (bAddPar)
2928         {
2929             ESelection aSel = pTableView->GetSelection();
2930             --aSel.nStartPos;
2931             --aSel.nEndPos;
2932             pTableView->SetSelection(aSel);
2933         }
2934     }
2935     if (pTopView)
2936     {
2937         pTopView->InsertText( aText, sal_False );
2938         if (bAddPar)
2939         {
2940             ESelection aSel = pTopView->GetSelection();
2941             --aSel.nStartPos;
2942             --aSel.nEndPos;
2943             pTopView->SetSelection(aSel);
2944         }
2945     }
2946 
2947     DataChanged();
2948 
2949     if (bAddPar)
2950         AutoParAdded();
2951 }
2952 
ClearText()2953 void ScInputHandler::ClearText()
2954 {
2955     if ( eMode == SC_INPUT_NONE )
2956     {
2957         DBG_ERROR("ClearText, nicht im Eingabemodus");
2958         return;
2959     }
2960 
2961     UpdateActiveView();
2962     if (!pTableView && !pTopView)
2963         return;                             // z.B. FillMode
2964 
2965     DataChanging();                         // darf nicht neu sein
2966 
2967     String aEmpty;
2968     if (pTableView)
2969     {
2970         pTableView->GetEditEngine()->SetText( aEmpty );
2971         pTableView->SetSelection( ESelection(0,0, 0,0) );
2972     }
2973     if (pTopView)
2974     {
2975         pTopView->GetEditEngine()->SetText( aEmpty );
2976         pTopView->SetSelection( ESelection(0,0, 0,0) );
2977     }
2978 
2979     DataChanged();
2980 }
2981 
KeyInput(const KeyEvent & rKEvt,sal_Bool bStartEdit)2982 sal_Bool ScInputHandler::KeyInput( const KeyEvent& rKEvt, sal_Bool bStartEdit /* = sal_False */ )
2983 {
2984     if (!bOptLoaded)
2985     {
2986         bAutoComplete = SC_MOD()->GetAppOptions().GetAutoComplete();
2987         bOptLoaded = sal_True;
2988     }
2989 
2990     KeyCode aCode = rKEvt.GetKeyCode();
2991     sal_uInt16 nModi  = aCode.GetModifier();
2992     sal_Bool bShift   = aCode.IsShift();
2993     sal_Bool bControl = aCode.IsMod1();
2994     sal_Bool bAlt     = aCode.IsMod2();
2995     sal_uInt16 nCode  = aCode.GetCode();
2996     sal_Unicode nChar = rKEvt.GetCharCode();
2997 
2998     //  Alt-Return is accepted, everything else with ALT, or CTRL-TAB are not:
2999     if (( bAlt && !bControl && nCode != KEY_RETURN ) ||
3000             ( bControl && aCode.GetCode() == KEY_TAB ))
3001         return sal_False;
3002 
3003     sal_Bool bInputLine = ( eMode==SC_INPUT_TOP );
3004 
3005     sal_Bool bUsed = sal_False;
3006     sal_Bool bSkip = sal_False;
3007     sal_Bool bDoEnter = sal_False;
3008 
3009     switch ( nCode )
3010     {
3011         case KEY_RETURN:
3012             if (bControl && !bShift && !bInputLine)
3013                 bDoEnter = sal_True;
3014             else if ( nModi == 0 && nTipVisible && pFormulaData && nAutoPos != SCPOS_INVALID )
3015             {
3016                 PasteFunctionData();
3017                 bUsed = sal_True;
3018             }
3019             else if ( nModi == 0 && nTipVisible && aManualTip.Len() )
3020             {
3021                 PasteManualTip();
3022                 bUsed = sal_True;
3023             }
3024             else
3025             {
3026                 sal_uInt8 nMode = SC_ENTER_NORMAL;
3027                 if ( bShift && bControl )
3028                     nMode = SC_ENTER_MATRIX;
3029                 else if ( bAlt )
3030                     nMode = SC_ENTER_BLOCK;
3031                 EnterHandler( nMode );
3032 
3033                 if (pActiveViewSh)
3034                     pActiveViewSh->MoveCursorEnter( bShift && !bControl );
3035 
3036                 bUsed = sal_True;
3037             }
3038             break;
3039         case KEY_TAB:
3040             if (!bControl && !bAlt)
3041             {
3042                 if ( pFormulaData && nTipVisible && nAutoPos != SCPOS_INVALID )
3043                 {
3044                     //  blaettern
3045 
3046                     NextFormulaEntry( bShift );
3047                 }
3048                 else if ( pColumnData && bUseTab && nAutoPos != SCPOS_INVALID )
3049                 {
3050                     //  in den Eintraegen der AutoEingabe blaettern
3051 
3052                     NextAutoEntry( bShift );
3053                 }
3054                 else
3055                 {
3056                     EnterHandler();
3057 
3058                     //  TabKeyInput gibt auf manchen Rechnern unter W95 Stackueberlaeufe,
3059                     //  darum direkter Aufruf:
3060                     if (pActiveViewSh)
3061                         pActiveViewSh->FindNextUnprot( bShift );
3062                 }
3063                 bUsed = sal_True;
3064             }
3065             break;
3066         case KEY_ESCAPE:
3067             if ( nTipVisible )
3068             {
3069                 HideTip();
3070                 bUsed = sal_True;
3071             }
3072             else if( nTipVisibleSec )
3073             {
3074                 HideTipBelow();
3075                 bUsed = sal_True;
3076             }
3077             else if (eMode != SC_INPUT_NONE)
3078             {
3079                 CancelHandler();
3080                 bUsed = sal_True;
3081             }
3082             else
3083                 bSkip = sal_True;
3084             break;
3085         case KEY_F2:
3086             if ( !bShift && !bControl && !bAlt && eMode == SC_INPUT_TABLE )
3087             {
3088                 eMode = SC_INPUT_TYPE;
3089                 bUsed = sal_True;
3090             }
3091             break;
3092     }
3093 
3094     //  Cursortasten nur ausfuehren, wenn schon im Edit-Modus
3095     //  z.B. wegen Shift-Ctrl-PageDn (ist nicht als Accelerator definiert)
3096 
3097     sal_Bool bCursorKey = EditEngine::DoesKeyMoveCursor(rKEvt);
3098     sal_Bool bInsKey = ( nCode == KEY_INSERT && !nModi );   // Insert wie Cursortasten behandeln
3099     if ( !bUsed && !bSkip && ( bDoEnter || EditEngine::DoesKeyChangeText(rKEvt) ||
3100                     ( eMode != SC_INPUT_NONE && ( bCursorKey || bInsKey ) ) ) )
3101     {
3102         HideTip();
3103         HideTipBelow();
3104 
3105         if (bSelIsRef)
3106         {
3107             RemoveSelection();
3108             bSelIsRef = sal_False;
3109         }
3110 
3111         UpdateActiveView();
3112         sal_Bool bNewView = DataChanging( nChar );
3113 
3114         if (bProtected)                             // Zelle geschuetzt?
3115             bUsed = sal_True;                           // Key-Event nicht weiterleiten
3116         else                                        // Aenderungen erlaubt
3117         {
3118             if (bNewView )                          // neu anlegen
3119             {
3120                 if (pActiveViewSh)
3121                     pActiveViewSh->GetViewData()->GetDocShell()->PostEditView( pEngine, aCursorPos );
3122                 UpdateActiveView();
3123                 if (eMode==SC_INPUT_NONE)
3124                     if (pTableView || pTopView)
3125                     {
3126                         String aStrLoP;
3127 
3128                         if ( bStartEdit && bCellHasPercentFormat && ((nChar >= '0' && nChar <= '9') || nChar == '-') )
3129                             aStrLoP = '%';
3130 
3131                         if (pTableView)
3132                         {
3133                             pTableView->GetEditEngine()->SetText( aStrLoP );
3134                             if ( aStrLoP.Len() )
3135                                 pTableView->SetSelection( ESelection(0,0, 0,0) );   // before the '%'
3136 
3137                             // don't call SetSelection if the string is empty anyway,
3138                             // to avoid breaking the bInitial handling in ScViewData::EditGrowY
3139                         }
3140                         if (pTopView)
3141                         {
3142                             pTopView->GetEditEngine()->SetText( aStrLoP );
3143                             if ( aStrLoP.Len() )
3144                                 pTopView->SetSelection( ESelection(0,0, 0,0) );     // before the '%'
3145                         }
3146                     }
3147                 SyncViews();
3148             }
3149 
3150             if (pTableView || pTopView)
3151             {
3152 //              pActiveView->SetEditEngineUpdateMode(sal_True);         //! gibt Muell !!!!
3153 
3154                 if (bDoEnter)
3155                 {
3156                     if (pTableView)
3157                         if( pTableView->PostKeyEvent( KeyEvent( CHAR_CR, KeyCode(KEY_RETURN) ) ) )
3158                             bUsed = sal_True;
3159                     if (pTopView)
3160                         if( pTopView->PostKeyEvent( KeyEvent( CHAR_CR, KeyCode(KEY_RETURN) ) ) )
3161                             bUsed = sal_True;
3162                 }
3163                 else if ( nAutoPar && nChar == ')' && CursorAtClosingPar() )
3164                 {
3165                     SkipClosingPar();
3166                     bUsed = sal_True;
3167                 }
3168                 else
3169                 {
3170                     if (pTableView)
3171                         if ( pTableView->PostKeyEvent( rKEvt ) )
3172                             bUsed = sal_True;
3173                     if (pTopView)
3174                         if ( pTopView->PostKeyEvent( rKEvt ) )
3175                             bUsed = sal_True;
3176                 }
3177 
3178                 //  Auto-Eingabe:
3179 
3180                 if ( bUsed && bAutoComplete )
3181                 {
3182                     bUseTab = sal_False;
3183                     nAutoPos = SCPOS_INVALID;                       // do not search further
3184 
3185                     KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
3186                     if ( nChar && nChar != 8 && nChar != 127 &&     // no 'backspace', no 'delete'
3187                          KEYFUNC_CUT != eFunc)                      // and no 'CTRL-X'
3188                     {
3189                         if (bFormulaMode)
3190                             UseFormulaData();
3191                         else
3192                             UseColData();
3193                     }
3194                 }
3195 
3196                 //  when the selection is changed manually or an opening parenthesis
3197                 //  is typed, stop overwriting parentheses
3198                 if ( bUsed && nChar == '(' )
3199                     ResetAutoPar();
3200 
3201                 if ( KEY_INSERT == nCode )
3202                 {
3203                     SfxViewFrame* pViewFrm = SfxViewFrame::Current();
3204                     if (pViewFrm)
3205                         pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
3206                 }
3207                 if( bUsed && bFormulaMode && ( bCursorKey || bInsKey || nCode == KEY_DELETE || nCode == KEY_BACKSPACE ) )
3208                 {
3209                     ShowTipCursor();
3210                 }
3211             }
3212 
3213             // #i114511# don't count cursor keys as modification
3214             sal_Bool bSetModified = !bCursorKey;
3215             DataChanged(sal_False, bSetModified);  // also calls UpdateParenthesis()
3216             InvalidateAttribs();        //! in DataChanged ?
3217         }
3218     }
3219 
3220     if (pTopView && eMode != SC_INPUT_NONE)
3221         SyncViews();
3222 
3223     return bUsed;
3224 }
3225 
InputCommand(const CommandEvent & rCEvt,sal_Bool bForce)3226 sal_Bool ScInputHandler::InputCommand( const CommandEvent& rCEvt, sal_Bool bForce )
3227 {
3228     sal_Bool bUsed = sal_False;
3229 
3230     if ( rCEvt.GetCommand() == COMMAND_CURSORPOS )
3231     {
3232         //  #90346# for COMMAND_CURSORPOS, do as little as possible, because
3233         //  with remote VCL, even a ShowCursor will generate another event.
3234         if ( eMode != SC_INPUT_NONE )
3235         {
3236             UpdateActiveView();
3237             if (pTableView || pTopView)
3238             {
3239                 if (pTableView)
3240                     pTableView->Command( rCEvt );
3241                 else if (pTopView)                      // call only once
3242                     pTopView->Command( rCEvt );
3243                 bUsed = sal_True;
3244             }
3245         }
3246     }
3247     else
3248     {
3249         if ( bForce || eMode != SC_INPUT_NONE )
3250         {
3251             if (!bOptLoaded)
3252             {
3253                 bAutoComplete = SC_MOD()->GetAppOptions().GetAutoComplete();
3254                 bOptLoaded = sal_True;
3255             }
3256 
3257             HideTip();
3258             HideTipBelow();
3259 
3260             if ( bSelIsRef )
3261             {
3262                 RemoveSelection();
3263                 bSelIsRef = sal_False;
3264             }
3265 
3266             UpdateActiveView();
3267             sal_Bool bNewView = DataChanging( 0, sal_True );
3268 
3269             if (bProtected)                             // cell protected
3270                 bUsed = sal_True;                           // event is used
3271             else                                        // changes allowed
3272             {
3273                 if (bNewView)                           // create new edit view
3274                 {
3275                     if (pActiveViewSh)
3276                         pActiveViewSh->GetViewData()->GetDocShell()->PostEditView( pEngine, aCursorPos );
3277                     UpdateActiveView();
3278                     if (eMode==SC_INPUT_NONE)
3279                         if (pTableView || pTopView)
3280                         {
3281                             String aStrLoP;
3282                             if (pTableView)
3283                             {
3284                                 pTableView->GetEditEngine()->SetText( aStrLoP );
3285                                 pTableView->SetSelection( ESelection(0,0, 0,0) );
3286                             }
3287                             if (pTopView)
3288                             {
3289                                 pTopView->GetEditEngine()->SetText( aStrLoP );
3290                                 pTopView->SetSelection( ESelection(0,0, 0,0) );
3291                             }
3292                         }
3293                     SyncViews();
3294                 }
3295 
3296                 if (pTableView || pTopView)
3297                 {
3298                     if (pTableView)
3299                         pTableView->Command( rCEvt );
3300                     if (pTopView)
3301                         pTopView->Command( rCEvt );
3302 
3303                     bUsed = sal_True;
3304 
3305                     if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
3306                     {
3307                         //  AutoInput after ext text input
3308 
3309                         nAutoPos = SCPOS_INVALID;
3310                         if (bFormulaMode)
3311                             UseFormulaData();
3312                         else
3313                             UseColData();
3314                     }
3315                 }
3316 
3317                 DataChanged();              //  calls UpdateParenthesis()
3318                 InvalidateAttribs();        //! in DataChanged ?
3319             }
3320         }
3321 
3322         if (pTopView && eMode != SC_INPUT_NONE)
3323             SyncViews();
3324     }
3325 
3326     return bUsed;
3327 }
3328 
NotifyChange(const ScInputHdlState * pState,sal_Bool bForce,ScTabViewShell * pSourceSh,sal_Bool bStopEditing)3329 void ScInputHandler::NotifyChange( const ScInputHdlState* pState,
3330                                    sal_Bool bForce, ScTabViewShell* pSourceSh,
3331                                    sal_Bool bStopEditing)
3332 {
3333     //  #62806# Wenn der Aufruf aus einem Makro-Aufruf im EnterHandler kommt,
3334     //  gleich abbrechen und nicht den Status durcheinander bringen
3335     if (bInEnterHandler)
3336         return;
3337 
3338     sal_Bool bRepeat = (pState == pLastState);
3339     if (!bRepeat && pState && pLastState)
3340         bRepeat = sal::static_int_cast<sal_Bool>(*pState == *pLastState);
3341     if (bRepeat && !bForce)
3342         return;
3343 
3344     bInOwnChange = sal_True;                // disable ModifyHdl (reset below)
3345 
3346     if ( pState && !pLastState )        // wieder enablen
3347         bForce = sal_True;
3348 
3349     sal_Bool bHadObject = pLastState && pLastState->GetEditData();
3350 
3351     //! Before EditEngine gets eventually created (so it gets the right pools)
3352     if ( pSourceSh )
3353         pActiveViewSh = pSourceSh;
3354     else
3355         pActiveViewSh = PTR_CAST(ScTabViewShell, SfxViewShell::Current());
3356 
3357     ImplCreateEditEngine();
3358 
3359     if ( pState != pLastState )
3360     {
3361         delete pLastState;
3362         pLastState = pState ? new ScInputHdlState( *pState ) : NULL;
3363     }
3364 
3365     if ( pState && pActiveViewSh )
3366     {
3367         ScModule* pScMod = SC_MOD();
3368 
3369         if ( pState )
3370         {
3371             sal_Bool bIgnore = sal_False;
3372 
3373             //  hier auch fremde Referenzeingabe beruecksichtigen (z.B. Funktions-AP),
3374             //  FormEditData falls gerade von der Hilfe auf Calc umgeschaltet wird:
3375 
3376             if ( !bFormulaMode && !pScMod->IsFormulaMode() && !pScMod->GetFormEditData() )
3377             {
3378                 if ( bModified )
3379                 {
3380                     if (pState->GetPos() != aCursorPos)
3381                     {
3382                         if (!bProtected)
3383                             EnterHandler();
3384                     }
3385                     else
3386                         bIgnore = sal_True;
3387                 }
3388 
3389                 if ( !bIgnore /* || bRepeat */ )
3390                 {
3391                     const ScAddress&        rSPos   = pState->GetStartPos();
3392                     const ScAddress&        rEPos   = pState->GetEndPos();
3393                     const EditTextObject*   pData   = pState->GetEditData();
3394                     String                  aString = pState->GetString();
3395                     sal_Bool                    bTxtMod = sal_False;
3396                     ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell();
3397                     ScDocument* pDoc = pDocSh->GetDocument();
3398 
3399                     aCursorPos  = pState->GetPos();
3400 
3401                     if ( pData /* || bRepeat */ )
3402                         bTxtMod = sal_True;
3403                     else if ( bHadObject )
3404                         bTxtMod = sal_True;
3405                     else if ( bTextValid )
3406                         bTxtMod = ( aString != aCurrentText );
3407                     else
3408                         bTxtMod = ( aString != GetEditText(pEngine) );
3409 
3410                     if ( bTxtMod || bForce )
3411                     {
3412                         if (pData)
3413                         {
3414                             pEngine->SetText( *pData );
3415                             aString = GetEditText(pEngine);
3416                             lcl_RemoveTabs(aString);
3417                             bTextValid = sal_False;
3418                             aCurrentText.Erase();
3419                         }
3420                         else
3421                         {
3422                             aCurrentText = aString;
3423                             bTextValid = sal_True;              //! erst nur als String merken
3424                         }
3425 
3426                         if ( pInputWin )
3427                             pInputWin->SetTextString(aString);
3428                     }
3429 
3430                     if ( pInputWin )                        // Bereichsanzeige
3431                     {
3432                         String aPosStr;
3433                         const ScAddress::Details aAddrDetails( pDoc, aCursorPos );
3434 
3435                         //  Ist der Bereich ein Name?
3436                         //! per Timer suchen ???
3437 
3438                         if ( pActiveViewSh )
3439                             pActiveViewSh->GetViewData()->GetDocument()->
3440                                 GetRangeAtBlock( ScRange( rSPos, rEPos ), &aPosStr );
3441 
3442                         if ( !aPosStr.Len() )           // kein Name -> formatieren
3443                         {
3444                             sal_uInt16 nFlags = 0;
3445                             if( aAddrDetails.eConv == formula::FormulaGrammar::CONV_XL_R1C1 )
3446                                 nFlags |= SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE;
3447                             if ( rSPos != rEPos )
3448                             {
3449                                 ScRange r(rSPos, rEPos);
3450                                 nFlags |= (nFlags << 4);
3451                                 r.Format( aPosStr, SCA_VALID | nFlags, pDoc, aAddrDetails );
3452                             }
3453                             else
3454                                 aCursorPos.Format( aPosStr, SCA_VALID | nFlags, pDoc, aAddrDetails );
3455                         }
3456                         // Disable the accessible VALUE_CHANGE event
3457                         sal_Bool bIsSuppressed = pInputWin->IsAccessibilityEventsSuppressed(sal_False);
3458                         pInputWin->SetAccessibilityEventsSuppressed(sal_True);
3459                         pInputWin->SetPosString(aPosStr);
3460                         pInputWin->SetAccessibilityEventsSuppressed(bIsSuppressed);
3461                         pInputWin->SetSumAssignMode();
3462                     }
3463 
3464                     if (bStopEditing)
3465                         SFX_APP()->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) );
3466 
3467                     //  As long as the content is not edited, turn off online spelling.
3468                     //  Online spelling is turned back on in StartTable, after setting
3469                     //  the right language from cell attributes.
3470 
3471                     sal_uLong nCntrl = pEngine->GetControlWord();
3472                     if ( nCntrl & EE_CNTRL_ONLINESPELLING )
3473                         pEngine->SetControlWord( nCntrl & ~EE_CNTRL_ONLINESPELLING );
3474 
3475                     bModified = sal_False;
3476                     bSelIsRef = sal_False;
3477                     bProtected = sal_False;
3478                     bCommandErrorShown = sal_False;
3479                 }
3480             }
3481         }
3482 
3483 //      bProtected = sal_False;
3484 
3485         if ( pInputWin)
3486         {
3487             if(!pScMod->IsFormulaMode()&& !pScMod->IsRefDialogOpen())   //BugID 54702
3488             {                                                           //Wenn RefDialog offen, dann nicht enablen
3489                 if ( !pInputWin->IsEnabled())
3490                 {
3491                     pInputWin->Enable();
3492                     if(pDelayTimer )
3493                     {
3494                         DELETEZ( pDelayTimer );
3495                     }
3496                 }
3497             }
3498             else if(pScMod->IsRefDialogOpen())
3499             {                                   // Da jedes Dokument eigenes InputWin hat, sollte
3500                 if ( !pDelayTimer )             // nochmals Timer gestartet werden, da sonst Ein-
3501                 {                               // gabezeile evt. noch aktiv ist.
3502                     pDelayTimer = new Timer;
3503                     pDelayTimer->SetTimeout( 500 ); // 100ms Verzoegerung
3504                     pDelayTimer->SetTimeoutHdl( LINK( this, ScInputHandler, DelayTimer ) );
3505                     pDelayTimer->Start();
3506                 }
3507             }
3508         }
3509     }
3510     else // !pState || !pActiveViewSh
3511     {
3512         if ( !pDelayTimer )
3513         {
3514             pDelayTimer = new Timer;
3515             pDelayTimer->SetTimeout( 500 ); // 100ms Verzoegerung
3516             pDelayTimer->SetTimeoutHdl( LINK( this, ScInputHandler, DelayTimer ) );
3517             pDelayTimer->Start();
3518         }
3519     }
3520 
3521     HideTip();
3522     HideTipBelow();
3523     bInOwnChange = sal_False;
3524 }
3525 
UpdateCellAdjust(SvxCellHorJustify eJust)3526 void ScInputHandler::UpdateCellAdjust( SvxCellHorJustify eJust )
3527 {
3528     eAttrAdjust = eJust;
3529     UpdateAdjust( 0 );
3530 }
3531 
ResetDelayTimer()3532 void ScInputHandler::ResetDelayTimer()
3533 {
3534     if(pDelayTimer!=NULL)
3535     {
3536         DELETEZ( pDelayTimer );
3537 
3538         if ( pInputWin)
3539         {
3540             pInputWin->Enable();
3541         }
3542     }
3543 }
3544 
IMPL_LINK(ScInputHandler,DelayTimer,Timer *,pTimer)3545 IMPL_LINK( ScInputHandler, DelayTimer, Timer*, pTimer )
3546 {
3547     if ( pTimer == pDelayTimer )
3548     {
3549         DELETEZ( pDelayTimer );
3550 
3551         if ( NULL == pLastState || SC_MOD()->IsFormulaMode() || SC_MOD()->IsRefDialogOpen())
3552         {
3553             //! new method at ScModule to query if function autopilot is open
3554 
3555             SfxViewFrame* pViewFrm = SfxViewFrame::Current();
3556             if ( pViewFrm && pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
3557             {
3558                 if ( pInputWin)
3559                 {
3560                     pInputWin->EnableButtons( sal_False );
3561                     pInputWin->Disable();
3562                 }
3563             }
3564             else if ( !bFormulaMode )   // #39210# Formel auch z.B. bei Hilfe behalten
3565             {
3566                 bInOwnChange = sal_True;    // disable ModifyHdl (reset below)
3567 
3568                 pActiveViewSh = NULL;
3569                 pEngine->SetText( EMPTY_STRING );
3570                 if ( pInputWin )
3571                 {
3572                     pInputWin->SetPosString( EMPTY_STRING );
3573                     pInputWin->SetTextString( EMPTY_STRING );
3574                     pInputWin->Disable();
3575                 }
3576 
3577                 bInOwnChange = sal_False;
3578             }
3579         }
3580     }
3581     return 0;
3582 }
3583 
InputSelection(EditView * pView)3584 void ScInputHandler::InputSelection( EditView* pView )
3585 {
3586     SyncViews( pView );
3587     ShowTipCursor();
3588     UpdateParenthesis();    //  Selektion geaendert -> Klammer-Hervorhebung neu
3589 
3590     //  when the selection is changed manually, stop overwriting parentheses
3591     ResetAutoPar();
3592 }
3593 
InputChanged(EditView * pView,sal_Bool bFromNotify)3594 void ScInputHandler::InputChanged( EditView* pView, sal_Bool bFromNotify )
3595 {
3596     ESelection aSelection = pView->GetSelection();
3597 
3598     UpdateActiveView();
3599 
3600     // #i20282# DataChanged needs to know if this is from the input line's modify handler
3601     sal_Bool bFromTopNotify = ( bFromNotify && pView == pTopView );
3602 
3603     sal_Bool bNewView = DataChanging();                     //! kann das hier ueberhaupt sein?
3604     aCurrentText = pView->GetEditEngine()->GetText();   // auch den String merken
3605     pEngine->SetText( aCurrentText );
3606     DataChanged( bFromTopNotify );
3607     bTextValid = sal_True;      // wird in DataChanged auf sal_False gesetzt
3608 
3609     if ( pActiveViewSh )
3610     {
3611         ScViewData* pViewData = pActiveViewSh->GetViewData();
3612         if ( bNewView )
3613             pViewData->GetDocShell()->PostEditView( pEngine, aCursorPos );
3614 
3615         pViewData->EditGrowY();
3616         pViewData->EditGrowX();
3617     }
3618 
3619     SyncViews( pView );
3620 }
3621 
GetEditString()3622 const String& ScInputHandler::GetEditString()
3623 {
3624     if (pEngine)
3625     {
3626         aCurrentText = pEngine->GetText();      // immer neu aus Engine
3627         bTextValid = sal_True;
3628     }
3629 
3630     return aCurrentText;
3631 }
3632 
GetTextSize()3633 Size ScInputHandler::GetTextSize()
3634 {
3635     Size aSize;
3636     if ( pEngine )
3637         aSize = Size( pEngine->CalcTextWidth(), pEngine->GetTextHeight() );
3638 
3639     return aSize;
3640 }
3641 
GetTextAndFields(ScEditEngineDefaulter & rDestEngine)3642 sal_Bool ScInputHandler::GetTextAndFields( ScEditEngineDefaulter& rDestEngine )
3643 {
3644     sal_Bool bRet = sal_False;
3645     if (pEngine)
3646     {
3647         //  Feldbefehle enthalten?
3648 
3649         sal_uInt16 nParCnt = pEngine->GetParagraphCount();
3650         SfxItemSet aSet = pEngine->GetAttribs( ESelection(0,0,nParCnt,0) );
3651         SfxItemState eFieldState = aSet.GetItemState( EE_FEATURE_FIELD, sal_False );
3652         if ( eFieldState == SFX_ITEM_DONTCARE || eFieldState == SFX_ITEM_SET )
3653         {
3654             //  Inhalt kopieren
3655 
3656             EditTextObject* pObj = pEngine->CreateTextObject();
3657             rDestEngine.SetText(*pObj);
3658             delete pObj;
3659 
3660             //  Attribute loeschen
3661 
3662             for (sal_uInt16 i=0; i<nParCnt; i++)
3663                 rDestEngine.QuickRemoveCharAttribs( i );
3664 
3665             //  Absaetze zusammenfassen
3666 
3667             while ( nParCnt > 1 )
3668             {
3669                 xub_StrLen nLen = rDestEngine.GetTextLen( (sal_uInt16)0 );
3670                 ESelection aSel( 0,nLen, 1,0 );
3671                 rDestEngine.QuickInsertText( ' ', aSel );       // Umbruch durch Space ersetzen
3672                 --nParCnt;
3673             }
3674 
3675             bRet = sal_True;
3676         }
3677     }
3678     return bRet;
3679 }
3680 
3681 
3682 //------------------------------------------------------------------------
3683 // Methoden fuer FunktionsAutopiloten:
3684 // InputGetSelection, InputSetSelection, InputReplaceSelection, InputGetFormulaStr
3685 //------------------------------------------------------------------------
3686 
InputGetSelection(xub_StrLen & rStart,xub_StrLen & rEnd)3687 void ScInputHandler::InputGetSelection( xub_StrLen& rStart, xub_StrLen& rEnd )
3688 {
3689     rStart = nFormSelStart;
3690     rEnd = nFormSelEnd;
3691 }
3692 
3693 //------------------------------------------------------------------------
3694 
GetFuncEditView()3695 EditView* ScInputHandler::GetFuncEditView()
3696 {
3697     UpdateActiveView();     // wegen pTableView
3698 
3699     EditView* pView = NULL;
3700     if ( pInputWin )
3701     {
3702         pInputWin->MakeDialogEditView();
3703         pView = pInputWin->GetEditView();
3704     }
3705     else
3706     {
3707         if ( eMode != SC_INPUT_TABLE )
3708         {
3709             bCreatingFuncView = sal_True;       // RangeFinder nicht anzeigen
3710             SetMode( SC_INPUT_TABLE );
3711             bCreatingFuncView = sal_False;
3712             if ( pTableView )
3713                 pTableView->GetEditEngine()->SetText( EMPTY_STRING );
3714         }
3715         pView = pTableView;
3716     }
3717 
3718     return pView;
3719 }
3720 
3721 //------------------------------------------------------------------------
3722 
InputSetSelection(xub_StrLen nStart,xub_StrLen nEnd)3723 void ScInputHandler::InputSetSelection( xub_StrLen nStart, xub_StrLen nEnd )
3724 {
3725     if ( nStart <= nEnd )
3726     {
3727         nFormSelStart = nStart;
3728         nFormSelEnd = nEnd;
3729     }
3730     else
3731     {
3732         nFormSelEnd = nStart;
3733         nFormSelStart = nEnd;
3734     }
3735 
3736     EditView* pView = GetFuncEditView();
3737     if (pView)
3738         pView->SetSelection( ESelection(0,nStart, 0,nEnd) );
3739 
3740     bModified = sal_True;
3741 }
3742 
3743 //------------------------------------------------------------------------
3744 
InputReplaceSelection(const String & rStr)3745 void ScInputHandler::InputReplaceSelection( const String& rStr )
3746 {
3747     if (!pRefViewSh)
3748         pRefViewSh = pActiveViewSh;
3749 
3750     DBG_ASSERT(nFormSelEnd>=nFormSelStart,"Selektion kaputt...");
3751 
3752     xub_StrLen nOldLen = nFormSelEnd-nFormSelStart;
3753     xub_StrLen nNewLen = rStr.Len();
3754     if (nOldLen)
3755         aFormText.Erase( nFormSelStart, nOldLen );
3756     if (nNewLen)
3757         aFormText.Insert( rStr, nFormSelStart );
3758     nFormSelEnd = nFormSelStart + nNewLen;
3759 
3760     EditView* pView = GetFuncEditView();
3761     if (pView)
3762     {
3763         pView->SetEditEngineUpdateMode( sal_False );
3764 //      pView->InsertText( rStr, sal_True );
3765         pView->GetEditEngine()->SetText( aFormText );
3766         pView->SetSelection( ESelection(0,nFormSelStart, 0,nFormSelEnd) );
3767         pView->SetEditEngineUpdateMode( sal_True );
3768     }
3769     bModified = sal_True;
3770 }
3771 
3772 //------------------------------------------------------------------------
3773 
InputGetFormulaStr()3774 String ScInputHandler::InputGetFormulaStr()
3775 {
3776     return aFormText;   //! eigene Membervariable?
3777 }
3778 
3779 //========================================================================
3780 //  ScInputHdlState
3781 //========================================================================
3782 
ScInputHdlState(const ScAddress & rCurPos,const ScAddress & rStartPos,const ScAddress & rEndPos,const String & rString,const EditTextObject * pData)3783 ScInputHdlState::ScInputHdlState( const ScAddress& rCurPos,
3784                                   const ScAddress& rStartPos,
3785                                   const ScAddress& rEndPos,
3786                                   const String& rString,
3787                                   const EditTextObject* pData )
3788     :   aCursorPos  ( rCurPos ),
3789         aStartPos   ( rStartPos ),
3790         aEndPos     ( rEndPos ),
3791         aString     ( rString ),
3792         pEditData   ( pData ? pData->Clone() : NULL )
3793 {
3794 }
3795 
3796 //------------------------------------------------------------------------
3797 
ScInputHdlState(const ScInputHdlState & rCpy)3798 ScInputHdlState::ScInputHdlState( const ScInputHdlState& rCpy )
3799     :   pEditData   ( NULL )
3800 {
3801     *this = rCpy;
3802 }
3803 
3804 //------------------------------------------------------------------------
3805 
~ScInputHdlState()3806 ScInputHdlState::~ScInputHdlState()
3807 {
3808     delete pEditData;
3809 }
3810 
3811 //------------------------------------------------------------------------
3812 
operator ==(const ScInputHdlState & r) const3813 int ScInputHdlState::operator==( const ScInputHdlState& r ) const
3814 {
3815     return (    (aStartPos  == r.aStartPos)
3816              && (aEndPos    == r.aEndPos)
3817              && (aCursorPos == r.aCursorPos)
3818              && (aString    == r.aString)
3819              && ScGlobal::EETextObjEqual( pEditData, r.pEditData ) );
3820 }
3821 
3822 //------------------------------------------------------------------------
3823 
operator =(const ScInputHdlState & r)3824 ScInputHdlState& ScInputHdlState::operator=( const ScInputHdlState& r )
3825 {
3826     delete pEditData;
3827 
3828     aCursorPos  = r.aCursorPos;
3829     aStartPos   = r.aStartPos;
3830     aEndPos     = r.aEndPos;
3831     aString     = r.aString;
3832     pEditData   = r.pEditData ? r.pEditData->Clone() : NULL;
3833 
3834     return *this;
3835 }
3836 
3837 
3838 
3839 
3840