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