LibreOffice Module sc (master) 1
inputhdl.cxx
Go to the documentation of this file.
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 <iterator>
21#include <memory>
22#include <string_view>
23
24#include <inputhdl.hxx>
25#include <scitems.hxx>
26#include <editeng/eeitem.hxx>
27
28#include <sfx2/app.hxx>
29#include <editeng/acorrcfg.hxx>
32#include <editeng/brushitem.hxx>
33#include <svtools/colorcfg.hxx>
34#include <editeng/colritem.hxx>
35#include <editeng/editobj.hxx>
36#include <editeng/editstat.hxx>
37#include <editeng/editview.hxx>
38#include <editeng/langitem.hxx>
39#include <editeng/svxacorr.hxx>
40#include <editeng/unolingu.hxx>
41#include <editeng/wghtitem.hxx>
44#include <sfx2/bindings.hxx>
45#include <sfx2/viewfrm.hxx>
46#include <sfx2/docfile.hxx>
47#include <sfx2/printer.hxx>
48#include <svl/numformat.hxx>
49#include <svl/zforlist.hxx>
52#include <utility>
53#include <vcl/help.hxx>
55#include <vcl/commandevent.hxx>
56#include <vcl/cursor.hxx>
57#include <vcl/settings.hxx>
58#include <vcl/svapp.hxx>
59#include <tools/urlobj.hxx>
61#include <formula/funcvarargs.h>
62#include <LibreOfficeKit/LibreOfficeKitEnums.h>
63#include <comphelper/lok.hxx>
64#include <osl/diagnose.h>
65
66#include <attrib.hxx>
67#include <inputwin.hxx>
68#include <tabvwsh.hxx>
69#include <docsh.hxx>
70#include <scmod.hxx>
71#include <formulaopt.hxx>
72#include <uiitems.hxx>
73#include <global.hxx>
74#include <sc.hrc>
75#include <globstr.hrc>
76#include <scresid.hxx>
77#include <patattr.hxx>
78#include <viewdata.hxx>
79#include <document.hxx>
80#include <docpool.hxx>
81#include <editutil.hxx>
82#include <appoptio.hxx>
83#include <docoptio.hxx>
84#include <validat.hxx>
85#include <rfindlst.hxx>
86#include <inputopt.hxx>
87#include <simpleformulacalc.hxx>
88#include <compiler.hxx>
89#include <editable.hxx>
90#include <funcdesc.hxx>
91#include <markdata.hxx>
92#include <tokenarray.hxx>
93#include <gridwin.hxx>
94#include <output.hxx>
95#include <fillinfo.hxx>
96
97// Maximum Ranges in RangeFinder
98#define RANGEFIND_MAX 128
99
100using namespace formula;
101
102namespace {
103
104ScTypedCaseStrSet::const_iterator findText(
105 const ScTypedCaseStrSet& rDataSet, ScTypedCaseStrSet::const_iterator const & itPos,
106 const OUString& rStart, OUString& rResult, bool bBack)
107{
108 auto lIsMatch = [&rStart](const ScTypedStrData& rData) {
109 return (rData.GetStringType() != ScTypedStrData::Value) && ScGlobal::GetTransliteration().isMatch(rStart, rData.GetString()); };
110
111 if (bBack) // Backwards
112 {
113 ScTypedCaseStrSet::const_reverse_iterator it = rDataSet.rbegin(), itEnd = rDataSet.rend();
114 if (itPos != rDataSet.end())
115 {
116 size_t nPos = std::distance(rDataSet.begin(), itPos);
117 size_t nRPos = rDataSet.size() - 1 - nPos;
118 std::advance(it, nRPos);
119 ++it;
120 }
121
122 it = std::find_if(it, itEnd, lIsMatch);
123 if (it != itEnd)
124 {
125 rResult = it->GetString();
126 return (++it).base(); // convert the reverse iterator back to iterator.
127 }
128 }
129 else // Forwards
130 {
131 ScTypedCaseStrSet::const_iterator it = rDataSet.begin(), itEnd = rDataSet.end();
132 if (itPos != itEnd)
133 {
134 it = std::next(itPos);
135 }
136
137 it = std::find_if(it, itEnd, lIsMatch);
138 if (it != itEnd)
139 {
140 rResult = it->GetString();
141 return it;
142 }
143 }
144
145 return rDataSet.end(); // no matching text found
146}
147
148OUString getExactMatch(const ScTypedCaseStrSet& rDataSet, const OUString& rString)
149{
150 auto it = std::find_if(rDataSet.begin(), rDataSet.end(),
151 [&rString](const ScTypedStrData& rData) {
152 return (rData.GetStringType() != ScTypedStrData::Value)
153 && ScGlobal::GetTransliteration().isEqual(rData.GetString(), rString);
154 });
155 if (it != rDataSet.end())
156 return it->GetString();
157 return rString;
158}
159
160// This assumes that rResults is a sorted ring w.r.t ScTypedStrData::LessCaseInsensitive() or
161// in the reverse direction, whose origin is specified by nRingOrigin.
162sal_Int32 getLongestCommonPrefixLength(const std::vector<OUString>& rResults, std::u16string_view aUserEntry, sal_Int32 nRingOrigin)
163{
164 sal_Int32 nResults = rResults.size();
165 if (!nResults)
166 return 0;
167
168 if (nResults == 1)
169 return rResults[0].getLength();
170
171 sal_Int32 nMinLen = aUserEntry.size();
172 sal_Int32 nLastIdx = nRingOrigin ? nRingOrigin - 1 : nResults - 1;
173 const OUString& rFirst = rResults[nRingOrigin];
174 const OUString& rLast = rResults[nLastIdx];
175 const sal_Int32 nMaxLen = std::min(rFirst.getLength(), rLast.getLength());
176
177 for (sal_Int32 nLen = nMaxLen; nLen > nMinLen; --nLen)
178 {
179 if (ScGlobal::GetTransliteration().isMatch(rFirst.copy(0, nLen), rLast))
180 return nLen;
181 }
182
183 return nMinLen;
184}
185
186ScTypedCaseStrSet::const_iterator findTextAll(
187 const ScTypedCaseStrSet& rDataSet, ScTypedCaseStrSet::const_iterator const & itPos,
188 const OUString& rStart, ::std::vector< OUString > &rResultVec, bool bBack, sal_Int32* pLongestPrefixLen = nullptr)
189{
190 rResultVec.clear(); // clear contents
191
192 if (!rDataSet.size())
193 return rDataSet.end();
194
195 sal_Int32 nRingOrigin = 0;
196 size_t nCount = 0;
197 ScTypedCaseStrSet::const_iterator retit;
198 if ( bBack ) // Backwards
199 {
200 ScTypedCaseStrSet::const_reverse_iterator it, itEnd;
201 if ( itPos == rDataSet.end() )
202 {
203 it = rDataSet.rend();
204 --it;
205 itEnd = it;
206 }
207 else
208 {
209 it = rDataSet.rbegin();
210 size_t nPos = std::distance(rDataSet.begin(), itPos);
211 size_t nRPos = rDataSet.size() - 1 - nPos; // if itPos == rDataSet.end(), then nRPos = -1
212 std::advance(it, nRPos);
213 if ( it == rDataSet.rend() )
214 it = rDataSet.rbegin();
215 itEnd = it;
216 }
217 bool bFirstTime = true;
218
219 while ( it != itEnd || bFirstTime )
220 {
221 ++it;
222 if ( it == rDataSet.rend() ) // go to the first if reach the end
223 {
224 it = rDataSet.rbegin();
225 nRingOrigin = nCount;
226 }
227
228 if ( bFirstTime )
229 bFirstTime = false;
230 const ScTypedStrData& rData = *it;
231 if ( rData.GetStringType() == ScTypedStrData::Value )
232 // skip values
233 continue;
234
235 if ( !ScGlobal::GetTransliteration().isMatch(rStart, rData.GetString()) )
236 // not a match
237 continue;
238
239 rResultVec.push_back(rData.GetString()); // set the match data
240 if ( nCount == 0 ) // convert the reverse iterator back to iterator.
241 {
242 // actually we want to do "retit = it;".
243 retit = rDataSet.begin();
244 size_t nRPos = std::distance(rDataSet.rbegin(), it);
245 size_t nPos = rDataSet.size() - 1 - nRPos;
246 std::advance(retit, nPos);
247 }
248 ++nCount;
249 }
250 }
251 else // Forwards
252 {
253 ScTypedCaseStrSet::const_iterator it, itEnd;
254 it = itPos;
255 if ( it == rDataSet.end() )
256 it = --rDataSet.end();
257 itEnd = it;
258 bool bFirstTime = true;
259
260 while ( it != itEnd || bFirstTime )
261 {
262 ++it;
263 if ( it == rDataSet.end() ) // go to the first if reach the end
264 {
265 it = rDataSet.begin();
266 nRingOrigin = nCount;
267 }
268
269 if ( bFirstTime )
270 bFirstTime = false;
271 const ScTypedStrData& rData = *it;
272 if ( rData.GetStringType() == ScTypedStrData::Value )
273 // skip values
274 continue;
275
276 if ( !ScGlobal::GetTransliteration().isMatch(rStart, rData.GetString()) )
277 // not a match
278 continue;
279
280 rResultVec.push_back(rData.GetString()); // set the match data
281 if ( nCount == 0 )
282 retit = it; // remember first match iterator
283 ++nCount;
284 }
285 }
286
287 if (pLongestPrefixLen)
288 {
289 if (nRingOrigin >= static_cast<sal_Int32>(nCount))
290 {
291 // All matches were picked when rDataSet was read in one direction.
292 nRingOrigin = 0;
293 }
294 // rResultsVec is a sorted ring with nRingOrigin "origin".
295 // The direction of sorting is not important for getLongestCommonPrefixLength.
296 *pLongestPrefixLen = getLongestCommonPrefixLength(rResultVec, rStart, nRingOrigin);
297 }
298
299 if ( nCount > 0 ) // at least one function has matched
300 return retit;
301 return rDataSet.end(); // no matching text found
302}
303
304}
305
307 const std::vector<ReferenceMark>& rReferenceMarks )
308{
309 if ( !pViewShell )
310 return;
311
312 bool bSend = false;
313
315
316 ss << "{ \"marks\": [ ";
317
318 for ( size_t i = 0; i < rReferenceMarks.size(); i++ )
319 {
320 if ( rReferenceMarks[i].Is() )
321 {
322 if ( bSend )
323 ss << ", ";
324
325 ss << "{ \"rectangle\": \""
326 << rReferenceMarks[i].nX << ", "
327 << rReferenceMarks[i].nY << ", "
328 << rReferenceMarks[i].nWidth << ", "
329 << rReferenceMarks[i].nHeight << "\", "
330 "\"color\": \"" << rReferenceMarks[i].aColor.AsRGBHexString() << "\", "
331 "\"part\": \"" << rReferenceMarks[i].nTab << "\" } ";
332
333 bSend = true;
334 }
335 }
336
337 ss << " ] }";
338
339 OString aPayload( ss.str() );
340 pViewShell->libreOfficeKitViewCallback(
341 LOK_CALLBACK_REFERENCE_MARKS, aPayload );
342}
343
344static inline void incPos( const sal_Unicode c, sal_Int32& rPos, ESelection& rSel )
345{
346 ++rPos;
347 if (c == '\n')
348 {
349 ++rSel.nEndPara;
350 rSel.nEndPos = 0;
351 }
352 else
353 {
354 ++rSel.nEndPos;
355 }
356}
357
358void ScInputHandler::InitRangeFinder( const OUString& rFormula )
359{
361 if ( !pActiveViewSh || !SC_MOD()->GetInputOptions().GetRangeFinder() )
362 return;
364 ScDocument& rDoc = pDocSh->GetDocument();
365 const sal_Unicode cSheetSep = rDoc.GetSheetSeparator();
366
367 OUString aDelimiters = ScEditUtil::ModifyDelimiters(" !~%\"\t\n");
368 // delimiters (in addition to ScEditUtil): only characters that are
369 // allowed in formulas next to references and the quotation mark (so
370 // string constants can be skipped)
371
372 sal_Int32 nColon = aDelimiters.indexOf( ':' );
373 if ( nColon != -1 )
374 aDelimiters = aDelimiters.replaceAt( nColon, 1, u""); // Delimiter without colon
375 sal_Int32 nDot = aDelimiters.indexOf(cSheetSep);
376 if ( nDot != -1 )
377 aDelimiters = aDelimiters.replaceAt( nDot, 1 , u""); // Delimiter without dot
378
379 const sal_Unicode* pChar = rFormula.getStr();
380 sal_Int32 nLen = rFormula.getLength();
381 sal_Int32 nPos = 0;
382 sal_Int32 nStart = 0;
383 ESelection aSel;
384 sal_uInt16 nCount = 0;
385 ScRange aRange;
386 while ( nPos < nLen && nCount < RANGEFIND_MAX )
387 {
388 // Skip separator
389 while ( nPos<nLen && ScGlobal::UnicodeStrChr( aDelimiters.getStr(), pChar[nPos] ) )
390 {
391 if ( pChar[nPos] == '"' ) // String
392 {
393 incPos( pChar[nPos], nPos, aSel);
394 while (nPos<nLen && pChar[nPos] != '"') // Skip until end
395 incPos( pChar[nPos], nPos, aSel);
396 }
397 incPos( pChar[nPos], nPos, aSel); // Separator or closing quote
398 }
399
400 // Text between separators. We only consider within one line/paragraph.
401 aSel.nStartPara = aSel.nEndPara;
402 aSel.nStartPos = aSel.nEndPos;
403 nStart = nPos;
404handle_r1c1:
405 {
406 bool bSingleQuoted = false;
407 while (nPos < nLen)
408 {
409 // tdf#114113: handle addresses with quoted sheet names like "'Sheet 1'.A1"
410 // Literal single quotes in sheet names are masked by another single quote
411 if (pChar[nPos] == '\'')
412 {
413 bSingleQuoted = !bSingleQuoted;
414 }
415 else if (!bSingleQuoted) // Get everything in single quotes, including separators
416 {
417 if (ScGlobal::UnicodeStrChr(aDelimiters.getStr(), pChar[nPos]))
418 break;
419 }
420 incPos( pChar[nPos], nPos, aSel);
421 }
422 }
423
424 // for R1C1 '-' in R[-]... or C[-]... are not delimiters
425 // Nothing heroic here to ensure that there are '[]' around a negative
426 // integer. we need to clean up this code.
427 if( nPos < nLen && nPos > 0 &&
428 '-' == pChar[nPos] && '[' == pChar[nPos-1] &&
430 {
431 incPos( pChar[nPos], nPos, aSel);
432 goto handle_r1c1;
433 }
434
435 if ( nPos > nStart )
436 {
437 OUString aTest = rFormula.copy( nStart, nPos-nStart );
438 const ScAddress::Details aAddrDetails( rDoc, aCursorPos );
439 ScRefFlags nFlags = aRange.ParseAny( aTest, rDoc, aAddrDetails );
440 if ( nFlags & ScRefFlags::VALID )
441 {
442 // Set tables if not specified
443 if ( (nFlags & ScRefFlags::TAB_3D) == ScRefFlags::ZERO)
445 if ( (nFlags & ScRefFlags::TAB2_3D) == ScRefFlags::ZERO)
446 aRange.aEnd.SetTab( aRange.aStart.Tab() );
447
450 {
451 // #i73766# if a single ref was parsed, set the same "abs" flags for ref2,
452 // so Format doesn't output a double ref because of different flags.
454 applyStartToEndFlags(nFlags, nAbsFlags);
455 }
456
457 if (!nCount)
458 {
459 mpEditEngine->SetUpdateLayout( false );
460 pRangeFindList.reset(new ScRangeFindList( pDocSh->GetTitle() ));
461 }
462
463 Color nColor = pRangeFindList->Insert( ScRangeFindData( aRange, nFlags, aSel));
464
465 SfxItemSet aSet( mpEditEngine->GetEmptyItemSet() );
466 aSet.Put( SvxColorItem( nColor, EE_CHAR_COLOR ) );
467 mpEditEngine->QuickSetAttribs( aSet, aSel );
468 ++nCount;
469 }
470 }
471
472 // Do not skip last separator; could be a quote (?)
473 }
474
476
477 if (nCount)
478 {
479 mpEditEngine->SetUpdateLayout( true );
480
481 pDocSh->Broadcast( SfxHint( SfxHintId::ScShowRangeFinder ) );
482 }
483}
484
487 tools::Long nTab, const Color& rColor )
488{
489 ScSplitPos eWhich = rViewData.GetActivePart();
490
491 // This method is LOK specific.
493 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
494 {
495 SCCOL nCol1 = nX1, nCol2 = nX2;
496 SCROW nRow1 = nY1, nRow2 = nY2;
497 PutInOrder(nCol1, nCol2);
498 PutInOrder(nRow1, nRow2);
499 if (nCol1 == nCol2 && nRow1 == nRow2)
500 pDocSh->GetDocument().ExtendMerge(nCol1, nRow1, nCol2, nRow2, nTab);
501
502 Point aTopLeft = rViewData.GetPrintTwipsPos(nCol1, nRow1);
503 Point aBottomRight = rViewData.GetPrintTwipsPos(nCol2 + 1, nRow2 + 1);
504 tools::Long nSizeX = aBottomRight.X() - aTopLeft.X() - 1;
505 tools::Long nSizeY = aBottomRight.Y() - aTopLeft.Y() - 1;
506
507 return ReferenceMark(aTopLeft.X(), aTopLeft.Y(), nSizeX, nSizeY, nTab, rColor);
508 }
509
510 Point aScrPos = rViewData.GetScrPos( nX1, nY1, eWhich );
511 tools::Long nScrX = aScrPos.X();
512 tools::Long nScrY = aScrPos.Y();
513
514 double nPPTX = rViewData.GetPPTX();
515 double nPPTY = rViewData.GetPPTY();
516
517 Fraction aZoomX = rViewData.GetZoomX();
518 Fraction aZoomY = rViewData.GetZoomY();
519
520 ScTableInfo aTabInfo;
521 pDocSh->GetDocument().FillInfo( aTabInfo, nX1, nY1, nX2, nY2,
522 nTab, nPPTX, nPPTY, false, false );
523
524 ScOutputData aOutputData( nullptr, OUTTYPE_WINDOW, aTabInfo,
525 &( pDocSh->GetDocument() ), nTab,
526 nScrX, nScrY,
527 nX1, nY1, nX2, nY2,
528 nPPTX, nPPTY,
529 &aZoomX, &aZoomY );
530
531 return aOutputData.FillReferenceMark( nX1, nY1, nX2, nY2,
532 rColor );
533}
534
536{
538 return;
539
541 : dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
542
543 if (!pShell)
544 return;
545
546 ScViewData& rViewData = pShell->GetViewData();
547 ScDocShell* pDocSh = rViewData.GetDocShell();
548 ScRangeFindList* pRangeFinder = GetRangeFindList();
549
550 if ( !pRangeFinder && !rViewData.IsRefMode() )
551 return;
552
553 sal_uInt16 nAdditionalMarks = 0;
554 std::vector<ReferenceMark> aReferenceMarks( 1 );
555
556 if ( rViewData.IsRefMode() )
557 {
558 nAdditionalMarks = 1;
559
560 const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
561 Color aRefColor( rColorCfg.GetColorValue( svtools::CALCREFERENCE ).nColor );
562 tools::Long nX1 = rViewData.GetRefStartX();
563 tools::Long nX2 = rViewData.GetRefEndX();
564 tools::Long nY1 = rViewData.GetRefStartY();
565 tools::Long nY2 = rViewData.GetRefEndY();
566 tools::Long nTab = rViewData.GetRefStartZ();
567
568 if (rViewData.GetRefEndZ() == rViewData.GetTabNo())
569 nTab = rViewData.GetRefEndZ();
570
571 PutInOrder(nX1, nX2);
572 PutInOrder(nY1, nY2);
573
574 aReferenceMarks[0] = ScInputHandler::GetReferenceMark( rViewData, pDocSh,
575 nX1, nX2, nY1, nY2,
576 nTab, aRefColor );
577 }
578
579 sal_uInt16 nCount = pRangeFinder ?
580 ( static_cast<sal_uInt16>( pRangeFinder->Count() ) + nAdditionalMarks ) : nAdditionalMarks;
581 aReferenceMarks.resize( nCount );
582
583 if ( nCount && pRangeFinder && !pRangeFinder->IsHidden() &&
584 pRangeFinder->GetDocName() == pDocSh->GetTitle() )
585 {
586 for (sal_uInt16 i = 0; i < nCount - nAdditionalMarks; i++)
587 {
588 ScRangeFindData& rData = pRangeFinder->GetObject( i );
589 ScRange aRef = rData.aRef;
590 aRef.PutInOrder();
591
592 tools::Long nX1 = aRef.aStart.Col();
593 tools::Long nX2 = aRef.aEnd.Col();
594 tools::Long nY1 = aRef.aStart.Row();
595 tools::Long nY2 = aRef.aEnd.Row();
596 tools::Long nTab = aRef.aStart.Tab();
597
598 aReferenceMarks[i + nAdditionalMarks] = ScInputHandler::GetReferenceMark( rViewData, pDocSh,
599 nX1, nX2, nY1, nY2,
600 nTab, rData.nColor );
601
602 ScInputHandler::SendReferenceMarks( pShell, aReferenceMarks );
603 }
604 }
605 else if ( nCount )
606 {
607 ScInputHandler::SendReferenceMarks( pShell, aReferenceMarks );
608 }
609 else
610 {
611 // Clear
612 aReferenceMarks.clear();
613 ScInputHandler::SendReferenceMarks( pShell, aReferenceMarks );
614 }
615}
616
618{
620}
621
622static void lcl_Replace( EditView* pView, const OUString& rNewStr, const ESelection& rOldSel )
623{
624 if ( !pView )
625 return;
626
627 ESelection aOldSel = pView->GetSelection();
628 if (aOldSel.HasRange())
629 pView->SetSelection( ESelection( aOldSel.nEndPara, aOldSel.nEndPos,
630 aOldSel.nEndPara, aOldSel.nEndPos ) );
631
632 EditEngine* pEngine = pView->GetEditEngine();
633 pEngine->QuickInsertText( rNewStr, rOldSel );
634
635 // Dummy InsertText for Update and Paint
636 // To do that we need to cancel the selection from above (before QuickInsertText)
637 pView->InsertText( OUString() );
638
639 const sal_Int32 nPara = pEngine->GetParagraphCount() - 1;
640 const sal_Int32 nLen = pEngine->GetTextLen(nPara);
641 ESelection aSel( nPara, nLen, nPara, nLen );
642 pView->SetSelection( aSel ); // Set cursor to the end
643}
644
645void ScInputHandler::UpdateRange( sal_uInt16 nIndex, const ScRange& rNew )
646{
648 if ( pDocView && pRangeFindList && nIndex < pRangeFindList->Count() )
649 {
650 ScRangeFindData& rData = pRangeFindList->GetObject( nIndex );
651 Color nNewColor = pRangeFindList->FindColor( rNew, nIndex );
652
653 ScRange aJustified = rNew;
654 aJustified.PutInOrder(); // Always display Ref in the Formula the right way
655 ScDocument& rDoc = pDocView->GetViewData().GetDocument();
656 const ScAddress::Details aAddrDetails( rDoc, aCursorPos );
657 OUString aNewStr(aJustified.Format(rDoc, rData.nFlags, aAddrDetails));
658 SfxItemSet aSet( mpEditEngine->GetEmptyItemSet() );
659
660 DataChanging();
661
662 lcl_Replace( pTopView, aNewStr, rData.maSel );
663 lcl_Replace( pTableView, aNewStr, rData.maSel );
664
665 // We are within one paragraph.
666 const sal_Int32 nDiff = aNewStr.getLength() - (rData.maSel.nEndPos - rData.maSel.nStartPos);
667 rData.maSel.nEndPos += nDiff;
668
669 aSet.Put( SvxColorItem( nNewColor, EE_CHAR_COLOR ) );
670 mpEditEngine->QuickSetAttribs( aSet, rData.maSel );
671
672 bInRangeUpdate = true;
673 DataChanged();
674 bInRangeUpdate = false;
675
676 rData.aRef = rNew;
677 rData.nColor = nNewColor;
678
679 if (nDiff)
680 {
681 const size_t nCount = pRangeFindList->Count();
682 for (size_t i = nIndex + 1; i < nCount; ++i)
683 {
684 ScRangeFindData& rNext = pRangeFindList->GetObject( i );
685 if (rNext.maSel.nStartPara != rData.maSel.nStartPara)
686 break;
687
688 rNext.maSel.nStartPos += nDiff;
689 rNext.maSel.nEndPos += nDiff;
690 }
691 }
692
693 EditView* pActiveView = pTopView ? pTopView : pTableView;
694 pActiveView->ShowCursor( false );
695 }
696 else
697 {
698 OSL_FAIL("UpdateRange: we're missing something");
699 }
700}
701
703{
705 if ( pRangeFindList && pPaintView )
706 {
708 pRangeFindList->SetHidden(true);
709 pDocSh->Broadcast( SfxHint( SfxHintId::ScShowRangeFinder ) ); // Steal
710 pRangeFindList.reset();
711 }
712}
713
714static OUString GetEditText(const EditEngine* pEng)
715{
716 return ScEditUtil::GetMultilineString(*pEng);
717}
718
719static void lcl_RemoveTabs(OUString& rStr)
720{
721 rStr = rStr.replace('\t', ' ');
722}
723
724static void lcl_RemoveLineEnd(OUString& rStr)
725{
726 rStr = convertLineEnd(rStr, LINEEND_LF);
727 rStr = rStr.replace('\n', ' ');
728}
729
730static sal_Int32 lcl_MatchParenthesis( const OUString& rStr, sal_Int32 nPos )
731{
732 int nDir;
733 sal_Unicode c1, c2 = 0;
734 c1 = rStr[nPos];
735 switch ( c1 )
736 {
737 case '(' :
738 c2 = ')';
739 nDir = 1;
740 break;
741 case ')' :
742 c2 = '(';
743 nDir = -1;
744 break;
745 case '<' :
746 c2 = '>';
747 nDir = 1;
748 break;
749 case '>' :
750 c2 = '<';
751 nDir = -1;
752 break;
753 case '{' :
754 c2 = '}';
755 nDir = 1;
756 break;
757 case '}' :
758 c2 = '{';
759 nDir = -1;
760 break;
761 case '[' :
762 c2 = ']';
763 nDir = 1;
764 break;
765 case ']' :
766 c2 = '[';
767 nDir = -1;
768 break;
769 default:
770 nDir = 0;
771 }
772 if ( !nDir )
773 return -1;
774 sal_Int32 nLen = rStr.getLength();
775 const sal_Unicode* p0 = rStr.getStr();
776 const sal_Unicode* p;
777 const sal_Unicode* p1;
778 sal_uInt16 nQuotes = 0;
779 if ( nPos < nLen / 2 )
780 {
781 p = p0;
782 p1 = p0 + nPos;
783 }
784 else
785 {
786 p = p0 + nPos;
787 p1 = p0 + nLen;
788 }
789 while ( p < p1 )
790 {
791 if ( *p++ == '\"' )
792 nQuotes++;
793 }
794 // Odd number of quotes that we find ourselves in a string
795 bool bLookInString = ((nQuotes % 2) != 0);
796 bool bInString = bLookInString;
797 p = p0 + nPos;
798 p1 = (nDir < 0 ? p0 : p0 + nLen) ;
799 sal_uInt16 nLevel = 1;
800 while ( p != p1 && nLevel )
801 {
802 p += nDir;
803 if ( *p == '\"' )
804 {
805 bInString = !bInString;
806 if ( bLookInString && !bInString )
807 p = p1; // That's it then
808 }
809 else if ( bInString == bLookInString )
810 {
811 if ( *p == c1 )
812 nLevel++;
813 else if ( *p == c2 )
814 nLevel--;
815 }
816 }
817 if ( nLevel )
818 return -1;
819 return static_cast<sal_Int32>(p - p0);
820}
821
823 : pInputWin( nullptr ),
824 pTableView( nullptr ),
825 pTopView( nullptr ),
826 pTipVisibleParent( nullptr ),
827 nTipVisible( nullptr ),
828 pTipVisibleSecParent( nullptr ),
829 nTipVisibleSec( nullptr ),
830 nFormSelStart( 0 ),
831 nFormSelEnd( 0 ),
832 nCellPercentFormatDecSep( 0 ),
833 nAutoPar( 0 ),
835 bUseTab( false ),
836 bTextValid( true ),
837 bModified( false ),
838 bSelIsRef( false ),
839 bFormulaMode( false ),
840 bInRangeUpdate( false ),
841 bParenthesisShown( false ),
842 bCreatingFuncView( false ),
843 bInEnterHandler( false ),
844 bCommandErrorShown( false ),
845 bInOwnChange( false ),
846 bProtected( false ),
847 bLastIsSymbol( false ),
848 mbDocumentDisposing(false),
849 mbPartialPrefix(false),
850 mbEditingExistingContent(false),
851 nValidation( 0 ),
852 eAttrAdjust( SvxCellHorJustify::Standard ),
853 aScaleX( 1,1 ),
854 aScaleY( 1,1 ),
855 pRefViewSh( nullptr ),
856 pLastPattern( nullptr )
857{
858 // The InputHandler is constructed with the view, so SfxViewShell::Current
859 // doesn't have the right view yet. pActiveViewSh is updated in NotifyChange.
860 pActiveViewSh = nullptr;
861
862 // Bindings (only still used for Invalidate) are retrieved if needed on demand
863
864 pDelayTimer.reset( new Timer( "ScInputHandlerDelay timer" ) );
865 pDelayTimer->SetTimeout( 500 ); // 500 ms delay
866 pDelayTimer->SetInvokeHandler( LINK( this, ScInputHandler, DelayTimer ) );
867}
868
870{
871 // If this is the application InputHandler, the dtor is called after SfxApplication::Main,
872 // thus we can't rely on any Sfx functions
873 if (!mbDocumentDisposing) // inplace
874 EnterHandler(); // Finish input
875
876 if (SC_MOD()->GetRefInputHdl() == this)
877 SC_MOD()->SetRefInputHdl(nullptr);
878
879 if ( pInputWin && pInputWin->GetInputHandler() == this )
880 pInputWin->SetInputHandler( nullptr );
881}
882
884{
885 if ( rX != aScaleX || rY != aScaleY )
886 {
887 aScaleX = rX;
888 aScaleY = rY;
889 if (mpEditEngine)
890 {
891 MapMode aMode( MapUnit::Map100thMM, Point(), aScaleX, aScaleY );
892 mpEditEngine->SetRefMapMode( aMode );
893 }
894 }
895}
896
898{
899 if (!mpEditEngine)
900 return;
901
902 bool bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
904 EEControlBits nCtrl = mpEditEngine->GetControlWord();
905 if ( bTextWysiwyg || bInPlace )
906 nCtrl |= EEControlBits::FORMAT100; // EditEngine default: always format for 100%
907 else
908 nCtrl &= ~EEControlBits::FORMAT100; // when formatting for screen, use the actual MapMode
909 mpEditEngine->SetControlWord( nCtrl );
910 if ( bTextWysiwyg && pActiveViewSh )
912 else
913 mpEditEngine->SetRefDevice( nullptr );
914
915 MapMode aMode( MapUnit::Map100thMM, Point(), aScaleX, aScaleY );
916 mpEditEngine->SetRefMapMode( aMode );
917
918 // SetRefDevice(NULL) uses VirtualDevice, SetRefMapMode forces creation of a local VDev,
919 // so the DigitLanguage can be safely modified (might use an own VDev instead of NULL).
920 if ( !( bTextWysiwyg && pActiveViewSh ) )
921 {
922 mpEditEngine->GetRefDevice()->SetDigitLanguage( ScModule::GetOptDigitLanguage() );
923 }
924}
925
927{
928 if ( mpEditEngine )
929 return;
930
931 if ( pActiveViewSh )
932 {
934 mpEditEngine = std::make_unique<ScFieldEditEngine>(&rDoc, rDoc.GetEnginePool(), rDoc.GetEditPool());
935 }
936 else
937 mpEditEngine = std::make_unique<ScFieldEditEngine>(nullptr, EditEngine::CreatePool().get(), nullptr, true);
938
939 mpEditEngine->SetWordDelimiters( ScEditUtil::ModifyDelimiters( mpEditEngine->GetWordDelimiters() ) );
940 UpdateRefDevice(); // also sets MapMode
941 mpEditEngine->SetPaperSize( Size( 1000000, 1000000 ) );
942 pEditDefaults.reset( new SfxItemSet( mpEditEngine->GetEmptyItemSet() ) );
943
944 mpEditEngine->SetControlWord( mpEditEngine->GetControlWord() | EEControlBits::AUTOCORRECT );
945 mpEditEngine->SetReplaceLeadingSingleQuotationMark( false );
946 mpEditEngine->SetModifyHdl( LINK( this, ScInputHandler, ModifyHdl ) );
947}
948
950{
951 EEControlBits nCntrl = mpEditEngine->GetControlWord();
952 EEControlBits nOld = nCntrl;
953
954 // Don't use pLastPattern here (may be invalid because of AutoStyle)
955 bool bDisable = bLastIsSymbol || bFormulaMode;
956 if ( bDisable )
957 nCntrl &= ~EEControlBits::AUTOCORRECT;
958 else
959 nCntrl |= EEControlBits::AUTOCORRECT;
960
961 if ( nCntrl != nOld )
962 mpEditEngine->SetControlWord(nCntrl);
963}
964
965void ScInputHandler::UpdateSpellSettings( bool bFromStartTab )
966{
967 if ( !pActiveViewSh )
968 return;
969
970 ScViewData& rViewData = pActiveViewSh->GetViewData();
971 bool bOnlineSpell = rViewData.GetDocument().GetDocOptions().IsAutoSpell();
972
973 // SetDefaultLanguage is independent of the language attributes,
974 // ScGlobal::GetEditDefaultLanguage is always used.
975 // It must be set every time in case the office language was changed.
976
977 mpEditEngine->SetDefaultLanguage( ScGlobal::GetEditDefaultLanguage() );
978
979 // if called for changed options, update flags only if already editing
980 // if called from StartTable, always update flags
981
982 if ( bFromStartTab || eMode != SC_INPUT_NONE )
983 {
984 EEControlBits nCntrl = mpEditEngine->GetControlWord();
985 EEControlBits nOld = nCntrl;
986 if( bOnlineSpell )
987 nCntrl |= EEControlBits::ONLINESPELLING;
988 else
989 nCntrl &= ~EEControlBits::ONLINESPELLING;
990 // No AutoCorrect for Symbol Font (EditEngine does no evaluate Default)
992 nCntrl &= ~EEControlBits::AUTOCORRECT;
993 else
994 nCntrl |= EEControlBits::AUTOCORRECT;
995 if ( nCntrl != nOld )
996 mpEditEngine->SetControlWord(nCntrl);
997
998 ScDocument& rDoc = rViewData.GetDocument();
1000 mpEditEngine->SetDefaultHorizontalTextDirection(
1001 rDoc.GetEditTextDirection( rViewData.GetTabNo() ) );
1002 mpEditEngine->SetFirstWordCapitalization( false );
1003 }
1004
1005 // Language is set separately, so the speller is needed only if online spelling is active
1006 if ( bOnlineSpell ) {
1007 css::uno::Reference<css::linguistic2::XSpellChecker1> xXSpellChecker1( LinguMgr::GetSpellChecker() );
1008 mpEditEngine->SetSpeller( xXSpellChecker1 );
1009 }
1010
1011 bool bHyphen = pLastPattern && pLastPattern->GetItem(ATTR_HYPHENATE).GetValue();
1012 if ( bHyphen ) {
1013 css::uno::Reference<css::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
1014 mpEditEngine->SetHyphenator( xXHyphenator );
1015 }
1016}
1017
1018// Function/Range names etc. as Tip help
1019
1020// The other types are defined in ScDocument::GetFormulaEntries
1022{
1023 if ( !pActiveViewSh )
1024 return;
1025
1027
1028 if ( pFormulaData )
1029 pFormulaData->clear();
1030 else
1031 {
1032 pFormulaData.reset( new ScTypedCaseStrSet );
1033 }
1034
1035 if( pFormulaDataPara )
1036 pFormulaDataPara->clear();
1037 else
1039
1040 const OUString aParenthesesReplacement( cParenthesesReplacement);
1042 const sal_uInt32 nListCount = pFuncList->GetCount();
1044 *pFormulaData = rFunctionNames.maFunctionData;
1045 *pFormulaDataPara = rFunctionNames.maFunctionDataPara;
1046 maFormulaChar = rFunctionNames.maFunctionChar;
1047
1048 // Increase suggestion priority of MRU formulas
1049 const ScAppOptions& rOpt = SC_MOD()->GetAppOptions();
1050 const sal_uInt16 nMRUCount = rOpt.GetLRUFuncListCount();
1051 const sal_uInt16* pMRUList = rOpt.GetLRUFuncList();
1052 for (sal_uInt16 i = 0; i < nMRUCount; i++)
1053 {
1054 const sal_uInt16 nId = pMRUList[i];
1055 for (sal_uInt32 j = 0; j < nListCount; j++)
1056 {
1057 const ScFuncDesc* pDesc = pFuncList->GetFunction(j);
1058 if (pDesc->nFIndex == nId && pDesc->mxFuncName)
1059 {
1060 const OUString aEntry = *pDesc->mxFuncName + aParenthesesReplacement;;
1061 const ScTypedStrData aData(aEntry, 0.0, 0.0, ScTypedStrData::Standard);
1062 auto it = pFormulaData->find(aData);
1063 if (it != pFormulaData->end())
1064 pFormulaData->erase(it);
1065 pFormulaData->insert(ScTypedStrData(aEntry, 0.0, 0.0, ScTypedStrData::MRU));
1066 break; // Stop searching
1067 }
1068 }
1069 }
1071
1072 // tdf#142031 - collect all the characters for the formula suggestion auto input
1073 ScTypedCaseStrSet aStrSet;
1074 rDoc.GetFormulaEntries( aStrSet );
1075 for (auto iter = aStrSet.begin(); iter != aStrSet.end(); ++iter)
1076 {
1077 const OUString aFuncName = ScGlobal::getCharClass().uppercase((*iter).GetString());
1078 // fdo#75264 fill maFormulaChar with all characters used in formula names
1079 for (sal_Int32 j = 0; j < aFuncName.getLength(); j++)
1080 maFormulaChar.insert(aFuncName[j]);
1081 }
1082 pFormulaData->insert(aStrSet.begin(), aStrSet.end());
1083 pFormulaDataPara->insert(aStrSet.begin(), aStrSet.end());
1084}
1085
1086IMPL_LINK( ScInputHandler, ShowHideTipVisibleParentListener, VclWindowEvent&, rEvent, void )
1087{
1088 if (rEvent.GetId() == VclEventId::ObjectDying || rEvent.GetId() == VclEventId::WindowHide
1089 || rEvent.GetId() == VclEventId::WindowLoseFocus || rEvent.GetId() == VclEventId::ControlLoseFocus)
1090 HideTip();
1091}
1092
1093IMPL_LINK( ScInputHandler, ShowHideTipVisibleSecParentListener, VclWindowEvent&, rEvent, void )
1094{
1095 if (rEvent.GetId() == VclEventId::ObjectDying || rEvent.GetId() == VclEventId::WindowHide
1096 || rEvent.GetId() == VclEventId::WindowLoseFocus || rEvent.GetId() == VclEventId::ControlLoseFocus)
1097 HideTipBelow();
1098}
1099
1101{
1102 if ( nTipVisible )
1103 {
1104 pTipVisibleParent->RemoveEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleParentListener ) );
1106 nTipVisible = nullptr;
1107 pTipVisibleParent = nullptr;
1108 }
1109 aManualTip.clear();
1110}
1112{
1113 if ( nTipVisibleSec )
1114 {
1115 pTipVisibleSecParent->RemoveEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleSecParentListener ) );
1117 nTipVisibleSec = nullptr;
1118 pTipVisibleSecParent = nullptr;
1119 }
1120 aManualTip.clear();
1121}
1122
1123namespace
1124{
1125
1126bool lcl_hasSingleToken(std::u16string_view s, sal_Unicode c)
1127{
1128 return !s.empty() && s.find(c) == std::u16string_view::npos;
1129}
1130
1131}
1132
1133void ScInputHandler::ShowArgumentsTip( OUString& rSelText )
1134{
1136 {
1137 return;
1138 }
1139
1140 if ( !pActiveViewSh )
1141 return;
1142
1145 const sal_Unicode cSheetSep = pDocSh->GetDocument().GetSheetSeparator();
1147 bool bFound = false;
1148 while( !bFound )
1149 {
1150 rSelText += ")";
1151 sal_Int32 nLeftParentPos = lcl_MatchParenthesis( rSelText, rSelText.getLength()-1 );
1152 if( nLeftParentPos != -1 )
1153 {
1154 sal_Int32 nNextFStart = aHelper.GetFunctionStart( rSelText, nLeftParentPos, true);
1155 const IFunctionDescription* ppFDesc;
1156 ::std::vector< OUString> aArgs;
1157 if( aHelper.GetNextFunc( rSelText, false, nNextFStart, nullptr, &ppFDesc, &aArgs ) )
1158 {
1159 if( !ppFDesc->getFunctionName().isEmpty() )
1160 {
1161 sal_Int32 nArgPos = aHelper.GetArgStart( rSelText, nNextFStart, 0 );
1162 sal_uInt16 nArgs = static_cast<sal_uInt16>(ppFDesc->getParameterCount());
1163 OUString aFuncName( ppFDesc->getFunctionName() + "(");
1164 OUString aNew;
1165 ScTypedCaseStrSet::const_iterator it =
1166 findText(*pFormulaDataPara, pFormulaDataPara->end(), aFuncName, aNew, false);
1167 if (it != pFormulaDataPara->end())
1168 {
1169 bool bFlag = false;
1170 sal_uInt16 nActive = 0;
1171 for( sal_uInt16 i=0; i < nArgs; i++ )
1172 {
1173 sal_Int32 nLength = aArgs[i].getLength();
1174 if( nArgPos <= rSelText.getLength()-1 )
1175 {
1176 nActive = i+1;
1177 bFlag = true;
1178 }
1179 nArgPos+=nLength+1;
1180 }
1181 if( bFlag )
1182 {
1183 sal_Int32 nStartPosition = 0;
1184 sal_Int32 nEndPosition = 0;
1185
1186 if( lcl_hasSingleToken(aNew, cSep) )
1187 {
1188 for (sal_Int32 i = 0; i < aNew.getLength(); ++i)
1189 {
1190 sal_Unicode cNext = aNew[i];
1191 if( cNext == '(' )
1192 {
1193 nStartPosition = i+1;
1194 }
1195 }
1196 }
1197 else if( lcl_hasSingleToken(aNew, cSheetSep) )
1198 {
1199 sal_uInt16 nCount = 0;
1200 for (sal_Int32 i = 0; i < aNew.getLength(); ++i)
1201 {
1202 sal_Unicode cNext = aNew[i];
1203 if( cNext == '(' )
1204 {
1205 nStartPosition = i+1;
1206 }
1207 else if( cNext == cSep )
1208 {
1209 nCount ++;
1210 nEndPosition = i;
1211 if( nCount == nActive )
1212 {
1213 break;
1214 }
1215 nStartPosition = nEndPosition+1;
1216 }
1217 }
1218 }
1219 else
1220 {
1221 sal_uInt16 nCount = 0;
1222 for (sal_Int32 i = 0; i < aNew.getLength(); ++i)
1223 {
1224 sal_Unicode cNext = aNew[i];
1225 if( cNext == '(' )
1226 {
1227 nStartPosition = i+1;
1228 }
1229 else if( cNext == cSep )
1230 {
1231 nCount ++;
1232 nEndPosition = i;
1233 if( nCount == nActive )
1234 {
1235 break;
1236 }
1237 nStartPosition = nEndPosition+1;
1238 }
1239 else if( cNext == cSheetSep )
1240 {
1241 continue;
1242 }
1243 }
1244 }
1245
1246 if (nStartPosition > 0)
1247 {
1248 nArgs = ppFDesc->getParameterCount();
1249 sal_Int16 nVarArgsSet = 0;
1250 if ( nArgs >= PAIRED_VAR_ARGS )
1251 {
1252 nVarArgsSet = 2;
1253 nArgs -= PAIRED_VAR_ARGS - nVarArgsSet;
1254 }
1255 else if ( nArgs >= VAR_ARGS )
1256 {
1257 nVarArgsSet = 1;
1258 nArgs -= VAR_ARGS - nVarArgsSet;
1259 }
1260 if ( nVarArgsSet > 0 && nActive > nArgs )
1261 nActive = nArgs - (nActive - nArgs) % nVarArgsSet;
1262 aNew = OUString::Concat(aNew.subView(0, nStartPosition)) +
1263 u"\x25BA" +
1264 aNew.subView(nStartPosition) +
1265 " : " +
1266 ppFDesc->getParameterDescription(nActive-1);
1267 if (eMode != SC_INPUT_TOP)
1268 {
1269 ShowTipBelow( aNew );
1270 }
1271 else
1272 {
1273 ShowTip(aNew);
1274 }
1275 bFound = true;
1276 }
1277 }
1278 else
1279 {
1280 ShowTipBelow( aNew );
1281 bFound = true;
1282 }
1283 }
1284 }
1285 }
1286 }
1287 else
1288 {
1289 break;
1290 }
1291 }
1292}
1293
1295{
1296 HideTip();
1297 HideTipBelow();
1298 EditView* pActiveView = pTopView ? pTopView : pTableView;
1299
1300 /* TODO: MLFORMULA: this should work also with multi-line formulas. */
1301 if ( !(bFormulaMode && pActiveView && pFormulaDataPara && mpEditEngine->GetParagraphCount() == 1) )
1302 return;
1303
1304 OUString aParagraph = mpEditEngine->GetText( 0 );
1305 ESelection aSel = pActiveView->GetSelection();
1306 aSel.Adjust();
1307
1308 if ( aParagraph.getLength() < aSel.nEndPos )
1309 return;
1310
1311 if ( aSel.nEndPos > 0 )
1312 {
1313 OUString aSelText( aParagraph.copy( 0, aSel.nEndPos ));
1314
1315 ShowArgumentsTip( aSelText );
1316 }
1317}
1318
1319void ScInputHandler::ShowTip( const OUString& rText )
1320{
1321 // aManualTip needs to be set afterwards from outside
1322
1323 HideTip();
1324 HideTipBelow();
1325
1326 EditView* pActiveView = pTopView ? pTopView : pTableView;
1327 if (!pActiveView)
1328 return;
1329
1330 Point aPos;
1331 if (pInputWin && pInputWin->GetEditView() == pActiveView)
1332 {
1333 pTipVisibleParent = pInputWin->GetEditWindow();
1334 aPos = pInputWin->GetCursorScreenPixelPos();
1335 }
1336 else
1337 {
1338 pTipVisibleParent = pActiveView->GetWindow();
1339 if (vcl::Cursor* pCur = pActiveView->GetCursor())
1340 aPos = pTipVisibleParent->LogicToPixel( pCur->GetPos() );
1341 aPos = pTipVisibleParent->OutputToScreenPixel( aPos );
1342 }
1343
1344 tools::Rectangle aRect( aPos, aPos );
1345 QuickHelpFlags const nAlign = QuickHelpFlags::Left|QuickHelpFlags::Bottom;
1346 nTipVisible = Help::ShowPopover(pTipVisibleParent, aRect, rText, nAlign);
1347 pTipVisibleParent->AddEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleParentListener ) );
1348}
1349
1350void ScInputHandler::ShowTipBelow( const OUString& rText )
1351{
1352 HideTipBelow();
1353
1354 EditView* pActiveView = pTopView ? pTopView : pTableView;
1355 if ( !pActiveView )
1356 return;
1357
1358 Point aPos;
1359 if (pInputWin && pInputWin->GetEditView() == pActiveView)
1360 {
1361 pTipVisibleSecParent = pInputWin->GetEditWindow();
1362 aPos = pInputWin->GetCursorScreenPixelPos(true);
1363 }
1364 else
1365 {
1366 pTipVisibleSecParent = pActiveView->GetWindow();
1367 if (vcl::Cursor* pCur = pActiveView->GetCursor())
1368 {
1369 Point aLogicPos = pCur->GetPos();
1370 aLogicPos.AdjustY(pCur->GetHeight() );
1371 aPos = pTipVisibleSecParent->LogicToPixel( aLogicPos );
1372 }
1373 aPos = pTipVisibleSecParent->OutputToScreenPixel( aPos );
1374 }
1375
1376 tools::Rectangle aRect( aPos, aPos );
1377 QuickHelpFlags const nAlign = QuickHelpFlags::Left | QuickHelpFlags::Top | QuickHelpFlags::NoEvadePointer;
1378 nTipVisibleSec = Help::ShowPopover(pTipVisibleSecParent, aRect, rText, nAlign);
1379 pTipVisibleSecParent->AddEventListener( LINK( this, ScInputHandler, ShowHideTipVisibleSecParentListener ) );
1380}
1381
1382bool ScInputHandler::GetFuncName( OUString& aStart, OUString& aResult )
1383{
1384 if ( aStart.isEmpty() )
1385 return false;
1386
1387 aStart = ScGlobal::getCharClass().uppercase( aStart );
1388 sal_Int32 nPos = aStart.getLength() - 1;
1389 sal_Unicode c = aStart[ nPos ];
1390 // fdo#75264 use maFormulaChar to check if characters are used in function names
1391 ::std::set< sal_Unicode >::const_iterator p = maFormulaChar.find( c );
1392 if ( p == maFormulaChar.end() )
1393 return false; // last character is not part of any function name, quit
1394
1395 ::std::vector<sal_Unicode> aTemp { c };
1396 for(sal_Int32 i = nPos - 1; i >= 0; --i)
1397 {
1398 c = aStart[ i ];
1399 p = maFormulaChar.find( c );
1400
1401 if (p == maFormulaChar.end())
1402 break;
1403
1404 aTemp.push_back( c );
1405 }
1406
1407 ::std::vector<sal_Unicode>::reverse_iterator rIt = aTemp.rbegin();
1408 aResult = OUString( *rIt++ );
1409 while ( rIt != aTemp.rend() )
1410 aResult += OUStringChar( *rIt++ );
1411
1412 return true;
1413}
1414
1415namespace {
1417 OString escapeJSON(const OUString &aStr)
1418 {
1419 OUString aEscaped = aStr;
1420 aEscaped = aEscaped.replaceAll("\n", " ");
1421 aEscaped = aEscaped.replaceAll("\"", "'");
1422 return OUStringToOString(aEscaped, RTL_TEXTENCODING_UTF8);
1423 }
1424}
1425
1426void ScInputHandler::ShowFuncList( const ::std::vector< OUString > & rFuncStrVec )
1427{
1428 const SfxViewShell* pViewShell = SfxViewShell::Current();
1430 {
1431 if (rFuncStrVec.size() && pViewShell && pViewShell->isLOKMobilePhone())
1432 {
1433 auto aPos = pFormulaData->begin();
1434 sal_uInt32 nCurIndex = std::distance(aPos, miAutoPosFormula);
1435 const sal_uInt32 nSize = pFormulaData->size();
1436
1437 OUString aFuncNameStr;
1438 OUString aDescFuncNameStr;
1439 OStringBuffer aPayload("[ ");
1440 for (const OUString& rFunc : rFuncStrVec)
1441 {
1442 if ( rFunc[rFunc.getLength()-1] == cParenthesesReplacement )
1443 {
1444 aFuncNameStr = rFunc.copy(0, rFunc.getLength()-1);
1445 }
1446 else
1447 {
1448 aFuncNameStr = rFunc;
1449 }
1450
1452 aDescFuncNameStr = aFuncNameStr + "()";
1453 sal_Int32 nNextFStart = 0;
1454 const IFunctionDescription* ppFDesc;
1455 ::std::vector< OUString > aArgs;
1456 OUString eqPlusFuncName = "=" + aDescFuncNameStr;
1457 if ( aHelper.GetNextFunc( eqPlusFuncName, false, nNextFStart, nullptr, &ppFDesc, &aArgs ) )
1458 {
1459 if ( !ppFDesc->getFunctionName().isEmpty() )
1460 {
1461 aPayload.append("{"
1462 "\"index\": "
1463 + OString::number(static_cast<sal_Int64>(nCurIndex))
1464 + ", "
1465 "\"signature\": \""
1466 + escapeJSON(ppFDesc->getSignature())
1467 + "\", "
1468 "\"description\": \""
1469 + escapeJSON(ppFDesc->getDescription())
1470 + "\"}, ");
1471 }
1472 }
1473 ++nCurIndex;
1474 if (nCurIndex == nSize)
1475 nCurIndex = 0;
1476 }
1477 sal_Int32 nLen = aPayload.getLength();
1478 aPayload[nLen - 2] = ' ';
1479 aPayload[nLen - 1] = ']';
1480
1481 OString s = aPayload.makeStringAndClear();
1482 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CALC_FUNCTION_LIST, s);
1483 }
1484 // not tunnel tooltips in the lok case
1485 return;
1486 }
1487
1488 OUStringBuffer aTipStr;
1489 OUString aFuncNameStr;
1490 OUString aDescFuncNameStr;
1491 ::std::vector<OUString>::const_iterator itStr = rFuncStrVec.begin();
1492 sal_Int32 nMaxFindNumber = 3;
1493 sal_Int32 nRemainFindNumber = nMaxFindNumber;
1494 for ( ; itStr != rFuncStrVec.end(); ++itStr )
1495 {
1496 const OUString& rFunc = *itStr;
1497 if ( rFunc[rFunc.getLength()-1] == cParenthesesReplacement )
1498 {
1499 aFuncNameStr = rFunc.copy(0, rFunc.getLength()-1);
1500 }
1501 else
1502 {
1503 aFuncNameStr = rFunc;
1504 }
1505 if ( itStr == rFuncStrVec.begin() )
1506 {
1507 aTipStr = "[";
1508 aDescFuncNameStr = aFuncNameStr + "()";
1509 }
1510 else
1511 {
1512 aTipStr.append(", ");
1513 }
1514 aTipStr.append(aFuncNameStr);
1515 if ( itStr == rFuncStrVec.begin() )
1516 aTipStr.append("]");
1517 if ( --nRemainFindNumber <= 0 )
1518 break;
1519 }
1520 sal_Int32 nRemainNumber = rFuncStrVec.size() - nMaxFindNumber;
1521 if ( nRemainFindNumber == 0 && nRemainNumber > 0 )
1522 {
1523 OUString aMessage( ScResId( STR_FUNCTIONS_FOUND ) );
1524 aMessage = aMessage.replaceFirst("%2", OUString::number(nRemainNumber));
1525 aMessage = aMessage.replaceFirst("%1", aTipStr);
1526 aTipStr = aMessage;
1527 }
1529 sal_Int32 nNextFStart = 0;
1530 const IFunctionDescription* ppFDesc;
1531 ::std::vector< OUString > aArgs;
1532 OUString eqPlusFuncName = "=" + aDescFuncNameStr;
1533 if ( aHelper.GetNextFunc( eqPlusFuncName, false, nNextFStart, nullptr, &ppFDesc, &aArgs ) )
1534 {
1535 if ( !ppFDesc->getFunctionName().isEmpty() )
1536 {
1537 aTipStr.append(" : " + ppFDesc->getDescription());
1538 }
1539 }
1540 ShowTip( aTipStr.makeStringAndClear() );
1541}
1542
1544{
1545 EditView* pActiveView = pTopView ? pTopView : pTableView;
1546
1547 /* TODO: MLFORMULA: this should work also with multi-line formulas. */
1548 if ( !(pActiveView && pFormulaData && mpEditEngine->GetParagraphCount() == 1) )
1549 return;
1550
1551 OUString aParagraph = mpEditEngine->GetText( 0 );
1552 ESelection aSel = pActiveView->GetSelection();
1553 aSel.Adjust();
1554
1555 // Due to differences between table and input cell (e.g clipboard with line breaks),
1556 // the selection may not be in line with the EditEngine anymore.
1557 // Just return without any indication as to why.
1558 if ( aSel.nEndPos > aParagraph.getLength() )
1559 return;
1560
1561 if ( aParagraph.getLength() > aSel.nEndPos &&
1562 ( ScGlobal::getCharClass().isLetterNumeric( aParagraph, aSel.nEndPos ) ||
1563 aParagraph[ aSel.nEndPos ] == '_' ||
1564 aParagraph[ aSel.nEndPos ] == '.' ||
1565 aParagraph[ aSel.nEndPos ] == '$' ) )
1566 return;
1567
1568 // Is the cursor at the end of a word?
1569 if ( aSel.nEndPos <= 0 )
1570 return;
1571
1572 OUString aSelText( aParagraph.copy( 0, aSel.nEndPos ));
1573
1574 OUString aText;
1575 if ( GetFuncName( aSelText, aText ) )
1576 {
1577 // function name is incomplete:
1578 // show matching functions name as tip above cell
1579 ::std::vector<OUString> aNewVec;
1581 miAutoPosFormula = findTextAll(*pFormulaData, miAutoPosFormula, aText, aNewVec, false);
1582 if (miAutoPosFormula != pFormulaData->end())
1583 {
1584 // check if partial function name is not between quotes
1585 sal_Unicode cBetweenQuotes = 0;
1586 for ( int n = 0; n < aSelText.getLength(); n++ )
1587 {
1588 if (cBetweenQuotes)
1589 {
1590 if (aSelText[n] == cBetweenQuotes)
1591 cBetweenQuotes = 0;
1592 }
1593 else if ( aSelText[ n ] == '"' )
1594 cBetweenQuotes = '"';
1595 else if ( aSelText[ n ] == '\'' )
1596 cBetweenQuotes = '\'';
1597 }
1598 if ( cBetweenQuotes )
1599 return; // we're between quotes
1600
1601 ShowFuncList(aNewVec);
1602 aAutoSearch = aText;
1603 }
1604 return;
1605 }
1606
1607 // function name is complete:
1608 // show tip below the cell with function name and arguments of function
1609 ShowArgumentsTip( aSelText );
1610}
1611
1613{
1614 EditView* pActiveView = pTopView ? pTopView : pTableView;
1615 if ( pActiveView && pFormulaData )
1616 {
1617 ::std::vector<OUString> aNewVec;
1618 ScTypedCaseStrSet::const_iterator itNew = findTextAll(*pFormulaData, miAutoPosFormula, aAutoSearch, aNewVec, bBack);
1619 if (itNew != pFormulaData->end())
1620 {
1621 miAutoPosFormula = itNew;
1622 ShowFuncList( aNewVec );
1623 }
1624 }
1625
1626 // For Tab we always call HideCursor first
1627 if (pActiveView)
1628 pActiveView->ShowCursor();
1629}
1630
1631namespace {
1632
1633void completeFunction( EditView* pView, const OUString& rInsert, bool& rParInserted )
1634{
1635 if (!pView)
1636 return;
1637
1638 ESelection aSel = pView->GetSelection();
1639
1640 bool bNoInitialLetter = false;
1641 OUString aOld = pView->GetEditEngine()->GetText(0);
1642 // in case we want just insert a function and not completing
1644 {
1645 ESelection aSelRange = aSel;
1646 --aSelRange.nStartPos;
1647 --aSelRange.nEndPos;
1648 pView->SetSelection(aSelRange);
1649 pView->SelectCurrentWord();
1650
1651 if ( aOld == "=" )
1652 {
1653 bNoInitialLetter = true;
1654 aSelRange.nStartPos = 1;
1655 aSelRange.nEndPos = 1;
1656 pView->SetSelection(aSelRange);
1657 }
1658 else if ( pView->GetSelected().startsWith("()") )
1659 {
1660 bNoInitialLetter = true;
1661 ++aSelRange.nStartPos;
1662 ++aSelRange.nEndPos;
1663 pView->SetSelection(aSelRange);
1664 }
1665 }
1666
1667 if(!bNoInitialLetter)
1668 {
1669 const sal_Int32 nMinLen = std::max(aSel.nEndPos - aSel.nStartPos, sal_Int32(1));
1670 // Since transliteration service is used to test for match, the replaced string could be
1671 // longer than rInsert, so in order to find longest match before the cursor, test whole
1672 // string from start to current cursor position (don't limit to length of rInsert)
1673 // Disclaimer: I really don't know if a match longer than rInsert is actually possible,
1674 // so the above is based on assumptions how "transliteration" might possibly work. If
1675 // it's in fact impossible, an optimization would be useful to limit aSel.nStartPos to
1676 // std::max(sal_Int32(0), aSel.nEndPos - rInsert.getLength()).
1677 aSel.nStartPos = 0;
1678 pView->SetSelection(aSel);
1679 const OUString aAll = pView->GetSelected();
1680 OUString aMatch;
1681 for (sal_Int32 n = aAll.getLength(); n >= nMinLen && aMatch.isEmpty(); --n)
1682 {
1683 const OUString aTest = aAll.copy(aAll.getLength() - n); // n trailing chars
1684 if (ScGlobal::GetTransliteration().isMatch(aTest, rInsert))
1685 aMatch = aTest; // Found => break the loop
1686 }
1687
1688 aSel.nStartPos = aSel.nEndPos - aMatch.getLength();
1689 pView->SetSelection(aSel);
1690 }
1691
1692 OUString aInsStr = rInsert;
1693 sal_Int32 nInsLen = aInsStr.getLength();
1694 bool bDoParen = ( nInsLen > 1 && aInsStr[nInsLen-2] == '('
1695 && aInsStr[nInsLen-1] == ')' );
1696 if ( bDoParen )
1697 {
1698 // Do not insert parentheses after function names if there already are some
1699 // (e.g. if the function name was edited).
1700 ESelection aWordSel = pView->GetSelection();
1701
1702 // aWordSel.EndPos points one behind string if word at end
1703 if (aWordSel.nEndPos < aOld.getLength())
1704 {
1705 sal_Unicode cNext = aOld[aWordSel.nEndPos];
1706 if ( cNext == '(' )
1707 {
1708 bDoParen = false;
1709 aInsStr = aInsStr.copy( 0, nInsLen - 2 ); // Skip parentheses
1710 }
1711 }
1712 }
1713
1714 pView->InsertText( aInsStr );
1715
1716 if ( bDoParen ) // Put cursor between parentheses
1717 {
1718 aSel = pView->GetSelection();
1719 --aSel.nStartPos;
1720 --aSel.nEndPos;
1721 pView->SetSelection(aSel);
1722
1723 rParInserted = true;
1724 }
1725}
1726
1727}
1728
1730{
1732 {
1733 const ScTypedStrData& rData = *miAutoPosFormula;
1734 OUString aInsert = rData.GetString();
1735 if (aInsert[aInsert.getLength()-1] == cParenthesesReplacement)
1736 aInsert = OUString::Concat(aInsert.subView( 0, aInsert.getLength()-1)) + "()";
1737 bool bParInserted = false;
1738
1739 DataChanging(); // Cannot be new
1740 completeFunction( pTopView, aInsert, bParInserted );
1741 completeFunction( pTableView, aInsert, bParInserted );
1742 DataChanged();
1743 ShowTipCursor();
1744
1745 if (bParInserted)
1746 AutoParAdded();
1747 }
1748
1749 HideTip();
1750
1751 EditView* pActiveView = pTopView ? pTopView : pTableView;
1753 pInputWin->TextGrabFocus();
1754 if (pActiveView)
1755 pActiveView->ShowCursor();
1756}
1757
1758void ScInputHandler::LOKPasteFunctionData(const OUString& rFunctionName)
1759{
1760 // in case we have no top view try to create it
1761 if (!pTopView && pInputWin)
1762 {
1763 ScInputMode eCurMode = eMode;
1765 if (!pTopView)
1766 SetMode(eCurMode);
1767 }
1768
1769 EditView* pEditView = pTopView ? pTopView : pTableView;
1770
1771 if (!pActiveViewSh || !pEditView)
1772 return;
1773
1774 bool bEdit = false;
1775 OUString aFormula;
1776 const EditEngine* pEditEngine = pEditView->GetEditEngine();
1777 if (pEditEngine)
1778 {
1779 aFormula = pEditEngine->GetText(0);
1780 /* TODO: LOK: are you sure you want '+' and '-' let start formulas with
1781 * function names? That was meant for "data typist" numeric keyboard
1782 * input. */
1783 bEdit = aFormula.getLength() > 1 && (aFormula[0] == '=' || aFormula[0] == '+' || aFormula[0] == '-');
1784 }
1785
1786 if ( !bEdit )
1787 {
1788 OUString aNewFormula('=');
1789 if ( aFormula.startsWith("=") )
1790 aNewFormula = aFormula;
1791
1792 InputReplaceSelection( aNewFormula );
1793 }
1794
1795 if (pFormulaData)
1796 {
1797 OUString aNew;
1798 ScTypedCaseStrSet::const_iterator aPos = findText(*pFormulaData, pFormulaData->begin(), rFunctionName, aNew, /* backward = */false);
1799
1800 if (aPos != pFormulaData->end())
1801 {
1802 miAutoPosFormula = aPos;
1804 }
1805 }
1806}
1807
1809 const SfxViewShell* pActiveViewSh,
1810 const OUString& rText,
1811 const ESelection& rSelection)
1812{
1813 OUString aSelection;
1814 if (pActiveView)
1815 {
1816 aSelection = OUString::number(pActiveView->GetPosWithField(0, rSelection.nStartPos)) + ";" +
1817 OUString::number(pActiveView->GetPosWithField(0, rSelection.nEndPos)) + ";" +
1818 OUString::number(rSelection.nStartPara) + ";" + OUString::number(rSelection.nEndPara);
1819 }
1820 else
1821 {
1822 aSelection = OUString::number(rSelection.nStartPos) + ";" + OUString::number(rSelection.nEndPos) + ";" +
1823 OUString::number(rSelection.nStartPara) + ";" + OUString::number(rSelection.nEndPara);
1824 }
1825
1826 std::unique_ptr<jsdialog::ActionDataMap> pData = std::make_unique<jsdialog::ActionDataMap>();
1827 (*pData)["action_type"] = "setText";
1828 (*pData)["text"] = rText;
1829 (*pData)["selection"] = aSelection;
1830
1831 sal_uInt64 nCurrentShellId = reinterpret_cast<sal_uInt64>(pActiveViewSh);
1832 OUString sWindowId = OUString::number(nCurrentShellId) + "formulabar";
1833 jsdialog::SendAction(sWindowId, "sc_input_window", std::move(pData));
1834}
1835
1836// Calculate selection and display as tip help
1837static OUString lcl_Calculate( const OUString& rFormula, ScDocument& rDoc, const ScAddress &rPos )
1838{
1839 //TODO: Merge with ScFormulaDlg::CalcValue and move into Document!
1840 // Quotation marks for Strings are only inserted here.
1841
1842 if(rFormula.isEmpty())
1843 return OUString();
1844
1845 std::optional<ScSimpleFormulaCalculator> pCalc( std::in_place, rDoc, rPos, rFormula, false );
1846
1847 // FIXME: HACK! In order to not get a #REF! for ColRowNames, if a name is actually inserted as a Range
1848 // into the whole Formula, but is interpreted as a single cell reference when displaying it on its own
1849 bool bColRowName = pCalc->HasColRowName();
1850 if ( bColRowName )
1851 {
1852 // ColRowName in RPN code?
1853 if ( pCalc->GetCode()->GetCodeLen() <= 1 )
1854 { // ==1: Single one is as a Parameter always a Range
1855 // ==0: It might be one, if ...
1856 OUString aBraced = "(" + rFormula + ")";
1857 pCalc.emplace( rDoc, rPos, aBraced, false );
1858 }
1859 else
1860 bColRowName = false;
1861 }
1862
1863 FormulaError nErrCode = pCalc->GetErrCode();
1864 if ( nErrCode != FormulaError::NONE )
1865 return ScGlobal::GetErrorString(nErrCode);
1866
1867 SvNumberFormatter& aFormatter = *rDoc.GetFormatTable();
1868 OUString aValue;
1869 if ( pCalc->IsValue() )
1870 {
1871 double n = pCalc->GetValue();
1872 sal_uInt32 nFormat = aFormatter.GetStandardFormat( n, 0,
1873 pCalc->GetFormatType(), ScGlobal::eLnge );
1874 aFormatter.GetInputLineString( n, nFormat, aValue );
1876 }
1877 else
1878 {
1879 OUString aStr = pCalc->GetString().getString();
1880 sal_uInt32 nFormat = aFormatter.GetStandardFormat(
1881 pCalc->GetFormatType(), ScGlobal::eLnge);
1882 {
1883 const Color* pColor;
1884 aFormatter.GetOutputString( aStr, nFormat,
1885 aValue, &pColor );
1886 }
1887
1888 aValue = "\"" + aValue + "\"";
1890 }
1891
1892 ScRange aTestRange;
1893 if ( bColRowName || (aTestRange.Parse(rFormula, rDoc) & ScRefFlags::VALID) )
1894 aValue += " ...";
1895
1896 return aValue;
1897}
1898
1900{
1901 OUString aValue;
1902 EditView* pActiveView = pTopView ? pTopView : pTableView;
1903 if ( pActiveView && pActiveViewSh )
1904 {
1905 OUString aPart = pActiveView->GetSelected();
1906 if (aPart.isEmpty())
1907 aPart = mpEditEngine->GetText(0);
1909 aValue = lcl_Calculate( aPart, rDoc, aCursorPos );
1910 }
1911
1912 if (!aValue.isEmpty())
1913 {
1914 ShowTip( aValue ); // Display as QuickHelp
1915 aManualTip = aValue; // Set after ShowTip
1916 if (pFormulaData)
1918 if (pColumnData)
1920 }
1921}
1922
1924{
1925 // Three dots at the end -> Range reference -> do not insert
1926 // FIXME: Once we have matrix constants, we can change this
1927 sal_Int32 nTipLen = aManualTip.getLength();
1928 sal_uInt32 const nTipLen2(sal::static_int_cast<sal_uInt32>(nTipLen));
1929 if ( nTipLen && ( nTipLen < 3 || aManualTip.subView( nTipLen2-3 ) != u"..." ) )
1930 {
1931 DataChanging(); // Cannot be new
1932
1933 OUString aInsert = aManualTip;
1934 EditView* pActiveView = pTopView ? pTopView : pTableView;
1935 if (!pActiveView->HasSelection())
1936 {
1937 // Nothing selected -> select everything
1938 sal_Int32 nOldLen = mpEditEngine->GetTextLen(0);
1939 ESelection aAllSel( 0, 0, 0, nOldLen );
1940 if ( pTopView )
1941 pTopView->SetSelection( aAllSel );
1942 if ( pTableView )
1943 pTableView->SetSelection( aAllSel );
1944 }
1945
1946 ESelection aSel = pActiveView->GetSelection();
1947 aSel.Adjust();
1948 OSL_ENSURE( !aSel.nStartPara && !aSel.nEndPara, "Too many paragraphs in Formula" );
1949 if ( !aSel.nStartPos ) // Selection from the start?
1950 {
1951 if ( aSel.nEndPos == mpEditEngine->GetTextLen(0) )
1952 {
1953 // Everything selected -> skip quotation marks
1954 if ( aInsert[0] == '"' )
1955 aInsert = aInsert.copy(1);
1956 sal_Int32 nInsLen = aInsert.getLength();
1957 if ( aInsert.endsWith("\"") )
1958 aInsert = aInsert.copy( 0, nInsLen-1 );
1959 }
1960 else if ( aSel.nEndPos )
1961 {
1962 // Not everything selected -> do not overwrite equality sign
1963 //FIXME: Even double equality signs??
1964 aSel.nStartPos = 1;
1965 if ( pTopView )
1966 pTopView->SetSelection( aSel );
1967 if ( pTableView )
1968 pTableView->SetSelection( aSel );
1969 }
1970 }
1971 if ( pTopView )
1972 pTopView->InsertText( aInsert, true );
1973 if ( pTableView )
1974 pTableView->InsertText( aInsert, true );
1975
1976 DataChanged();
1977 }
1978
1979 HideTip();
1980}
1981
1983{
1984 nAutoPar = 0;
1985}
1986
1988{
1989 ++nAutoPar; // Closing parenthesis can be overwritten
1990}
1991
1993{
1994 // Test if the cursor is before a closing parenthesis
1995 // Selection from SetReference has been removed before
1996 EditView* pActiveView = pTopView ? pTopView : pTableView;
1997 if ( pActiveView && !pActiveView->HasSelection() && bFormulaMode )
1998 {
1999 ESelection aSel = pActiveView->GetSelection();
2000 sal_Int32 nPos = aSel.nStartPos;
2001 OUString aFormula = mpEditEngine->GetText(0);
2002 if ( nPos < aFormula.getLength() && aFormula[nPos] == ')' )
2003 return true;
2004 }
2005 return false;
2006}
2007
2009{
2010 // this is called when a ')' is typed and the cursor is before a ')'
2011 // that can be overwritten -> just set the cursor behind the ')'
2012
2013 EditView* pActiveView = pTopView ? pTopView : pTableView;
2014 if (pActiveView)
2015 {
2016 ESelection aSel = pActiveView->GetSelection();
2017 ++aSel.nStartPos;
2018 ++aSel.nEndPos;
2019
2020 // this is in a formula (only one paragraph), so the selection
2021 // can be used directly for the TopView
2022
2023 if ( pTopView )
2024 pTopView->SetSelection( aSel );
2025 if ( pTableView )
2026 pTableView->SetSelection( aSel );
2027 }
2028
2029 OSL_ENSURE(nAutoPar, "SkipClosingPar: count is wrong");
2030 --nAutoPar;
2031}
2032
2033// Auto input
2034
2036{
2037 if ( !pActiveViewSh )
2038 return;
2039
2041
2042 if ( pColumnData )
2043 pColumnData->clear();
2044 else
2045 pColumnData.reset( new ScTypedCaseStrSet );
2046
2047 std::vector<ScTypedStrData> aEntries;
2048 rDoc.GetDataEntries(
2050 if (!aEntries.empty())
2051 pColumnData->insert(aEntries.begin(), aEntries.end());
2052
2054}
2055
2056void ScInputHandler::UseColData() // When typing
2057{
2058 EditView* pActiveView = pTopView ? pTopView : pTableView;
2059 if ( !(pActiveView && pColumnData) )
2060 return;
2061
2062 // Only change when cursor is at the end
2063 ESelection aSel = pActiveView->GetSelection();
2064 aSel.Adjust();
2065
2066 sal_Int32 nParCnt = mpEditEngine->GetParagraphCount();
2067 if ( aSel.nEndPara+1 != nParCnt )
2068 return;
2069
2070 sal_Int32 nParLen = mpEditEngine->GetTextLen( aSel.nEndPara );
2071 if ( aSel.nEndPos != nParLen )
2072 return;
2073
2074 OUString aText = GetEditText(mpEditEngine.get());
2075 if (aText.isEmpty())
2076 return;
2077
2078 std::vector< OUString > aResultVec;
2079 OUString aNew;
2080 sal_Int32 nLongestPrefixLen = 0;
2082 mbPartialPrefix = false;
2083 miAutoPosColumn = findTextAll(*pColumnData, miAutoPosColumn, aText, aResultVec, false, &nLongestPrefixLen);
2084
2085 if (nLongestPrefixLen <= 0 || aResultVec.empty())
2086 return;
2087
2088 if (aResultVec.size() > 1)
2089 {
2090 mbPartialPrefix = true;
2091 bUseTab = true; // Allow Ctrl (+ Shift + ) + TAB cycling.
2093
2094 // Display the rest of longest common prefix as suggestion.
2095 aNew = aResultVec[0].copy(0, nLongestPrefixLen);
2096 }
2097 else
2098 {
2099 aNew = aResultVec[0];
2100 }
2101
2102 // Strings can contain line endings (e.g. due to dBase import),
2103 // which would result in multiple paragraphs here, which is not desirable.
2105 lcl_RemoveLineEnd( aNew );
2106
2107 // Keep paragraph, just append the rest
2109 // One Space between paragraphs:
2110 sal_Int32 nEdLen = mpEditEngine->GetTextLen() + nParCnt - 1;
2111 OUString aIns = aNew.copy(nEdLen);
2112
2113 // Selection must be "backwards", so the cursor stays behind the last
2114 // typed character
2115 ESelection aSelection( aSel.nEndPara, aSel.nEndPos + aIns.getLength(),
2116 aSel.nEndPara, aSel.nEndPos );
2117
2118 // When editing in input line, apply to both edit views
2119 if ( pTableView )
2120 {
2121 pTableView->InsertText( aIns );
2122 pTableView->SetSelection( aSelection );
2123 }
2124 if ( pTopView )
2125 {
2126 pTopView->InsertText( aIns );
2127 pTopView->SetSelection( aSelection );
2128 }
2129
2130 aAutoSearch = aText; // To keep searching - nAutoPos is set
2131}
2132
2134{
2135 EditView* pActiveView = pTopView ? pTopView : pTableView;
2136 if ( pActiveView && pColumnData )
2137 {
2138 if (!aAutoSearch.isEmpty())
2139 {
2140 // Is the selection still valid (could be changed via the mouse)?
2141 ESelection aSel = pActiveView->GetSelection();
2142 aSel.Adjust();
2143 sal_Int32 nParCnt = mpEditEngine->GetParagraphCount();
2144 if ( aSel.nEndPara+1 == nParCnt && aSel.nStartPara == aSel.nEndPara )
2145 {
2146 OUString aText = GetEditText(mpEditEngine.get());
2147 sal_Int32 nSelLen = aSel.nEndPos - aSel.nStartPos;
2148 sal_Int32 nParLen = mpEditEngine->GetTextLen( aSel.nEndPara );
2149 if ( aSel.nEndPos == nParLen && aText.getLength() == aAutoSearch.getLength() + nSelLen )
2150 {
2151 OUString aNew;
2152 ScTypedCaseStrSet::const_iterator itNew =
2153 findText(*pColumnData, miAutoPosColumn, aAutoSearch, aNew, bBack);
2154
2155 if (itNew != pColumnData->end())
2156 {
2157 // match found!
2158 miAutoPosColumn = itNew;
2159 bInOwnChange = true; // disable ModifyHdl (reset below)
2160 mbPartialPrefix = false;
2161
2162 lcl_RemoveLineEnd( aNew );
2163 OUString aIns = aNew.copy(aAutoSearch.getLength());
2164
2165 // when editing in input line, apply to both edit views
2166 if ( pTableView )
2167 {
2169 pTableView->InsertText( aIns );
2171 aSel.nEndPara, aSel.nStartPos + aIns.getLength(),
2172 aSel.nEndPara, aSel.nStartPos ) );
2173 }
2174 if ( pTopView )
2175 {
2177 pTopView->InsertText( aIns );
2179 aSel.nEndPara, aSel.nStartPos + aIns.getLength(),
2180 aSel.nEndPara, aSel.nStartPos ) );
2181 }
2182
2183 bInOwnChange = false;
2184 }
2185 }
2186 }
2187 }
2188 }
2189
2190 // For Tab, HideCursor was always called first
2191 if (pActiveView)
2192 pActiveView->ShowCursor();
2193}
2194
2195// Highlight parentheses
2197{
2198 // Find parentheses
2199 //TODO: Can we disable parentheses highlighting per parentheses?
2200 bool bFound = false;
2201 if ( bFormulaMode && eMode != SC_INPUT_TOP )
2202 {
2203 if ( pTableView && !pTableView->HasSelection() ) // Selection is always at the bottom
2204 {
2206 if (aSel.nStartPos)
2207 {
2208 // Examine character left to the cursor
2209 sal_Int32 nPos = aSel.nStartPos - 1;
2210 OUString aFormula = mpEditEngine->GetText(aSel.nStartPara);
2211 sal_Unicode c = aFormula[nPos];
2212 if ( c == '(' || c == ')' )
2213 {
2214 // Note this matches only within one paragraph.
2215 sal_Int32 nOther = lcl_MatchParenthesis( aFormula, nPos );
2216 if ( nOther != -1 )
2217 {
2218 SfxItemSet aSet( mpEditEngine->GetEmptyItemSet() );
2220
2223 {
2224 // Remove old highlighting
2225 sal_Int32 nCount = mpEditEngine->GetParagraphCount();
2226 for (sal_Int32 i=0; i<nCount; i++)
2227 mpEditEngine->RemoveCharAttribs( i, EE_CHAR_WEIGHT );
2228 }
2229
2230 ESelection aSelThis( aSel.nStartPara, nPos, aSel.nStartPara, nPos+1);
2231 mpEditEngine->QuickSetAttribs( aSet, aSelThis );
2232 ESelection aSelOther( aSel.nStartPara, nOther, aSel.nStartPara, nOther+1);
2233 mpEditEngine->QuickSetAttribs( aSet, aSelOther );
2234
2235 // Dummy InsertText for Update and Paint (selection is empty)
2236 pTableView->InsertText( OUString() );
2237
2238 bFound = true;
2239 }
2240 }
2241 }
2242
2243 // mark parenthesis right of cursor if it will be overwritten (nAutoPar)
2244 // with different color (COL_LIGHTBLUE) ??
2245 }
2246 }
2247
2248 // Remove old highlighting, if no new one is set
2249 if ( bParenthesisShown && !bFound && pTableView )
2250 {
2251 sal_Int32 nCount = mpEditEngine->GetParagraphCount();
2252 for (sal_Int32 i=0; i<nCount; i++)
2254 }
2255
2256 bParenthesisShown = bFound;
2257}
2258
2259void ScInputHandler::ViewShellGone(const ScTabViewShell* pViewSh) // Executed synchronously!
2260{
2261 if ( pViewSh == pActiveViewSh )
2262 {
2263 pLastState.reset();
2264 pLastPattern = nullptr;
2265 }
2266
2267 if ( pViewSh == pRefViewSh )
2268 {
2270 // We end the EditMode anyways
2271 EnterHandler();
2272 bFormulaMode = false;
2273 pRefViewSh = nullptr;
2274 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScRefModeChanged ) );
2275 SC_MOD()->SetRefInputHdl(nullptr);
2276 if (pInputWin)
2277 pInputWin->SetFormulaMode(false);
2279 }
2280
2282
2283 if ( pActiveViewSh && pActiveViewSh == pViewSh )
2284 {
2285 OSL_FAIL("pActiveViewSh is gone");
2286 pActiveViewSh = nullptr;
2287 }
2288
2289 if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
2290 UpdateRefDevice(); // Don't keep old document's printer as RefDevice
2291}
2292
2294{
2296
2297 // #i20588# Don't rely on focus to find the active edit view. Instead, the
2298 // active pane at the start of editing is now stored (GetEditActivePart).
2299 // GetActiveWin (the currently active pane) fails for ref input across the
2300 // panes of a split view.
2301
2302 vcl::Window* pShellWin = pActiveViewSh ?
2304 nullptr;
2305
2306 sal_uInt16 nCount = mpEditEngine->GetViewCount();
2307 if (nCount > 0)
2308 {
2309 pTableView = mpEditEngine->GetView();
2310 for (sal_uInt16 i=1; i<nCount; i++)
2311 {
2312 EditView* pThis = mpEditEngine->GetView(i);
2313 vcl::Window* pWin = pThis->GetWindow();
2314 if ( pWin==pShellWin )
2315 pTableView = pThis;
2316 }
2317 }
2318 else
2319 pTableView = nullptr;
2320
2321 // setup the pTableView editeng for tiled rendering to get cursor and selections
2323 {
2325 {
2327 }
2328 }
2329
2331 {
2332 // tdf#71409: Always create the edit engine instance for the input
2333 // window, in order to properly manage accessibility events.
2334 pTopView = pInputWin->GetEditView();
2335 if (eMode != SC_INPUT_TOP)
2336 pTopView = nullptr;
2337 }
2338 else
2339 pTopView = nullptr;
2340}
2341
2343{
2344 pInputWin = pNew;
2345}
2346
2348{
2349 if (pInputWin && !pInputWin->isDisposed())
2350 pInputWin->StopEditEngine( bAll );
2351
2352 pTopView = nullptr; // invalid now
2353}
2354
2356{
2358 return pTopView ? pTopView : pTableView;
2359}
2360
2362{
2363 pLastPattern = nullptr;
2364 if ( !pLastState && pActiveViewSh )
2365 pActiveViewSh->UpdateInputHandler( true ); // Get status again
2366 else
2367 NotifyChange( pLastState.get(), true );
2368}
2369
2371{
2372 SvxAdjust eSvxAdjust;
2373 switch (eAttrAdjust)
2374 {
2375 case SvxCellHorJustify::Standard:
2376 {
2377 bool bNumber = false;
2378 if (cTyped) // Restarted
2379 bNumber = (cTyped>='0' && cTyped<='9'); // Only ciphers are numbers
2380 else if ( pActiveViewSh )
2381 {
2383 bNumber = ( rDoc.GetCellType( aCursorPos ) == CELLTYPE_VALUE );
2384 }
2385 eSvxAdjust = bNumber ? SvxAdjust::Right : SvxAdjust::Left;
2386 }
2387 break;
2388 case SvxCellHorJustify::Block:
2389 eSvxAdjust = SvxAdjust::Block;
2390 break;
2391 case SvxCellHorJustify::Center:
2392 eSvxAdjust = SvxAdjust::Center;
2393 break;
2394 case SvxCellHorJustify::Right:
2395 eSvxAdjust = SvxAdjust::Right;
2396 break;
2397 default: // SvxCellHorJustify::Left
2398 eSvxAdjust = SvxAdjust::Left;
2399 break;
2400 }
2401
2402 bool bAsianVertical = pLastPattern &&
2403 pLastPattern->GetItem( ATTR_STACKED ).GetValue() &&
2405 if ( bAsianVertical )
2406 {
2407 // Always edit at top of cell -> LEFT when editing vertically
2408 eSvxAdjust = SvxAdjust::Left;
2409 }
2410
2411 pEditDefaults->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
2412 mpEditEngine->SetDefaults( *pEditDefaults );
2413
2414 if ( pActiveViewSh )
2415 {
2416 pActiveViewSh->GetViewData().SetEditAdjust( eSvxAdjust );
2417 }
2418 mpEditEngine->SetVertical( bAsianVertical );
2419}
2420
2422{
2423 // Delete hard alignment attributes
2424 bool bUndo = mpEditEngine->IsUndoEnabled();
2425 if ( bUndo )
2426 mpEditEngine->EnableUndo( false );
2427
2428 // Non-default paragraph attributes (e.g. from clipboard)
2429 // must be turned into character attributes
2430 mpEditEngine->RemoveParaAttribs();
2431
2432 if ( bUndo )
2433 mpEditEngine->EnableUndo( true );
2434
2435}
2436
2438{
2439 // Delete pRangeFindList and colors
2440 mpEditEngine->SetUpdateLayout(false);
2441 sal_Int32 nCount = mpEditEngine->GetParagraphCount(); // Could just have been inserted
2442 for (sal_Int32 i=0; i<nCount; i++)
2443 mpEditEngine->RemoveCharAttribs( i, EE_CHAR_COLOR );
2444 mpEditEngine->SetUpdateLayout(true);
2445
2446 EditView* pActiveView = pTopView ? pTopView : pTableView;
2447 pActiveView->ShowCursor( false );
2448
2449 DeleteRangeFinder(); // Deletes the list and the labels on the table
2450}
2451
2452bool ScInputHandler::StartTable( sal_Unicode cTyped, bool bFromCommand, bool bInputActivated,
2453 ScEditEngineDefaulter* pTopEngine )
2454{
2455 bool bNewTable = false;
2456
2457 if (bModified)
2458 return false;
2459
2460 if (pActiveViewSh)
2461 {
2463
2464 if (!rDoc.ValidCol(aCursorPos.Col()))
2465 return false;
2466
2469 SyncViews();
2470
2471
2472 const ScMarkData& rMark = pActiveViewSh->GetViewData().GetMarkData();
2473 ScEditableTester aTester;
2474 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
2475 aTester.TestSelection( rDoc, rMark );
2476 else
2477 aTester.TestSelectedBlock(
2478 rDoc, aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Col(), aCursorPos.Row(), rMark );
2479
2480 bool bStartInputMode = true;
2481
2482 if (!aTester.IsEditable())
2483 {
2484 bProtected = true;
2485 // We allow read-only input mode activation regardless
2486 // whether it's part of an array or not or whether explicit cell
2487 // activation is requested (double-click or F2) or a click in input
2488 // line.
2489 bool bShowError = (!bInputActivated || !aTester.GetMessageId() || aTester.GetMessageId() != STR_PROTECTIONERR) &&
2491 if (bShowError)
2492 {
2494 StopInputWinEngine( true );
2496 if ( pActiveViewSh && ( !bFromCommand || !bCommandErrorShown ) )
2497 {
2498 // Prevent repeated error messages for the same cell from command events
2499 // (for keyboard events, multiple messages are wanted).
2500 // Set the flag before showing the error message because the command handler
2501 // for the next IME command may be called when showing the dialog.
2502 if ( bFromCommand )
2503 bCommandErrorShown = true;
2504
2507 }
2508 bStartInputMode = false;
2509 }
2510 }
2511
2512 if (bStartInputMode)
2513 {
2514 // UpdateMode is enabled again in ScViewData::SetEditEngine (and not needed otherwise)
2515 mpEditEngine->SetUpdateLayout( false );
2516
2517 // Take over attributes in EditEngine
2518 const ScPatternAttr* pPattern = rDoc.GetPattern( aCursorPos.Col(),
2519 aCursorPos.Row(),
2520 aCursorPos.Tab() );
2521 if (pPattern != pLastPattern)
2522 {
2523 // Percent format?
2524 const SfxItemSet& rAttrSet = pPattern->GetItemSet();
2525
2526 if ( const SfxUInt32Item* pItem = rAttrSet.GetItemIfSet( ATTR_VALUE_FORMAT ) )
2527 {
2528 sal_uInt32 nFormat = pItem->GetValue();
2529 if (SvNumFormatType::PERCENT == rDoc.GetFormatTable()->GetType( nFormat ))
2530 nCellPercentFormatDecSep = rDoc.GetFormatTable()->GetFormatDecimalSep( nFormat).toChar();
2531 else
2533 }
2534 else
2535 nCellPercentFormatDecSep = 0; // Default: no percent
2536
2537 // Validity specified?
2538 if ( const SfxUInt32Item* pItem = rAttrSet.GetItemIfSet( ATTR_VALIDDATA ) )
2539 nValidation = pItem->GetValue();
2540 else
2541 nValidation = 0;
2542
2543 // EditEngine Defaults
2544 // In no case SetParaAttribs, because the EditEngine might already
2545 // be filled (for Edit cells).
2546 // SetParaAttribs would change the content.
2547
2551
2552 pPattern->FillEditItemSet( pEditDefaults.get() );
2553 mpEditEngine->SetDefaults( *pEditDefaults );
2554 pLastPattern = pPattern;
2555 bLastIsSymbol = pPattern->IsSymbolFont();
2556
2557 // Background color must be known for automatic font color.
2558 // For transparent cell background, the document background color must be used.
2559
2560 Color aBackCol = pPattern->GetItem( ATTR_BACKGROUND ).GetColor();
2561 ScModule* pScMod = SC_MOD();
2562 if ( aBackCol.IsTransparent() ||
2565 mpEditEngine->SetBackgroundColor( aBackCol );
2566
2567 // Adjustment
2568 eAttrAdjust = pPattern->GetItem(ATTR_HOR_JUSTIFY).GetValue();
2569 if ( eAttrAdjust == SvxCellHorJustify::Repeat &&
2570 pPattern->GetItem(ATTR_LINEBREAK).GetValue() )
2571 {
2572 // #i31843# "repeat" with "line breaks" is treated as default alignment
2573 eAttrAdjust = SvxCellHorJustify::Standard;
2574 }
2575 }
2576
2577 if (pTopEngine)
2578 {
2579 // Necessary to sync SvxAutoCorrect behavior. This has to be
2580 // done before InitRangeFinder() below.
2581 MergeLanguageAttributes( *pTopEngine);
2582 }
2583
2584 // UpdateSpellSettings enables online spelling if needed
2585 // -> also call if attributes are unchanged
2586 UpdateSpellSettings( true ); // uses pLastPattern
2587
2588 // Fill EditEngine
2589 OUString aStr;
2590 if (bTextValid)
2591 {
2592 mpEditEngine->SetTextCurrentDefaults(aCurrentText);
2594 bTextValid = false;
2595 aCurrentText.clear();
2596 }
2597 else
2598 aStr = GetEditText(mpEditEngine.get());
2599
2600 // cTyped!=0 is overtyping, not editing.
2601 mbEditingExistingContent = !cTyped && !aStr.isEmpty();
2602
2603 if (aStr.startsWith("{=") && aStr.endsWith("}") ) // Matrix formula?
2604 {
2605 aStr = aStr.copy(1, aStr.getLength() -2);
2606 mpEditEngine->SetTextCurrentDefaults(aStr);
2607 if ( pInputWin )
2608 pInputWin->SetTextString(aStr);
2609 }
2610
2611 UpdateAdjust( cTyped );
2612
2613 if ( SC_MOD()->GetAppOptions().GetAutoComplete() )
2614 GetColData();
2615
2616 if (!cTyped && !bCreatingFuncView && StartsLikeFormula(aStr))
2617 InitRangeFinder(aStr); // Formula is being edited -> RangeFinder
2618
2619 bNewTable = true; // -> PostEditView Call
2620 }
2621 }
2622
2623 if (!bProtected && pInputWin)
2624 pInputWin->SetOkCancelMode();
2625
2626 return bNewTable;
2627}
2628
2630{
2631 const SfxItemSet& rSrcSet = mpEditEngine->GetDefaults();
2632 rDestEngine.SetDefaultItem( rSrcSet.Get( EE_CHAR_LANGUAGE ));
2633 rDestEngine.SetDefaultItem( rSrcSet.Get( EE_CHAR_LANGUAGE_CJK ));
2634 rDestEngine.SetDefaultItem( rSrcSet.Get( EE_CHAR_LANGUAGE_CTL ));
2635}
2636
2637static void lcl_SetTopSelection( EditView* pEditView, ESelection& rSel )
2638{
2639 OSL_ENSURE( rSel.nStartPara==0 && rSel.nEndPara==0, "SetTopSelection: Para != 0" );
2640
2641 EditEngine* pEngine = pEditView->GetEditEngine();
2642 sal_Int32 nCount = pEngine->GetParagraphCount();
2643 if (nCount > 1)
2644 {
2645 sal_Int32 nParLen = pEngine->GetTextLen(rSel.nStartPara);
2646 while (rSel.nStartPos > nParLen && rSel.nStartPara+1 < nCount)
2647 {
2648 rSel.nStartPos -= nParLen + 1; // Including space from line break
2649 nParLen = pEngine->GetTextLen(++rSel.nStartPara);
2650 }
2651
2652 nParLen = pEngine->GetTextLen(rSel.nEndPara);
2653 while (rSel.nEndPos > nParLen && rSel.nEndPara+1 < nCount)
2654 {
2655 rSel.nEndPos -= nParLen + 1; // Including space from line break
2656 nParLen = pEngine->GetTextLen(++rSel.nEndPara);
2657 }
2658 }
2659
2660 ESelection aSel = pEditView->GetSelection();
2661
2662 if ( rSel.nStartPara != aSel.nStartPara || rSel.nEndPara != aSel.nEndPara
2663 || rSel.nStartPos != aSel.nStartPos || rSel.nEndPos != aSel.nEndPos )
2664 pEditView->SetSelection( rSel );
2665}
2666
2667void ScInputHandler::SyncViews( const EditView* pSourceView )
2668{
2669 if (pSourceView)
2670 {
2671 bool bSelectionForTopView = false;
2672 if (pTopView && pTopView != pSourceView)
2673 bSelectionForTopView = true;
2674 bool bSelectionForTableView = false;
2675 if (pTableView && pTableView != pSourceView)
2676 bSelectionForTableView = true;
2677 if (bSelectionForTopView || bSelectionForTableView)
2678 {
2679 ESelection aSel(pSourceView->GetSelection());
2680 if (bSelectionForTopView)
2681 pTopView->SetSelection(aSel);
2682 if (bSelectionForTableView)
2684 }
2685 }
2686 // Only sync selection from topView if we are actually editing there
2687 else if (pTopView && pTableView)
2688 {
2691 }
2692}
2693
2695{
2696 if ( !bInOwnChange && ( eMode==SC_INPUT_TYPE || eMode==SC_INPUT_TABLE ) &&
2697 mpEditEngine && mpEditEngine->IsUpdateLayout() && pInputWin )
2698 {
2699 // Update input line from ModifyHdl for changes that are not
2700 // wrapped by DataChanging/DataChanged calls (like Drag&Drop)
2701 OUString aText(ScEditUtil::GetMultilineString(*mpEditEngine));
2702 lcl_RemoveTabs(aText);
2703 pInputWin->SetTextString(aText);
2704 }
2705}
2706
2710bool ScInputHandler::DataChanging( sal_Unicode cTyped, bool bFromCommand )
2711{
2712 if (pActiveViewSh)
2714 bInOwnChange = true; // disable ModifyHdl (reset in DataChanged)
2715
2716 if ( eMode == SC_INPUT_NONE )
2717 return StartTable( cTyped, bFromCommand, false, nullptr );
2718 else
2719 return false;
2720}
2721
2722void ScInputHandler::DataChanged( bool bFromTopNotify, bool bSetModified )
2723{
2725
2726 if (eMode==SC_INPUT_NONE)
2728
2729 if ( eMode == SC_INPUT_TOP && pTopView && !bFromTopNotify )
2730 {
2731 // table EditEngine is formatted below, input line needs formatting after paste
2732 // #i20282# not when called from the input line's modify handler
2734
2735 // #i23720# QuickFormatDoc hides the cursor, but can't show it again because it
2736 // can't safely access the EditEngine's current view, so the cursor has to be
2737 // shown again here.
2739 }
2740
2741 if (bSetModified)
2742 bModified = true;
2743 bSelIsRef = false;
2744
2746 RemoveRangeFinder(); // Delete attributes and labels
2747
2748 UpdateParenthesis(); // Highlight parentheses anew
2749
2751 {
2752 OUString aText;
2753 if (pInputWin)
2755 else
2756 aText = GetEditText(mpEditEngine.get());
2757 lcl_RemoveTabs(aText);
2758
2759 if ( pInputWin )
2760 pInputWin->SetTextString( aText );
2761
2763 {
2764 if (pActiveViewSh)
2765 {
2766 // TODO: deprecated?
2767 pActiveViewSh->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_FORMULA, aText.toUtf8());
2768 }
2769 }
2770 }
2771
2772 // If the cursor is before the end of a paragraph, parts are being pushed to
2773 // the right (independently from the eMode) -> Adapt View!
2774 // If the cursor is at the end, the StatusHandler of the ViewData is sufficient.
2775 //
2776 // First make sure the status handler is called now if the cursor
2777 // is outside the visible area
2778 mpEditEngine->QuickFormatDoc();
2779
2780 EditView* pActiveView = pTopView ? pTopView : pTableView;
2781 ESelection aSel;
2782 if (pActiveView && pActiveViewSh)
2783 {
2784 ScViewData& rViewData = pActiveViewSh->GetViewData();
2785
2786 bool bNeedGrow = ( rViewData.GetEditAdjust() != SvxAdjust::Left ); // Always right-aligned
2787 if (!bNeedGrow)
2788 {
2789 // Cursor before the end?
2790 aSel = pActiveView->GetSelection();
2791 aSel.Adjust();
2792 bNeedGrow = ( aSel.nEndPos != mpEditEngine->GetTextLen(aSel.nEndPara) );
2793 }
2794 if (!bNeedGrow)
2795 {
2796 bNeedGrow = rViewData.GetDocument().IsLayoutRTL( rViewData.GetTabNo() );
2797 }
2798 if (bNeedGrow)
2799 {
2800 // Adjust inplace view
2801 rViewData.EditGrowY();
2802 rViewData.EditGrowX();
2803 }
2804 }
2805
2807 {
2809 if (pActiveView)
2810 aSel = pActiveView->GetSelection();
2811
2814 aSel);
2815 }
2816
2818 bTextValid = false; // Changes only in the EditEngine
2819 bInOwnChange = false;
2820}
2821
2822bool ScInputHandler::StartsLikeFormula( std::u16string_view rStr ) const
2823{
2824 // For new input '+' and '-' may start the dreaded "lazy data typist"
2825 // formula input, editing existing formula content can only start with '='.
2826 return !rStr.empty() && (rStr[0] == '=' || (!mbEditingExistingContent && (rStr[0] == '+' || rStr[0] == '-')));
2827}
2828
2830{
2831 SfxApplication* pSfxApp = SfxGetpApp();
2832
2833 bool bIsFormula = !bProtected;
2834 if (bIsFormula)
2835 {
2836 const OUString& rText = mpEditEngine->GetText(0);
2837 bIsFormula = StartsLikeFormula(rText);
2838 }
2839
2840 if ( bIsFormula )
2841 {
2842 if (!bFormulaMode)
2843 {
2844 bFormulaMode = true;
2846 pSfxApp->Broadcast( SfxHint( SfxHintId::ScRefModeChanged ) );
2847 ScModule* pMod = SC_MOD();
2848 pMod->SetRefInputHdl(this);
2849 if (pInputWin)
2850 pInputWin->SetFormulaMode(true);
2851
2852 // in LOK, we always need to perform the GetFormulaData() call so
2853 // that the formula insertion works
2856
2859 }
2860 }
2861 else // Deactivate
2862 {
2863 if (bFormulaMode)
2864 {
2865 ShowRefFrame();
2866 bFormulaMode = false;
2867 pRefViewSh = nullptr;
2868 pSfxApp->Broadcast( SfxHint( SfxHintId::ScRefModeChanged ) );
2869 SC_MOD()->SetRefInputHdl(nullptr);
2870 if (pInputWin)
2871 pInputWin->SetFormulaMode(false);
2873 }
2874 }
2875}
2876
2878{
2879 // Modifying pActiveViewSh here would interfere with the bInEnterHandler / bRepeat
2880 // checks in NotifyChange, and lead to keeping the wrong value in pActiveViewSh.
2881 // A local variable is used instead.
2882 ScTabViewShell* pVisibleSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() );
2883 if ( !(pRefViewSh && pRefViewSh != pVisibleSh) )
2884 return;
2885
2886 bool bFound = false;
2887 SfxViewFrame& rRefFrame = pRefViewSh->GetViewFrame();
2888 SfxViewFrame* pOneFrame = SfxViewFrame::GetFirst();
2889 while ( pOneFrame && !bFound )
2890 {
2891 if ( pOneFrame == &rRefFrame )
2892 bFound = true;
2893 pOneFrame = SfxViewFrame::GetNext( *pOneFrame );
2894 }
2895
2896 if (bFound)
2897 {
2898 // We count on Activate working synchronously here
2899 // (pActiveViewSh is set while doing so)
2900 pRefViewSh->SetActive(); // Appear and SetViewFrame
2901
2902 // pLastState is set correctly in the NotifyChange from the Activate
2903 }
2904 else
2905 {
2906 OSL_FAIL("ViewFrame for reference input is not here anymore");
2907 }
2908}
2909
2911{
2912 EditView* pActiveView = pTopView ? pTopView : pTableView;
2913 if (!pActiveView)
2914 return;
2915
2916 ESelection aSel = pActiveView->GetSelection();
2917 aSel.nStartPara = aSel.nEndPara;
2918 aSel.nStartPos = aSel.nEndPos;
2919 if (pTableView)
2920 pTableView->SetSelection( aSel );
2921 if (pTopView)
2922 pTopView->SetSelection( aSel );
2923}
2924
2926{
2927 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
2928 if (!pViewFrm)
2929 return;
2930
2931 SfxBindings& rBindings = pViewFrm->GetBindings();
2932
2933 rBindings.Invalidate( SID_ATTR_CHAR_FONT );
2934 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
2935 rBindings.Invalidate( SID_ATTR_CHAR_COLOR );
2936
2937 rBindings.Invalidate( SID_ATTR_CHAR_WEIGHT );
2938 rBindings.Invalidate( SID_ATTR_CHAR_POSTURE );
2939 rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE );
2940 rBindings.Invalidate( SID_ATTR_CHAR_OVERLINE );
2941 rBindings.Invalidate( SID_ULINE_VAL_NONE );
2942 rBindings.Invalidate( SID_ULINE_VAL_SINGLE );
2943 rBindings.Invalidate( SID_ULINE_VAL_DOUBLE );
2944 rBindings.Invalidate( SID_ULINE_VAL_DOTTED );
2945
2946 rBindings.Invalidate( SID_HYPERLINK_GETLINK );
2947
2948 rBindings.Invalidate( SID_ATTR_CHAR_KERNING );
2949 rBindings.Invalidate( SID_SET_SUPER_SCRIPT );
2950 rBindings.Invalidate( SID_SET_SUB_SCRIPT );
2951 rBindings.Invalidate( SID_ATTR_CHAR_STRIKEOUT );
2952 rBindings.Invalidate( SID_ATTR_CHAR_SHADOWED );
2953
2954 rBindings.Invalidate( SID_SAVEDOC );
2955 rBindings.Invalidate( SID_DOC_MODIFIED );
2956}
2957
2958// --------------- public methods --------------------------------------------
2959
2960void ScInputHandler::SetMode( ScInputMode eNewMode, const OUString* pInitText, ScEditEngineDefaulter* pTopEngine )
2961{
2962 if ( eMode == eNewMode )
2963 return;
2964
2966
2967 if (bProtected)
2968 {
2970 StopInputWinEngine( true );
2971 if (pActiveViewSh)
2973 return;
2974 }
2975
2976 if (eNewMode != SC_INPUT_NONE && pActiveViewSh)
2977 // Disable paste mode when edit mode starts.
2979
2980 bInOwnChange = true; // disable ModifyHdl (reset below)
2981
2982 ScInputMode eOldMode = eMode;
2983 eMode = eNewMode;
2984 if (eOldMode == SC_INPUT_TOP && eNewMode != eOldMode)
2985 StopInputWinEngine( false );
2986
2988 {
2989 if (eOldMode == SC_INPUT_NONE) // not if switching between modes
2990 {
2991 if (StartTable(0, false, eMode == SC_INPUT_TABLE, pTopEngine))
2992 {
2993 if (pActiveViewSh)
2995 }
2996 }
2997
2998 if (pInitText)
2999 {
3000 mpEditEngine->SetTextCurrentDefaults(*pInitText);
3001 bModified = true;
3002 }
3003
3004 sal_Int32 nPara = mpEditEngine->GetParagraphCount()-1;
3005 sal_Int32 nLen = mpEditEngine->GetText(nPara).getLength();
3006 sal_uInt16 nCount = mpEditEngine->GetViewCount();
3007
3008 for (sal_uInt16 i=0; i<nCount; i++)
3009 {
3010 if ( eMode == SC_INPUT_TABLE && eOldMode == SC_INPUT_TOP )
3011 {
3012 // Keep Selection
3013 }
3014 else
3015 {
3016 mpEditEngine->GetView(i)->
3017 SetSelection( ESelection( nPara, nLen, nPara, nLen ) );
3018 }
3019 mpEditEngine->GetView(i)->ShowCursor(false);
3020 }
3021 }
3022
3025 {
3026 if (pTableView)
3028 }
3029 else
3030 {
3031 if (pTopView)
3033 }
3034
3035 if (eNewMode != eOldMode)
3037
3038 bInOwnChange = false;
3039}
3040
3044static bool lcl_IsNumber(std::u16string_view aString)
3045{
3046 size_t nLen = aString.size();
3047 for (size_t i=0; i<nLen; i++)
3048 {
3049 sal_Unicode c = aString[i];
3050 if ( c < '0' || c > '9' )
3051 return false;
3052 }
3053 return true;
3054}
3055
3056static void lcl_SelectionToEnd( EditView* pView )
3057{
3058 if ( pView )
3059 {
3060 EditEngine* pEngine = pView->GetEditEngine();
3061 sal_Int32 nParCnt = pEngine->GetParagraphCount();
3062 if ( nParCnt == 0 )
3063 nParCnt = 1;
3064 ESelection aSel( nParCnt-1, pEngine->GetTextLen(nParCnt-1) ); // empty selection, cursor at the end
3065 pView->SetSelection( aSel );
3066 }
3067}
3068
3069void ScInputHandler::EnterHandler( ScEnterMode nBlockMode, bool bBeforeSavingInLOK )
3070{
3073 return;
3074
3075 // Macro calls for validity can cause a lot of problems, so inhibit
3076 // nested calls of EnterHandler().
3077 if (bInEnterHandler) return;
3078 bInEnterHandler = true;
3079 bInOwnChange = true; // disable ModifyHdl (reset below)
3080 mbPartialPrefix = false;
3081
3083
3084 bool bMatrix = ( nBlockMode == ScEnterMode::MATRIX );
3085
3086 SfxApplication* pSfxApp = SfxGetpApp();
3087 std::unique_ptr<EditTextObject> pObject;
3088 std::unique_ptr<ScPatternAttr> pCellAttrs;
3089 bool bForget = false; // Remove due to validity?
3090
3091 OUString aString = GetEditText(mpEditEngine.get());
3092 OUString aPreAutoCorrectString(aString);
3093 EditView* pActiveView = pTopView ? pTopView : pTableView;
3094 if (bModified && pActiveView && !aString.isEmpty() && !lcl_IsNumber(aString))
3095 {
3096 if (pColumnData && miAutoPosColumn != pColumnData->end())
3097 {
3098 // #i47125# If AutoInput appended something, do the final AutoCorrect
3099 // with the cursor at the end of the input.
3102 }
3103
3104 vcl::Window* pFrameWin = pActiveViewSh ? pActiveViewSh->GetFrameWin() : nullptr;
3105
3106 if (pTopView)
3107 pTopView->CompleteAutoCorrect(); // CompleteAutoCorrect for both Views
3108 if (pTableView)
3109 pTableView->CompleteAutoCorrect(pFrameWin);
3110 aString = GetEditText(mpEditEngine.get());
3111 }
3112 lcl_RemoveTabs(aString);
3113 lcl_RemoveTabs(aPreAutoCorrectString);
3114
3115 // Test if valid (always with simple string)
3117 {
3120 if (pData && pData->HasErrMsg())
3121 {
3122 // #i67990# don't use pLastPattern in EnterHandler
3123 const ScPatternAttr* pPattern = rDoc.GetPattern( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab() );
3124
3125 bool bOk;
3126
3127 if (pData->GetDataMode() == SC_VALID_CUSTOM)
3128 {
3129 bOk = pData->IsDataValidCustom( aString, *pPattern, aCursorPos, ScValidationData::CustomValidationPrivateAccess() );
3130 }
3131 else
3132 {
3133 bOk = pData->IsDataValid( aString, *pPattern, aCursorPos );
3134 }
3135
3136 if (!bOk)
3137 {
3138 pActiveViewSh->StopMarking(); // (the InfoBox consumes the MouseButtonUp)
3139
3140 // tdf#125917 Release the grab that a current mouse-down event being handled
3141 // by ScTabView has put on the mouse via its SelectionEngine.
3142 // Otherwise the warning box cannot interact with the mouse
3143 if (ScTabView* pView = pActiveViewSh->GetViewData().GetView())
3144 {
3145 if (ScViewSelectionEngine* pSelEngine = pView->GetSelEngine())
3146 pSelEngine->ReleaseMouse();
3147 }
3148
3149 if (bBeforeSavingInLOK)
3150 {
3151 // Invalid entry but not applied to the document model.
3152 // Exit to complete the "save", leaving the edit view as it is
3153 // for the user to continue after save.
3154 bInOwnChange = false;
3155 bInEnterHandler = false;
3156 return;
3157 }
3158
3159 if (pData->DoError(pActiveViewSh->GetFrameWeld(), aString, aCursorPos))
3160 bForget = true; // Do not take over input
3161 }
3162 }
3163 }
3164
3165 // Check for input into DataPilot table
3166 if ( bModified && pActiveViewSh && !bForget )
3167 {
3170 if ( pDPObj )
3171 {
3172 // Any input within the DataPilot table is either a valid renaming
3173 // or an invalid action - normal cell input is always aborted
3175 bForget = true;
3176 }
3177 }
3178
3179 std::vector<editeng::MisspellRanges> aMisspellRanges;
3180 // UpdateLayout must be true during CompleteOnlineSpelling
3181 const bool bUpdateLayout = mpEditEngine->SetUpdateLayout( true );
3182 mpEditEngine->CompleteOnlineSpelling();
3183 bool bSpellErrors = !bFormulaMode && mpEditEngine->HasOnlineSpellErrors();
3184 if ( bSpellErrors )
3185 {
3186 // #i3820# If the spell checker flags numerical input as error,
3187 // it still has to be treated as number, not EditEngine object.
3188 if ( pActiveViewSh )
3189 {
3191 // #i67990# don't use pLastPattern in EnterHandler
3192 const ScPatternAttr* pPattern = rDoc.GetPattern( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab() );
3193 if (pPattern)
3194 {
3195 SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
3196 // without conditional format, as in ScColumn::SetString
3197 sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
3198 double nVal;
3199 if ( pFormatter->IsNumberFormat( aString, nFormat, nVal ) )
3200 {
3201 bSpellErrors = false; // ignore the spelling errors
3202 }
3203 }
3204 }
3205 }
3206
3207 // After RemoveAdjust, the EditView must not be repainted (has wrong font size etc).
3208 // SetUpdateLayout must come after CompleteOnlineSpelling.
3209 // The view is hidden in any case below (Broadcast).
3210 mpEditEngine->SetUpdateLayout( false );
3211
3212 if ( bModified && !bForget ) // What is being entered (text/object)?
3213 {
3214 sal_Int32 nParCnt = mpEditEngine->GetParagraphCount();
3215 if ( nParCnt == 0 )
3216 nParCnt = 1;
3217
3218 bool bUniformAttribs = true;
3219 SfxItemSet aPara1Attribs = mpEditEngine->GetAttribs(0, 0, mpEditEngine->GetTextLen(0));
3220 for (sal_Int32 nPara = 1; nPara < nParCnt; ++nPara)
3221 {
3222 SfxItemSet aPara2Attribs = mpEditEngine->GetAttribs(nPara, 0, mpEditEngine->GetTextLen(nPara));
3223 if (!(aPara1Attribs == aPara2Attribs))
3224 {
3225 // Paragraph format different from that of the 1st paragraph.
3226 bUniformAttribs = false;
3227 break;
3228 }
3229 }
3230
3231 ESelection aSel( 0, 0, nParCnt-1, mpEditEngine->GetTextLen(nParCnt-1) );
3232 SfxItemSet aOldAttribs = mpEditEngine->GetAttribs( aSel );
3233 const SfxPoolItem* pItem = nullptr;
3234
3235 // Find common (cell) attributes before RemoveAdjust
3236 if ( pActiveViewSh && bUniformAttribs )
3237 {
3238 std::optional<SfxItemSet> pCommonAttrs;
3239 for (sal_uInt16 nId = EE_CHAR_START; nId <= EE_CHAR_END; nId++)
3240 {
3241 SfxItemState eState = aOldAttribs.GetItemState( nId, false, &pItem );
3242 if ( eState == SfxItemState::SET &&
3245 *pItem != pEditDefaults->Get(nId) )
3246 {
3247 if ( !pCommonAttrs )
3248 pCommonAttrs.emplace( mpEditEngine->GetEmptyItemSet() );
3249 pCommonAttrs->Put( *pItem );
3250 }
3251 }
3252
3253 if ( pCommonAttrs )
3254 {
3256 pCellAttrs = std::make_unique<ScPatternAttr>(rDoc.GetPool());
3257 pCellAttrs->GetFromEditItemSet( &*pCommonAttrs );
3258 }
3259 }
3260
3261 // Clear ParaAttribs (including adjustment)
3262 RemoveAdjust();
3263
3264 bool bAttrib = false; // Formatting present?
3265
3266 // check if EditObject is needed
3267 if (nParCnt > 1)
3268 bAttrib = true;
3269 else
3270 {
3271 for (sal_uInt16 nId = EE_CHAR_START; nId <= EE_CHAR_END && !bAttrib; nId++)
3272 {
3273 SfxItemState eState = aOldAttribs.GetItemState( nId, false, &pItem );
3274 if (eState == SfxItemState::DONTCARE)
3275 bAttrib = true;
3276 else if (eState == SfxItemState::SET)
3277 {
3278 // Keep same items in EditEngine as in ScEditAttrTester
3281 {
3282 if ( *pItem != pEditDefaults->Get(nId) )
3283 bAttrib = true;
3284 }
3285 }
3286 }
3287
3288 // Contains fields?
3289 SfxItemState eFieldState = aOldAttribs.GetItemState( EE_FEATURE_FIELD, false );
3290 if ( eFieldState == SfxItemState::DONTCARE || eFieldState == SfxItemState::SET )
3291 bAttrib = true;
3292
3293 // Not converted characters?
3294 SfxItemState eConvState = aOldAttribs.GetItemState( EE_FEATURE_NOTCONV, false );
3295 if ( eConvState == SfxItemState::DONTCARE || eConvState == SfxItemState::SET )
3296 bAttrib = true;
3297
3298 // Always recognize formulas as formulas
3299 // We still need the preceding test due to cell attributes
3300 }
3301
3302 if (bSpellErrors)
3303 mpEditEngine->GetAllMisspellRanges(aMisspellRanges);
3304
3305 if (bMatrix)
3306 bAttrib = false;
3307
3308 if (bAttrib)
3309 {
3310 mpEditEngine->ClearSpellErrors();
3311 pObject = mpEditEngine->CreateTextObject();
3312 }
3313 else if (SC_MOD()->GetAppOptions().GetAutoComplete()) // Adjust Upper/Lower case
3314 {
3315 // Perform case-matching only when the typed text is partial.
3316 if (pColumnData && aAutoSearch.getLength() < aString.getLength())
3317 aString = getExactMatch(*pColumnData, aString);
3318 }
3319 }
3320
3321 // Don't rely on ShowRefFrame switching the active view synchronously
3322 // execute the function directly on the correct view's bindings instead
3323 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
3325
3326 if (bFormulaMode)
3327 {
3328 ShowRefFrame();
3329
3330 if (pExecuteSh)
3331 {
3332 pExecuteSh->SetTabNo(aCursorPos.Tab());
3333 pExecuteSh->ActiveGrabFocus();
3334 }
3335
3336 bFormulaMode = false;
3337 pSfxApp->Broadcast( SfxHint( SfxHintId::ScRefModeChanged ) );
3338 SC_MOD()->SetRefInputHdl(nullptr);
3339 if (pInputWin)
3340 pInputWin->SetFormulaMode(false);
3342 }
3343 pRefViewSh = nullptr; // Also without FormulaMode due to FunctionsAutoPilot
3345 ResetAutoPar();
3346
3347 bool bOldMod = bModified;
3348
3349 bModified = false;
3350 bSelIsRef = false;
3352 StopInputWinEngine(true);
3353
3354 // Text input (through number formats) or ApplySelectionPattern modify
3355 // the cell's attributes, so pLastPattern is no longer valid
3356 pLastPattern = nullptr;
3357
3358 if (bOldMod && !bProtected && !bForget)
3359 {
3360 bool bInsertPreCorrectedString = true;
3361 // No typographic quotes in formulas
3362 if (aString.startsWith("="))
3363 {
3365 if ( pAuto )
3366 {
3367 bInsertPreCorrectedString = false;
3368 OUString aReplace(pAuto->GetStartDoubleQuote());
3369 if( aReplace.isEmpty() )
3371 if( aReplace != "\"" )
3372 aString = aString.replaceAll( aReplace, "\"" );
3373
3374 aReplace = OUString(pAuto->GetEndDoubleQuote());
3375 if( aReplace.isEmpty() )
3377 if( aReplace != "\"" )
3378 aString = aString.replaceAll( aReplace, "\"" );
3379
3380 aReplace = OUString(pAuto->GetStartSingleQuote());
3381 if( aReplace.isEmpty() )
3383 if( aReplace != "'" )
3384 aString = aString.replaceAll( aReplace, "'" );
3385
3386 aReplace = OUString(pAuto->GetEndSingleQuote());
3387 if( aReplace.isEmpty() )
3389 if( aReplace != "'" )
3390 aString = aString.replaceAll( aReplace, "'");
3391 }
3392 }
3393
3394 pSfxApp->Broadcast( SfxHint( SfxHintId::ScKillEditViewNoPaint ) );
3395
3396 if ( pExecuteSh )
3397 {
3398 SfxBindings& rBindings = pExecuteSh->GetViewFrame().GetBindings();
3399
3400 sal_uInt16 nId = FID_INPUTLINE_ENTER;
3401 if ( nBlockMode == ScEnterMode::BLOCK )
3402 nId = FID_INPUTLINE_BLOCK;
3403 else if ( nBlockMode == ScEnterMode::MATRIX )
3404 nId = FID_INPUTLINE_MATRIX;
3405
3406 const SfxPoolItem* aArgs[2];
3407 aArgs[1] = nullptr;
3408
3409 if ( bInsertPreCorrectedString && aString != aPreAutoCorrectString )
3410 {
3411 ScInputStatusItem aItem(FID_INPUTLINE_STATUS,
3413 aPreAutoCorrectString, pObject.get());
3414 aArgs[0] = &aItem;
3415 rBindings.Execute(nId, aArgs);
3416 }
3417
3418 ScInputStatusItem aItemCorrected(FID_INPUTLINE_STATUS,
3420 aString, pObject.get());
3421 if ( !aMisspellRanges.empty() )
3422 aItemCorrected.SetMisspellRanges(&aMisspellRanges);
3423
3424 aArgs[0] = &aItemCorrected;
3425 rBindings.Execute(nId, aArgs);
3426 }
3427
3428 pLastState.reset(); // pLastState still contains the old text
3429 }
3430 else
3431 pSfxApp->Broadcast( SfxHint( SfxHintId::ScKillEditView ) );
3432
3433 if ( bOldMod && pExecuteSh && pCellAttrs && !bForget )
3434 {
3435 // Combine with input?
3436 pExecuteSh->ApplySelectionPattern( *pCellAttrs, true );
3437 pExecuteSh->AdjustBlockHeight();
3438 }
3439
3440 HideTip();
3441 HideTipBelow();
3442
3444 aFormText.clear();
3445
3447 bInOwnChange = false;
3448 bInEnterHandler = false;
3449 if (bUpdateLayout)
3450 mpEditEngine->SetUpdateLayout( true );
3451}
3452
3454{
3455 bInOwnChange = true; // Also without FormulaMode due to FunctionsAutoPilot
3456
3458
3459 bModified = false;
3460 mbPartialPrefix = false;
3462
3463 // Don't rely on ShowRefFrame switching the active view synchronously
3464 // execute the function directly on the correct view's bindings instead
3465 // pRefViewSh is reset in ShowRefFrame - get pointer before ShowRefFrame call
3467
3468 if (bFormulaMode)
3469 {
3470 ShowRefFrame();
3471 if (pExecuteSh)
3472 {
3473 pExecuteSh->SetTabNo(aCursorPos.Tab());
3474 pExecuteSh->ActiveGrabFocus();
3475 }
3476 bFormulaMode = false;
3477 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScRefModeChanged ) );
3478 SC_MOD()->SetRefInputHdl(nullptr);
3479 if (pInputWin)
3480 pInputWin->SetFormulaMode(false);
3482 }
3483 pRefViewSh = nullptr; // Also without FormulaMode due to FunctionsAutoPilot
3485 ResetAutoPar();
3486
3488 StopInputWinEngine( true );
3489 SCCOL nMaxCol(MAXCOL);
3490 if (pExecuteSh)
3491 {
3492 pExecuteSh->StopEditShell();
3493 nMaxCol = pExecuteSh->GetViewData().GetDocument().MaxCol();
3494 }
3495
3496 aCursorPos.Set(nMaxCol+1,0,0); // Invalid flag
3497 mpEditEngine->SetTextCurrentDefaults(OUString());
3498
3499 if ( !pLastState && pExecuteSh )
3500 pExecuteSh->UpdateInputHandler( true ); // Update status again
3501 else
3502 NotifyChange( pLastState.get(), true );
3503
3505 aFormText.clear();
3506
3507 bInOwnChange = false;
3508
3509 if ( comphelper::LibreOfficeKit::isActive() && pExecuteSh )
3510 {
3511 // Clear
3512 std::vector<ReferenceMark> aReferenceMarks;
3514 }
3515}
3516
3518{
3519 // References to unnamed document; that doesn't work
3520 return bFormulaMode && pRefViewSh
3522 && !pDocSh->HasName();
3523}
3524
3526{
3529 if (!pTableView && !pTopView)
3530 return; // E.g. FillMode
3531
3532 DataChanging(); // Cannot be new
3533
3535 OUString aText = GetEditText(mpEditEngine.get());
3536 sal_Unicode cLastChar = 0;
3537 sal_Int32 nPos = aText.getLength() - 1;
3538 while (nPos >= 0) //checking space
3539 {
3540 cLastChar = aText[nPos];
3541 if (cLastChar != ' ')
3542 break;
3543 --nPos;
3544 }
3545
3546 bool bAppendSeparator = (cLastChar != '(' && cLastChar != cSep && cLastChar != '=');
3547 if (bAppendSeparator)
3548 {
3549 if (pTableView)
3550 pTableView->InsertText( OUString(cSep) );
3551 if (pTopView)
3552 pTopView->InsertText( OUString(cSep) );
3553 }
3554
3555 DataChanged();
3556}
3557
3558void ScInputHandler::SetReference( const ScRange& rRef, const ScDocument& rDoc )
3559{
3560 HideTip();
3561
3562 const ScDocument* pThisDoc = nullptr;
3563 if (pRefViewSh)
3564 pThisDoc = &pRefViewSh->GetViewData().GetDocument();
3565 bool bOtherDoc = (pThisDoc != &rDoc);
3566 if (bOtherDoc && !rDoc.GetDocumentShell()->HasName())
3567 {
3568 // References to unnamed document; that doesn't work
3569 // SetReference should not be called, then
3570 return;
3571 }
3572 if (!pThisDoc)
3573 pThisDoc = &rDoc;
3574
3576 if (!pTableView && !pTopView)
3577 return; // E.g. FillMode
3578
3579 // Never overwrite the "="!
3580 EditView* pActiveView = pTopView ? pTopView : pTableView;
3581 ESelection aSel = pActiveView->GetSelection();
3582 aSel.Adjust();
3583 if ( aSel.nStartPara == 0 && aSel.nStartPos == 0 )
3584 return;
3585
3586 DataChanging(); // Cannot be new
3587
3588 // Turn around selection if backwards.
3589 if (pTableView)
3590 {
3591 ESelection aTabSel = pTableView->GetSelection();
3592 if (aTabSel.nStartPos > aTabSel.nEndPos && aTabSel.nStartPara == aTabSel.nEndPara)
3593 {
3594 aTabSel.Adjust();
3595 pTableView->SetSelection(aTabSel);
3596 }
3597 }
3598 if (pTopView)
3599 {
3600 ESelection aTopSel = pTopView->GetSelection();
3601 if (aTopSel.nStartPos > aTopSel.nEndPos && aTopSel.nStartPara == aTopSel.nEndPara)
3602 {
3603 aTopSel.Adjust();
3604 pTopView->SetSelection(aTopSel);
3605 }
3606 }
3607
3608 // Create string from reference, in the syntax of the document being edited.
3609 OUString aRefStr;
3610 const ScAddress::Details aAddrDetails( *pThisDoc, aCursorPos );
3611 if (bOtherDoc)
3612 {
3613 // Reference to other document
3614 OSL_ENSURE(rRef.aStart.Tab()==rRef.aEnd.Tab(), "nStartTab!=nEndTab");
3615
3616 // Always 3D and absolute.
3617 OUString aTmp(rRef.Format(rDoc, ScRefFlags::VALID | ScRefFlags::TAB_ABS_3D, aAddrDetails));
3618
3619 SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
3620 // #i75893# convert escaped URL of the document to something user friendly
3622
3623 switch(aAddrDetails.eConv)
3624 {
3628 aRefStr = "[\'" + aFileName + "']";
3629 break;
3631 default:
3632 aRefStr = "\'" + aFileName + "'#";
3633 break;
3634 }
3635 aRefStr += aTmp;
3636 }
3637 else
3638 {
3639 if ( rRef.aStart.Tab() != aCursorPos.Tab() ||
3640 rRef.aStart.Tab() != rRef.aEnd.Tab() )
3641 // pointer-selected => absolute sheet reference
3642 aRefStr = rRef.Format(rDoc, ScRefFlags::VALID | ScRefFlags::TAB_ABS_3D, aAddrDetails);
3643 else
3644 aRefStr = rRef.Format(rDoc, ScRefFlags::VALID, aAddrDetails);
3645 }
3646 bool bLOKShowSelect = true;
3648 bLOKShowSelect = false;
3649
3650 if (pTableView || pTopView)
3651 {
3652 if (pTableView)
3653 pTableView->InsertText( aRefStr, true, bLOKShowSelect );
3654 if (pTopView)
3655 pTopView->InsertText( aRefStr, true, bLOKShowSelect );
3656
3657 DataChanged();
3658 }
3659
3660 bSelIsRef = true;
3661}
3662
3663void ScInputHandler::InsertFunction( const OUString& rFuncName, bool bAddPar )
3664{
3665 if ( eMode == SC_INPUT_NONE )
3666 {
3667 OSL_FAIL("InsertFunction, not during input mode");
3668 return;
3669 }
3670
3672 if (!pTableView && !pTopView)
3673 return; // E.g. FillMode
3674
3675 DataChanging(); // Cannot be new
3676
3677 OUString aText = rFuncName;
3678 if (bAddPar)
3679 aText += "()";
3680
3681 if (pTableView)
3682 {
3683 pTableView->InsertText( aText );
3684 if (bAddPar)
3685 {
3687 --aSel.nStartPos;
3688 --aSel.nEndPos;
3689 pTableView->SetSelection(aSel);
3690 }
3691 }
3692 if (pTopView)
3693 {
3694 pTopView->InsertText( aText );
3695 if (bAddPar)
3696 {
3698 --aSel.nStartPos;
3699 --aSel.nEndPos;
3700 pTopView->SetSelection(aSel);
3701 }
3702 }
3703
3704 DataChanged();
3705
3706 if (bAddPar)
3707 AutoParAdded();
3708}
3709
3711{
3712 if ( eMode == SC_INPUT_NONE )
3713 {
3714 OSL_FAIL("ClearText, not during input mode");
3715 return;
3716 }
3717
3719 if (!pTableView && !pTopView)
3720 return; // E.g. FillMode
3721
3722 DataChanging(); // Cannot be new
3723
3724 if (pTableView)
3725 {
3727 pTableView->SetSelection( ESelection(0,0, 0,0) );
3728 }
3729 if (pTopView)
3730 {
3731 pTopView->GetEditEngine()->SetText( "" );
3732 pTopView->SetSelection( ESelection(0,0, 0,0) );
3733 }
3734
3735 DataChanged();
3736}
3737
3738bool ScInputHandler::KeyInput( const KeyEvent& rKEvt, bool bStartEdit /* = false */ )
3739{
3740 vcl::KeyCode aCode = rKEvt.GetKeyCode();
3741 sal_uInt16 nModi = aCode.GetModifier();
3742 bool bShift = aCode.IsShift();
3743 bool bControl = aCode.IsMod1();
3744 bool bAlt = aCode.IsMod2();
3745 sal_uInt16 nCode = aCode.GetCode();
3746 sal_Unicode nChar = rKEvt.GetCharCode();
3747
3748 if (bAlt && !bControl && nCode != KEY_RETURN)
3749 // Alt-Return and Alt-Ctrl-* are accepted. Everything else with ALT are not.
3750 return false;
3751
3752 // There is a partial autocomplete suggestion.
3753 // Allow its completion with right arrow key (without modifiers).
3754 if (mbPartialPrefix && nCode == KEY_RIGHT && !bControl && !bShift && !bAlt &&
3755 (pTopView || pTableView))
3756 {
3757 if (pTopView)
3758 pTopView->PostKeyEvent(KeyEvent(0, css::awt::Key::MOVE_TO_END_OF_PARAGRAPH));
3759 if (pTableView)
3760 pTableView->PostKeyEvent(KeyEvent(0, css::awt::Key::MOVE_TO_END_OF_PARAGRAPH));
3761
3762 mbPartialPrefix = false;
3763
3764 // Indicate that this event has been consumed and ScTabViewShell should not act on this.
3765 return true;
3766 }
3767
3768 if (!bControl && nCode == KEY_TAB)
3769 {
3770 // Normal TAB moves the cursor right.
3771 EnterHandler();
3772
3773 if (pActiveViewSh)
3774 pActiveViewSh->FindNextUnprot( bShift, true );
3775 return true;
3776 }
3777
3778 bool bInputLine = ( eMode==SC_INPUT_TOP );
3779
3780 bool bUsed = false;
3781 bool bSkip = false;
3782 bool bDoEnter = false;
3783
3784 switch ( nCode )
3785 {
3786 case KEY_RETURN:
3787 // New line when in the input line and Shift/Ctrl-Enter is pressed,
3788 // or when in a cell and Ctrl-Enter is pressed.
3789 if ((pInputWin && bInputLine && bControl != bShift) || (!bInputLine && bControl && !bShift))
3790 {
3791 bDoEnter = true;
3792 }
3793 else if (nModi == 0 && nTipVisible && pFormulaData && miAutoPosFormula != pFormulaData->end())
3794 {
3796 bUsed = true;
3797 }
3798 else if ( nModi == 0 && nTipVisible && !aManualTip.isEmpty() )
3799 {
3801 bUsed = true;
3802 }
3803 else
3804 {
3806 if ( bShift && bControl )
3807 nMode = ScEnterMode::MATRIX;
3808 else if ( bAlt )
3809 nMode = ScEnterMode::BLOCK;
3810 EnterHandler( nMode );
3811
3812 if (pActiveViewSh)
3813 pActiveViewSh->MoveCursorEnter( bShift && !bControl );
3814
3815 bUsed = true;
3816 }
3817 break;
3818 case KEY_TAB:
3819 if (bControl && !bAlt)
3820 {
3822 {
3823 // Iterate
3824 NextFormulaEntry( bShift );
3825 bUsed = true;
3826 }
3827 else if (pColumnData && bUseTab)
3828 {
3829 // Iterate through AutoInput entries
3830 NextAutoEntry( bShift );
3831 bUsed = true;
3832 }
3833 }
3834 break;
3835 case KEY_ESCAPE:
3836 if ( nTipVisible )
3837 {
3838 HideTip();
3839 bUsed = true;
3840 }
3841 else if( nTipVisibleSec )
3842 {
3843 HideTipBelow();
3844 bUsed = true;
3845 }
3846 else if (eMode != SC_INPUT_NONE)
3847 {
3848 CancelHandler();
3849 bUsed = true;
3850 }
3851 else
3852 bSkip = true;
3853 break;
3854 case KEY_F2:
3855 if ( !bShift && !bControl && !bAlt && eMode == SC_INPUT_TABLE )
3856 {
3858 bUsed = true;
3859 }
3860 break;
3861 }
3862
3863 // Only execute cursor keys if already in EditMode
3864 // E.g. due to Shift-Ctrl-PageDn (not defined as an accelerator)
3865 bool bCursorKey = EditEngine::DoesKeyMoveCursor(rKEvt);
3866 bool bInsKey = ( nCode == KEY_INSERT && !nModi ); // Treat Insert like Cursorkeys
3867 if ( !bUsed && !bSkip && ( bDoEnter || EditEngine::DoesKeyChangeText(rKEvt) ||
3868 ( eMode != SC_INPUT_NONE && ( bCursorKey || bInsKey ) ) ) )
3869 {
3870 HideTip();
3871 HideTipBelow();
3872
3873 if (bSelIsRef)
3874 {
3876 bSelIsRef = false;
3877 }
3878
3880 bool bNewView = DataChanging( nChar );
3881
3882 if (bProtected) // Protected cell?
3883 bUsed = true; // Don't forward KeyEvent
3884 else // Changes allowed
3885 {
3886 if (bNewView ) // Create anew
3887 {
3888 if (pActiveViewSh)
3891 if (eMode==SC_INPUT_NONE)
3892 if (pTableView || pTopView)
3893 {
3894 OUString aStrLoP;
3895
3896 if (bStartEdit && nCellPercentFormatDecSep != 0 &&
3897 ((nChar >= '0' && nChar <= '9') || nChar == '-' || nChar == nCellPercentFormatDecSep))
3898 {
3899 aStrLoP = "%";
3900 }
3901
3902 if (pTableView)
3903 {
3904 pTableView->GetEditEngine()->SetText( aStrLoP );
3905 if ( !aStrLoP.isEmpty() )
3906 pTableView->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3907
3908 // Don't call SetSelection if the string is empty anyway,
3909 // to avoid breaking the bInitial handling in ScViewData::EditGrowY
3910 }
3911 if (pTopView)
3912 {
3913 pTopView->GetEditEngine()->SetText( aStrLoP );
3914 if ( !aStrLoP.isEmpty() )
3915 pTopView->SetSelection( ESelection(0,0, 0,0) ); // before the '%'
3916 }
3917 }
3918 SyncViews();
3919 }
3920
3921 if (pTableView || pTopView)
3922 {
3923 if (bDoEnter)
3924 {
3925 if (pTableView)
3927 bUsed = true;
3928 if (pTopView)
3930 bUsed = true;
3931 }
3932 else if ( nAutoPar && nChar == ')' && CursorAtClosingPar() )
3933 {
3935 bUsed = true;
3936 }
3937 else
3938 {
3939 if (pTableView)
3940 {
3941 if (pTopView)
3942 pTableView->SetControlWord(pTableView->GetControlWord() | EVControlBits::SINGLELINEPASTE);
3943
3944 vcl::Window* pFrameWin = pActiveViewSh ? pActiveViewSh->GetFrameWin() : nullptr;
3945 if ( pTableView->PostKeyEvent( rKEvt, pFrameWin ) )
3946 bUsed = true;
3947
3948 pTableView->SetControlWord(pTableView->GetControlWord() & ~EVControlBits::SINGLELINEPASTE);
3949 }
3950 if (pTopView)
3951 {
3952 if ( bUsed && rKEvt.GetKeyCode().GetFunction() == KeyFuncType::CUT )
3954 else if ( pTopView->PostKeyEvent( rKEvt ) )
3955 bUsed = true;
3956 }
3957 }
3958
3959 // AutoInput:
3960 if ( bUsed && SC_MOD()->GetAppOptions().GetAutoComplete() )
3961 {
3962 bUseTab = false;
3963 if (pFormulaData)
3964 miAutoPosFormula = pFormulaData->end(); // do not search further
3965 if (pColumnData)
3967
3968 KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
3969 if ( nChar && nChar != 8 && nChar != 127 && // no 'backspace', no 'delete'
3970 KeyFuncType::CUT != eFunc) // and no 'CTRL-X'
3971 {
3972 if (bFormulaMode)
3974 else
3975 UseColData();
3976 }
3977 }
3978
3979 // When the selection is changed manually or an opening parenthesis
3980 // is typed, stop overwriting parentheses
3981 if ( bUsed && nChar == '(' )
3982 ResetAutoPar();
3983
3984 if ( KEY_INSERT == nCode )
3985 {
3986 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
3987 if (pViewFrm)
3988 pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
3989 }
3990 if( bUsed && bFormulaMode && ( bCursorKey || bInsKey || nCode == KEY_DELETE || nCode == KEY_BACKSPACE ) )
3991 {
3992 ShowTipCursor();
3993 }
3994 if( bUsed && bFormulaMode && nCode == KEY_BACKSPACE )
3995 {
3997 }
3998
3999 }
4000
4001 // #i114511# don't count cursor keys as modification
4002 bool bSetModified = !bCursorKey;
4003 DataChanged(false, bSetModified); // also calls UpdateParenthesis()
4004
4005 // In the LOK case, we want to set the document modified state
4006 // right away at the start of the edit, so that the content is
4007 // saved even when the user leaves the document before hitting
4008 // Enter
4011
4013 }
4014 }
4015
4016 if (pTopView && eMode != SC_INPUT_NONE)
4017 SyncViews();
4018
4019 return bUsed;
4020}
4021
4023{
4024 if (eMode != SC_INPUT_NONE)
4025 {
4027 if (pTableView || pTopView)
4028 {
4029 if (pTableView)
4031 else if (pTopView) // call only once
4032 return pTopView->GetSurroundingText();
4033 }
4034 }
4035 return OUString();
4036}
4037
4039{
4040 if (eMode != SC_INPUT_NONE)
4041 {
4043 if (pTableView || pTopView)
4044 {
4045 if (pTableView)
4047 else if (pTopView) // call only once
4049 }
4050 }
4051 return Selection(0, 0);
4052}
4053
4055{
4056 if (eMode != SC_INPUT_NONE)
4057 {
4059 if (pTableView || pTopView)
4060 {
4061 if (pTableView)
4062 return pTableView->DeleteSurroundingText(rSelection);
4063 else if (pTopView) // call only once
4064 return pTopView->DeleteSurroundingText(rSelection);
4065 }
4066 }
4067 return false;
4068}
4069
4071{
4072 if ( rCEvt.GetCommand() == CommandEventId::CursorPos )
4073 {
4074 // For CommandEventId::CursorPos, do as little as possible, because
4075 // with remote VCL, even a ShowCursor will generate another event.
4076 if ( eMode != SC_INPUT_NONE )
4077 {
4079 if (pTableView || pTopView)
4080 {
4081 if (pTableView)
4082 pTableView->Command( rCEvt );
4083 else if (pTopView) // call only once
4084 pTopView->Command( rCEvt );
4085 }
4086 }
4087 }
4088 else if ( rCEvt.GetCommand() == CommandEventId::QueryCharPosition )
4089 {
4090 if ( eMode != SC_INPUT_NONE )
4091 {
4093 if (pTableView || pTopView)
4094 {
4095 if (pTableView)
4096 pTableView->Command( rCEvt );
4097 else if (pTopView) // call only once
4098 pTopView->Command( rCEvt );
4099 }
4100 }
4101 }
4102 else
4103 {
4104 HideTip();
4105 HideTipBelow();
4106
4107 if ( bSelIsRef )
4108 {
4110 bSelIsRef = false;
4111 }
4112
4114 bool bNewView = DataChanging( 0, true );
4115
4116 if (!bProtected) // changes allowed
4117 {
4118 if (bNewView) // create new edit view
4119 {
4120 if (pActiveViewSh)
4123 if (eMode==SC_INPUT_NONE)
4124 if (pTableView || pTopView)
4125 {
4126 if (pTableView)
4127 {
4129 pTableView->SetSelection( ESelection(0,0, 0,0) );
4130 }
4131 if (pTopView)
4132 {
4133 pTopView->GetEditEngine()->SetText( "" );
4134 pTopView->SetSelection( ESelection(0,0, 0,0) );
4135 }
4136 }
4137 SyncViews();
4138 }
4139
4140 if (pTableView || pTopView)
4141 {
4142 if (pTableView)
4143 pTableView->Command( rCEvt );
4144 if (pTopView)
4145 pTopView->Command( rCEvt );
4146
4147 if ( rCEvt.GetCommand() == CommandEventId::EndExtTextInput )
4148 {
4149 // AutoInput after ext text input
4150
4151 if (pFormulaData)
4153 if (pColumnData)
4155
4156 if (bFormulaMode)
4158 else
4159 UseColData();
4160 }
4161 }
4162
4163 DataChanged(); // calls UpdateParenthesis()
4165 }
4166
4167 if (pTopView && eMode != SC_INPUT_NONE)
4168 SyncViews();
4169 }
4170}
4171
4173 bool bForce, ScTabViewShell* pSourceSh,
4174 bool bStopEditing)
4175{
4176 // If the call originates from a macro call in the EnterHandler,
4177 // return immediately and don't mess up the status
4178 if (bInEnterHandler)
4179 return;
4180
4181 bool bRepeat = (pState == pLastState.get());
4182 if (!bRepeat && pState && pLastState)
4183 bRepeat = (*pState == *pLastState);
4184 if (bRepeat && !bForce)
4185 return;
4186
4187 bInOwnChange = true; // disable ModifyHdl (reset below)
4188
4189 if ( pState && !pLastState ) // Enable again
4190 bForce = true;
4191
4192 bool bHadObject = pLastState && pLastState->GetEditData();
4193
4195 if ( pSourceSh )
4196 pActiveViewSh = pSourceSh;
4197 else
4199
4201
4202 if ( pState != pLastState.get() )
4203 {
4204 pLastState.reset( pState ? new ScInputHdlState( *pState ) : nullptr);
4205 }
4206
4207 if ( pState && pActiveViewSh )
4208 {
4209 ScModule* pScMod = SC_MOD();
4210
4211 ScTabViewShell* pScTabViewShell = dynamic_cast<ScTabViewShell*>(pScMod->GetViewShell());
4212
4213 // Also take foreign reference input into account here (e.g. FunctionsAutoPilot),
4214 // FormEditData, if we're switching from Help to Calc:
4215 if ( !bFormulaMode && !pScMod->IsFormulaMode() &&
4216 ( !pScTabViewShell || !pScTabViewShell->GetFormEditData() ) )
4217 {
4218 bool bIgnore = false;
4219 if ( bModified )
4220 {
4221 if (pState->GetPos() != aCursorPos)
4222 {
4223 if (!bProtected)
4224 EnterHandler();
4225 }
4226 else
4227 bIgnore = true;
4228 }
4229
4230 if ( !bIgnore )
4231 {
4232 const ScAddress& rSPos = pState->GetStartPos();
4233 const ScAddress& rEPos = pState->GetEndPos();
4234 const EditTextObject* pData = pState->GetEditData();
4235 OUString aString = pState->GetString();
4236 bool bTxtMod = false;
4238 ScDocument& rDoc = pDocSh->GetDocument();
4239
4240 aCursorPos = pState->GetPos();
4241
4242 if ( pData )
4243 bTxtMod = true;
4244 else if ( bHadObject )
4245 bTxtMod = true;
4246 else if ( bTextValid )
4247 bTxtMod = ( aString != aCurrentText );
4248 else
4249 bTxtMod = ( aString != GetEditText(mpEditEngine.get()) );
4250
4251 if ( bTxtMod || bForce )
4252 {
4253 if (pData)
4254 {
4255 mpEditEngine->SetTextCurrentDefaults( *pData );
4256 if (pInputWin)
4258 else
4259 aString = GetEditText(mpEditEngine.get());
4260 lcl_RemoveTabs(aString);
4261 bTextValid = false;
4262 aCurrentText.clear();
4263 }
4264 else
4265 {
4266 aCurrentText = aString;
4267 bTextValid = true;
4268 }
4269
4270 if ( pInputWin )
4271 pInputWin->SetTextString(aString);
4272
4274 {
4276 EditView* pActiveView = pTopView ? pTopView : pTableView;
4277 ESelection aSel = pActiveView ? pActiveView->GetSelection() : ESelection();
4278
4279 // if we switched content completely - don't send huge numbers
4280 if (aSel.nStartPara == EE_PARA_NOT_FOUND)
4281 aSel.nStartPara = 0;
4282
4283 if (aSel.nEndPara == EE_PARA_NOT_FOUND)
4284 aSel.nEndPara = 0;
4285
4286 ScInputHandler::LOKSendFormulabarUpdate(pActiveView, pActiveViewSh, aString, aSel);
4287 // TODO: deprecated?
4288 pActiveViewSh->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_FORMULA, aString.toUtf8());
4289 }
4290 }
4291
4292 if ( pInputWin || comphelper::LibreOfficeKit::isActive()) // Named range input
4293 {
4294 OUString aPosStr;
4295 bool bSheetLocal = false;
4296 const ScAddress::Details aAddrDetails( rDoc, aCursorPos );
4297
4298 // Is the range a name?
4300 if ( pActiveViewSh )
4302 GetRangeAtBlock( ScRange( rSPos, rEPos ), aPosStr, &bSheetLocal);
4303
4304 if ( aPosStr.isEmpty() ) // Not a name -> format
4305 {
4307 if( aAddrDetails.eConv == formula::FormulaGrammar::CONV_XL_R1C1 )
4309 if ( rSPos != rEPos )
4310 {
4311 ScRange r(rSPos, rEPos);
4312 applyStartToEndFlags(nFlags);
4313 aPosStr = r.Format(rDoc, ScRefFlags::VALID | nFlags, aAddrDetails);
4314 }
4315 else
4316 aPosStr = aCursorPos.Format(ScRefFlags::VALID | nFlags, &rDoc, aAddrDetails);
4317 }
4318 else if (bSheetLocal)
4319 {
4320 OUString aName;
4321 if (rDoc.GetName( rSPos.Tab(), aName))
4322 aPosStr = ScPosWnd::createLocalRangeName( aPosStr, aName);
4323 }
4324
4325 if (pInputWin)
4326 {
4327 // Disable the accessible VALUE_CHANGE event
4328 bool bIsSuppressed = pInputWin->IsAccessibilityEventsSuppressed(false);
4329 pInputWin->SetAccessibilityEventsSuppressed(true);
4330 pInputWin->SetPosString(aPosStr);
4331 pInputWin->SetAccessibilityEventsSuppressed(bIsSuppressed);
4332 pInputWin->SetSumAssignMode();
4333 }
4334
4336 pActiveViewSh->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_ADDRESS, aPosStr.toUtf8());
4337 }
4338
4339 if (bStopEditing) {
4340 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScKillEditView ) );
4341
4342 // As long as the content is not edited, turn off online spelling.
4343 // Online spelling is turned back on in StartTable, after setting
4344 // the right language from cell attributes.
4345
4346 EEControlBits nCntrl = mpEditEngine->GetControlWord();
4347 if ( nCntrl & EEControlBits::ONLINESPELLING )
4348 mpEditEngine->SetControlWord( nCntrl & ~EEControlBits::ONLINESPELLING );
4349 }
4350
4351 bModified = false;
4352 bSelIsRef = false;
4353 bProtected = false;
4354 bCommandErrorShown = false;
4355 }
4356 }
4357
4358 if ( pInputWin)
4359 {
4360 // Do not enable if RefDialog is open
4361 if(!pScMod->IsFormulaMode()&& !pScMod->IsRefDialogOpen())
4362 {
4363 if ( !pInputWin->IsEnabled())
4364 {
4365 pDelayTimer->Stop();
4366 pInputWin->Enable();
4367 }
4368 }
4369 else if(pScMod->IsRefDialogOpen())
4370 { // Because every document has its own InputWin,
4371 // we should start Timer again, because the input line may
4372 // still be active
4373 if ( !pDelayTimer->IsActive() )
4374 pDelayTimer->Start();
4375 }
4376 }
4377 }
4378 else // !pState || !pActiveViewSh
4379 {
4380 if ( !pDelayTimer->IsActive() )
4381 pDelayTimer->Start();
4382 }
4383
4384 HideTip();
4385 HideTipBelow();
4386 bInOwnChange = false;
4387}
4388
4390{
4391 eAttrAdjust = eJust;
4392 UpdateAdjust( 0 );
4393}
4394
4396{
4397 if( pDelayTimer->IsActive() )
4398 {
4399 pDelayTimer->Stop();
4400 if ( pInputWin )
4401 pInputWin->Enable();
4402 }
4403}
4404
4406{
4407 if ( !(nullptr == pLastState || SC_MOD()->IsFormulaMode() || SC_MOD()->IsRefDialogOpen()))
4408 return;
4409
4411 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
4412 if ( pViewFrm && pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
4413 {
4414 if ( pInputWin)
4415 {
4416 pInputWin->EnableButtons( false );
4417 pInputWin->Disable();
4418 }
4419 }
4420 else if ( !bFormulaMode ) // Keep formula e.g. for help
4421 {
4422 bInOwnChange = true; // disable ModifyHdl (reset below)
4423
4424 pActiveViewSh = nullptr;
4425 mpEditEngine->SetTextCurrentDefaults( OUString() );
4426 if ( pInputWin )
4427 {
4428 pInputWin->SetPosString( OUString() );
4429 pInputWin->SetTextString( OUString() );
4430 pInputWin->Disable();
4431 }
4432
4433 bInOwnChange = false;
4434 }
4435}
4436
4438{
4439 SyncViews( pView );
4440 ShowTipCursor();
4441 UpdateParenthesis(); // Selection changed -> update parentheses highlighting
4442
4443 // When the selection is changed manually, stop overwriting parentheses
4444 ResetAutoPar();
4445
4447 {
4448 EditView* pActiveView = pTopView ? pTopView : pTableView;
4449 ESelection aSel = pActiveView ? pActiveView->GetSelection() : ESelection();
4451 }
4452}
4453
4454void ScInputHandler::InputChanged( const EditView* pView, bool bFromNotify )
4455{
4456 if ( !pView )
4457 return;
4458
4460
4461 // #i20282# DataChanged needs to know if this is from the input line's modify handler
4462 bool bFromTopNotify = ( bFromNotify && pView == pTopView );
4463
4464 bool bNewView = DataChanging(); //FIXME: Is this at all possible?
4465 aCurrentText = pView->GetEditEngine()->GetText(); // Also remember the string
4466 mpEditEngine->SetTextCurrentDefaults( aCurrentText );
4467 DataChanged( bFromTopNotify );
4468 bTextValid = true; // Is set to false in DataChanged
4469
4470 if ( pActiveViewSh )
4471 {
4472 ScViewData& rViewData = pActiveViewSh->GetViewData();
4473 if ( bNewView )
4474 rViewData.GetDocShell()->PostEditView( mpEditEngine.get(), aCursorPos );
4475
4476 rViewData.EditGrowY();
4477 rViewData.EditGrowX();
4478 }
4479
4480 SyncViews( pView );
4481}
4482
4484{
4485 if (mpEditEngine)
4486 {
4487 aCurrentText = mpEditEngine->GetText(); // Always new from Engine
4488 bTextValid = true;
4489 }
4490
4491 return aCurrentText;
4492}
4493
4495{
4496 Size aSize;
4497 if ( mpEditEngine )
4498 aSize = Size( mpEditEngine->CalcTextWidth(), mpEditEngine->GetTextHeight() );
4499
4500 return aSize;
4501}
4502
4504{
4505 bool bRet = false;
4506 if (mpEditEngine)
4507 {
4508 // Contains field?
4509 sal_Int32 nParCnt = mpEditEngine->GetParagraphCount();
4510 SfxItemSet aSet = mpEditEngine->GetAttribs( ESelection(0,0,nParCnt,0) );
4511 SfxItemState eFieldState = aSet.GetItemState( EE_FEATURE_FIELD, false );
4512 if ( eFieldState == SfxItemState::DONTCARE || eFieldState == SfxItemState::SET )
4513 {
4514 // Copy content
4515 std::unique_ptr<EditTextObject> pObj = mpEditEngine->CreateTextObject();
4516 rDestEngine.SetTextCurrentDefaults(*pObj);
4517 pObj.reset();
4518
4519 // Delete attributes
4520 for (sal_Int32 i=0; i<nParCnt; i++)
4521 rDestEngine.RemoveCharAttribs( i );
4522
4523 // Combine paragraphs
4524 while ( nParCnt > 1 )
4525 {
4526 sal_Int32 nLen = rDestEngine.GetTextLen( 0 );
4527 ESelection aSel( 0,nLen, 1,0 );
4528 rDestEngine.QuickInsertText( OUString(' '), aSel ); // Replace line break with space
4529 --nParCnt;
4530 }
4531
4532 bRet = true;
4533 }
4534 }
4535 return bRet;
4536}
4537
4542void ScInputHandler::InputGetSelection( sal_Int32& rStart, sal_Int32& rEnd )
4543{
4544 rStart = nFormSelStart;
4545 rEnd = nFormSelEnd;
4546}
4547
4549{
4550 UpdateActiveView(); // Due to pTableView
4551
4552 EditView* pView = nullptr;
4553 if ( pInputWin )
4554 {
4555 pInputWin->MakeDialogEditView();
4556 pView = pInputWin->GetEditView();
4557 }
4558 else
4559 {
4560 if ( eMode != SC_INPUT_TABLE )
4561 {
4562 bCreatingFuncView = true; // Don't display RangeFinder
4564 bCreatingFuncView = false;
4565 if ( pTableView )
4566 pTableView->GetEditEngine()->SetText( OUString() );
4567 }
4568 pView = pTableView;
4569 }
4570
4571 return pView;
4572}
4573
4574void ScInputHandler::InputSetSelection( sal_Int32 nStart, sal_Int32 nEnd )
4575{
4576 if ( nStart <= nEnd )
4577 {
4578 nFormSelStart = nStart;
4579 nFormSelEnd = nEnd;
4580 }
4581 else
4582 {
4583 nFormSelEnd = nStart;
4584 nFormSelStart = nEnd;
4585 }
4586
4587 EditView* pView = GetFuncEditView();
4588 if (pView)
4589 pView->SetSelection( ESelection(0,nStart, 0,nEnd) );
4590
4591 bModified = true;
4592}
4593
4594void ScInputHandler::InputReplaceSelection( std::u16string_view aStr )
4595{
4596 if (!pRefViewSh)
4598
4599 OSL_ENSURE(nFormSelEnd>=nFormSelStart,"Selection broken...");
4600
4601 sal_Int32 nOldLen = nFormSelEnd - nFormSelStart;
4602 sal_Int32 nNewLen = aStr.size();
4603
4604 OUStringBuffer aBuf(aFormText);
4605 if (nOldLen)
4606 aBuf.remove(nFormSelStart, nOldLen);
4607 if (nNewLen)
4608 aBuf.insert(nFormSelStart, aStr);
4609
4610 aFormText = aBuf.makeStringAndClear();
4611
4612 nFormSelEnd = nFormSelStart + nNewLen;
4613
4614 EditView* pView = GetFuncEditView();
4615 if (pView)
4616 {
4617 pView->SetEditEngineUpdateLayout( false );
4618 pView->GetEditEngine()->SetText( aFormText );
4620 pView->SetEditEngineUpdateLayout( true );
4621 }
4622 bModified = true;
4623}
4624
4626{
4627 bInOwnChange = true; // disable ModifyHdl (reset below)
4628
4630 /* TODO: it would be better if there was some way to reset the input bar
4631 * engine instead of deleting and having it recreate through
4632 * GetFuncEditView(), but first least invasively let this fix fdo#71667 and
4633 * fdo#72278 without reintroducing fdo#69971. */
4634 StopInputWinEngine(true);
4635
4636 bInOwnChange = false;
4637}
4638
4643 const ScAddress& rStartPos,
4644 const ScAddress& rEndPos,
4645 OUString _aString,
4646 const EditTextObject* pData )
4647 : aCursorPos ( rCurPos ),
4648 aStartPos ( rStartPos ),
4649 aEndPos ( rEndPos ),
4650 aString (std::move( _aString )),
4651 pEditData ( pData ? pData->Clone() : nullptr )
4652{
4653}
4654
4656{
4657 *this = rCpy;
4658}
4659
4661{
4662}
4663
4665{
4666 return ( (aStartPos == r.aStartPos)
4667 && (aEndPos == r.aEndPos)
4668 && (aCursorPos == r.aCursorPos)
4669 && (aString == r.aString)
4670 && ScGlobal::EETextObjEqual( pEditData.get(), r.pEditData.get() ) );
4671}
4672
4674{
4675 if (this != &r)
4676 {
4678 aStartPos = r.aStartPos;
4679 aEndPos = r.aEndPos;
4680 aString = r.aString;
4681 pEditData.reset();
4682 if (r.pEditData)
4683 pEditData = r.pEditData->Clone();
4684 }
4685 return *this;
4686}
4687
4688/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScRefFlags
Definition: address.hxx:158
void applyStartToEndFlags(ScRefFlags &target, const ScRefFlags source)
Definition: address.hxx:196
const SCCOL MAXCOL
Definition: address.hxx:69
void PutInOrder(T &nStart, T &nEnd)
Definition: address.hxx:150
SfxApplication * SfxGetpApp()
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
bool isLetterNumeric(const OUString &rStr, sal_Int32 nPos) const
bool IsTransparent() const
CommandEventId GetCommand() const
void QuickFormatDoc(bool bFull=false)
OUString GetText(LineEnd eEnd=LINEEND_LF) const
void SetText(const OUString &rStr)
void RemoveCharAttribs(sal_Int32 nPara, sal_uInt16 nWhich=0, bool bRemoveFeatures=false)
sal_Int32 GetParagraphCount() const
sal_Int32 GetTextLen() const
static rtl::Reference< SfxItemPool > CreatePool()
static bool DoesKeyMoveCursor(const KeyEvent &rKeyEvent)
void QuickInsertText(const OUString &rText, const ESelection &rSel)
static bool DoesKeyChangeText(const KeyEvent &rKeyEvent)
bool DeleteSurroundingText(const Selection &rRange)
void SetControlWord(EVControlBits nWord)
OUString GetSurroundingText() const
void RemoveCharAttribs(sal_Int32 nPara, sal_uInt16 nWhich)
ESelection GetSelection() const
void SelectCurrentWord(sal_Int16 nWordType=css::i18n::WordType::ANYWORD_IGNOREWHITESPACES)
void RegisterViewShell(OutlinerViewShell *pViewShell)
Selection GetSurroundingTextSelection() const
bool HasSelection() const
void SetSelection(const ESelection &rNewSel)
void InsertText(const OUString &rNew, bool bSelect=false, bool bLOKShowSelect=true)
bool PostKeyEvent(const KeyEvent &rKeyEvent, vcl::Window const *pFrameWin=nullptr)
sal_Int32 GetPosWithField(sal_Int32 nPara, sal_Int32 nPos) const
void ShowCursor(bool bGotoCursor=true, bool bForceVisCursor=true, bool bActivate=false)
vcl::Cursor * GetCursor() const
vcl::Window * GetWindow() const
void DeleteSelected()
EVControlBits GetControlWord() const
void CompleteAutoCorrect(vcl::Window const *pFrameWin=nullptr)
bool Command(const CommandEvent &rCEvt)
EditEngine * GetEditEngine() const
OUString GetSelected() const
bool SetEditEngineUpdateLayout(bool bUpdate)
static void * ShowPopover(vcl::Window *pParent, const tools::Rectangle &rScreenRect, const OUString &rText, QuickHelpFlags nStyle)
static void HidePopover(vcl::Window const *pParent, void *nId)
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
sal_Unicode GetCharCode() const
const vcl::KeyCode & GetKeyCode() const
static css::uno::Reference< css::linguistic2::XSpellChecker1 > GetSpellChecker()
static css::uno::Reference< css::linguistic2::XHyphenator > GetHyphenator()
const OUString & getDoubleQuotationMarkStart() const
const OUString & getQuotationMarkStart() const
const OUString & getDoubleQuotationMarkEnd() const
const OUString & getQuotationMarkEnd() const
constexpr tools::Long Y() const
tools::Long AdjustY(tools::Long nVertMove)
constexpr tools::Long X() const
SCTAB Tab() const
Definition: address.hxx:283
void Set(SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: address.hxx:403
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2074
SCROW Row() const
Definition: address.hxx:274
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
SCCOL Col() const
Definition: address.hxx:279
sal_uInt16 GetLRUFuncListCount() const
Definition: appoptio.hxx:47
sal_uInt16 * GetLRUFuncList() const
Definition: appoptio.hxx:48
bool GetAutoComplete() const
Definition: appoptio.hxx:54
void DataPilotInput(const ScAddress &rPos, const OUString &rString)
Definition: dbfunc3.cxx:1380
bool IsAutoSpell() const
Definition: docoptio.hxx:53
virtual void SetModified(bool=true) override
Definition: docsh.cxx:2973
const ScDocument & GetDocument() const
Definition: docsh.hxx:219
void PostEditView(ScEditEngineDefaulter *pEditEngine, const ScAddress &rCursorPos)
Definition: docsh3.cxx:79
SC_DLLPUBLIC SfxItemPool * GetEnginePool() const
Definition: documen2.cxx:478
SC_DLLPUBLIC bool ExtendMerge(SCCOL nStartCol, SCROW nStartRow, SCCOL &rEndCol, SCROW &rEndRow, SCTAB nTab, bool bRefresh=false)
Definition: document.cxx:5556
EEHorizontalTextDirection GetEditTextDirection(SCTAB nTab) const
Definition: documen8.cxx:355
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:892
SC_DLLPUBLIC const ScValidationData * GetValidationEntry(sal_uInt32 nIndex) const
Definition: documen4.cxx:873
SC_DLLPUBLIC ScDocumentPool * GetPool()
Definition: document.cxx:6050
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:492
void FillInfo(ScTableInfo &rTabInfo, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, double fColScale, double fRowScale, bool bPageMode, bool bFormulaMode, const ScMarkData *pMarkData=nullptr)
Definition: fillinfo.cxx:355
SC_DLLPUBLIC SfxItemPool * GetEditPool() const
Definition: documen2.cxx:473
void GetDataEntries(SCCOL nCol, SCROW nRow, SCTAB nTab, std::vector< ScTypedStrData > &rStrings, bool bValidation=false)
Entries for selection list listbox (no numbers/formulas)
Definition: documen3.cxx:1622
SC_DLLPUBLIC ScDPObject * GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: documen3.cxx:377
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1083
bool ValidCol(SCCOL nCol) const
Definition: document.hxx:899
void ApplyAsianEditSettings(ScEditEngineDefaulter &rEngine)
Definition: documen9.cxx:662
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:467
SC_DLLPUBLIC CellType GetCellType(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:3736
SC_DLLPUBLIC bool IsLayoutRTL(SCTAB nTab) const
Definition: document.cxx:974
SfxPrinter * GetPrinter(bool bCreateIfNotExist=true)
Definition: documen8.cxx:114
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:204
SC_DLLPUBLIC sal_Unicode GetSheetSeparator() const
Obtain the sheet separator corresponding to the document's grammar.
Definition: documen4.cxx:1351
SC_DLLPUBLIC const ScPatternAttr * GetPattern(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:4719
SC_DLLPUBLIC const ScDocOptions & GetDocOptions() const
Definition: documen3.cxx:1936
void GetFormulaEntries(ScTypedCaseStrSet &rStrings)
Entries for Formula auto input.
Definition: documen3.cxx:1659
void SetTextCurrentDefaults(const EditTextObject &rTextObject)
SetText and apply defaults already set.
Definition: editutil.cxx:619
void SetDefaultItem(const SfxPoolItem &rItem)
Set the item in the default ItemSet which is created if it doesn't exist yet.
Definition: editutil.cxx:598
static OUString ModifyDelimiters(const OUString &rOld)
Definition: editutil.cxx:65
static OUString GetMultilineString(const EditEngine &rEngine)
Retrieves string with paragraphs delimited by new lines (' ').
Definition: editutil.cxx:109
void TestSelection(const ScDocument &rDoc, const ScMarkData &rMark)
Definition: editable.cxx:123
bool IsEditable() const
Definition: editable.hxx:84
TranslateId GetMessageId() const
Definition: editable.cxx:152
void TestSelectedBlock(const ScDocument &rDoc, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScMarkData &rMark)
Definition: editable.cxx:97
Stores and generates human readable descriptions for spreadsheet-functions, e.g. functions used in fo...
Definition: funcdesc.hxx:41
sal_uInt16 nFIndex
Unique function index.
Definition: funcdesc.hxx:221
std::optional< OUString > mxFuncName
Function name.
Definition: funcdesc.hxx:216
List of spreadsheet functions.
Definition: funcdesc.hxx:242
const ScFuncDesc * GetFunction(sal_uInt32 nIndex) const
Definition: funcdesc.cxx:993
sal_uInt32 GetCount() const
Definition: funcdesc.hxx:247
static const sal_Unicode * UnicodeStrChr(const sal_Unicode *pStr, sal_Unicode c)
strchr() functionality on unicode, as long as we need it for FormulaToken etc.
Definition: global.cxx:691
static LanguageType GetEditDefaultLanguage()
Definition: global.cxx:909
static SC_DLLPUBLIC ::utl::TransliterationWrapper & GetTransliteration()
Definition: global.cxx:1026
static const InputHandlerFunctionNames & GetInputHandlerFunctionNames()
Definition: global.cxx:653
static SC_DLLPUBLIC LanguageType eLnge
Definition: global.hxx:560
static bool EETextObjEqual(const EditTextObject *pObj1, const EditTextObject *pObj2)
Definition: global.cxx:798
static ScFunctionList * GetStarCalcFunctionList()
Definition: global.cxx:626
static SC_DLLPUBLIC const LocaleDataWrapper & getLocaleData()
Definition: global.cxx:1055
static OUString GetErrorString(FormulaError nErrNumber)
Definition: global.cxx:315
static ScFunctionMgr * GetStarCalcFunctionMgr()
Definition: global.cxx:635
static SC_DLLPUBLIC const CharClass & getCharClass()
Definition: global.cxx:1064
std::set< sal_Unicode > maFormulaChar
Definition: inputhdl.hxx:71
OUString aCurrentText
Definition: inputhdl.hxx:80
SvxCellHorJustify eAttrAdjust
Definition: inputhdl.hxx:112
void CancelHandler()
Definition: inputhdl.cxx:3453
void ForgetLastPattern()
Definition: inputhdl.cxx:2361
void SetReference(const ScRange &rRef, const ScDocument &rDoc)
Definition: inputhdl.cxx:3558
bool mbEditingExistingContent
Definition: inputhdl.hxx:109
bool KeyInput(const KeyEvent &rKEvt, bool bStartEdit)
Definition: inputhdl.cxx:3738
void * nTipVisibleSec
Definition: inputhdl.hxx:76
void SetDocumentDisposing(bool b)
Definition: inputhdl.cxx:617
EditView * GetFuncEditView()
Definition: inputhdl.cxx:4548
void InputCommand(const CommandEvent &rCEvt)
Definition: inputhdl.cxx:4070
void AddRefEntry()
Definition: inputhdl.cxx:3525
void ShowArgumentsTip(OUString &rSelText)
Definition: inputhdl.cxx:1133
std::unique_ptr< ScInputHdlState > pLastState
Definition: inputhdl.hxx:125
void ViewShellGone(const ScTabViewShell *pViewSh)
Definition: inputhdl.cxx:2259
void UpdateSpellSettings(bool bFromStartTab=false)
Definition: inputhdl.cxx:965
void InputTurnOffWinEngine()
Definition: inputhdl.cxx:4625
ScInputMode eMode
Definition: inputhdl.hxx:91
static void LOKSendFormulabarUpdate(EditView *pEditView, const SfxViewShell *pActiveViewSh, const OUString &rText, const ESelection &rSelection)
Definition: inputhdl.cxx:1808
OUString aAutoSearch
Definition: inputhdl.hxx:78
void ShowTip(const OUString &rText)
Definition: inputhdl.cxx:1319
void FormulaPreview()
Definition: inputhdl.cxx:1899
Fraction aScaleX
Definition: inputhdl.hxx:114
ScTabViewShell * pActiveViewSh
Definition: inputhdl.hxx:118
void UpdateAdjust(sal_Unicode cTyped)
Definition: inputhdl.cxx:2370
Size GetTextSize()
Definition: inputhdl.cxx:4494
bool bFormulaMode
Definition: inputhdl.hxx:96
bool GetFuncName(OUString &aStart, OUString &aResult)
Definition: inputhdl.cxx:1382
void ResetDelayTimer()
Definition: inputhdl.cxx:4395
void PasteManualTip()
Definition: inputhdl.cxx:1923
static void SendReferenceMarks(const SfxViewShell *pViewShell, const std::vector< ReferenceMark > &rReferenceMarks)
Definition: inputhdl.cxx:306
bool GetTextAndFields(ScEditEngineDefaulter &rDestEngine)
Definition: inputhdl.cxx:4503
sal_uLong nValidation
Definition: inputhdl.hxx:111
void NotifyChange(const ScInputHdlState *pState, bool bForce=false, ScTabViewShell *pSourceSh=nullptr, bool bStopEditing=true)
Definition: inputhdl.cxx:4172
bool bLastIsSymbol
Definition: inputhdl.hxx:105
void ShowFuncList(const ::std::vector< OUString > &rFuncStrVec)
Definition: inputhdl.cxx:1426
bool StartTable(sal_Unicode cTyped, bool bFromCommand, bool bInputActivated, ScEditEngineDefaulter *pTopEngine)
Definition: inputhdl.cxx:2452
bool bCreatingFuncView
Definition: inputhdl.hxx:99
void ShowTipCursor()
Definition: inputhdl.cxx:1294
void UpdateRange(sal_uInt16 nIndex, const ScRange &rNew)
Definition: inputhdl.cxx:645
void UseFormulaData()
Definition: inputhdl.cxx:1543
static void InvalidateAttribs()
Definition: inputhdl.cxx:2925
void UpdateCellAdjust(SvxCellHorJustify eJust)
Definition: inputhdl.cxx:4389
std::unique_ptr< ScEditEngineDefaulter > mpEditEngine
Edited data in the sheet (when the user clicks into the sheet, and starts writing there).
Definition: inputhdl.hxx:62
sal_uInt16 nAutoPar
Definition: inputhdl.hxx:88
void HideTipBelow()
Definition: inputhdl.cxx:1111
void DeleteRangeFinder()
Definition: inputhdl.cxx:702
void ResetAutoPar()
Definition: inputhdl.cxx:1982
OUString aFormText
Definition: inputhdl.hxx:82
ScAddress aCursorPos
Definition: inputhdl.hxx:90
void * nTipVisible
Definition: inputhdl.hxx:74
void PasteFunctionData()
Definition: inputhdl.cxx:1729
ScTabViewShell * pRefViewSh
Definition: inputhdl.hxx:117
bool mbDocumentDisposing
Definition: inputhdl.hxx:106
EditView * pTopView
Definition: inputhdl.hxx:64
void DataChanged(bool bFromTopNotify=false, bool bSetModified=true)
Definition: inputhdl.cxx:2722
void UpdateRefDevice()
Definition: inputhdl.cxx:897
bool mbPartialPrefix
To indicate if there is a partial prefix completion.
Definition: inputhdl.hxx:108
void NextAutoEntry(bool bBack)
Definition: inputhdl.cxx:2133
void GetFormulaData()
Definition: inputhdl.cxx:1021
OUString GetSurroundingText()
Definition: inputhdl.cxx:4022
void SetMode(ScInputMode eNewMode, const OUString *pInitText=nullptr, ScEditEngineDefaulter *pTopEngine=nullptr)
Definition: inputhdl.cxx:2960
EditView * pTableView
Definition: inputhdl.hxx:63
OUString aManualTip
Definition: inputhdl.hxx:77
Fraction aScaleY
Definition: inputhdl.hxx:115
ScTypedCaseStrSet::const_iterator miAutoPosFormula
Definition: inputhdl.hxx:70
void UpdateLokReferenceMarks()
Definition: inputhdl.cxx:535
void RemoveSelection()
Definition: inputhdl.cxx:2910
void ImplCreateEditEngine()
Definition: inputhdl.cxx:926
std::unique_ptr< Timer > pDelayTimer
Definition: inputhdl.hxx:126
bool StartsLikeFormula(std::u16string_view rStr) const
Definition: inputhdl.cxx:2822
void NextFormulaEntry(bool bBack)
Definition: inputhdl.cxx:1612
bool CursorAtClosingPar()
Definition: inputhdl.cxx:1992
void GetColData()
Definition: inputhdl.cxx:2035
std::unique_ptr< ScTypedCaseStrSet > pFormulaData
Definition: inputhdl.hxx:67
void InputGetSelection(sal_Int32 &rStart, sal_Int32 &rEnd)
Methods for FunctionAutoPilot: InputGetSelection, InputSetSelection, InputReplaceSelection,...
Definition: inputhdl.cxx:4542
EditView * GetActiveView()
Definition: inputhdl.cxx:2355
void ShowRefFrame()
Definition: inputhdl.cxx:2877
void LOKPasteFunctionData(const OUString &rFunctionName)
Definition: inputhdl.cxx:1758
void AutoParAdded()
Definition: inputhdl.cxx:1987
sal_Int32 nFormSelEnd
Definition: inputhdl.hxx:84
ScTypedCaseStrSet::const_iterator miAutoPosColumn
Definition: inputhdl.hxx:69
void RemoveRangeFinder()
Definition: inputhdl.cxx:2437
void InsertFunction(const OUString &rFuncName, bool bAddPar=true)
Definition: inputhdl.cxx:3663
void SetInputWindow(ScInputWindow *pNew)
Definition: inputhdl.cxx:2342
void UseColData()
Definition: inputhdl.cxx:2056
void ShowTipBelow(const OUString &rText)
Definition: inputhdl.cxx:1350
ScRangeFindList * GetRangeFindList()
Definition: inputhdl.hxx:253
sal_Int32 nFormSelStart
Definition: inputhdl.hxx:83
bool bParenthesisShown
Definition: inputhdl.hxx:98
void RemoveAdjust()
Definition: inputhdl.cxx:2421
void InitRangeFinder(const OUString &rFormula)
Definition: inputhdl.cxx:358
const ScPatternAttr * pLastPattern
Definition: inputhdl.hxx:120
void InputChanged(const EditView *pView, bool bFromNotify)
Definition: inputhdl.cxx:4454
void UpdateFormulaMode()
Definition: inputhdl.cxx:2829
void InputSelection(const EditView *pView)
Definition: inputhdl.cxx:4437
VclPtr< vcl::Window > pTipVisibleSecParent
Definition: inputhdl.hxx:75
VclPtr< ScInputWindow > pInputWin
Definition: inputhdl.hxx:60
void UpdateParenthesis()
Definition: inputhdl.cxx:2196
std::unique_ptr< ScTypedCaseStrSet > pFormulaDataPara
Definition: inputhdl.hxx:68
Selection GetSurroundingTextSelection()
Definition: inputhdl.cxx:4038
bool DeleteSurroundingText(const Selection &rSelection)
Definition: inputhdl.cxx:4054
static ReferenceMark GetReferenceMark(const ScViewData &rViewData, ScDocShell *pDocSh, tools::Long nX1, tools::Long nX2, tools::Long nY1, tools::Long nY2, tools::Long nTab, const Color &rColor)
Definition: inputhdl.cxx:485
bool IsModalMode(const SfxObjectShell *pDocSh)
Definition: inputhdl.cxx:3517
void ClearText()
Definition: inputhdl.cxx:3710
void UpdateActiveView()
Definition: inputhdl.cxx:2293
bool bCommandErrorShown
Definition: inputhdl.hxx:101
bool DataChanging(sal_Unicode cTyped=0, bool bFromCommand=false)
Definition: inputhdl.cxx:2710
void SkipClosingPar()
Definition: inputhdl.cxx:2008
sal_Unicode nCellPercentFormatDecSep
Definition: inputhdl.hxx:86
void SetRefScale(const Fraction &rX, const Fraction &rY)
Definition: inputhdl.cxx:883
VclPtr< vcl::Window > pTipVisibleParent
Definition: inputhdl.hxx:73
void EnterHandler(ScEnterMode nBlockMode=ScEnterMode::NORMAL, bool bBeforeSavingInLOK=false)
Definition: inputhdl.cxx:3069
void StopInputWinEngine(bool bAll)
Definition: inputhdl.cxx:2347
std::unique_ptr< SfxItemSet > pEditDefaults
Definition: inputhdl.hxx:122
void SyncViews(const EditView *pSourceView=nullptr)
Definition: inputhdl.cxx:2667
void MergeLanguageAttributes(ScEditEngineDefaulter &rDestEngine) const
Definition: inputhdl.cxx:2629
bool bInEnterHandler
Definition: inputhdl.hxx:100
std::unique_ptr< ScRangeFindList > pRangeFindList
Definition: inputhdl.hxx:129
void UpdateAutoCorrFlag()
Definition: inputhdl.cxx:949
void InputReplaceSelection(std::u16string_view aStr)
Definition: inputhdl.cxx:4594
const OUString & GetEditString()
Definition: inputhdl.cxx:4483
void InputSetSelection(sal_Int32 nStart, sal_Int32 nEnd)
Definition: inputhdl.cxx:4574
bool bInRangeUpdate
Definition: inputhdl.hxx:97
std::unique_ptr< ScTypedCaseStrSet > pColumnData
Definition: inputhdl.hxx:66
ScInputHdlState(const ScAddress &rCurPos, const ScAddress &rStartPos, const ScAddress &rEndPos, OUString aString, const EditTextObject *pData)
ScInputHdlState.
Definition: inputhdl.cxx:4642
const ScAddress & GetEndPos() const
Definition: inputhdl.hxx:322
ScAddress aCursorPos
Definition: inputhdl.hxx:327
ScAddress aEndPos
Definition: inputhdl.hxx:329
std::unique_ptr< EditTextObject > pEditData
Definition: inputhdl.hxx:331
ScInputHdlState & operator=(const ScInputHdlState &r)
Definition: inputhdl.cxx:4673
const OUString & GetString() const
Definition: inputhdl.hxx:323
const ScAddress & GetStartPos() const
Definition: inputhdl.hxx:321
ScAddress aStartPos
Definition: inputhdl.hxx:328
const EditTextObject * GetEditData() const
Definition: inputhdl.hxx:324
const ScAddress & GetPos() const
Definition: inputhdl.hxx:320
bool operator==(const ScInputHdlState &r) const
Definition: inputhdl.cxx:4664
OUString aString
Definition: inputhdl.hxx:330
void SetMisspellRanges(const std::vector< editeng::MisspellRanges > *pRanges)
Definition: uiitems.cxx:77
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
bool IsMultiMarked() const
Definition: markdata.hxx:81
bool IsMarked() const
Definition: markdata.hxx:80
svtools::ColorConfig & GetColorConfig()
Definition: scmod.cxx:887
void SetRefInputHdl(ScInputHandler *pNew)
Definition: scmod.cxx:1449
SC_DLLPUBLIC const ScAppOptions & GetAppOptions()
Definition: scmod.cxx:799
bool IsFormulaMode()
Definition: scmod.cxx:1681
bool IsRefDialogOpen()
Definition: scmod.cxx:1665
static LanguageType GetOptDigitLanguage()
Definition: scmod.cxx:907
ReferenceMark FillReferenceMark(SCCOL nRefStartX, SCROW nRefStartY, SCCOL nRefEndX, SCROW nRefEndY, const Color &rColor)
Definition: output.cxx:1917
bool IsSymbolFont() const
If font is an old symbol font StarBats/StarMath with text encoding RTL_TEXTENC_SYMBOL.
Definition: patattr.cxx:1376
sal_uInt32 GetNumberFormat(SvNumberFormatter *) const
Definition: patattr.cxx:1398
SfxItemSet & GetItemSet()
Definition: patattr.hxx:192
const SfxPoolItem & GetItem(sal_uInt16 nWhichP) const
Definition: patattr.hxx:73
void FillEditItemSet(SfxItemSet *pEditSet, const SfxItemSet *pCondSet=nullptr) const
Converts all Calc items contained in the own item set to edit engine items and puts them into pEditSe...
Definition: patattr.cxx:868
static OUString createLocalRangeName(std::u16string_view rName, std::u16string_view rTableName)
Definition: inputwin.cxx:2348
bool IsHidden() const
Definition: rfindlst.hxx:58
ScRangeFindData & GetObject(size_t nIndex)
Definition: rfindlst.hxx:53
size_t Count() const
Definition: rfindlst.hxx:50
const OUString & GetDocName() const
Definition: rfindlst.hxx:57
OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2170
void PutInOrder()
Definition: address.hxx:622
ScAddress aEnd
Definition: address.hxx:498
ScRefFlags ParseAny(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1)
Definition: address.cxx:1733
ScRefFlags Parse(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, ScAddress::ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1700
ScAddress aStart
Definition: address.hxx:497
ScFormEditData * GetFormEditData()
Definition: tabvwsh.hxx:414
void UpdateInputHandler(bool bForce=false, bool bStopEditing=true)
Definition: tabvwsha.cxx:690
void SetActive()
Definition: tabvwsh4.cxx:276
void StopEditShell()
Definition: tabvwsh4.cxx:1106
void StopMarking()
Definition: tabview2.cxx:1507
void ErrorMessage(TranslateId pGlobStrId)
Definition: tabview2.cxx:1553
void FindNextUnprot(bool bShift, bool bInSelection)
Definition: tabview3.cxx:1541
vcl::Window * GetFrameWin() const
Definition: tabview.hxx:596
ScViewData & GetViewData()
Definition: tabview.hxx:344
ScGridWindow * GetActiveWin()
Definition: tabview.cxx:878
vcl::Window * GetWindowByPos(ScSplitPos ePos) const
Definition: tabview.hxx:382
void MoveCursorEnter(bool bShift)
Definition: tabview3.cxx:1409
void ActiveGrabFocus()
Definition: tabview.cxx:892
SC_DLLPUBLIC void SetTabNo(SCTAB nTab, bool bNew=false, bool bExtendSelection=false, bool bSameTabButMoved=false)
Definition: tabview3.cxx:1819
StringType GetStringType() const
const OUString & GetString() const
Point GetPrintTwipsPos(SCCOL nCol, SCROW nRow) const
returns the position (top-left corner) of the requested cell in print twips coordinates.
Definition: viewdata.cxx:2556
void EditGrowX()
Extend the output area for the edit engine view in a horizontal direction as needed.
Definition: viewdata.cxx:1847
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3146
const Fraction & GetZoomY() const
Definition: viewdata.hxx:460
SCTAB GetTabNo() const
Definition: viewdata.hxx:395
ScDocument & GetDocument() const
Definition: viewdata.hxx:380
SCCOL GetRefStartX() const
Definition: viewdata.hxx:532
void EditGrowY(bool bInitial=false)
Extend the output area for the edit engine view in a vertical direction as needed.
Definition: viewdata.cxx:2139
double GetPPTY() const
Definition: viewdata.hxx:469
ScSplitPos GetEditActivePart() const
Definition: viewdata.hxx:602
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:354
ScDBFunc * GetView() const
Definition: viewdata.cxx:864
void SetEditAdjust(SvxAdjust eNewEditAdjust)
Definition: viewdata.hxx:519
ScSplitPos GetActivePart() const
Definition: viewdata.hxx:398
SCROW GetRefEndY() const
Definition: viewdata.hxx:536
Point GetScrPos(SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich, bool bAllowNeg=false, SCTAB nForTab=-1) const
Definition: viewdata.cxx:2380
SCTAB GetRefStartZ() const
Definition: viewdata.hxx:534
void SetPasteMode(ScPasteFlags nFlags)
Definition: viewdata.hxx:448
SCCOL GetRefEndX() const
Definition: viewdata.hxx:535
SCROW GetRefStartY() const
Definition: viewdata.hxx:533
SCTAB GetRefEndZ() const
Definition: viewdata.hxx:537
const Fraction & GetZoomX() const
Definition: viewdata.hxx:459
SCTAB GetRefTabNo() const
Definition: viewdata.hxx:392
SvxAdjust GetEditAdjust() const
Definition: viewdata.hxx:518
bool IsRefMode() const
Definition: viewdata.hxx:530
double GetPPTX() const
Definition: viewdata.hxx:468
void ApplySelectionPattern(const ScPatternAttr &rAttr, bool bCursorOnly=false)
Definition: viewfunc.cxx:1227
bool AdjustBlockHeight(bool bPaint=true, ScMarkData *pMarkData=nullptr)
Definition: viewfun2.cxx:115
bool Execute(sal_uInt16 nSlot, const SfxPoolItem **pArgs=nullptr, SfxCallMode nCall=SfxCallMode::SLOT)
void Invalidate(sal_uInt16 nId)
bool IsInPlace() const
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
const INetURLObject & GetURLObject() const
bool HasName() const
bool IsReadOnly() const
bool IsModified() const
SfxMedium * GetMedium() const
OUString GetTitle(sal_uInt16 nMaxLen=0) const
SfxViewShell * GetViewShell() const
static SAL_WARN_UNUSED_RESULT SfxViewFrame * Current()
SfxBindings & GetBindings()
static SAL_WARN_UNUSED_RESULT SfxViewFrame * GetNext(const SfxViewFrame &rPrev, const SfxObjectShell *pDoc=nullptr, bool bOnlyVisible=true)
SfxChildWindow * GetChildWindow(sal_uInt16)
static SAL_WARN_UNUSED_RESULT SfxViewFrame * GetFirst(const SfxObjectShell *pDoc=nullptr, bool bOnlyVisible=true)
SfxFrame & GetFrame() const
bool isLOKMobilePhone() const
weld::Window * GetFrameWeld() const
virtual void libreOfficeKitViewCallback(int nType, const OString &pPayload) const override
SfxViewFrame & GetViewFrame() const
static SAL_WARN_UNUSED_RESULT SfxViewShell * Current()
bool GetHighContrastMode() const
sal_uInt32 GetStandardFormat(SvNumFormatType eType, LanguageType eLnge=LANGUAGE_DONTKNOW)
void GetOutputString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &sOutString, const Color **ppColor, bool bUseStarFormat=false)
void GetInputLineString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &rOutString, bool bFiltering=false, bool bForceSystemLocale=false)
SvNumFormatType GetType(sal_uInt32 nFIndex) const
OUString GetFormatDecimalSep(sal_uInt32 nFormat) const
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
SvxAutoCorrect * GetAutoCorrect()
static SvxAutoCorrCfg & Get()
sal_Unicode GetStartSingleQuote() const
sal_Unicode GetEndSingleQuote() const
sal_Unicode GetEndDoubleQuote() const
sal_Unicode GetStartDoubleQuote() const
static sal_Unicode GetNativeSymbolChar(OpCode eOp)
virtual OUString getParameterDescription(sal_uInt32 _nPos) const=0
virtual OUString getFunctionName() const=0
virtual OUString getSignature() const=0
virtual sal_uInt32 getParameterCount() const=0
virtual OUString getDescription() const=0
ColorConfigValue GetColorValue(ColorConfigEntry eEntry, bool bSmart=true) const
bool isMatch(const OUString &rStr1, const OUString &rStr2) const
bool IsMod1() const
sal_uInt16 GetCode() const
sal_uInt16 GetModifier() const
KeyFuncType GetFunction() const
bool IsShift() const
bool IsMod2() const
void GrabFocus()
int nCount
constexpr double nPPTX
constexpr double nPPTY
float u
ScXMLEditAttributeMap::Entry const aEntries[]
#define EE_PARA_NOT_FOUND
EEControlBits
constexpr TypedWhichId< SvxKerningItem > EE_CHAR_KERNING(EE_CHAR_START+12)
constexpr TypedWhichId< SvxFieldItem > EE_FEATURE_FIELD(EE_FEATURE_NOTCONV+1)
constexpr TypedWhichId< SvxAdjustItem > EE_PARA_JUST(EE_PARA_START+16)
constexpr TypedWhichId< SvxAutoKernItem > EE_CHAR_PAIRKERNING(EE_CHAR_START+11)
constexpr TypedWhichId< SvxLanguageItem > EE_CHAR_LANGUAGE_CTL(EE_CHAR_START+16)
constexpr TypedWhichId< SvxWeightItem > EE_CHAR_WEIGHT(EE_CHAR_START+4)
constexpr TypedWhichId< SvxColorItem > EE_CHAR_COLOR(EE_CHAR_START+0)
constexpr sal_uInt16 EE_CHAR_START(EE_PARA_END+1)
constexpr sal_uInt16 EE_FEATURE_NOTCONV(EE_FEATURE_LINEBR+1)
constexpr TypedWhichId< SvxEscapementItem > EE_CHAR_ESCAPEMENT(EE_CHAR_START+10)
constexpr sal_uInt16 EE_CHAR_END(EE_CHAR_START+32)
constexpr TypedWhichId< SvxLanguageItem > EE_CHAR_LANGUAGE_CJK(EE_CHAR_START+15)
constexpr TypedWhichId< SvxLanguageItem > EE_CHAR_LANGUAGE(EE_CHAR_START+14)
constexpr TypedWhichId< SvXMLAttrContainerItem > EE_CHAR_XMLATTRIBS(EE_CHAR_START+28)
EmbeddedObjectRef * pObject
FormulaError
Any aHelper
WEIGHT_BOLD
#define VAR_ARGS
#define PAIRED_VAR_ARGS
constexpr sal_Unicode cParenthesesReplacement
Definition: global.hxx:463
@ CELLTYPE_VALUE
Definition: global.hxx:274
ScInputMode
Definition: global.hxx:360
@ SC_INPUT_TYPE
Definition: global.hxx:362
@ SC_INPUT_NONE
Definition: global.hxx:361
@ SC_INPUT_TABLE
Definition: global.hxx:363
@ SC_INPUT_TOP
Definition: global.hxx:364
ScEnterMode
Definition: global.hxx:219
QuickHelpFlags
IMPL_LINK_NOARG(ScInputHandler, ModifyHdl, LinkParamNone *, void)
Definition: inputhdl.cxx:2694
IMPL_LINK(ScInputHandler, ShowHideTipVisibleParentListener, VclWindowEvent &, rEvent, void)
Definition: inputhdl.cxx:1086
static void lcl_RemoveLineEnd(OUString &rStr)
Definition: inputhdl.cxx:724
static void lcl_SetTopSelection(EditView *pEditView, ESelection &rSel)
Definition: inputhdl.cxx:2637
#define RANGEFIND_MAX
Definition: inputhdl.cxx:98
static OUString lcl_Calculate(const OUString &rFormula, ScDocument &rDoc, const ScAddress &rPos)
Definition: inputhdl.cxx:1837
static void incPos(const sal_Unicode c, sal_Int32 &rPos, ESelection &rSel)
Definition: inputhdl.cxx:344
static void lcl_RemoveTabs(OUString &rStr)
Definition: inputhdl.cxx:719
static sal_Int32 lcl_MatchParenthesis(const OUString &rStr, sal_Int32 nPos)
Definition: inputhdl.cxx:730
static OUString GetEditText(const EditEngine *pEng)
Definition: inputhdl.cxx:714
static bool lcl_IsNumber(std::u16string_view aString)
Definition: inputhdl.cxx:3044
static void lcl_SelectionToEnd(EditView *pView)
Definition: inputhdl.cxx:3056
static void lcl_Replace(EditView *pView, const OUString &rNewStr, const ESelection &rOldSel)
Definition: inputhdl.cxx:622
sal_Int32 nIndex
OUString aName
Mode eMode
void * p
sal_Int64 n
KeyFuncType
constexpr sal_uInt16 KEY_RETURN
constexpr sal_uInt16 KEY_F2
constexpr sal_uInt16 KEY_ESCAPE
constexpr sal_uInt16 KEY_TAB
constexpr sal_uInt16 KEY_RIGHT
constexpr sal_uInt16 KEY_DELETE
constexpr sal_uInt16 KEY_INSERT
constexpr sal_uInt16 KEY_BACKSPACE
LINEEND_LF
TOOLS_DLLPUBLIC OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
sal_uInt16 nPos
aStr
aBuf
std::unique_ptr< sal_Int32[]> pData
constexpr OUStringLiteral aData
bool isCompatFlagSet(Compat flag)
int i
VCL_DLLPUBLIC void SendAction(const OUString &nWindowId, const OUString &rWidget, std::unique_ptr< ActionDataMap > pData)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
css::uno::Reference< css::animations::XAnimationNode > Clone(const css::uno::Reference< css::animations::XAnimationNode > &xSourceNode, const SdPage *pSource=nullptr, const SdPage *pTarget=nullptr)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
long Long
sal_Int16 nId
ocSep
@ OUTTYPE_WINDOW
Definition: output.hxx:59
SfxItemState
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
constexpr TypedWhichId< SfxBoolItem > ATTR_VERTICAL_ASIAN(137)
constexpr TypedWhichId< SvxBrushItem > ATTR_BACKGROUND(148)
constexpr TypedWhichId< SvxHorJustifyItem > ATTR_HOR_JUSTIFY(129)
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALUE_FORMAT(146)
constexpr TypedWhichId< ScVerticalStackCell > ATTR_STACKED(134)
constexpr TypedWhichId< ScHyphenateCell > ATTR_HYPHENATE(125)
constexpr TypedWhichId< ScLineBreakCell > ATTR_LINEBREAK(139)
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALIDDATA(153)
#define SC_MOD()
Definition: scmod.hxx:247
bool HasRange() const
sal_Int32 nStartPara
sal_Int32 nEndPos
sal_Int32 nStartPos
void Adjust()
sal_Int32 nEndPara
ScTypedCaseStrSet maFunctionDataPara
Definition: global.hxx:467
std::set< sal_Unicode > maFunctionChar
Definition: global.hxx:468
ScTypedCaseStrSet maFunctionData
Definition: global.hxx:466
Describes reference mark to be drawn, position & size in TWIPs.
Definition: output.hxx:65
formula::FormulaGrammar::AddressConvention eConv
Definition: address.hxx:225
ScRefFlags nFlags
Definition: rfindlst.hxx:33
ESelection maSel
Definition: rfindlst.hxx:32
ScRange aRef
Definition: rfindlst.hxx:31
SvxCellHorJustify
SvxAdjust
std::set< ScTypedStrData, ScTypedStrData::LessCaseSensitive > ScTypedCaseStrSet
sal_uInt16 sal_Unicode
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
Count
#define stringstream
Definition: utils.hxx:45
@ SC_VALID_CUSTOM
Definition: validat.hxx:49
ScSplitPos
Definition: viewdata.hxx:44
const char * pChar
sal_Int32 nLength