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