summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2019-07-19 23:44:20 +0100
committerMichael Meeks <michael.meeks@collabora.com>2019-08-02 11:41:47 -0400
commit3dbf6e43ebd6a52b665fab906711f173f0e5ba82 (patch)
treefd6c4db33a2653871d5298bdb0a6775790d63308 /desktop
parenta85b62cb8cbbbd25316f77b49055c1fb817c60e3 (diff)
Add more powerful selection fetch & clipboard set methods.
Change-Id: I6633356d13480377a83a006588ec69ebcb56a93f
Diffstat (limited to 'desktop')
-rw-r--r--desktop/source/lib/init.cxx144
-rw-r--r--desktop/source/lib/lokclipboard.cxx71
-rw-r--r--desktop/source/lib/lokclipboard.hxx13
3 files changed, 180 insertions, 48 deletions
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 4b808f4b1c1b..bb50736df0fe 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -170,6 +170,7 @@ static std::weak_ptr< LibreOfficeKitDocumentClass > gDocumentClass;
static void SetLastExceptionMsg(const OUString& s = OUString())
{
+ SAL_WARN("lok", "lok exception " + s);
if (gImpl)
gImpl->maLastExceptionMsg = s;
}
@@ -787,6 +788,17 @@ static void doc_setTextSelection (LibreOfficeKitDocument* pThis,
static char* doc_getTextSelection(LibreOfficeKitDocument* pThis,
const char* pMimeType,
char** pUsedMimeType);
+static int doc_getSelection (LibreOfficeKitDocument* pThis,
+ const char **pMimeTypes,
+ size_t *pOutCount,
+ char ***pOutMimeTypes,
+ size_t **pOutSizes,
+ char ***pOutStreams);
+static int doc_setClipboard (LibreOfficeKitDocument* pThis,
+ const size_t nInCount,
+ const char **pInMimeTypes,
+ const size_t *pInSizes,
+ const char **pInStreams);
static bool doc_paste(LibreOfficeKitDocument* pThis,
const char* pMimeType,
const char* pData,
@@ -886,6 +898,8 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone
m_pDocumentClass->postUnoCommand = doc_postUnoCommand;
m_pDocumentClass->setTextSelection = doc_setTextSelection;
m_pDocumentClass->getTextSelection = doc_getTextSelection;
+ m_pDocumentClass->getSelection = doc_getSelection;
+ m_pDocumentClass->setClipboard = doc_setClipboard;
m_pDocumentClass->paste = doc_paste;
m_pDocumentClass->setGraphicSelection = doc_setGraphicSelection;
m_pDocumentClass->resetSelection = doc_resetSelection;
@@ -3372,10 +3386,11 @@ static void doc_setTextSelection(LibreOfficeKitDocument* pThis, int nType, int n
static bool getFromTransferrable(
const css::uno::Reference<css::datatransfer::XTransferable> &xTransferable,
- const char *pMimeType, OString &aRet)
+ const OString &aInMimeType, OString &aRet)
{
+ OString aMimeType(aInMimeType);
+
// Take care of UTF-8 text here.
- OString aMimeType(pMimeType);
bool bConvert = false;
sal_Int32 nIndex = 0;
if (aMimeType.getToken(0, ';', nIndex) == "text/plain")
@@ -3435,6 +3450,14 @@ static bool getFromTransferrable(
return true;;
}
+// Tolerate embedded \0s etc.
+static char *convertOString(const OString &rStr)
+{
+ char* pMemory = static_cast<char*>(malloc(rStr.getLength() + 1));
+ memcpy(pMemory, rStr.getStr(), rStr.getLength() + 1);
+ return pMemory;
+}
+
static char* doc_getTextSelection(LibreOfficeKitDocument* pThis, const char* pMimeType, char** pUsedMimeType)
{
comphelper::ProfileZone aZone("doc_getTextSelection");
@@ -3461,30 +3484,107 @@ static char* doc_getTextSelection(LibreOfficeKitDocument* pThis, const char* pMi
pType = "text/plain;charset=utf-8";
OString aRet;
- bool bSuccess = getFromTransferrable(xTransferable, pType, aRet);
+ bool bSuccess = getFromTransferrable(xTransferable, OString(pType), aRet);
if (!bSuccess)
return nullptr;
- char* pMemory = static_cast<char*>(malloc(aRet.getLength() + 1));
- assert(pMemory); // Don't handle OOM conditions
- strcpy(pMemory, aRet.getStr());
-
if (pUsedMimeType) // legacy
{
if (pMimeType)
+ *pUsedMimeType = strdup(pMimeType);
+ else
+ *pUsedMimeType = nullptr;
+ }
+
+ return convertOString(aRet);
+}
+
+static int doc_getSelection(LibreOfficeKitDocument* pThis,
+ const char **pMimeTypes,
+ size_t *pOutCount,
+ char ***pOutMimeTypes,
+ size_t **pOutSizes,
+ char ***pOutStreams)
+{
+ SolarMutexGuard aGuard;
+ SetLastExceptionMsg();
+
+ assert (pOutCount);
+ assert (pOutMimeTypes);
+ assert (pOutSizes);
+ assert (pOutStreams);
+
+ *pOutCount = 0;
+ *pOutMimeTypes = nullptr;
+ *pOutSizes = nullptr;
+ *pOutStreams = nullptr;
+
+ ITiledRenderable* pDoc = getTiledRenderable(pThis);
+ if (!pDoc)
+ {
+ SetLastExceptionMsg("Document doesn't support tiled rendering");
+ return 0;
+ }
+
+ css::uno::Reference<css::datatransfer::XTransferable> xTransferable = pDoc->getSelection();
+ if (!xTransferable)
+ {
+ SetLastExceptionMsg("No selection available");
+ return 0;
+ }
+
+ std::vector<OString> aMimeTypes;
+ if (!pMimeTypes) // everything
+ {
+ uno::Sequence< css::datatransfer::DataFlavor > flavors = xTransferable->getTransferDataFlavors();
+ if (!flavors.getLength())
+ {
+ SetLastExceptionMsg("Flavourless selection");
+ return 0;
+ }
+ for (auto &it : flavors)
+ aMimeTypes.push_back(OUStringToOString(it.MimeType, RTL_TEXTENCODING_UTF8));
+ }
+ else
+ {
+ for (size_t i = 0; pMimeTypes[i]; ++i)
+ aMimeTypes.push_back(OString(pMimeTypes[i]));
+ }
+
+ *pOutCount = aMimeTypes.size();
+ *pOutSizes = static_cast<size_t *>(malloc(*pOutCount * sizeof(size_t)));
+ *pOutMimeTypes = static_cast<char **>(malloc(*pOutCount * sizeof(char *)));
+ *pOutStreams = static_cast<char **>(malloc(*pOutCount * sizeof(char *)));
+ for (size_t i = 0; i < aMimeTypes.size(); ++i)
+ {
+ (*pOutMimeTypes)[i] = strdup(aMimeTypes[i].getStr());
+
+ OString aRet;
+ bool bSuccess = getFromTransferrable(xTransferable, aMimeTypes[i], aRet);
+ if (!bSuccess || aRet.getLength() < 1)
{
- *pUsedMimeType = static_cast<char*>(malloc(strlen(pMimeType) + 1));
- strcpy(*pUsedMimeType, pMimeType);
+ (*pOutSizes)[i] = 0;
+ (*pOutStreams)[i] = nullptr;
}
else
- *pUsedMimeType = nullptr;
+ {
+ (*pOutSizes)[i] = aRet.getLength();
+ (*pOutStreams)[i] = convertOString(aRet);
+ }
}
- return pMemory;
+ return 1;
}
-static bool doc_paste(LibreOfficeKitDocument* pThis, const char* pMimeType, const char* pData, size_t nSize)
+static int doc_setClipboard(LibreOfficeKitDocument* pThis,
+ const size_t nInCount,
+ const char **pInMimeTypes,
+ const size_t *pInSizes,
+ const char **pInStreams)
{
+ SolarMutexGuard aGuard;
+ if (gImpl)
+
comphelper::ProfileZone aZone("doc_paste");
SolarMutexGuard aGuard;
@@ -3497,16 +3597,34 @@ static bool doc_paste(LibreOfficeKitDocument* pThis, const char* pMimeType, cons
return false;
}
- uno::Reference<datatransfer::XTransferable> xTransferable(new LOKTransferable(pMimeType, pData, nSize));
+ uno::Reference<datatransfer::XTransferable> xTransferable(new LOKTransferable(nInCount, pInMimeTypes, pInSizes, pInStreams));
uno::Reference<datatransfer::clipboard::XClipboard> xClipboard(new LOKClipboard);
xClipboard->setContents(xTransferable, uno::Reference<datatransfer::clipboard::XClipboardOwner>());
pDoc->setClipboard(xClipboard);
+
if (!pDoc->isMimeTypeSupported())
{
SetLastExceptionMsg("Document doesn't support this mime type");
return false;
}
+ return true;
+}
+
+static bool doc_paste(LibreOfficeKitDocument* pThis, const char* pMimeType, const char* pData, size_t nSize)
+{
+ SolarMutexGuard aGuard;
+
+ const char *pInMimeTypes[1];
+ const char *pInStreams[1];
+ size_t pInSizes[1];
+ pInMimeTypes[0] = pMimeType;
+ pInSizes[0] = nSize;
+ pInStreams[0] = pData;
+
+ if (!doc_setClipboard(pThis, 1, pInMimeTypes, pInSizes, pInStreams))
+ return false;
+
uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
{
{"AnchorType", uno::makeAny(static_cast<sal_uInt16>(text::TextContentAnchorType_AS_CHARACTER))},
diff --git a/desktop/source/lib/lokclipboard.cxx b/desktop/source/lib/lokclipboard.cxx
index e5ba5fe9e80a..015690bd9bc4 100644
--- a/desktop/source/lib/lokclipboard.cxx
+++ b/desktop/source/lib/lokclipboard.cxx
@@ -38,50 +38,65 @@ LOKTransferable::LOKTransferable(OUString sMimeType, const css::uno::Sequence<sa
{
}
-uno::Any SAL_CALL LOKTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor)
+LOKTransferable::LOKTransferable(const size_t nInCount, const char** pInMimeTypes,
+ const size_t* pInSizes, const char** pInStreams)
{
- uno::Any aRet;
- if (rFlavor.DataType == cppu::UnoType<OUString>::get())
+ m_aContent.reserve(nInCount);
+ m_aFlavors = css::uno::Sequence<css::datatransfer::DataFlavor>(nInCount);
+ for (size_t i = 0; i < nInCount; ++i)
{
- auto pText = reinterpret_cast<sal_Char*>(m_aSequence.getArray());
- aRet <<= OUString(pText, m_aSequence.getLength(), RTL_TEXTENCODING_UTF8);
+ OUString aMimeType = OUString::fromUtf8(pInMimeTypes[i]);
+
+ // cf. sot/source/base/exchange.cxx for these two exceptional types.
+ if (aMimeType.startsWith("text/plain"))
+ {
+ aMimeType = "text/plain;charset=utf-16";
+ m_aFlavors[i].DataType = cppu::UnoType<OUString>::get();
+ }
+ else if (aMimeType == "application/x-libreoffice-tsvc")
+ m_aFlavors[i].DataType = cppu::UnoType<OUString>::get();
+ else
+ m_aFlavors[i].DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get();
+ m_aFlavors[i].MimeType = aMimeType;
+ m_aFlavors[i].HumanPresentableName = aMimeType;
+
+ uno::Any aContent;
+ if (m_aFlavors[i].DataType == cppu::UnoType<OUString>::get())
+ aContent <<= OUString(pInStreams[i], pInSizes[i], RTL_TEXTENCODING_UTF8);
+ else
+ aContent <<= css::uno::Sequence<sal_Int8>(
+ reinterpret_cast<const sal_Int8*>(pInStreams[i]), pInSizes[i]);
+ m_aContent.push_back(aContent);
}
- else
- aRet <<= m_aSequence;
- return aRet;
}
-std::vector<datatransfer::DataFlavor> LOKTransferable::getTransferDataFlavorsAsVector()
+uno::Any SAL_CALL LOKTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor)
{
- std::vector<datatransfer::DataFlavor> aRet;
- datatransfer::DataFlavor aFlavor;
- aFlavor.MimeType = m_aMimeType;
- aFlavor.DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get();
-
- sal_Int32 nIndex(0);
- if (m_aMimeType.getToken(0, ';', nIndex) == "text/plain")
+ assert(m_aContent.size() == m_aFlavors.getLength());
+ for (size_t i = 0; i < m_aContent.size(); ++i)
{
- if (m_aMimeType.getToken(0, ';', nIndex) != "charset=utf-16")
- aFlavor.MimeType = "text/plain;charset=utf-16";
- aFlavor.DataType = cppu::UnoType<OUString>::get();
+ if (m_aFlavors[i].MimeType == rFlavor.MimeType)
+ {
+ if (m_aFlavors[i].DataType != rFlavor.DataType)
+ SAL_WARN("lok", "Horror type mismatch!");
+ return m_aContent[i];
+ }
}
- aRet.push_back(aFlavor);
-
- return aRet;
+ return uno::Any();
}
uno::Sequence<datatransfer::DataFlavor> SAL_CALL LOKTransferable::getTransferDataFlavors()
{
- return comphelper::containerToSequence(getTransferDataFlavorsAsVector());
+ return m_aFlavors;
}
sal_Bool SAL_CALL LOKTransferable::isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor)
{
- const std::vector<datatransfer::DataFlavor> aFlavors = getTransferDataFlavorsAsVector();
- return std::any_of(aFlavors.begin(), aFlavors.end(),
- [&rFlavor](const datatransfer::DataFlavor& i) {
- return i.MimeType == rFlavor.MimeType && i.DataType == rFlavor.DataType;
- });
+ return std::find_if(m_aFlavors.begin(), m_aFlavors.end(),
+ [&rFlavor](const datatransfer::DataFlavor& i) {
+ return i.MimeType == rFlavor.MimeType && i.DataType == rFlavor.DataType;
+ })
+ != m_aFlavors.end();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/source/lib/lokclipboard.hxx b/desktop/source/lib/lokclipboard.hxx
index db2c7380bb25..5da8b3e2b63e 100644
--- a/desktop/source/lib/lokclipboard.hxx
+++ b/desktop/source/lib/lokclipboard.hxx
@@ -34,15 +34,14 @@ public:
/// Represents the contents of LOKClipboard.
class LOKTransferable : public cppu::WeakImplHelper<css::datatransfer::XTransferable>
{
- OUString m_aMimeType;
- css::uno::Sequence<sal_Int8> m_aSequence;
-
- /// Provides a list of flavors, used by getTransferDataFlavors() and isDataFlavorSupported().
- std::vector<css::datatransfer::DataFlavor> getTransferDataFlavorsAsVector();
+ css::uno::Sequence<css::datatransfer::DataFlavor> m_aFlavors;
+ std::vector<css::uno::Any> m_aContent;
public:
- LOKTransferable(const char* pMimeType, const char* pData, std::size_t nSize);
- LOKTransferable(OUString sMimeType, const css::uno::Sequence<sal_Int8>& aSequence);
+ LOKTransferable(const size_t nInCount,
+ const char **pInMimeTypes,
+ const size_t *pInSizes,
+ const char **pInStreams);
css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& rFlavor) override;