LibreOffice Module sc (master)  1
impex.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 
22 #include <i18nutil/unicode.hxx>
23 #include <sot/formats.hxx>
24 #include <sfx2/mieclip.hxx>
25 #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
26 #include <sal/log.hxx>
27 #include <unotools/charclass.hxx>
28 #include <osl/module.hxx>
29 
30 #include <global.hxx>
31 #include <docsh.hxx>
32 #include <undoblk.hxx>
33 #include <rangenam.hxx>
34 #include <tabvwsh.hxx>
35 #include <filter.hxx>
36 #include <asciiopt.hxx>
37 #include <formulacell.hxx>
38 #include <cellform.hxx>
39 #include <progress.hxx>
40 #include <scitems.hxx>
41 #include <editable.hxx>
42 #include <compiler.hxx>
43 #include <warnbox.hxx>
44 #include <clipparam.hxx>
45 #include <impex.hxx>
46 #include <editutil.hxx>
47 #include <patattr.hxx>
48 #include <docpool.hxx>
49 #include <stringutil.hxx>
50 #include <cellvalue.hxx>
51 #include <tokenarray.hxx>
52 #include <documentimport.hxx>
53 #include <refundo.hxx>
54 #include <mtvelements.hxx>
55 
56 #include <globstr.hrc>
57 #include <scresid.hxx>
58 #include <o3tl/safeint.hxx>
59 #include <tools/svlibrary.h>
60 #include <unotools/configmgr.hxx>
61 #include <vcl/svapp.hxx>
62 #include <vcl/weld.hxx>
63 #include <editeng/editobj.hxx>
64 
65 #include <memory>
66 #include <string_view>
67 
68 #include <osl/endian.h>
69 
70 // We don't want to end up with 2GB read in one line just because of malformed
71 // multiline fields, so chop it _somewhere_, which is twice supported columns
72 // times arbitrary maximum cell content length, 2*1024*64K=128M, and because
73 // it's sal_Unicode that's 256MB. If it's 2GB of data without LF we're out of
74 // luck anyway.
77 
78 namespace
79 {
80  const char SYLK_LF[] = "\x1b :";
81 
82  bool lcl_IsEndianSwap( const SvStream& rStrm )
83  {
84  #ifdef OSL_BIGENDIAN
85  return rStrm.GetEndian() != SvStreamEndian::BIG;
86  #else
87  return rStrm.GetEndian() != SvStreamEndian::LITTLE;
88  #endif
89  }
90 }
91 
92 namespace {
93 
94 enum class SylkVersion
95 {
96  SCALC3, // Wrote wrongly quoted strings and unescaped semicolons.
97  OOO32, // Correct strings, plus multiline content.
98  OWN, // Place our new versions, if any, before this value.
99  OTHER // Assume that aliens wrote correct strings.
100 };
101 
102 }
103 
104 // Whole document without Undo
106  : pDocSh( dynamic_cast< ScDocShell* >(r.GetDocumentShell()) ), rDoc( r ),
107  nSizeLimit( 0 ), nMaxImportRow(!utl::ConfigManager::IsFuzzing() ? rDoc.MaxRow() : SCROWS32K),
108  cSep( '\t' ), cStr( '"' ),
109  bFormulas( false ), bIncludeFiltered( true ),
110  bAll( true ), bSingle( true ), bUndo( false ),
111  bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
112  mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ),
113  mExportTextOptions()
114 {
115  pUndoDoc = nullptr;
116  pExtOptions = nullptr;
117 }
118 
119 // Insert am current cell without range(es)
121  : pDocSh( dynamic_cast< ScDocShell* >(r.GetDocumentShell()) ), rDoc( r ),
122  aRange( rPt ),
123  nSizeLimit( 0 ), nMaxImportRow(!utl::ConfigManager::IsFuzzing() ? rDoc.MaxRow() : SCROWS32K),
124  cSep( '\t' ), cStr( '"' ),
125  bFormulas( false ), bIncludeFiltered( true ),
126  bAll( false ), bSingle( true ), bUndo( pDocSh != nullptr ),
127  bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
128  mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ),
129  mExportTextOptions()
130 {
131  pUndoDoc = nullptr;
132  pExtOptions = nullptr;
133 }
134 
135 // ctor with a range is only used for export
138  : pDocSh( dynamic_cast<ScDocShell* >(r.GetDocumentShell()) ), rDoc( r ),
139  aRange( rRange ),
140  nSizeLimit( 0 ), nMaxImportRow(!utl::ConfigManager::IsFuzzing() ? rDoc.MaxRow() : SCROWS32K),
141  cSep( '\t' ), cStr( '"' ),
142  bFormulas( false ), bIncludeFiltered( true ),
143  bAll( false ), bSingle( false ), bUndo( pDocSh != nullptr ),
144  bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
145  mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ),
146  mExportTextOptions()
147 {
148  pUndoDoc = nullptr;
149  pExtOptions = nullptr;
150  // Only one sheet (table) supported
152 }
153 
154 // Evaluate input string - either range, cell or the whole document (when error)
155 // If a View exists, the TabNo of the view will be used.
156 ScImportExport::ScImportExport( ScDocument& r, const OUString& rPos )
157  : pDocSh( dynamic_cast< ScDocShell* >(r.GetDocumentShell()) ), rDoc( r ),
158  nSizeLimit( 0 ), nMaxImportRow(!utl::ConfigManager::IsFuzzing() ? rDoc.MaxRow() : SCROWS32K),
159  cSep( '\t' ), cStr( '"' ),
160  bFormulas( false ), bIncludeFiltered( true ),
161  bAll( false ), bSingle( true ), bUndo( pDocSh != nullptr ),
162  bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
163  mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ),
164  mExportTextOptions()
165 {
166  pUndoDoc = nullptr;
167  pExtOptions = nullptr;
168 
169  SCTAB nTab = ScDocShell::GetCurTab();
170  aRange.aStart.SetTab( nTab );
171  OUString aPos( rPos );
172  // Named range?
173  ScRangeName* pRange = rDoc.GetRangeName();
174  if (pRange)
175  {
176  const ScRangeData* pData = pRange->findByUpperName(ScGlobal::getCharClassPtr()->uppercase(aPos));
177  if (pData)
178  {
179  if( pData->HasType( ScRangeData::Type::RefArea )
181  || pData->HasType( ScRangeData::Type::AbsPos ) )
182  {
183  pData->GetSymbol(aPos);
184  }
185  }
186  }
188  // Range?
189  if (aRange.Parse(aPos, rDoc, eConv) & ScRefFlags::VALID)
190  bSingle = false;
191  // Cell?
192  else if (aRange.aStart.Parse(aPos, rDoc, eConv) & ScRefFlags::VALID)
194  else
195  bAll = true;
196 }
197 
198 ScImportExport::~ScImportExport() COVERITY_NOEXCEPT_FALSE
199 {
200  pUndoDoc.reset();
201  pExtOptions.reset();
202 }
203 
205 {
206  if ( pExtOptions )
207  *pExtOptions = rOpt;
208  else
209  pExtOptions.reset(new ScAsciiOptions( rOpt ));
210 
211  // "normal" Options
212 
214  cStr = rOpt.GetTextSep();
215 }
216 
217 void ScImportExport::SetFilterOptions(const OUString& rFilterOptions)
218 {
219  maFilterOptions = rFilterOptions;
220 }
221 
223 {
224  return nFormat == SotClipboardFormatId::STRING
225  || nFormat == SotClipboardFormatId::STRING_TSVC
226  || nFormat == SotClipboardFormatId::SYLK
227  || nFormat == SotClipboardFormatId::LINK
228  || nFormat == SotClipboardFormatId::HTML
229  || nFormat == SotClipboardFormatId::HTML_SIMPLE
230  || nFormat == SotClipboardFormatId::DIF;
231 }
232 
233 // Prepare for Undo
235 {
236  if ( !bAll )
237  {
238  ScEditableTester aTester( rDoc, aRange );
239  if ( !aTester.IsEditable() )
240  {
241  std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
242  VclMessageType::Info, VclButtonsType::Ok,
243  ScResId(aTester.GetMessageId())));
244  xInfoBox->run();
245  return false;
246  }
247  }
248  if( bUndo && pDocSh && rDoc.IsUndoEnabled())
249  {
250  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
251  pUndoDoc->InitUndo( rDoc, aRange.aStart.Tab(), aRange.aEnd.Tab() );
253  }
254  return true;
255 }
256 
257 // Create Undo/Redo actions, Invalidate/Repaint
258 void ScImportExport::EndPaste(bool bAutoRowHeight)
259 {
260  bool bHeight = bAutoRowHeight && pDocSh && pDocSh->AdjustRowHeight(
262 
263  if( pUndoDoc && rDoc.IsUndoEnabled() && pDocSh )
264  {
266  pRedoDoc->InitUndo( rDoc, aRange.aStart.Tab(), aRange.aEnd.Tab() );
268  ScMarkData aDestMark(pRedoDoc->GetSheetLimits());
269  aDestMark.SetMarkArea(aRange);
271  std::make_unique<ScUndoPaste>(pDocSh, aRange, aDestMark, std::move(pUndoDoc), std::move(pRedoDoc), InsertDeleteFlags::ALL, nullptr));
272  }
273  pUndoDoc.reset();
274  if( pDocSh )
275  {
276  if (!bHeight)
279  }
281  if ( pViewSh )
282  pViewSh->UpdateInputHandler();
283 
284 }
285 
286 bool ScImportExport::ExportData( const OUString& rMimeType,
287  css::uno::Any & rValue )
288 {
289  SvMemoryStream aStrm;
290  // mba: no BaseURL for data exchange
291  if( ExportStream( aStrm, OUString(),
293  {
294  aStrm.WriteUChar( 0 );
295  rValue <<= css::uno::Sequence< sal_Int8 >(
296  static_cast<sal_Int8 const *>(aStrm.GetData()),
297  aStrm.TellEnd() );
298  return true;
299  }
300  return false;
301 }
302 
303 bool ScImportExport::ImportString( const OUString& rText, SotClipboardFormatId nFmt )
304 {
305  switch ( nFmt )
306  {
307  // formats supporting unicode
308  case SotClipboardFormatId::STRING :
309  case SotClipboardFormatId::STRING_TSVC :
310  {
311  ScImportStringStream aStrm( rText);
312  return ImportStream( aStrm, OUString(), nFmt );
313  // ImportStream must handle RTL_TEXTENCODING_UNICODE
314  }
315  default:
316  {
317  rtl_TextEncoding eEnc = osl_getThreadTextEncoding();
318  OString aTmp( rText.getStr(), rText.getLength(), eEnc );
319  SvMemoryStream aStrm( const_cast<char *>(aTmp.getStr()), aTmp.getLength() * sizeof(char), StreamMode::READ );
320  aStrm.SetStreamCharSet( eEnc );
321  SetNoEndianSwap( aStrm );
322  return ImportStream( aStrm, OUString(), nFmt );
323  }
324  }
325 }
326 
328 {
329  if ( nFmt != SotClipboardFormatId::STRING && nFmt != SotClipboardFormatId::STRING_TSVC )
330  {
331  SAL_WARN("sc.ui", "ScImportExport::ExportString: Unicode not supported for other formats than SotClipboardFormatId::STRING[_TSV]");
332  rtl_TextEncoding eEnc = osl_getThreadTextEncoding();
333  OString aTmp;
334  bool bOk = ExportByteString( aTmp, eEnc, nFmt );
335  rText = OStringToOUString( aTmp, eEnc );
336  return bOk;
337  }
338  // nSizeLimit not needed for OUString
339 
340  SvMemoryStream aStrm;
341  aStrm.SetStreamCharSet( RTL_TEXTENCODING_UNICODE );
342  SetNoEndianSwap( aStrm );
343  // mba: no BaseURL for data exc
344  if( ExportStream( aStrm, OUString(), nFmt ) )
345  {
346  aStrm.WriteUInt16( 0 );
347  rText = OUString( static_cast<const sal_Unicode*>(aStrm.GetData()) );
348  return true;
349  }
350  rText.clear();
351  return false;
352 
353  // ExportStream must handle RTL_TEXTENCODING_UNICODE
354 }
355 
356 bool ScImportExport::ExportByteString( OString& rText, rtl_TextEncoding eEnc, SotClipboardFormatId nFmt )
357 {
358  OSL_ENSURE( eEnc != RTL_TEXTENCODING_UNICODE, "ScImportExport::ExportByteString: Unicode not supported" );
359  if ( eEnc == RTL_TEXTENCODING_UNICODE )
360  eEnc = osl_getThreadTextEncoding();
361 
362  if (!nSizeLimit)
364 
365  SvMemoryStream aStrm;
366  aStrm.SetStreamCharSet( eEnc );
367  SetNoEndianSwap( aStrm );
368  // mba: no BaseURL for data exchange
369  if( ExportStream( aStrm, OUString(), nFmt ) )
370  {
371  aStrm.WriteChar( 0 );
372  if( aStrm.TellEnd() <= nSizeLimit )
373  {
374  rText = static_cast<const char*>(aStrm.GetData());
375  return true;
376  }
377  }
378  rText.clear();
379  return false;
380 }
381 
382 bool ScImportExport::ImportStream( SvStream& rStrm, const OUString& rBaseURL, SotClipboardFormatId nFmt )
383 {
384  if( nFmt == SotClipboardFormatId::STRING || nFmt == SotClipboardFormatId::STRING_TSVC )
385  {
386  if( ExtText2Doc( rStrm ) ) // evaluate pExtOptions
387  return true;
388  }
389  if( nFmt == SotClipboardFormatId::SYLK )
390  {
391  if( Sylk2Doc( rStrm ) )
392  return true;
393  }
394  if( nFmt == SotClipboardFormatId::DIF )
395  {
396  if( Dif2Doc( rStrm ) )
397  return true;
398  }
399  if( nFmt == SotClipboardFormatId::RTF || nFmt == SotClipboardFormatId::RICHTEXT )
400  {
401  if( RTF2Doc( rStrm, rBaseURL ) )
402  return true;
403  }
404  if( nFmt == SotClipboardFormatId::LINK )
405  return true; // Link-Import?
406  if ( nFmt == SotClipboardFormatId::HTML )
407  {
408  if( HTML2Doc( rStrm, rBaseURL ) )
409  return true;
410  }
411  if ( nFmt == SotClipboardFormatId::HTML_SIMPLE )
412  {
413  MSE40HTMLClipFormatObj aMSE40ClpObj; // needed to skip the header data
414  SvStream* pHTML = aMSE40ClpObj.IsValid( rStrm );
415  if ( pHTML && HTML2Doc( *pHTML, rBaseURL ) )
416  return true;
417  }
418 
419  return false;
420 }
421 
422 bool ScImportExport::ExportStream( SvStream& rStrm, const OUString& rBaseURL, SotClipboardFormatId nFmt )
423 {
424  if( nFmt == SotClipboardFormatId::STRING || nFmt == SotClipboardFormatId::STRING_TSVC )
425  {
426  if( Doc2Text( rStrm ) )
427  return true;
428  }
429  if( nFmt == SotClipboardFormatId::SYLK )
430  {
431  if( Doc2Sylk( rStrm ) )
432  return true;
433  }
434  if( nFmt == SotClipboardFormatId::DIF )
435  {
436  if( Doc2Dif( rStrm ) )
437  return true;
438  }
439  if( nFmt == SotClipboardFormatId::LINK && !bAll )
440  {
441  OUString aDocName;
442  if ( rDoc.IsClipboard() )
443  aDocName = ScGlobal::GetClipDocName();
444  else
445  {
447  if (pShell)
448  aDocName = pShell->GetTitle( SFX_TITLE_FULLNAME );
449  }
450 
451  OSL_ENSURE( !aDocName.isEmpty(), "ClipBoard document has no name! :-/" );
452  if( !aDocName.isEmpty() )
453  {
454  // Always use Calc A1 syntax for paste link.
455  OUString aRefName;
457  if( bSingle )
459  else
460  {
461  if( aRange.aStart.Tab() != aRange.aEnd.Tab() )
462  nFlags |= ScRefFlags::TAB2_3D;
464  }
465  OUString aAppName = Application::GetAppName();
466 
467  // extra bits are used to tell the client to prefer external
468  // reference link.
469 
470  WriteUnicodeOrByteString( rStrm, aAppName, true );
471  WriteUnicodeOrByteString( rStrm, aDocName, true );
472  WriteUnicodeOrByteString( rStrm, aRefName, true );
473  WriteUnicodeOrByteString( rStrm, "calc:extref", true );
474  if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
475  rStrm.WriteUInt16( 0 );
476  else
477  rStrm.WriteChar( 0 );
478  return rStrm.GetError() == ERRCODE_NONE;
479  }
480  }
481  if( nFmt == SotClipboardFormatId::HTML )
482  {
483  if( Doc2HTML( rStrm, rBaseURL ) )
484  return true;
485  }
486  if( nFmt == SotClipboardFormatId::RTF || nFmt == SotClipboardFormatId::RICHTEXT )
487  {
488  if( Doc2RTF( rStrm ) )
489  return true;
490  }
491 
492  return false;
493 }
494 
495 void ScImportExport::WriteUnicodeOrByteString( SvStream& rStrm, const OUString& rString, bool bZero )
496 {
497  rtl_TextEncoding eEnc = rStrm.GetStreamCharSet();
498  if ( eEnc == RTL_TEXTENCODING_UNICODE )
499  {
500  if ( !lcl_IsEndianSwap( rStrm ) )
501  rStrm.WriteBytes(rString.getStr(), rString.getLength() * sizeof(sal_Unicode));
502  else
503  {
504  const sal_Unicode* p = rString.getStr();
505  const sal_Unicode* const pStop = p + rString.getLength();
506  while ( p < pStop )
507  {
508  rStrm.WriteUInt16( *p );
509  }
510  }
511  if ( bZero )
512  rStrm.WriteUInt16( 0 );
513  }
514  else
515  {
516  OString aByteStr(OUStringToOString(rString, eEnc));
517  rStrm.WriteOString( aByteStr );
518  if ( bZero )
519  rStrm.WriteChar( 0 );
520  }
521 }
522 
523 // This function could be replaced by endlub()
525 {
526  if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
527  { // same as endl() but unicode
528  switch ( rStrm.GetLineDelimiter() )
529  {
530  case LINEEND_CR :
531  rStrm.WriteUInt16( '\r' );
532  break;
533  case LINEEND_LF :
534  rStrm.WriteUInt16( '\n' );
535  break;
536  default:
537  rStrm.WriteUInt16( '\r' ).WriteUInt16( '\n' );
538  }
539  }
540  else
541  endl( rStrm );
542 }
543 
544 sal_Int32 ScImportExport::CountVisualWidth(const OUString& rStr, sal_Int32& nIdx, sal_Int32 nMaxWidth)
545 {
546  sal_Int32 nWidth = 0;
547  while(nIdx < rStr.getLength() && nWidth < nMaxWidth)
548  {
549  sal_uInt32 nCode = rStr.iterateCodePoints(&nIdx);
550 
551  if (unicode::isCJKIVSCharacter(nCode) || (nCode >= 0x3000 && nCode <= 0x303F))
552  nWidth += 2;
553  else if (!unicode::isIVSSelector(nCode))
554  nWidth += 1;
555  }
556 
557  if (nIdx < rStr.getLength())
558  {
559  sal_Int32 nTmpIdx = nIdx;
560  sal_uInt32 nCode = rStr.iterateCodePoints(&nTmpIdx);
561 
562  if (unicode::isIVSSelector(nCode))
563  nIdx = nTmpIdx;
564  }
565  return nWidth;
566 }
567 
568 sal_Int32 ScImportExport::CountVisualWidth(const OUString& rStr)
569 {
570  sal_Int32 nIdx = 0;
571  return CountVisualWidth(rStr, nIdx, SAL_MAX_INT32);
572 }
573 
575 {
576 #ifdef OSL_BIGENDIAN
577  rStrm.SetEndian( SvStreamEndian::BIG );
578 #else
579  rStrm.SetEndian( SvStreamEndian::LITTLE );
580 #endif
581 }
582 
583 namespace {
584 
586 {
587  FIELDSTART_QUOTE,
588  FIRST_QUOTE,
589  SECOND_QUOTE,
590  FIELDEND_QUOTE,
591  DONTKNOW_QUOTE
592 };
593 
594 }
595 
604 static QuoteType lcl_isFieldEndQuote( const sal_Unicode* p, const sal_Unicode* pSeps, sal_Unicode& rcDetectSep )
605 {
606  // Due to broken CSV generators that don't double embedded quotes check if
607  // a field separator immediately or with trailing spaces follows the quote,
608  // only then end the field, or at end of string.
609  const sal_Unicode cBlank = ' ';
610  if (p[1] == cBlank && ScGlobal::UnicodeStrChr( pSeps, cBlank))
611  return FIELDEND_QUOTE;
612  // Detect a possible blank separator if it's not already in the list (which
613  // was checked right above for p[1]==cBlank).
614  if (p[1] == cBlank && !rcDetectSep && p[2] && p[2] != cBlank)
615  rcDetectSep = cBlank;
616  while (p[1] == cBlank)
617  ++p;
618  if (!p[1] || ScGlobal::UnicodeStrChr( pSeps, p[1]))
619  return FIELDEND_QUOTE;
620  return DONTKNOW_QUOTE;
621 }
622 
644 static QuoteType lcl_isEscapedOrFieldEndQuote( sal_Int32 nQuotes, const sal_Unicode* p,
645  const sal_Unicode* pSeps, sal_Unicode cStr, sal_Unicode& rcDetectSep )
646 {
647  if ((nQuotes % 2) == 0)
648  {
649  if (p[-1] == cStr)
650  return SECOND_QUOTE;
651  else
652  {
653  SAL_WARN( "sc", "lcl_isEscapedOrFieldEndQuote: really want a FIELDSTART_QUOTE?");
654  return FIELDSTART_QUOTE;
655  }
656  }
657  if (p[1] == cStr)
658  return FIRST_QUOTE;
659  return lcl_isFieldEndQuote( p, pSeps, rcDetectSep);
660 }
661 
666 static bool lcl_appendLineData( OUString& rField, const sal_Unicode* p1, const sal_Unicode* p2 )
667 {
668  if (rField.getLength() + (p2 - p1) <= nArbitraryCellLengthLimit)
669  {
670  rField += std::u16string_view( p1, sal::static_int_cast<sal_Int32>( p2 - p1 ) );
671  return true;
672  }
673  else
674  {
675  SAL_WARN( "sc", "lcl_appendLineData: data overflow");
676  rField += std::u16string_view( p1, nArbitraryCellLengthLimit - rField.getLength() );
677  return false;
678  }
679 }
680 
681 namespace {
682 
684 {
685  KEEP_ALL, // both are taken, additionally start and end quote are included in string
686  ESCAPE, // escaped quote, one is taken, one ignored
687 };
688 
689 }
690 
691 static const sal_Unicode* lcl_ScanString( const sal_Unicode* p, OUString& rString,
692  const sal_Unicode* pSeps, sal_Unicode cStr, DoubledQuoteMode eMode, bool& rbOverflowCell )
693 {
694  if (eMode != DoubledQuoteMode::KEEP_ALL)
695  p++;
696  bool bCont;
697  do
698  {
699  bCont = false;
700  const sal_Unicode* p0 = p;
701  for( ;; )
702  {
703  if( !*p )
704  break;
705  if( *p == cStr )
706  {
707  if ( *++p != cStr )
708  {
709  // break or continue for loop
710  if (eMode == DoubledQuoteMode::ESCAPE)
711  {
712  sal_Unicode cDetectSep = 0xffff; // No separator detection here.
713  if (lcl_isFieldEndQuote( p-1, pSeps, cDetectSep) == FIELDEND_QUOTE)
714  break;
715  else
716  continue;
717  }
718  else
719  break;
720  }
721  // doubled quote char
722  switch ( eMode )
723  {
724  case DoubledQuoteMode::KEEP_ALL :
725  p++; // both for us (not breaking for-loop)
726  break;
727  case DoubledQuoteMode::ESCAPE :
728  p++; // one for us (breaking for-loop)
729  bCont = true; // and more
730  break;
731  }
732  if ( eMode == DoubledQuoteMode::ESCAPE )
733  break;
734  }
735  else
736  p++;
737  }
738  if ( p0 < p )
739  {
740  if (!lcl_appendLineData( rString, p0, ((eMode != DoubledQuoteMode::KEEP_ALL && (*p || *(p-1) == cStr)) ? p-1 : p)))
741  rbOverflowCell = true;
742  }
743  } while ( bCont );
744  return p;
745 }
746 
747 static void lcl_UnescapeSylk( OUString & rString, SylkVersion eVersion )
748 {
749  // Older versions didn't escape the semicolon.
750  // Older versions quoted the string and doubled embedded quotes, but not
751  // the semicolons, which was plain wrong.
752  if (eVersion >= SylkVersion::OOO32)
753  rString = rString.replaceAll(";;", ";");
754  else
755  rString = rString.replaceAll("\"\"", "\"");
756 
757  rString = rString.replaceAll(SYLK_LF, "\n");
758 }
759 
761  OUString& rString, SylkVersion eVersion )
762 {
763  const sal_Unicode* pStartQuote = p;
764  const sal_Unicode* pEndQuote = nullptr;
765  while( *(++p) )
766  {
767  if( *p == '"' )
768  {
769  pEndQuote = p;
770  if (eVersion >= SylkVersion::OOO32)
771  {
772  if (*(p+1) == ';')
773  {
774  if (*(p+2) == ';')
775  {
776  p += 2; // escaped ';'
777  pEndQuote = nullptr;
778  }
779  else
780  break; // end field
781  }
782  }
783  else
784  {
785  if (*(p+1) == '"')
786  {
787  ++p; // escaped '"'
788  pEndQuote = nullptr;
789  }
790  else if (*(p+1) == ';')
791  break; // end field
792  }
793  }
794  }
795  if (!pEndQuote)
796  pEndQuote = p; // Take all data as string.
797  rString += std::u16string_view(pStartQuote + 1, sal::static_int_cast<sal_Int32>( pEndQuote - pStartQuote - 1 ) );
798  lcl_UnescapeSylk( rString, eVersion);
799  return p;
800 }
801 
803  OUString& rString, SylkVersion eVersion )
804 {
805  const sal_Unicode* pStart = p;
806  if (eVersion >= SylkVersion::OOO32)
807  {
808  while (*p)
809  {
810  if (*p == ';')
811  {
812  if (*(p+1) == ';')
813  ++p; // escaped ';'
814  else
815  break; // end field
816  }
817  ++p;
818  }
819  rString += std::u16string_view( pStart, sal::static_int_cast<sal_Int32>( p - pStart));
820  lcl_UnescapeSylk( rString, eVersion);
821  }
822  else
823  {
824  // Nasty. If in old versions the formula contained a semicolon, it was
825  // quoted and embedded quotes were doubled, but semicolons were not. If
826  // there was no semicolon, it could still contain quotes and doubled
827  // embedded quotes if it was something like ="a""b", which was saved as
828  // E"a""b" as is and has to be preserved, even if older versions
829  // couldn't even load it correctly. However, theoretically another
830  // field might follow and thus the line contain a semicolon again, such
831  // as ...;E"a""b";...
832  bool bQuoted = false;
833  if (*p == '"')
834  {
835  // May be a quoted expression or just a string constant expression
836  // with quotes.
837  while (*(++p))
838  {
839  if (*p == '"')
840  {
841  if (*(p+1) == '"')
842  ++p; // escaped '"'
843  else
844  break; // closing '"', had no ';' yet
845  }
846  else if (*p == ';')
847  {
848  bQuoted = true; // ';' within quoted expression
849  break;
850  }
851  }
852  p = pStart;
853  }
854  if (bQuoted)
855  p = lcl_ScanSylkString( p, rString, eVersion);
856  else
857  {
858  while (*p && *p != ';')
859  ++p;
860  rString += std::u16string_view( pStart, sal::static_int_cast<sal_Int32>( p - pStart));
861  }
862  }
863  return p;
864 }
865 
866 static void lcl_DoubleEscapeChar( OUString& rString, sal_Unicode cStr )
867 {
868  sal_Int32 n = 0;
869  while( ( n = rString.indexOf( cStr, n ) ) != -1 )
870  {
871  rString = rString.replaceAt( n, 0, OUString(cStr) );
872  n += 2;
873  }
874 }
875 
876 static void lcl_WriteString( SvStream& rStrm, OUString& rString, sal_Unicode cQuote, sal_Unicode cEsc )
877 {
878  if (cEsc)
879  lcl_DoubleEscapeChar( rString, cEsc );
880 
881  if (cQuote)
882  {
883  rString = OUStringChar(cQuote) + rString + OUStringChar(cQuote);
884  }
885 
887 }
888 
889 static void lcl_WriteSimpleString( SvStream& rStrm, const OUString& rString )
890 {
892 }
893 
895 {
896  bool bOk = true;
897 
898  sal_Unicode pSeps[2];
899  pSeps[0] = cSep;
900  pSeps[1] = 0;
901 
902  ScSetStringParam aSetStringParam;
903  aSetStringParam.mbCheckLinkFormula = true;
904 
905  SCCOL nStartCol = aRange.aStart.Col();
906  SCROW nStartRow = aRange.aStart.Row();
907  SCCOL nEndCol = aRange.aEnd.Col();
908  SCROW nEndRow = aRange.aEnd.Row();
909  sal_uLong nOldPos = rStrm.Tell();
910  rStrm.StartReadingUnicodeText( rStrm.GetStreamCharSet() );
911  bool bData = !bSingle;
912  if( !bSingle)
913  bOk = StartPaste();
914 
915  while( bOk )
916  {
917  OUString aLine;
918  OUString aCell;
919  SCROW nRow = nStartRow;
920  rStrm.Seek( nOldPos );
921  for( ;; )
922  {
924  // tdf#125440 When inserting tab separated string, consider quotes as field markers
925  DoubledQuoteMode mode = aLine.indexOf("\t") >= 0 ? DoubledQuoteMode::ESCAPE : DoubledQuoteMode::KEEP_ALL;
926  if( rStrm.eof() )
927  break;
928  SCCOL nCol = nStartCol;
929  const sal_Unicode* p = aLine.getStr();
930  while( *p )
931  {
932  aCell.clear();
933  const sal_Unicode* q = p;
934  while (*p && *p != cSep)
935  {
936  // Always look for a pairing quote and ignore separator in between.
937  while (*p && *p == cStr)
938  q = p = lcl_ScanString( p, aCell, pSeps, cStr, mode, bOverflowCell );
939  // All until next separator or quote.
940  while (*p && *p != cSep && *p != cStr)
941  ++p;
942  if (!lcl_appendLineData( aCell, q, p))
943  bOverflowCell = true; // display warning on import
944  q = p;
945  }
946  if (*p)
947  ++p;
948  if (rDoc.ValidCol(nCol) && rDoc.ValidRow(nRow) )
949  {
950  if( bSingle )
951  {
952  if (nCol>nEndCol) nEndCol = nCol;
953  if (nRow>nEndRow) nEndRow = nRow;
954  }
955  if( bData && nCol <= nEndCol && nRow <= nEndRow )
956  rDoc.SetString( nCol, nRow, aRange.aStart.Tab(), aCell, &aSetStringParam );
957  }
958  else // too many columns/rows
959  {
960  if (!rDoc.ValidRow(nRow))
961  bOverflowRow = true; // display warning on import
962  if (!rDoc.ValidCol(nCol))
963  bOverflowCol = true; // display warning on import
964  }
965  ++nCol;
966  }
967  ++nRow;
968  }
969 
970  if( !bData )
971  {
972  aRange.aEnd.SetCol( nEndCol );
973  aRange.aEnd.SetRow( nEndRow );
974  bOk = StartPaste();
975  bData = true;
976  }
977  else
978  break;
979  }
980 
981  EndPaste();
982  if (bOk && mbImportBroadcast)
983  {
984  rDoc.BroadcastCells(aRange, SfxHintId::ScDataChanged);
986  }
987 
988  return bOk;
989 }
990 
991 // Extended Ascii-Import
992 
993 static bool lcl_PutString(
994  ScDocumentImport& rDocImport, bool bUseDocImport,
995  SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString& rStr, sal_uInt8 nColFormat,
996  SvNumberFormatter* pFormatter, bool bDetectNumFormat, bool bSkipEmptyCells,
997  const ::utl::TransliterationWrapper& rTransliteration, CalendarWrapper& rCalendar,
998  const ::utl::TransliterationWrapper* pSecondTransliteration, CalendarWrapper* pSecondCalendar )
999 {
1000  ScDocument& rDoc = rDocImport.getDoc();
1001  bool bMultiLine = false;
1002  if ( nColFormat == SC_COL_SKIP || !rDoc.ValidCol(nCol) || !rDoc.ValidRow(nRow) )
1003  return bMultiLine;
1004  if ( rStr.isEmpty() )
1005  {
1006  if ( !bSkipEmptyCells )
1007  { // delete destination cell
1008  if ( bUseDocImport )
1009  rDocImport.setAutoInput(ScAddress(nCol, nRow, nTab), rStr );
1010  else
1011  rDoc.SetString( nCol, nRow, nTab, rStr );
1012  }
1013  return false;
1014  }
1015 
1016  if ( nColFormat == SC_COL_TEXT )
1017  {
1018  double fDummy;
1019  sal_uInt32 nIndex = 0;
1020  if (pFormatter->IsNumberFormat(rStr, nIndex, fDummy))
1021  {
1022  // Set the format of this cell to Text.
1023  sal_uInt32 nFormat = pFormatter->GetStandardFormat(SvNumFormatType::TEXT);
1024  ScPatternAttr aNewAttrs(rDoc.GetPool());
1025  SfxItemSet& rSet = aNewAttrs.GetItemSet();
1026  rSet.Put( SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat) );
1027  rDoc.ApplyPattern(nCol, nRow, nTab, aNewAttrs);
1028  }
1029  if ( bUseDocImport )
1030  {
1031  if(ScStringUtil::isMultiline(rStr))
1032  {
1033  ScFieldEditEngine& rEngine = rDoc.GetEditEngine();
1034  rEngine.SetTextCurrentDefaults(rStr);
1035  rDocImport.setEditCell(ScAddress(nCol, nRow, nTab), rEngine.CreateTextObject());
1036  return true;
1037  }
1038  else
1039  {
1040  rDocImport.setStringCell(ScAddress(nCol, nRow, nTab), rStr);
1041  return false;
1042  }
1043  } else
1044  {
1045  rDoc.SetTextCell(ScAddress(nCol, nRow, nTab), rStr);
1046  return bMultiLine;
1047  }
1048  }
1049 
1050  if ( nColFormat == SC_COL_ENGLISH )
1051  {
1053 
1054  SvNumberFormatter* pDocFormatter = rDoc.GetFormatTable();
1055  sal_uInt32 nEnglish = pDocFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
1056  double fVal;
1057  if ( pDocFormatter->IsNumberFormat( rStr, nEnglish, fVal ) )
1058  {
1059  // Numberformat will not be set to English
1060  if ( bUseDocImport )
1061  rDocImport.setNumericCell( ScAddress( nCol, nRow, nTab ), fVal );
1062  else
1063  rDoc.SetValue( nCol, nRow, nTab, fVal );
1064  return bMultiLine;
1065  }
1066  // else, continue with SetString
1067  }
1068  else if ( nColFormat != SC_COL_STANDARD ) // Datumformats
1069  {
1070  const sal_uInt16 nMaxNumberParts = 7; // Y-M-D h:m:s.t
1071  const sal_Int32 nLen = rStr.getLength();
1072  sal_Int32 nStart[nMaxNumberParts];
1073  sal_Int32 nEnd[nMaxNumberParts];
1074 
1075  sal_uInt16 nDP, nMP, nYP;
1076  switch ( nColFormat )
1077  {
1078  case SC_COL_YMD: nDP = 2; nMP = 1; nYP = 0; break;
1079  case SC_COL_MDY: nDP = 1; nMP = 0; nYP = 2; break;
1080  case SC_COL_DMY:
1081  default: nDP = 0; nMP = 1; nYP = 2; break;
1082  }
1083 
1084  sal_uInt16 nFound = 0;
1085  bool bInNum = false;
1086  for ( sal_Int32 nPos=0; nPos<nLen && (bInNum ||
1087  nFound<nMaxNumberParts); nPos++ )
1088  {
1089  if (bInNum && nFound == 3 && nColFormat == SC_COL_YMD &&
1090  nPos <= nStart[nFound]+2 && rStr[nPos] == 'T')
1091  bInNum = false; // ISO-8601: YYYY-MM-DDThh:mm...
1092  else if ((((!bInNum && nFound==nMP) || (bInNum && nFound==nMP+1))
1093  && ScGlobal::getCharClassPtr()->isLetterNumeric( rStr, nPos))
1094  || ScGlobal::getCharClassPtr()->isDigit( rStr, nPos))
1095  {
1096  if (!bInNum)
1097  {
1098  bInNum = true;
1099  nStart[nFound] = nPos;
1100  ++nFound;
1101  }
1102  nEnd[nFound-1] = nPos;
1103  }
1104  else
1105  bInNum = false;
1106  }
1107 
1108  if ( nFound == 1 )
1109  {
1110  // try to break one number (without separators) into date fields
1111 
1112  sal_Int32 nDateStart = nStart[0];
1113  sal_Int32 nDateLen = nEnd[0] + 1 - nDateStart;
1114 
1115  if ( nDateLen >= 5 && nDateLen <= 8 &&
1116  ScGlobal::getCharClassPtr()->isNumeric( rStr.copy( nDateStart, nDateLen ) ) )
1117  {
1118  // 6 digits: 2 each for day, month, year
1119  // 8 digits: 4 for year, 2 each for day and month
1120  // 5 or 7 digits: first field is shortened by 1
1121 
1122  bool bLongYear = ( nDateLen >= 7 );
1123  bool bShortFirst = ( nDateLen == 5 || nDateLen == 7 );
1124 
1125  sal_uInt16 nFieldStart = nDateStart;
1126  for (sal_uInt16 nPos=0; nPos<3; nPos++)
1127  {
1128  sal_uInt16 nFieldEnd = nFieldStart + 1; // default: 2 digits
1129  if ( bLongYear && nPos == nYP )
1130  nFieldEnd += 2; // 2 extra digits for long year
1131  if ( bShortFirst && nPos == 0 )
1132  --nFieldEnd; // first field shortened?
1133 
1134  nStart[nPos] = nFieldStart;
1135  nEnd[nPos] = nFieldEnd;
1136  nFieldStart = nFieldEnd + 1;
1137  }
1138  nFound = 3;
1139  }
1140  }
1141 
1142  if ( nFound >= 3 )
1143  {
1144  using namespace ::com::sun::star;
1145  bool bSecondCal = false;
1146  sal_uInt16 nDay = static_cast<sal_uInt16>(rStr.copy( nStart[nDP], nEnd[nDP]+1-nStart[nDP] ).toInt32());
1147  sal_uInt16 nYear = static_cast<sal_uInt16>(rStr.copy( nStart[nYP], nEnd[nYP]+1-nStart[nYP] ).toInt32());
1148  OUString aMStr = rStr.copy( nStart[nMP], nEnd[nMP]+1-nStart[nMP] );
1149  sal_Int16 nMonth = static_cast<sal_Int16>(aMStr.toInt32());
1150  if (!nMonth)
1151  {
1152  static constexpr OUStringLiteral aSepShortened = u"SEP";
1153  uno::Sequence< i18n::CalendarItem2 > xMonths;
1154  sal_Int32 i, nMonthCount;
1155  // first test all month names from local international
1156  xMonths = rCalendar.getMonths();
1157  nMonthCount = xMonths.getLength();
1158  for (i=0; i<nMonthCount && !nMonth; i++)
1159  {
1160  if ( rTransliteration.isEqual( aMStr, xMonths[i].FullName ) ||
1161  rTransliteration.isEqual( aMStr, xMonths[i].AbbrevName ) )
1162  nMonth = sal::static_int_cast<sal_Int16>( i+1 );
1163  else if ( i == 8 && rTransliteration.isEqual( "SEPT",
1164  xMonths[i].AbbrevName ) &&
1165  rTransliteration.isEqual( aMStr, aSepShortened ) )
1166  { // correct English abbreviation is SEPT,
1167  // but data mostly contains SEP only
1168  nMonth = sal::static_int_cast<sal_Int16>( i+1 );
1169  }
1170  }
1171  // if none found, then test english month names
1172  if ( !nMonth && pSecondCalendar && pSecondTransliteration )
1173  {
1174  xMonths = pSecondCalendar->getMonths();
1175  nMonthCount = xMonths.getLength();
1176  for (i=0; i<nMonthCount && !nMonth; i++)
1177  {
1178  if ( pSecondTransliteration->isEqual( aMStr, xMonths[i].FullName ) ||
1179  pSecondTransliteration->isEqual( aMStr, xMonths[i].AbbrevName ) )
1180  {
1181  nMonth = sal::static_int_cast<sal_Int16>( i+1 );
1182  bSecondCal = true;
1183  }
1184  else if ( i == 8 && pSecondTransliteration->isEqual(
1185  aMStr, aSepShortened ) )
1186  { // correct English abbreviation is SEPT,
1187  // but data mostly contains SEP only
1188  nMonth = sal::static_int_cast<sal_Int16>( i+1 );
1189  bSecondCal = true;
1190  }
1191  }
1192  }
1193  }
1194 
1195  SvNumberFormatter* pDocFormatter = rDoc.GetFormatTable();
1196  if ( nYear < 100 )
1197  nYear = pDocFormatter->ExpandTwoDigitYear( nYear );
1198 
1199  CalendarWrapper* pCalendar = (bSecondCal ? pSecondCalendar : &rCalendar);
1200  sal_Int16 nNumMonths = pCalendar->getNumberOfMonthsInYear();
1201  if ( nDay && nMonth && nDay<=31 && nMonth<=nNumMonths )
1202  {
1203  --nMonth;
1204  pCalendar->setValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, nDay );
1205  pCalendar->setValue( i18n::CalendarFieldIndex::MONTH, nMonth );
1206  pCalendar->setValue( i18n::CalendarFieldIndex::YEAR, nYear );
1207  sal_Int16 nHour, nMinute, nSecond;
1208  // #i14974# The imported value should have no fractional value, so set the
1209  // time fields to zero (ICU calendar instance defaults to current date/time)
1210  nHour = nMinute = nSecond = 0;
1211  if (nFound > 3)
1212  nHour = static_cast<sal_Int16>(rStr.copy( nStart[3], nEnd[3]+1-nStart[3]).toInt32());
1213  if (nFound > 4)
1214  nMinute = static_cast<sal_Int16>(rStr.copy( nStart[4], nEnd[4]+1-nStart[4]).toInt32());
1215  if (nFound > 5)
1216  nSecond = static_cast<sal_Int16>(rStr.copy( nStart[5], nEnd[5]+1-nStart[5]).toInt32());
1217  // do not use calendar's milliseconds, to avoid fractional part truncation
1218  double fFrac = 0.0;
1219  if (nFound > 6)
1220  {
1221  sal_Unicode cDec = '.';
1222  OUString aT = OUStringChar(cDec) + rStr.subView( nStart[6], nEnd[6]+1-nStart[6]);
1223  rtl_math_ConversionStatus eStatus;
1224  double fV = rtl::math::stringToDouble( aT, cDec, 0, &eStatus );
1225  if (eStatus == rtl_math_ConversionStatus_Ok)
1226  fFrac = fV / 86400.0;
1227  }
1228  sal_Int32 nPos;
1229  if (nFound > 3 && 1 <= nHour && nHour <= 12 // nHour 0 and >=13 can't be AM/PM
1230  && (nPos = nEnd[nFound-1] + 1) < nLen)
1231  {
1232  // Dreaded AM/PM may be following.
1233  while (nPos < nLen && rStr[nPos] == ' ')
1234  ++nPos;
1235  if (nPos < nLen)
1236  {
1237  sal_Int32 nStop = nPos;
1238  while (nStop < nLen && rStr[nStop] != ' ')
1239  ++nStop;
1240  OUString aAmPm = rStr.copy( nPos, nStop - nPos);
1241  // For AM only 12 needs to be treated, whereas for PM
1242  // it must not. Check both, locale and second/English
1243  // strings.
1244  if (nHour == 12 &&
1245  (rTransliteration.isEqual( aAmPm, pFormatter->GetLocaleData()->getTimeAM()) ||
1246  (pSecondTransliteration && pSecondTransliteration->isEqual( aAmPm, "AM"))))
1247  {
1248  nHour = 0;
1249  }
1250  else if (nHour < 12 &&
1251  (rTransliteration.isEqual( aAmPm, pFormatter->GetLocaleData()->getTimePM()) ||
1252  (pSecondTransliteration && pSecondTransliteration->isEqual( aAmPm, "PM"))))
1253  {
1254  nHour += 12;
1255  }
1256  }
1257  }
1258  pCalendar->setValue( i18n::CalendarFieldIndex::HOUR, nHour );
1259  pCalendar->setValue( i18n::CalendarFieldIndex::MINUTE, nMinute );
1260  pCalendar->setValue( i18n::CalendarFieldIndex::SECOND, nSecond );
1261  pCalendar->setValue( i18n::CalendarFieldIndex::MILLISECOND, 0 );
1262  if ( pCalendar->isValid() )
1263  {
1264  double fDiff = DateTime(pDocFormatter->GetNullDate()) -
1265  pCalendar->getEpochStart();
1266  // #i14974# must use getLocalDateTime to get the same
1267  // date values as set above
1268  double fDays = pCalendar->getLocalDateTime() + fFrac;
1269  fDays -= fDiff;
1270 
1271  LanguageType eLatin, eCjk, eCtl;
1272  rDoc.GetLanguage( eLatin, eCjk, eCtl );
1273  LanguageType eDocLang = eLatin; //! which language for date formats?
1274 
1275  SvNumFormatType nType = (nFound > 3 ? SvNumFormatType::DATETIME : SvNumFormatType::DATE);
1276  sal_uLong nFormat = pDocFormatter->GetStandardFormat( nType, eDocLang );
1277  // maybe there is a special format including seconds or milliseconds
1278  if (nFound > 5)
1279  nFormat = pDocFormatter->GetStandardFormat( fDays, nFormat, nType, eDocLang);
1280 
1281  ScAddress aPos(nCol,nRow,nTab);
1282  if ( bUseDocImport )
1283  rDocImport.setNumericCell(aPos, fDays);
1284  else
1285  rDoc.SetValue( aPos, fDays );
1286  rDoc.SetNumberFormat(aPos, nFormat);
1287 
1288  return bMultiLine; // success
1289  }
1290  }
1291  }
1292  }
1293 
1294  // Standard or date not determined -> SetString / EditCell
1295  if( rStr.indexOf( '\n' ) == -1 )
1296  {
1297  ScSetStringParam aParam;
1298  aParam.mpNumFormatter = pFormatter;
1299  aParam.mbDetectNumberFormat = bDetectNumFormat;
1300  aParam.meSetTextNumFormat = ScSetStringParam::SpecialNumberOnly;
1301  aParam.mbHandleApostrophe = false;
1302  aParam.mbCheckLinkFormula = true;
1303  if ( bUseDocImport )
1304  rDocImport.setAutoInput(ScAddress(nCol, nRow, nTab), rStr, &aParam);
1305  else
1306  rDoc.SetString( nCol, nRow, nTab, rStr, &aParam );
1307  }
1308  else
1309  {
1310  bMultiLine = true;
1311  ScFieldEditEngine& rEngine = rDoc.GetEditEngine();
1312  rEngine.SetTextCurrentDefaults(rStr);
1313  if ( bUseDocImport )
1314  rDocImport.setEditCell(ScAddress(nCol, nRow, nTab), rEngine.CreateTextObject());
1315  else
1316  rDoc.SetEditText( ScAddress( nCol, nRow, nTab ), rEngine.CreateTextObject() );
1317  }
1318  return bMultiLine;
1319 }
1320 
1321 static OUString lcl_GetFixed( const OUString& rLine, sal_Int32 nStart, sal_Int32 nNext,
1322  bool& rbIsQuoted, bool& rbOverflowCell )
1323 {
1324  sal_Int32 nLen = rLine.getLength();
1325  if (nNext > nLen)
1326  nNext = nLen;
1327  if ( nNext <= nStart )
1328  return EMPTY_OUSTRING;
1329 
1330  const sal_Unicode* pStr = rLine.getStr();
1331 
1332  sal_Int32 nSpace = nNext;
1333  while ( nSpace > nStart && pStr[nSpace-1] == ' ' )
1334  --nSpace;
1335 
1336  rbIsQuoted = (pStr[nStart] == '"' && pStr[nSpace-1] == '"');
1337  if (rbIsQuoted)
1338  {
1339  bool bFits = (nSpace - nStart - 3 <= nArbitraryCellLengthLimit);
1340  if (bFits)
1341  return rLine.copy(nStart+1, std::max< sal_Int32 >(0, nSpace-nStart-2));
1342  else
1343  {
1344  SAL_WARN( "sc", "lcl_GetFixed: line doesn't fit into data");
1345  rbOverflowCell = true;
1346  return rLine.copy(nStart+1, nArbitraryCellLengthLimit);
1347  }
1348  }
1349  else
1350  {
1351  bool bFits = (nSpace - nStart <= nArbitraryCellLengthLimit);
1352  if (bFits)
1353  return rLine.copy(nStart, nSpace-nStart);
1354  else
1355  {
1356  SAL_WARN( "sc", "lcl_GetFixed: line doesn't fit into data");
1357  rbOverflowCell = true;
1358  return rLine.copy(nStart, nArbitraryCellLengthLimit);
1359  }
1360  }
1361 }
1362 
1363 bool ScImportExport::ExtText2Doc( SvStream& rStrm )
1364 {
1365  if (!pExtOptions)
1366  return Text2Doc( rStrm );
1367 
1368  sal_uInt64 const nOldPos = rStrm.Tell();
1369  sal_uInt64 const nRemaining = rStrm.remainingSize();
1370  std::unique_ptr<ScProgress> xProgress( new ScProgress( pDocSh,
1371  ScResId( STR_LOAD_DOC ), nRemaining, true ));
1372  rStrm.StartReadingUnicodeText( rStrm.GetStreamCharSet() );
1373 
1374  SCCOL nStartCol = aRange.aStart.Col();
1375  SCCOL nEndCol = aRange.aEnd.Col();
1376  SCROW nStartRow = aRange.aStart.Row();
1377  SCTAB nTab = aRange.aStart.Tab();
1378 
1379  bool bFixed = pExtOptions->IsFixedLen();
1380  OUString aSeps = pExtOptions->GetFieldSeps(); // Need non-const for ReadCsvLine(),
1381  const sal_Unicode* pSeps = aSeps.getStr(); // but it will be const anyway (asserted below).
1382  bool bMerge = pExtOptions->IsMergeSeps();
1383  bool bRemoveSpace = pExtOptions->IsRemoveSpace();
1384  sal_uInt16 nInfoCount = pExtOptions->GetInfoCount();
1385  const sal_Int32* pColStart = pExtOptions->GetColStart();
1386  const sal_uInt8* pColFormat = pExtOptions->GetColFormat();
1387  tools::Long nSkipLines = pExtOptions->GetStartRow();
1388 
1389  LanguageType eDocLang = pExtOptions->GetLanguage();
1390  SvNumberFormatter aNumFormatter( comphelper::getProcessComponentContext(), eDocLang);
1391  bool bDetectNumFormat = pExtOptions->IsDetectSpecialNumber();
1392  bool bSkipEmptyCells = pExtOptions->IsSkipEmptyCells();
1393 
1394  // For date recognition
1395  ::utl::TransliterationWrapper aTransliteration(
1396  comphelper::getProcessComponentContext(), TransliterationFlags::IGNORE_CASE );
1397  aTransliteration.loadModuleIfNeeded( eDocLang );
1398  CalendarWrapper aCalendar( comphelper::getProcessComponentContext() );
1399  aCalendar.loadDefaultCalendar(
1400  LanguageTag::convertToLocale( eDocLang ) );
1401  std::unique_ptr< ::utl::TransliterationWrapper > pEnglishTransliteration;
1402  std::unique_ptr< CalendarWrapper > pEnglishCalendar;
1403  if ( eDocLang != LANGUAGE_ENGLISH_US )
1404  {
1405  pEnglishTransliteration.reset(new ::utl::TransliterationWrapper (
1406  comphelper::getProcessComponentContext(), TransliterationFlags::IGNORE_CASE ));
1407  aTransliteration.loadModuleIfNeeded( LANGUAGE_ENGLISH_US );
1408  pEnglishCalendar.reset(new CalendarWrapper ( comphelper::getProcessComponentContext() ));
1409  pEnglishCalendar->loadDefaultCalendar(
1410  LanguageTag::convertToLocale( LANGUAGE_ENGLISH_US ) );
1411  }
1412 
1413  OUString aLine;
1414  OUString aCell;
1415  sal_uInt16 i;
1416  SCROW nRow = nStartRow;
1417  sal_Unicode cDetectSep = 0xffff; // No separator detection here.
1418 
1419  while(--nSkipLines>0)
1420  {
1421  aLine = ReadCsvLine(rStrm, !bFixed, aSeps, cStr, cDetectSep); // content is ignored
1422  if ( rStrm.eof() )
1423  break;
1424  }
1425 
1426  // Determine range for Undo.
1427  // We don't need this during import of a file to a new sheet or document...
1428  bool bDetermineRange = bUndo;
1429 
1430  // Row heights don't need to be adjusted on the fly if EndPaste() is called
1431  // afterwards, which happens only if bDetermineRange. This variable also
1432  // survives the toggle of bDetermineRange down at the end of the do{} loop.
1433  bool bRangeIsDetermined = bDetermineRange;
1434 
1435  bool bQuotedAsText = pExtOptions && pExtOptions->IsQuotedAsText();
1436 
1437  sal_uLong nOriginalStreamPos = rStrm.Tell();
1438 
1439  ScDocumentImport aDocImport(rDoc);
1440  do
1441  {
1442  for( ;; )
1443  {
1444  aLine = ReadCsvLine(rStrm, !bFixed, aSeps, cStr, cDetectSep);
1445  if ( rStrm.eof() && aLine.isEmpty() )
1446  break;
1447 
1448  assert(pSeps == aSeps.getStr());
1449 
1450  if ( nRow > rDoc.MaxRow() )
1451  {
1452  bOverflowRow = true; // display warning on import
1453  break; // for
1454  }
1455 
1456  EmbeddedNullTreatment( aLine);
1457 
1458  sal_Int32 nLineLen = aLine.getLength();
1459  SCCOL nCol = nStartCol;
1460  bool bMultiLine = false;
1461  if ( bFixed ) // Fixed line length
1462  {
1463  sal_Int32 nStartIdx = 0;
1464  // Yes, the check is nCol<=rDoc.MaxCol()+1, +1 because it is only an
1465  // overflow if there is really data following to be put behind
1466  // the last column, which doesn't happen if info is
1467  // SC_COL_SKIP.
1468  for ( i=0; i<nInfoCount && nCol <= rDoc.MaxCol()+1; i++ )
1469  {
1470  sal_uInt8 nFmt = pColFormat[i];
1471  if (nFmt != SC_COL_SKIP) // otherwise don't increment nCol either
1472  {
1473  if (nCol > rDoc.MaxCol())
1474  bOverflowCol = true; // display warning on import
1475  else if (!bDetermineRange)
1476  {
1477  sal_Int32 nNextIdx = nStartIdx;
1478  if ( i + 1 < nInfoCount )
1479  CountVisualWidth( aLine, nNextIdx, pColStart[i+1] - pColStart[i] );
1480  else
1481  nNextIdx = nLineLen;
1482 
1483  bool bIsQuoted = false;
1484  aCell = lcl_GetFixed( aLine, nStartIdx, nNextIdx, bIsQuoted, bOverflowCell );
1485  if (bIsQuoted && bQuotedAsText)
1486  nFmt = SC_COL_TEXT;
1487 
1488  bMultiLine |= lcl_PutString(
1489  aDocImport, !mbOverwriting, nCol, nRow, nTab, aCell, nFmt,
1490  &aNumFormatter, bDetectNumFormat, bSkipEmptyCells, aTransliteration, aCalendar,
1491  pEnglishTransliteration.get(), pEnglishCalendar.get());
1492 
1493  nStartIdx = nNextIdx;
1494  }
1495  ++nCol;
1496  }
1497  }
1498  }
1499  else // Search for the separator
1500  {
1501  SCCOL nSourceCol = 0;
1502  sal_uInt16 nInfoStart = 0;
1503  const sal_Unicode* p = aLine.getStr();
1504  // Yes, the check is nCol<=rDoc.MaxCol()+1, +1 because it is only an
1505  // overflow if there is really data following to be put behind
1506  // the last column, which doesn't happen if info is
1507  // SC_COL_SKIP.
1508  while (*p && nCol <= rDoc.MaxCol()+1)
1509  {
1510  bool bIsQuoted = false;
1512  cStr, pSeps, bMerge, bIsQuoted, bOverflowCell, bRemoveSpace );
1513 
1514  sal_uInt8 nFmt = SC_COL_STANDARD;
1515  for ( i=nInfoStart; i<nInfoCount; i++ )
1516  {
1517  if ( pColStart[i] == nSourceCol + 1 ) // pColStart is 1-based
1518  {
1519  nFmt = pColFormat[i];
1520  nInfoStart = i + 1; // ColInfos are in succession
1521  break; // for
1522  }
1523  }
1524  if ( nFmt != SC_COL_SKIP )
1525  {
1526  if (nCol > rDoc.MaxCol())
1527  bOverflowCol = true; // display warning on import
1528  else if (!bDetermineRange)
1529  {
1530  if (bIsQuoted && bQuotedAsText)
1531  nFmt = SC_COL_TEXT;
1532 
1533  bMultiLine |= lcl_PutString(
1534  aDocImport, !mbOverwriting, nCol, nRow, nTab, aCell, nFmt,
1535  &aNumFormatter, bDetectNumFormat, bSkipEmptyCells, aTransliteration,
1536  aCalendar, pEnglishTransliteration.get(), pEnglishCalendar.get());
1537  }
1538  ++nCol;
1539  }
1540 
1541  ++nSourceCol;
1542  }
1543  }
1544  if (nEndCol < nCol)
1545  nEndCol = nCol;
1546 
1547  if (!bDetermineRange)
1548  {
1549  if (bMultiLine && !bRangeIsDetermined && pDocSh)
1550  pDocSh->AdjustRowHeight( nRow, nRow, nTab);
1551  xProgress->SetStateOnPercent( rStrm.Tell() - nOldPos );
1552  }
1553  ++nRow;
1554  }
1555  // so far nRow/nEndCol pointed to the next free
1556  if (nRow > nStartRow)
1557  --nRow;
1558  if (nEndCol > nStartCol)
1559  nEndCol = ::std::min( static_cast<SCCOL>(nEndCol - 1), rDoc.MaxCol());
1560 
1561  if (bDetermineRange)
1562  {
1563  aRange.aEnd.SetCol( nEndCol );
1564  aRange.aEnd.SetRow( nRow );
1565 
1566  if ( !mbApi && nStartCol != nEndCol &&
1567  !rDoc.IsBlockEmpty( nTab, nStartCol + 1, nStartRow, nEndCol, nRow ) )
1568  {
1570  if (aBox.run() != RET_YES)
1571  {
1572  return false;
1573  }
1574  }
1575 
1576  rStrm.Seek( nOriginalStreamPos );
1577  nRow = nStartRow;
1578  if (!StartPaste())
1579  {
1580  EndPaste(false);
1581  return false;
1582  }
1583  }
1584 
1585  bDetermineRange = !bDetermineRange; // toggle
1586  } while (!bDetermineRange);
1587  if ( !mbOverwriting )
1588  aDocImport.finalize();
1589 
1590  xProgress.reset(); // make room for AdjustRowHeight progress
1591  if (bRangeIsDetermined)
1592  EndPaste(false);
1593 
1594  if (mbImportBroadcast && !mbOverwriting)
1595  {
1596  rDoc.BroadcastCells(aRange, SfxHintId::ScDataChanged);
1597  pDocSh->PostDataChanged();
1598  }
1599  return true;
1600 }
1601 
1603 {
1604  // A nasty workaround for data with embedded NULL characters. As long as we
1605  // can't handle them properly as cell content (things assume 0-terminated
1606  // strings at too many places) simply strip all NULL characters from raw
1607  // data. Excel does the same. See fdo#57841 for sample data.
1608 
1609  // The normal case is no embedded NULL, check first before de-/allocating
1610  // ustring stuff.
1611  sal_Unicode cNull = 0;
1612  if (rStr.indexOf( cNull) >= 0)
1613  {
1614  rStr = rStr.replaceAll( std::u16string_view( &cNull, 1), "");
1615  }
1616 }
1617 
1619  OUString& rField, sal_Unicode cStr, const sal_Unicode* pSeps, bool bMergeSeps, bool& rbIsQuoted,
1620  bool& rbOverflowCell, bool bRemoveSpace )
1621 {
1622  rbIsQuoted = false;
1623  rField.clear();
1624  const sal_Unicode cBlank = ' ';
1625  if (cStr && !ScGlobal::UnicodeStrChr(pSeps, cBlank))
1626  {
1627  // Cope with broken generators that put leading blanks before a quoted
1628  // field, like "field1", "field2", "..."
1629  // NOTE: this is not in conformance with http://tools.ietf.org/html/rfc4180
1630  const sal_Unicode* pb = p;
1631  while (*pb == cBlank)
1632  ++pb;
1633  if (*pb == cStr)
1634  p = pb;
1635  }
1636  if (cStr && *p == cStr) // String in quotes
1637  {
1638  rbIsQuoted = true;
1639  const sal_Unicode* p1;
1640  p1 = p = lcl_ScanString( p, rField, pSeps, cStr, DoubledQuoteMode::ESCAPE, rbOverflowCell );
1641  while ( *p && !ScGlobal::UnicodeStrChr( pSeps, *p ) )
1642  p++;
1643  // Append remaining unquoted and undelimited data (dirty, dirty) to
1644  // this field.
1645  if (p > p1)
1646  {
1647  const sal_Unicode* ptrim_f = p;
1648  if ( bRemoveSpace )
1649  {
1650  while ( ptrim_f > p1 && ( *(ptrim_f - 1) == cBlank ) )
1651  --ptrim_f;
1652  }
1653  if (!lcl_appendLineData( rField, p1, ptrim_f))
1654  rbOverflowCell = true;
1655  }
1656  if( *p )
1657  p++;
1658  }
1659  else // up to delimiter
1660  {
1661  const sal_Unicode* p0 = p;
1662  while ( *p && !ScGlobal::UnicodeStrChr( pSeps, *p ) )
1663  p++;
1664  const sal_Unicode* ptrim_i = p0;
1665  const sal_Unicode* ptrim_f = p; // [ptrim_i,ptrim_f) is cell data after trimming
1666  if ( bRemoveSpace )
1667  {
1668  while ( *ptrim_i == cBlank )
1669  ++ptrim_i;
1670  while ( ptrim_f > ptrim_i && ( *(ptrim_f - 1) == cBlank ) )
1671  --ptrim_f;
1672  }
1673  if (!lcl_appendLineData( rField, ptrim_i, ptrim_f))
1674  rbOverflowCell = true;
1675  if( *p )
1676  p++;
1677  }
1678  if ( bMergeSeps ) // skip following delimiters
1679  {
1680  while ( *p && ScGlobal::UnicodeStrChr( pSeps, *p ) )
1681  p++;
1682  }
1683  return p;
1684 }
1685 
1686 namespace {
1687 
1694 bool hasLineBreaksOrSeps( const OUString& rStr, sal_Unicode cSep )
1695 {
1696  const sal_Unicode* p = rStr.getStr();
1697  for (sal_Int32 i = 0, n = rStr.getLength(); i < n; ++i, ++p)
1698  {
1699  sal_Unicode c = *p;
1700  if (c == cSep)
1701  // separator found.
1702  return true;
1703 
1704  switch (c)
1705  {
1706  case '\n':
1707  case '\r':
1708  // line break found.
1709  return true;
1710  default:
1711  ;
1712  }
1713  }
1714  return false;
1715 }
1716 
1717 }
1718 
1720 {
1721  SCCOL nCol;
1722  SCROW nRow;
1723  SCCOL nStartCol = aRange.aStart.Col();
1724  SCROW nStartRow = aRange.aStart.Row();
1725  SCTAB nStartTab = aRange.aStart.Tab();
1726  SCCOL nEndCol = aRange.aEnd.Col();
1727  SCROW nEndRow = aRange.aEnd.Row();
1728  SCTAB nEndTab = aRange.aEnd.Tab();
1729 
1730  if (!rDoc.GetClipParam().isMultiRange() && nStartTab == nEndTab)
1731  if (!rDoc.ShrinkToDataArea( nStartTab, nStartCol, nStartRow, nEndCol, nEndRow ))
1732  return false;
1733 
1734  OUString aCellStr;
1735 
1736  bool bConvertLF = (GetSystemLineEnd() != LINEEND_LF);
1737 
1738  // We need to cache sc::ColumnBlockPosition per each column, tab is always nStartTab.
1739  std::vector< sc::ColumnBlockPosition > blockPos( nEndCol - nStartCol + 1 );
1740  for( SCCOL i = nStartCol; i <= nEndCol; ++i )
1741  rDoc.InitColumnBlockPosition( blockPos[ i - nStartCol ], nStartTab, i );
1742  for (nRow = nStartRow; nRow <= nEndRow; nRow++)
1743  {
1744  if (bIncludeFiltered || !rDoc.RowFiltered( nRow, nStartTab ))
1745  {
1746  for (nCol = nStartCol; nCol <= nEndCol; nCol++)
1747  {
1748  ScAddress aPos(nCol, nRow, nStartTab);
1749  sal_uInt32 nNumFmt = rDoc.GetNumberFormat(aPos);
1750  SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
1751 
1752  ScRefCellValue aCell(rDoc, aPos, blockPos[ nCol - nStartCol ]);
1753  switch (aCell.meType)
1754  {
1755  case CELLTYPE_FORMULA:
1756  {
1757  if (bFormulas)
1758  {
1759  aCell.mpFormula->GetFormula( aCellStr );
1760  if( aCellStr.indexOf( cSep ) != -1 )
1761  lcl_WriteString( rStrm, aCellStr, cStr, cStr );
1762  else
1763  lcl_WriteSimpleString( rStrm, aCellStr );
1764  }
1765  else
1766  {
1767  const Color* pColor;
1768  ScCellFormat::GetString(aCell, nNumFmt, aCellStr, &pColor, *pFormatter, rDoc);
1769 
1770  bool bMultiLineText = ( aCellStr.indexOf( '\n' ) != -1 );
1771  if( bMultiLineText )
1772  {
1774  aCellStr = aCellStr.replaceAll( "\n", " " );
1776  aCellStr = convertLineEnd(aCellStr, GetSystemLineEnd());
1777  }
1778 
1780  aCellStr = aCellStr.replaceAll( OUStringChar(cSep), OUStringChar(mExportTextOptions.mcSeparatorConvertTo) );
1781 
1782  if( mExportTextOptions.mbAddQuotes && ( aCellStr.indexOf( cSep ) != -1 ) )
1783  lcl_WriteString( rStrm, aCellStr, cStr, cStr );
1784  else
1785  lcl_WriteSimpleString( rStrm, aCellStr );
1786  }
1787  }
1788  break;
1789  case CELLTYPE_VALUE:
1790  {
1791  const Color* pColor;
1792  ScCellFormat::GetString(aCell, nNumFmt, aCellStr, &pColor, *pFormatter, rDoc);
1793  lcl_WriteSimpleString( rStrm, aCellStr );
1794  }
1795  break;
1796  case CELLTYPE_NONE:
1797  break;
1798  default:
1799  {
1800  const Color* pColor;
1801  ScCellFormat::GetString(aCell, nNumFmt, aCellStr, &pColor, *pFormatter, rDoc);
1802 
1803  bool bMultiLineText = ( aCellStr.indexOf( '\n' ) != -1 );
1804  if( bMultiLineText )
1805  {
1807  aCellStr = aCellStr.replaceAll( "\n", " " );
1809  aCellStr = convertLineEnd(aCellStr, GetSystemLineEnd());
1810  }
1811 
1813  aCellStr = aCellStr.replaceAll( OUStringChar(cSep), OUStringChar(mExportTextOptions.mcSeparatorConvertTo) );
1814 
1815  if( mExportTextOptions.mbAddQuotes && hasLineBreaksOrSeps(aCellStr, cSep) )
1816  lcl_WriteString( rStrm, aCellStr, cStr, cStr );
1817  else
1818  lcl_WriteSimpleString( rStrm, aCellStr );
1819  }
1820  }
1821  if( nCol < nEndCol )
1822  lcl_WriteSimpleString( rStrm, OUString(cSep) );
1823  }
1824  WriteUnicodeOrByteEndl( rStrm );
1825  if( rStrm.GetError() != ERRCODE_NONE )
1826  break;
1827  if( nSizeLimit && rStrm.Tell() > nSizeLimit )
1828  break;
1829  }
1830  }
1831 
1832  return rStrm.GetError() == ERRCODE_NONE;
1833 }
1834 
1836 {
1837  bool bOk = true;
1838  bool bMyDoc = false;
1839  SylkVersion eVersion = SylkVersion::OTHER;
1840 
1841  // US-English separators for StringToDouble
1842  sal_Unicode const cDecSep = '.';
1843  sal_Unicode const cGrpSep = ',';
1844 
1845  SCCOL nStartCol = aRange.aStart.Col();
1846  SCROW nStartRow = aRange.aStart.Row();
1847  SCCOL nEndCol = aRange.aEnd.Col();
1848  SCROW nEndRow = aRange.aEnd.Row();
1849  sal_uLong nOldPos = rStrm.Tell();
1850  bool bData = !bSingle;
1851  ::std::vector< sal_uInt32 > aFormats;
1852 
1853  if( !bSingle)
1854  bOk = StartPaste();
1855 
1856  while( bOk )
1857  {
1858  OUString aLine;
1859  OUString aText;
1860  OString aByteLine;
1861  SCCOL nCol = nStartCol;
1862  SCROW nRow = nStartRow;
1863  SCCOL nRefCol = nCol;
1864  SCROW nRefRow = nRow;
1865  rStrm.Seek( nOldPos );
1866  for( ;; )
1867  {
1869  rStrm.ReadLine( aByteLine );
1870  aLine = OStringToOUString(aByteLine, rStrm.GetStreamCharSet());
1871  if( rStrm.eof() )
1872  break;
1873  bool bInvalidCol = false;
1874  bool bInvalidRow = false;
1875  const sal_Unicode* p = aLine.getStr();
1876  sal_Unicode cTag = *p++;
1877  if( cTag == 'C' ) // Content
1878  {
1879  if( *p++ != ';' )
1880  return false;
1881 
1882  bool bInvalidRefCol = false;
1883  bool bInvalidRefRow = false;
1884  while( *p )
1885  {
1886  sal_Unicode ch = *p++;
1887  ch = ScGlobal::ToUpperAlpha( ch );
1888  switch( ch )
1889  {
1890  case 'X':
1891  {
1892  bInvalidCol = false;
1893  bool bFail = o3tl::checked_add<SCCOL>(OUString(p).toInt32(), nStartCol - 1, nCol);
1894  if (bFail || nCol < 0 || rDoc.MaxCol() < nCol)
1895  {
1896  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;X invalid nCol=" << nCol);
1897  nCol = std::clamp<SCCOL>(nCol, 0, rDoc.MaxCol());
1898  bInvalidCol = bOverflowCol = true;
1899  }
1900  break;
1901  }
1902  case 'Y':
1903  {
1904  bInvalidRow = false;
1905  bool bFail = o3tl::checked_add(OUString(p).toInt32(), nStartRow - 1, nRow);
1906  if (bFail || nRow < 0 || nMaxImportRow < nRow)
1907  {
1908  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;Y invalid nRow=" << nRow);
1909  nRow = std::clamp<SCROW>(nRow, 0, nMaxImportRow);
1910  bInvalidRow = bOverflowRow = true;
1911  }
1912  break;
1913  }
1914  case 'C':
1915  {
1916  bInvalidRefCol = false;
1917  bool bFail = o3tl::checked_add<SCCOL>(OUString(p).toInt32(), nStartCol - 1, nRefCol);
1918  if (bFail || nRefCol < 0 || rDoc.MaxCol() < nRefCol)
1919  {
1920  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;C invalid nRefCol=" << nRefCol);
1921  nRefCol = std::clamp<SCCOL>(nRefCol, 0, rDoc.MaxCol());
1922  bInvalidRefCol = bOverflowCol = true;
1923  }
1924  break;
1925  }
1926  case 'R':
1927  {
1928  bInvalidRefRow = false;
1929  bool bFail = o3tl::checked_add(OUString(p).toInt32(), nStartRow - 1, nRefRow);
1930  if (bFail || nRefRow < 0 || nMaxImportRow < nRefRow)
1931  {
1932  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;R invalid nRefRow=" << nRefRow);
1933  nRefRow = std::clamp<SCROW>(nRefRow, 0, nMaxImportRow);
1934  bInvalidRefRow = bOverflowRow = true;
1935  }
1936  break;
1937  }
1938  case 'K':
1939  {
1940  if( !bSingle &&
1941  ( nCol < nStartCol || nCol > nEndCol
1942  || nRow < nStartRow || nRow > nEndRow
1943  || nCol > rDoc.MaxCol() || nRow > nMaxImportRow
1944  || bInvalidCol || bInvalidRow ) )
1945  break;
1946  if( !bData )
1947  {
1948  if( nRow > nEndRow )
1949  nEndRow = nRow;
1950  if( nCol > nEndCol )
1951  nEndCol = nCol;
1952  break;
1953  }
1954  bool bText;
1955  if( *p == '"' )
1956  {
1957  bText = true;
1958  aText.clear();
1959  p = lcl_ScanSylkString( p, aText, eVersion);
1960  }
1961  else
1962  bText = false;
1963  const sal_Unicode* q = p;
1964  while( *q && *q != ';' )
1965  q++;
1966  if ( (*q != ';' || *(q+1) != 'I') && !bInvalidCol && !bInvalidRow )
1967  { // don't ignore value
1968  if( bText )
1969  {
1970  rDoc.EnsureTable(aRange.aStart.Tab());
1971  rDoc.SetTextCell(
1972  ScAddress(nCol, nRow, aRange.aStart.Tab()), aText);
1973  }
1974  else
1975  {
1976  double fVal = rtl_math_uStringToDouble( p,
1977  aLine.getStr() + aLine.getLength(),
1978  cDecSep, cGrpSep, nullptr, nullptr );
1979  rDoc.SetValue( nCol, nRow, aRange.aStart.Tab(), fVal );
1980  }
1981  }
1982  }
1983  break;
1984  case 'E':
1985  case 'M':
1986  {
1987  if ( ch == 'M' )
1988  {
1989  if ( nRefCol < nCol )
1990  nRefCol = nCol;
1991  if ( nRefRow < nRow )
1992  nRefRow = nRow;
1993  if ( !bData )
1994  {
1995  if( nRefRow > nEndRow )
1996  nEndRow = nRefRow;
1997  if( nRefCol > nEndCol )
1998  nEndCol = nRefCol;
1999  }
2000  }
2001  if( !bMyDoc || !bData )
2002  break;
2003  aText = "=";
2004  p = lcl_ScanSylkFormula( p, aText, eVersion);
2005 
2006  if (bInvalidCol || bInvalidRow || (ch == 'M' && (bInvalidRefCol || bInvalidRefRow)))
2007  break;
2008 
2009  ScAddress aPos( nCol, nRow, aRange.aStart.Tab() );
2010  /* FIXME: do we want GRAM_ODFF_A1 instead? At the
2011  * end it probably should be GRAM_ODFF_R1C1, since
2012  * R1C1 is what Excel writes in SYLK, or even
2013  * better GRAM_ENGLISH_XL_R1C1. */
2015  ScCompiler aComp(rDoc, aPos, eGrammar);
2016  std::unique_ptr<ScTokenArray> xCode(aComp.CompileString(aText)); // ctor/InsertMatrixFormula did copy TokenArray
2017  rDoc.CheckLinkFormulaNeedingCheck(*xCode);
2018  if ( ch == 'M' )
2019  {
2020  ScMarkData aMark(rDoc.GetSheetLimits());
2021  aMark.SelectTable( aPos.Tab(), true );
2022  rDoc.InsertMatrixFormula( nCol, nRow, nRefCol,
2023  nRefRow, aMark, EMPTY_OUSTRING, xCode.get() );
2024  }
2025  else
2026  {
2027  ScFormulaCell* pFCell = new ScFormulaCell(
2028  rDoc, aPos, *xCode, eGrammar, ScMatrixMode::NONE);
2029  rDoc.SetFormulaCell(aPos, pFCell);
2030  }
2031  }
2032  break;
2033  }
2034  while( *p && *p != ';' )
2035  p++;
2036  if( *p )
2037  p++;
2038  }
2039  }
2040  else if( cTag == 'F' ) // Format
2041  {
2042  if( *p++ != ';' )
2043  return false;
2044  sal_Int32 nFormat = -1;
2045  while( *p )
2046  {
2047  sal_Unicode ch = *p++;
2048  ch = ScGlobal::ToUpperAlpha( ch );
2049  switch( ch )
2050  {
2051  case 'X':
2052  {
2053  bInvalidCol = false;
2054  bool bFail = o3tl::checked_add<SCCOL>(OUString(p).toInt32(), nStartCol - 1, nCol);
2055  if (bFail || nCol < 0 || rDoc.MaxCol() < nCol)
2056  {
2057  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;X invalid nCol=" << nCol);
2058  nCol = std::clamp<SCCOL>(nCol, 0, rDoc.MaxCol());
2059  bInvalidCol = bOverflowCol = true;
2060  }
2061  break;
2062  }
2063  case 'Y':
2064  {
2065  bInvalidRow = false;
2066  bool bFail = o3tl::checked_add(OUString(p).toInt32(), nStartRow - 1, nRow);
2067  if (bFail || nRow < 0 || nMaxImportRow < nRow)
2068  {
2069  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;Y invalid nRow=" << nRow);
2070  nRow = std::clamp<SCROW>(nRow, 0, nMaxImportRow);
2071  bInvalidRow = bOverflowRow = true;
2072  }
2073  break;
2074  }
2075  case 'P' :
2076  if ( bData )
2077  {
2078  // F;P<n> sets format code of P;P<code> at
2079  // current position, or at ;X;Y if specified.
2080  // Note that ;X;Y may appear after ;P
2081  const sal_Unicode* p0 = p;
2082  while( *p && *p != ';' )
2083  p++;
2084  OUString aNumber(p0, p - p0);
2085  nFormat = aNumber.toInt32();
2086  }
2087  break;
2088  }
2089  while( *p && *p != ';' )
2090  p++;
2091  if( *p )
2092  p++;
2093  }
2094  if ( !bData )
2095  {
2096  if( nRow > nEndRow )
2097  nEndRow = nRow;
2098  if( nCol > nEndCol )
2099  nEndCol = nCol;
2100  }
2101  if ( 0 <= nFormat && nFormat < static_cast<sal_Int32>(aFormats.size()) && !bInvalidCol && !bInvalidRow )
2102  {
2103  sal_uInt32 nKey = aFormats[nFormat];
2104  rDoc.ApplyAttr( nCol, nRow, aRange.aStart.Tab(),
2105  SfxUInt32Item( ATTR_VALUE_FORMAT, nKey ) );
2106  }
2107  }
2108  else if( cTag == 'P' )
2109  {
2110  if ( bData && *p == ';' && *(p+1) == 'P' )
2111  {
2112  OUString aCode( p+2 );
2113 
2114  sal_uInt32 nKey;
2115  sal_Int32 nCheckPos;
2116 
2117  if (aCode.getLength() > 2048 && utl::ConfigManager::IsFuzzing())
2118  {
2119  // consider an excessive length as a failure when fuzzing
2120  nCheckPos = 1;
2121  }
2122  else
2123  {
2124  // unescape doubled semicolons
2125  aCode = aCode.replaceAll(";;", ";");
2126  // get rid of Xcl escape characters
2127  aCode = aCode.replaceAll("\x1b", "");
2129  rDoc.GetFormatTable()->PutandConvertEntry( aCode, nCheckPos, nType, nKey,
2131  }
2132 
2133  if ( nCheckPos )
2134  nKey = 0;
2135 
2136  aFormats.push_back( nKey );
2137  }
2138  }
2139  else if( cTag == 'I' && *p == 'D' )
2140  {
2141  aLine = aLine.copy(4);
2142  if (aLine == "CALCOOO32")
2143  eVersion = SylkVersion::OOO32;
2144  else if (aLine == "SCALC3")
2145  eVersion = SylkVersion::SCALC3;
2146  bMyDoc = (eVersion <= SylkVersion::OWN);
2147  }
2148  else if( cTag == 'E' ) // End
2149  break;
2150  }
2151  if( !bData )
2152  {
2153  aRange.aEnd.SetCol( nEndCol );
2154  aRange.aEnd.SetRow( nEndRow );
2155  bOk = StartPaste();
2156  bData = true;
2157  }
2158  else
2159  break;
2160  }
2161 
2162  EndPaste();
2163  return bOk;
2164 }
2165 
2167 {
2168  SCCOL nCol;
2169  SCROW nRow;
2170  SCCOL nStartCol = aRange.aStart.Col();
2171  SCROW nStartRow = aRange.aStart.Row();
2172  SCCOL nEndCol = aRange.aEnd.Col();
2173  SCROW nEndRow = aRange.aEnd.Row();
2174  OUString aCellStr;
2175  OUString aValStr;
2176  lcl_WriteSimpleString( rStrm, "ID;PCALCOOO32" );
2177  WriteUnicodeOrByteEndl( rStrm );
2178 
2179  for (nRow = nStartRow; nRow <= nEndRow; nRow++)
2180  {
2181  for (nCol = nStartCol; nCol <= nEndCol; nCol++)
2182  {
2183  OUString aBufStr;
2184  double nVal;
2185  bool bForm = false;
2186  SCROW r = nRow - nStartRow + 1;
2187  SCCOL c = nCol - nStartCol + 1;
2188  ScRefCellValue aCell(rDoc, ScAddress(nCol, nRow, aRange.aStart.Tab()));
2189  CellType eType = aCell.meType;
2190  switch( eType )
2191  {
2192  case CELLTYPE_FORMULA:
2193  bForm = bFormulas;
2194  if( rDoc.HasValueData( nCol, nRow, aRange.aStart.Tab()) )
2195  goto hasvalue;
2196  else
2197  goto hasstring;
2198 
2199  case CELLTYPE_VALUE:
2200  hasvalue:
2201  rDoc.GetValue( nCol, nRow, aRange.aStart.Tab(), nVal );
2202 
2203  aValStr = ::rtl::math::doubleToUString( nVal,
2204  rtl_math_StringFormat_Automatic,
2205  rtl_math_DecimalPlaces_Max, '.', true );
2206 
2207  aBufStr = "C;X"
2208  + OUString::number( c )
2209  + ";Y"
2210  + OUString::number( r )
2211  + ";K"
2212  + aValStr;
2213  lcl_WriteSimpleString( rStrm, aBufStr );
2214  goto checkformula;
2215 
2216  case CELLTYPE_STRING:
2217  case CELLTYPE_EDIT:
2218  hasstring:
2219  aCellStr = rDoc.GetString(nCol, nRow, aRange.aStart.Tab());
2220  aCellStr = aCellStr.replaceAll("\n", SYLK_LF);
2221 
2222  aBufStr = "C;X"
2223  + OUString::number( c )
2224  + ";Y"
2225  + OUString::number( r )
2226  + ";K";
2227  lcl_WriteSimpleString( rStrm, aBufStr );
2228  lcl_WriteString( rStrm, aCellStr, '"', ';' );
2229 
2230  checkformula:
2231  if( bForm )
2232  {
2233  const ScFormulaCell* pFCell = aCell.mpFormula;
2234  switch ( pFCell->GetMatrixFlag() )
2235  {
2237  aCellStr.clear();
2238  break;
2239  default:
2240  OUString aOUCellStr;
2242  aCellStr = aOUCellStr;
2243  /* FIXME: do we want GRAM_ODFF_A1 instead? At
2244  * the end it probably should be
2245  * GRAM_ODFF_R1C1, since R1C1 is what Excel
2246  * writes in SYLK, or even better
2247  * GRAM_ENGLISH_XL_R1C1. */
2248  }
2249  if ( pFCell->GetMatrixFlag() != ScMatrixMode::NONE &&
2250  aCellStr.startsWith("{") &&
2251  aCellStr.endsWith("}") )
2252  { // cut off matrix {} characters
2253  aCellStr = aCellStr.copy(1, aCellStr.getLength()-2);
2254  }
2255  if ( aCellStr[0] == '=' )
2256  aCellStr = aCellStr.copy(1);
2257  OUString aPrefix;
2258  switch ( pFCell->GetMatrixFlag() )
2259  {
2260  case ScMatrixMode::Formula :
2261  { // diff expression with 'M' M$-extension
2262  SCCOL nC;
2263  SCROW nR;
2264  pFCell->GetMatColsRows( nC, nR );
2265  nC += c - 1;
2266  nR += r - 1;
2267  aPrefix = ";R"
2268  + OUString::number( nR )
2269  + ";C"
2270  + OUString::number( nC )
2271  + ";M";
2272  }
2273  break;
2275  { // diff expression with 'I' M$-extension
2276  ScAddress aPos;
2277  (void)pFCell->GetMatrixOrigin( rDoc, aPos );
2278  aPrefix = ";I;R"
2279  + OUString::number( aPos.Row() - nStartRow + 1 )
2280  + ";C"
2281  + OUString::number( aPos.Col() - nStartCol + 1 );
2282  }
2283  break;
2284  default:
2285  // formula Expression
2286  aPrefix = ";E";
2287  }
2288  lcl_WriteSimpleString( rStrm, aPrefix );
2289  if ( !aCellStr.isEmpty() )
2290  lcl_WriteString( rStrm, aCellStr, 0, ';' );
2291  }
2292  WriteUnicodeOrByteEndl( rStrm );
2293  break;
2294 
2295  default:
2296  {
2297  // added to avoid warnings
2298  }
2299  }
2300  }
2301  }
2302  lcl_WriteSimpleString( rStrm, OUString( 'E' ) );
2303  WriteUnicodeOrByteEndl( rStrm );
2304  return rStrm.GetError() == ERRCODE_NONE;
2305 }
2306 
2307 bool ScImportExport::Doc2HTML( SvStream& rStrm, const OUString& rBaseURL )
2308 {
2309  // rtl_TextEncoding is ignored in ScExportHTML, read from Load/Save HTML options
2310  ScFormatFilter::Get().ScExportHTML( rStrm, rBaseURL, &rDoc, aRange, RTL_TEXTENCODING_DONTKNOW, bAll,
2312  return rStrm.GetError() == ERRCODE_NONE;
2313 }
2314 
2316 {
2317  // rtl_TextEncoding is ignored in ScExportRTF
2318  ScFormatFilter::Get().ScExportRTF( rStrm, &rDoc, aRange, RTL_TEXTENCODING_DONTKNOW );
2319  return rStrm.GetError() == ERRCODE_NONE;
2320 }
2321 
2323 {
2324  // for DIF in the clipboard, IBM_850 is always used
2325  ScFormatFilter::Get().ScExportDif( rStrm, &rDoc, aRange, RTL_TEXTENCODING_IBM_850 );
2326  return true;
2327 }
2328 
2330 {
2331  SCTAB nTab = aRange.aStart.Tab();
2332  ScDocumentUniquePtr pImportDoc( new ScDocument( SCDOCMODE_UNDO ) );
2333  pImportDoc->InitUndo( rDoc, nTab, nTab );
2334 
2335  // for DIF in the clipboard, IBM_850 is always used
2336  ScFormatFilter::Get().ScImportDif( rStrm, pImportDoc.get(), aRange.aStart, RTL_TEXTENCODING_IBM_850 );
2337 
2338  SCCOL nEndCol;
2339  SCROW nEndRow;
2340  pImportDoc->GetCellArea( nTab, nEndCol, nEndRow );
2341  // if there are no cells in the imported content, nEndCol/nEndRow may be before the start
2342  if ( nEndCol < aRange.aStart.Col() )
2343  nEndCol = aRange.aStart.Col();
2344  if ( nEndRow < aRange.aStart.Row() )
2345  nEndRow = aRange.aStart.Row();
2346  aRange.aEnd = ScAddress( nEndCol, nEndRow, nTab );
2347 
2348  bool bOk = StartPaste();
2349  if (bOk)
2350  {
2352  rDoc.DeleteAreaTab( aRange, nFlags );
2353  pImportDoc->CopyToDocument(aRange, nFlags, false, rDoc);
2354  EndPaste();
2355  }
2356 
2357  return bOk;
2358 }
2359 
2360 bool ScImportExport::RTF2Doc( SvStream& rStrm, const OUString& rBaseURL )
2361 {
2362  std::unique_ptr<ScEEAbsImport> pImp = ScFormatFilter::Get().CreateRTFImport( &rDoc, aRange );
2363  if (!pImp)
2364  return false;
2365  pImp->Read( rStrm, rBaseURL );
2366  aRange = pImp->GetRange();
2367 
2368  bool bOk = StartPaste();
2369  if (bOk)
2370  {
2372  rDoc.DeleteAreaTab( aRange, nFlags );
2373  pImp->WriteToDocument();
2374  EndPaste();
2375  }
2376  return bOk;
2377 }
2378 
2379 bool ScImportExport::HTML2Doc( SvStream& rStrm, const OUString& rBaseURL )
2380 {
2381  std::unique_ptr<ScEEAbsImport> pImp = ScFormatFilter::Get().CreateHTMLImport( &rDoc, rBaseURL, aRange);
2382  if (!pImp)
2383  return false;
2384  pImp->Read( rStrm, rBaseURL );
2385  aRange = pImp->GetRange();
2386 
2387  bool bOk = StartPaste();
2388  if (bOk)
2389  {
2390  // ScHTMLImport may call ScDocument::InitDrawLayer, resulting in
2391  // a Draw Layer but no Draw View -> create Draw Layer and View here
2392  if (pDocSh)
2393  pDocSh->MakeDrawLayer();
2394 
2396  rDoc.DeleteAreaTab( aRange, nFlags );
2397 
2398  if (pExtOptions)
2399  {
2400  // Pick up import options if available.
2401  LanguageType eLang = pExtOptions->GetLanguage();
2403  bool bSpecialNumber = pExtOptions->IsDetectSpecialNumber();
2404  pImp->WriteToDocument(false, 1.0, &aNumFormatter, bSpecialNumber);
2405  }
2406  else
2407  // Regular import, with no options.
2408  pImp->WriteToDocument();
2409 
2410  EndPaste();
2411  }
2412  return bOk;
2413 }
2414 
2415 #ifndef DISABLE_DYNLOADING
2416 
2417 extern "C" { static void thisModule() {} }
2418 
2419 #else
2420 
2421 extern "C" {
2423 }
2424 
2425 #endif
2426 
2427 typedef ScFormatFilterPlugin * (*FilterFn)();
2429 {
2430  static ScFormatFilterPlugin *plugin = [&]()
2431  {
2432 #ifndef DISABLE_DYNLOADING
2433  OUString sFilterLib(SVLIBRARY("scfilt"));
2434  static ::osl::Module aModule;
2435  bool bLoaded = aModule.is();
2436  if (!bLoaded)
2437  bLoaded = aModule.loadRelative(&thisModule, sFilterLib);
2438  if (!bLoaded)
2439  bLoaded = aModule.load(sFilterLib);
2440  if (bLoaded)
2441  {
2442  oslGenericFunction fn = aModule.getFunctionSymbol( "ScFilterCreate" );
2443  if (fn != nullptr)
2444  return reinterpret_cast<FilterFn>(fn)();
2445  }
2446  assert(false);
2447  return static_cast<ScFormatFilterPlugin*>(nullptr);
2448 #else
2449  return ScFilterCreate();
2450 #endif
2451  }();
2452 
2453  return *plugin;
2454 }
2455 
2456 // Precondition: pStr is guaranteed to be non-NULL and points to a 0-terminated
2457 // array.
2458 static const sal_Unicode* lcl_UnicodeStrChr( const sal_Unicode* pStr,
2459  sal_Unicode c )
2460 {
2461  while (*pStr)
2462  {
2463  if (*pStr == c)
2464  return pStr;
2465  ++pStr;
2466  }
2467  return nullptr;
2468 }
2469 
2471  : SvMemoryStream( const_cast<sal_Unicode *>(rStr.getStr()),
2472  rStr.getLength() * sizeof(sal_Unicode), StreamMode::READ)
2473 {
2474  SetStreamCharSet( RTL_TEXTENCODING_UNICODE );
2475 #ifdef OSL_BIGENDIAN
2476  SetEndian(SvStreamEndian::BIG);
2477 #else
2478  SetEndian(SvStreamEndian::LITTLE);
2479 #endif
2480 }
2481 
2482 OUString ReadCsvLine( SvStream &rStream, bool bEmbeddedLineBreak,
2483  OUString& rFieldSeparators, sal_Unicode cFieldQuote, sal_Unicode& rcDetectSep )
2484 {
2485  enum RetryState
2486  {
2487  FORBID,
2488  ALLOW,
2489  RETRY,
2490  RETRIED
2491  } eRetryState = (bEmbeddedLineBreak && rcDetectSep == 0 ? RetryState::ALLOW : RetryState::FORBID);
2492 
2493  sal_uInt64 nStreamPos = (eRetryState == RetryState::ALLOW ? rStream.Tell() : 0);
2494 
2495 Label_RetryWithNewSep:
2496 
2497  if (eRetryState == RetryState::RETRY)
2498  {
2499  eRetryState = RetryState::RETRIED;
2500  rStream.Seek( nStreamPos);
2501  }
2502 
2503  OUString aStr;
2505 
2506  if (bEmbeddedLineBreak)
2507  {
2508  const sal_Unicode* pSeps = rFieldSeparators.getStr();
2509 
2510  QuoteType eQuoteState = FIELDEND_QUOTE;
2511  bool bFieldStart = true;
2512 
2513  sal_Int32 nLastOffset = 0;
2514  sal_Int32 nQuotes = 0;
2515  while (!rStream.eof() && aStr.getLength() < nArbitraryLineLengthLimit)
2516  {
2517  const sal_Unicode * p = aStr.getStr() + nLastOffset;
2518  while (*p)
2519  {
2520  if (nQuotes)
2521  {
2522  if (*p == cFieldQuote)
2523  {
2524  if (bFieldStart)
2525  {
2526  ++nQuotes;
2527  bFieldStart = false;
2528  eQuoteState = FIELDSTART_QUOTE;
2529  }
2530  // Do not detect a FIELDSTART_QUOTE if not in
2531  // bFieldStart mode, in which case for unquoted content
2532  // we are in FIELDEND_QUOTE state.
2533  else if (eQuoteState != FIELDEND_QUOTE)
2534  {
2535  eQuoteState = lcl_isEscapedOrFieldEndQuote( nQuotes, p, pSeps, cFieldQuote, rcDetectSep);
2536 
2537  if (eRetryState == RetryState::ALLOW && rcDetectSep == ' ')
2538  {
2539  eRetryState = RetryState::RETRY;
2540  rFieldSeparators += " ";
2541  goto Label_RetryWithNewSep;
2542  }
2543 
2544  // DONTKNOW_QUOTE is an embedded unescaped quote we
2545  // don't count for pairing.
2546  if (eQuoteState != DONTKNOW_QUOTE)
2547  ++nQuotes;
2548  }
2549  }
2550  else if (eQuoteState == FIELDEND_QUOTE)
2551  {
2552  if (bFieldStart)
2553  // If blank is a separator it starts a field, if it
2554  // is not and thus maybe leading before quote we
2555  // are still at start of field regarding quotes.
2556  bFieldStart = (*p == ' ' || lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2557  else
2558  bFieldStart = (lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2559  }
2560  }
2561  else
2562  {
2563  if (*p == cFieldQuote && bFieldStart)
2564  {
2565  nQuotes = 1;
2566  eQuoteState = FIELDSTART_QUOTE;
2567  bFieldStart = false;
2568  }
2569  else if (eQuoteState == FIELDEND_QUOTE)
2570  {
2571  // This also skips leading blanks at beginning of line
2572  // if followed by a quote. It's debatable whether we
2573  // actually want that or not, but congruent with what
2574  // ScanNextFieldFromString() does.
2575  if (bFieldStart)
2576  bFieldStart = (*p == ' ' || lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2577  else
2578  bFieldStart = (lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2579  }
2580  }
2581  // A quote character inside a field content does not start
2582  // a quote.
2583  ++p;
2584  }
2585 
2586  if (nQuotes % 2 == 0)
2587  // We still have a (theoretical?) problem here if due to
2588  // nArbitraryLineLengthLimit we split a string right between a
2589  // doubled quote pair.
2590  break;
2591  else
2592  {
2593  nLastOffset = aStr.getLength();
2594  OUString aNext;
2596  aStr += "\n" + aNext;
2597  }
2598  }
2599  }
2600  return aStr;
2601 }
2602 
2603 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static const OUString & GetClipDocName()
Definition: global.cxx:478
static OUString GetAppName()
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2116
const SCROW SCROWS32K
Definition: address.hxx:85
static const sal_Unicode * lcl_ScanString(const sal_Unicode *p, OUString &rString, const sal_Unicode *pSeps, sal_Unicode cStr, DoubledQuoteMode eMode, bool &rbOverflowCell)
Definition: impex.cxx:691
sal_Int32 nIndex
ScAddress aStart
Definition: address.hxx:499
TOOLS_DLLPUBLIC OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
static void lcl_WriteSimpleString(SvStream &rStrm, const OUString &rString)
Definition: impex.cxx:889
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:42
void SetExtOptions(const ScAsciiOptions &rOpt)
Definition: impex.cxx:204
const sal_uInt8 SC_COL_STANDARD
Definition: csvcontrol.hxx:54
Store parameters used in the ScDocument::SetString() method.
Definition: stringutil.hxx:34
sal_Unicode GetTextSep() const
Definition: asciiopt.hxx:62
const sal_uInt8 SC_COL_TEXT
Definition: csvcontrol.hxx:55
#define EMPTY_OUSTRING
Definition: global.hxx:213
static void WriteUnicodeOrByteEndl(SvStream &rStrm)
Definition: impex.cxx:524
bool isDigit(const OUString &rStr, sal_Int32 nPos) const
SvStream & WriteUInt16(sal_uInt16 nUInt16)
void setValue(sal_Int16 nFieldIndex, sal_Int16 nValue)
Sheet / outlining (grouping) information.
SCROW Row() const
Definition: address.hxx:261
bool isNumeric(const OUString &rStr) const
OUString GetTitle(sal_uInt16 nMaxLen=0) const
#define LANGUAGE_ENGLISH_US
bool AdjustRowHeight(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
merge with docfunc
Definition: docsh5.cxx:404
bool ExportString(OUString &, SotClipboardFormatId)
Definition: impex.cxx:327
sal_Int16 getNumberOfMonthsInYear() const
std::unique_ptr< ContentProperties > pData
static weld::Window * GetActiveDialogParent()
Definition: docsh.cxx:3045
bool ReadUniOrByteStringLine(OUString &rStr, rtl_TextEncoding eSrcCharSet, sal_Int32 nMaxCodepointsToRead=0xFFFE)
bool Doc2Text(SvStream &)
Definition: impex.cxx:1719
signed char sal_Int8
bool Doc2Dif(SvStream &)
Definition: impex.cxx:2322
static bool lcl_appendLineData(OUString &rField, const sal_Unicode *p1, const sal_Unicode *p2)
Append characters of [p1,p2) to rField.
Definition: impex.cxx:666
bool mbCheckLinkFormula
When true and the string results in a compiled formula, check the formula tokens for presence of func...
Definition: stringutil.hxx:100
LineEnd GetLineDelimiter() const
static bool IsFormatSupported(SotClipboardFormatId nFormat)
Definition: impex.cxx:222
void GetFormula(OUString &rFormula, const formula::FormulaGrammar::Grammar=formula::FormulaGrammar::GRAM_DEFAULT, const ScInterpreterContext *pContext=nullptr) const
sal_uIntPtr sal_uLong
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:168
sal_Unicode cSep
Definition: impex.hxx:57
sal_Int32 toInt32(OUString const &rStr)
SC_DLLPUBLIC bool InitColumnBlockPosition(sc::ColumnBlockPosition &rBlockPos, SCTAB nTab, SCCOL nCol)
Definition: document.cxx:2627
Warning box for "Replace cell contents?".
Definition: warnbox.hxx:26
sal_Int64 n
std::unique_ptr< ScTokenArray > CompileString(const OUString &rFormula)
Tokenize formula expression string into an array of tokens.
Definition: compiler.cxx:4546
static const sal_Unicode * lcl_ScanSylkFormula(const sal_Unicode *p, OUString &rString, SylkVersion eVersion)
Definition: impex.cxx:802
void SetDocumentModified()
Definition: docsh.cxx:2915
SvStream * IsValid(SvStream &)
sal_uInt64 Seek(sal_uInt64 nPos)
static const sal_Unicode * lcl_ScanSylkString(const sal_Unicode *p, OUString &rString, SylkVersion eVersion)
Definition: impex.cxx:760
static SC_DLLPUBLIC ScFormatFilterPlugin & Get()
Definition: impex.cxx:2428
SC_DLLPUBLIC void GetNumberFormat(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt32 &rFormat) const
Definition: document.cxx:3672
bool bIncludeFiltered
Definition: impex.hxx:60
ScAddress aEnd
Definition: address.hxx:500
bool bUndo
Definition: impex.hxx:63
bool Doc2HTML(SvStream &, const OUString &)
Definition: impex.cxx:2307
SC_DLLPUBLIC void SetValue(SCCOL nCol, SCROW nRow, SCTAB nTab, const double &rVal)
Definition: document.cxx:3489
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:103
static bool lcl_PutString(ScDocumentImport &rDocImport, bool bUseDocImport, SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString &rStr, sal_uInt8 nColFormat, SvNumberFormatter *pFormatter, bool bDetectNumFormat, bool bSkipEmptyCells, const ::utl::TransliterationWrapper &rTransliteration, CalendarWrapper &rCalendar, const ::utl::TransliterationWrapper *pSecondTransliteration, CalendarWrapper *pSecondCalendar)
Definition: impex.cxx:993
const SCCOL MAXCOLCOUNT
Definition: address.hxx:63
SC_DLLPUBLIC void ApplyAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem &rAttr)
Definition: document.cxx:4788
Accessor class to ScDocument.
bool bSingle
Definition: impex.hxx:62
LINEEND_CR
std::unique_ptr< ScAsciiOptions > pExtOptions
Definition: impex.hxx:74
bool ImportStream(SvStream &, const OUString &rBaseURL, SotClipboardFormatId)
Definition: impex.cxx:382
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:494
bool ExportData(const OUString &rMimeType, css::uno::Any &rValue)
Definition: impex.cxx:286
static QuoteType lcl_isFieldEndQuote(const sal_Unicode *p, const sal_Unicode *pSeps, sal_Unicode &rcDetectSep)
Determine if *p is a quote that ends a quoted field.
Definition: impex.cxx:604
void setEditCell(const ScAddress &rPos, std::unique_ptr< EditTextObject > pEditText)
SC_DLLPUBLIC void SetTextCell(const ScAddress &rPos, const OUString &rStr)
Call this if you are not sure whether to put this as an edit text or a simple text.
Definition: document.cxx:3462
virtual sal_uInt64 TellEnd() override
SC_DLLPUBLIC ScDocumentPool * GetPool()
Definition: document.cxx:6087
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2901
static QuoteType lcl_isEscapedOrFieldEndQuote(sal_Int32 nQuotes, const sal_Unicode *p, const sal_Unicode *pSeps, sal_Unicode cStr, sal_Unicode &rcDetectSep)
Determine if *p is a quote that is escaped by being doubled or ends a quoted field.
Definition: impex.cxx:644
static void lcl_UnescapeSylk(OUString &rString, SylkVersion eVersion)
Definition: impex.cxx:747
static bool SC_DLLPUBLIC isMultiline(const OUString &rStr)
Definition: stringutil.cxx:423
sal_uInt16 sal_Unicode
bool Doc2RTF(SvStream &)
Definition: impex.cxx:2315
void EndPaste(bool bAutoRowHeight=true)
Definition: impex.cxx:258
virtual void ScExportDif(SvStream &, ScDocument *, const ScAddress &rOutPos, const rtl_TextEncoding eDest)=0
SC_DLLPUBLIC void CheckLinkFormulaNeedingCheck(const ScTokenArray &rCode)
Check token array and set link check if ocDde/ocWebservice is contained.
Definition: documen8.cxx:1154
RET_YES
ErrCode GetError() const
static void WriteUnicodeOrByteString(SvStream &rStrm, const OUString &rString, bool bZero=false)
Definition: impex.cxx:495
ScClipParam & GetClipParam()
Definition: document.cxx:2565
bool eof() const
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > pUndoDoc
Definition: impex.hxx:50
void StartReadingUnicodeText(rtl_TextEncoding eReadBomCharSet)
static bool isCJKIVSCharacter(sal_uInt32 nCode)
NewlineConversion meNewlineConversion
Definition: impex.hxx:41
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:872
sal_uInt16 ExpandTwoDigitYear(sal_uInt16 nYear) const
#define SAL_MAX_UINT16
static sal_Unicode GetWeightedFieldSep(const OUString &rFieldSeps, bool bDecodeNumbers)
From the import field separators obtain the one most likely to be used for export, if multiple separators weighted comma, tab, semicolon, space and other.
Definition: asciiopt.cxx:260
static OUString lcl_GetFixed(const OUString &rLine, sal_Int32 nStart, sal_Int32 nNext, bool &rbIsQuoted, bool &rbOverflowCell)
Definition: impex.cxx:1321
ScImportStringStream(const OUString &rStr)
Definition: impex.cxx:2470
sal_uInt32 GetStandardIndex(LanguageType eLnge=LANGUAGE_DONTKNOW)
static void thisModule()
Definition: impex.cxx:2417
OUString aStreamPath
Definition: impex.hxx:52
static bool IsFuzzing()
bool ReadLine(OString &rStr, sal_Int32 nMaxBytesToRead=0xFFFE)
SC_DLLPUBLIC OUString GetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScInterpreterContext *pContext=nullptr) const
Definition: document.cxx:3517
LineEnd GetSystemLineEnd()
void CopyToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, InsertDeleteFlags nFlags, bool bMarked, ScDocument &rDestDoc, const ScMarkData *pMarks=nullptr, bool bColRowFlags=true)
Definition: document.cxx:2050
sal_uInt32 nSizeLimit
Definition: impex.hxx:55
void UpdateInputHandler(bool bForce=false, bool bStopEditing=true)
Definition: tabvwsha.cxx:653
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:110
SCTAB Tab() const
Definition: address.hxx:270
void SetRow(SCROW nRowP)
Definition: address.hxx:274
static void lcl_WriteString(SvStream &rStrm, OUString &rString, sal_Unicode cQuote, sal_Unicode cEsc)
Definition: impex.cxx:876
constexpr sal_Int32 nArbitraryCellLengthLimit
Definition: impex.cxx:75
bool Text2Doc(SvStream &)
Definition: impex.cxx:894
OUString aNonConvertibleChars
Definition: impex.hxx:53
SotClipboardFormatId
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
virtual void ScExportHTML(SvStream &, const OUString &rBaseURL, ScDocument *, const ScRange &rRange, const rtl_TextEncoding eDest, bool bAll, const OUString &rStreamPath, OUString &rNonConvertibleChars, const OUString &rFilterOptions)=0
static bool isIVSSelector(sal_uInt32 nCode)
sal_uInt16 nCode
void SetCol(SCCOL nColP)
Definition: address.hxx:278
ScDocShell * pDocSh
Definition: impex.hxx:48
ScDrawLayer * MakeDrawLayer()
Definition: docsh2.cxx:169
bool HTML2Doc(SvStream &, const OUString &rBaseURL)
Definition: impex.cxx:2379
OUString maFilterOptions
Definition: impex.hxx:54
bool IsClipboard() const
Definition: document.hxx:1534
SC_DLLPUBLIC double GetValue(const ScAddress &rPos) const
Definition: document.cxx:3659
DocumentType eType
SC_DLLPUBLIC void InsertMatrixFormula(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData &rMark, const OUString &rFormula, const ScTokenArray *p=nullptr, const formula::FormulaGrammar::Grammar=formula::FormulaGrammar::GRAM_DEFAULT)
Definition: documen4.cxx:258
const char * GetMessageId() const
Definition: editable.cxx:152
virtual std::unique_ptr< ScEEAbsImport > CreateHTMLImport(ScDocument *pDocP, const OUString &rBaseURL, const ScRange &rRange)=0
void SetMarkArea(const ScRange &rRange)
Definition: markdata.cxx:97
SC_DLLPUBLIC bool SetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString &rString, const ScSetStringParam *pParam=nullptr)
Definition: document.cxx:3394
bool bFormulas
Definition: impex.hxx:59
void SetTab(SCTAB nTabP)
Definition: address.hxx:282
#define SFX_TITLE_FULLNAME
SC_DLLPUBLIC ScRangeData * findByUpperName(const OUString &rName)
Definition: rangenam.cxx:681
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:871
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:440
virtual void AddUndoAction(std::unique_ptr< SfxUndoAction > pAction, bool bTryMerg=false)
LINEEND_LF
#define SAL_MAX_INT32
void SetTextCurrentDefaults(const EditTextObject &rTextObject)
SetText and apply defaults already set.
Definition: editutil.cxx:596
SylkVersion
Definition: impex.cxx:94
SC_DLLPUBLIC void GetSymbol(OUString &rSymbol, const formula::FormulaGrammar::Grammar eGrammar=formula::FormulaGrammar::GRAM_DEFAULT) const
Definition: rangenam.cxx:243
int i
virtual void ScExportRTF(SvStream &, ScDocument *, const ScRange &rRange, const rtl_TextEncoding eDest)=0
bool ExportByteString(OString &, rtl_TextEncoding, SotClipboardFormatId)
Definition: impex.cxx:356
SC_DLLPUBLIC bool RowFiltered(SCROW nRow, SCTAB nTab, SCROW *pFirstRow=nullptr, SCROW *pLastRow=nullptr) const
Definition: document.cxx:4530
void SelectTable(SCTAB nTab, bool bNew)
Definition: markdata.cxx:172
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > ScDocumentUniquePtr
Definition: document.hxx:2621
sal_Int16 SCCOL
Definition: types.hxx:21
InsertDeleteFlags
Definition: global.hxx:157
bool ValidCol(SCCOL nCol) const
Definition: document.hxx:874
StreamMode
ScSheetLimits & GetSheetLimits() const
Definition: document.hxx:873
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:2212
SC_DLLPUBLIC void ApplyPattern(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr &rAttr)
Definition: document.cxx:4794
std::enable_if< std::is_signed< T >::value, bool >::type checked_add(T a, T b, T &result)
std::unique_ptr< EditTextObject > CreateTextObject()
std::size_t WriteBytes(const void *pData, std::size_t nSize)
float u
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALUE_FORMAT(146)
bool ShrinkToDataArea(SCTAB nTab, SCCOL &rStartCol, SCROW &rStartRow, SCCOL &rEndCol, SCROW &rEndRow) const
Shrink a range to only include data area.
Definition: document.cxx:1031
static void lcl_DoubleEscapeChar(OUString &rString, sal_Unicode cStr)
Definition: impex.cxx:866
SvNumFormatType
bool IsEditable() const
Definition: editable.hxx:83
bool IsBlockEmpty(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes=false) const
Definition: document.cxx:5322
~ScImportExport() COVERITY_NOEXCEPT_FALSE
Definition: impex.cxx:198
static SC_DLLPUBLIC LanguageType eLnge
Definition: global.hxx:547
sal_Unicode mcSeparatorConvertTo
Definition: impex.hxx:42
SC_DLLPUBLIC bool HasValueData(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:3796
bool ExportStream(SvStream &, const OUString &rBaseURL, SotClipboardFormatId)
Definition: impex.cxx:422
void PostPaint(SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, PaintPartFlags nPart, sal_uInt16 nExtFlags=0)
Definition: docsh3.cxx:100
bool HasType(Type nType) const
Definition: rangenam.hxx:176
ScFormatFilterPlugin * ScFilterCreate()
Definition: ftools.cxx:353
void PostDataChanged()
Definition: docsh3.cxx:92
void setAutoInput(const ScAddress &rPos, const OUString &rStr, const ScSetStringParam *pStringParam=nullptr)
void BroadcastCells(const ScRange &rRange, SfxHintId nHint, bool bBroadcastSingleBroadcasters=true)
Definition: documen7.cxx:143
SCCOL Col() const
Definition: address.hxx:266
bool mbImportBroadcast
Definition: impex.hxx:68
SC_DLLPUBLIC void EnsureTable(SCTAB nTab)
Definition: documen2.cxx:539
bool PutandConvertEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge, LanguageType eNewLnge, bool bConvertDateOrder, bool bReplaceBooleanEquivalent=true)
bool Doc2Sylk(SvStream &)
Definition: impex.cxx:2166
ConversionMode mode
static void EmbeddedNullTreatment(OUString &rStr)
Definition: impex.cxx:1602
bool GetMatrixOrigin(const ScDocument &rDoc, ScAddress &rPos) const
ScRange aRange
Definition: impex.hxx:51
CellType meType
Definition: cellvalue.hxx:105
SvStreamEndian GetEndian() const
ScDocument & rDoc
Definition: impex.hxx:49
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
sal_Int32 SCROW
Definition: types.hxx:17
bool bOverflowCell
Definition: impex.hxx:66
bool ValidRow(SCROW nRow) const
Definition: document.hxx:875
OUString ScResId(std::string_view aId)
Definition: scdll.cxx:89
SC_DLLPUBLIC ScFormulaCell * SetFormulaCell(const ScAddress &rPos, ScFormulaCell *pCell)
Set formula cell, and transfer its ownership to the document.
Definition: documen2.cxx:1083
static ScTabViewShell * GetActiveViewShell()
Definition: tabvwsh4.cxx:1038
DoubledQuoteMode
Definition: impex.cxx:683
exports com.sun.star. document
static sal_Unicode ToUpperAlpha(sal_Unicode c)
Definition: global.hxx:618
bool Sylk2Doc(SvStream &)
Definition: impex.cxx:1835
SvStream & WriteOString(std::string_view rStr)
#define ERRCODE_NONE
sal_Unicode cStr
Definition: impex.hxx:58
unsigned char sal_uInt8
ScImportExport(ScDocument &)
Definition: impex.cxx:105
static SotClipboardFormatId GetFormatIdFromMimeType(const OUString &rMimeType)
void GetMatColsRows(SCCOL &nCols, SCROW &nRows) const
CellType
Definition: global.hxx:280
SvStream & endl(SvStream &rStr)
virtual std::unique_ptr< ScEEAbsImport > CreateRTFImport(ScDocument *pDoc, const ScRange &rRange)=0
void SetEndian(SvStreamEndian SvStreamEndian)
void setStringCell(const ScAddress &rPos, const OUString &rStr)
SvStream & WriteUChar(unsigned char nChar)
bool bOverflowCol
Definition: impex.hxx:65
ScExportTextOptions mExportTextOptions
Definition: impex.hxx:72
sal_uInt32 GetStandardFormat(SvNumFormatType eType, LanguageType eLnge=LANGUAGE_DONTKNOW)
css::uno::Sequence< css::i18n::CalendarItem2 > getMonths() const
void SetStreamCharSet(rtl_TextEncoding eCharSet)
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:1742
const sal_uInt8 SC_COL_MDY
Definition: csvcontrol.hxx:56
const sal_uInt8 SC_COL_ENGLISH
Definition: csvcontrol.hxx:60
static const sal_Unicode * lcl_UnicodeStrChr(const sal_Unicode *pStr, sal_Unicode c)
Definition: impex.cxx:2458
rtl_TextEncoding GetStreamCharSet() const
static SC_DLLPUBLIC const CharClass * getCharClassPtr()
Definition: global.cxx:1010
sal_uInt64 Tell() const
void * p
Reference< XComponentContext > getProcessComponentContext()
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:400
bool RTF2Doc(SvStream &, const OUString &rBaseURL)
Definition: impex.cxx:2360
double getLength(const B2DPolygon &rCandidate)
bool ImportString(const OUString &, SotClipboardFormatId)
Definition: impex.cxx:303
SvStream & WriteChar(char nChar)
#define SVLIBRARY(Base)
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:640
virtual ErrCode ScImportDif(SvStream &, ScDocument *, const ScAddress &rInsPos, const rtl_TextEncoding eSrc)=0
bool Dif2Doc(SvStream &)
Definition: impex.cxx:2329
OUString ReadCsvLine(SvStream &rStream, bool bEmbeddedLineBreak, OUString &rFieldSeparators, sal_Unicode cFieldQuote, sal_Unicode &rcDetectSep)
Read a CSV (comma separated values) data line using ReadUniOrByteStringLine().
Definition: impex.cxx:2482
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1057
#define SAL_WARN(area, stream)
bool IsUndoEnabled() const
Definition: document.hxx:1535
static void GetString(const ScRefCellValue &rCell, sal_uInt32 nFormat, OUString &rString, const Color **ppColor, SvNumberFormatter &rFormatter, const ScDocument &rDoc, bool bNullVals=true, bool bFormula=false, bool bUseStarFormat=false)
Definition: cellform.cxx:31
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument &, const Details &rDetails=detailsOOOa1, ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, sal_Int32 *pSheetEndPos=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1548
ScRefFlags
Definition: address.hxx:144
void setNumericCell(const ScAddress &rPos, double fVal)
const sal_uInt8 SC_COL_DMY
Definition: csvcontrol.hxx:57
void SetFilterOptions(const OUString &rFilterOptions)
Definition: impex.cxx:217
bool StartPaste()
Definition: impex.cxx:234
SCROW nMaxImportRow
Definition: impex.hxx:56
SC_DLLPUBLIC void DeleteAreaTab(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, InsertDeleteFlags nDelFlag)
Definition: document.cxx:1929
bool ExtText2Doc(SvStream &)
Definition: impex.cxx:1363
bool bOverflowRow
Definition: impex.hxx:64
static const sal_Unicode * ScanNextFieldFromString(const sal_Unicode *p, OUString &rField, sal_Unicode cStr, const sal_Unicode *pSeps, bool bMergeSeps, bool &rbIsQuoted, bool &rbOverflowCell, bool bRemoveSpace)
Definition: impex.cxx:1618
void SvStream & rStrm
ScMatrixMode GetMatrixFlag() const
constexpr sal_Int32 nArbitraryLineLengthLimit
Definition: impex.cxx:76
static void SetNoEndianSwap(SvStream &rStrm)
only if stream is only used in own (!) memory
Definition: impex.cxx:574
const OUString & GetFieldSeps() const
Definition: asciiopt.hxx:56
static SCTAB GetCurTab()
Definition: docsh4.cxx:2565
ScFormatFilterPlugin *(* FilterFn)()
Definition: impex.cxx:2427
const sal_uInt8 SC_COL_SKIP
Definition: csvcontrol.hxx:59
aStr
QuoteType
Definition: impex.cxx:585
READ
SC_DLLPUBLIC ScFieldEditEngine & GetEditEngine()
Definition: documen2.cxx:456
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
sal_uInt16 nPos
sal_Int16 SCTAB
Definition: types.hxx:22
const void * GetData()
static sal_Int32 CountVisualWidth(const OUString &rStr, sal_Int32 &nIdx, sal_Int32 nMaxWidth)
ScImportExport::CountVisualWidth Count the width of string visually ( in multiple of western characte...
Definition: impex.cxx:544
bool isMultiRange() const
Definition: clipparam.cxx:38
const sal_uInt8 SC_COL_YMD
Definition: csvcontrol.hxx:58
ScDocument & getDoc()
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo