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