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