LCOV - code coverage report
Current view: top level - libreoffice/sc/source/ui/docshell - impex.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 423 1214 34.8 %
Date: 2012-12-27 Functions: 21 68 30.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "sc.hrc"
      21             : 
      22             : #include <comphelper/processfactory.hxx>
      23             : #include <i18npool/languagetag.hxx>
      24             : #include <sot/formats.hxx>
      25             : #include <sfx2/mieclip.hxx>
      26             : #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
      27             : 
      28             : #include "global.hxx"
      29             : #include "scerrors.hxx"
      30             : #include "docsh.hxx"
      31             : #include "undoblk.hxx"
      32             : #include "rangenam.hxx"
      33             : #include "viewdata.hxx"
      34             : #include "tabvwsh.hxx"
      35             : #include "filter.hxx"
      36             : #include "asciiopt.hxx"
      37             : #include "cell.hxx"
      38             : #include "column.hxx"
      39             : #include "docoptio.hxx"
      40             : #include "progress.hxx"
      41             : #include "scitems.hxx"
      42             : #include "editable.hxx"
      43             : #include "compiler.hxx"
      44             : #include "warnbox.hxx"
      45             : #include "clipparam.hxx"
      46             : #include "impex.hxx"
      47             : #include "editutil.hxx"
      48             : #include "patattr.hxx"
      49             : #include "docpool.hxx"
      50             : #include "stringutil.hxx"
      51             : 
      52             : #include "globstr.hrc"
      53             : #include <vcl/svapp.hxx>
      54             : 
      55             : //========================================================================
      56             : 
      57             : // We don't want to end up with 2GB read in one line just because of malformed
      58             : // multiline fields, so chop it _somewhere_, which is twice supported columns
      59             : // times maximum cell content length, 2*1024*64K=128M, and because it's
      60             : // sal_Unicode that's 256MB. If it's 2GB of data without LF we're out of luck
      61             : // anyway.
      62             : static const sal_Int32 nArbitraryLineLengthLimit = 2 * MAXCOLCOUNT * STRING_MAXLEN;
      63             : 
      64             : namespace
      65             : {
      66             :     const char SYLK_LF[]  = "\x1b :";
      67             :     const char DOUBLE_SEMICOLON[] = ";;";
      68             :     const char DOUBLE_DOUBLEQUOTE[] = "\"\"";
      69             : }
      70             : 
      71             : enum SylkVersion
      72             : {
      73             :     SYLK_SCALC3,    // Wrote wrongly quoted strings and unescaped semicolons.
      74             :     SYLK_OOO32,     // Correct strings, plus multiline content.
      75             :     SYLK_OWN,       // Place our new versions, if any, before this value.
      76             :     SYLK_OTHER      // Assume that aliens wrote correct strings.
      77             : };
      78             : 
      79             : 
      80             : // Gesamtdokument ohne Undo
      81             : 
      82             : 
      83           6 : ScImportExport::ScImportExport( ScDocument* p )
      84          12 :     : pDocSh( PTR_CAST(ScDocShell,p->GetDocumentShell()) ), pDoc( p ),
      85             :       nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
      86             :       bFormulas( false ), bIncludeFiltered( true ),
      87             :       bAll( true ), bSingle( true ), bUndo( false ),
      88             :       bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
      89          12 :       mbApi( true ), mExportTextOptions()
      90             : {
      91           6 :     pUndoDoc = NULL;
      92           6 :     pExtOptions = NULL;
      93           6 : }
      94             : 
      95             : // Insert am Punkt ohne Bereichschecks
      96             : 
      97             : 
      98           0 : ScImportExport::ScImportExport( ScDocument* p, const ScAddress& rPt )
      99           0 :     : pDocSh( PTR_CAST(ScDocShell,p->GetDocumentShell()) ), pDoc( p ),
     100             :       aRange( rPt ),
     101             :       nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
     102             :       bFormulas( false ), bIncludeFiltered( true ),
     103             :       bAll( false ), bSingle( true ), bUndo( pDocSh != NULL ),
     104             :       bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
     105           0 :       mbApi( true ), mExportTextOptions()
     106             : {
     107           0 :     pUndoDoc = NULL;
     108           0 :     pExtOptions = NULL;
     109           0 : }
     110             : 
     111             : 
     112             : //  ctor with a range is only used for export
     113             : //! ctor with a string (and bSingle=true) is also used for DdeSetData
     114             : 
     115           0 : ScImportExport::ScImportExport( ScDocument* p, const ScRange& r )
     116           0 :     : pDocSh( PTR_CAST(ScDocShell,p->GetDocumentShell()) ), pDoc( p ),
     117             :       aRange( r ),
     118             :       nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
     119             :       bFormulas( false ), bIncludeFiltered( true ),
     120             :       bAll( false ), bSingle( false ), bUndo( pDocSh != NULL ),
     121             :       bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
     122           0 :       mbApi( true ), mExportTextOptions()
     123             : {
     124           0 :     pUndoDoc = NULL;
     125           0 :     pExtOptions = NULL;
     126             :     // Zur Zeit nur in einer Tabelle!
     127           0 :     aRange.aEnd.SetTab( aRange.aStart.Tab() );
     128           0 : }
     129             : 
     130             : // String auswerten: Entweder Bereich, Punkt oder Gesamtdoc (bei Fehler)
     131             : // Falls eine View existiert, wird die TabNo der View entnommen!
     132             : 
     133             : 
     134           0 : ScImportExport::ScImportExport( ScDocument* p, const String& rPos )
     135           0 :     : pDocSh( PTR_CAST(ScDocShell,p->GetDocumentShell()) ), pDoc( p ),
     136             :       nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
     137             :       bFormulas( false ), bIncludeFiltered( true ),
     138             :       bAll( false ), bSingle( true ), bUndo( pDocSh != NULL ),
     139             :       bOverflowRow( false ), bOverflowCol( false ), bOverflowCell( false ),
     140           0 :       mbApi( true ), mExportTextOptions()
     141             : {
     142           0 :     pUndoDoc = NULL;
     143           0 :     pExtOptions = NULL;
     144             : 
     145           0 :     SCTAB nTab = ScDocShell::GetCurTab();
     146           0 :     aRange.aStart.SetTab( nTab );
     147           0 :     String aPos( rPos );
     148             :     //  Benannter Bereich?
     149           0 :     ScRangeName* pRange = pDoc->GetRangeName();
     150           0 :     if( pRange )
     151             :     {
     152           0 :         const ScRangeData* pData = pRange->findByUpperName(ScGlobal::pCharClass->uppercase(aPos));
     153           0 :         if (pData)
     154             :         {
     155           0 :             if( pData->HasType( RT_REFAREA )
     156           0 :                 || pData->HasType( RT_ABSAREA )
     157           0 :                 || pData->HasType( RT_ABSPOS ) )
     158           0 :                 pData->GetSymbol( aPos );                   // mit dem Inhalt weitertesten
     159             :         }
     160             :     }
     161           0 :     formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
     162             :     // Bereich?
     163           0 :     if( aRange.Parse( aPos, pDoc, eConv ) & SCA_VALID )
     164           0 :         bSingle = false;
     165             :     // Zelle?
     166           0 :     else if( aRange.aStart.Parse( aPos, pDoc, eConv ) & SCA_VALID )
     167           0 :         aRange.aEnd = aRange.aStart;
     168             :     else
     169           0 :         bAll = true;
     170           0 : }
     171             : 
     172             : 
     173          12 : ScImportExport::~ScImportExport()
     174             : {
     175           6 :     delete pUndoDoc;
     176           6 :     delete pExtOptions;
     177           6 : }
     178             : 
     179             : 
     180           2 : void ScImportExport::SetExtOptions( const ScAsciiOptions& rOpt )
     181             : {
     182           2 :     if ( pExtOptions )
     183           0 :         *pExtOptions = rOpt;
     184             :     else
     185           2 :         pExtOptions = new ScAsciiOptions( rOpt );
     186             : 
     187             :     //  "normale" Optionen uebernehmen
     188             : 
     189           2 :     cSep = rOpt.GetFieldSeps().GetChar(0);
     190           2 :     cStr = rOpt.GetTextSep();
     191           2 : }
     192             : 
     193             : 
     194           0 : bool ScImportExport::IsFormatSupported( sal_uLong nFormat )
     195             : {
     196             :     return nFormat == FORMAT_STRING
     197             :               || nFormat == SOT_FORMATSTR_ID_SYLK
     198             :               || nFormat == SOT_FORMATSTR_ID_LINK
     199             :               || nFormat == SOT_FORMATSTR_ID_HTML
     200             :               || nFormat == SOT_FORMATSTR_ID_HTML_SIMPLE
     201           0 :               || nFormat == SOT_FORMATSTR_ID_DIF;
     202             : }
     203             : 
     204             : 
     205             : //////////////////////////////////////////////////////////////////////////////
     206             : 
     207             : // Vorbereitung fuer Undo: Undo-Dokument erzeugen
     208             : 
     209             : 
     210           6 : bool ScImportExport::StartPaste()
     211             : {
     212           6 :     if ( !bAll )
     213             :     {
     214           0 :         ScEditableTester aTester( pDoc, aRange );
     215           0 :         if ( !aTester.IsEditable() )
     216             :         {
     217             :             InfoBox aInfoBox(Application::GetDefDialogParent(),
     218           0 :                                 ScGlobal::GetRscString( aTester.GetMessageId() ) );
     219           0 :             aInfoBox.Execute();
     220           0 :             return false;
     221           0 :         }
     222             :     }
     223           6 :     if( bUndo && pDocSh && pDoc->IsUndoEnabled())
     224             :     {
     225           0 :         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
     226           0 :         pUndoDoc->InitUndo( pDoc, aRange.aStart.Tab(), aRange.aEnd.Tab() );
     227           0 :         pDoc->CopyToDocument( aRange, IDF_ALL | IDF_NOCAPTIONS, false, pUndoDoc );
     228             :     }
     229           6 :     return true;
     230             : }
     231             : 
     232             : // Nachbereitung Insert: Undo/Redo-Aktionen erzeugen, Invalidate/Repaint
     233             : 
     234             : 
     235           6 : void ScImportExport::EndPaste()
     236             : {
     237             :     bool bHeight = pDocSh && pDocSh->AdjustRowHeight(
     238           6 :                     aRange.aStart.Row(), aRange.aEnd.Row(), aRange.aStart.Tab() );
     239             : 
     240           6 :     if( pUndoDoc && pDoc->IsUndoEnabled() )
     241             :     {
     242           0 :         ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
     243           0 :         pRedoDoc->InitUndo( pDoc, aRange.aStart.Tab(), aRange.aEnd.Tab() );
     244           0 :         pDoc->CopyToDocument( aRange, IDF_ALL | IDF_NOCAPTIONS, false, pRedoDoc );
     245           0 :         ScMarkData aDestMark;
     246           0 :         aDestMark.SetMarkArea(aRange);
     247           0 :         pDocSh->GetUndoManager()->AddUndoAction(
     248           0 :             new ScUndoPaste(pDocSh, aRange, aDestMark, pUndoDoc, pRedoDoc, IDF_ALL, NULL));
     249             :     }
     250           6 :     pUndoDoc = NULL;
     251           6 :     if( pDocSh )
     252             :     {
     253           6 :         if (!bHeight)
     254           0 :             pDocSh->PostPaint( aRange, PAINT_GRID );    // AdjustRowHeight paintet evtl. selber
     255           6 :         pDocSh->SetDocumentModified();
     256             :     }
     257           6 :     ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
     258           6 :     if ( pViewSh )
     259           0 :         pViewSh->UpdateInputHandler();
     260             : 
     261           6 : }
     262             : 
     263             : /////////////////////////////////////////////////////////////////////////////
     264             : 
     265           0 : bool ScImportExport::ImportData( const String& /* rMimeType */,
     266             :                      const ::com::sun::star::uno::Any & /* rValue */ )
     267             : {
     268             :     OSL_ENSURE( !this, "Implementation is missing" );
     269           0 :     return false;
     270             : }
     271             : 
     272           0 : bool ScImportExport::ExportData( const String& rMimeType,
     273             :                                  ::com::sun::star::uno::Any & rValue )
     274             : {
     275           0 :     SvMemoryStream aStrm;
     276             :     // mba: no BaseURL for data exchange
     277           0 :     if( ExportStream( aStrm, String(),
     278           0 :                 SotExchange::GetFormatIdFromMimeType( rMimeType ) ))
     279             :     {
     280           0 :         aStrm << (sal_uInt8) 0;
     281             :         rValue <<= ::com::sun::star::uno::Sequence< sal_Int8 >(
     282           0 :                                         (sal_Int8*)aStrm.GetData(),
     283           0 :                                         aStrm.Seek( STREAM_SEEK_TO_END ) );
     284           0 :         return true;
     285             :     }
     286           0 :     return false;
     287             : }
     288             : 
     289             : 
     290           0 : bool ScImportExport::ImportString( const ::rtl::OUString& rText, sal_uLong nFmt )
     291             : {
     292           0 :     switch ( nFmt )
     293             :     {
     294             :         // formats supporting unicode
     295             :         case FORMAT_STRING :
     296             :         {
     297           0 :             ScImportStringStream aStrm( rText);
     298           0 :             return ImportStream( aStrm, String(), nFmt );
     299             :             // ImportStream must handle RTL_TEXTENCODING_UNICODE
     300             :         }
     301             :         //break;
     302             :         default:
     303             :         {
     304           0 :             rtl_TextEncoding eEnc = osl_getThreadTextEncoding();
     305           0 :             ::rtl::OString aTmp( rText.getStr(), rText.getLength(), eEnc );
     306           0 :             SvMemoryStream aStrm( (void*)aTmp.getStr(), aTmp.getLength() * sizeof(sal_Char), STREAM_READ );
     307           0 :             aStrm.SetStreamCharSet( eEnc );
     308           0 :             SetNoEndianSwap( aStrm );       //! no swapping in memory
     309           0 :             return ImportStream( aStrm, String(), nFmt );
     310             :         }
     311             :     }
     312             : }
     313             : 
     314             : 
     315           0 : bool ScImportExport::ExportString( ::rtl::OUString& rText, sal_uLong nFmt )
     316             : {
     317             :     OSL_ENSURE( nFmt == FORMAT_STRING, "ScImportExport::ExportString: Unicode not supported for other formats than FORMAT_STRING" );
     318           0 :     if ( nFmt != FORMAT_STRING )
     319             :     {
     320           0 :         rtl_TextEncoding eEnc = osl_getThreadTextEncoding();
     321           0 :         rtl::OString aTmp;
     322           0 :         bool bOk = ExportByteString( aTmp, eEnc, nFmt );
     323           0 :         rText = rtl::OStringToOUString( aTmp, eEnc );
     324           0 :         return bOk;
     325             :     }
     326             :     //  nSizeLimit not needed for OUString
     327             : 
     328           0 :     SvMemoryStream aStrm;
     329           0 :     aStrm.SetStreamCharSet( RTL_TEXTENCODING_UNICODE );
     330           0 :     SetNoEndianSwap( aStrm );       //! no swapping in memory
     331             :     // mba: no BaseURL for data exc
     332           0 :     if( ExportStream( aStrm, String(), nFmt ) )
     333             :     {
     334           0 :         aStrm << (sal_Unicode) 0;
     335           0 :         aStrm.Seek( STREAM_SEEK_TO_END );
     336             : 
     337           0 :         rText = rtl::OUString( (const sal_Unicode*) aStrm.GetData() );
     338           0 :         return true;
     339             :     }
     340           0 :     rText = rtl::OUString();
     341           0 :     return false;
     342             : 
     343             :     // ExportStream must handle RTL_TEXTENCODING_UNICODE
     344             : }
     345             : 
     346             : 
     347           0 : bool ScImportExport::ExportByteString( rtl::OString& rText, rtl_TextEncoding eEnc, sal_uLong nFmt )
     348             : {
     349             :     OSL_ENSURE( eEnc != RTL_TEXTENCODING_UNICODE, "ScImportExport::ExportByteString: Unicode not supported" );
     350           0 :     if ( eEnc == RTL_TEXTENCODING_UNICODE )
     351           0 :         eEnc = osl_getThreadTextEncoding();
     352             : 
     353           0 :     if (!nSizeLimit)
     354           0 :         nSizeLimit = STRING_MAXLEN;
     355             : 
     356           0 :     SvMemoryStream aStrm;
     357           0 :     aStrm.SetStreamCharSet( eEnc );
     358           0 :     SetNoEndianSwap( aStrm );       //! no swapping in memory
     359             :     // mba: no BaseURL for data exchange
     360           0 :     if( ExportStream( aStrm, String(), nFmt ) )
     361             :     {
     362           0 :         aStrm << (sal_Char) 0;
     363           0 :         aStrm.Seek( STREAM_SEEK_TO_END );
     364             :         // Sicherheits-Check:
     365           0 :         if( aStrm.Tell() <= (sal_uLong) STRING_MAXLEN )
     366             :         {
     367           0 :             rText = (const sal_Char*) aStrm.GetData();
     368           0 :             return true;
     369             :         }
     370             :     }
     371           0 :     rText = rtl::OString();
     372           0 :     return false;
     373             : }
     374             : 
     375             : 
     376           6 : bool ScImportExport::ImportStream( SvStream& rStrm, const String& rBaseURL, sal_uLong nFmt )
     377             : {
     378           6 :     if( nFmt == FORMAT_STRING )
     379             :     {
     380           2 :         if( ExtText2Doc( rStrm ) )      // pExtOptions auswerten
     381           2 :             return true;
     382             :     }
     383           4 :     if( nFmt == SOT_FORMATSTR_ID_SYLK )
     384             :     {
     385           4 :         if( Sylk2Doc( rStrm ) )
     386           4 :             return true;
     387             :     }
     388           0 :     if( nFmt == SOT_FORMATSTR_ID_DIF )
     389             :     {
     390           0 :         if( Dif2Doc( rStrm ) )
     391           0 :             return true;
     392             :     }
     393           0 :     if( nFmt == FORMAT_RTF )
     394             :     {
     395           0 :         if( RTF2Doc( rStrm, rBaseURL ) )
     396           0 :             return true;
     397             :     }
     398           0 :     if( nFmt == SOT_FORMATSTR_ID_LINK )
     399           0 :         return true;            // Link-Import?
     400           0 :     if ( nFmt == SOT_FORMATSTR_ID_HTML )
     401             :     {
     402           0 :         if( HTML2Doc( rStrm, rBaseURL ) )
     403           0 :             return true;
     404             :     }
     405           0 :     if ( nFmt == SOT_FORMATSTR_ID_HTML_SIMPLE )
     406             :     {
     407           0 :         MSE40HTMLClipFormatObj aMSE40ClpObj;                // needed to skip the header data
     408           0 :         SvStream* pHTML = aMSE40ClpObj.IsValid( rStrm );
     409           0 :         if ( pHTML && HTML2Doc( *pHTML, rBaseURL ) )
     410           0 :             return true;
     411             :     }
     412             : 
     413           0 :     return false;
     414             : }
     415             : 
     416             : 
     417           0 : bool ScImportExport::ExportStream( SvStream& rStrm, const String& rBaseURL, sal_uLong nFmt )
     418             : {
     419           0 :     if( nFmt == FORMAT_STRING )
     420             :     {
     421           0 :         if( Doc2Text( rStrm ) )
     422           0 :             return true;
     423             :     }
     424           0 :     if( nFmt == SOT_FORMATSTR_ID_SYLK )
     425             :     {
     426           0 :         if( Doc2Sylk( rStrm ) )
     427           0 :             return true;
     428             :     }
     429           0 :     if( nFmt == SOT_FORMATSTR_ID_DIF )
     430             :     {
     431           0 :         if( Doc2Dif( rStrm ) )
     432           0 :             return true;
     433             :     }
     434           0 :     if( nFmt == SOT_FORMATSTR_ID_LINK && !bAll )
     435             :     {
     436           0 :         String aDocName;
     437           0 :         if ( pDoc->IsClipboard() )
     438           0 :             aDocName = ScGlobal::GetClipDocName();
     439             :         else
     440             :         {
     441           0 :             SfxObjectShell* pShell = pDoc->GetDocumentShell();
     442           0 :             if (pShell)
     443           0 :                 aDocName = pShell->GetTitle( SFX_TITLE_FULLNAME );
     444             :         }
     445             : 
     446             :         OSL_ENSURE( aDocName.Len(), "ClipBoard document has no name! :-/" );
     447           0 :         if( aDocName.Len() )
     448             :         {
     449             :             // Always use Calc A1 syntax for paste link.
     450           0 :             String aRefName;
     451           0 :             sal_uInt16 nFlags = SCA_VALID | SCA_TAB_3D;
     452           0 :             if( bSingle )
     453           0 :                 aRange.aStart.Format( aRefName, nFlags, pDoc, formula::FormulaGrammar::CONV_OOO );
     454             :             else
     455             :             {
     456           0 :                 if( aRange.aStart.Tab() != aRange.aEnd.Tab() )
     457           0 :                     nFlags |= SCA_TAB2_3D;
     458           0 :                 aRange.Format( aRefName, nFlags, pDoc, formula::FormulaGrammar::CONV_OOO );
     459             :             }
     460           0 :             String aAppName = Application::GetAppName();
     461             : 
     462             :             // extra bits are used to tell the client to prefer external
     463             :             // reference link.
     464           0 :             ::rtl::OUString aExtraBits(RTL_CONSTASCII_USTRINGPARAM("calc:extref"));
     465             : 
     466           0 :             WriteUnicodeOrByteString( rStrm, aAppName, true );
     467           0 :             WriteUnicodeOrByteString( rStrm, aDocName, true );
     468           0 :             WriteUnicodeOrByteString( rStrm, aRefName, true );
     469           0 :             WriteUnicodeOrByteString( rStrm, aExtraBits, true );
     470           0 :             if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
     471           0 :                 rStrm << sal_Unicode(0);
     472             :             else
     473           0 :                 rStrm << sal_Char(0);
     474           0 :             return rStrm.GetError() == SVSTREAM_OK;
     475           0 :         }
     476             :     }
     477           0 :     if( nFmt == SOT_FORMATSTR_ID_HTML )
     478             :     {
     479           0 :         if( Doc2HTML( rStrm, rBaseURL ) )
     480           0 :             return true;
     481             :     }
     482           0 :     if( nFmt == FORMAT_RTF )
     483             :     {
     484           0 :         if( Doc2RTF( rStrm ) )
     485           0 :             return true;
     486             :     }
     487             : 
     488           0 :     return false;
     489             : }
     490             : 
     491             : 
     492           0 : void ScImportExport::WriteUnicodeOrByteString( SvStream& rStrm, const String& rString, bool bZero )
     493             : {
     494           0 :     rtl_TextEncoding eEnc = rStrm.GetStreamCharSet();
     495           0 :     if ( eEnc == RTL_TEXTENCODING_UNICODE )
     496             :     {
     497           0 :         if ( !IsEndianSwap( rStrm ) )
     498           0 :             rStrm.Write( rString.GetBuffer(), rString.Len() * sizeof(sal_Unicode) );
     499             :         else
     500             :         {
     501           0 :             const sal_Unicode* p = rString.GetBuffer();
     502           0 :             const sal_Unicode* const pStop = p + rString.Len();
     503           0 :             while ( p < pStop )
     504             :             {
     505           0 :                 rStrm << *p;
     506             :             }
     507             :         }
     508           0 :         if ( bZero )
     509           0 :             rStrm << sal_Unicode(0);
     510             :     }
     511             :     else
     512             :     {
     513           0 :         rtl::OString aByteStr(rtl::OUStringToOString(rString, eEnc));
     514           0 :         rStrm << aByteStr.getStr();
     515           0 :         if ( bZero )
     516           0 :             rStrm << sal_Char(0);
     517             :     }
     518           0 : }
     519             : 
     520             : 
     521             : // This function could be replaced by endlub()
     522           0 : void ScImportExport::WriteUnicodeOrByteEndl( SvStream& rStrm )
     523             : {
     524           0 :     if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE )
     525             :     {   // same as endl() but unicode
     526           0 :         switch ( rStrm.GetLineDelimiter() )
     527             :         {
     528             :             case LINEEND_CR :
     529           0 :                 rStrm << sal_Unicode(_CR);
     530           0 :             break;
     531             :             case LINEEND_LF :
     532           0 :                 rStrm << sal_Unicode(_LF);
     533           0 :             break;
     534             :             default:
     535           0 :                 rStrm << sal_Unicode(_CR) << sal_Unicode(_LF);
     536             :         }
     537             :     }
     538             :     else
     539           0 :         endl( rStrm );
     540           0 : }
     541             : 
     542             : 
     543             : enum QuoteType
     544             : {
     545             :     FIELDSTART_QUOTE,
     546             :     FIRST_QUOTE,
     547             :     SECOND_QUOTE,
     548             :     FIELDEND_QUOTE,
     549             :     DONTKNOW_QUOTE
     550             : };
     551             : 
     552             : 
     553             : /** Determine if *p is a quote that ends a quoted field.
     554             : 
     555             :     Precondition: we are parsing a quoted field already and *p is a quote.
     556             : 
     557             :     @return
     558             :         FIELDEND_QUOTE if end of field quote
     559             :         DONTKNOW_QUOTE anything else
     560             :  */
     561         968 : static QuoteType lcl_isFieldEndQuote( const sal_Unicode* p, const sal_Unicode* pSeps )
     562             : {
     563             :     // Due to broken CSV generators that don't double embedded quotes check if
     564             :     // a field separator immediately or with trailing spaces follows the quote,
     565             :     // only then end the field, or at end of string.
     566         968 :     const sal_Unicode cBlank = ' ';
     567         968 :     if (p[1] == cBlank && ScGlobal::UnicodeStrChr( pSeps, cBlank))
     568           0 :         return FIELDEND_QUOTE;
     569        1976 :     while (p[1] == cBlank)
     570          40 :         ++p;
     571         968 :     if (!p[1] || ScGlobal::UnicodeStrChr( pSeps, p[1]))
     572         772 :         return FIELDEND_QUOTE;
     573         196 :     return DONTKNOW_QUOTE;
     574             : }
     575             : 
     576             : 
     577             : /** Determine if *p is a quote that is escaped by being doubled or ends a
     578             :     quoted field.
     579             : 
     580             :     Precondition: *p is a quote.
     581             : 
     582             :     @param nQuotes
     583             :         Quote characters encountered so far.
     584             :         Odd (after opening quote) means either no embedded quotes or only quote
     585             :         pairs so far.
     586             :         Even means either not in a quoted field or already one quote
     587             :         encountered, the first of a pair.
     588             : 
     589             :     @return
     590             :         FIELDSTART_QUOTE if first quote in a field, either starting content or
     591             :                             embedded so caller should check beforehand.
     592             :         FIRST_QUOTE      if first of a doubled quote
     593             :         SECOND_QUOTE     if second of a doubled quote
     594             :         FIELDEND_QUOTE   if end of field quote
     595             :         DONTKNOW_QUOTE   if an unescaped quote we don't consider as end of field,
     596             :                             do not increment nQuotes in caller then!
     597             :  */
     598         580 : static QuoteType lcl_isEscapedOrFieldEndQuote( sal_Int32 nQuotes, const sal_Unicode* p,
     599             :         const sal_Unicode* pSeps, sal_Unicode cStr )
     600             : {
     601         580 :     if ((nQuotes % 2) == 0)
     602             :     {
     603          48 :         if (p[-1] == cStr)
     604          48 :             return SECOND_QUOTE;
     605             :         else
     606             :         {
     607             :             SAL_WARN( "sc", "lcl_isEscapedOrFieldEndQuote: really want a FIELDSTART_QUOTE?");
     608           0 :             return FIELDSTART_QUOTE;
     609             :         }
     610             :     }
     611         532 :     if (p[1] == cStr)
     612          48 :         return FIRST_QUOTE;
     613         484 :     return lcl_isFieldEndQuote( p, pSeps);
     614             : }
     615             : 
     616             : 
     617             : /** Append characters of [p1,p2) to rField.
     618             : 
     619             :     @returns TRUE if ok; FALSE if data overflow, truncated
     620             :  */
     621         778 : static bool lcl_appendLineData( String& rField, const sal_Unicode* p1, const sal_Unicode* p2 )
     622             : {
     623             :     OSL_ENSURE( rField.Len() + (p2 - p1) <= STRING_MAXLEN, "lcl_appendLineData: data overflow");
     624         778 :     if (rField.Len() + (p2 - p1) <= STRING_MAXLEN)
     625             :     {
     626         778 :         rField.Append( p1, sal::static_int_cast<xub_StrLen>( p2 - p1 ) );
     627         778 :         return true;
     628             :     }
     629             :     else
     630             :     {
     631             :         // If STRING_MAXLEN is passed as length, then String attempts to
     632             :         // determine the length of the string and comes up with an overflow
     633             :         // casted to xub_StrLen again ... so pass max-1, data will be truncated
     634             :         // anyway.
     635           0 :         rField.Append( p1, (rField.Len() ? STRING_MAXLEN - rField.Len() : STRING_MAXLEN - 1) );
     636           0 :         return false;
     637             :     }
     638             : }
     639             : 
     640             : 
     641             : enum DoubledQuoteMode
     642             : {
     643             :     DQM_KEEP,       // both are taken
     644             :     DQM_ESCAPE,     // escaped quote, one is taken, one ignored
     645             :     DQM_CONCAT,     // first is end, next is start, both ignored => strings combined
     646             :     DQM_SEPARATE    // end one string and begin next
     647             : };
     648             : 
     649         386 : static const sal_Unicode* lcl_ScanString( const sal_Unicode* p, String& rString,
     650             :             const sal_Unicode* pSeps, sal_Unicode cStr, DoubledQuoteMode eMode, bool& rbOverflowCell )
     651             : {
     652         386 :     p++;    //! jump over opening quote
     653             :     bool bCont;
     654         434 :     do
     655             :     {
     656         434 :         bCont = false;
     657         434 :         const sal_Unicode* p0 = p;
     658        3764 :         for( ;; )
     659             :         {
     660        4198 :             if( !*p )
     661           0 :                 break;
     662        4198 :             if( *p == cStr )
     663             :             {
     664         532 :                 if ( *++p != cStr )
     665             :                 {
     666             :                     // break or continue for loop
     667         484 :                     if (eMode == DQM_ESCAPE)
     668             :                     {
     669         484 :                         if (lcl_isFieldEndQuote( p-1, pSeps) == FIELDEND_QUOTE)
     670         386 :                             break;
     671             :                         else
     672          98 :                             continue;
     673             :                     }
     674             :                     else
     675           0 :                         break;
     676             :                 }
     677             :                 // doubled quote char
     678          48 :                 switch ( eMode )
     679             :                 {
     680             :                     case DQM_KEEP :
     681           0 :                         p++;            // both for us (not breaking for-loop)
     682           0 :                     break;
     683             :                     case DQM_ESCAPE :
     684          48 :                         p++;            // one for us (breaking for-loop)
     685          48 :                         bCont = true;   // and more
     686          48 :                     break;
     687             :                     case DQM_CONCAT :
     688           0 :                         if ( p0+1 < p )
     689             :                         {
     690             :                             // first part
     691           0 :                             if (!lcl_appendLineData( rString, p0, p-1))
     692           0 :                                 rbOverflowCell = true;
     693             :                         }
     694           0 :                         p0 = ++p;       // text of next part starts here
     695           0 :                     break;
     696             :                     case DQM_SEPARATE :
     697             :                                         // positioned on next opening quote
     698           0 :                     break;
     699             :                 }
     700          48 :                 if ( eMode == DQM_ESCAPE || eMode == DQM_SEPARATE )
     701          48 :                     break;
     702             :             }
     703             :             else
     704        3666 :                 p++;
     705             :         }
     706         434 :         if ( p0 < p )
     707             :         {
     708         434 :             if (!lcl_appendLineData( rString, p0, ((*p || *(p-1) == cStr) ? p-1 : p)))
     709           0 :                 rbOverflowCell = true;
     710             :         }
     711             :     } while ( bCont );
     712         386 :     return p;
     713             : }
     714             : 
     715         941 : static void lcl_UnescapeSylk( String & rString, SylkVersion eVersion )
     716             : {
     717             :     // Older versions didn't escape the semicolon.
     718             :     // Older versions quoted the string and doubled embedded quotes, but not
     719             :     // the semicolons, which was plain wrong.
     720         941 :     if (eVersion >= SYLK_OOO32)
     721         496 :         rString.SearchAndReplaceAll( rtl::OUString(DOUBLE_SEMICOLON), rtl::OUString(';') );
     722             :     else
     723         445 :         rString.SearchAndReplaceAll( rtl::OUString(DOUBLE_DOUBLEQUOTE), rtl::OUString('"') );
     724             : 
     725         941 :     rString.SearchAndReplaceAll( rtl::OUString(SYLK_LF), rtl::OUString(_LF) );
     726         941 : }
     727             : 
     728         941 : static const sal_Unicode* lcl_ScanSylkString( const sal_Unicode* p,
     729             :         String& rString, SylkVersion eVersion )
     730             : {
     731         941 :     const sal_Unicode* pStartQuote = p;
     732         941 :     const sal_Unicode* pEndQuote = 0;
     733       16714 :     while( *(++p) )
     734             :     {
     735       14832 :         if( *p == '"' )
     736             :         {
     737         941 :             pEndQuote = p;
     738         941 :             if (eVersion >= SYLK_OOO32)
     739             :             {
     740         496 :                 if (*(p+1) == ';')
     741             :                 {
     742           0 :                     if (*(p+2) == ';')
     743             :                     {
     744           0 :                         p += 2;     // escaped ';'
     745           0 :                         pEndQuote = 0;
     746             :                     }
     747             :                     else
     748           0 :                         break;      // end field
     749             :                 }
     750             :             }
     751             :             else
     752             :             {
     753         445 :                 if (*(p+1) == '"')
     754             :                 {
     755           0 :                     ++p;            // escaped '"'
     756           0 :                     pEndQuote = 0;
     757             :                 }
     758         445 :                 else if (*(p+1) == ';')
     759           0 :                     break;          // end field
     760             :             }
     761             :         }
     762             :     }
     763         941 :     if (!pEndQuote)
     764           0 :         pEndQuote = p;  // Take all data as string.
     765         941 :     rString.Append( pStartQuote + 1, sal::static_int_cast<xub_StrLen>( pEndQuote - pStartQuote - 1 ) );
     766         941 :     lcl_UnescapeSylk( rString, eVersion);
     767         941 :     return p;
     768             : }
     769             : 
     770           0 : static const sal_Unicode* lcl_ScanSylkFormula( const sal_Unicode* p,
     771             :         String& rString, SylkVersion eVersion )
     772             : {
     773           0 :     const sal_Unicode* pStart = p;
     774           0 :     if (eVersion >= SYLK_OOO32)
     775             :     {
     776           0 :         while (*p)
     777             :         {
     778           0 :             if (*p == ';')
     779             :             {
     780           0 :                 if (*(p+1) == ';')
     781           0 :                     ++p;        // escaped ';'
     782             :                 else
     783           0 :                     break;      // end field
     784             :             }
     785           0 :             ++p;
     786             :         }
     787           0 :         rString.Append( pStart, sal::static_int_cast<xub_StrLen>( p - pStart));
     788           0 :         lcl_UnescapeSylk( rString, eVersion);
     789             :     }
     790             :     else
     791             :     {
     792             :         // Nasty. If in old versions the formula contained a semicolon, it was
     793             :         // quoted and embedded quotes were doubled, but semicolons were not. If
     794             :         // there was no semicolon, it could still contain quotes and doubled
     795             :         // embedded quotes if it was something like ="a""b", which was saved as
     796             :         // E"a""b" as is and has to be preserved, even if older versions
     797             :         // couldn't even load it correctly. However, theoretically another
     798             :         // field might follow and thus the line contain a semicolon again, such
     799             :         // as ...;E"a""b";...
     800           0 :         bool bQuoted = false;
     801           0 :         if (*p == '"')
     802             :         {
     803             :             // May be a quoted expression or just a string constant expression
     804             :             // with quotes.
     805           0 :             while (*(++p))
     806             :             {
     807           0 :                 if (*p == '"')
     808             :                 {
     809           0 :                     if (*(p+1) == '"')
     810           0 :                         ++p;            // escaped '"'
     811             :                     else
     812           0 :                         break;          // closing '"', had no ';' yet
     813             :                 }
     814           0 :                 else if (*p == ';')
     815             :                 {
     816           0 :                     bQuoted = true;     // ';' within quoted expression
     817           0 :                     break;
     818             :                 }
     819             :             }
     820           0 :             p = pStart;
     821             :         }
     822           0 :         if (bQuoted)
     823           0 :             p = lcl_ScanSylkString( p, rString, eVersion);
     824             :         else
     825             :         {
     826           0 :             while (*p && *p != ';')
     827           0 :                 ++p;
     828           0 :             rString.Append( pStart, sal::static_int_cast<xub_StrLen>( p - pStart));
     829             :         }
     830             :     }
     831           0 :     return p;
     832             : }
     833             : 
     834           0 : static void lcl_DoubleEscapeChar( String& rString, sal_Unicode cStr )
     835             : {
     836           0 :     xub_StrLen n = 0;
     837           0 :     while( ( n = rString.Search( cStr, n ) ) != STRING_NOTFOUND )
     838             :     {
     839           0 :         rString.Insert( cStr, n );
     840           0 :         n += 2;
     841             :     }
     842           0 : }
     843             : 
     844           0 : static void lcl_WriteString( SvStream& rStrm, String& rString, sal_Unicode cQuote, sal_Unicode cEsc )
     845             : {
     846           0 :     if (cEsc)
     847           0 :         lcl_DoubleEscapeChar( rString, cEsc );
     848             : 
     849           0 :     if (cQuote)
     850             :     {
     851           0 :         rString.Insert( cQuote, 0 );
     852           0 :         rString.Append( cQuote );
     853             :     }
     854             : 
     855           0 :     ScImportExport::WriteUnicodeOrByteString( rStrm, rString );
     856           0 : }
     857             : 
     858           0 : static inline void lcl_WriteSimpleString( SvStream& rStrm, const String& rString )
     859             : {
     860           0 :     ScImportExport::WriteUnicodeOrByteString( rStrm, rString );
     861           0 : }
     862             : 
     863             : //////////////////////////////////////////////////////////////////////////////
     864             : 
     865             : 
     866           0 : bool ScImportExport::Text2Doc( SvStream& rStrm )
     867             : {
     868           0 :     bool bOk = true;
     869             : 
     870             :     sal_Unicode pSeps[2];
     871           0 :     pSeps[0] = cSep;
     872           0 :     pSeps[1] = 0;
     873             : 
     874           0 :     SCCOL nStartCol = aRange.aStart.Col();
     875           0 :     SCROW nStartRow = aRange.aStart.Row();
     876           0 :     SCCOL nEndCol = aRange.aEnd.Col();
     877           0 :     SCROW nEndRow = aRange.aEnd.Row();
     878           0 :     sal_uLong  nOldPos = rStrm.Tell();
     879           0 :     rStrm.StartReadingUnicodeText( rStrm.GetStreamCharSet() );
     880           0 :     bool   bData = !bSingle;
     881           0 :     if( !bSingle)
     882           0 :         bOk = StartPaste();
     883             : 
     884           0 :     while( bOk )
     885             :     {
     886           0 :         rtl::OUString aLine;
     887           0 :         String aCell;
     888           0 :         SCROW nRow = nStartRow;
     889           0 :         rStrm.Seek( nOldPos );
     890           0 :         for( ;; )
     891             :         {
     892           0 :             rStrm.ReadUniOrByteStringLine( aLine, rStrm.GetStreamCharSet(), nArbitraryLineLengthLimit );
     893           0 :             if( rStrm.IsEof() )
     894           0 :                 break;
     895           0 :             SCCOL nCol = nStartCol;
     896           0 :             const sal_Unicode* p = aLine.getStr();
     897           0 :             while( *p )
     898             :             {
     899           0 :                 aCell.Erase();
     900           0 :                 if( *p == cStr )
     901             :                 {
     902           0 :                     p = lcl_ScanString( p, aCell, pSeps, cStr, DQM_KEEP, bOverflowCell );
     903           0 :                     while( *p && *p != cSep )
     904           0 :                         p++;
     905           0 :                     if( *p )
     906           0 :                         p++;
     907             :                 }
     908             :                 else
     909             :                 {
     910           0 :                     const sal_Unicode* q = p;
     911           0 :                     while( *p && *p != cSep )
     912           0 :                         p++;
     913           0 :                     if (!lcl_appendLineData( aCell, q, p))
     914           0 :                         bOverflowCell = true;   // display warning on import
     915           0 :                     if( *p )
     916           0 :                         p++;
     917             :                 }
     918           0 :                 if (ValidCol(nCol) && ValidRow(nRow) )
     919             :                 {
     920           0 :                     if( bSingle )
     921             :                     {
     922           0 :                         if (nCol>nEndCol) nEndCol = nCol;
     923           0 :                         if (nRow>nEndRow) nEndRow = nRow;
     924             :                     }
     925           0 :                     if( bData && nCol <= nEndCol && nRow <= nEndRow )
     926           0 :                         pDoc->SetString( nCol, nRow, aRange.aStart.Tab(), aCell );
     927             :                 }
     928             :                 else                            // zuviele Spalten/Zeilen
     929             :                 {
     930           0 :                     if (!ValidRow(nRow))
     931           0 :                         bOverflowRow = true;    // display warning on import
     932           0 :                     if (!ValidCol(nCol))
     933           0 :                         bOverflowCol = true;    // display warning on import
     934             :                 }
     935           0 :                 ++nCol;
     936             :             }
     937           0 :             ++nRow;
     938             :         }
     939             : 
     940           0 :         if( !bData )
     941             :         {
     942           0 :             aRange.aEnd.SetCol( nEndCol );
     943           0 :             aRange.aEnd.SetRow( nEndRow );
     944           0 :             bOk = StartPaste();
     945           0 :             bData = true;
     946             :         }
     947             :         else
     948             :             break;
     949           0 :     }
     950             : 
     951           0 :     EndPaste();
     952           0 :     return bOk;
     953             : }
     954             : 
     955             :         //
     956             :         //  erweiterter Ascii-Import
     957             :         //
     958             : 
     959             : 
     960         361 : static bool lcl_PutString(
     961             :     ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rStr, sal_uInt8 nColFormat,
     962             :     SvNumberFormatter* pFormatter, bool bDetectNumFormat,
     963             :     ::utl::TransliterationWrapper& rTransliteration, CalendarWrapper& rCalendar,
     964             :     ::utl::TransliterationWrapper* pSecondTransliteration, CalendarWrapper* pSecondCalendar )
     965             : {
     966         361 :     bool bMultiLine = false;
     967         361 :     if ( nColFormat == SC_COL_SKIP || !rStr.Len() || !ValidCol(nCol) || !ValidRow(nRow) )
     968          74 :         return bMultiLine;
     969             : 
     970         287 :     if ( nColFormat == SC_COL_TEXT )
     971             :     {
     972             :         double fDummy;
     973             :         sal_uInt32 nIndex;
     974           0 :         if (pFormatter->IsNumberFormat(rStr, nIndex, fDummy))
     975             :         {
     976             :             // Set the format of this cell to Text.
     977           0 :             sal_uInt32 nFormat = pFormatter->GetStandardFormat(NUMBERFORMAT_TEXT);
     978           0 :             ScPatternAttr aNewAttrs(pDoc->GetPool());
     979           0 :             SfxItemSet& rSet = aNewAttrs.GetItemSet();
     980           0 :             rSet.Put( SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat) );
     981           0 :             pDoc->ApplyPattern(nCol, nRow, nTab, aNewAttrs);
     982             : 
     983             :         }
     984           0 :         pDoc->PutCell( nCol, nRow, nTab, ScBaseCell::CreateTextCell( rStr, pDoc ) );
     985           0 :         return bMultiLine;
     986             :     }
     987             : 
     988         287 :     if ( nColFormat == SC_COL_ENGLISH )
     989             :     {
     990             :         //! SetString mit Extra-Flag ???
     991             : 
     992           0 :         SvNumberFormatter* pDocFormatter = pDoc->GetFormatTable();
     993           0 :         sal_uInt32 nEnglish = pDocFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
     994             :         double fVal;
     995           0 :         if ( pDocFormatter->IsNumberFormat( rStr, nEnglish, fVal ) )
     996             :         {
     997             :             //  Zahlformat wird nicht auf englisch gesetzt
     998           0 :             pDoc->SetValue( nCol, nRow, nTab, fVal );
     999           0 :             return bMultiLine;
    1000             :         }
    1001             :         //  sonst weiter mit SetString
    1002             :     }
    1003         287 :     else if ( nColFormat != SC_COL_STANDARD )                   // Datumsformate
    1004             :     {
    1005           0 :         const sal_uInt16 nMaxNumberParts = 7;   // Y-M-D h:m:s.t
    1006           0 :         xub_StrLen nLen = rStr.Len();
    1007             :         xub_StrLen nStart[nMaxNumberParts];
    1008             :         xub_StrLen nEnd[nMaxNumberParts];
    1009             : 
    1010             :         sal_uInt16 nDP, nMP, nYP;
    1011           0 :         switch ( nColFormat )
    1012             :         {
    1013           0 :             case SC_COL_YMD: nDP = 2; nMP = 1; nYP = 0; break;
    1014           0 :             case SC_COL_MDY: nDP = 1; nMP = 0; nYP = 2; break;
    1015             :             case SC_COL_DMY:
    1016           0 :             default:         nDP = 0; nMP = 1; nYP = 2; break;
    1017             :         }
    1018             : 
    1019           0 :         sal_uInt16 nFound = 0;
    1020           0 :         bool bInNum = false;
    1021           0 :         for ( xub_StrLen nPos=0; nPos<nLen && (bInNum ||
    1022             :                     nFound<nMaxNumberParts); nPos++ )
    1023             :         {
    1024           0 :             if (bInNum && nFound == 3 && nColFormat == SC_COL_YMD &&
    1025           0 :                     nPos <= nStart[nFound]+2 && rStr.GetChar(nPos) == 'T')
    1026           0 :                 bInNum = false;     // ISO-8601: YYYY-MM-DDThh:mm...
    1027           0 :             else if ((((!bInNum && nFound==nMP) || (bInNum && nFound==nMP+1))
    1028           0 :                         && ScGlobal::pCharClass->isLetterNumeric( rStr, nPos))
    1029           0 :                     || ScGlobal::pCharClass->isDigit( rStr, nPos))
    1030             :             {
    1031           0 :                 if (!bInNum)
    1032             :                 {
    1033           0 :                     bInNum = true;
    1034           0 :                     nStart[nFound] = nPos;
    1035           0 :                     ++nFound;
    1036             :                 }
    1037           0 :                 nEnd[nFound-1] = nPos;
    1038             :             }
    1039             :             else
    1040           0 :                 bInNum = false;
    1041             :         }
    1042             : 
    1043           0 :         if ( nFound == 1 )
    1044             :         {
    1045             :             //  try to break one number (without separators) into date fields
    1046             : 
    1047           0 :             xub_StrLen nDateStart = nStart[0];
    1048           0 :             xub_StrLen nDateLen = nEnd[0] + 1 - nDateStart;
    1049             : 
    1050           0 :             if ( nDateLen >= 5 && nDateLen <= 8 &&
    1051           0 :                     ScGlobal::pCharClass->isNumeric( rStr.Copy( nDateStart, nDateLen ) ) )
    1052             :             {
    1053             :                 //  6 digits: 2 each for day, month, year
    1054             :                 //  8 digits: 4 for year, 2 each for day and month
    1055             :                 //  5 or 7 digits: first field is shortened by 1
    1056             : 
    1057           0 :                 bool bLongYear = ( nDateLen >= 7 );
    1058           0 :                 bool bShortFirst = ( nDateLen == 5 || nDateLen == 7 );
    1059             : 
    1060           0 :                 sal_uInt16 nFieldStart = nDateStart;
    1061           0 :                 for (sal_uInt16 nPos=0; nPos<3; nPos++)
    1062             :                 {
    1063           0 :                     sal_uInt16 nFieldEnd = nFieldStart + 1;     // default: 2 digits
    1064           0 :                     if ( bLongYear && nPos == nYP )
    1065           0 :                         nFieldEnd += 2;                     // 2 extra digits for long year
    1066           0 :                     if ( bShortFirst && nPos == 0 )
    1067           0 :                         --nFieldEnd;                        // first field shortened?
    1068             : 
    1069           0 :                     nStart[nPos] = nFieldStart;
    1070           0 :                     nEnd[nPos]   = nFieldEnd;
    1071           0 :                     nFieldStart  = nFieldEnd + 1;
    1072             :                 }
    1073           0 :                 nFound = 3;
    1074             :             }
    1075             :         }
    1076             : 
    1077           0 :         if ( nFound >= 3 )
    1078             :         {
    1079             :             using namespace ::com::sun::star;
    1080           0 :             bool bSecondCal = false;
    1081           0 :             sal_uInt16 nDay  = (sal_uInt16) rStr.Copy( nStart[nDP], nEnd[nDP]+1-nStart[nDP] ).ToInt32();
    1082           0 :             sal_uInt16 nYear = (sal_uInt16) rStr.Copy( nStart[nYP], nEnd[nYP]+1-nStart[nYP] ).ToInt32();
    1083           0 :             String aMStr = rStr.Copy( nStart[nMP], nEnd[nMP]+1-nStart[nMP] );
    1084           0 :             sal_Int16 nMonth = (sal_Int16) aMStr.ToInt32();
    1085           0 :             if (!nMonth)
    1086             :             {
    1087           0 :                 static const String aSeptCorrect( RTL_CONSTASCII_USTRINGPARAM( "SEPT" ) );
    1088           0 :                 static const String aSepShortened( RTL_CONSTASCII_USTRINGPARAM( "SEP" ) );
    1089           0 :                 uno::Sequence< i18n::CalendarItem2 > xMonths;
    1090             :                 sal_Int32 i, nMonthCount;
    1091             :                 //  first test all month names from local international
    1092           0 :                 xMonths = rCalendar.getMonths();
    1093           0 :                 nMonthCount = xMonths.getLength();
    1094           0 :                 for (i=0; i<nMonthCount && !nMonth; i++)
    1095             :                 {
    1096           0 :                     if ( rTransliteration.isEqual( aMStr, xMonths[i].FullName ) ||
    1097           0 :                          rTransliteration.isEqual( aMStr, xMonths[i].AbbrevName ) )
    1098           0 :                         nMonth = sal::static_int_cast<sal_Int16>( i+1 );
    1099           0 :                     else if ( i == 8 && rTransliteration.isEqual( aSeptCorrect,
    1100           0 :                                 xMonths[i].AbbrevName ) &&
    1101           0 :                             rTransliteration.isEqual( aMStr, aSepShortened ) )
    1102             :                     {   // correct English abbreviation is SEPT,
    1103             :                         // but data mostly contains SEP only
    1104           0 :                         nMonth = sal::static_int_cast<sal_Int16>( i+1 );
    1105             :                     }
    1106             :                 }
    1107             :                 //  if none found, then test english month names
    1108           0 :                 if ( !nMonth && pSecondCalendar && pSecondTransliteration )
    1109             :                 {
    1110           0 :                     xMonths = pSecondCalendar->getMonths();
    1111           0 :                     nMonthCount = xMonths.getLength();
    1112           0 :                     for (i=0; i<nMonthCount && !nMonth; i++)
    1113             :                     {
    1114           0 :                         if ( pSecondTransliteration->isEqual( aMStr, xMonths[i].FullName ) ||
    1115           0 :                              pSecondTransliteration->isEqual( aMStr, xMonths[i].AbbrevName ) )
    1116             :                         {
    1117           0 :                             nMonth = sal::static_int_cast<sal_Int16>( i+1 );
    1118           0 :                             bSecondCal = true;
    1119             :                         }
    1120           0 :                         else if ( i == 8 && pSecondTransliteration->isEqual(
    1121           0 :                                     aMStr, aSepShortened ) )
    1122             :                         {   // correct English abbreviation is SEPT,
    1123             :                             // but data mostly contains SEP only
    1124           0 :                             nMonth = sal::static_int_cast<sal_Int16>( i+1 );
    1125           0 :                             bSecondCal = true;
    1126             :                         }
    1127             :                     }
    1128           0 :                 }
    1129             :             }
    1130             : 
    1131           0 :             SvNumberFormatter* pDocFormatter = pDoc->GetFormatTable();
    1132           0 :             if ( nYear < 100 )
    1133           0 :                 nYear = pDocFormatter->ExpandTwoDigitYear( nYear );
    1134             : 
    1135           0 :             CalendarWrapper* pCalendar = (bSecondCal ? pSecondCalendar : &rCalendar);
    1136           0 :             sal_Int16 nNumMonths = pCalendar->getNumberOfMonthsInYear();
    1137           0 :             if ( nDay && nMonth && nDay<=31 && nMonth<=nNumMonths )
    1138             :             {
    1139           0 :                 --nMonth;
    1140           0 :                 pCalendar->setValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, nDay );
    1141           0 :                 pCalendar->setValue( i18n::CalendarFieldIndex::MONTH, nMonth );
    1142           0 :                 pCalendar->setValue( i18n::CalendarFieldIndex::YEAR, nYear );
    1143             :                 sal_Int16 nHour, nMinute, nSecond, nMilli;
    1144             :                 // #i14974# The imported value should have no fractional value, so set the
    1145             :                 // time fields to zero (ICU calendar instance defaults to current date/time)
    1146           0 :                 nHour = nMinute = nSecond = nMilli = 0;
    1147           0 :                 if (nFound > 3)
    1148           0 :                     nHour = (sal_Int16) rStr.Copy( nStart[3], nEnd[3]+1-nStart[3]).ToInt32();
    1149           0 :                 if (nFound > 4)
    1150           0 :                     nMinute = (sal_Int16) rStr.Copy( nStart[4], nEnd[4]+1-nStart[4]).ToInt32();
    1151           0 :                 if (nFound > 5)
    1152           0 :                     nSecond = (sal_Int16) rStr.Copy( nStart[5], nEnd[5]+1-nStart[5]).ToInt32();
    1153           0 :                 if (nFound > 6)
    1154             :                 {
    1155           0 :                     sal_Unicode cDec = '.';
    1156           0 :                     rtl::OUString aT( &cDec, 1);
    1157           0 :                     aT += rStr.Copy( nStart[6], nEnd[6]+1-nStart[6]);
    1158             :                     rtl_math_ConversionStatus eStatus;
    1159           0 :                     double fV = rtl::math::stringToDouble( aT, cDec, 0, &eStatus, 0);
    1160           0 :                     if (eStatus == rtl_math_ConversionStatus_Ok)
    1161           0 :                         nMilli = (sal_Int16) (1000.0 * fV + 0.5);
    1162             :                 }
    1163           0 :                 pCalendar->setValue( i18n::CalendarFieldIndex::HOUR, nHour );
    1164           0 :                 pCalendar->setValue( i18n::CalendarFieldIndex::MINUTE, nMinute );
    1165           0 :                 pCalendar->setValue( i18n::CalendarFieldIndex::SECOND, nSecond );
    1166           0 :                 pCalendar->setValue( i18n::CalendarFieldIndex::MILLISECOND, nMilli );
    1167           0 :                 if ( pCalendar->isValid() )
    1168             :                 {
    1169           0 :                     double fDiff = DateTime(*pDocFormatter->GetNullDate()) -
    1170           0 :                         pCalendar->getEpochStart();
    1171             :                     // #i14974# must use getLocalDateTime to get the same
    1172             :                     // date values as set above
    1173           0 :                     double fDays = pCalendar->getLocalDateTime();
    1174           0 :                     fDays -= fDiff;
    1175             : 
    1176             :                     LanguageType eLatin, eCjk, eCtl;
    1177           0 :                     pDoc->GetLanguage( eLatin, eCjk, eCtl );
    1178           0 :                     LanguageType eDocLang = eLatin;     //! which language for date formats?
    1179             : 
    1180           0 :                     short nType = (nFound > 3 ? NUMBERFORMAT_DATETIME : NUMBERFORMAT_DATE);
    1181           0 :                     sal_uLong nFormat = pDocFormatter->GetStandardFormat( nType, eDocLang );
    1182             :                     // maybe there is a special format including seconds or milliseconds
    1183           0 :                     if (nFound > 5)
    1184           0 :                         nFormat = pDocFormatter->GetStandardFormat( fDays, nFormat, nType, eDocLang);
    1185             : 
    1186           0 :                     pDoc->PutCell( nCol, nRow, nTab, new ScValueCell(fDays), nFormat, false );
    1187             : 
    1188           0 :                     return bMultiLine;     // success
    1189             :                 }
    1190           0 :             }
    1191             :         }
    1192             :     }
    1193             : 
    1194             :     // Standard or date not determined -> SetString / EditCell
    1195         287 :     if( rStr.Search( _LF ) == STRING_NOTFOUND )
    1196             :     {
    1197         271 :         ScSetStringParam aParam;
    1198         271 :         aParam.mpNumFormatter = pFormatter;
    1199         271 :         aParam.mbDetectNumberFormat = bDetectNumFormat;
    1200         271 :         aParam.meSetTextNumFormat = ScSetStringParam::SpecialNumberOnly;
    1201         271 :         aParam.mbHandleApostrophe = false;
    1202         271 :         pDoc->SetString( nCol, nRow, nTab, rStr, &aParam );
    1203             :     }
    1204             :     else
    1205             :     {
    1206          16 :         bMultiLine = true;
    1207          16 :         pDoc->PutCell( nCol, nRow, nTab, new ScEditCell( rStr, pDoc ) );
    1208             :     }
    1209         287 :     return bMultiLine;
    1210             : }
    1211             : 
    1212             : 
    1213           0 : static String lcl_GetFixed( const rtl::OUString& rLine, sal_Int32 nStart, sal_Int32 nNext,
    1214             :                      bool& rbIsQuoted, bool& rbOverflowCell )
    1215             : {
    1216           0 :     sal_Int32 nLen = rLine.getLength();
    1217           0 :     if (nNext > nLen)
    1218           0 :         nNext = nLen;
    1219           0 :     if ( nNext <= nStart )
    1220           0 :         return EMPTY_STRING;
    1221             : 
    1222           0 :     const sal_Unicode* pStr = rLine.getStr();
    1223             : 
    1224           0 :     sal_Int32 nSpace = nNext;
    1225           0 :     while ( nSpace > nStart && pStr[nSpace-1] == ' ' )
    1226           0 :         --nSpace;
    1227             : 
    1228           0 :     rbIsQuoted = (pStr[nStart] == sal_Unicode('"') && pStr[nSpace-1] == sal_Unicode('"'));
    1229           0 :     if (rbIsQuoted)
    1230             :     {
    1231           0 :         bool bFits = (nSpace - nStart - 3 <= STRING_MAXLEN);
    1232             :         OSL_ENSURE( bFits, "lcl_GetFixed: line doesn't fit into data");
    1233           0 :         if (bFits)
    1234           0 :             return rLine.copy(nStart+1, nSpace-nStart-2);
    1235             :         else
    1236             :         {
    1237           0 :             rbOverflowCell = true;
    1238           0 :             return rLine.copy(nStart+1, STRING_MAXLEN);
    1239             :         }
    1240             :     }
    1241             :     else
    1242             :     {
    1243           0 :         bool bFits = (nSpace - nStart <= STRING_MAXLEN);
    1244             :         OSL_ENSURE( bFits, "lcl_GetFixed: line doesn't fit into data");
    1245           0 :         if (bFits)
    1246           0 :             return rLine.copy(nStart, nSpace-nStart);
    1247             :         else
    1248             :         {
    1249           0 :             rbOverflowCell = true;
    1250           0 :             return rLine.copy(nStart, STRING_MAXLEN);
    1251             :         }
    1252             :     }
    1253             : }
    1254             : 
    1255           2 : bool ScImportExport::ExtText2Doc( SvStream& rStrm )
    1256             : {
    1257           2 :     if (!pExtOptions)
    1258           0 :         return Text2Doc( rStrm );
    1259             : 
    1260           2 :     sal_uLong nOldPos = rStrm.Tell();
    1261           2 :     rStrm.Seek( STREAM_SEEK_TO_END );
    1262             :     ::std::auto_ptr<ScProgress> xProgress( new ScProgress( pDocSh,
    1263           2 :             ScGlobal::GetRscString( STR_LOAD_DOC ), rStrm.Tell() - nOldPos ));
    1264           2 :     rStrm.Seek( nOldPos );
    1265           2 :     rStrm.StartReadingUnicodeText( rStrm.GetStreamCharSet() );
    1266             : 
    1267           2 :     SCCOL nStartCol = aRange.aStart.Col();
    1268           2 :     SCCOL nEndCol = aRange.aEnd.Col();
    1269           2 :     SCROW nStartRow = aRange.aStart.Row();
    1270           2 :     SCTAB nTab = aRange.aStart.Tab();
    1271             : 
    1272           2 :     bool    bFixed              = pExtOptions->IsFixedLen();
    1273           2 :     const String& rSeps         = pExtOptions->GetFieldSeps();
    1274           2 :     const sal_Unicode* pSeps    = rSeps.GetBuffer();
    1275           2 :     bool    bMerge              = pExtOptions->IsMergeSeps();
    1276           2 :     sal_uInt16  nInfoCount      = pExtOptions->GetInfoCount();
    1277           2 :     const sal_Int32* pColStart  = pExtOptions->GetColStart();
    1278           2 :     const sal_uInt8* pColFormat = pExtOptions->GetColFormat();
    1279           2 :     long nSkipLines             = pExtOptions->GetStartRow();
    1280             : 
    1281           2 :     LanguageType eDocLang = pExtOptions->GetLanguage();
    1282           2 :     SvNumberFormatter aNumFormatter(pDoc->GetServiceManager(), eDocLang);
    1283           2 :     bool bDetectNumFormat = pExtOptions->IsDetectSpecialNumber();
    1284             : 
    1285             :     // For date recognition
    1286             :     ::utl::TransliterationWrapper aTransliteration(
    1287           2 :         comphelper::getComponentContext(pDoc->GetServiceManager()), SC_TRANSLITERATION_IGNORECASE );
    1288           2 :     aTransliteration.loadModuleIfNeeded( eDocLang );
    1289           2 :     CalendarWrapper aCalendar( comphelper::getComponentContext(pDoc->GetServiceManager()) );
    1290             :     aCalendar.loadDefaultCalendar(
    1291           2 :         LanguageTag( eDocLang ).getLocale() );
    1292           2 :     ::utl::TransliterationWrapper* pEnglishTransliteration = NULL;
    1293           2 :     CalendarWrapper* pEnglishCalendar = NULL;
    1294           2 :     if ( eDocLang != LANGUAGE_ENGLISH_US )
    1295             :     {
    1296             :         pEnglishTransliteration = new ::utl::TransliterationWrapper (
    1297           2 :             comphelper::getComponentContext(pDoc->GetServiceManager()), SC_TRANSLITERATION_IGNORECASE );
    1298           2 :         aTransliteration.loadModuleIfNeeded( LANGUAGE_ENGLISH_US );
    1299           2 :         pEnglishCalendar = new CalendarWrapper ( comphelper::getComponentContext(pDoc->GetServiceManager()) );
    1300             :         pEnglishCalendar->loadDefaultCalendar(
    1301           2 :             LanguageTag( LANGUAGE_ENGLISH_US ).getLocale() );
    1302             :     }
    1303             : 
    1304           2 :     rtl::OUString aLine;
    1305           2 :     String aCell;
    1306             :     sal_uInt16 i;
    1307           2 :     SCROW nRow = nStartRow;
    1308             : 
    1309           4 :     while(--nSkipLines>0)
    1310             :     {
    1311           0 :         aLine = ReadCsvLine(rStrm, !bFixed, rSeps, cStr); // content is ignored
    1312           0 :         if ( rStrm.IsEof() )
    1313           0 :             break;
    1314             :     }
    1315             : 
    1316             :     // Determine range for Undo.
    1317             :     // TODO: we don't need this during import of a file to a new sheet or
    1318             :     // document, could set bDetermineRange=false then.
    1319           2 :     bool bDetermineRange = true;
    1320             : 
    1321             :     // Row heights don't need to be adjusted on the fly if EndPaste() is called
    1322             :     // afterwards, which happens only if bDetermineRange. This variable also
    1323             :     // survives the toggle of bDetermineRange down at the end of the do{} loop.
    1324           2 :     bool bRangeIsDetermined = bDetermineRange;
    1325             : 
    1326           2 :     bool bQuotedAsText = pExtOptions && pExtOptions->IsQuotedAsText();
    1327             : 
    1328           2 :     sal_uLong nOriginalStreamPos = rStrm.Tell();
    1329             : 
    1330           4 :     do
    1331             :     {
    1332         142 :         for( ;; )
    1333             :         {
    1334         146 :             aLine = ReadCsvLine(rStrm, !bFixed, rSeps, cStr);
    1335         146 :             if ( rStrm.IsEof() && aLine.isEmpty() )
    1336           4 :                 break;
    1337             : 
    1338         142 :             sal_Int32 nLineLen = aLine.getLength();
    1339         142 :             SCCOL nCol = nStartCol;
    1340         142 :             bool bMultiLine = false;
    1341         142 :             if ( bFixed )               //  Feste Satzlaenge
    1342             :             {
    1343             :                 // Yes, the check is nCol<=MAXCOL+1, +1 because it is only an
    1344             :                 // overflow if there is really data following to be put behind
    1345             :                 // the last column, which doesn't happen if info is
    1346             :                 // SC_COL_SKIP.
    1347           0 :                 for ( i=0; i<nInfoCount && nCol <= MAXCOL+1; i++ )
    1348             :                 {
    1349           0 :                     sal_uInt8 nFmt = pColFormat[i];
    1350           0 :                     if (nFmt != SC_COL_SKIP)        // sonst auch nCol nicht hochzaehlen
    1351             :                     {
    1352           0 :                         if (nCol > MAXCOL)
    1353           0 :                             bOverflowCol = true;    // display warning on import
    1354           0 :                         else if (!bDetermineRange)
    1355             :                         {
    1356           0 :                             sal_Int32 nStart = pColStart[i];
    1357           0 :                             sal_Int32 nNext = ( i+1 < nInfoCount ) ? pColStart[i+1] : nLineLen;
    1358           0 :                             bool bIsQuoted = false;
    1359           0 :                             aCell = lcl_GetFixed( aLine, nStart, nNext, bIsQuoted, bOverflowCell );
    1360           0 :                             if (bIsQuoted && bQuotedAsText)
    1361           0 :                                 nFmt = SC_COL_TEXT;
    1362             : 
    1363             :                             bMultiLine |= lcl_PutString(
    1364             :                                 pDoc, nCol, nRow, nTab, aCell, nFmt,
    1365             :                                 &aNumFormatter, bDetectNumFormat, aTransliteration, aCalendar,
    1366           0 :                                 pEnglishTransliteration, pEnglishCalendar);
    1367             :                         }
    1368           0 :                         ++nCol;
    1369             :                     }
    1370             :                 }
    1371             :             }
    1372             :             else                        //  Nach Trennzeichen suchen
    1373             :             {
    1374         142 :                 SCCOL nSourceCol = 0;
    1375         142 :                 sal_uInt16 nInfoStart = 0;
    1376         142 :                 const sal_Unicode* p = aLine.getStr();
    1377             :                 // Yes, the check is nCol<=MAXCOL+1, +1 because it is only an
    1378             :                 // overflow if there is really data following to be put behind
    1379             :                 // the last column, which doesn't happen if info is
    1380             :                 // SC_COL_SKIP.
    1381        1006 :                 while (*p && nCol <= MAXCOL+1)
    1382             :                 {
    1383         722 :                     bool bIsQuoted = false;
    1384             :                     p = ScImportExport::ScanNextFieldFromString( p, aCell,
    1385         722 :                             cStr, pSeps, bMerge, bIsQuoted, bOverflowCell );
    1386             : 
    1387         722 :                     sal_uInt8 nFmt = SC_COL_STANDARD;
    1388         722 :                     for ( i=nInfoStart; i<nInfoCount; i++ )
    1389             :                     {
    1390           0 :                         if ( pColStart[i] == nSourceCol + 1 )       // pColStart ist 1-basiert
    1391             :                         {
    1392           0 :                             nFmt = pColFormat[i];
    1393           0 :                             nInfoStart = i + 1;     // ColInfos sind in Reihenfolge
    1394           0 :                             break;  // for
    1395             :                         }
    1396             :                     }
    1397         722 :                     if ( nFmt != SC_COL_SKIP )
    1398             :                     {
    1399         722 :                         if (nCol > MAXCOL)
    1400           0 :                             bOverflowCol = true;    // display warning on import
    1401         722 :                         else if (!bDetermineRange)
    1402             :                         {
    1403         361 :                             if (bIsQuoted && bQuotedAsText)
    1404           0 :                                 nFmt = SC_COL_TEXT;
    1405             : 
    1406             :                             bMultiLine |= lcl_PutString(
    1407             :                                 pDoc, nCol, nRow, nTab, aCell, nFmt,
    1408             :                                 &aNumFormatter, bDetectNumFormat, aTransliteration,
    1409         361 :                                 aCalendar, pEnglishTransliteration, pEnglishCalendar);
    1410             :                         }
    1411         722 :                         ++nCol;
    1412             :                     }
    1413             : 
    1414         722 :                     ++nSourceCol;
    1415             :                 }
    1416             :             }
    1417         142 :             if (nEndCol < nCol)
    1418           6 :                 nEndCol = nCol;     //! points to the next free or even MAXCOL+2
    1419             : 
    1420         142 :             if (!bDetermineRange)
    1421             :             {
    1422          71 :                 if (bMultiLine && !bRangeIsDetermined && pDocSh)
    1423           0 :                     pDocSh->AdjustRowHeight( nRow, nRow, nTab);
    1424          71 :                 xProgress->SetStateOnPercent( rStrm.Tell() - nOldPos );
    1425             :             }
    1426         142 :             ++nRow;
    1427         142 :             if ( nRow > MAXROW )
    1428             :             {
    1429           0 :                 bOverflowRow = true;    // display warning on import
    1430           0 :                 break;  // for
    1431             :             }
    1432             :         }
    1433             :         // so far nRow/nEndCol pointed to the next free
    1434           4 :         if (nRow > nStartRow)
    1435           4 :             --nRow;
    1436           4 :         if (nEndCol > nStartCol)
    1437           4 :             nEndCol = ::std::min( static_cast<SCCOL>(nEndCol - 1), MAXCOL);
    1438             : 
    1439           4 :         if (bDetermineRange)
    1440             :         {
    1441           2 :             aRange.aEnd.SetCol( nEndCol );
    1442           2 :             aRange.aEnd.SetRow( nRow );
    1443             : 
    1444           2 :             if ( !mbApi && nStartCol != nEndCol &&
    1445           0 :                  !pDoc->IsBlockEmpty( nTab, nStartCol + 1, nStartRow, nEndCol, nRow ) )
    1446             :             {
    1447           0 :                 ScReplaceWarnBox aBox( pDocSh->GetActiveDialogParent() );
    1448           0 :                 if ( aBox.Execute() != RET_YES )
    1449             :                 {
    1450           0 :                     delete pEnglishTransliteration;
    1451           0 :                     delete pEnglishCalendar;
    1452           0 :                     return false;
    1453           0 :                 }
    1454             :             }
    1455             : 
    1456           2 :             rStrm.Seek( nOriginalStreamPos );
    1457           2 :             nRow = nStartRow;
    1458           2 :             if (!StartPaste())
    1459             :             {
    1460           0 :                 EndPaste();
    1461           0 :                 return false;
    1462             :             }
    1463             :         }
    1464             : 
    1465           4 :         bDetermineRange = !bDetermineRange;     // toggle
    1466           4 :     } while (!bDetermineRange);
    1467             : 
    1468           2 :     pDoc->DoColResize( nTab, nStartCol, nEndCol, 0 );
    1469             : 
    1470           2 :     delete pEnglishTransliteration;
    1471           2 :     delete pEnglishCalendar;
    1472             : 
    1473           2 :     xProgress.reset();    // make room for AdjustRowHeight progress
    1474           2 :     if (bRangeIsDetermined)
    1475           2 :         EndPaste();
    1476             : 
    1477           2 :     return true;
    1478             : }
    1479             : 
    1480             : 
    1481         722 : const sal_Unicode* ScImportExport::ScanNextFieldFromString( const sal_Unicode* p,
    1482             :         String& rField, sal_Unicode cStr, const sal_Unicode* pSeps, bool bMergeSeps, bool& rbIsQuoted,
    1483             :         bool& rbOverflowCell )
    1484             : {
    1485         722 :     rbIsQuoted = false;
    1486         722 :     rField.Erase();
    1487         722 :     const sal_Unicode cBlank = ' ';
    1488         722 :     if (!ScGlobal::UnicodeStrChr( pSeps, cBlank))
    1489             :     {
    1490             :         // Cope with broken generators that put leading blanks before a quoted
    1491             :         // field, like "field1", "field2", "..."
    1492             :         // NOTE: this is not in conformance with http://tools.ietf.org/html/rfc4180
    1493         722 :         const sal_Unicode* pb = p;
    1494        1468 :         while (*pb == cBlank)
    1495          24 :             ++pb;
    1496         722 :         if (*pb == cStr)
    1497         386 :             p = pb;
    1498             :     }
    1499         722 :     if ( *p == cStr )           // String in quotes
    1500             :     {
    1501         386 :         rbIsQuoted = true;
    1502             :         const sal_Unicode* p1;
    1503         386 :         p1 = p = lcl_ScanString( p, rField, pSeps, cStr, DQM_ESCAPE, rbOverflowCell );
    1504         780 :         while ( *p && !ScGlobal::UnicodeStrChr( pSeps, *p ) )
    1505           8 :             p++;
    1506             :         // Append remaining unquoted and undelimited data (dirty, dirty) to
    1507             :         // this field.
    1508         386 :         if (p > p1)
    1509             :         {
    1510           8 :             if (!lcl_appendLineData( rField, p1, p))
    1511           0 :                 rbOverflowCell = true;
    1512             :         }
    1513         386 :         if( *p )
    1514         354 :             p++;
    1515             :     }
    1516             :     else                        // up to delimiter
    1517             :     {
    1518         336 :         const sal_Unicode* p0 = p;
    1519        3410 :         while ( *p && !ScGlobal::UnicodeStrChr( pSeps, *p ) )
    1520        2738 :             p++;
    1521         336 :         if (!lcl_appendLineData( rField, p0, p))
    1522           0 :             rbOverflowCell = true;
    1523         336 :         if( *p )
    1524         252 :             p++;
    1525             :     }
    1526         722 :     if ( bMergeSeps )           // skip following delimiters
    1527             :     {
    1528           0 :         while ( *p && ScGlobal::UnicodeStrChr( pSeps, *p ) )
    1529           0 :             p++;
    1530             :     }
    1531         722 :     return p;
    1532             : }
    1533             : 
    1534             : namespace {
    1535             : 
    1536             : /**
    1537             :  * Check if a given string has any line break characters or separators.
    1538             :  *
    1539             :  * @param rStr string to inspect.
    1540             :  * @param cSep separator character.
    1541             :  */
    1542           0 : bool hasLineBreaksOrSeps( const String& rStr, sal_Unicode cSep )
    1543             : {
    1544           0 :     const sal_Unicode* p = rStr.GetBuffer();
    1545           0 :     for (xub_StrLen i = 0, n = rStr.Len(); i < n; ++i, ++p)
    1546             :     {
    1547           0 :         sal_Unicode c = *p;
    1548           0 :         if (c == cSep)
    1549             :             // separator found.
    1550           0 :             return true;
    1551             : 
    1552           0 :         switch (c)
    1553             :         {
    1554             :             case _LF:
    1555             :             case _CR:
    1556             :                 // line break found.
    1557           0 :                 return true;
    1558             :             default:
    1559             :                 ;
    1560             :         }
    1561             :     }
    1562           0 :     return false;
    1563             : }
    1564             : 
    1565             : }
    1566             : 
    1567           0 : bool ScImportExport::Doc2Text( SvStream& rStrm )
    1568             : {
    1569             :     SCCOL nCol;
    1570             :     SCROW nRow;
    1571           0 :     SCCOL nStartCol = aRange.aStart.Col();
    1572           0 :     SCROW nStartRow = aRange.aStart.Row();
    1573           0 :     SCTAB nStartTab = aRange.aStart.Tab();
    1574           0 :     SCCOL nEndCol = aRange.aEnd.Col();
    1575           0 :     SCROW nEndRow = aRange.aEnd.Row();
    1576           0 :     SCTAB nEndTab = aRange.aEnd.Tab();
    1577             : 
    1578           0 :     if (!pDoc->GetClipParam().isMultiRange() && nStartTab == nEndTab)
    1579           0 :         pDoc->ShrinkToDataArea( nStartTab, nStartCol, nStartRow, nEndCol, nEndRow );
    1580             : 
    1581           0 :     String aCell;
    1582             : 
    1583           0 :     bool bConvertLF = (GetSystemLineEnd() != LINEEND_LF);
    1584             : 
    1585           0 :     for (nRow = nStartRow; nRow <= nEndRow; nRow++)
    1586             :     {
    1587           0 :         if (bIncludeFiltered || !pDoc->RowFiltered( nRow, nStartTab ))
    1588             :         {
    1589           0 :             for (nCol = nStartCol; nCol <= nEndCol; nCol++)
    1590             :             {
    1591             :                 CellType eType;
    1592           0 :                 pDoc->GetCellType( nCol, nRow, nStartTab, eType );
    1593           0 :                 switch (eType)
    1594             :                 {
    1595             :                     case CELLTYPE_FORMULA:
    1596             :                     {
    1597           0 :                         if (bFormulas)
    1598             :                         {
    1599           0 :                             pDoc->GetFormula( nCol, nRow, nStartTab, aCell );
    1600           0 :                             if( aCell.Search( cSep ) != STRING_NOTFOUND )
    1601           0 :                                 lcl_WriteString( rStrm, aCell, cStr, cStr );
    1602             :                             else
    1603           0 :                                 lcl_WriteSimpleString( rStrm, aCell );
    1604             :                         }
    1605             :                         else
    1606             :                         {
    1607           0 :                             pDoc->GetString( nCol, nRow, nStartTab, aCell );
    1608             : 
    1609           0 :                             bool bMultiLineText = ( aCell.Search( _LF ) != STRING_NOTFOUND );
    1610           0 :                             if( bMultiLineText )
    1611             :                             {
    1612           0 :                                 if( mExportTextOptions.meNewlineConversion == ScExportTextOptions::ToSpace )
    1613           0 :                                     aCell.SearchAndReplaceAll( _LF, ' ' );
    1614           0 :                                 else if ( mExportTextOptions.meNewlineConversion == ScExportTextOptions::ToSystem && bConvertLF )
    1615           0 :                                     aCell = convertLineEnd(aCell, GetSystemLineEnd());
    1616             :                             }
    1617             : 
    1618           0 :                             if( mExportTextOptions.mcSeparatorConvertTo && cSep )
    1619           0 :                                 aCell.SearchAndReplaceAll( cSep, mExportTextOptions.mcSeparatorConvertTo );
    1620             : 
    1621           0 :                             if( mExportTextOptions.mbAddQuotes && ( aCell.Search( cSep ) != STRING_NOTFOUND ) )
    1622           0 :                                 lcl_WriteString( rStrm, aCell, cStr, cStr );
    1623             :                             else
    1624           0 :                                 lcl_WriteSimpleString( rStrm, aCell );
    1625             :                         }
    1626             :                     }
    1627           0 :                     break;
    1628             :                     case CELLTYPE_VALUE:
    1629             :                     {
    1630           0 :                         pDoc->GetString( nCol, nRow, nStartTab, aCell );
    1631           0 :                         lcl_WriteSimpleString( rStrm, aCell );
    1632             :                     }
    1633           0 :                     break;
    1634             :                     case CELLTYPE_NOTE:
    1635             :                     case CELLTYPE_NONE:
    1636           0 :                     break;
    1637             :                     default:
    1638             :                     {
    1639           0 :                         pDoc->GetString( nCol, nRow, nStartTab, aCell );
    1640             : 
    1641           0 :                         bool bMultiLineText = ( aCell.Search( _LF ) != STRING_NOTFOUND );
    1642           0 :                         if( bMultiLineText )
    1643             :                         {
    1644           0 :                             if( mExportTextOptions.meNewlineConversion == ScExportTextOptions::ToSpace )
    1645           0 :                                 aCell.SearchAndReplaceAll( _LF, ' ' );
    1646           0 :                             else if ( mExportTextOptions.meNewlineConversion == ScExportTextOptions::ToSystem && bConvertLF )
    1647           0 :                                 aCell = convertLineEnd(aCell, GetSystemLineEnd());
    1648             :                         }
    1649             : 
    1650           0 :                         if( mExportTextOptions.mcSeparatorConvertTo && cSep )
    1651           0 :                             aCell.SearchAndReplaceAll( cSep, mExportTextOptions.mcSeparatorConvertTo );
    1652             : 
    1653           0 :                         if( mExportTextOptions.mbAddQuotes && hasLineBreaksOrSeps(aCell, cSep) )
    1654           0 :                             lcl_WriteString( rStrm, aCell, cStr, cStr );
    1655             :                         else
    1656           0 :                             lcl_WriteSimpleString( rStrm, aCell );
    1657             :                     }
    1658             :                 }
    1659           0 :                 if( nCol < nEndCol )
    1660           0 :                     lcl_WriteSimpleString( rStrm, rtl::OUString(cSep) );
    1661             :             }
    1662           0 :                 WriteUnicodeOrByteEndl( rStrm );
    1663           0 :             if( rStrm.GetError() != SVSTREAM_OK )
    1664           0 :                 break;
    1665           0 :             if( nSizeLimit && rStrm.Tell() > nSizeLimit )
    1666           0 :                 break;
    1667             :         }
    1668             :     }
    1669             : 
    1670           0 :     return rStrm.GetError() == SVSTREAM_OK;
    1671             : }
    1672             : 
    1673             : 
    1674           4 : bool ScImportExport::Sylk2Doc( SvStream& rStrm )
    1675             : {
    1676           4 :     bool bOk = true;
    1677           4 :     bool bMyDoc = false;
    1678           4 :     SylkVersion eVersion = SYLK_OTHER;
    1679             : 
    1680             :     // US-English separators for StringToDouble
    1681           4 :     sal_Unicode cDecSep = '.';
    1682           4 :     sal_Unicode cGrpSep = ',';
    1683             : 
    1684           4 :     SCCOL nStartCol = aRange.aStart.Col();
    1685           4 :     SCROW nStartRow = aRange.aStart.Row();
    1686           4 :     SCCOL nEndCol = aRange.aEnd.Col();
    1687           4 :     SCROW nEndRow = aRange.aEnd.Row();
    1688           4 :     sal_uLong nOldPos = rStrm.Tell();
    1689           4 :     bool bData = !bSingle;
    1690           4 :     ::std::vector< sal_uInt32 > aFormats;
    1691             : 
    1692           4 :     if( !bSingle)
    1693           0 :         bOk = StartPaste();
    1694             : 
    1695          12 :     while( bOk )
    1696             :     {
    1697           8 :         String aLine;
    1698           8 :         String aText;
    1699           8 :         rtl::OString aByteLine;
    1700           8 :         SCCOL nCol = nStartCol;
    1701           8 :         SCROW nRow = nStartRow;
    1702           8 :         SCCOL nRefCol = 1;
    1703           8 :         SCROW nRefRow = 1;
    1704           8 :         rStrm.Seek( nOldPos );
    1705        6052 :         for( ;; )
    1706             :         {
    1707             :             //! allow unicode
    1708        6060 :             rStrm.ReadLine( aByteLine );
    1709        6060 :             aLine = rtl::OStringToOUString(aByteLine, rStrm.GetStreamCharSet());
    1710        6060 :             if( rStrm.IsEof() )
    1711           2 :                 break;
    1712        6058 :             const sal_Unicode* p = aLine.GetBuffer();
    1713        6058 :             sal_Unicode cTag = *p++;
    1714        6058 :             if( cTag == 'C' )       // Content
    1715             :             {
    1716        4620 :                 if( *p++ != ';' )
    1717           0 :                     return false;
    1718       20780 :                 while( *p )
    1719             :                 {
    1720       11540 :                     sal_Unicode ch = *p++;
    1721       11540 :                     ch = ScGlobal::ToUpperAlpha( ch );
    1722       11540 :                     switch( ch )
    1723             :                     {
    1724             :                         case 'X':
    1725        4460 :                             nCol = static_cast<SCCOL>(rtl::OUString(p).toInt32()) + nStartCol - 1;
    1726        4460 :                             break;
    1727             :                         case 'Y':
    1728        2444 :                             nRow = rtl::OUString(p).toInt32() + nStartRow - 1;
    1729        2444 :                             break;
    1730             :                         case 'C':
    1731           0 :                             nRefCol = static_cast<SCCOL>(rtl::OUString(p).toInt32()) + nStartCol - 1;
    1732           0 :                             break;
    1733             :                         case 'R':
    1734           0 :                             nRefRow = rtl::OUString(p).toInt32() + nStartRow - 1;
    1735           0 :                             break;
    1736             :                         case 'K':
    1737             :                         {
    1738        4620 :                             if( !bSingle &&
    1739             :                                     ( nCol < nStartCol || nCol > nEndCol
    1740             :                                       || nRow < nStartRow || nRow > nEndRow
    1741             :                                       || nCol > MAXCOL || nRow > MAXROW ) )
    1742           0 :                                 break;
    1743        4620 :                             if( !bData )
    1744             :                             {
    1745        2310 :                                 if( nRow > nEndRow )
    1746         221 :                                     nEndRow = nRow;
    1747        2310 :                                 if( nCol > nEndCol )
    1748          18 :                                     nEndCol = nCol;
    1749        2310 :                                 break;
    1750             :                             }
    1751             :                             bool bText;
    1752        2310 :                             if( *p == '"' )
    1753             :                             {
    1754         941 :                                 bText = true;
    1755         941 :                                 aText.Erase();
    1756         941 :                                 p = lcl_ScanSylkString( p, aText, eVersion);
    1757             :                             }
    1758             :                             else
    1759        1369 :                                 bText = false;
    1760        2310 :                             const sal_Unicode* q = p;
    1761        9527 :                             while( *q && *q != ';' )
    1762        4907 :                                 q++;
    1763        2310 :                             if ( !(*q == ';' && *(q+1) == 'I') )
    1764             :                             {   // don't ignore value
    1765        2310 :                                 if( bText )
    1766             :                                 {
    1767         941 :                                     pDoc->PutCell( nCol, nRow, aRange.aStart.Tab(),
    1768             :                                             ScBaseCell::CreateTextCell( aText, pDoc),
    1769        1882 :                                             true);
    1770             :                                 }
    1771             :                                 else
    1772             :                                 {
    1773             :                                     double fVal = rtl_math_uStringToDouble( p,
    1774        1369 :                                             aLine.GetBuffer() + aLine.Len(),
    1775        2738 :                                             cDecSep, cGrpSep, NULL, NULL );
    1776        1369 :                                     pDoc->SetValue( nCol, nRow, aRange.aStart.Tab(), fVal );
    1777             :                                 }
    1778             :                             }
    1779             :                         }
    1780        2310 :                         break;
    1781             :                         case 'E':
    1782             :                         case 'M':
    1783             :                         {
    1784           0 :                             if ( ch == 'M' )
    1785             :                             {
    1786           0 :                                 if ( nRefCol < nCol )
    1787           0 :                                     nRefCol = nCol;
    1788           0 :                                 if ( nRefRow < nRow )
    1789           0 :                                     nRefRow = nRow;
    1790           0 :                                 if ( !bData )
    1791             :                                 {
    1792           0 :                                     if( nRefRow > nEndRow )
    1793           0 :                                         nEndRow = nRefRow;
    1794           0 :                                     if( nRefCol > nEndCol )
    1795           0 :                                         nEndCol = nRefCol;
    1796             :                                 }
    1797             :                             }
    1798           0 :                             if( !bMyDoc || !bData )
    1799             :                                 break;
    1800           0 :                             aText = '=';
    1801           0 :                             p = lcl_ScanSylkFormula( p, aText, eVersion);
    1802           0 :                             ScAddress aPos( nCol, nRow, aRange.aStart.Tab() );
    1803             :                             /* FIXME: do we want GRAM_ODFF_A1 instead? At the
    1804             :                              * end it probably should be GRAM_ODFF_R1C1, since
    1805             :                              * R1C1 is what Excel writes in SYLK. */
    1806           0 :                             const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_PODF_A1;
    1807           0 :                             ScCompiler aComp( pDoc, aPos);
    1808           0 :                             aComp.SetGrammar(eGrammar);
    1809           0 :                             ScTokenArray* pCode = aComp.CompileString( aText );
    1810           0 :                             if ( ch == 'M' )
    1811             :                             {
    1812           0 :                                 ScMarkData aMark;
    1813           0 :                                 aMark.SelectTable( aPos.Tab(), true );
    1814             :                                 pDoc->InsertMatrixFormula( nCol, nRow, nRefCol,
    1815           0 :                                     nRefRow, aMark, EMPTY_STRING, pCode );
    1816             :                             }
    1817             :                             else
    1818             :                             {
    1819             :                                 ScFormulaCell* pFCell = new ScFormulaCell(
    1820           0 :                                         pDoc, aPos, pCode, eGrammar, MM_NONE);
    1821           0 :                                 pDoc->PutCell( aPos, pFCell );
    1822             :                             }
    1823           0 :                             delete pCode;   // ctor/InsertMatrixFormula did copy TokenArray
    1824             :                         }
    1825           0 :                         break;
    1826             :                     }
    1827       58497 :                     while( *p && *p != ';' )
    1828       35417 :                         p++;
    1829       11540 :                     if( *p )
    1830        6920 :                         p++;
    1831             :                 }
    1832             :             }
    1833        1438 :             else if( cTag == 'F' )      // Format
    1834             :             {
    1835         196 :                 if( *p++ != ';' )
    1836           0 :                     return false;
    1837         196 :                 sal_Int32 nFormat = -1;
    1838         942 :                 while( *p )
    1839             :                 {
    1840         550 :                     sal_Unicode ch = *p++;
    1841         550 :                     ch = ScGlobal::ToUpperAlpha( ch );
    1842         550 :                     switch( ch )
    1843             :                     {
    1844             :                         case 'X':
    1845         160 :                             nCol = static_cast<SCCOL>(rtl::OUString(p).toInt32()) + nStartCol - 1;
    1846         160 :                             break;
    1847             :                         case 'Y':
    1848          22 :                             nRow = rtl::OUString(p).toInt32() + nStartRow - 1;
    1849          22 :                             break;
    1850             :                         case 'P' :
    1851         166 :                             if ( bData )
    1852             :                             {
    1853             :                                 // F;P<n> sets format code of P;P<code> at
    1854             :                                 // current position, or at ;X;Y if specified.
    1855             :                                 // Note that ;X;Y may appear after ;P
    1856          83 :                                 const sal_Unicode* p0 = p;
    1857         258 :                                 while( *p && *p != ';' )
    1858          92 :                                     p++;
    1859          83 :                                 rtl::OUString aNumber(p0, p - p0);
    1860          83 :                                 nFormat = aNumber.toInt32();
    1861             :                             }
    1862         166 :                             break;
    1863             :                     }
    1864        2100 :                     while( *p && *p != ';' )
    1865        1000 :                         p++;
    1866         550 :                     if( *p )
    1867         354 :                         p++;
    1868             :                 }
    1869         196 :                 if ( !bData )
    1870             :                 {
    1871          98 :                     if( nRow > nEndRow )
    1872          10 :                         nEndRow = nRow;
    1873          98 :                     if( nCol > nEndCol )
    1874           1 :                         nEndCol = nCol;
    1875             :                 }
    1876         196 :                 if ( 0 <= nFormat && nFormat < (sal_Int32)aFormats.size() )
    1877             :                 {
    1878          83 :                     sal_uInt32 nKey = aFormats[nFormat];
    1879          83 :                     pDoc->ApplyAttr( nCol, nRow, aRange.aStart.Tab(),
    1880         166 :                             SfxUInt32Item( ATTR_VALUE_FORMAT, nKey ) );
    1881             :                 }
    1882             :             }
    1883        1242 :             else if( cTag == 'P' )
    1884             :             {
    1885        1220 :                 if ( bData && *p == ';' && *(p+1) == 'P' )
    1886             :                 {
    1887         605 :                     rtl::OUString aCode( p+2 );
    1888             :                     // unescape doubled semicolons
    1889         605 :                     aCode = aCode.replaceAll(";;", ";");
    1890             :                     // get rid of Xcl escape characters
    1891         605 :                     aCode = aCode.replaceAll(rtl::OUString(static_cast<sal_Unicode>(0x1b)), rtl::OUString());
    1892             :                     sal_Int32 nCheckPos;
    1893             :                     short nType;
    1894             :                     sal_uInt32 nKey;
    1895             :                     pDoc->GetFormatTable()->PutandConvertEntry( aCode, nCheckPos, nType, nKey,
    1896         605 :                                                                 LANGUAGE_ENGLISH_US, ScGlobal::eLnge );
    1897         605 :                     if ( nCheckPos )
    1898           0 :                         nKey = 0;
    1899         605 :                     aFormats.push_back( nKey );
    1900             :                 }
    1901             :             }
    1902          22 :             else if( cTag == 'I' && *p == 'D' )
    1903             :             {
    1904           8 :                 aLine.Erase( 0, 4 );
    1905           8 :                 if (aLine.EqualsAscii( "CALCOOO32" ))
    1906           0 :                     eVersion = SYLK_OOO32;
    1907           8 :                 else if (aLine.EqualsAscii( "SCALC3" ))
    1908           2 :                     eVersion = SYLK_SCALC3;
    1909           8 :                 bMyDoc = (eVersion <= SYLK_OWN);
    1910             :             }
    1911          14 :             else if( cTag == 'E' )                      // Ende
    1912           6 :                 break;
    1913             :         }
    1914           8 :         if( !bData )
    1915             :         {
    1916           4 :             aRange.aEnd.SetCol( nEndCol );
    1917           4 :             aRange.aEnd.SetRow( nEndRow );
    1918           4 :             bOk = StartPaste();
    1919           4 :             bData = true;
    1920             :         }
    1921             :         else
    1922             :             break;
    1923           8 :     }
    1924             : 
    1925           4 :     EndPaste();
    1926           4 :     return bOk;
    1927             : }
    1928             : 
    1929             : 
    1930           0 : bool ScImportExport::Doc2Sylk( SvStream& rStrm )
    1931             : {
    1932             :     SCCOL nCol;
    1933             :     SCROW nRow;
    1934           0 :     SCCOL nStartCol = aRange.aStart.Col();
    1935           0 :     SCROW nStartRow = aRange.aStart.Row();
    1936           0 :     SCCOL nEndCol = aRange.aEnd.Col();
    1937           0 :     SCROW nEndRow = aRange.aEnd.Row();
    1938           0 :     String aCellStr;
    1939           0 :     String aValStr;
    1940             :     lcl_WriteSimpleString( rStrm,
    1941           0 :             String( RTL_CONSTASCII_USTRINGPARAM( "ID;PCALCOOO32")));
    1942           0 :     WriteUnicodeOrByteEndl( rStrm );
    1943             : 
    1944           0 :     for (nRow = nStartRow; nRow <= nEndRow; nRow++)
    1945             :     {
    1946           0 :         for (nCol = nStartCol; nCol <= nEndCol; nCol++)
    1947             :         {
    1948           0 :             String aBufStr;
    1949             :             double nVal;
    1950           0 :             bool bForm = false;
    1951           0 :             SCROW r = nRow - nStartRow + 1;
    1952           0 :             SCCOL c = nCol - nStartCol + 1;
    1953             :             ScBaseCell* pCell;
    1954           0 :             pDoc->GetCell( nCol, nRow, aRange.aStart.Tab(), pCell );
    1955           0 :             CellType eType = (pCell ? pCell->GetCellType() : CELLTYPE_NONE);
    1956           0 :             switch( eType )
    1957             :             {
    1958             :                 case CELLTYPE_FORMULA:
    1959           0 :                     bForm = bFormulas;
    1960           0 :                     if( pDoc->HasValueData( nCol, nRow, aRange.aStart.Tab()) )
    1961           0 :                         goto hasvalue;
    1962             :                     else
    1963           0 :                         goto hasstring;
    1964             : 
    1965             :                 case CELLTYPE_VALUE:
    1966             :                 hasvalue:
    1967           0 :                     pDoc->GetValue( nCol, nRow, aRange.aStart.Tab(), nVal );
    1968             : 
    1969             :                     aValStr = ::rtl::math::doubleToUString( nVal,
    1970             :                             rtl_math_StringFormat_Automatic,
    1971           0 :                             rtl_math_DecimalPlaces_Max, '.', true );
    1972             : 
    1973           0 :                     aBufStr.AssignAscii(RTL_CONSTASCII_STRINGPARAM( "C;X" ));
    1974           0 :                     aBufStr += String::CreateFromInt32( c );
    1975           0 :                     aBufStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";Y" ));
    1976           0 :                     aBufStr += String::CreateFromInt32( r );
    1977           0 :                     aBufStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";K" ));
    1978           0 :                     aBufStr += aValStr;
    1979           0 :                     lcl_WriteSimpleString( rStrm, aBufStr );
    1980           0 :                     goto checkformula;
    1981             : 
    1982             :                 case CELLTYPE_STRING:
    1983             :                 case CELLTYPE_EDIT:
    1984             :                 hasstring:
    1985           0 :                     pDoc->GetString( nCol, nRow, aRange.aStart.Tab(), aCellStr );
    1986           0 :                     aCellStr.SearchAndReplaceAll( rtl::OUString(_LF), rtl::OUString(SYLK_LF) );
    1987             : 
    1988           0 :                     aBufStr.AssignAscii(RTL_CONSTASCII_STRINGPARAM( "C;X" ));
    1989           0 :                     aBufStr += String::CreateFromInt32( c );
    1990           0 :                     aBufStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";Y" ));
    1991           0 :                     aBufStr += String::CreateFromInt32( r );
    1992           0 :                     aBufStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";K" ));
    1993           0 :                     lcl_WriteSimpleString( rStrm, aBufStr );
    1994           0 :                     lcl_WriteString( rStrm, aCellStr, '"', ';' );
    1995             : 
    1996             :                 checkformula:
    1997           0 :                     if( bForm )
    1998             :                     {
    1999             :                         const ScFormulaCell* pFCell =
    2000           0 :                             static_cast<const ScFormulaCell*>(pCell);
    2001           0 :                         switch ( pFCell->GetMatrixFlag() )
    2002             :                         {
    2003             :                             case MM_REFERENCE :
    2004           0 :                                 aCellStr.Erase();
    2005             :                             break;
    2006             :                             default:
    2007           0 :                                 rtl::OUString aOUCellStr;
    2008           0 :                                 pFCell->GetFormula( aOUCellStr,formula::FormulaGrammar::GRAM_PODF_A1);
    2009           0 :                                 aCellStr = aOUCellStr;
    2010             :                                 /* FIXME: do we want GRAM_ODFF_A1 instead? At
    2011             :                                  * the end it probably should be
    2012             :                                  * GRAM_ODFF_R1C1, since R1C1 is what Excel
    2013             :                                  * writes in SYLK. */
    2014             :                         }
    2015           0 :                         if ( pFCell->GetMatrixFlag() != MM_NONE &&
    2016           0 :                                 aCellStr.Len() > 2 &&
    2017           0 :                                 aCellStr.GetChar(0) == '{' &&
    2018           0 :                                 aCellStr.GetChar(aCellStr.Len()-1) == '}' )
    2019             :                         {   // cut off matrix {} characters
    2020           0 :                             aCellStr.Erase(aCellStr.Len()-1,1);
    2021           0 :                             aCellStr.Erase(0,1);
    2022             :                         }
    2023           0 :                         if ( aCellStr.GetChar(0) == '=' )
    2024           0 :                             aCellStr.Erase(0,1);
    2025           0 :                         String aPrefix;
    2026           0 :                         switch ( pFCell->GetMatrixFlag() )
    2027             :                         {
    2028             :                             case MM_FORMULA :
    2029             :                             {   // diff expression with 'M' M$-extension
    2030             :                                 SCCOL nC;
    2031             :                                 SCROW nR;
    2032           0 :                                 pFCell->GetMatColsRows( nC, nR );
    2033           0 :                                 nC += c - 1;
    2034           0 :                                 nR += r - 1;
    2035           0 :                                 aPrefix.AssignAscii( RTL_CONSTASCII_STRINGPARAM( ";R" ) );
    2036           0 :                                 aPrefix += String::CreateFromInt32( nR );
    2037           0 :                                 aPrefix.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ";C" ) );
    2038           0 :                                 aPrefix += String::CreateFromInt32( nC );
    2039           0 :                                 aPrefix.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ";M" ) );
    2040             :                             }
    2041           0 :                             break;
    2042             :                             case MM_REFERENCE :
    2043             :                             {   // diff expression with 'I' M$-extension
    2044           0 :                                 ScAddress aPos;
    2045           0 :                                 pFCell->GetMatrixOrigin( aPos );
    2046           0 :                                 aPrefix.AssignAscii( RTL_CONSTASCII_STRINGPARAM( ";I;R" ) );
    2047           0 :                                 aPrefix += String::CreateFromInt32( aPos.Row() - nStartRow + 1 );
    2048           0 :                                 aPrefix.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ";C" ) );
    2049           0 :                                 aPrefix += String::CreateFromInt32( aPos.Col() - nStartCol + 1 );
    2050             :                             }
    2051           0 :                             break;
    2052             :                             default:
    2053             :                                 // formula Expression
    2054           0 :                                 aPrefix.AssignAscii( RTL_CONSTASCII_STRINGPARAM( ";E" ) );
    2055             :                         }
    2056           0 :                         lcl_WriteSimpleString( rStrm, aPrefix );
    2057           0 :                         if ( aCellStr.Len() )
    2058           0 :                             lcl_WriteString( rStrm, aCellStr, 0, ';' );
    2059             :                     }
    2060           0 :                     WriteUnicodeOrByteEndl( rStrm );
    2061           0 :                     break;
    2062             : 
    2063             :                 default:
    2064             :                 {
    2065             :                     // added to avoid warnings
    2066             :                 }
    2067             :             }
    2068           0 :         }
    2069             :     }
    2070           0 :     lcl_WriteSimpleString( rStrm, rtl::OUString( 'E' ) );
    2071           0 :     WriteUnicodeOrByteEndl( rStrm );
    2072           0 :     return rStrm.GetError() == SVSTREAM_OK;
    2073             : }
    2074             : 
    2075             : 
    2076           0 : bool ScImportExport::Doc2HTML( SvStream& rStrm, const String& rBaseURL )
    2077             : {
    2078             :     // CharSet is ignored in ScExportHTML, read from Load/Save HTML options
    2079           0 :     ScFormatFilter::Get().ScExportHTML( rStrm, rBaseURL, pDoc, aRange, RTL_TEXTENCODING_DONTKNOW, bAll,
    2080           0 :         aStreamPath, aNonConvertibleChars );
    2081           0 :     return rStrm.GetError() == SVSTREAM_OK;
    2082             : }
    2083             : 
    2084           0 : bool ScImportExport::Doc2RTF( SvStream& rStrm )
    2085             : {
    2086             :     //  CharSet is ignored in ScExportRTF
    2087           0 :     ScFormatFilter::Get().ScExportRTF( rStrm, pDoc, aRange, RTL_TEXTENCODING_DONTKNOW );
    2088           0 :     return rStrm.GetError() == SVSTREAM_OK;
    2089             : }
    2090             : 
    2091             : 
    2092           0 : bool ScImportExport::Doc2Dif( SvStream& rStrm )
    2093             : {
    2094             :     // for DIF in the clipboard, IBM_850 is always used
    2095           0 :     ScFormatFilter::Get().ScExportDif( rStrm, pDoc, aRange, RTL_TEXTENCODING_IBM_850 );
    2096           0 :     return true;
    2097             : }
    2098             : 
    2099             : 
    2100           0 : bool ScImportExport::Dif2Doc( SvStream& rStrm )
    2101             : {
    2102           0 :     SCTAB nTab = aRange.aStart.Tab();
    2103           0 :     ScDocument* pImportDoc = new ScDocument( SCDOCMODE_UNDO );
    2104           0 :     pImportDoc->InitUndo( pDoc, nTab, nTab );
    2105             : 
    2106             :     // for DIF in the clipboard, IBM_850 is always used
    2107           0 :     ScFormatFilter::Get().ScImportDif( rStrm, pImportDoc, aRange.aStart, RTL_TEXTENCODING_IBM_850 );
    2108             : 
    2109             :     SCCOL nEndCol;
    2110             :     SCROW nEndRow;
    2111           0 :     pImportDoc->GetCellArea( nTab, nEndCol, nEndRow );
    2112             :     // if there are no cells in the imported content, nEndCol/nEndRow may be before the start
    2113           0 :     if ( nEndCol < aRange.aStart.Col() )
    2114           0 :         nEndCol = aRange.aStart.Col();
    2115           0 :     if ( nEndRow < aRange.aStart.Row() )
    2116           0 :         nEndRow = aRange.aStart.Row();
    2117           0 :     aRange.aEnd = ScAddress( nEndCol, nEndRow, nTab );
    2118             : 
    2119           0 :     bool bOk = StartPaste();
    2120           0 :     if (bOk)
    2121             :     {
    2122           0 :         sal_uInt16 nFlags = IDF_ALL & ~IDF_STYLES;
    2123           0 :         pDoc->DeleteAreaTab( aRange, nFlags );
    2124           0 :         pImportDoc->CopyToDocument( aRange, nFlags, false, pDoc );
    2125           0 :         EndPaste();
    2126             :     }
    2127             : 
    2128           0 :     delete pImportDoc;
    2129             : 
    2130           0 :     return bOk;
    2131             : }
    2132             : 
    2133             : 
    2134           0 : bool ScImportExport::RTF2Doc( SvStream& rStrm, const String& rBaseURL )
    2135             : {
    2136           0 :     ScEEAbsImport *pImp = ScFormatFilter::Get().CreateRTFImport( pDoc, aRange );
    2137           0 :     if (!pImp)
    2138           0 :         return false;
    2139           0 :     pImp->Read( rStrm, rBaseURL );
    2140           0 :     aRange = pImp->GetRange();
    2141             : 
    2142           0 :     bool bOk = StartPaste();
    2143           0 :     if (bOk)
    2144             :     {
    2145           0 :         sal_uInt16 nFlags = IDF_ALL & ~IDF_STYLES;
    2146           0 :         pDoc->DeleteAreaTab( aRange, nFlags );
    2147           0 :         pImp->WriteToDocument();
    2148           0 :         EndPaste();
    2149             :     }
    2150           0 :     delete pImp;
    2151           0 :     return bOk;
    2152             : }
    2153             : 
    2154             : 
    2155           0 : bool ScImportExport::HTML2Doc( SvStream& rStrm, const String& rBaseURL )
    2156             : {
    2157           0 :     ScEEAbsImport *pImp = ScFormatFilter::Get().CreateHTMLImport( pDoc, rBaseURL, aRange, true);
    2158           0 :     if (!pImp)
    2159           0 :         return false;
    2160           0 :     pImp->Read( rStrm, rBaseURL );
    2161           0 :     aRange = pImp->GetRange();
    2162             : 
    2163           0 :     bool bOk = StartPaste();
    2164           0 :     if (bOk)
    2165             :     {
    2166             :         // ScHTMLImport may call ScDocument::InitDrawLayer, resulting in
    2167             :         // a Draw Layer but no Draw View -> create Draw Layer and View here
    2168           0 :         if (pDocSh)
    2169           0 :             pDocSh->MakeDrawLayer();
    2170             : 
    2171           0 :         sal_uInt16 nFlags = IDF_ALL & ~IDF_STYLES;
    2172           0 :         pDoc->DeleteAreaTab( aRange, nFlags );
    2173             : 
    2174           0 :         if (pExtOptions)
    2175             :         {
    2176             :             // Pick up import options if available.
    2177           0 :             LanguageType eLang = pExtOptions->GetLanguage();
    2178           0 :             SvNumberFormatter aNumFormatter(pDoc->GetServiceManager(), eLang);
    2179           0 :             bool bSpecialNumber = pExtOptions->IsDetectSpecialNumber();
    2180           0 :             pImp->WriteToDocument(false, 1.0, &aNumFormatter, bSpecialNumber);
    2181             :         }
    2182             :         else
    2183             :             // Regular import, with no options.
    2184           0 :             pImp->WriteToDocument();
    2185             : 
    2186           0 :         EndPaste();
    2187             :     }
    2188           0 :     delete pImp;
    2189           0 :     return bOk;
    2190             : }
    2191             : 
    2192             : #ifndef DISABLE_DYNLOADING
    2193             : 
    2194             : #define RETURN_ERROR { return eERR_INTERN; }
    2195             : class ScFormatFilterMissing : public ScFormatFilterPlugin {
    2196             :   public:
    2197           0 :     ScFormatFilterMissing()
    2198           0 :     {
    2199             :       OSL_FAIL("Missing file filters");
    2200           0 :     }
    2201           0 :     virtual ~ScFormatFilterMissing() {}
    2202           0 :     virtual FltError ScImportLotus123( SfxMedium&, ScDocument*, CharSet ) RETURN_ERROR
    2203           0 :     virtual FltError ScImportQuattroPro( SfxMedium &, ScDocument * ) RETURN_ERROR
    2204           0 :     virtual FltError ScImportExcel( SfxMedium&, ScDocument*, const EXCIMPFORMAT ) RETURN_ERROR
    2205           0 :     virtual FltError ScImportStarCalc10( SvStream&, ScDocument* ) RETURN_ERROR
    2206           0 :     virtual FltError ScImportDif( SvStream&, ScDocument*, const ScAddress&,
    2207           0 :                  const CharSet, sal_uInt32 ) RETURN_ERROR
    2208           0 :     virtual FltError ScImportRTF( SvStream&, const String&, ScDocument*, ScRange& ) RETURN_ERROR
    2209           0 :     virtual FltError ScImportHTML( SvStream&, const String&, ScDocument*, ScRange&, double, bool, SvNumberFormatter*, bool ) RETURN_ERROR
    2210             : 
    2211           0 :     virtual ScEEAbsImport *CreateRTFImport( ScDocument*, const ScRange& ) { return NULL; }
    2212           0 :     virtual ScEEAbsImport *CreateHTMLImport( ScDocument*, const String&, const ScRange&, bool ) { return NULL; }
    2213           0 :     virtual String         GetHTMLRangeNameList( ScDocument*, const String& ) { return String(); }
    2214             : 
    2215           0 :     virtual FltError ScExportExcel5( SfxMedium&, ScDocument*, ExportFormatExcel, CharSet ) RETURN_ERROR
    2216           0 :     virtual FltError ScExportDif( SvStream&, ScDocument*, const ScAddress&, const CharSet, sal_uInt32 ) RETURN_ERROR
    2217           0 :     virtual FltError ScExportDif( SvStream&, ScDocument*, const ScRange&, const CharSet, sal_uInt32 ) RETURN_ERROR
    2218           0 :     virtual FltError ScExportHTML( SvStream&, const String&, ScDocument*, const ScRange&, const CharSet, bool,
    2219           0 :                   const String&, String& ) RETURN_ERROR
    2220           0 :     virtual FltError ScExportRTF( SvStream&, ScDocument*, const ScRange&, const CharSet ) RETURN_ERROR
    2221             : 
    2222           0 :     virtual ScOrcusFilters* GetOrcusFilters() { return NULL; }
    2223             : };
    2224             : 
    2225           0 : extern "C" { static void SAL_CALL thisModule() {} }
    2226             : 
    2227             : #else
    2228             : 
    2229             : extern "C" {
    2230             : ScFormatFilterPlugin* ScFilterCreate();
    2231             : }
    2232             : 
    2233             : #endif
    2234             : 
    2235             : typedef ScFormatFilterPlugin * (*FilterFn)(void);
    2236          26 : ScFormatFilterPlugin &ScFormatFilter::Get()
    2237             : {
    2238             :     static ScFormatFilterPlugin *plugin;
    2239             : 
    2240          26 :     if (plugin != NULL)
    2241          24 :         return *plugin;
    2242             : 
    2243             : #ifndef DISABLE_DYNLOADING
    2244           2 :     ::rtl::OUString sFilterLib(RTL_CONSTASCII_USTRINGPARAM(SVLIBRARY("scfilt")));
    2245           2 :     static ::osl::Module aModule;
    2246           2 :     bool bLoaded = aModule.loadRelative(&thisModule, sFilterLib);
    2247           2 :     if (!bLoaded)
    2248           0 :         bLoaded = aModule.load(sFilterLib);
    2249           2 :     if (bLoaded)
    2250             :     {
    2251           2 :         oslGenericFunction fn = aModule.getFunctionSymbol( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ScFilterCreate" )) );
    2252           2 :         if (fn != NULL)
    2253           2 :             plugin = reinterpret_cast<FilterFn>(fn)();
    2254             :     }
    2255           2 :     if (plugin == NULL)
    2256           0 :         plugin = new ScFormatFilterMissing();
    2257             : #else
    2258             :     plugin = ScFilterCreate();
    2259             : #endif
    2260             : 
    2261           2 :     return *plugin;
    2262             : }
    2263             : 
    2264             : // Precondition: pStr is guaranteed to be non-NULL and points to a 0-terminated
    2265             : // array.
    2266        3422 : static inline const sal_Unicode* lcl_UnicodeStrChr( const sal_Unicode* pStr,
    2267             :         sal_Unicode c )
    2268             : {
    2269        9660 :     while (*pStr)
    2270             :     {
    2271        3422 :         if (*pStr == c)
    2272         606 :             return pStr;
    2273        2816 :         ++pStr;
    2274             :     }
    2275        2816 :     return 0;
    2276             : }
    2277             : 
    2278         146 : rtl::OUString ReadCsvLine( SvStream &rStream, bool bEmbeddedLineBreak,
    2279             :         const String& rFieldSeparators, sal_Unicode cFieldQuote )
    2280             : {
    2281         146 :     rtl::OUString aStr;
    2282         146 :     rStream.ReadUniOrByteStringLine(aStr, rStream.GetStreamCharSet(), nArbitraryLineLengthLimit);
    2283             : 
    2284         146 :     if (bEmbeddedLineBreak)
    2285             :     {
    2286         146 :         const sal_Unicode* pSeps = rFieldSeparators.GetBuffer();
    2287             : 
    2288             :         // See if the separator(s) include tab.
    2289         146 :         bool bTabSep = lcl_UnicodeStrChr(pSeps, '\t') != NULL;
    2290             : 
    2291         146 :         QuoteType eQuoteState = FIELDEND_QUOTE;
    2292         146 :         bool bFieldStart = true;
    2293             : 
    2294         146 :         sal_Int32 nLastOffset = 0;
    2295         146 :         sal_Int32 nQuotes = 0;
    2296         336 :         while (!rStream.IsEof() && aStr.getLength() < nArbitraryLineLengthLimit)
    2297             :         {
    2298             :             const sal_Unicode *p, *pStart;
    2299         186 :             p = pStart = aStr.getStr();
    2300         186 :             p += nLastOffset;
    2301        8364 :             while (*p)
    2302             :             {
    2303        7992 :                 if (nQuotes)
    2304             :                 {
    2305        5724 :                     if (bTabSep && *p == '\t' && (nQuotes % 2) != 0)
    2306             :                     {
    2307             :                         // When tab-delimited, tab char ends quoted sequence
    2308             :                         // even if we haven't reached the end quote.  Doing
    2309             :                         // this helps keep mal-formed rows from damaging
    2310             :                         // other, well-formed rows.
    2311           0 :                         nQuotes = 0;
    2312           0 :                         break;
    2313             :                     }
    2314             : 
    2315        5724 :                     if (*p == cFieldQuote)
    2316             :                     {
    2317         968 :                         if (bFieldStart)
    2318             :                         {
    2319         328 :                             ++nQuotes;
    2320         328 :                             bFieldStart = false;
    2321         328 :                             eQuoteState = FIELDSTART_QUOTE;
    2322             :                         }
    2323             :                         // Do not detect a FIELDSTART_QUOTE if not in
    2324             :                         // bFieldStart mode, in which case for unquoted content
    2325             :                         // we are in FIELDEND_QUOTE state.
    2326         640 :                         else if (eQuoteState != FIELDEND_QUOTE)
    2327             :                         {
    2328         580 :                             eQuoteState = lcl_isEscapedOrFieldEndQuote( nQuotes, p, pSeps, cFieldQuote);
    2329             :                             // DONTKNOW_QUOTE is an embedded unescaped quote we
    2330             :                             // don't count for pairing.
    2331         580 :                             if (eQuoteState != DONTKNOW_QUOTE)
    2332         482 :                                 ++nQuotes;
    2333             :                         }
    2334             :                     }
    2335        4756 :                     else if (eQuoteState == FIELDEND_QUOTE)
    2336             :                     {
    2337        1090 :                         if (bFieldStart)
    2338             :                             // If blank is a separator it starts a field, if it
    2339             :                             // is not and thus maybe leading before quote we
    2340             :                             // are still at start of field regarding quotes.
    2341         234 :                             bFieldStart = (*p == ' ' || lcl_UnicodeStrChr( pSeps, *p) != NULL);
    2342             :                         else
    2343         856 :                             bFieldStart = (lcl_UnicodeStrChr( pSeps, *p) != NULL);
    2344             :                     }
    2345             :                 }
    2346             :                 else
    2347             :                 {
    2348        2268 :                     if (*p == cFieldQuote && bFieldStart)
    2349             :                     {
    2350          58 :                         nQuotes = 1;
    2351          58 :                         eQuoteState = FIELDSTART_QUOTE;
    2352          58 :                         bFieldStart = false;
    2353             :                     }
    2354        2210 :                     else if (eQuoteState == FIELDEND_QUOTE)
    2355             :                     {
    2356             :                         // This also skips leading blanks at beginning of line
    2357             :                         // if followed by a quote. It's debatable whether we
    2358             :                         // actually want that or not, but congruent with what
    2359             :                         // ScanNextFieldFromString() does.
    2360        2210 :                         if (bFieldStart)
    2361         126 :                             bFieldStart = (*p == ' ' || lcl_UnicodeStrChr( pSeps, *p) != NULL);
    2362             :                         else
    2363        2084 :                             bFieldStart = (lcl_UnicodeStrChr( pSeps, *p) != NULL);
    2364             :                     }
    2365             :                 }
    2366             :                 // A quote character inside a field content does not start
    2367             :                 // a quote.
    2368        7992 :                 ++p;
    2369             :             }
    2370             : 
    2371         186 :             if (nQuotes % 2 == 0)
    2372             :                 // We still have a (theoretical?) problem here if due to
    2373             :                 // nArbitraryLineLengthLimit we split a string right between a
    2374             :                 // doubled quote pair.
    2375         142 :                 break;
    2376             :             else
    2377             :             {
    2378          44 :                 nLastOffset = aStr.getLength();
    2379          44 :                 rtl::OUString aNext;
    2380          44 :                 rStream.ReadUniOrByteStringLine(aNext, rStream.GetStreamCharSet(), nArbitraryLineLengthLimit);
    2381          44 :                 aStr += rtl::OUString( sal_Unicode(_LF));
    2382          44 :                 aStr += aNext;
    2383             :             }
    2384             :         }
    2385             :     }
    2386         146 :     return aStr;
    2387          15 : }
    2388             : 
    2389             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10