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