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 += OUString( 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 += OUString( 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 += OUString(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 += OUString( 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 += OUString( 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  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  pCalendar->setValue( i18n::CalendarFieldIndex::HOUR, nHour );
1229  pCalendar->setValue( i18n::CalendarFieldIndex::MINUTE, nMinute );
1230  pCalendar->setValue( i18n::CalendarFieldIndex::SECOND, nSecond );
1231  pCalendar->setValue( i18n::CalendarFieldIndex::MILLISECOND, 0 );
1232  if ( pCalendar->isValid() )
1233  {
1234  double fDiff = DateTime(pDocFormatter->GetNullDate()) -
1235  pCalendar->getEpochStart();
1236  // #i14974# must use getLocalDateTime to get the same
1237  // date values as set above
1238  double fDays = pCalendar->getLocalDateTime() + fFrac;
1239  fDays -= fDiff;
1240 
1241  LanguageType eLatin, eCjk, eCtl;
1242  rDoc.GetLanguage( eLatin, eCjk, eCtl );
1243  LanguageType eDocLang = eLatin;
1244 
1245  SvNumFormatType nType = (nFound > 3 ? SvNumFormatType::DATETIME : SvNumFormatType::DATE);
1246  sal_uLong nFormat = pDocFormatter->GetStandardFormat( nType, eDocLang );
1247  // maybe there is a special format including seconds or milliseconds
1248  if (nFound > 5)
1249  nFormat = pDocFormatter->GetStandardFormat( fDays, nFormat, nType, eDocLang);
1250 
1251  ScAddress aPos(nCol,nRow,nTab);
1252  if ( bUseDocImport )
1253  rDocImport.setNumericCell(aPos, fDays);
1254  else
1255  rDoc.SetValue( aPos, fDays );
1256  rDoc.SetNumberFormat(aPos, nFormat);
1257 
1258  return bMultiLine; // success
1259  }
1260  }
1261  }
1262  }
1263 
1264  // Standard or date not determined -> SetString / EditCell
1265  if( rStr.indexOf( '\n' ) == -1 )
1266  {
1267  ScSetStringParam aParam;
1268  aParam.mpNumFormatter = pFormatter;
1269  aParam.mbDetectNumberFormat = bDetectNumFormat;
1271  aParam.mbHandleApostrophe = false;
1272  aParam.mbCheckLinkFormula = true;
1273  if ( bUseDocImport )
1274  rDocImport.setAutoInput(ScAddress(nCol, nRow, nTab), rStr, &aParam);
1275  else
1276  rDoc.SetString( nCol, nRow, nTab, rStr, &aParam );
1277  }
1278  else
1279  {
1280  bMultiLine = true;
1281  ScFieldEditEngine& rEngine = rDoc.GetEditEngine();
1282  rEngine.SetTextCurrentDefaults(rStr);
1283  if ( bUseDocImport )
1284  rDocImport.setEditCell(ScAddress(nCol, nRow, nTab), rEngine.CreateTextObject());
1285  else
1286  rDoc.SetEditText( ScAddress( nCol, nRow, nTab ), rEngine.CreateTextObject() );
1287  }
1288  return bMultiLine;
1289 }
1290 
1291 static OUString lcl_GetFixed( const OUString& rLine, sal_Int32 nStart, sal_Int32 nNext,
1292  bool& rbIsQuoted, bool& rbOverflowCell )
1293 {
1294  sal_Int32 nLen = rLine.getLength();
1295  if (nNext > nLen)
1296  nNext = nLen;
1297  if ( nNext <= nStart )
1298  return EMPTY_OUSTRING;
1299 
1300  const sal_Unicode* pStr = rLine.getStr();
1301 
1302  sal_Int32 nSpace = nNext;
1303  while ( nSpace > nStart && pStr[nSpace-1] == ' ' )
1304  --nSpace;
1305 
1306  rbIsQuoted = (pStr[nStart] == '"' && pStr[nSpace-1] == '"');
1307  if (rbIsQuoted)
1308  {
1309  bool bFits = (nSpace - nStart - 3 <= nArbitraryCellLengthLimit);
1310  if (bFits)
1311  return rLine.copy(nStart+1, std::max< sal_Int32 >(0, nSpace-nStart-2));
1312  else
1313  {
1314  SAL_WARN( "sc", "lcl_GetFixed: line doesn't fit into data");
1315  rbOverflowCell = true;
1316  return rLine.copy(nStart+1, nArbitraryCellLengthLimit);
1317  }
1318  }
1319  else
1320  {
1321  bool bFits = (nSpace - nStart <= nArbitraryCellLengthLimit);
1322  if (bFits)
1323  return rLine.copy(nStart, nSpace-nStart);
1324  else
1325  {
1326  SAL_WARN( "sc", "lcl_GetFixed: line doesn't fit into data");
1327  rbOverflowCell = true;
1328  return rLine.copy(nStart, nArbitraryCellLengthLimit);
1329  }
1330  }
1331 }
1332 
1334 {
1335  if (!pExtOptions)
1336  return Text2Doc( rStrm );
1337 
1338  sal_uInt64 const nOldPos = rStrm.Tell();
1339  sal_uInt64 const nRemaining = rStrm.remainingSize();
1340  std::unique_ptr<ScProgress> xProgress( new ScProgress( pDocSh,
1341  ScResId( STR_LOAD_DOC ), nRemaining, true ));
1342  rStrm.StartReadingUnicodeText( rStrm.GetStreamCharSet() );
1343 
1344  SCCOL nStartCol = aRange.aStart.Col();
1345  SCCOL nEndCol = aRange.aEnd.Col();
1346  SCROW nStartRow = aRange.aStart.Row();
1347  SCTAB nTab = aRange.aStart.Tab();
1348 
1349  bool bFixed = pExtOptions->IsFixedLen();
1350  OUString aSeps = pExtOptions->GetFieldSeps(); // Need non-const for ReadCsvLine(),
1351  const sal_Unicode* pSeps = aSeps.getStr(); // but it will be const anyway (asserted below).
1352  bool bMerge = pExtOptions->IsMergeSeps();
1353  bool bRemoveSpace = pExtOptions->IsRemoveSpace();
1354  sal_uInt16 nInfoCount = pExtOptions->GetInfoCount();
1355  const sal_Int32* pColStart = pExtOptions->GetColStart();
1356  const sal_uInt8* pColFormat = pExtOptions->GetColFormat();
1357  tools::Long nSkipLines = pExtOptions->GetStartRow();
1358 
1359  LanguageType eDocLang = pExtOptions->GetLanguage();
1360  SvNumberFormatter aNumFormatter( comphelper::getProcessComponentContext(), eDocLang);
1361  bool bDetectNumFormat = pExtOptions->IsDetectSpecialNumber();
1362  bool bSkipEmptyCells = pExtOptions->IsSkipEmptyCells();
1363 
1364  // For date recognition
1365  ::utl::TransliterationWrapper aTransliteration(
1366  comphelper::getProcessComponentContext(), TransliterationFlags::IGNORE_CASE );
1367  aTransliteration.loadModuleIfNeeded( eDocLang );
1369  aCalendar.loadDefaultCalendar(
1370  LanguageTag::convertToLocale( eDocLang ) );
1371  std::unique_ptr< ::utl::TransliterationWrapper > pEnglishTransliteration;
1372  std::unique_ptr< CalendarWrapper > pEnglishCalendar;
1373  if ( eDocLang != LANGUAGE_ENGLISH_US )
1374  {
1375  pEnglishTransliteration.reset(new ::utl::TransliterationWrapper (
1376  comphelper::getProcessComponentContext(), TransliterationFlags::IGNORE_CASE ));
1377  aTransliteration.loadModuleIfNeeded( LANGUAGE_ENGLISH_US );
1378  pEnglishCalendar.reset(new CalendarWrapper ( comphelper::getProcessComponentContext() ));
1379  pEnglishCalendar->loadDefaultCalendar(
1381  }
1382 
1383  OUString aLine;
1384  OUString aCell;
1385  sal_uInt16 i;
1386  SCROW nRow = nStartRow;
1387  sal_Unicode cDetectSep = 0xffff; // No separator detection here.
1388 
1389  while(--nSkipLines>0)
1390  {
1391  aLine = ReadCsvLine(rStrm, !bFixed, aSeps, cStr, cDetectSep); // content is ignored
1392  if ( rStrm.eof() )
1393  break;
1394  }
1395 
1396  // Determine range for Undo.
1397  // We don't need this during import of a file to a new sheet or document...
1398  bool bDetermineRange = bUndo;
1399 
1400  // Row heights don't need to be adjusted on the fly if EndPaste() is called
1401  // afterwards, which happens only if bDetermineRange. This variable also
1402  // survives the toggle of bDetermineRange down at the end of the do{} loop.
1403  bool bRangeIsDetermined = bDetermineRange;
1404 
1405  bool bQuotedAsText = pExtOptions && pExtOptions->IsQuotedAsText();
1406 
1407  sal_uLong nOriginalStreamPos = rStrm.Tell();
1408 
1409  ScDocumentImport aDocImport(rDoc);
1410  do
1411  {
1412  for( ;; )
1413  {
1414  aLine = ReadCsvLine(rStrm, !bFixed, aSeps, cStr, cDetectSep);
1415  if ( rStrm.eof() && aLine.isEmpty() )
1416  break;
1417 
1418  assert(pSeps == aSeps.getStr());
1419 
1420  if ( nRow > rDoc.MaxRow() )
1421  {
1422  bOverflowRow = true; // display warning on import
1423  break; // for
1424  }
1425 
1426  EmbeddedNullTreatment( aLine);
1427 
1428  sal_Int32 nLineLen = aLine.getLength();
1429  SCCOL nCol = nStartCol;
1430  bool bMultiLine = false;
1431  if ( bFixed ) // Fixed line length
1432  {
1433  sal_Int32 nStartIdx = 0;
1434  // Yes, the check is nCol<=rDoc.MaxCol()+1, +1 because it is only an
1435  // overflow if there is really data following to be put behind
1436  // the last column, which doesn't happen if info is
1437  // SC_COL_SKIP.
1438  for ( i=0; i<nInfoCount && nCol <= rDoc.MaxCol()+1; i++ )
1439  {
1440  sal_uInt8 nFmt = pColFormat[i];
1441  if (nFmt != SC_COL_SKIP) // otherwise don't increment nCol either
1442  {
1443  if (nCol > rDoc.MaxCol())
1444  bOverflowCol = true; // display warning on import
1445  else if (!bDetermineRange)
1446  {
1447  sal_Int32 nNextIdx = nStartIdx;
1448  if ( i + 1 < nInfoCount )
1449  CountVisualWidth( aLine, nNextIdx, pColStart[i+1] - pColStart[i] );
1450  else
1451  nNextIdx = nLineLen;
1452 
1453  bool bIsQuoted = false;
1454  aCell = lcl_GetFixed( aLine, nStartIdx, nNextIdx, bIsQuoted, bOverflowCell );
1455  if (bIsQuoted && bQuotedAsText)
1456  nFmt = SC_COL_TEXT;
1457 
1458  bMultiLine |= lcl_PutString(
1459  aDocImport, !mbOverwriting, nCol, nRow, nTab, aCell, nFmt,
1460  &aNumFormatter, bDetectNumFormat, bSkipEmptyCells, aTransliteration, aCalendar,
1461  pEnglishTransliteration.get(), pEnglishCalendar.get());
1462 
1463  nStartIdx = nNextIdx;
1464  }
1465  ++nCol;
1466  }
1467  }
1468  }
1469  else // Search for the separator
1470  {
1471  SCCOL nSourceCol = 0;
1472  sal_uInt16 nInfoStart = 0;
1473  const sal_Unicode* p = aLine.getStr();
1474  // Yes, the check is nCol<=rDoc.MaxCol()+1, +1 because it is only an
1475  // overflow if there is really data following to be put behind
1476  // the last column, which doesn't happen if info is
1477  // SC_COL_SKIP.
1478  while (*p && nCol <= rDoc.MaxCol()+1)
1479  {
1480  bool bIsQuoted = false;
1482  cStr, pSeps, bMerge, bIsQuoted, bOverflowCell, bRemoveSpace );
1483 
1484  sal_uInt8 nFmt = SC_COL_STANDARD;
1485  for ( i=nInfoStart; i<nInfoCount; i++ )
1486  {
1487  if ( pColStart[i] == nSourceCol + 1 ) // pColStart is 1-based
1488  {
1489  nFmt = pColFormat[i];
1490  nInfoStart = i + 1; // ColInfos are in succession
1491  break; // for
1492  }
1493  }
1494  if ( nFmt != SC_COL_SKIP )
1495  {
1496  if (nCol > rDoc.MaxCol())
1497  bOverflowCol = true; // display warning on import
1498  else if (!bDetermineRange)
1499  {
1500  if (bIsQuoted && bQuotedAsText)
1501  nFmt = SC_COL_TEXT;
1502 
1503  bMultiLine |= lcl_PutString(
1504  aDocImport, !mbOverwriting, nCol, nRow, nTab, aCell, nFmt,
1505  &aNumFormatter, bDetectNumFormat, bSkipEmptyCells, aTransliteration,
1506  aCalendar, pEnglishTransliteration.get(), pEnglishCalendar.get());
1507  }
1508  ++nCol;
1509  }
1510 
1511  ++nSourceCol;
1512  }
1513  }
1514  if (nEndCol < nCol)
1515  nEndCol = nCol;
1516 
1517  if (!bDetermineRange)
1518  {
1519  if (bMultiLine && !bRangeIsDetermined && pDocSh)
1520  pDocSh->AdjustRowHeight( nRow, nRow, nTab);
1521  xProgress->SetStateOnPercent( rStrm.Tell() - nOldPos );
1522  }
1523  ++nRow;
1524  }
1525  // so far nRow/nEndCol pointed to the next free
1526  if (nRow > nStartRow)
1527  --nRow;
1528  if (nEndCol > nStartCol)
1529  nEndCol = ::std::min( static_cast<SCCOL>(nEndCol - 1), rDoc.MaxCol());
1530 
1531  if (bDetermineRange)
1532  {
1533  aRange.aEnd.SetCol( nEndCol );
1534  aRange.aEnd.SetRow( nRow );
1535 
1536  if ( !mbApi && nStartCol != nEndCol &&
1537  !rDoc.IsBlockEmpty( nTab, nStartCol + 1, nStartRow, nEndCol, nRow ) )
1538  {
1540  if (aBox.run() != RET_YES)
1541  {
1542  return false;
1543  }
1544  }
1545 
1546  rStrm.Seek( nOriginalStreamPos );
1547  nRow = nStartRow;
1548  if (!StartPaste())
1549  {
1550  EndPaste(false);
1551  return false;
1552  }
1553  }
1554 
1555  bDetermineRange = !bDetermineRange; // toggle
1556  } while (!bDetermineRange);
1557  if ( !mbOverwriting )
1558  aDocImport.finalize();
1559 
1560  xProgress.reset(); // make room for AdjustRowHeight progress
1561  if (bRangeIsDetermined)
1562  EndPaste(false);
1563 
1565  {
1566  rDoc.BroadcastCells(aRange, SfxHintId::ScDataChanged);
1568  }
1569  return true;
1570 }
1571 
1573 {
1574  // A nasty workaround for data with embedded NULL characters. As long as we
1575  // can't handle them properly as cell content (things assume 0-terminated
1576  // strings at too many places) simply strip all NULL characters from raw
1577  // data. Excel does the same. See fdo#57841 for sample data.
1578 
1579  // The normal case is no embedded NULL, check first before de-/allocating
1580  // ustring stuff.
1581  sal_Unicode cNull = 0;
1582  if (rStr.indexOf( cNull) >= 0)
1583  {
1584  rStr = rStr.replaceAll( std::u16string_view( &cNull, 1), "");
1585  }
1586 }
1587 
1589  OUString& rField, sal_Unicode cStr, const sal_Unicode* pSeps, bool bMergeSeps, bool& rbIsQuoted,
1590  bool& rbOverflowCell, bool bRemoveSpace )
1591 {
1592  rbIsQuoted = false;
1593  rField.clear();
1594  const sal_Unicode cBlank = ' ';
1595  if (!ScGlobal::UnicodeStrChr( pSeps, cBlank))
1596  {
1597  // Cope with broken generators that put leading blanks before a quoted
1598  // field, like "field1", "field2", "..."
1599  // NOTE: this is not in conformance with http://tools.ietf.org/html/rfc4180
1600  const sal_Unicode* pb = p;
1601  while (*pb == cBlank)
1602  ++pb;
1603  if (*pb == cStr)
1604  p = pb;
1605  }
1606  if ( *p == cStr ) // String in quotes
1607  {
1608  rbIsQuoted = true;
1609  const sal_Unicode* p1;
1610  p1 = p = lcl_ScanString( p, rField, pSeps, cStr, DoubledQuoteMode::ESCAPE, rbOverflowCell );
1611  while ( *p && !ScGlobal::UnicodeStrChr( pSeps, *p ) )
1612  p++;
1613  // Append remaining unquoted and undelimited data (dirty, dirty) to
1614  // this field.
1615  if (p > p1)
1616  {
1617  const sal_Unicode* ptrim_f = p;
1618  if ( bRemoveSpace )
1619  {
1620  while ( ptrim_f > p1 && ( *(ptrim_f - 1) == cBlank ) )
1621  --ptrim_f;
1622  }
1623  if (!lcl_appendLineData( rField, p1, ptrim_f))
1624  rbOverflowCell = true;
1625  }
1626  if( *p )
1627  p++;
1628  }
1629  else // up to delimiter
1630  {
1631  const sal_Unicode* p0 = p;
1632  while ( *p && !ScGlobal::UnicodeStrChr( pSeps, *p ) )
1633  p++;
1634  const sal_Unicode* ptrim_i = p0;
1635  const sal_Unicode* ptrim_f = p; // [ptrim_i,ptrim_f) is cell data after trimming
1636  if ( bRemoveSpace )
1637  {
1638  while ( *ptrim_i == cBlank )
1639  ++ptrim_i;
1640  while ( ptrim_f > ptrim_i && ( *(ptrim_f - 1) == cBlank ) )
1641  --ptrim_f;
1642  }
1643  if (!lcl_appendLineData( rField, ptrim_i, ptrim_f))
1644  rbOverflowCell = true;
1645  if( *p )
1646  p++;
1647  }
1648  if ( bMergeSeps ) // skip following delimiters
1649  {
1650  while ( *p && ScGlobal::UnicodeStrChr( pSeps, *p ) )
1651  p++;
1652  }
1653  return p;
1654 }
1655 
1656 namespace {
1657 
1664 bool hasLineBreaksOrSeps( const OUString& rStr, sal_Unicode cSep )
1665 {
1666  const sal_Unicode* p = rStr.getStr();
1667  for (sal_Int32 i = 0, n = rStr.getLength(); i < n; ++i, ++p)
1668  {
1669  sal_Unicode c = *p;
1670  if (c == cSep)
1671  // separator found.
1672  return true;
1673 
1674  switch (c)
1675  {
1676  case '\n':
1677  case '\r':
1678  // line break found.
1679  return true;
1680  default:
1681  ;
1682  }
1683  }
1684  return false;
1685 }
1686 
1687 }
1688 
1690 {
1691  SCCOL nCol;
1692  SCROW nRow;
1693  SCCOL nStartCol = aRange.aStart.Col();
1694  SCROW nStartRow = aRange.aStart.Row();
1695  SCTAB nStartTab = aRange.aStart.Tab();
1696  SCCOL nEndCol = aRange.aEnd.Col();
1697  SCROW nEndRow = aRange.aEnd.Row();
1698  SCTAB nEndTab = aRange.aEnd.Tab();
1699 
1700  if (!rDoc.GetClipParam().isMultiRange() && nStartTab == nEndTab)
1701  if (!rDoc.ShrinkToDataArea( nStartTab, nStartCol, nStartRow, nEndCol, nEndRow ))
1702  return false;
1703 
1704  OUString aCellStr;
1705 
1706  bool bConvertLF = (GetSystemLineEnd() != LINEEND_LF);
1707 
1708  // We need to cache sc::ColumnBlockPosition per each column, tab is always nStartTab.
1709  std::vector< sc::ColumnBlockPosition > blockPos( nEndCol - nStartCol + 1 );
1710  for( SCCOL i = nStartCol; i <= nEndCol; ++i )
1711  rDoc.InitColumnBlockPosition( blockPos[ i - nStartCol ], nStartTab, i );
1712  for (nRow = nStartRow; nRow <= nEndRow; nRow++)
1713  {
1714  if (bIncludeFiltered || !rDoc.RowFiltered( nRow, nStartTab ))
1715  {
1716  for (nCol = nStartCol; nCol <= nEndCol; nCol++)
1717  {
1718  ScAddress aPos(nCol, nRow, nStartTab);
1719  sal_uInt32 nNumFmt = rDoc.GetNumberFormat(aPos);
1720  SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
1721 
1722  ScRefCellValue aCell(rDoc, aPos, blockPos[ nCol - nStartCol ]);
1723  switch (aCell.meType)
1724  {
1725  case CELLTYPE_FORMULA:
1726  {
1727  if (bFormulas)
1728  {
1729  aCell.mpFormula->GetFormula( aCellStr );
1730  if( aCellStr.indexOf( cSep ) != -1 )
1731  lcl_WriteString( rStrm, aCellStr, cStr, cStr );
1732  else
1733  lcl_WriteSimpleString( rStrm, aCellStr );
1734  }
1735  else
1736  {
1737  const Color* pColor;
1738  ScCellFormat::GetString(aCell, nNumFmt, aCellStr, &pColor, *pFormatter, rDoc);
1739 
1740  bool bMultiLineText = ( aCellStr.indexOf( '\n' ) != -1 );
1741  if( bMultiLineText )
1742  {
1744  aCellStr = aCellStr.replaceAll( "\n", " " );
1746  aCellStr = convertLineEnd(aCellStr, GetSystemLineEnd());
1747  }
1748 
1750  aCellStr = aCellStr.replaceAll( OUStringChar(cSep), OUStringChar(mExportTextOptions.mcSeparatorConvertTo) );
1751 
1752  if( mExportTextOptions.mbAddQuotes && ( aCellStr.indexOf( cSep ) != -1 ) )
1753  lcl_WriteString( rStrm, aCellStr, cStr, cStr );
1754  else
1755  lcl_WriteSimpleString( rStrm, aCellStr );
1756  }
1757  }
1758  break;
1759  case CELLTYPE_VALUE:
1760  {
1761  const Color* pColor;
1762  ScCellFormat::GetString(aCell, nNumFmt, aCellStr, &pColor, *pFormatter, rDoc);
1763  lcl_WriteSimpleString( rStrm, aCellStr );
1764  }
1765  break;
1766  case CELLTYPE_NONE:
1767  break;
1768  default:
1769  {
1770  const Color* pColor;
1771  ScCellFormat::GetString(aCell, nNumFmt, aCellStr, &pColor, *pFormatter, rDoc);
1772 
1773  bool bMultiLineText = ( aCellStr.indexOf( '\n' ) != -1 );
1774  if( bMultiLineText )
1775  {
1777  aCellStr = aCellStr.replaceAll( "\n", " " );
1779  aCellStr = convertLineEnd(aCellStr, GetSystemLineEnd());
1780  }
1781 
1783  aCellStr = aCellStr.replaceAll( OUStringChar(cSep), OUStringChar(mExportTextOptions.mcSeparatorConvertTo) );
1784 
1785  if( mExportTextOptions.mbAddQuotes && hasLineBreaksOrSeps(aCellStr, cSep) )
1786  lcl_WriteString( rStrm, aCellStr, cStr, cStr );
1787  else
1788  lcl_WriteSimpleString( rStrm, aCellStr );
1789  }
1790  }
1791  if( nCol < nEndCol )
1792  lcl_WriteSimpleString( rStrm, OUString(cSep) );
1793  }
1794  WriteUnicodeOrByteEndl( rStrm );
1795  if( rStrm.GetError() != ERRCODE_NONE )
1796  break;
1797  if( nSizeLimit && rStrm.Tell() > nSizeLimit )
1798  break;
1799  }
1800  }
1801 
1802  return rStrm.GetError() == ERRCODE_NONE;
1803 }
1804 
1806 {
1807  bool bOk = true;
1808  bool bMyDoc = false;
1809  SylkVersion eVersion = SylkVersion::OTHER;
1810 
1811  // US-English separators for StringToDouble
1812  sal_Unicode const cDecSep = '.';
1813  sal_Unicode const cGrpSep = ',';
1814 
1815  SCCOL nStartCol = aRange.aStart.Col();
1816  SCROW nStartRow = aRange.aStart.Row();
1817  SCCOL nEndCol = aRange.aEnd.Col();
1818  SCROW nEndRow = aRange.aEnd.Row();
1819  sal_uLong nOldPos = rStrm.Tell();
1820  bool bData = !bSingle;
1821  ::std::vector< sal_uInt32 > aFormats;
1822 
1823  if( !bSingle)
1824  bOk = StartPaste();
1825 
1826  while( bOk )
1827  {
1828  OUString aLine;
1829  OUString aText;
1830  OString aByteLine;
1831  SCCOL nCol = nStartCol;
1832  SCROW nRow = nStartRow;
1833  SCCOL nRefCol = nCol;
1834  SCROW nRefRow = nRow;
1835  rStrm.Seek( nOldPos );
1836  for( ;; )
1837  {
1839  rStrm.ReadLine( aByteLine );
1840  aLine = OStringToOUString(aByteLine, rStrm.GetStreamCharSet());
1841  if( rStrm.eof() )
1842  break;
1843  bool bInvalidCol = false;
1844  bool bInvalidRow = false;
1845  const sal_Unicode* p = aLine.getStr();
1846  sal_Unicode cTag = *p++;
1847  if( cTag == 'C' ) // Content
1848  {
1849  if( *p++ != ';' )
1850  return false;
1851 
1852  bool bInvalidRefCol = false;
1853  bool bInvalidRefRow = false;
1854  while( *p )
1855  {
1856  sal_Unicode ch = *p++;
1857  ch = ScGlobal::ToUpperAlpha( ch );
1858  switch( ch )
1859  {
1860  case 'X':
1861  {
1862  bInvalidCol = false;
1863  bool bFail = o3tl::checked_add<SCCOL>(OUString(p).toInt32(), nStartCol - 1, nCol);
1864  if (bFail || nCol < 0 || rDoc.MaxCol() < nCol)
1865  {
1866  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;X invalid nCol=" << nCol);
1867  nCol = std::clamp<SCCOL>(nCol, 0, rDoc.MaxCol());
1868  bInvalidCol = bOverflowCol = true;
1869  }
1870  break;
1871  }
1872  case 'Y':
1873  {
1874  bInvalidRow = false;
1875  bool bFail = o3tl::checked_add(OUString(p).toInt32(), nStartRow - 1, nRow);
1876  if (bFail || nRow < 0 || nMaxImportRow < nRow)
1877  {
1878  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;Y invalid nRow=" << nRow);
1879  nRow = std::clamp<SCROW>(nRow, 0, nMaxImportRow);
1880  bInvalidRow = bOverflowRow = true;
1881  }
1882  break;
1883  }
1884  case 'C':
1885  {
1886  bInvalidRefCol = false;
1887  bool bFail = o3tl::checked_add<SCCOL>(OUString(p).toInt32(), nStartCol - 1, nRefCol);
1888  if (bFail || nRefCol < 0 || rDoc.MaxCol() < nRefCol)
1889  {
1890  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;C invalid nRefCol=" << nRefCol);
1891  nRefCol = std::clamp<SCCOL>(nRefCol, 0, rDoc.MaxCol());
1892  bInvalidRefCol = bOverflowCol = true;
1893  }
1894  break;
1895  }
1896  case 'R':
1897  {
1898  bInvalidRefRow = false;
1899  bool bFail = o3tl::checked_add(OUString(p).toInt32(), nStartRow - 1, nRefRow);
1900  if (bFail || nRefRow < 0 || nMaxImportRow < nRefRow)
1901  {
1902  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;R invalid nRefRow=" << nRefRow);
1903  nRefRow = std::clamp<SCROW>(nRefRow, 0, nMaxImportRow);
1904  bInvalidRefRow = bOverflowRow = true;
1905  }
1906  break;
1907  }
1908  case 'K':
1909  {
1910  if( !bSingle &&
1911  ( nCol < nStartCol || nCol > nEndCol
1912  || nRow < nStartRow || nRow > nEndRow
1913  || nCol > rDoc.MaxCol() || nRow > nMaxImportRow
1914  || bInvalidCol || bInvalidRow ) )
1915  break;
1916  if( !bData )
1917  {
1918  if( nRow > nEndRow )
1919  nEndRow = nRow;
1920  if( nCol > nEndCol )
1921  nEndCol = nCol;
1922  break;
1923  }
1924  bool bText;
1925  if( *p == '"' )
1926  {
1927  bText = true;
1928  aText.clear();
1929  p = lcl_ScanSylkString( p, aText, eVersion);
1930  }
1931  else
1932  bText = false;
1933  const sal_Unicode* q = p;
1934  while( *q && *q != ';' )
1935  q++;
1936  if ( (*q != ';' || *(q+1) != 'I') && !bInvalidCol && !bInvalidRow )
1937  { // don't ignore value
1938  if( bText )
1939  {
1941  rDoc.SetTextCell(
1942  ScAddress(nCol, nRow, aRange.aStart.Tab()), aText);
1943  }
1944  else
1945  {
1946  double fVal = rtl_math_uStringToDouble( p,
1947  aLine.getStr() + aLine.getLength(),
1948  cDecSep, cGrpSep, nullptr, nullptr );
1949  rDoc.SetValue( nCol, nRow, aRange.aStart.Tab(), fVal );
1950  }
1951  }
1952  }
1953  break;
1954  case 'E':
1955  case 'M':
1956  {
1957  if ( ch == 'M' )
1958  {
1959  if ( nRefCol < nCol )
1960  nRefCol = nCol;
1961  if ( nRefRow < nRow )
1962  nRefRow = nRow;
1963  if ( !bData )
1964  {
1965  if( nRefRow > nEndRow )
1966  nEndRow = nRefRow;
1967  if( nRefCol > nEndCol )
1968  nEndCol = nRefCol;
1969  }
1970  }
1971  if( !bMyDoc || !bData )
1972  break;
1973  aText = "=";
1974  p = lcl_ScanSylkFormula( p, aText, eVersion);
1975 
1976  if (bInvalidCol || bInvalidRow || (ch == 'M' && (bInvalidRefCol || bInvalidRefRow)))
1977  break;
1978 
1979  ScAddress aPos( nCol, nRow, aRange.aStart.Tab() );
1980  /* FIXME: do we want GRAM_ODFF_A1 instead? At the
1981  * end it probably should be GRAM_ODFF_R1C1, since
1982  * R1C1 is what Excel writes in SYLK, or even
1983  * better GRAM_ENGLISH_XL_R1C1. */
1985  ScCompiler aComp(rDoc, aPos, eGrammar);
1986  std::unique_ptr<ScTokenArray> xCode(aComp.CompileString(aText)); // ctor/InsertMatrixFormula did copy TokenArray
1988  if ( ch == 'M' )
1989  {
1990  ScMarkData aMark(rDoc.GetSheetLimits());
1991  aMark.SelectTable( aPos.Tab(), true );
1992  rDoc.InsertMatrixFormula( nCol, nRow, nRefCol,
1993  nRefRow, aMark, EMPTY_OUSTRING, xCode.get() );
1994  }
1995  else
1996  {
1997  ScFormulaCell* pFCell = new ScFormulaCell(
1998  rDoc, aPos, *xCode, eGrammar, ScMatrixMode::NONE);
1999  rDoc.SetFormulaCell(aPos, pFCell);
2000  }
2001  }
2002  break;
2003  }
2004  while( *p && *p != ';' )
2005  p++;
2006  if( *p )
2007  p++;
2008  }
2009  }
2010  else if( cTag == 'F' ) // Format
2011  {
2012  if( *p++ != ';' )
2013  return false;
2014  sal_Int32 nFormat = -1;
2015  while( *p )
2016  {
2017  sal_Unicode ch = *p++;
2018  ch = ScGlobal::ToUpperAlpha( ch );
2019  switch( ch )
2020  {
2021  case 'X':
2022  {
2023  bInvalidCol = false;
2024  bool bFail = o3tl::checked_add<SCCOL>(OUString(p).toInt32(), nStartCol - 1, nCol);
2025  if (bFail || nCol < 0 || rDoc.MaxCol() < nCol)
2026  {
2027  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;X invalid nCol=" << nCol);
2028  nCol = std::clamp<SCCOL>(nCol, 0, rDoc.MaxCol());
2029  bInvalidCol = bOverflowCol = true;
2030  }
2031  break;
2032  }
2033  case 'Y':
2034  {
2035  bInvalidRow = false;
2036  bool bFail = o3tl::checked_add(OUString(p).toInt32(), nStartRow - 1, nRow);
2037  if (bFail || nRow < 0 || nMaxImportRow < nRow)
2038  {
2039  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;Y invalid nRow=" << nRow);
2040  nRow = std::clamp<SCROW>(nRow, 0, nMaxImportRow);
2041  bInvalidRow = bOverflowRow = true;
2042  }
2043  break;
2044  }
2045  case 'P' :
2046  if ( bData )
2047  {
2048  // F;P<n> sets format code of P;P<code> at
2049  // current position, or at ;X;Y if specified.
2050  // Note that ;X;Y may appear after ;P
2051  const sal_Unicode* p0 = p;
2052  while( *p && *p != ';' )
2053  p++;
2054  OUString aNumber(p0, p - p0);
2055  nFormat = aNumber.toInt32();
2056  }
2057  break;
2058  }
2059  while( *p && *p != ';' )
2060  p++;
2061  if( *p )
2062  p++;
2063  }
2064  if ( !bData )
2065  {
2066  if( nRow > nEndRow )
2067  nEndRow = nRow;
2068  if( nCol > nEndCol )
2069  nEndCol = nCol;
2070  }
2071  if ( 0 <= nFormat && nFormat < static_cast<sal_Int32>(aFormats.size()) && !bInvalidCol && !bInvalidRow )
2072  {
2073  sal_uInt32 nKey = aFormats[nFormat];
2074  rDoc.ApplyAttr( nCol, nRow, aRange.aStart.Tab(),
2075  SfxUInt32Item( ATTR_VALUE_FORMAT, nKey ) );
2076  }
2077  }
2078  else if( cTag == 'P' )
2079  {
2080  if ( bData && *p == ';' && *(p+1) == 'P' )
2081  {
2082  OUString aCode( p+2 );
2083 
2084  sal_uInt32 nKey;
2085  sal_Int32 nCheckPos;
2086 
2087  if (aCode.getLength() > 2048 && utl::ConfigManager::IsFuzzing())
2088  {
2089  // consider an excessive length as a failure when fuzzing
2090  nCheckPos = 1;
2091  }
2092  else
2093  {
2094  // unescape doubled semicolons
2095  aCode = aCode.replaceAll(";;", ";");
2096  // get rid of Xcl escape characters
2097  aCode = aCode.replaceAll("\x1b", "");
2099  rDoc.GetFormatTable()->PutandConvertEntry( aCode, nCheckPos, nType, nKey,
2101  }
2102 
2103  if ( nCheckPos )
2104  nKey = 0;
2105 
2106  aFormats.push_back( nKey );
2107  }
2108  }
2109  else if( cTag == 'I' && *p == 'D' )
2110  {
2111  aLine = aLine.copy(4);
2112  if (aLine == "CALCOOO32")
2113  eVersion = SylkVersion::OOO32;
2114  else if (aLine == "SCALC3")
2115  eVersion = SylkVersion::SCALC3;
2116  bMyDoc = (eVersion <= SylkVersion::OWN);
2117  }
2118  else if( cTag == 'E' ) // End
2119  break;
2120  }
2121  if( !bData )
2122  {
2123  aRange.aEnd.SetCol( nEndCol );
2124  aRange.aEnd.SetRow( nEndRow );
2125  bOk = StartPaste();
2126  bData = true;
2127  }
2128  else
2129  break;
2130  }
2131 
2132  EndPaste();
2133  return bOk;
2134 }
2135 
2137 {
2138  SCCOL nCol;
2139  SCROW nRow;
2140  SCCOL nStartCol = aRange.aStart.Col();
2141  SCROW nStartRow = aRange.aStart.Row();
2142  SCCOL nEndCol = aRange.aEnd.Col();
2143  SCROW nEndRow = aRange.aEnd.Row();
2144  OUString aCellStr;
2145  OUString aValStr;
2146  lcl_WriteSimpleString( rStrm, "ID;PCALCOOO32" );
2147  WriteUnicodeOrByteEndl( rStrm );
2148 
2149  for (nRow = nStartRow; nRow <= nEndRow; nRow++)
2150  {
2151  for (nCol = nStartCol; nCol <= nEndCol; nCol++)
2152  {
2153  OUString aBufStr;
2154  double nVal;
2155  bool bForm = false;
2156  SCROW r = nRow - nStartRow + 1;
2157  SCCOL c = nCol - nStartCol + 1;
2158  ScRefCellValue aCell(rDoc, ScAddress(nCol, nRow, aRange.aStart.Tab()));
2159  CellType eType = aCell.meType;
2160  switch( eType )
2161  {
2162  case CELLTYPE_FORMULA:
2163  bForm = bFormulas;
2164  if( rDoc.HasValueData( nCol, nRow, aRange.aStart.Tab()) )
2165  goto hasvalue;
2166  else
2167  goto hasstring;
2168 
2169  case CELLTYPE_VALUE:
2170  hasvalue:
2171  rDoc.GetValue( nCol, nRow, aRange.aStart.Tab(), nVal );
2172 
2173  aValStr = ::rtl::math::doubleToUString( nVal,
2174  rtl_math_StringFormat_Automatic,
2175  rtl_math_DecimalPlaces_Max, '.', true );
2176 
2177  aBufStr = "C;X"
2178  + OUString::number( c )
2179  + ";Y"
2180  + OUString::number( r )
2181  + ";K"
2182  + aValStr;
2183  lcl_WriteSimpleString( rStrm, aBufStr );
2184  goto checkformula;
2185 
2186  case CELLTYPE_STRING:
2187  case CELLTYPE_EDIT:
2188  hasstring:
2189  aCellStr = rDoc.GetString(nCol, nRow, aRange.aStart.Tab());
2190  aCellStr = aCellStr.replaceAll("\n", SYLK_LF);
2191 
2192  aBufStr = "C;X"
2193  + OUString::number( c )
2194  + ";Y"
2195  + OUString::number( r )
2196  + ";K";
2197  lcl_WriteSimpleString( rStrm, aBufStr );
2198  lcl_WriteString( rStrm, aCellStr, '"', ';' );
2199 
2200  checkformula:
2201  if( bForm )
2202  {
2203  const ScFormulaCell* pFCell = aCell.mpFormula;
2204  switch ( pFCell->GetMatrixFlag() )
2205  {
2207  aCellStr.clear();
2208  break;
2209  default:
2210  OUString aOUCellStr;
2212  aCellStr = aOUCellStr;
2213  /* FIXME: do we want GRAM_ODFF_A1 instead? At
2214  * the end it probably should be
2215  * GRAM_ODFF_R1C1, since R1C1 is what Excel
2216  * writes in SYLK, or even better
2217  * GRAM_ENGLISH_XL_R1C1. */
2218  }
2219  if ( pFCell->GetMatrixFlag() != ScMatrixMode::NONE &&
2220  aCellStr.startsWith("{") &&
2221  aCellStr.endsWith("}") )
2222  { // cut off matrix {} characters
2223  aCellStr = aCellStr.copy(1, aCellStr.getLength()-2);
2224  }
2225  if ( aCellStr[0] == '=' )
2226  aCellStr = aCellStr.copy(1);
2227  OUString aPrefix;
2228  switch ( pFCell->GetMatrixFlag() )
2229  {
2230  case ScMatrixMode::Formula :
2231  { // diff expression with 'M' M$-extension
2232  SCCOL nC;
2233  SCROW nR;
2234  pFCell->GetMatColsRows( nC, nR );
2235  nC += c - 1;
2236  nR += r - 1;
2237  aPrefix = ";R"
2238  + OUString::number( nR )
2239  + ";C"
2240  + OUString::number( nC )
2241  + ";M";
2242  }
2243  break;
2245  { // diff expression with 'I' M$-extension
2246  ScAddress aPos;
2247  (void)pFCell->GetMatrixOrigin( rDoc, aPos );
2248  aPrefix = ";I;R"
2249  + OUString::number( aPos.Row() - nStartRow + 1 )
2250  + ";C"
2251  + OUString::number( aPos.Col() - nStartCol + 1 );
2252  }
2253  break;
2254  default:
2255  // formula Expression
2256  aPrefix = ";E";
2257  }
2258  lcl_WriteSimpleString( rStrm, aPrefix );
2259  if ( !aCellStr.isEmpty() )
2260  lcl_WriteString( rStrm, aCellStr, 0, ';' );
2261  }
2262  WriteUnicodeOrByteEndl( rStrm );
2263  break;
2264 
2265  default:
2266  {
2267  // added to avoid warnings
2268  }
2269  }
2270  }
2271  }
2272  lcl_WriteSimpleString( rStrm, OUString( 'E' ) );
2273  WriteUnicodeOrByteEndl( rStrm );
2274  return rStrm.GetError() == ERRCODE_NONE;
2275 }
2276 
2277 bool ScImportExport::Doc2HTML( SvStream& rStrm, const OUString& rBaseURL )
2278 {
2279  // rtl_TextEncoding is ignored in ScExportHTML, read from Load/Save HTML options
2280  ScFormatFilter::Get().ScExportHTML( rStrm, rBaseURL, &rDoc, aRange, RTL_TEXTENCODING_DONTKNOW, bAll,
2282  return rStrm.GetError() == ERRCODE_NONE;
2283 }
2284 
2286 {
2287  // rtl_TextEncoding is ignored in ScExportRTF
2288  ScFormatFilter::Get().ScExportRTF( rStrm, &rDoc, aRange, RTL_TEXTENCODING_DONTKNOW );
2289  return rStrm.GetError() == ERRCODE_NONE;
2290 }
2291 
2293 {
2294  // for DIF in the clipboard, IBM_850 is always used
2295  ScFormatFilter::Get().ScExportDif( rStrm, &rDoc, aRange, RTL_TEXTENCODING_IBM_850 );
2296  return true;
2297 }
2298 
2300 {
2301  SCTAB nTab = aRange.aStart.Tab();
2302  ScDocumentUniquePtr pImportDoc( new ScDocument( SCDOCMODE_UNDO ) );
2303  pImportDoc->InitUndo( rDoc, nTab, nTab );
2304 
2305  // for DIF in the clipboard, IBM_850 is always used
2306  ScFormatFilter::Get().ScImportDif( rStrm, pImportDoc.get(), aRange.aStart, RTL_TEXTENCODING_IBM_850 );
2307 
2308  SCCOL nEndCol;
2309  SCROW nEndRow;
2310  pImportDoc->GetCellArea( nTab, nEndCol, nEndRow );
2311  // if there are no cells in the imported content, nEndCol/nEndRow may be before the start
2312  if ( nEndCol < aRange.aStart.Col() )
2313  nEndCol = aRange.aStart.Col();
2314  if ( nEndRow < aRange.aStart.Row() )
2315  nEndRow = aRange.aStart.Row();
2316  aRange.aEnd = ScAddress( nEndCol, nEndRow, nTab );
2317 
2318  bool bOk = StartPaste();
2319  if (bOk)
2320  {
2322  rDoc.DeleteAreaTab( aRange, nFlags );
2323  pImportDoc->CopyToDocument(aRange, nFlags, false, rDoc);
2324  EndPaste();
2325  }
2326 
2327  return bOk;
2328 }
2329 
2330 bool ScImportExport::RTF2Doc( SvStream& rStrm, const OUString& rBaseURL )
2331 {
2332  std::unique_ptr<ScEEAbsImport> pImp = ScFormatFilter::Get().CreateRTFImport( &rDoc, aRange );
2333  if (!pImp)
2334  return false;
2335  pImp->Read( rStrm, rBaseURL );
2336  aRange = pImp->GetRange();
2337 
2338  bool bOk = StartPaste();
2339  if (bOk)
2340  {
2342  rDoc.DeleteAreaTab( aRange, nFlags );
2343  pImp->WriteToDocument();
2344  EndPaste();
2345  }
2346  return bOk;
2347 }
2348 
2349 bool ScImportExport::HTML2Doc( SvStream& rStrm, const OUString& rBaseURL )
2350 {
2351  std::unique_ptr<ScEEAbsImport> pImp = ScFormatFilter::Get().CreateHTMLImport( &rDoc, rBaseURL, aRange);
2352  if (!pImp)
2353  return false;
2354  pImp->Read( rStrm, rBaseURL );
2355  aRange = pImp->GetRange();
2356 
2357  bool bOk = StartPaste();
2358  if (bOk)
2359  {
2360  // ScHTMLImport may call ScDocument::InitDrawLayer, resulting in
2361  // a Draw Layer but no Draw View -> create Draw Layer and View here
2362  if (pDocSh)
2363  pDocSh->MakeDrawLayer();
2364 
2366  rDoc.DeleteAreaTab( aRange, nFlags );
2367 
2368  if (pExtOptions)
2369  {
2370  // Pick up import options if available.
2371  LanguageType eLang = pExtOptions->GetLanguage();
2373  bool bSpecialNumber = pExtOptions->IsDetectSpecialNumber();
2374  pImp->WriteToDocument(false, 1.0, &aNumFormatter, bSpecialNumber);
2375  }
2376  else
2377  // Regular import, with no options.
2378  pImp->WriteToDocument();
2379 
2380  EndPaste();
2381  }
2382  return bOk;
2383 }
2384 
2385 #ifndef DISABLE_DYNLOADING
2386 
2387 extern "C" { static void thisModule() {} }
2388 
2389 #else
2390 
2391 extern "C" {
2393 }
2394 
2395 #endif
2396 
2397 typedef ScFormatFilterPlugin * (*FilterFn)();
2399 {
2400  static ScFormatFilterPlugin *plugin = [&]()
2401  {
2402 #ifndef DISABLE_DYNLOADING
2403  OUString sFilterLib(SVLIBRARY("scfilt"));
2404  static ::osl::Module aModule;
2405  bool bLoaded = aModule.is();
2406  if (!bLoaded)
2407  bLoaded = aModule.loadRelative(&thisModule, sFilterLib);
2408  if (!bLoaded)
2409  bLoaded = aModule.load(sFilterLib);
2410  if (bLoaded)
2411  {
2412  oslGenericFunction fn = aModule.getFunctionSymbol( "ScFilterCreate" );
2413  if (fn != nullptr)
2414  return reinterpret_cast<FilterFn>(fn)();
2415  }
2416  assert(false);
2417  return static_cast<ScFormatFilterPlugin*>(nullptr);
2418 #else
2419  return ScFilterCreate();
2420 #endif
2421  }();
2422 
2423  return *plugin;
2424 }
2425 
2426 // Precondition: pStr is guaranteed to be non-NULL and points to a 0-terminated
2427 // array.
2428 static const sal_Unicode* lcl_UnicodeStrChr( const sal_Unicode* pStr,
2429  sal_Unicode c )
2430 {
2431  while (*pStr)
2432  {
2433  if (*pStr == c)
2434  return pStr;
2435  ++pStr;
2436  }
2437  return nullptr;
2438 }
2439 
2441  : SvMemoryStream( const_cast<sal_Unicode *>(rStr.getStr()),
2442  rStr.getLength() * sizeof(sal_Unicode), StreamMode::READ)
2443 {
2444  SetStreamCharSet( RTL_TEXTENCODING_UNICODE );
2445 #ifdef OSL_BIGENDIAN
2446  SetEndian(SvStreamEndian::BIG);
2447 #else
2448  SetEndian(SvStreamEndian::LITTLE);
2449 #endif
2450 }
2451 
2452 OUString ReadCsvLine( SvStream &rStream, bool bEmbeddedLineBreak,
2453  OUString& rFieldSeparators, sal_Unicode cFieldQuote, sal_Unicode& rcDetectSep )
2454 {
2455  enum RetryState
2456  {
2457  FORBID,
2458  ALLOW,
2459  RETRY,
2460  RETRIED
2461  } eRetryState = (bEmbeddedLineBreak && rcDetectSep == 0 ? RetryState::ALLOW : RetryState::FORBID);
2462 
2463  sal_uInt64 nStreamPos = (eRetryState == RetryState::ALLOW ? rStream.Tell() : 0);
2464 
2465 Label_RetryWithNewSep:
2466 
2467  if (eRetryState == RetryState::RETRY)
2468  {
2469  eRetryState = RetryState::RETRIED;
2470  rStream.Seek( nStreamPos);
2471  }
2472 
2473  OUString aStr;
2475 
2476  if (bEmbeddedLineBreak)
2477  {
2478  const sal_Unicode* pSeps = rFieldSeparators.getStr();
2479 
2480  QuoteType eQuoteState = FIELDEND_QUOTE;
2481  bool bFieldStart = true;
2482 
2483  sal_Int32 nLastOffset = 0;
2484  sal_Int32 nQuotes = 0;
2485  while (!rStream.eof() && aStr.getLength() < nArbitraryLineLengthLimit)
2486  {
2487  const sal_Unicode * p = aStr.getStr() + nLastOffset;
2488  while (*p)
2489  {
2490  if (nQuotes)
2491  {
2492  if (*p == cFieldQuote)
2493  {
2494  if (bFieldStart)
2495  {
2496  ++nQuotes;
2497  bFieldStart = false;
2498  eQuoteState = FIELDSTART_QUOTE;
2499  }
2500  // Do not detect a FIELDSTART_QUOTE if not in
2501  // bFieldStart mode, in which case for unquoted content
2502  // we are in FIELDEND_QUOTE state.
2503  else if (eQuoteState != FIELDEND_QUOTE)
2504  {
2505  eQuoteState = lcl_isEscapedOrFieldEndQuote( nQuotes, p, pSeps, cFieldQuote, rcDetectSep);
2506 
2507  if (eRetryState == RetryState::ALLOW && rcDetectSep == ' ')
2508  {
2509  eRetryState = RetryState::RETRY;
2510  rFieldSeparators += OUString(' ');
2511  goto Label_RetryWithNewSep;
2512  }
2513 
2514  // DONTKNOW_QUOTE is an embedded unescaped quote we
2515  // don't count for pairing.
2516  if (eQuoteState != DONTKNOW_QUOTE)
2517  ++nQuotes;
2518  }
2519  }
2520  else if (eQuoteState == FIELDEND_QUOTE)
2521  {
2522  if (bFieldStart)
2523  // If blank is a separator it starts a field, if it
2524  // is not and thus maybe leading before quote we
2525  // are still at start of field regarding quotes.
2526  bFieldStart = (*p == ' ' || lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2527  else
2528  bFieldStart = (lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2529  }
2530  }
2531  else
2532  {
2533  if (*p == cFieldQuote && bFieldStart)
2534  {
2535  nQuotes = 1;
2536  eQuoteState = FIELDSTART_QUOTE;
2537  bFieldStart = false;
2538  }
2539  else if (eQuoteState == FIELDEND_QUOTE)
2540  {
2541  // This also skips leading blanks at beginning of line
2542  // if followed by a quote. It's debatable whether we
2543  // actually want that or not, but congruent with what
2544  // ScanNextFieldFromString() does.
2545  if (bFieldStart)
2546  bFieldStart = (*p == ' ' || lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2547  else
2548  bFieldStart = (lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2549  }
2550  }
2551  // A quote character inside a field content does not start
2552  // a quote.
2553  ++p;
2554  }
2555 
2556  if (nQuotes % 2 == 0)
2557  // We still have a (theoretical?) problem here if due to
2558  // nArbitraryLineLengthLimit we split a string right between a
2559  // doubled quote pair.
2560  break;
2561  else
2562  {
2563  nLastOffset = aStr.getLength();
2564  OUString aNext;
2566  aStr += "\n" + aNext;
2567  }
2568  }
2569  }
2570  return aStr;
2571 }
2572 
2573 /* 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
bool mbHandleApostrophe
When true, treat input with a leading apostrophe as an escape character for a numeric value content...
Definition: stringutil.hxx:91
#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
SvNumberFormatter * mpNumFormatter
Stores the pointer to the number formatter instance to be used during number format detection...
Definition: stringutil.hxx:70
bool ExportString(OUString &, SotClipboardFormatId)
Definition: impex.cxx:327
sal_Int16 getNumberOfMonthsInYear() const
std::unique_ptr< ContentProperties > pData
static weld::Window * GetActiveDialogParent()
Definition: docsh.cxx:2950
bool ReadUniOrByteStringLine(OUString &rStr, rtl_TextEncoding eSrcCharSet, sal_Int32 nMaxCodepointsToRead=0xFFFE)
bool Doc2Text(SvStream &)
Definition: impex.cxx:1689
bool mbOverwriting
Definition: impex.hxx:69
signed char sal_Int8
bool Doc2Dif(SvStream &)
Definition: impex.cxx:2292
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
long Long
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:2603
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:4542
static const sal_Unicode * lcl_ScanSylkFormula(const sal_Unicode *p, OUString &rString, SylkVersion eVersion)
Definition: impex.cxx:802
void SetDocumentModified()
Definition: docsh.cxx:2820
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:2398
SC_DLLPUBLIC void GetNumberFormat(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt32 &rFormat) const
Definition: document.cxx:3633
bool bIncludeFiltered
Definition: impex.hxx:60
ScAddress aEnd
Definition: address.hxx:500
bool bUndo
Definition: impex.hxx:63
SvStream & WriteOString(const OString &rStr)
bool Doc2HTML(SvStream &, const OUString &)
Definition: impex.cxx:2277
SC_DLLPUBLIC void SetValue(SCCOL nCol, SCROW nRow, SCTAB nTab, const double &rVal)
Definition: document.cxx:3450
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:4749
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:3423
virtual sal_uInt64 TellEnd() override
TextFormatPolicy meSetTextNumFormat
Determine when to set the 'Text' number format to the cell where the input string is being set...
Definition: stringutil.hxx:83
SC_DLLPUBLIC ScDocumentPool * GetPool()
Definition: document.cxx:6048
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2806
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:2285
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:2541
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:871
sal_uInt16 ExpandTwoDigitYear(sal_uInt16 nYear) const
#define SAL_MAX_UINT16
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
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:246
static OUString lcl_GetFixed(const OUString &rLine, sal_Int32 nStart, sal_Int32 nNext, bool &rbIsQuoted, bool &rbOverflowCell)
Definition: impex.cxx:1291
ScImportStringStream(const OUString &rStr)
Definition: impex.cxx:2440
sal_uInt32 GetStandardIndex(LanguageType eLnge=LANGUAGE_DONTKNOW)
static void thisModule()
Definition: impex.cxx:2387
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:3478
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:2068
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
sal_uInt64 remainingSize()
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:2349
OUString maFilterOptions
Definition: impex.hxx:54
bool IsClipboard() const
Definition: document.hxx:1532
double getLocalDateTime() const
SC_DLLPUBLIC double GetValue(const ScAddress &rPos) const
Definition: document.cxx:3620
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
SC_DLLPUBLIC bool SetEditText(const ScAddress &rPos, std::unique_ptr< EditTextObject > pEditText)
This method manages the lifecycle of the passed edit text object.
Definition: document.cxx:3386
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:3355
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:679
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:870
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:598
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
bool PutandConvertEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge, LanguageType eNewLnge, bool bConvertDateOrder)
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:4491
void SelectTable(SCTAB nTab, bool bNew)
Definition: markdata.cxx:172
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > ScDocumentUniquePtr
Definition: document.hxx:2616
sal_Int16 SCCOL
Definition: types.hxx:21
InsertDeleteFlags
Definition: global.hxx:157
bool ValidCol(SCCOL nCol) const
Definition: document.hxx:873
Set Text number format only when the input string is considered a special number but we only want to ...
Definition: stringutil.hxx:51
StreamMode
ScSheetLimits & GetSheetLimits() const
Definition: document.hxx:872
SC_DLLPUBLIC 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:4755
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
OUString ScResId(const char *pId)
Definition: scdll.cxx:89
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:5283
~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:3757
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 Doc2Sylk(SvStream &)
Definition: impex.cxx:2136
ConversionMode mode
static void EmbeddedNullTreatment(OUString &rStr)
Definition: impex.cxx:1572
bool GetMatrixOrigin(const ScDocument &rDoc, ScAddress &rPos) const
bool mbApi
Definition: impex.hxx:67
ScRange aRange
Definition: impex.hxx:51
CellType meType
Definition: cellvalue.hxx:105
SvStreamEndian GetEndian() const
void SetNumberFormat(const ScAddress &rPos, sal_uInt32 nNumberFormat)
Definition: document.cxx:3681
ScDocument & rDoc
Definition: impex.hxx:49
sal_Int32 SCROW
Definition: types.hxx:17
bool bOverflowCell
Definition: impex.hxx:66
bool ValidRow(SCROW nRow) const
Definition: document.hxx:874
SC_DLLPUBLIC ScFormulaCell * SetFormulaCell(const ScAddress &rPos, ScFormulaCell *pCell)
Set formula cell, and transfer its ownership to the document.
Definition: documen2.cxx:1083
bool mbDetectNumberFormat
When true, we try to detect special number format (dates etc) from the input string, when false, we only try to detect a basic decimal number format.
Definition: stringutil.hxx:77
static ScTabViewShell * GetActiveViewShell()
Definition: tabvwsh4.cxx:1038
DoubledQuoteMode
Definition: impex.cxx:683
static sal_Unicode ToUpperAlpha(sal_Unicode c)
Definition: global.hxx:618
bool Sylk2Doc(SvStream &)
Definition: impex.cxx:1805
#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)
SC_DLLPUBLIC 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:2428
rtl_TextEncoding GetStreamCharSet() const
static SC_DLLPUBLIC const CharClass * getCharClassPtr()
Definition: global.cxx:1009
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:2330
double getLength(const B2DPolygon &rCandidate)
bool ImportString(const OUString &, SotClipboardFormatId)
Definition: impex.cxx:303
SvStream & WriteChar(char nChar)
#define SVLIBRARY(Base)
bool isValid() const
void loadDefaultCalendar(const css::lang::Locale &rLocale, bool bTimeZoneUTC=true)
const DateTime & getEpochStart() const
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:2299
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:2452
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1056
#define SAL_WARN(area, stream)
bool IsUndoEnabled() const
Definition: document.hxx:1533
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
SC_DLLPUBLIC void GetLanguage(LanguageType &rLatin, LanguageType &rCjk, LanguageType &rCtl) const
Definition: documen3.cxx:1965
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:1947
bool ExtText2Doc(SvStream &)
Definition: impex.cxx:1333
const Date & GetNullDate() const
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:1588
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:2556
ScFormatFilterPlugin *(* FilterFn)()
Definition: impex.cxx:2397
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)
virtual short run() override
Opens dialog if IsDialogEnabled() returns true.
Definition: warnbox.cxx:35
sal_uInt16 nPos
sal_Int16 SCTAB
Definition: types.hxx:22
void loadModuleIfNeeded(LanguageType nLang)
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
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
const sal_uInt8 SC_COL_YMD
Definition: csvcontrol.hxx:58
ScDocument & getDoc()
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo