summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2017-11-13 16:41:49 +0100
committerEike Rathke <erack@redhat.com>2017-11-13 18:43:35 +0100
commitf435cdba5b4ea98dc30b4b4879de21a542c8a84d (patch)
tree742c42d3f3a3d170df47838bd756be1a74115e52
parent971b81b1c0922ab749eaf620cbf56d9780a15cfb (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>
-rw-r--r--sc/source/ui/app/seltrans.cxx1
-rw-r--r--sc/source/ui/app/transobj.cxx11
-rw-r--r--sc/source/ui/docshell/docsh4.cxx6
-rw-r--r--sc/source/ui/docshell/impex.cxx10
-rw-r--r--sc/source/ui/docshell/servobj.cxx4
-rw-r--r--sc/source/ui/view/cellsh.cxx2
-rw-r--r--sc/source/ui/view/editsh.cxx14
-rw-r--r--sc/source/ui/view/gridwin.cxx3
-rw-r--r--sc/source/ui/view/tabvwshe.cxx1
-rw-r--r--sc/source/ui/view/viewfun3.cxx4
-rw-r--r--sc/source/ui/view/viewfun5.cxx6
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();