#include "CursorSet.h"
#include "ServerCursor.h"
#include <AppServerLink.h>
#include <AutoDeleter.h>
#include <PortLink.h>
#include <ServerProtocol.h>
#include <OS.h>
#include <String.h>
#include <File.h>
#include <new>
CursorSet::CursorSet(const char *name)
: BMessage()
{
AddString("name", name != NULL ? name : "Untitled");
}
status_t
CursorSet::Save(const char *path, int32 saveFlags)
{
if (path == NULL)
return B_BAD_VALUE;
BFile file;
status_t status = file.SetTo(path, B_READ_WRITE | saveFlags);
if (status != B_OK)
return status;
return Flatten(&file);
}
status_t
CursorSet::Load(const char *path)
{
if (path == NULL)
return B_BAD_VALUE;
BFile file;
status_t status = file.SetTo(path, B_READ_ONLY);
if (status != B_OK)
return status;
return Unflatten(&file);
}
status_t
CursorSet::AddCursor(BCursorID which, const BBitmap *cursor,
const BPoint &hotspot)
{
if (cursor == NULL)
return B_BAD_VALUE;
RemoveData(_CursorWhichToString(which));
BMessage message((int32)which);
message.AddString("class", "bitmap");
message.AddRect("_frame", cursor->Bounds());
message.AddInt32("_cspace", cursor->ColorSpace());
message.AddInt32("_bmflags", 0);
message.AddInt32("_rowbytes", cursor->BytesPerRow());
message.AddPoint("hotspot", hotspot);
message.AddData("_data", B_RAW_TYPE, cursor->Bits(), cursor->BitsLength());
return AddMessage(_CursorWhichToString(which), &message);
}
status_t
CursorSet::AddCursor(BCursorID which, uint8 *data)
{
if (data == NULL)
return B_BAD_VALUE;
ObjectDeleter<BBitmap> bitmap(_CursorDataToBitmap(data));
BPoint hotspot(data[2], data[3]);
status_t result = AddCursor(which, bitmap.Get(), hotspot);
return result;
}
void
CursorSet::RemoveCursor(BCursorID which)
{
RemoveData(_CursorWhichToString(which));
}
status_t
CursorSet::FindCursor(BCursorID which, BBitmap **_cursor, BPoint *_hotspot)
{
if (_cursor == NULL || _hotspot == NULL)
return B_BAD_VALUE;
BMessage message;
if (FindMessage(_CursorWhichToString(which), &message) != B_OK)
return B_NAME_NOT_FOUND;
const char *className;
if (message.FindString("class", &className) != B_OK
|| strcmp(className, "cursor") != 0) {
return B_ERROR;
}
BPoint hotspot;
if (message.FindPoint("hotspot", &hotspot) != B_OK)
return B_ERROR;
const void *buffer;
int32 bufferLength;
if (message.FindData("_data", B_RAW_TYPE, (const void **)&buffer,
(ssize_t *)&bufferLength) != B_OK) {
return B_ERROR;
}
BBitmap *bitmap = new(std::nothrow) BBitmap(message.FindRect("_frame"),
(color_space)message.FindInt32("_cspace"), true);
if (bitmap == NULL)
return B_NO_MEMORY;
memcpy(bitmap->Bits(), buffer,
min_c(bufferLength, bitmap->BitsLength()));
*_cursor = bitmap;
*_hotspot = hotspot;
return B_OK;
}
status_t
CursorSet::FindCursor(BCursorID which, ServerCursor **_cursor) const
{
if (_cursor == NULL)
return B_BAD_VALUE;
BMessage message;
if (FindMessage(_CursorWhichToString(which), &message) != B_OK)
return B_NAME_NOT_FOUND;
const char *className;
if (message.FindString("class", &className) != B_OK
|| strcmp(className, "cursor") != 0) {
return B_ERROR;
}
BPoint hotspot;
if (message.FindPoint("hotspot", &hotspot) != B_OK)
return B_ERROR;
const void *buffer;
int32 bufferLength;
if (message.FindData("_data", B_RAW_TYPE, (const void **)&buffer,
(ssize_t *)&bufferLength) != B_OK) {
return B_ERROR;
}
ServerCursor *cursor = new(std::nothrow) ServerCursor(
message.FindRect("_frame"), (color_space)message.FindInt32("_cspace"),
0, hotspot);
if (cursor == NULL)
return B_NO_MEMORY;
memcpy(cursor->Bits(), buffer,
min_c(bufferLength, (ssize_t)cursor->BitsLength()));
*_cursor = cursor;
return B_OK;
}
const char *
CursorSet::GetName()
{
const char *name;
if (FindString("name", &name) == B_OK)
return name;
return NULL;
}
void
CursorSet::SetName(const char *name)
{
if (name == NULL)
return;
RemoveData("name");
AddString("name", name);
}
const char *
CursorSet::_CursorWhichToString(BCursorID which) const
{
switch (which) {
case B_CURSOR_ID_SYSTEM_DEFAULT:
return "System default";
case B_CURSOR_ID_CONTEXT_MENU:
return "Context menu";
case B_CURSOR_ID_COPY:
return "Copy";
case B_CURSOR_ID_CROSS_HAIR:
return "Cross hair";
case B_CURSOR_ID_NO_CURSOR:
return "No cursor";
case B_CURSOR_ID_FOLLOW_LINK:
return "Follow link";
case B_CURSOR_ID_GRAB:
return "Grab";
case B_CURSOR_ID_GRABBING:
return "Grabbing";
case B_CURSOR_ID_HELP:
return "Help";
case B_CURSOR_ID_I_BEAM:
return "I-beam";
case B_CURSOR_ID_I_BEAM_HORIZONTAL:
return "I-beam horizontal";
case B_CURSOR_ID_MOVE:
return "Move";
case B_CURSOR_ID_NOT_ALLOWED:
return "Not allowed";
case B_CURSOR_ID_PROGRESS:
return "Progress";
case B_CURSOR_ID_RESIZE_NORTH:
return "Resize North";
case B_CURSOR_ID_RESIZE_EAST:
return "Resize East";
case B_CURSOR_ID_RESIZE_SOUTH:
return "Resize South";
case B_CURSOR_ID_RESIZE_WEST:
return "Resize West";
case B_CURSOR_ID_RESIZE_NORTH_EAST:
return "Resize North East";
case B_CURSOR_ID_RESIZE_NORTH_WEST:
return "Resize North West";
case B_CURSOR_ID_RESIZE_SOUTH_EAST:
return "Resize South East";
case B_CURSOR_ID_RESIZE_SOUTH_WEST:
return "Resize South West";
case B_CURSOR_ID_RESIZE_NORTH_SOUTH:
return "Resize North South";
case B_CURSOR_ID_RESIZE_EAST_WEST:
return "Resize East West";
case B_CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST:
return "Resize North East South West";
case B_CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST:
return "Resize North West South East";
case B_CURSOR_ID_ZOOM_IN:
return "Zoom in";
case B_CURSOR_ID_ZOOM_OUT:
return "Zoom out";
default:
return "Invalid";
}
}
BBitmap *
CursorSet::_CursorDataToBitmap(uint8 *data)
{
if (data == NULL)
return NULL;
BBitmap *bitmap
= new(std::nothrow) BBitmap(BRect(0,0,15,15), B_RGBA32, 0);
if (bitmap == NULL)
return NULL;
const uint32 black = 0xff000000;
const uint32 white = 0xffffffff;
uint8 *buffer = (uint8 *)bitmap->Bits();
uint16 *cursorPosition = (uint16 *)(data + 4);
uint16 *maskPosition = (uint16 *)(data + 36);
for (uint8 y = 0; y < 16; y++) {
uint32 *bitmapPosition
= (uint32 *)(buffer + y * bitmap->BytesPerRow());
uint16 cursorFlip = (cursorPosition[y] & 0xff) << 8;
cursorFlip |= (cursorPosition[y] & 0xff00) >> 8;
uint16 maskFlip = (maskPosition[y] & 0xff) << 8;
maskFlip |= (maskPosition[y] & 0xff00) >> 8;
for (uint8 x = 0; x < 16; x++) {
uint16 bit = 1 << (15 - x);
bitmapPosition[x] = ((cursorFlip & bit) != 0 ? black : white)
& ((maskFlip & bit) != 0 ? 0xffffffff : 0x00ffffff);
}
}
return bitmap;
}