xref: /trunk/main/sc/source/ui/app/inputhdl.cxx (revision c2eaa082)
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_uInt32 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_uInt32 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_uInt32 nCount = pEngine->GetParagraphCount();
1624 							for (sal_uInt32 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_uInt32 nCount = pEngine->GetParagraphCount();
1651 		for (sal_uInt32 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_uInt32 nCount = pEngine->GetParagraphCount();
1812 	for (sal_uInt32 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_uInt32 nCount = pEngine->GetParagraphCount();	// koennte gerade neu eingefuegt worden sein
1848 	for (sal_uInt32 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_uInt32 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(0).GetChar(0) == '=' ||
2180            pEngine->GetText(0).GetChar(0) == '+' ||
2181            pEngine->GetText(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_uInt32 nPara    = pEngine->GetParagraphCount()-1;
2334 		xub_StrLen nLen = pEngine->GetText(nPara).Len();
2335 		sal_uInt16 nCount   = pEngine->GetViewCount();
2336 
2337 		for (sal_uInt32 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_uInt32 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_uInt32 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_uInt32 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_uInt32 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( 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