diff options
author | Eike Rathke <erack@redhat.com> | 2017-11-13 16:41:49 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2017-11-13 18:43:35 +0100 |
commit | f435cdba5b4ea98dc30b4b4879de21a542c8a84d (patch) | |
tree | 742c42d3f3a3d170df47838bd756be1a74115e52 /sc | |
parent | 971b81b1c0922ab749eaf620cbf56d9780a15cfb (diff) |
Resolves: tdf#113571 paste-special "Unformatted text [TSV-Calc]", tdf#32213
For intra-Calc on-cell pastes using the paste special toolbar
button the SotClipboardFormatId::STRING_TSVC format can be used,
which preserves embedded line breaks and tabs by enclosing such
content in double quotes and escaping quotes by doubling them,
similar to CSV. This differs from the IANA
text/tab-separated-values MIME type (see
https://www.iana.org/assignments/media-types/text/tab-separated-values)
that does not allow quoted fields or embedded line breaks or tabs.
The text/plain "Unformatted text" format now again (after the
change with commit cdcd262ea4aa3c3e407b14ed533e514f75de2d3a for
tdf#32213) results in unquoted/unescaped content as expected for
external pastes.
A follow-up commit probably should distinguish whether the source
is one single cell or multiple cells and for multiple cells use a
strict TSV (with embedded line breaks and tabs changed to spaces)
if a simple "Unformatted text" is requested, which always uses
tabs as field separators anyway.
Further enhancement could be to offer strict
text/tab-separated-values and also text/csv at the clipboard if
there are applications that actually handle these MIME types.
Change-Id: Ica60f256e26867d854639823c62eedbf13eb4d4b
Reviewed-on: https://gerrit.libreoffice.org/44686
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins <ci@libreoffice.org>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/source/ui/app/seltrans.cxx | 1 | ||||
-rw-r--r-- | sc/source/ui/app/transobj.cxx | 11 | ||||
-rw-r--r-- | sc/source/ui/docshell/docsh4.cxx | 6 | ||||
-rw-r--r-- | sc/source/ui/docshell/impex.cxx | 10 | ||||
-rw-r--r-- | sc/source/ui/docshell/servobj.cxx | 4 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/view/editsh.cxx | 14 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin.cxx | 3 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwshe.cxx | 1 | ||||
-rw-r--r-- | sc/source/ui/view/viewfun3.cxx | 4 | ||||
-rw-r--r-- | sc/source/ui/view/viewfun5.cxx | 6 |
11 files changed, 48 insertions, 14 deletions
diff --git a/sc/source/ui/app/seltrans.cxx b/sc/source/ui/app/seltrans.cxx index 6b4b7212018b..65b12506d3a7 100644 --- a/sc/source/ui/app/seltrans.cxx +++ b/sc/source/ui/app/seltrans.cxx @@ -190,6 +190,7 @@ void ScSelectionTransferObj::AddSupportedFormats() AddFormat( SotClipboardFormatId::LINK ); AddFormat( SotClipboardFormatId::DIF ); AddFormat( SotClipboardFormatId::STRING ); + AddFormat( SotClipboardFormatId::STRING_TSVC ); AddFormat( SotClipboardFormatId::RTF ); AddFormat( SotClipboardFormatId::RICHTEXT ); if ( eMode == SC_SELTRANS_CELL ) diff --git a/sc/source/ui/app/transobj.cxx b/sc/source/ui/app/transobj.cxx index 0b2075084e4d..a45583af79d7 100644 --- a/sc/source/ui/app/transobj.cxx +++ b/sc/source/ui/app/transobj.cxx @@ -238,6 +238,7 @@ void ScTransferObj::AddSupportedFormats() AddFormat( SotClipboardFormatId::LINK ); AddFormat( SotClipboardFormatId::DIF ); AddFormat( SotClipboardFormatId::STRING ); + AddFormat( SotClipboardFormatId::STRING_TSVC ); AddFormat( SotClipboardFormatId::RTF ); AddFormat( SotClipboardFormatId::RICHTEXT ); @@ -319,7 +320,15 @@ bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor, const OUSt } ScImportExport aObj( pDoc, aReducedBlock ); - ScExportTextOptions aTextOptions(ScExportTextOptions::None, 0, true); + // Plain string ("Unformatted text") contains embedded line breaks + // but is not enclosed in quotes. Which makes it unsuitable for + // multiple cells if one of them is multi-line, but otherwise is + // expected behavior for plain text. + // Add quotes only for STRING_TSVC. + /* TODO: a possible future STRING_TSV should not contain embedded + * line breaks nor tab (separator) characters and not be quoted. */ + ScExportTextOptions aTextOptions( ScExportTextOptions::None, 0, + (nFormat == SotClipboardFormatId::STRING_TSVC)); if ( bUsedForLink ) { // For a DDE link, convert line breaks and separators to space. diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx index 7654fdca0459..e5620e8dd74a 100644 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -2196,7 +2196,8 @@ bool ScDocShell::DdeGetData( const OUString& rItem, const OUString& rMimeType, css::uno::Any & rValue ) { - if( SotClipboardFormatId::STRING == SotExchange::GetFormatIdFromMimeType( rMimeType ) ) + SotClipboardFormatId eFormatId = SotExchange::GetFormatIdFromMimeType( rMimeType ); + if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId) { if( rItem.equalsIgnoreAsciiCase( "Format" ) ) { @@ -2244,7 +2245,8 @@ bool ScDocShell::DdeSetData( const OUString& rItem, const OUString& rMimeType, const css::uno::Any & rValue ) { - if( SotClipboardFormatId::STRING == SotExchange::GetFormatIdFromMimeType( rMimeType )) + SotClipboardFormatId eFormatId = SotExchange::GetFormatIdFromMimeType( rMimeType ); + if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId) { if( rItem.equalsIgnoreAsciiCase( "Format" ) ) { diff --git a/sc/source/ui/docshell/impex.cxx b/sc/source/ui/docshell/impex.cxx index 953956213faa..864ddaf591ac 100644 --- a/sc/source/ui/docshell/impex.cxx +++ b/sc/source/ui/docshell/impex.cxx @@ -205,6 +205,7 @@ void ScImportExport::SetFilterOptions(const OUString& rFilterOptions) bool ScImportExport::IsFormatSupported( SotClipboardFormatId nFormat ) { return nFormat == SotClipboardFormatId::STRING + || nFormat == SotClipboardFormatId::STRING_TSVC || nFormat == SotClipboardFormatId::SYLK || nFormat == SotClipboardFormatId::LINK || nFormat == SotClipboardFormatId::HTML @@ -287,6 +288,7 @@ bool ScImportExport::ImportString( const OUString& rText, SotClipboardFormatId n { // formats supporting unicode case SotClipboardFormatId::STRING : + case SotClipboardFormatId::STRING_TSVC : { ScImportStringStream aStrm( rText); return ImportStream( aStrm, OUString(), nFmt ); @@ -306,9 +308,9 @@ bool ScImportExport::ImportString( const OUString& rText, SotClipboardFormatId n bool ScImportExport::ExportString( OUString& rText, SotClipboardFormatId nFmt ) { - OSL_ENSURE( nFmt == SotClipboardFormatId::STRING, "ScImportExport::ExportString: Unicode not supported for other formats than SotClipboardFormatId::STRING" ); - if ( nFmt != SotClipboardFormatId::STRING ) + if ( nFmt != SotClipboardFormatId::STRING && nFmt != SotClipboardFormatId::STRING_TSVC ) { + SAL_WARN("sc.ui", "ScImportExport::ExportString: Unicode not supported for other formats than SotClipboardFormatId::STRING[_TSV]"); rtl_TextEncoding eEnc = osl_getThreadTextEncoding(); OString aTmp; bool bOk = ExportByteString( aTmp, eEnc, nFmt ); @@ -364,7 +366,7 @@ bool ScImportExport::ExportByteString( OString& rText, rtl_TextEncoding eEnc, So bool ScImportExport::ImportStream( SvStream& rStrm, const OUString& rBaseURL, SotClipboardFormatId nFmt ) { - if( nFmt == SotClipboardFormatId::STRING ) + if( nFmt == SotClipboardFormatId::STRING || nFmt == SotClipboardFormatId::STRING_TSVC ) { if( ExtText2Doc( rStrm ) ) // evaluate pExtOptions return true; @@ -404,7 +406,7 @@ bool ScImportExport::ImportStream( SvStream& rStrm, const OUString& rBaseURL, So bool ScImportExport::ExportStream( SvStream& rStrm, const OUString& rBaseURL, SotClipboardFormatId nFmt ) { - if( nFmt == SotClipboardFormatId::STRING ) + if( nFmt == SotClipboardFormatId::STRING || nFmt == SotClipboardFormatId::STRING_TSVC ) { if( Doc2Text( rStrm ) ) return true; diff --git a/sc/source/ui/docshell/servobj.cxx b/sc/source/ui/docshell/servobj.cxx index 712da4e96ade..1b4190f95737 100644 --- a/sc/source/ui/docshell/servobj.cxx +++ b/sc/source/ui/docshell/servobj.cxx @@ -163,7 +163,8 @@ bool ScServerObject::GetData( OUString aDdeTextFmt = pDocSh->GetDdeTextFmt(); ScDocument& rDoc = pDocSh->GetDocument(); - if( SotClipboardFormatId::STRING == SotExchange::GetFormatIdFromMimeType( rMimeType )) + SotClipboardFormatId eFormatId = SotExchange::GetFormatIdFromMimeType( rMimeType ); + if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId) { ScImportExport aObj( &rDoc, aRange ); if( aDdeTextFmt[0] == 'F' ) @@ -182,6 +183,7 @@ bool ScServerObject::GetData( } if( aDdeTextFmt == "CSV" || aDdeTextFmt == "FCSV" ) aObj.SetSeparator( ',' ); + /* TODO: STRING_TSVC could preserve line breaks with added quotes. */ aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) ); return aObj.ExportData( rMimeType, rData ); } diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx index 6c96acf74570..da7d1d30eeb4 100644 --- a/sc/source/ui/view/cellsh.cxx +++ b/sc/source/ui/view/cellsh.cxx @@ -464,6 +464,7 @@ void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFormatItem& rFormats { lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::LINK ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::STRING ); + lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::STRING_TSVC ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::DIF ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::RTF ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::RICHTEXT ); @@ -499,6 +500,7 @@ static bool lcl_IsCellPastePossible( const TransferableDataHelper& rData ) rData.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE ) || rData.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE ) || rData.HasFormat( SotClipboardFormatId::STRING ) || + rData.HasFormat( SotClipboardFormatId::STRING_TSVC ) || rData.HasFormat( SotClipboardFormatId::SYLK ) || rData.HasFormat( SotClipboardFormatId::LINK ) || rData.HasFormat( SotClipboardFormatId::HTML ) || diff --git a/sc/source/ui/view/editsh.cxx b/sc/source/ui/view/editsh.cxx index 42e8c4a6d0f4..3d1876798c88 100644 --- a/sc/source/ui/view/editsh.cxx +++ b/sc/source/ui/view/editsh.cxx @@ -280,6 +280,8 @@ void ScEditShell::Execute( SfxRequest& rReq ) pDlg->Insert( SotClipboardFormatId::STRING, EMPTY_OUSTRING ); pDlg->Insert( SotClipboardFormatId::RTF, EMPTY_OUSTRING ); pDlg->Insert( SotClipboardFormatId::RICHTEXT, EMPTY_OUSTRING ); + // Do not offer SotClipboardFormatId::STRING_TSVC for + // in-cell paste. TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pViewData->GetActiveWin() ) ); @@ -798,8 +800,9 @@ const SvxURLField* ScEditShell::GetURLField() IMPL_LINK( ScEditShell, ClipboardChanged, TransferableDataHelper*, pDataHelper, void ) { - bPastePossible = ( pDataHelper->HasFormat( SotClipboardFormatId::STRING ) || pDataHelper->HasFormat( SotClipboardFormatId::RTF ) - || pDataHelper->HasFormat( SotClipboardFormatId::RICHTEXT ) ); + bPastePossible = ( pDataHelper->HasFormat( SotClipboardFormatId::STRING ) + || pDataHelper->HasFormat( SotClipboardFormatId::RTF ) + || pDataHelper->HasFormat( SotClipboardFormatId::RICHTEXT )); SfxBindings& rBindings = pViewData->GetBindings(); rBindings.Invalidate( SID_PASTE ); @@ -809,6 +812,8 @@ IMPL_LINK( ScEditShell, ClipboardChanged, TransferableDataHelper*, pDataHelper, void ScEditShell::GetClipState( SfxItemSet& rSet ) { + // Do not offer SotClipboardFormatId::STRING_TSVC for in-cell paste. + if ( !mxClipEvtLstnr.is() ) { // create listener @@ -818,8 +823,9 @@ void ScEditShell::GetClipState( SfxItemSet& rSet ) // get initial state TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pViewData->GetActiveWin() ) ); - bPastePossible = ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) || aDataHelper.HasFormat( SotClipboardFormatId::RTF ) - || aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) ); + bPastePossible = ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) + || aDataHelper.HasFormat( SotClipboardFormatId::RTF ) + || aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) ); } SfxWhichIter aIter( rSet ); diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 6741839dd5ea..b2b553f24700 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -3642,6 +3642,7 @@ sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt ) IsDropFormatSupported( SotClipboardFormatId::LINK_SOURCE_OLE ) || IsDropFormatSupported( SotClipboardFormatId::EMBEDDED_OBJ_OLE ) || IsDropFormatSupported( SotClipboardFormatId::STRING ) || + IsDropFormatSupported( SotClipboardFormatId::STRING_TSVC ) || IsDropFormatSupported( SotClipboardFormatId::SYLK ) || IsDropFormatSupported( SotClipboardFormatId::LINK ) || IsDropFormatSupported( SotClipboardFormatId::HTML ) || @@ -3791,6 +3792,8 @@ static SotClipboardFormatId lcl_GetDropFormatId( const uno::Reference<datatransf nFormatId = SotClipboardFormatId::FILE_LIST; else if ( aDataHelper.HasFormat( SotClipboardFormatId::SIMPLE_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers) nFormatId = SotClipboardFormatId::SIMPLE_FILE; + else if ( aDataHelper.HasFormat( SotClipboardFormatId::STRING_TSVC ) ) + nFormatId = SotClipboardFormatId::STRING_TSVC; else if ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) ) nFormatId = SotClipboardFormatId::STRING; else if ( aDataHelper.HasFormat( SotClipboardFormatId::GDIMETAFILE ) ) diff --git a/sc/source/ui/view/tabvwshe.cxx b/sc/source/ui/view/tabvwshe.cxx index 78e83bf3a3b9..fe0ae20854f3 100644 --- a/sc/source/ui/view/tabvwshe.cxx +++ b/sc/source/ui/view/tabvwshe.cxx @@ -97,6 +97,7 @@ OUString ScTabViewShell::GetSelectionText( bool bWholeWord ) ScImportExport aObj( pDoc, aRange ); aObj.SetFormulas( GetViewData().GetOptions().GetOption( VOPT_FORMULAS ) ); OUString aExportOUString; + /* TODO: STRING_TSVC under some circumstances? */ aObj.ExportString( aExportOUString, SotClipboardFormatId::STRING ); aStrSelection = convertLineEnd(aExportOUString, LINEEND_CR); diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx index 4756372d151f..3f18067a8d3f 100644 --- a/sc/source/ui/view/viewfun3.cxx +++ b/sc/source/ui/view/viewfun3.cxx @@ -586,6 +586,8 @@ void ScViewFunc::PasteFromSystem() PasteFromSystem(SotClipboardFormatId::HTML_SIMPLE); else if (aDataHelper.HasFormat(SotClipboardFormatId::SYLK)) PasteFromSystem(SotClipboardFormatId::SYLK); + else if (aDataHelper.HasFormat(SotClipboardFormatId::STRING_TSVC)) + PasteFromSystem(SotClipboardFormatId::STRING_TSVC); else if (aDataHelper.HasFormat(SotClipboardFormatId::STRING)) PasteFromSystem(SotClipboardFormatId::STRING); // xxx_OLE formats come last, like in SotExchange tables @@ -685,6 +687,8 @@ void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTran nFormatId = SotClipboardFormatId::HTML_SIMPLE; else if (aDataHelper.HasFormat(SotClipboardFormatId::SYLK)) nFormatId = SotClipboardFormatId::SYLK; + else if (aDataHelper.HasFormat(SotClipboardFormatId::STRING_TSVC)) + nFormatId = SotClipboardFormatId::STRING_TSVC; else if (aDataHelper.HasFormat(SotClipboardFormatId::STRING)) nFormatId = SotClipboardFormatId::STRING; else if (aDataHelper.HasFormat(SotClipboardFormatId::GDIMETAFILE)) diff --git a/sc/source/ui/view/viewfun5.cxx b/sc/source/ui/view/viewfun5.cxx index f1feed622442..7e3194ab64d4 100644 --- a/sc/source/ui/view/viewfun5.cxx +++ b/sc/source/ui/view/viewfun5.cxx @@ -327,7 +327,8 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId, bRet = aObj.ImportStream( *xStream, OUString(), nFormatId ); // mba: clipboard always must contain absolute URLs (could be from alien source) } - else if (nFormatId == SotClipboardFormatId::STRING && aDataHelper.GetString( nFormatId, aStr )) + else if ((nFormatId == SotClipboardFormatId::STRING || nFormatId == SotClipboardFormatId::STRING_TSVC) + && aDataHelper.GetString( nFormatId, aStr )) { // Do CSV dialog if more than one line. sal_Int32 nDelim = aStr.indexOf('\n'); @@ -362,7 +363,8 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId, else bRet = aObj.ImportString( aStr, nFormatId ); } - else if (nFormatId != SotClipboardFormatId::STRING && aDataHelper.GetString( nFormatId, aStr )) + else if ((nFormatId != SotClipboardFormatId::STRING && nFormatId != SotClipboardFormatId::STRING_TSVC) + && aDataHelper.GetString( nFormatId, aStr )) bRet = aObj.ImportString( aStr, nFormatId ); InvalidateAttribs(); |