2006-02-05 21:14:14 +03:00
|
|
|
/*
|
|
|
|
* Copyright 2001-2006, Haiku.
|
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* DarkWyrm <bpmagic@columbus.rr.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2004-07-30 19:16:59 +04:00
|
|
|
#include <AppServerLink.h>
|
2006-02-05 21:14:14 +03:00
|
|
|
#include <CursorSet.h>
|
|
|
|
#include <PortLink.h>
|
|
|
|
#include <ServerCursor.h>
|
2003-07-24 23:41:15 +04:00
|
|
|
#include <ServerProtocol.h>
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
#include <OS.h>
|
|
|
|
#include <String.h>
|
|
|
|
#include <File.h>
|
|
|
|
|
2005-05-27 17:34:52 +04:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
/*!
|
|
|
|
\brief Constructor
|
|
|
|
\name Name of the cursor set.
|
|
|
|
*/
|
|
|
|
CursorSet::CursorSet(const char *name)
|
2005-05-27 17:34:52 +04:00
|
|
|
: BMessage()
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
2005-05-27 17:34:52 +04:00
|
|
|
AddString("name", name ? name : "Untitled");
|
2003-07-24 23:41:15 +04:00
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
/*!
|
|
|
|
\brief Saves the data in the cursor set to a file
|
|
|
|
\param path Path of the file to save to.
|
|
|
|
\param saveflags BFile open file flags. B_READ_WRITE is implied.
|
|
|
|
\return
|
|
|
|
- \c B_OK: Everything went fine.
|
|
|
|
- \c B_BAD_VALUE: path is NULL
|
|
|
|
- \c other value: See BFile::SetTo and BMessage::Flatten return codes
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
status_t
|
2006-02-05 21:14:14 +03:00
|
|
|
CursorSet::Save(const char *path, int32 saveFlags)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
2005-05-27 17:34:52 +04:00
|
|
|
if (!path)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_BAD_VALUE;
|
|
|
|
|
|
|
|
BFile file;
|
2006-02-05 21:14:14 +03:00
|
|
|
status_t status = file.SetTo(path, B_READ_WRITE | saveFlags);
|
2005-05-27 17:34:52 +04:00
|
|
|
if (status != B_OK)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
return Flatten(&file);
|
2003-07-24 23:41:15 +04:00
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
/*!
|
|
|
|
\brief Loads the data into the cursor set from a file
|
|
|
|
\param path Path of the file to load from.
|
|
|
|
\return
|
|
|
|
- \c B_OK: Everything went fine.
|
|
|
|
- \c B_BAD_VALUE: path is NULL
|
|
|
|
- \c other value: See BFile::SetTo and BMessage::Flatten return codes
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
status_t
|
|
|
|
CursorSet::Load(const char *path)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
2005-05-27 17:34:52 +04:00
|
|
|
if (!path)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_BAD_VALUE;
|
|
|
|
|
|
|
|
BFile file;
|
2005-05-27 17:34:52 +04:00
|
|
|
status_t status = file.SetTo(path, B_READ_ONLY);
|
|
|
|
if (status != B_OK)
|
|
|
|
return status;
|
2003-07-24 23:41:15 +04:00
|
|
|
|
2005-05-27 17:34:52 +04:00
|
|
|
return Unflatten(&file);
|
2003-07-24 23:41:15 +04:00
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
/*!
|
|
|
|
\brief Adds the cursor to the set and replaces any existing entry for the given specifier
|
2005-07-18 04:22:08 +04:00
|
|
|
\param which System cursor specifier defined in CursorSet.h
|
2003-07-24 23:41:15 +04:00
|
|
|
\param cursor BBitmap to represent the new cursor. Size should be 48x48 or less.
|
|
|
|
\param hotspot The recipient of the hotspot for the cursor
|
|
|
|
\return B_BAD_VALUE if cursor is NULL, otherwise B_OK
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
status_t
|
|
|
|
CursorSet::AddCursor(cursor_which which, const BBitmap *cursor, const BPoint &hotspot)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
2005-05-27 17:34:52 +04:00
|
|
|
if (!cursor)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_BAD_VALUE;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
// Remove the data if it exists already
|
2006-02-05 21:14:14 +03:00
|
|
|
RemoveData(_CursorWhichToString(which));
|
2005-05-27 17:34:52 +04:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
// Actually add the data to our set
|
|
|
|
BMessage msg((int32)which);
|
|
|
|
|
|
|
|
msg.AddString("class","bitmap");
|
|
|
|
msg.AddRect("_frame",cursor->Bounds());
|
|
|
|
msg.AddInt32("_cspace",cursor->ColorSpace());
|
|
|
|
|
|
|
|
msg.AddInt32("_bmflags",0);
|
|
|
|
msg.AddInt32("_rowbytes",cursor->BytesPerRow());
|
|
|
|
msg.AddPoint("hotspot",hotspot);
|
|
|
|
msg.AddData("_data",B_RAW_TYPE,cursor->Bits(), cursor->BitsLength());
|
2006-02-05 21:14:14 +03:00
|
|
|
AddMessage(_CursorWhichToString(which),&msg);
|
2003-07-24 23:41:15 +04:00
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
/*!
|
|
|
|
\brief Adds the cursor to the set and replaces any existing entry for the given specifier
|
2005-07-18 04:22:08 +04:00
|
|
|
\param which System cursor specifier defined in CursorSet.h
|
2003-07-24 23:41:15 +04:00
|
|
|
\param data R5 cursor data pointer
|
|
|
|
\return B_BAD_VALUE if data is NULL, otherwise B_OK
|
|
|
|
|
|
|
|
When possible, it is better to use the BBitmap version of AddCursor because this
|
|
|
|
function must convert the R5 cursor data into a BBitmap
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
status_t
|
|
|
|
CursorSet::AddCursor(cursor_which which, int8 *data)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
|
|
|
// Convert cursor data to a bitmap because all cursors are internally stored
|
|
|
|
// as bitmaps
|
2005-05-27 17:34:52 +04:00
|
|
|
if (!data)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_BAD_VALUE;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
BBitmap *bmp = _CursorDataToBitmap(data);
|
2003-07-24 23:41:15 +04:00
|
|
|
BPoint pt(data[2],data[3]);
|
2005-05-27 17:34:52 +04:00
|
|
|
|
|
|
|
status_t stat = AddCursor(which,bmp,pt);
|
|
|
|
|
|
|
|
delete bmp;
|
2003-07-24 23:41:15 +04:00
|
|
|
return stat;
|
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
/*!
|
|
|
|
\brief Removes the data associated with the specifier from the cursor set
|
2005-07-18 04:22:08 +04:00
|
|
|
\param which System cursor specifier defined in CursorSet.h
|
2003-07-24 23:41:15 +04:00
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
void
|
|
|
|
CursorSet::RemoveCursor(cursor_which which)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
2006-02-05 21:14:14 +03:00
|
|
|
RemoveData(_CursorWhichToString(which));
|
2003-07-24 23:41:15 +04:00
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
/*!
|
|
|
|
\brief Retrieves a cursor from the set.
|
2005-07-18 04:22:08 +04:00
|
|
|
\param which System cursor specifier defined in CursorSet.h
|
2003-07-24 23:41:15 +04:00
|
|
|
\param cursor Bitmap** to receive a newly-allocated BBitmap containing the appropriate data
|
|
|
|
\param hotspot The recipient of the hotspot for the cursor
|
|
|
|
\return
|
|
|
|
- \c B_OK: Success
|
|
|
|
- \c B_BAD_VALUE: a NULL parameter was passed
|
|
|
|
- \c B_NAME_NOT_FOUND: The specified cursor does not exist in this set
|
|
|
|
- \c B_ERROR: An internal error occurred
|
|
|
|
|
|
|
|
BBitmaps created by this function are the responsibility of the caller.
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
status_t
|
|
|
|
CursorSet::FindCursor(cursor_which which, BBitmap **cursor, BPoint *hotspot)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
2005-05-27 17:34:52 +04:00
|
|
|
if (!cursor || !hotspot);
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_BAD_VALUE;
|
|
|
|
|
2005-05-27 17:34:52 +04:00
|
|
|
BMessage msg;
|
2006-02-05 21:14:14 +03:00
|
|
|
if (FindMessage(_CursorWhichToString(which), &msg) != B_OK)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_NAME_NOT_FOUND;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
const void *buffer;
|
2004-07-30 19:16:59 +04:00
|
|
|
const char *tempstr;
|
2003-07-24 23:41:15 +04:00
|
|
|
int32 bufferLength;
|
|
|
|
BBitmap *bmp;
|
|
|
|
BPoint hotpt;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
|
|
|
if (msg.FindString("class", &tempstr) != B_OK)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_ERROR;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
|
|
|
if (msg.FindPoint("hotspot", &hotpt) != B_OK)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_ERROR;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
|
|
|
if (strcmp(tempstr, "cursor") == 0) {
|
|
|
|
bmp = new BBitmap(msg.FindRect("_frame"),
|
|
|
|
(color_space)msg.FindInt32("_cspace"), true);
|
|
|
|
msg.FindData("_data", B_RAW_TYPE, (const void **)&buffer,
|
|
|
|
(ssize_t *)&bufferLength);
|
2003-07-24 23:41:15 +04:00
|
|
|
memcpy(bmp->Bits(), buffer, bufferLength);
|
|
|
|
|
2005-05-27 17:34:52 +04:00
|
|
|
*cursor = bmp;
|
|
|
|
*hotspot = hotpt;
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
return B_ERROR;
|
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
/*!
|
|
|
|
\brief Retrieves a cursor from the set.
|
2005-07-18 04:22:08 +04:00
|
|
|
\param which System cursor specifier defined in CursorSet.h
|
2003-07-24 23:41:15 +04:00
|
|
|
\param cursor ServerCursor** to receive a newly-allocated ServerCursor containing the appropriate data
|
|
|
|
\return
|
|
|
|
- \c B_OK: Success
|
|
|
|
- \c B_BAD_VALUE: a NULL parameter was passed
|
|
|
|
- \c B_NAME_NOT_FOUND: The specified cursor does not exist in this set
|
|
|
|
- \c B_ERROR: An internal error occurred
|
|
|
|
|
|
|
|
BBitmaps created by this function are the responsibility of the caller.
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
status_t
|
|
|
|
CursorSet::FindCursor(cursor_which which, ServerCursor **_cursor)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
|
|
|
BMessage msg;
|
2006-02-05 21:14:14 +03:00
|
|
|
if (FindMessage(_CursorWhichToString(which), &msg) != B_OK)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_NAME_NOT_FOUND;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
|
|
|
const char *className;
|
|
|
|
BPoint hotspot;
|
|
|
|
|
|
|
|
if (msg.FindString("class", &className) != B_OK)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_ERROR;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
|
|
|
if (msg.FindPoint("hotspot", &hotspot) != B_OK)
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_ERROR;
|
|
|
|
|
2005-05-27 17:34:52 +04:00
|
|
|
if (strcmp(className, "cursor") == 0) {
|
|
|
|
ServerCursor *cursor = new ServerCursor(msg.FindRect("_frame"),
|
|
|
|
(color_space)msg.FindInt32("_cspace"), 0, hotspot);
|
|
|
|
|
|
|
|
const void *buffer;
|
|
|
|
int32 bufferLength;
|
|
|
|
msg.FindData("_data",B_RAW_TYPE, (const void **)&buffer,
|
|
|
|
(ssize_t *)&bufferLength);
|
|
|
|
memcpy(cursor->Bits(), buffer, bufferLength);
|
2003-07-24 23:41:15 +04:00
|
|
|
|
2005-05-27 17:34:52 +04:00
|
|
|
*_cursor = cursor;
|
2003-07-24 23:41:15 +04:00
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
return B_ERROR;
|
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-10-10 06:33:38 +04:00
|
|
|
/*!
|
|
|
|
\brief Returns the name of the set
|
|
|
|
\return The name of the set
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
const char *
|
|
|
|
CursorSet::GetName(void)
|
2003-10-10 06:33:38 +04:00
|
|
|
{
|
2004-07-30 19:16:59 +04:00
|
|
|
const char *name;
|
2005-05-27 17:34:52 +04:00
|
|
|
if (FindString("name", &name) == B_OK)
|
2004-07-27 11:15:43 +04:00
|
|
|
return name;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
2003-10-10 06:33:38 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
/*!
|
|
|
|
\brief Renames the cursor set
|
|
|
|
\param name new name of the set.
|
|
|
|
|
|
|
|
This function will fail if given a NULL name
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
void
|
|
|
|
CursorSet::SetName(const char *name)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
2005-05-27 17:34:52 +04:00
|
|
|
if (!name)
|
2003-07-24 23:41:15 +04:00
|
|
|
return;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
RemoveData("name");
|
2005-05-27 17:34:52 +04:00
|
|
|
AddString("name", name);
|
2003-07-24 23:41:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Returns a string for the specified cursor attribute
|
2005-07-18 04:22:08 +04:00
|
|
|
\param which System cursor specifier defined in CursorSet.h
|
2003-07-24 23:41:15 +04:00
|
|
|
\return Name for the cursor specifier
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
const char *
|
2006-02-05 21:14:14 +03:00
|
|
|
CursorSet::_CursorWhichToString(cursor_which which)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
2005-05-27 17:34:52 +04:00
|
|
|
switch (which) {
|
2003-07-24 23:41:15 +04:00
|
|
|
case B_CURSOR_DEFAULT:
|
|
|
|
return "Default";
|
|
|
|
case B_CURSOR_TEXT:
|
|
|
|
return "Text";
|
|
|
|
case B_CURSOR_MOVE:
|
|
|
|
return "Move";
|
|
|
|
case B_CURSOR_DRAG:
|
|
|
|
return "Drag";
|
|
|
|
case B_CURSOR_RESIZE:
|
|
|
|
return "Resize";
|
|
|
|
case B_CURSOR_RESIZE_NWSE:
|
|
|
|
return "Resize NWSE";
|
|
|
|
case B_CURSOR_RESIZE_NESW:
|
|
|
|
return "Resize NESW";
|
|
|
|
case B_CURSOR_RESIZE_NS:
|
|
|
|
return "Resize NS";
|
|
|
|
case B_CURSOR_RESIZE_EW:
|
|
|
|
return "Resize EW";
|
|
|
|
case B_CURSOR_OTHER:
|
|
|
|
return "Other";
|
|
|
|
default:
|
|
|
|
return "Invalid";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Creates a new BBitmap from R5 cursor data
|
|
|
|
\param data Pointer to data in the R5 cursor data format
|
|
|
|
\return NULL if data was NULL, otherwise a new BBitmap
|
|
|
|
|
|
|
|
BBitmaps returned by this function are always in the RGBA32 color space
|
|
|
|
*/
|
2005-05-27 17:34:52 +04:00
|
|
|
BBitmap *
|
2006-02-05 21:14:14 +03:00
|
|
|
CursorSet::_CursorDataToBitmap(int8 *data)
|
2003-07-24 23:41:15 +04:00
|
|
|
{
|
|
|
|
// 68-byte array used in R5 for holding cursors.
|
|
|
|
// This API has serious problems and should be deprecated(but supported) in R2
|
|
|
|
|
|
|
|
// Now that we have all the setup, we're going to map (for now) the cursor
|
|
|
|
// to RGBA32. Eventually, there will be support for 16 and 8-bit depths
|
2005-05-27 17:34:52 +04:00
|
|
|
if (data) {
|
|
|
|
BBitmap *bmp = new BBitmap(BRect(0,0,15,15),B_RGBA32,0);
|
|
|
|
uint32 black = 0xFF000000, white=0xFFFFFFFF, *bmppos;
|
|
|
|
uint16 *cursorpos, *maskpos, cursorflip, maskflip;
|
|
|
|
uint16 cursorval, maskval, powval;
|
|
|
|
uint8 i, j, *_buffer;
|
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
_buffer=(uint8*)bmp->Bits();
|
|
|
|
cursorpos=(uint16*)(data+4);
|
|
|
|
maskpos=(uint16*)(data+36);
|
|
|
|
|
|
|
|
// for each row in the cursor data
|
2005-05-27 17:34:52 +04:00
|
|
|
for (j = 0; j < 16; j++) {
|
|
|
|
bmppos = (uint32*)(_buffer+ (j*bmp->BytesPerRow()) );
|
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
// On intel, our bytes end up swapped, so we must swap them back
|
2005-05-27 17:34:52 +04:00
|
|
|
cursorflip = (cursorpos[j] & 0xFF) << 8;
|
2003-07-24 23:41:15 +04:00
|
|
|
cursorflip |= (cursorpos[j] & 0xFF00) >> 8;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
|
|
|
maskflip = (maskpos[j] & 0xFF) << 8;
|
2003-07-24 23:41:15 +04:00
|
|
|
maskflip |= (maskpos[j] & 0xFF00) >> 8;
|
2005-05-27 17:34:52 +04:00
|
|
|
|
2003-07-24 23:41:15 +04:00
|
|
|
// for each column in each row of cursor data
|
2005-05-27 17:34:52 +04:00
|
|
|
for (i = 0; i < 16; i++) {
|
2003-07-24 23:41:15 +04:00
|
|
|
// Get the values and dump them to the bitmap
|
2005-05-27 17:34:52 +04:00
|
|
|
powval = 1 << (15-i);
|
|
|
|
cursorval = cursorflip & powval;
|
|
|
|
maskval = maskflip & powval;
|
|
|
|
bmppos[i] = (cursorval != 0 ? black : white)
|
|
|
|
& (maskval > 0 ? 0xFFFFFFFF : 0x00FFFFFF);
|
2003-07-24 23:41:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return bmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|