usb_ecm: Use the current configuration instead of a fixed one.
[haiku.git] / src / servers / app / CursorSet.cpp
blob67c71491fc3e38f4a79522397c7740f63dbaf8cd
1 /*
2 * Copyright 2001-2010, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 */
10 #include "CursorSet.h"
11 #include "ServerCursor.h"
13 #include <AppServerLink.h>
14 #include <PortLink.h>
15 #include <ServerProtocol.h>
17 #include <OS.h>
18 #include <String.h>
19 #include <File.h>
21 #include <new>
24 /*!
25 \brief Constructor
26 \name Name of the cursor set.
28 CursorSet::CursorSet(const char *name)
29 : BMessage()
31 AddString("name", name != NULL ? name : "Untitled");
35 /*!
36 \brief Saves the data in the cursor set to a file
37 \param path Path of the file to save to.
38 \param saveflags BFile open file flags. B_READ_WRITE is implied.
39 \return
40 - \c B_OK: Everything went fine.
41 - \c B_BAD_VALUE: path is NULL
42 - \c other value: See BFile::SetTo and BMessage::Flatten return codes
44 status_t
45 CursorSet::Save(const char *path, int32 saveFlags)
47 if (path == NULL)
48 return B_BAD_VALUE;
50 BFile file;
51 status_t status = file.SetTo(path, B_READ_WRITE | saveFlags);
52 if (status != B_OK)
53 return status;
55 return Flatten(&file);
59 /*!
60 \brief Loads the data into the cursor set from a file
61 \param path Path of the file to load from.
62 \return
63 - \c B_OK: Everything went fine.
64 - \c B_BAD_VALUE: path is NULL
65 - \c other value: See BFile::SetTo and BMessage::Flatten return codes
67 status_t
68 CursorSet::Load(const char *path)
70 if (path == NULL)
71 return B_BAD_VALUE;
73 BFile file;
74 status_t status = file.SetTo(path, B_READ_ONLY);
75 if (status != B_OK)
76 return status;
78 return Unflatten(&file);
82 /*!
83 \brief Adds the cursor to the set and replaces any existing entry for the given specifier
84 \param which System cursor specifier defined in CursorSet.h
85 \param cursor BBitmap to represent the new cursor. Size should be 48x48 or less.
86 \param hotspot The recipient of the hotspot for the cursor
87 \return
88 - \c B_OK: Everything went fine.
89 - \c B_BAD_VALUE: cursor is NULL
90 - \c other value: See BMessage::AddMessage return codes.
92 status_t
93 CursorSet::AddCursor(BCursorID which, const BBitmap *cursor,
94 const BPoint &hotspot)
96 if (cursor == NULL)
97 return B_BAD_VALUE;
99 // Remove the data if it exists already
100 RemoveData(_CursorWhichToString(which));
102 // Actually add the data to our set
103 BMessage message((int32)which);
105 message.AddString("class", "bitmap");
106 message.AddRect("_frame", cursor->Bounds());
107 message.AddInt32("_cspace", cursor->ColorSpace());
109 message.AddInt32("_bmflags", 0);
110 message.AddInt32("_rowbytes", cursor->BytesPerRow());
111 message.AddPoint("hotspot", hotspot);
112 message.AddData("_data", B_RAW_TYPE, cursor->Bits(), cursor->BitsLength());
114 return AddMessage(_CursorWhichToString(which), &message);
119 \brief Adds the cursor to the set and replaces any existing entry for the given specifier
120 \param which System cursor specifier defined in CursorSet.h
121 \param data R5 cursor data pointer
122 \return B_BAD_VALUE if data is NULL, otherwise B_OK
124 When possible, it is better to use the BBitmap version of AddCursor because this
125 function must convert the R5 cursor data into a BBitmap
127 status_t
128 CursorSet::AddCursor(BCursorID which, uint8 *data)
130 // Convert cursor data to a bitmap because all cursors are internally stored
131 // as bitmaps
132 if (data == NULL)
133 return B_BAD_VALUE;
135 BBitmap *bitmap = _CursorDataToBitmap(data);
136 BPoint hotspot(data[2], data[3]);
138 status_t result = AddCursor(which, bitmap, hotspot);
140 delete bitmap;
141 return result;
146 \brief Removes the data associated with the specifier from the cursor set
147 \param which System cursor specifier defined in CursorSet.h
149 void
150 CursorSet::RemoveCursor(BCursorID which)
152 RemoveData(_CursorWhichToString(which));
157 \brief Retrieves a cursor from the set.
158 \param which System cursor specifier defined in CursorSet.h
159 \param cursor Bitmap** to receive a newly-allocated BBitmap containing the appropriate data
160 \param hotspot The recipient of the hotspot for the cursor
161 \return
162 - \c B_OK: Success
163 - \c B_BAD_VALUE: a NULL parameter was passed
164 - \c B_NAME_NOT_FOUND: The specified cursor does not exist in this set
165 - \c B_ERROR: An internal error occurred
167 BBitmaps created by this function are the responsibility of the caller.
169 status_t
170 CursorSet::FindCursor(BCursorID which, BBitmap **_cursor, BPoint *_hotspot)
172 if (_cursor == NULL || _hotspot == NULL)
173 return B_BAD_VALUE;
175 BMessage message;
176 if (FindMessage(_CursorWhichToString(which), &message) != B_OK)
177 return B_NAME_NOT_FOUND;
179 const char *className;
180 if (message.FindString("class", &className) != B_OK
181 || strcmp(className, "cursor") != 0) {
182 return B_ERROR;
185 BPoint hotspot;
186 if (message.FindPoint("hotspot", &hotspot) != B_OK)
187 return B_ERROR;
189 const void *buffer;
190 int32 bufferLength;
191 if (message.FindData("_data", B_RAW_TYPE, (const void **)&buffer,
192 (ssize_t *)&bufferLength) != B_OK) {
193 return B_ERROR;
196 BBitmap *bitmap = new(std::nothrow) BBitmap(message.FindRect("_frame"),
197 (color_space)message.FindInt32("_cspace"), true);
198 if (bitmap == NULL)
199 return B_NO_MEMORY;
201 memcpy(bitmap->Bits(), buffer,
202 min_c(bufferLength, bitmap->BitsLength()));
204 *_cursor = bitmap;
205 *_hotspot = hotspot;
206 return B_OK;
211 \brief Retrieves a cursor from the set.
212 \param which System cursor specifier defined in CursorSet.h
213 \param cursor ServerCursor** to receive a newly-allocated ServerCursor containing the appropriate data
214 \return
215 - \c B_OK: Success
216 - \c B_BAD_VALUE: a NULL parameter was passed
217 - \c B_NAME_NOT_FOUND: The specified cursor does not exist in this set
218 - \c B_ERROR: An internal error occurred
220 BBitmaps created by this function are the responsibility of the caller.
222 status_t
223 CursorSet::FindCursor(BCursorID which, ServerCursor **_cursor) const
225 if (_cursor == NULL)
226 return B_BAD_VALUE;
228 BMessage message;
229 if (FindMessage(_CursorWhichToString(which), &message) != B_OK)
230 return B_NAME_NOT_FOUND;
232 const char *className;
233 if (message.FindString("class", &className) != B_OK
234 || strcmp(className, "cursor") != 0) {
235 return B_ERROR;
238 BPoint hotspot;
239 if (message.FindPoint("hotspot", &hotspot) != B_OK)
240 return B_ERROR;
242 const void *buffer;
243 int32 bufferLength;
244 if (message.FindData("_data", B_RAW_TYPE, (const void **)&buffer,
245 (ssize_t *)&bufferLength) != B_OK) {
246 return B_ERROR;
249 ServerCursor *cursor = new(std::nothrow) ServerCursor(
250 message.FindRect("_frame"), (color_space)message.FindInt32("_cspace"),
251 0, hotspot);
252 if (cursor == NULL)
253 return B_NO_MEMORY;
255 memcpy(cursor->Bits(), buffer,
256 min_c(bufferLength, (ssize_t)cursor->BitsLength()));
258 *_cursor = cursor;
259 return B_OK;
264 \brief Returns the name of the set
265 \return The name of the set
267 const char *
268 CursorSet::GetName()
270 const char *name;
271 if (FindString("name", &name) == B_OK)
272 return name;
274 return NULL;
279 \brief Renames the cursor set
280 \param name new name of the set.
282 This function will fail if given a NULL name
284 void
285 CursorSet::SetName(const char *name)
287 if (name == NULL)
288 return;
290 RemoveData("name");
291 AddString("name", name);
296 \brief Returns a string for the specified cursor attribute
297 \param which System cursor specifier defined in CursorSet.h
298 \return Name for the cursor specifier
300 const char *
301 CursorSet::_CursorWhichToString(BCursorID which) const
303 switch (which) {
304 case B_CURSOR_ID_SYSTEM_DEFAULT:
305 return "System default";
306 case B_CURSOR_ID_CONTEXT_MENU:
307 return "Context menu";
308 case B_CURSOR_ID_COPY:
309 return "Copy";
310 case B_CURSOR_ID_CROSS_HAIR:
311 return "Cross hair";
312 case B_CURSOR_ID_NO_CURSOR:
313 return "No cursor";
314 case B_CURSOR_ID_FOLLOW_LINK:
315 return "Follow link";
316 case B_CURSOR_ID_GRAB:
317 return "Grab";
318 case B_CURSOR_ID_GRABBING:
319 return "Grabbing";
320 case B_CURSOR_ID_HELP:
321 return "Help";
322 case B_CURSOR_ID_I_BEAM:
323 return "I-beam";
324 case B_CURSOR_ID_I_BEAM_HORIZONTAL:
325 return "I-beam horizontal";
326 case B_CURSOR_ID_MOVE:
327 return "Move";
328 case B_CURSOR_ID_NOT_ALLOWED:
329 return "Not allowed";
330 case B_CURSOR_ID_PROGRESS:
331 return "Progress";
332 case B_CURSOR_ID_RESIZE_NORTH:
333 return "Resize North";
334 case B_CURSOR_ID_RESIZE_EAST:
335 return "Resize East";
336 case B_CURSOR_ID_RESIZE_SOUTH:
337 return "Resize South";
338 case B_CURSOR_ID_RESIZE_WEST:
339 return "Resize West";
340 case B_CURSOR_ID_RESIZE_NORTH_EAST:
341 return "Resize North East";
342 case B_CURSOR_ID_RESIZE_NORTH_WEST:
343 return "Resize North West";
344 case B_CURSOR_ID_RESIZE_SOUTH_EAST:
345 return "Resize South East";
346 case B_CURSOR_ID_RESIZE_SOUTH_WEST:
347 return "Resize South West";
348 case B_CURSOR_ID_RESIZE_NORTH_SOUTH:
349 return "Resize North South";
350 case B_CURSOR_ID_RESIZE_EAST_WEST:
351 return "Resize East West";
352 case B_CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST:
353 return "Resize North East South West";
354 case B_CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST:
355 return "Resize North West South East";
356 case B_CURSOR_ID_ZOOM_IN:
357 return "Zoom in";
358 case B_CURSOR_ID_ZOOM_OUT:
359 return "Zoom out";
360 default:
361 return "Invalid";
366 \brief Creates a new BBitmap from R5 cursor data
367 \param data Pointer to data in the R5 cursor data format
368 \return NULL if data was NULL, otherwise a new BBitmap
370 BBitmaps returned by this function are always in the RGBA32 color space
372 BBitmap *
373 CursorSet::_CursorDataToBitmap(uint8 *data)
375 // 68-byte array used in R5 for holding cursors.
376 // This API has serious problems and should be deprecated (but supported)
377 // in R2
379 if (data == NULL)
380 return NULL;
382 // Now that we have all the setup, we're going to map (for now) the cursor
383 // to RGBA32. Eventually, there will be support for 16 and 8-bit depths
384 BBitmap *bitmap
385 = new(std::nothrow) BBitmap(BRect(0,0,15,15), B_RGBA32, 0);
386 if (bitmap == NULL)
387 return NULL;
389 const uint32 black = 0xff000000;
390 const uint32 white = 0xffffffff;
392 uint8 *buffer = (uint8 *)bitmap->Bits();
393 uint16 *cursorPosition = (uint16 *)(data + 4);
394 uint16 *maskPosition = (uint16 *)(data + 36);
396 // for each row in the cursor data
397 for (uint8 y = 0; y < 16; y++) {
398 uint32 *bitmapPosition
399 = (uint32 *)(buffer + y * bitmap->BytesPerRow());
401 // TODO: use proper byteswap macros
402 // On intel, our bytes end up swapped, so we must swap them back
403 uint16 cursorFlip = (cursorPosition[y] & 0xff) << 8;
404 cursorFlip |= (cursorPosition[y] & 0xff00) >> 8;
406 uint16 maskFlip = (maskPosition[y] & 0xff) << 8;
407 maskFlip |= (maskPosition[y] & 0xff00) >> 8;
409 // for each column in each row of cursor data
410 for (uint8 x = 0; x < 16; x++) {
411 // Get the values and dump them to the bitmap
412 uint16 bit = 1 << (15 - x);
413 bitmapPosition[x] = ((cursorFlip & bit) != 0 ? black : white)
414 & ((maskFlip & bit) != 0 ? 0xffffffff : 0x00ffffff);
418 return bitmap;