301 lines
6.1 KiB
C++
301 lines
6.1 KiB
C++
/*
|
|
* Copyright 2001-2009, Haiku Inc.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Gabe Yoder (gyoder@stny.rr.com)
|
|
*/
|
|
|
|
|
|
#include <Clipboard.h>
|
|
|
|
#include <Application.h>
|
|
#include <RegistrarDefs.h>
|
|
#include <RosterPrivate.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef RUN_WITHOUT_REGISTRAR
|
|
static BClipboard sClipboard(NULL);
|
|
BClipboard *be_clipboard = &sClipboard;
|
|
#else
|
|
BClipboard *be_clipboard = NULL;
|
|
#endif
|
|
|
|
|
|
using namespace BPrivate;
|
|
|
|
|
|
BClipboard::BClipboard(const char *name, bool transient)
|
|
:
|
|
fLock("clipboard")
|
|
{
|
|
if (name != NULL)
|
|
fName = strdup(name);
|
|
else
|
|
fName = strdup("system");
|
|
|
|
fData = new BMessage();
|
|
fCount = 0;
|
|
|
|
BMessage message(B_REG_GET_CLIPBOARD_MESSENGER), reply;
|
|
if (BRoster::Private().SendTo(&message, &reply, false) == B_OK
|
|
&& reply.what == B_REG_SUCCESS
|
|
&& reply.FindMessenger("messenger", &fClipHandler) == B_OK) {
|
|
BMessage handlerMessage(B_REG_ADD_CLIPBOARD), handlerReply;
|
|
int32 result;
|
|
if (handlerMessage.AddString("name", fName) == B_OK
|
|
&& fClipHandler.SendMessage(&handlerMessage, &handlerReply) == B_OK)
|
|
handlerReply.FindInt32("result", &result);
|
|
}
|
|
}
|
|
|
|
|
|
BClipboard::~BClipboard()
|
|
{
|
|
free(fName);
|
|
delete fData;
|
|
}
|
|
|
|
|
|
const char *
|
|
BClipboard::Name() const
|
|
{
|
|
return (const char *)fName;
|
|
}
|
|
|
|
|
|
/*! \brief Returns the (locally cached) number of commits to the clipboard.
|
|
|
|
The returned value is the number of successful Commit() invocations for
|
|
the clipboard represented by this object, either invoked on this object
|
|
or another (even from another application). This method returns a locally
|
|
cached value, which might already be obsolete. For an up-to-date value
|
|
SystemCount() can be invoked.
|
|
|
|
\return The number of commits to the clipboard.
|
|
*/
|
|
uint32
|
|
BClipboard::LocalCount() const
|
|
{
|
|
return fCount;
|
|
}
|
|
|
|
|
|
/*! \brief Returns the number of commits to the clipboard.
|
|
|
|
The returned value is the number of successful Commit() invocations for
|
|
the clipboard represented by this object, either invoked on this object
|
|
or another (even from another application). This method retrieves the
|
|
value directly from the system service managing the clipboards, so it is
|
|
more expensive, but more up-to-date than LocalCount(), which returns a
|
|
locally cached value.
|
|
|
|
\return The number of commits to the clipboard.
|
|
*/
|
|
uint32
|
|
BClipboard::SystemCount() const
|
|
{
|
|
int32 value;
|
|
BMessage message(B_REG_GET_CLIPBOARD_COUNT), reply;
|
|
if (message.AddString("name", fName) == B_OK
|
|
&& fClipHandler.SendMessage(&message, &reply) == B_OK
|
|
&& reply.FindInt32("count", &value) == B_OK)
|
|
return (uint32)value;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
status_t
|
|
BClipboard::StartWatching(BMessenger target)
|
|
{
|
|
if (!target.IsValid())
|
|
return B_BAD_VALUE;
|
|
|
|
BMessage message(B_REG_CLIPBOARD_START_WATCHING), reply;
|
|
if (message.AddString("name", fName) == B_OK
|
|
&& message.AddMessenger("target", target) == B_OK
|
|
&& fClipHandler.SendMessage(&message, &reply) == B_OK) {
|
|
int32 result;
|
|
reply.FindInt32("result", &result);
|
|
return result;
|
|
}
|
|
return B_ERROR;
|
|
}
|
|
|
|
|
|
status_t
|
|
BClipboard::StopWatching(BMessenger target)
|
|
{
|
|
if (!target.IsValid())
|
|
return B_BAD_VALUE;
|
|
|
|
BMessage message(B_REG_CLIPBOARD_STOP_WATCHING), reply;
|
|
if (message.AddString("name", fName) == B_OK
|
|
&& message.AddMessenger("target", target) == B_OK
|
|
&& fClipHandler.SendMessage(&message, &reply) == B_OK) {
|
|
int32 result;
|
|
if (reply.FindInt32("result", &result) == B_OK)
|
|
return result;
|
|
}
|
|
return B_ERROR;
|
|
}
|
|
|
|
|
|
bool
|
|
BClipboard::Lock()
|
|
{
|
|
// Will this work correctly if clipboard is deleted while still waiting on
|
|
// fLock.Lock() ?
|
|
bool locked = fLock.Lock();
|
|
|
|
#ifndef RUN_WITHOUT_REGISTRAR
|
|
if (locked && _DownloadFromSystem() != B_OK) {
|
|
locked = false;
|
|
fLock.Unlock();
|
|
}
|
|
#endif
|
|
|
|
return locked;
|
|
}
|
|
|
|
|
|
void
|
|
BClipboard::Unlock()
|
|
{
|
|
fLock.Unlock();
|
|
}
|
|
|
|
|
|
bool
|
|
BClipboard::IsLocked() const
|
|
{
|
|
return fLock.IsLocked();
|
|
}
|
|
|
|
|
|
status_t
|
|
BClipboard::Clear()
|
|
{
|
|
if (!_AssertLocked())
|
|
return B_NOT_ALLOWED;
|
|
|
|
return fData->MakeEmpty();
|
|
}
|
|
|
|
|
|
status_t
|
|
BClipboard::Commit()
|
|
{
|
|
return Commit(false);
|
|
}
|
|
|
|
|
|
status_t
|
|
BClipboard::Commit(bool failIfChanged)
|
|
{
|
|
if (!_AssertLocked())
|
|
return B_NOT_ALLOWED;
|
|
|
|
status_t status = B_ERROR;
|
|
BMessage message(B_REG_UPLOAD_CLIPBOARD), reply;
|
|
if (message.AddString("name", fName) == B_OK
|
|
&& message.AddMessage("data", fData) == B_OK
|
|
&& message.AddMessenger("data source", be_app_messenger) == B_OK
|
|
&& message.AddInt32("count", fCount) == B_OK
|
|
&& message.AddBool("fail if changed", failIfChanged) == B_OK)
|
|
status = fClipHandler.SendMessage(&message, &reply);
|
|
|
|
if (status == B_OK) {
|
|
int32 count;
|
|
if (reply.FindInt32("count", &count) == B_OK)
|
|
fCount = count;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
status_t
|
|
BClipboard::Revert()
|
|
{
|
|
if (!_AssertLocked())
|
|
return B_NOT_ALLOWED;
|
|
|
|
status_t status = fData->MakeEmpty();
|
|
if (status == B_OK)
|
|
status = _DownloadFromSystem();
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
BMessenger
|
|
BClipboard::DataSource() const
|
|
{
|
|
return fDataSource;
|
|
}
|
|
|
|
|
|
BMessage *
|
|
BClipboard::Data() const
|
|
{
|
|
if (!_AssertLocked())
|
|
return NULL;
|
|
|
|
return fData;
|
|
}
|
|
|
|
|
|
// #pragma mark - Private methods
|
|
|
|
|
|
BClipboard::BClipboard(const BClipboard &)
|
|
{
|
|
// This is private, and I don't use it, so I'm not going to implement it
|
|
}
|
|
|
|
|
|
BClipboard & BClipboard::operator=(const BClipboard &)
|
|
{
|
|
// This is private, and I don't use it, so I'm not going to implement it
|
|
return *this;
|
|
}
|
|
|
|
|
|
void BClipboard::_ReservedClipboard1() {}
|
|
void BClipboard::_ReservedClipboard2() {}
|
|
void BClipboard::_ReservedClipboard3() {}
|
|
|
|
|
|
bool
|
|
BClipboard::_AssertLocked() const
|
|
{
|
|
// This function is for jumping to the debugger if not locked
|
|
if (!fLock.IsLocked()) {
|
|
debugger("The clipboard must be locked before proceeding.");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
status_t
|
|
BClipboard::_DownloadFromSystem(bool force)
|
|
{
|
|
// Apparently, the force paramater was used in some sort of
|
|
// optimization in R5. Currently, we ignore it.
|
|
BMessage message(B_REG_DOWNLOAD_CLIPBOARD), reply;
|
|
if (message.AddString("name", fName) == B_OK
|
|
&& fClipHandler.SendMessage(&message, &reply) == B_OK
|
|
&& reply.FindMessage("data", fData) == B_OK
|
|
&& reply.FindMessenger("data source", &fDataSource) == B_OK
|
|
&& reply.FindInt32("count", (int32 *)&fCount) == B_OK)
|
|
return B_OK;
|
|
|
|
return B_ERROR;
|
|
}
|