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 maximum cell content length, 2*1024*64K=128M, and because it's
70 // sal_Unicode that's 256MB. If it's 2GB of data without LF we're out of luck
71 // anyway.
72 const sal_Int32 nArbitraryLineLengthLimit = 2 * MAXCOLCOUNT * 65536;
73 
74 namespace
75 {
76  const char SYLK_LF[] = "\x1b :";
77 
78  bool lcl_IsEndianSwap( const SvStream& rStrm )
79  {
80  #ifdef OSL_BIGENDIAN
81  return rStrm.GetEndian() != SvStreamEndian::BIG;
82  #else
83  return rStrm.GetEndian() != SvStreamEndian::LITTLE;
84  #endif
85  }
86 }
87 
88 namespace {
89 
90 enum class SylkVersion
91 {
92  SCALC3, // Wrote wrongly quoted strings and unescaped semicolons.
93  OOO32, // Correct strings, plus multiline content.
94  OWN, // Place our new versions, if any, before this value.
95  OTHER // Assume that aliens wrote correct strings.
96 };
97 
98 }
99 
100 // Whole document without Undo
102  : pDocSh( dynamic_cast< ScDocShell* >(p->GetDocumentShell()) ), pDoc( p ),
103  nSizeLimit( 0 ), nMaxImportRow(!utl::ConfigManager::IsFuzzing() ? pDoc->MaxRow() : SCROWS32K),
104  cSep( '\t' ), cStr( '"' ),
105  bFormulas( false ), bIncludeFiltered( true ),
106  bAll( true ), bSingle( true ), bUndo( false ),
107  bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
108  mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ),
109  mExportTextOptions()
110 {
111  pUndoDoc = nullptr;
112  pExtOptions = nullptr;
113 }
114 
115 // Insert am current cell without range(es)
117  : pDocSh( dynamic_cast< ScDocShell* >(p->GetDocumentShell()) ), pDoc( p ),
118  aRange( rPt ),
119  nSizeLimit( 0 ), nMaxImportRow(!utl::ConfigManager::IsFuzzing() ? pDoc->MaxRow() : SCROWS32K),
120  cSep( '\t' ), cStr( '"' ),
121  bFormulas( false ), bIncludeFiltered( true ),
122  bAll( false ), bSingle( true ), bUndo( pDocSh != nullptr ),
123  bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
124  mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ),
125  mExportTextOptions()
126 {
127  pUndoDoc = nullptr;
128  pExtOptions = nullptr;
129 }
130 
131 // ctor with a range is only used for export
134  : pDocSh( dynamic_cast<ScDocShell* >(p->GetDocumentShell()) ), pDoc( p ),
135  aRange( r ),
136  nSizeLimit( 0 ), nMaxImportRow(!utl::ConfigManager::IsFuzzing() ? pDoc->MaxRow() : SCROWS32K),
137  cSep( '\t' ), cStr( '"' ),
138  bFormulas( false ), bIncludeFiltered( true ),
139  bAll( false ), bSingle( false ), bUndo( pDocSh != nullptr ),
140  bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
141  mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ),
142  mExportTextOptions()
143 {
144  pUndoDoc = nullptr;
145  pExtOptions = nullptr;
146  // Only one sheet (table) supported
148 }
149 
150 // Evaluate input string - either range, cell or the whole document (when error)
151 // If a View exists, the TabNo of the view will be used.
152 ScImportExport::ScImportExport( ScDocument* p, const OUString& rPos )
153  : pDocSh( dynamic_cast< ScDocShell* >(p->GetDocumentShell()) ), pDoc( p ),
154  nSizeLimit( 0 ), nMaxImportRow(!utl::ConfigManager::IsFuzzing() ? pDoc->MaxRow() : SCROWS32K),
155  cSep( '\t' ), cStr( '"' ),
156  bFormulas( false ), bIncludeFiltered( true ),
157  bAll( false ), bSingle( true ), bUndo( pDocSh != nullptr ),
158  bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
159  mbApi( true ), mbImportBroadcast(false), mbOverwriting( false ),
160  mExportTextOptions()
161 {
162  pUndoDoc = nullptr;
163  pExtOptions = nullptr;
164 
165  SCTAB nTab = ScDocShell::GetCurTab();
166  aRange.aStart.SetTab( nTab );
167  OUString aPos( rPos );
168  // Named range?
169  ScRangeName* pRange = pDoc->GetRangeName();
170  if (pRange)
171  {
172  const ScRangeData* pData = pRange->findByUpperName(ScGlobal::getCharClassPtr()->uppercase(aPos));
173  if (pData)
174  {
175  if( pData->HasType( ScRangeData::Type::RefArea )
177  || pData->HasType( ScRangeData::Type::AbsPos ) )
178  {
179  pData->GetSymbol(aPos);
180  }
181  }
182  }
184  // Range?
185  if (aRange.Parse(aPos, pDoc, eConv) & ScRefFlags::VALID)
186  bSingle = false;
187  // Cell?
188  else if (aRange.aStart.Parse(aPos, pDoc, eConv) & ScRefFlags::VALID)
190  else
191  bAll = true;
192 }
193 
194 ScImportExport::~ScImportExport() COVERITY_NOEXCEPT_FALSE
195 {
196  pUndoDoc.reset();
197  pExtOptions.reset();
198 }
199 
201 {
202  if ( pExtOptions )
203  *pExtOptions = rOpt;
204  else
205  pExtOptions.reset(new ScAsciiOptions( rOpt ));
206 
207  // "normal" Options
208 
210  cStr = rOpt.GetTextSep();
211 }
212 
213 void ScImportExport::SetFilterOptions(const OUString& rFilterOptions)
214 {
215  maFilterOptions = rFilterOptions;
216 }
217 
219 {
220  return nFormat == SotClipboardFormatId::STRING
221  || nFormat == SotClipboardFormatId::STRING_TSVC
222  || nFormat == SotClipboardFormatId::SYLK
223  || nFormat == SotClipboardFormatId::LINK
224  || nFormat == SotClipboardFormatId::HTML
225  || nFormat == SotClipboardFormatId::HTML_SIMPLE
226  || nFormat == SotClipboardFormatId::DIF;
227 }
228 
229 // Prepare for Undo
231 {
232  if ( !bAll )
233  {
234  ScEditableTester aTester( pDoc, aRange );
235  if ( !aTester.IsEditable() )
236  {
238  std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
239  VclMessageType::Info, VclButtonsType::Ok,
240  ScResId(aTester.GetMessageId())));
241  xInfoBox->run();
242  return false;
243  }
244  }
245  if( bUndo && pDocSh && pDoc->IsUndoEnabled())
246  {
247  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
248  pUndoDoc->InitUndo( pDoc, aRange.aStart.Tab(), aRange.aEnd.Tab() );
250  }
251  return true;
252 }
253 
254 // Create Undo/Redo actions, Invalidate/Repaint
255 void ScImportExport::EndPaste(bool bAutoRowHeight)
256 {
257  bool bHeight = bAutoRowHeight && pDocSh && pDocSh->AdjustRowHeight(
259 
260  if( pUndoDoc && pDoc->IsUndoEnabled() && pDocSh )
261  {
263  pRedoDoc->InitUndo( pDoc, aRange.aStart.Tab(), aRange.aEnd.Tab() );
265  ScMarkData aDestMark(pRedoDoc->GetSheetLimits());
266  aDestMark.SetMarkArea(aRange);
268  std::make_unique<ScUndoPaste>(pDocSh, aRange, aDestMark, std::move(pUndoDoc), std::move(pRedoDoc), InsertDeleteFlags::ALL, nullptr));
269  }
270  pUndoDoc.reset();
271  if( pDocSh )
272  {
273  if (!bHeight)
276  }
278  if ( pViewSh )
279  pViewSh->UpdateInputHandler();
280 
281 }
282 
283 bool ScImportExport::ExportData( const OUString& rMimeType,
284  css::uno::Any & rValue )
285 {
286  SvMemoryStream aStrm;
287  // mba: no BaseURL for data exchange
288  if( ExportStream( aStrm, OUString(),
290  {
291  aStrm.WriteUChar( 0 );
292  rValue <<= css::uno::Sequence< sal_Int8 >(
293  static_cast<sal_Int8 const *>(aStrm.GetData()),
294  aStrm.TellEnd() );
295  return true;
296  }
297  return false;
298 }
299 
300 bool ScImportExport::ImportString( const OUString& rText, SotClipboardFormatId nFmt )
301 {
302  switch ( nFmt )
303  {
304  // formats supporting unicode
305  case SotClipboardFormatId::STRING :
306  case SotClipboardFormatId::STRING_TSVC :
307  {
308  ScImportStringStream aStrm( rText);
309  return ImportStream( aStrm, OUString(), nFmt );
310  // ImportStream must handle RTL_TEXTENCODING_UNICODE
311  }
312  default:
313  {
314  rtl_TextEncoding eEnc = osl_getThreadTextEncoding();
315  OString aTmp( rText.getStr(), rText.getLength(), eEnc );
316  SvMemoryStream aStrm( const_cast<char *>(aTmp.getStr()), aTmp.getLength() * sizeof(char), StreamMode::READ );
317  aStrm.SetStreamCharSet( eEnc );
318  SetNoEndianSwap( aStrm );
319  return ImportStream( aStrm, OUString(), nFmt );
320  }
321  }
322 }
323 
325 {
326  if ( nFmt != SotClipboardFormatId::STRING && nFmt != SotClipboardFormatId::STRING_TSVC )
327  {
328  SAL_WARN("sc.ui", "ScImportExport::ExportString: Unicode not supported for other formats than SotClipboardFormatId::STRING[_TSV]");
329  rtl_TextEncoding eEnc = osl_getThreadTextEncoding();
330  OString aTmp;
331  bool bOk = ExportByteString( aTmp, eEnc, nFmt );
332  rText = OStringToOUString( aTmp, eEnc );
333  return bOk;
334  }
335  // nSizeLimit not needed for OUString
336 
337  SvMemoryStream aStrm;
338  aStrm.SetStreamCharSet( RTL_TEXTENCODING_UNICODE );
339  SetNoEndianSwap( aStrm );
340  // mba: no BaseURL for data exc
341  if( ExportStream( aStrm, OUString(), nFmt ) )
342  {
343  aStrm.WriteUInt16( 0 );
344  rText = OUString( static_cast<const sal_Unicode*>(aStrm.GetData()) );
345  return true;
346  }
347  rText.clear();
348  return false;
349 
350  // ExportStream must handle RTL_TEXTENCODING_UNICODE
351 }
352 
353 bool ScImportExport::ExportByteString( OString& rText, rtl_TextEncoding eEnc, SotClipboardFormatId nFmt )
354 {
355  OSL_ENSURE( eEnc != RTL_TEXTENCODING_UNICODE, "ScImportExport::ExportByteString: Unicode not supported" );
356  if ( eEnc == RTL_TEXTENCODING_UNICODE )
357  eEnc = osl_getThreadTextEncoding();
358 
359  if (!nSizeLimit)
361 
362  SvMemoryStream aStrm;
363  aStrm.SetStreamCharSet( eEnc );
364  SetNoEndianSwap( aStrm );
365  // mba: no BaseURL for data exchange
366  if( ExportStream( aStrm, OUString(), nFmt ) )
367  {
368  aStrm.WriteChar( 0 );
369  if( aStrm.TellEnd() <= nSizeLimit )
370  {
371  rText = static_cast<const char*>(aStrm.GetData());
372  return true;
373  }
374  }
375  rText.clear();
376  return false;
377 }
378 
379 bool ScImportExport::ImportStream( SvStream& rStrm, const OUString& rBaseURL, SotClipboardFormatId nFmt )
380 {
381  if( nFmt == SotClipboardFormatId::STRING || nFmt == SotClipboardFormatId::STRING_TSVC )
382  {
383  if( ExtText2Doc( rStrm ) ) // evaluate pExtOptions
384  return true;
385  }
386  if( nFmt == SotClipboardFormatId::SYLK )
387  {
388  if( Sylk2Doc( rStrm ) )
389  return true;
390  }
391  if( nFmt == SotClipboardFormatId::DIF )
392  {
393  if( Dif2Doc( rStrm ) )
394  return true;
395  }
396  if( nFmt == SotClipboardFormatId::RTF || nFmt == SotClipboardFormatId::RICHTEXT )
397  {
398  if( RTF2Doc( rStrm, rBaseURL ) )
399  return true;
400  }
401  if( nFmt == SotClipboardFormatId::LINK )
402  return true; // Link-Import?
403  if ( nFmt == SotClipboardFormatId::HTML )
404  {
405  if( HTML2Doc( rStrm, rBaseURL ) )
406  return true;
407  }
408  if ( nFmt == SotClipboardFormatId::HTML_SIMPLE )
409  {
410  MSE40HTMLClipFormatObj aMSE40ClpObj; // needed to skip the header data
411  SvStream* pHTML = aMSE40ClpObj.IsValid( rStrm );
412  if ( pHTML && HTML2Doc( *pHTML, rBaseURL ) )
413  return true;
414  }
415 
416  return false;
417 }
418 
419 bool ScImportExport::ExportStream( SvStream& rStrm, const OUString& rBaseURL, SotClipboardFormatId nFmt )
420 {
421  if( nFmt == SotClipboardFormatId::STRING || nFmt == SotClipboardFormatId::STRING_TSVC )
422  {
423  if( Doc2Text( rStrm ) )
424  return true;
425  }
426  if( nFmt == SotClipboardFormatId::SYLK )
427  {
428  if( Doc2Sylk( rStrm ) )
429  return true;
430  }
431  if( nFmt == SotClipboardFormatId::DIF )
432  {
433  if( Doc2Dif( rStrm ) )
434  return true;
435  }
436  if( nFmt == SotClipboardFormatId::LINK && !bAll )
437  {
438  OUString aDocName;
439  if ( pDoc->IsClipboard() )
440  aDocName = ScGlobal::GetClipDocName();
441  else
442  {
443  SfxObjectShell* pShell = pDoc->GetDocumentShell();
444  if (pShell)
445  aDocName = pShell->GetTitle( SFX_TITLE_FULLNAME );
446  }
447 
448  OSL_ENSURE( !aDocName.isEmpty(), "ClipBoard document has no name! :-/" );
449  if( !aDocName.isEmpty() )
450  {
451  // Always use Calc A1 syntax for paste link.
452  OUString aRefName;
454  if( bSingle )
456  else
457  {
458  if( aRange.aStart.Tab() != aRange.aEnd.Tab() )
459  nFlags |= ScRefFlags::TAB2_3D;
460  aRefName = aRange.Format(*pDoc, nFlags, formula::FormulaGrammar::CONV_OOO);
461  }
462  OUString aAppName = Application::GetAppName();
463 
464  // extra bits are used to tell the client to prefer external
465  // reference link.
466 
467  WriteUnicodeOrByteString( rStrm, aAppName, true );
468  WriteUnicodeOrByteString( rStrm, aDocName, true );
469  WriteUnicodeOrByteString( rStrm, aRefName, true );
470  WriteUnicodeOrByteString( rStrm, "calc:extref", true );
471  if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
472  rStrm.WriteUInt16( 0 );
473  else
474  rStrm.WriteChar( 0 );
475  return rStrm.GetError() == ERRCODE_NONE;
476  }
477  }
478  if( nFmt == SotClipboardFormatId::HTML )
479  {
480  if( Doc2HTML( rStrm, rBaseURL ) )
481  return true;
482  }
483  if( nFmt == SotClipboardFormatId::RTF || nFmt == SotClipboardFormatId::RICHTEXT )
484  {
485  if( Doc2RTF( rStrm ) )
486  return true;
487  }
488 
489  return false;
490 }
491 
492 void ScImportExport::WriteUnicodeOrByteString( SvStream& rStrm, const OUString& rString, bool bZero )
493 {
494  rtl_TextEncoding eEnc = rStrm.GetStreamCharSet();
495  if ( eEnc == RTL_TEXTENCODING_UNICODE )
496  {
497  if ( !lcl_IsEndianSwap( rStrm ) )
498  rStrm.WriteBytes(rString.getStr(), rString.getLength() * sizeof(sal_Unicode));
499  else
500  {
501  const sal_Unicode* p = rString.getStr();
502  const sal_Unicode* const pStop = p + rString.getLength();
503  while ( p < pStop )
504  {
505  rStrm.WriteUInt16( *p );
506  }
507  }
508  if ( bZero )
509  rStrm.WriteUInt16( 0 );
510  }
511  else
512  {
513  OString aByteStr(OUStringToOString(rString, eEnc));
514  rStrm.WriteOString( aByteStr );
515  if ( bZero )
516  rStrm.WriteChar( 0 );
517  }
518 }
519 
520 // This function could be replaced by endlub()
522 {
523  if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
524  { // same as endl() but unicode
525  switch ( rStrm.GetLineDelimiter() )
526  {
527  case LINEEND_CR :
528  rStrm.WriteUInt16( '\r' );
529  break;
530  case LINEEND_LF :
531  rStrm.WriteUInt16( '\n' );
532  break;
533  default:
534  rStrm.WriteUInt16( '\r' ).WriteUInt16( '\n' );
535  }
536  }
537  else
538  endl( rStrm );
539 }
540 
542 {
543 #ifdef OSL_BIGENDIAN
544  rStrm.SetEndian( SvStreamEndian::BIG );
545 #else
546  rStrm.SetEndian( SvStreamEndian::LITTLE );
547 #endif
548 }
549 
550 namespace {
551 
553 {
554  FIELDSTART_QUOTE,
555  FIRST_QUOTE,
556  SECOND_QUOTE,
557  FIELDEND_QUOTE,
558  DONTKNOW_QUOTE
559 };
560 
561 }
562 
571 static QuoteType lcl_isFieldEndQuote( const sal_Unicode* p, const sal_Unicode* pSeps, sal_Unicode& rcDetectSep )
572 {
573  // Due to broken CSV generators that don't double embedded quotes check if
574  // a field separator immediately or with trailing spaces follows the quote,
575  // only then end the field, or at end of string.
576  const sal_Unicode cBlank = ' ';
577  if (p[1] == cBlank && ScGlobal::UnicodeStrChr( pSeps, cBlank))
578  return FIELDEND_QUOTE;
579  // Detect a possible blank separator if it's not already in the list (which
580  // was checked right above for p[1]==cBlank).
581  if (p[1] == cBlank && !rcDetectSep && p[2] && p[2] != cBlank)
582  rcDetectSep = cBlank;
583  while (p[1] == cBlank)
584  ++p;
585  if (!p[1] || ScGlobal::UnicodeStrChr( pSeps, p[1]))
586  return FIELDEND_QUOTE;
587  return DONTKNOW_QUOTE;
588 }
589 
611 static QuoteType lcl_isEscapedOrFieldEndQuote( sal_Int32 nQuotes, const sal_Unicode* p,
612  const sal_Unicode* pSeps, sal_Unicode cStr, sal_Unicode& rcDetectSep )
613 {
614  if ((nQuotes % 2) == 0)
615  {
616  if (p[-1] == cStr)
617  return SECOND_QUOTE;
618  else
619  {
620  SAL_WARN( "sc", "lcl_isEscapedOrFieldEndQuote: really want a FIELDSTART_QUOTE?");
621  return FIELDSTART_QUOTE;
622  }
623  }
624  if (p[1] == cStr)
625  return FIRST_QUOTE;
626  return lcl_isFieldEndQuote( p, pSeps, rcDetectSep);
627 }
628 
633 static bool lcl_appendLineData( OUString& rField, const sal_Unicode* p1, const sal_Unicode* p2 )
634 {
635  OSL_ENSURE( rField.getLength() + (p2 - p1) <= SAL_MAX_UINT16, "lcl_appendLineData: data overflow");
636  if (rField.getLength() + (p2 - p1) <= SAL_MAX_UINT16)
637  {
638  rField += OUString( p1, sal::static_int_cast<sal_Int32>( p2 - p1 ) );
639  return true;
640  }
641  else
642  {
643  rField += OUString( p1, SAL_MAX_UINT16 - rField.getLength() );
644  return false;
645  }
646 }
647 
648 namespace {
649 
651 {
652  KEEP_ALL, // both are taken, additionally start and end quote are included in string
653  ESCAPE, // escaped quote, one is taken, one ignored
654 };
655 
656 }
657 
658 static const sal_Unicode* lcl_ScanString( const sal_Unicode* p, OUString& rString,
659  const sal_Unicode* pSeps, sal_Unicode cStr, DoubledQuoteMode eMode, bool& rbOverflowCell )
660 {
661  if (eMode != DoubledQuoteMode::KEEP_ALL)
662  p++;
663  bool bCont;
664  do
665  {
666  bCont = false;
667  const sal_Unicode* p0 = p;
668  for( ;; )
669  {
670  if( !*p )
671  break;
672  if( *p == cStr )
673  {
674  if ( *++p != cStr )
675  {
676  // break or continue for loop
677  if (eMode == DoubledQuoteMode::ESCAPE)
678  {
679  sal_Unicode cDetectSep = 0xffff; // No separator detection here.
680  if (lcl_isFieldEndQuote( p-1, pSeps, cDetectSep) == FIELDEND_QUOTE)
681  break;
682  else
683  continue;
684  }
685  else
686  break;
687  }
688  // doubled quote char
689  switch ( eMode )
690  {
691  case DoubledQuoteMode::KEEP_ALL :
692  p++; // both for us (not breaking for-loop)
693  break;
694  case DoubledQuoteMode::ESCAPE :
695  p++; // one for us (breaking for-loop)
696  bCont = true; // and more
697  break;
698  }
699  if ( eMode == DoubledQuoteMode::ESCAPE )
700  break;
701  }
702  else
703  p++;
704  }
705  if ( p0 < p )
706  {
707  if (!lcl_appendLineData( rString, p0, ((eMode != DoubledQuoteMode::KEEP_ALL && (*p || *(p-1) == cStr)) ? p-1 : p)))
708  rbOverflowCell = true;
709  }
710  } while ( bCont );
711  return p;
712 }
713 
714 static void lcl_UnescapeSylk( OUString & rString, SylkVersion eVersion )
715 {
716  // Older versions didn't escape the semicolon.
717  // Older versions quoted the string and doubled embedded quotes, but not
718  // the semicolons, which was plain wrong.
719  if (eVersion >= SylkVersion::OOO32)
720  rString = rString.replaceAll(";;", ";");
721  else
722  rString = rString.replaceAll("\"\"", "\"");
723 
724  rString = rString.replaceAll(SYLK_LF, "\n");
725 }
726 
728  OUString& rString, SylkVersion eVersion )
729 {
730  const sal_Unicode* pStartQuote = p;
731  const sal_Unicode* pEndQuote = nullptr;
732  while( *(++p) )
733  {
734  if( *p == '"' )
735  {
736  pEndQuote = p;
737  if (eVersion >= SylkVersion::OOO32)
738  {
739  if (*(p+1) == ';')
740  {
741  if (*(p+2) == ';')
742  {
743  p += 2; // escaped ';'
744  pEndQuote = nullptr;
745  }
746  else
747  break; // end field
748  }
749  }
750  else
751  {
752  if (*(p+1) == '"')
753  {
754  ++p; // escaped '"'
755  pEndQuote = nullptr;
756  }
757  else if (*(p+1) == ';')
758  break; // end field
759  }
760  }
761  }
762  if (!pEndQuote)
763  pEndQuote = p; // Take all data as string.
764  rString += OUString(pStartQuote + 1, sal::static_int_cast<sal_Int32>( pEndQuote - pStartQuote - 1 ) );
765  lcl_UnescapeSylk( rString, eVersion);
766  return p;
767 }
768 
770  OUString& rString, SylkVersion eVersion )
771 {
772  const sal_Unicode* pStart = p;
773  if (eVersion >= SylkVersion::OOO32)
774  {
775  while (*p)
776  {
777  if (*p == ';')
778  {
779  if (*(p+1) == ';')
780  ++p; // escaped ';'
781  else
782  break; // end field
783  }
784  ++p;
785  }
786  rString += OUString( pStart, sal::static_int_cast<sal_Int32>( p - pStart));
787  lcl_UnescapeSylk( rString, eVersion);
788  }
789  else
790  {
791  // Nasty. If in old versions the formula contained a semicolon, it was
792  // quoted and embedded quotes were doubled, but semicolons were not. If
793  // there was no semicolon, it could still contain quotes and doubled
794  // embedded quotes if it was something like ="a""b", which was saved as
795  // E"a""b" as is and has to be preserved, even if older versions
796  // couldn't even load it correctly. However, theoretically another
797  // field might follow and thus the line contain a semicolon again, such
798  // as ...;E"a""b";...
799  bool bQuoted = false;
800  if (*p == '"')
801  {
802  // May be a quoted expression or just a string constant expression
803  // with quotes.
804  while (*(++p))
805  {
806  if (*p == '"')
807  {
808  if (*(p+1) == '"')
809  ++p; // escaped '"'
810  else
811  break; // closing '"', had no ';' yet
812  }
813  else if (*p == ';')
814  {
815  bQuoted = true; // ';' within quoted expression
816  break;
817  }
818  }
819  p = pStart;
820  }
821  if (bQuoted)
822  p = lcl_ScanSylkString( p, rString, eVersion);
823  else
824  {
825  while (*p && *p != ';')
826  ++p;
827  rString += OUString( pStart, sal::static_int_cast<sal_Int32>( p - pStart));
828  }
829  }
830  return p;
831 }
832 
833 static void lcl_DoubleEscapeChar( OUString& rString, sal_Unicode cStr )
834 {
835  sal_Int32 n = 0;
836  while( ( n = rString.indexOf( cStr, n ) ) != -1 )
837  {
838  rString = rString.replaceAt( n, 0, OUString(cStr) );
839  n += 2;
840  }
841 }
842 
843 static void lcl_WriteString( SvStream& rStrm, OUString& rString, sal_Unicode cQuote, sal_Unicode cEsc )
844 {
845  if (cEsc)
846  lcl_DoubleEscapeChar( rString, cEsc );
847 
848  if (cQuote)
849  {
850  rString = OUStringChar(cQuote) + rString + OUStringChar(cQuote);
851  }
852 
854 }
855 
856 static void lcl_WriteSimpleString( SvStream& rStrm, const OUString& rString )
857 {
859 }
860 
862 {
863  bool bOk = true;
864 
865  sal_Unicode pSeps[2];
866  pSeps[0] = cSep;
867  pSeps[1] = 0;
868 
869  ScSetStringParam aSetStringParam;
870  aSetStringParam.mbCheckLinkFormula = true;
871 
872  SCCOL nStartCol = aRange.aStart.Col();
873  SCROW nStartRow = aRange.aStart.Row();
874  SCCOL nEndCol = aRange.aEnd.Col();
875  SCROW nEndRow = aRange.aEnd.Row();
876  sal_uLong nOldPos = rStrm.Tell();
877  rStrm.StartReadingUnicodeText( rStrm.GetStreamCharSet() );
878  bool bData = !bSingle;
879  if( !bSingle)
880  bOk = StartPaste();
881 
882  while( bOk )
883  {
884  OUString aLine;
885  OUString aCell;
886  SCROW nRow = nStartRow;
887  rStrm.Seek( nOldPos );
888  for( ;; )
889  {
891  // tdf#125440 When inserting tab separated string, consider quotes as field markers
892  DoubledQuoteMode mode = aLine.indexOf("\t") >= 0 ? DoubledQuoteMode::ESCAPE : DoubledQuoteMode::KEEP_ALL;
893  if( rStrm.eof() )
894  break;
895  SCCOL nCol = nStartCol;
896  const sal_Unicode* p = aLine.getStr();
897  while( *p )
898  {
899  aCell.clear();
900  const sal_Unicode* q = p;
901  while (*p && *p != cSep)
902  {
903  // Always look for a pairing quote and ignore separator in between.
904  while (*p && *p == cStr)
905  q = p = lcl_ScanString( p, aCell, pSeps, cStr, mode, bOverflowCell );
906  // All until next separator or quote.
907  while (*p && *p != cSep && *p != cStr)
908  ++p;
909  if (!lcl_appendLineData( aCell, q, p))
910  bOverflowCell = true; // display warning on import
911  q = p;
912  }
913  if (*p)
914  ++p;
915  if (pDoc->ValidCol(nCol) && pDoc->ValidRow(nRow) )
916  {
917  if( bSingle )
918  {
919  if (nCol>nEndCol) nEndCol = nCol;
920  if (nRow>nEndRow) nEndRow = nRow;
921  }
922  if( bData && nCol <= nEndCol && nRow <= nEndRow )
923  pDoc->SetString( nCol, nRow, aRange.aStart.Tab(), aCell, &aSetStringParam );
924  }
925  else // too many columns/rows
926  {
927  if (!pDoc->ValidRow(nRow))
928  bOverflowRow = true; // display warning on import
929  if (!pDoc->ValidCol(nCol))
930  bOverflowCol = true; // display warning on import
931  }
932  ++nCol;
933  }
934  ++nRow;
935  }
936 
937  if( !bData )
938  {
939  aRange.aEnd.SetCol( nEndCol );
940  aRange.aEnd.SetRow( nEndRow );
941  bOk = StartPaste();
942  bData = true;
943  }
944  else
945  break;
946  }
947 
948  EndPaste();
949  if (bOk && mbImportBroadcast)
950  {
951  pDoc->BroadcastCells(aRange, SfxHintId::ScDataChanged);
953  }
954 
955  return bOk;
956 }
957 
958 // Extended Ascii-Import
959 
960 static bool lcl_PutString(
961  ScDocumentImport& rDocImport, bool bUseDocImport,
962  SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString& rStr, sal_uInt8 nColFormat,
963  SvNumberFormatter* pFormatter, bool bDetectNumFormat, bool bSkipEmptyCells,
964  const ::utl::TransliterationWrapper& rTransliteration, CalendarWrapper& rCalendar,
965  const ::utl::TransliterationWrapper* pSecondTransliteration, CalendarWrapper* pSecondCalendar )
966 {
967  ScDocument* pDoc = &rDocImport.getDoc();
968  bool bMultiLine = false;
969  if ( nColFormat == SC_COL_SKIP || !pDoc->ValidCol(nCol) || !pDoc->ValidRow(nRow) )
970  return bMultiLine;
971  if ( rStr.isEmpty() )
972  {
973  if ( !bSkipEmptyCells )
974  { // delete destination cell
975  if ( bUseDocImport )
976  rDocImport.setAutoInput(ScAddress(nCol, nRow, nTab), rStr );
977  else
978  pDoc->SetString( nCol, nRow, nTab, rStr );
979  }
980  return false;
981  }
982 
983  if ( nColFormat == SC_COL_TEXT )
984  {
985  double fDummy;
986  sal_uInt32 nIndex = 0;
987  if (pFormatter->IsNumberFormat(rStr, nIndex, fDummy))
988  {
989  // Set the format of this cell to Text.
990  sal_uInt32 nFormat = pFormatter->GetStandardFormat(SvNumFormatType::TEXT);
991  ScPatternAttr aNewAttrs(pDoc->GetPool());
992  SfxItemSet& rSet = aNewAttrs.GetItemSet();
993  rSet.Put( SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat) );
994  pDoc->ApplyPattern(nCol, nRow, nTab, aNewAttrs);
995 
996  }
997  if ( bUseDocImport )
998  {
999  if(ScStringUtil::isMultiline(rStr))
1000  {
1001  ScFieldEditEngine& rEngine = pDoc->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  pDoc->SetTextCell(ScAddress(nCol, nRow, nTab), rStr);
1014  return bMultiLine;
1015  }
1016  }
1017 
1018  if ( nColFormat == SC_COL_ENGLISH )
1019  {
1021 
1022  SvNumberFormatter* pDocFormatter = pDoc->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  pDoc->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 = pDoc->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  pDoc->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  pDoc->SetValue( aPos, fDays );
1224  pDoc->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  pDoc->SetString( nCol, nRow, nTab, rStr, &aParam );
1245  }
1246  else
1247  {
1248  bMultiLine = true;
1249  ScFieldEditEngine& rEngine = pDoc->GetEditEngine();
1250  rEngine.SetTextCurrentDefaults(rStr);
1251  if ( bUseDocImport )
1252  rDocImport.setEditCell(ScAddress(nCol, nRow, nTab), rEngine.CreateTextObject());
1253  else
1254  pDoc->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 <= SAL_MAX_UINT16);
1278  OSL_ENSURE( bFits, "lcl_GetFixed: line doesn't fit into data");
1279  if (bFits)
1280  return rLine.copy(nStart+1, std::max< sal_Int32 >(0, nSpace-nStart-2));
1281  else
1282  {
1283  rbOverflowCell = true;
1284  return rLine.copy(nStart+1, SAL_MAX_UINT16);
1285  }
1286  }
1287  else
1288  {
1289  bool bFits = (nSpace - nStart <= SAL_MAX_UINT16);
1290  OSL_ENSURE( bFits, "lcl_GetFixed: line doesn't fit into data");
1291  if (bFits)
1292  return rLine.copy(nStart, nSpace-nStart);
1293  else
1294  {
1295  rbOverflowCell = true;
1296  return rLine.copy(nStart, SAL_MAX_UINT16);
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  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(*pDoc);
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 > pDoc->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 <= pDoc->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 > pDoc->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 <= pDoc->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 > pDoc->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), pDoc->MaxCol());
1491 
1492  if (bDetermineRange)
1493  {
1494  aRange.aEnd.SetCol( nEndCol );
1495  aRange.aEnd.SetRow( nRow );
1496 
1497  if ( !mbApi && nStartCol != nEndCol &&
1498  !pDoc->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  pDoc->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 (!pDoc->GetClipParam().isMultiRange() && nStartTab == nEndTab)
1662  if (!pDoc->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  pDoc->InitColumnBlockPosition( blockPos[ i - nStartCol ], nStartTab, i );
1673  for (nRow = nStartRow; nRow <= nEndRow; nRow++)
1674  {
1675  if (bIncludeFiltered || !pDoc->RowFiltered( nRow, nStartTab ))
1676  {
1677  for (nCol = nStartCol; nCol <= nEndCol; nCol++)
1678  {
1679  ScAddress aPos(nCol, nRow, nStartTab);
1680  sal_uInt32 nNumFmt = pDoc->GetNumberFormat(aPos);
1681  SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1682 
1683  ScRefCellValue aCell(*pDoc, 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  Color* pColor;
1699  ScCellFormat::GetString(aCell, nNumFmt, aCellStr, &pColor, *pFormatter, pDoc);
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  Color* pColor;
1723  ScCellFormat::GetString(aCell, nNumFmt, aCellStr, &pColor, *pFormatter, pDoc);
1724  lcl_WriteSimpleString( rStrm, aCellStr );
1725  }
1726  break;
1727  case CELLTYPE_NONE:
1728  break;
1729  default:
1730  {
1731  Color* pColor;
1732  ScCellFormat::GetString(aCell, nNumFmt, aCellStr, &pColor, *pFormatter, pDoc);
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 || pDoc->MaxCol() < nCol)
1826  {
1827  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;X invalid nCol=" << nCol);
1828  nCol = std::max<SCCOL>(0, std::min<SCCOL>(nCol, pDoc->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 || pDoc->MaxCol() < nRefCol)
1850  {
1851  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;C invalid nRefCol=" << nRefCol);
1852  nRefCol = std::max<SCCOL>(0, std::min<SCCOL>(nRefCol, pDoc->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 > pDoc->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  pDoc->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  pDoc->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( pDoc, aPos, eGrammar);
1947  std::unique_ptr<ScTokenArray> xCode(aComp.CompileString(aText)); // ctor/InsertMatrixFormula did copy TokenArray
1949  if ( ch == 'M' )
1950  {
1951  ScMarkData aMark(pDoc->GetSheetLimits());
1952  aMark.SelectTable( aPos.Tab(), true );
1953  pDoc->InsertMatrixFormula( nCol, nRow, nRefCol,
1954  nRefRow, aMark, EMPTY_OUSTRING, xCode.get() );
1955  }
1956  else
1957  {
1958  ScFormulaCell* pFCell = new ScFormulaCell(
1959  pDoc, aPos, *xCode, eGrammar, ScMatrixMode::NONE);
1960  pDoc->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 || pDoc->MaxCol() < nCol)
1987  {
1988  SAL_WARN("sc.ui","ScImportExport::Sylk2Doc - ;X invalid nCol=" << nCol);
1989  nCol = std::max<SCCOL>(0, std::min<SCCOL>(nCol, pDoc->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  pDoc->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  // unescape doubled semicolons
2045  aCode = aCode.replaceAll(";;", ";");
2046  // get rid of Xcl escape characters
2047  aCode = aCode.replaceAll("\x1b", "");
2048  sal_Int32 nCheckPos;
2050  sal_uInt32 nKey;
2051  pDoc->GetFormatTable()->PutandConvertEntry( aCode, nCheckPos, nType, nKey,
2053  if ( nCheckPos )
2054  nKey = 0;
2055  aFormats.push_back( nKey );
2056  }
2057  }
2058  else if( cTag == 'I' && *p == 'D' )
2059  {
2060  aLine = aLine.copy(4);
2061  if (aLine == "CALCOOO32")
2062  eVersion = SylkVersion::OOO32;
2063  else if (aLine == "SCALC3")
2064  eVersion = SylkVersion::SCALC3;
2065  bMyDoc = (eVersion <= SylkVersion::OWN);
2066  }
2067  else if( cTag == 'E' ) // End
2068  break;
2069  }
2070  if( !bData )
2071  {
2072  aRange.aEnd.SetCol( nEndCol );
2073  aRange.aEnd.SetRow( nEndRow );
2074  bOk = StartPaste();
2075  bData = true;
2076  }
2077  else
2078  break;
2079  }
2080 
2081  EndPaste();
2082  return bOk;
2083 }
2084 
2086 {
2087  SCCOL nCol;
2088  SCROW nRow;
2089  SCCOL nStartCol = aRange.aStart.Col();
2090  SCROW nStartRow = aRange.aStart.Row();
2091  SCCOL nEndCol = aRange.aEnd.Col();
2092  SCROW nEndRow = aRange.aEnd.Row();
2093  OUString aCellStr;
2094  OUString aValStr;
2095  lcl_WriteSimpleString( rStrm, "ID;PCALCOOO32" );
2096  WriteUnicodeOrByteEndl( rStrm );
2097 
2098  for (nRow = nStartRow; nRow <= nEndRow; nRow++)
2099  {
2100  for (nCol = nStartCol; nCol <= nEndCol; nCol++)
2101  {
2102  OUString aBufStr;
2103  double nVal;
2104  bool bForm = false;
2105  SCROW r = nRow - nStartRow + 1;
2106  SCCOL c = nCol - nStartCol + 1;
2107  ScRefCellValue aCell(*pDoc, ScAddress(nCol, nRow, aRange.aStart.Tab()));
2108  CellType eType = aCell.meType;
2109  switch( eType )
2110  {
2111  case CELLTYPE_FORMULA:
2112  bForm = bFormulas;
2113  if( pDoc->HasValueData( nCol, nRow, aRange.aStart.Tab()) )
2114  goto hasvalue;
2115  else
2116  goto hasstring;
2117 
2118  case CELLTYPE_VALUE:
2119  hasvalue:
2120  pDoc->GetValue( nCol, nRow, aRange.aStart.Tab(), nVal );
2121 
2122  aValStr = ::rtl::math::doubleToUString( nVal,
2123  rtl_math_StringFormat_Automatic,
2124  rtl_math_DecimalPlaces_Max, '.', true );
2125 
2126  aBufStr = "C;X"
2127  + OUString::number( c )
2128  + ";Y"
2129  + OUString::number( r )
2130  + ";K"
2131  + aValStr;
2132  lcl_WriteSimpleString( rStrm, aBufStr );
2133  goto checkformula;
2134 
2135  case CELLTYPE_STRING:
2136  case CELLTYPE_EDIT:
2137  hasstring:
2138  aCellStr = pDoc->GetString(nCol, nRow, aRange.aStart.Tab());
2139  aCellStr = aCellStr.replaceAll("\n", SYLK_LF);
2140 
2141  aBufStr = "C;X"
2142  + OUString::number( c )
2143  + ";Y"
2144  + OUString::number( r )
2145  + ";K";
2146  lcl_WriteSimpleString( rStrm, aBufStr );
2147  lcl_WriteString( rStrm, aCellStr, '"', ';' );
2148 
2149  checkformula:
2150  if( bForm )
2151  {
2152  const ScFormulaCell* pFCell = aCell.mpFormula;
2153  switch ( pFCell->GetMatrixFlag() )
2154  {
2156  aCellStr.clear();
2157  break;
2158  default:
2159  OUString aOUCellStr;
2161  aCellStr = aOUCellStr;
2162  /* FIXME: do we want GRAM_ODFF_A1 instead? At
2163  * the end it probably should be
2164  * GRAM_ODFF_R1C1, since R1C1 is what Excel
2165  * writes in SYLK, or even better
2166  * GRAM_ENGLISH_XL_R1C1. */
2167  }
2168  if ( pFCell->GetMatrixFlag() != ScMatrixMode::NONE &&
2169  aCellStr.startsWith("{") &&
2170  aCellStr.endsWith("}") )
2171  { // cut off matrix {} characters
2172  aCellStr = aCellStr.copy(1, aCellStr.getLength()-2);
2173  }
2174  if ( aCellStr[0] == '=' )
2175  aCellStr = aCellStr.copy(1);
2176  OUString aPrefix;
2177  switch ( pFCell->GetMatrixFlag() )
2178  {
2179  case ScMatrixMode::Formula :
2180  { // diff expression with 'M' M$-extension
2181  SCCOL nC;
2182  SCROW nR;
2183  pFCell->GetMatColsRows( nC, nR );
2184  nC += c - 1;
2185  nR += r - 1;
2186  aPrefix = ";R"
2187  + OUString::number( nR )
2188  + ";C"
2189  + OUString::number( nC )
2190  + ";M";
2191  }
2192  break;
2194  { // diff expression with 'I' M$-extension
2195  ScAddress aPos;
2196  (void)pFCell->GetMatrixOrigin( pDoc, aPos );
2197  aPrefix = ";I;R"
2198  + OUString::number( aPos.Row() - nStartRow + 1 )
2199  + ";C"
2200  + OUString::number( aPos.Col() - nStartCol + 1 );
2201  }
2202  break;
2203  default:
2204  // formula Expression
2205  aPrefix = ";E";
2206  }
2207  lcl_WriteSimpleString( rStrm, aPrefix );
2208  if ( !aCellStr.isEmpty() )
2209  lcl_WriteString( rStrm, aCellStr, 0, ';' );
2210  }
2211  WriteUnicodeOrByteEndl( rStrm );
2212  break;
2213 
2214  default:
2215  {
2216  // added to avoid warnings
2217  }
2218  }
2219  }
2220  }
2221  lcl_WriteSimpleString( rStrm, OUString( 'E' ) );
2222  WriteUnicodeOrByteEndl( rStrm );
2223  return rStrm.GetError() == ERRCODE_NONE;
2224 }
2225 
2226 bool ScImportExport::Doc2HTML( SvStream& rStrm, const OUString& rBaseURL )
2227 {
2228  // rtl_TextEncoding is ignored in ScExportHTML, read from Load/Save HTML options
2229  ScFormatFilter::Get().ScExportHTML( rStrm, rBaseURL, pDoc, aRange, RTL_TEXTENCODING_DONTKNOW, bAll,
2231  return rStrm.GetError() == ERRCODE_NONE;
2232 }
2233 
2235 {
2236  // rtl_TextEncoding is ignored in ScExportRTF
2237  ScFormatFilter::Get().ScExportRTF( rStrm, pDoc, aRange, RTL_TEXTENCODING_DONTKNOW );
2238  return rStrm.GetError() == ERRCODE_NONE;
2239 }
2240 
2242 {
2243  // for DIF in the clipboard, IBM_850 is always used
2244  ScFormatFilter::Get().ScExportDif( rStrm, pDoc, aRange, RTL_TEXTENCODING_IBM_850 );
2245  return true;
2246 }
2247 
2249 {
2250  SCTAB nTab = aRange.aStart.Tab();
2251  ScDocumentUniquePtr pImportDoc( new ScDocument( SCDOCMODE_UNDO ) );
2252  pImportDoc->InitUndo( pDoc, nTab, nTab );
2253 
2254  // for DIF in the clipboard, IBM_850 is always used
2255  ScFormatFilter::Get().ScImportDif( rStrm, pImportDoc.get(), aRange.aStart, RTL_TEXTENCODING_IBM_850 );
2256 
2257  SCCOL nEndCol;
2258  SCROW nEndRow;
2259  pImportDoc->GetCellArea( nTab, nEndCol, nEndRow );
2260  // if there are no cells in the imported content, nEndCol/nEndRow may be before the start
2261  if ( nEndCol < aRange.aStart.Col() )
2262  nEndCol = aRange.aStart.Col();
2263  if ( nEndRow < aRange.aStart.Row() )
2264  nEndRow = aRange.aStart.Row();
2265  aRange.aEnd = ScAddress( nEndCol, nEndRow, nTab );
2266 
2267  bool bOk = StartPaste();
2268  if (bOk)
2269  {
2271  pDoc->DeleteAreaTab( aRange, nFlags );
2272  pImportDoc->CopyToDocument(aRange, nFlags, false, *pDoc);
2273  EndPaste();
2274  }
2275 
2276  return bOk;
2277 }
2278 
2279 bool ScImportExport::RTF2Doc( SvStream& rStrm, const OUString& rBaseURL )
2280 {
2281  std::unique_ptr<ScEEAbsImport> pImp = ScFormatFilter::Get().CreateRTFImport( pDoc, aRange );
2282  if (!pImp)
2283  return false;
2284  pImp->Read( rStrm, rBaseURL );
2285  aRange = pImp->GetRange();
2286 
2287  bool bOk = StartPaste();
2288  if (bOk)
2289  {
2291  pDoc->DeleteAreaTab( aRange, nFlags );
2292  pImp->WriteToDocument();
2293  EndPaste();
2294  }
2295  return bOk;
2296 }
2297 
2298 bool ScImportExport::HTML2Doc( SvStream& rStrm, const OUString& rBaseURL )
2299 {
2300  std::unique_ptr<ScEEAbsImport> pImp = ScFormatFilter::Get().CreateHTMLImport( pDoc, rBaseURL, aRange);
2301  if (!pImp)
2302  return false;
2303  pImp->Read( rStrm, rBaseURL );
2304  aRange = pImp->GetRange();
2305 
2306  bool bOk = StartPaste();
2307  if (bOk)
2308  {
2309  // ScHTMLImport may call ScDocument::InitDrawLayer, resulting in
2310  // a Draw Layer but no Draw View -> create Draw Layer and View here
2311  if (pDocSh)
2312  pDocSh->MakeDrawLayer();
2313 
2315  pDoc->DeleteAreaTab( aRange, nFlags );
2316 
2317  if (pExtOptions)
2318  {
2319  // Pick up import options if available.
2320  LanguageType eLang = pExtOptions->GetLanguage();
2322  bool bSpecialNumber = pExtOptions->IsDetectSpecialNumber();
2323  pImp->WriteToDocument(false, 1.0, &aNumFormatter, bSpecialNumber);
2324  }
2325  else
2326  // Regular import, with no options.
2327  pImp->WriteToDocument();
2328 
2329  EndPaste();
2330  }
2331  return bOk;
2332 }
2333 
2334 #ifndef DISABLE_DYNLOADING
2335 
2336 extern "C" { static void thisModule() {} }
2337 
2338 #else
2339 
2340 extern "C" {
2342 }
2343 
2344 #endif
2345 
2346 typedef ScFormatFilterPlugin * (*FilterFn)();
2348 {
2349  static ScFormatFilterPlugin *plugin = [&]()
2350  {
2351 #ifndef DISABLE_DYNLOADING
2352  OUString sFilterLib(SVLIBRARY("scfilt"));
2353  static ::osl::Module aModule;
2354  bool bLoaded = aModule.is();
2355  if (!bLoaded)
2356  bLoaded = aModule.loadRelative(&thisModule, sFilterLib);
2357  if (!bLoaded)
2358  bLoaded = aModule.load(sFilterLib);
2359  if (bLoaded)
2360  {
2361  oslGenericFunction fn = aModule.getFunctionSymbol( "ScFilterCreate" );
2362  if (fn != nullptr)
2363  return reinterpret_cast<FilterFn>(fn)();
2364  }
2365  assert(false);
2366  return static_cast<ScFormatFilterPlugin*>(nullptr);
2367 #else
2368  return ScFilterCreate();
2369 #endif
2370  }();
2371 
2372  return *plugin;
2373 }
2374 
2375 // Precondition: pStr is guaranteed to be non-NULL and points to a 0-terminated
2376 // array.
2377 static const sal_Unicode* lcl_UnicodeStrChr( const sal_Unicode* pStr,
2378  sal_Unicode c )
2379 {
2380  while (*pStr)
2381  {
2382  if (*pStr == c)
2383  return pStr;
2384  ++pStr;
2385  }
2386  return nullptr;
2387 }
2388 
2390  : SvMemoryStream( const_cast<sal_Unicode *>(rStr.getStr()),
2391  rStr.getLength() * sizeof(sal_Unicode), StreamMode::READ)
2392 {
2393  SetStreamCharSet( RTL_TEXTENCODING_UNICODE );
2394 #ifdef OSL_BIGENDIAN
2395  SetEndian(SvStreamEndian::BIG);
2396 #else
2397  SetEndian(SvStreamEndian::LITTLE);
2398 #endif
2399 }
2400 
2401 OUString ReadCsvLine( SvStream &rStream, bool bEmbeddedLineBreak,
2402  OUString& rFieldSeparators, sal_Unicode cFieldQuote, sal_Unicode& rcDetectSep )
2403 {
2404  enum RetryState
2405  {
2406  FORBID,
2407  ALLOW,
2408  RETRY,
2409  RETRIED
2410  } eRetryState = (bEmbeddedLineBreak && rcDetectSep == 0 ? RetryState::ALLOW : RetryState::FORBID);
2411 
2412  sal_uInt64 nStreamPos = (eRetryState == RetryState::ALLOW ? rStream.Tell() : 0);
2413 
2414 Label_RetryWithNewSep:
2415 
2416  if (eRetryState == RetryState::RETRY)
2417  {
2418  eRetryState = RetryState::RETRIED;
2419  rStream.Seek( nStreamPos);
2420  }
2421 
2422  OUString aStr;
2424 
2425  if (bEmbeddedLineBreak)
2426  {
2427  const sal_Unicode* pSeps = rFieldSeparators.getStr();
2428 
2429  QuoteType eQuoteState = FIELDEND_QUOTE;
2430  bool bFieldStart = true;
2431 
2432  sal_Int32 nLastOffset = 0;
2433  sal_Int32 nQuotes = 0;
2434  while (!rStream.eof() && aStr.getLength() < nArbitraryLineLengthLimit)
2435  {
2436  const sal_Unicode * p = aStr.getStr() + nLastOffset;
2437  while (*p)
2438  {
2439  if (nQuotes)
2440  {
2441  if (*p == cFieldQuote)
2442  {
2443  if (bFieldStart)
2444  {
2445  ++nQuotes;
2446  bFieldStart = false;
2447  eQuoteState = FIELDSTART_QUOTE;
2448  }
2449  // Do not detect a FIELDSTART_QUOTE if not in
2450  // bFieldStart mode, in which case for unquoted content
2451  // we are in FIELDEND_QUOTE state.
2452  else if (eQuoteState != FIELDEND_QUOTE)
2453  {
2454  eQuoteState = lcl_isEscapedOrFieldEndQuote( nQuotes, p, pSeps, cFieldQuote, rcDetectSep);
2455 
2456  if (eRetryState == RetryState::ALLOW && rcDetectSep == ' ')
2457  {
2458  eRetryState = RetryState::RETRY;
2459  rFieldSeparators += OUString(' ');
2460  goto Label_RetryWithNewSep;
2461  }
2462 
2463  // DONTKNOW_QUOTE is an embedded unescaped quote we
2464  // don't count for pairing.
2465  if (eQuoteState != DONTKNOW_QUOTE)
2466  ++nQuotes;
2467  }
2468  }
2469  else if (eQuoteState == FIELDEND_QUOTE)
2470  {
2471  if (bFieldStart)
2472  // If blank is a separator it starts a field, if it
2473  // is not and thus maybe leading before quote we
2474  // are still at start of field regarding quotes.
2475  bFieldStart = (*p == ' ' || lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2476  else
2477  bFieldStart = (lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2478  }
2479  }
2480  else
2481  {
2482  if (*p == cFieldQuote && bFieldStart)
2483  {
2484  nQuotes = 1;
2485  eQuoteState = FIELDSTART_QUOTE;
2486  bFieldStart = false;
2487  }
2488  else if (eQuoteState == FIELDEND_QUOTE)
2489  {
2490  // This also skips leading blanks at beginning of line
2491  // if followed by a quote. It's debatable whether we
2492  // actually want that or not, but congruent with what
2493  // ScanNextFieldFromString() does.
2494  if (bFieldStart)
2495  bFieldStart = (*p == ' ' || lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2496  else
2497  bFieldStart = (lcl_UnicodeStrChr( pSeps, *p) != nullptr);
2498  }
2499  }
2500  // A quote character inside a field content does not start
2501  // a quote.
2502  ++p;
2503  }
2504 
2505  if (nQuotes % 2 == 0)
2506  // We still have a (theoretical?) problem here if due to
2507  // nArbitraryLineLengthLimit we split a string right between a
2508  // doubled quote pair.
2509  break;
2510  else
2511  {
2512  nLastOffset = aStr.getLength();
2513  OUString aNext;
2515  aStr += "\n" + aNext;
2516  }
2517  }
2518  }
2519  return aStr;
2520 }
2521 
2522 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static const OUString & GetClipDocName()
Definition: global.cxx:485
static OUString GetAppName()
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2111
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:658
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:856
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:200
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:214
static void WriteUnicodeOrByteEndl(SvStream &rStrm)
Definition: impex.cxx:521
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:324
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:2241
static bool lcl_appendLineData(OUString &rField, const sal_Unicode *p1, const sal_Unicode *p2)
Append characters of [p1,p2) to rField.
Definition: impex.cxx:633
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 void GetString(const ScRefCellValue &rCell, sal_uInt32 nFormat, OUString &rString, Color **ppColor, SvNumberFormatter &rFormatter, const ScDocument *pDoc, bool bNullVals=true, bool bFormula=false, bool bUseStarFormat=false)
Definition: cellform.cxx:33
static vcl::Window * GetDefDialogParent()
ScImportExport(ScDocument *)
Definition: impex.cxx:101
static bool IsFormatSupported(SotClipboardFormatId nFormat)
Definition: impex.cxx:218
void GetFormula(OUString &rFormula, const formula::FormulaGrammar::Grammar=formula::FormulaGrammar::GRAM_DEFAULT, const ScInterpreterContext *pContext=nullptr) const
sal_uIntPtr sal_uLong
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:168
sal_Unicode cSep
Definition: impex.hxx:58
sal_Int32 toInt32(OUString const &rStr)
SC_DLLPUBLIC bool InitColumnBlockPosition(sc::ColumnBlockPosition &rBlockPos, SCTAB nTab, SCCOL nCol)
Definition: document.cxx:2614
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:4478
static const sal_Unicode * lcl_ScanSylkFormula(const sal_Unicode *p, OUString &rString, SylkVersion eVersion)
Definition: impex.cxx:769
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:727
static SC_DLLPUBLIC ScFormatFilterPlugin & Get()
Definition: impex.cxx:2347
SC_DLLPUBLIC void GetNumberFormat(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt32 &rFormat) const
Definition: document.cxx:3644
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:2226
SC_DLLPUBLIC void SetValue(SCCOL nCol, SCROW nRow, SCTAB nTab, const double &rVal)
Definition: document.cxx:3461
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:960
const SCCOL MAXCOLCOUNT
Definition: address.hxx:64
SC_DLLPUBLIC void ApplyAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem &rAttr)
Definition: document.cxx:4760
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:379
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:475
bool ExportData(const OUString &rMimeType, css::uno::Any &rValue)
Definition: impex.cxx:283
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:571
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:3434
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:6064
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:611
weld::Window * GetFrameWeld() const
static void lcl_UnescapeSylk(OUString &rString, SylkVersion eVersion)
Definition: impex.cxx:714
static bool SC_DLLPUBLIC isMultiline(const OUString &rStr)
Definition: stringutil.cxx:424
sal_uInt16 sal_Unicode
bool Doc2RTF(SvStream &)
Definition: impex.cxx:2234
void EndPaste(bool bAutoRowHeight=true)
Definition: impex.cxx:255
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:492
ScClipParam & GetClipParam()
Definition: document.cxx:2552
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:2389
sal_uInt32 GetStandardIndex(LanguageType eLnge=LANGUAGE_DONTKNOW)
static void thisModule()
Definition: impex.cxx:2336
OUString aStreamPath
Definition: impex.hxx:53
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:3489
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:632
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:111
SCTAB Tab() const
Definition: address.hxx:271
bool GetMatrixOrigin(const ScDocument *pDoc, ScAddress &rPos) const
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:843
bool Text2Doc(SvStream &)
Definition: impex.cxx:861
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:2298
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:3631
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:3397
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:3366
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:90
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:353
bool RowFiltered(SCROW nRow, SCTAB nTab, SCROW *pFirstRow=nullptr, SCROW *pLastRow=nullptr) const
Definition: document.cxx:4502
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:158
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:2207
SC_DLLPUBLIC void ApplyPattern(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr &rAttr)
Definition: document.cxx:4766
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:833
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:5299
~ScImportExport() COVERITY_NOEXCEPT_FALSE
Definition: impex.cxx:194
static SC_DLLPUBLIC LanguageType eLnge
Definition: global.hxx:550
sal_Unicode mcSeparatorConvertTo
Definition: impex.hxx:43
SC_DLLPUBLIC bool HasValueData(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:3768
bool ExportStream(SvStream &, const OUString &rBaseURL, SotClipboardFormatId)
Definition: impex.cxx:419
void PostPaint(SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, PaintPartFlags nPart, sal_uInt16 nExtFlags=0)
Definition: docsh3.cxx:99
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument *=nullptr, 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:1737
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:2085
ConversionMode mode
static void EmbeddedNullTreatment(OUString &rStr)
Definition: impex.cxx:1533
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:3692
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
ScDocument * pDoc
Definition: impex.hxx:50
static ScTabViewShell * GetActiveViewShell()
Definition: tabvwsh4.cxx:1023
DoubledQuoteMode
Definition: impex.cxx:650
static sal_Unicode ToUpperAlpha(sal_Unicode c)
Definition: global.hxx:621
bool Sylk2Doc(SvStream &)
Definition: impex.cxx:1766
#define ERRCODE_NONE
sal_Unicode cStr
Definition: impex.hxx:59
unsigned char sal_uInt8
static SotClipboardFormatId GetFormatIdFromMimeType(const OUString &rMimeType)
void GetMatColsRows(SCCOL &nCols, SCROW &nRows) const
CellType
Definition: global.hxx:281
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)
const sal_Int32 nArbitraryLineLengthLimit
Definition: impex.cxx:72
css::uno::Sequence< css::i18n::CalendarItem2 > getMonths() const
void SetStreamCharSet(rtl_TextEncoding eCharSet)
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:2377
rtl_TextEncoding GetStreamCharSet() const
static SC_DLLPUBLIC const CharClass * getCharClassPtr()
Definition: global.cxx:1016
sal_uInt64 Tell() const
Reference< XComponentContext > getProcessComponentContext()
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:401
bool RTF2Doc(SvStream &, const OUString &rBaseURL)
Definition: impex.cxx:2279
double getLength(const B2DPolygon &rCandidate)
bool ImportString(const OUString &, SotClipboardFormatId)
Definition: impex.cxx:300
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:648
virtual ErrCode ScImportDif(SvStream &, ScDocument *, const ScAddress &rInsPos, const rtl_TextEncoding eSrc)=0
bool Dif2Doc(SvStream &)
Definition: impex.cxx:2248
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:2401
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1058
#define SAL_WARN(area, stream)
bool IsUndoEnabled() const
Definition: document.hxx:1531
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:213
SC_DLLPUBLIC void GetLanguage(LanguageType &rLatin, LanguageType &rCjk, LanguageType &rCtl) const
Definition: documen3.cxx:1930
bool StartPaste()
Definition: impex.cxx:230
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
static void SetNoEndianSwap(SvStream &rStrm)
only if stream is only used in own (!) memory
Definition: impex.cxx:541
const OUString & GetFieldSeps() const
Definition: asciiopt.hxx:57
static SCTAB GetCurTab()
Definition: docsh4.cxx:2549
ScFormatFilterPlugin *(* FilterFn)()
Definition: impex.cxx:2346
const sal_uInt8 SC_COL_SKIP
Definition: csvcontrol.hxx:61
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument *=nullptr, 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:1543
aStr
QuoteType
Definition: impex.cxx:552
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