1 /* 2 * Copyright 2002-2006, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold, bonefish@users.sf.net 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 11 #include <NodeInfo.h> 12 13 #include <new> 14 #include <string.h> 15 16 #include <MimeTypes.h> 17 #include <Bitmap.h> 18 #include <Entry.h> 19 #include <IconUtils.h> 20 #include <Node.h> 21 #include <Path.h> 22 #include <Rect.h> 23 24 #include <fs_attr.h> 25 #include <fs_info.h> 26 27 using namespace std; 28 29 // attribute names 30 #define NI_BEOS "BEOS" 31 static const char *kNITypeAttribute = NI_BEOS ":TYPE"; 32 static const char *kNIPreferredAppAttribute = NI_BEOS ":PREF_APP"; 33 static const char *kNIAppHintAttribute = NI_BEOS ":PPATH"; 34 static const char *kNIMiniIconAttribute = NI_BEOS ":M:STD_ICON"; 35 static const char *kNILargeIconAttribute = NI_BEOS ":L:STD_ICON"; 36 static const char *kNIIconAttribute = NI_BEOS ":ICON"; 37 38 39 /*! \brief Creates an uninitialized BNodeInfo object. 40 41 After created a BNodeInfo with this, you should call SetTo(). 42 43 \see SetTo(BNode *node) 44 */ 45 BNodeInfo::BNodeInfo() 46 : 47 fNode(NULL), 48 fCStatus(B_NO_INIT) 49 { 50 } 51 52 // constructor 53 /*! \brief Creates a BNodeInfo object and initializes it to the supplied node. 54 55 \param node The node to gather information on. Can be any flavor. 56 57 \see SetTo(BNode *node) 58 */ 59 BNodeInfo::BNodeInfo(BNode *node) 60 : 61 fNode(NULL), 62 fCStatus(B_NO_INIT) 63 { 64 fCStatus = SetTo(node); 65 } 66 67 // destructor 68 /*! \brief Frees all resources associated with this object. 69 70 The BNode object passed to the constructor or to SetTo() is not deleted. 71 */ 72 BNodeInfo::~BNodeInfo() 73 { 74 } 75 76 // SetTo 77 /*! \brief Initializes the BNodeInfo to the supplied node. 78 79 The BNodeInfo object does not copy the supplied object, but uses it 80 directly. You must not delete the object you supply while the BNodeInfo 81 does exist. The BNodeInfo does not take over ownership of the BNode and 82 it doesn't delete it on destruction. 83 84 \param node The node to play with 85 86 \return 87 - \c B_OK: Everything went fine. 88 - \c B_BAD_VALUE: The node was bad. 89 */ 90 status_t 91 BNodeInfo::SetTo(BNode *node) 92 { 93 fNode = NULL; 94 // check parameter 95 fCStatus = (node && node->InitCheck() == B_OK ? B_OK : B_BAD_VALUE); 96 if (fCStatus == B_OK) 97 fNode = node; 98 return fCStatus; 99 } 100 101 // InitCheck 102 /*! \brief returns whether the object has been properly initialized. 103 104 \return 105 - \c B_OK: Everything went fine. 106 - \c B_NO_INIT: The node is not properly initialized. 107 */ 108 status_t 109 BNodeInfo::InitCheck() const 110 { 111 return fCStatus; 112 } 113 114 // GetType 115 /*! \brief Gets the node's MIME type. 116 117 Writes the contents of the "BEOS:TYPE" attribute into the supplied buffer 118 \a type. 119 120 \param type A pointer to a pre-allocated character buffer of size 121 \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the 122 node shall be written. 123 \return 124 - \c B_OK: Everything went fine. 125 - \c B_NO_INIT: The object is not properly initialized. 126 - \c B_BAD_VALUE: \c NULL \a type or the type string stored in the 127 attribute is longer than \c B_MIME_TYPE_LENGTH. 128 - \c B_BAD_TYPE: The attribute the type string is stored in has the wrong 129 type. 130 - \c B_ENTRY_NOT_FOUND: No type is set on the node. 131 - other error codes 132 */ 133 status_t 134 BNodeInfo::GetType(char *type) const 135 { 136 // check parameter and initialization 137 status_t error = (type ? B_OK : B_BAD_VALUE); 138 if (error == B_OK && InitCheck() != B_OK) 139 error = B_NO_INIT; 140 // get the attribute info and check type and length of the attr contents 141 attr_info attrInfo; 142 if (error == B_OK) 143 error = fNode->GetAttrInfo(kNITypeAttribute, &attrInfo); 144 if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE) 145 error = B_BAD_TYPE; 146 if (error == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH) 147 error = B_BAD_DATA; 148 149 // read the data 150 if (error == B_OK) { 151 ssize_t read = fNode->ReadAttr(kNITypeAttribute, attrInfo.type, 0, 152 type, attrInfo.size); 153 if (read < 0) 154 error = read; 155 else if (read != attrInfo.size) 156 error = B_ERROR; 157 158 if (error == B_OK) { 159 // attribute strings doesn't have to be null terminated 160 type[min_c(attrInfo.size, B_MIME_TYPE_LENGTH - 1)] = '\0'; 161 } 162 } 163 return error; 164 } 165 166 // SetType 167 /*! \brief Sets the node's MIME type. 168 169 The supplied string is written into the node's "BEOS:TYPE" attribute. 170 171 If \a type is \c NULL, the respective attribute is removed. 172 173 \param type The MIME type to be assigned to the node. Must not be longer 174 than \c B_MIME_TYPE_LENGTH (including the terminating null). 175 May be \c NULL. 176 \return 177 - \c B_OK: Everything went fine. 178 - \c B_NO_INIT: The object is not properly initialized. 179 - \c B_BAD_VALUE: \a type is longer than \c B_MIME_TYPE_LENGTH. 180 - other error codes 181 */ 182 status_t 183 BNodeInfo::SetType(const char *type) 184 { 185 // check parameter and initialization 186 status_t error = B_OK; 187 if (error == B_OK && type && strlen(type) >= B_MIME_TYPE_LENGTH) 188 error = B_BAD_VALUE; 189 if (error == B_OK && InitCheck() != B_OK) 190 error = B_NO_INIT; 191 192 // write/remove the attribute 193 if (error == B_OK) { 194 if (type) { 195 size_t toWrite = strlen(type) + 1; 196 ssize_t written = fNode->WriteAttr(kNITypeAttribute, 197 B_MIME_STRING_TYPE, 0, type, 198 toWrite); 199 if (written < 0) 200 error = written; 201 else if (written != (ssize_t)toWrite) 202 error = B_ERROR; 203 } else 204 error = fNode->RemoveAttr(kNITypeAttribute); 205 } 206 return error; 207 } 208 209 // GetIcon 210 /*! \brief Gets the node's icon. 211 212 The icon stored in the node's "BEOS:L:STD_ICON" (large) or 213 "BEOS:M:STD_ICON" (mini) attribute is retrieved. 214 215 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 216 to store the requested icon (16x16 for the mini and 32x32 for the 217 large icon). 218 \param k Specifies the size of the icon to be retrieved: \c B_MINI_ICON 219 for the mini and \c B_LARGE_ICON for the large icon. 220 \return 221 - \c B_OK: Everything went fine. 222 - \c B_NO_INIT: The object is not properly initialized. 223 - \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a k or bitmap 224 dimensions (\a icon) and icon size (\a k) do not match. 225 - other error codes 226 */ 227 status_t 228 BNodeInfo::GetIcon(BBitmap *icon, icon_size k) const 229 { 230 const char* iconAttribute = kNIIconAttribute; 231 const char* miniIconAttribute = kNIMiniIconAttribute; 232 const char* largeIconAttribute = kNILargeIconAttribute; 233 234 return BIconUtils::GetIcon(fNode, iconAttribute, miniIconAttribute, 235 largeIconAttribute, k, icon); 236 237 // status_t error = B_OK; 238 // // set some icon size related variables 239 // const char *attribute = NULL; 240 // BRect bounds; 241 // uint32 attrType = 0; 242 // size_t attrSize = 0; 243 // switch (k) { 244 // case B_MINI_ICON: 245 // attribute = kNIMiniIconAttribute; 246 // bounds.Set(0, 0, 15, 15); 247 // attrType = B_MINI_ICON_TYPE; 248 // attrSize = 16 * 16; 249 // break; 250 // case B_LARGE_ICON: 251 // attribute = kNILargeIconAttribute; 252 // bounds.Set(0, 0, 31, 31); 253 // attrType = B_LARGE_ICON_TYPE; 254 // attrSize = 32 * 32; 255 // break; 256 // default: 257 // error = B_BAD_VALUE; 258 // break; 259 // } 260 // 261 // // check parameter and initialization 262 // if (error == B_OK 263 // && (!icon || icon->InitCheck() != B_OK || icon->Bounds() != bounds)) { 264 // error = B_BAD_VALUE; 265 // } 266 // if (error == B_OK && InitCheck() != B_OK) 267 // error = B_NO_INIT; 268 // 269 // // get the attribute info and check type and size of the attr contents 270 // attr_info attrInfo; 271 // if (error == B_OK) 272 // error = fNode->GetAttrInfo(attribute, &attrInfo); 273 // if (error == B_OK && attrInfo.type != attrType) 274 // error = B_BAD_TYPE; 275 // if (error == B_OK && attrInfo.size != attrSize) 276 // error = B_BAD_DATA; 277 // 278 // // read the attribute 279 // if (error == B_OK) { 280 // bool otherColorSpace = (icon->ColorSpace() != B_CMAP8); 281 // char *buffer = NULL; 282 // ssize_t read; 283 // if (otherColorSpace) { 284 // // other color space than stored in attribute 285 // buffer = new(nothrow) char[attrSize]; 286 // if (!buffer) 287 // error = B_NO_MEMORY; 288 // if (error == B_OK) { 289 // read = fNode->ReadAttr(attribute, attrType, 0, buffer, 290 // attrSize); 291 // } 292 // } else { 293 // read = fNode->ReadAttr(attribute, attrType, 0, icon->Bits(), 294 // attrSize); 295 // } 296 // if (error == B_OK) { 297 // if (read < 0) 298 // error = read; 299 // else if (read != attrInfo.size) 300 // error = B_ERROR; 301 // } 302 // if (otherColorSpace) { 303 // // other color space than stored in attribute 304 // if (error == B_OK) { 305 // error = icon->ImportBits(buffer, attrSize, B_ANY_BYTES_PER_ROW, 306 // 0, B_CMAP8); 307 // } 308 // delete[] buffer; 309 // } 310 // } 311 // return error; 312 } 313 314 // SetIcon 315 /*! \brief Sets the node's icon. 316 317 The icon is stored in the node's "BEOS:L:STD_ICON" (large) or 318 "BEOS:M:STD_ICON" (mini) attribute. 319 320 If \a icon is \c NULL, the respective attribute is removed. 321 322 \param icon A pointer to the BBitmap containing the icon to be set. 323 May be \c NULL. 324 \param k Specifies the size of the icon to be set: \c B_MINI_ICON 325 for the mini and \c B_LARGE_ICON for the large icon. 326 \return 327 - \c B_OK: Everything went fine. 328 - \c B_NO_INIT: The object is not properly initialized. 329 - \c B_BAD_VALUE: Unknown icon size \a k or bitmap dimensions (\a icon) 330 and icon size (\a k) do not match. 331 - other error codes 332 */ 333 status_t 334 BNodeInfo::SetIcon(const BBitmap *icon, icon_size k) 335 { 336 status_t error = B_OK; 337 // set some icon size related variables 338 const char *attribute = NULL; 339 BRect bounds; 340 uint32 attrType = 0; 341 size_t attrSize = 0; 342 switch (k) { 343 case B_MINI_ICON: 344 attribute = kNIMiniIconAttribute; 345 bounds.Set(0, 0, 15, 15); 346 attrType = B_MINI_ICON_TYPE; 347 attrSize = 16 * 16; 348 break; 349 case B_LARGE_ICON: 350 attribute = kNILargeIconAttribute; 351 bounds.Set(0, 0, 31, 31); 352 attrType = B_LARGE_ICON_TYPE; 353 attrSize = 32 * 32; 354 break; 355 default: 356 error = B_BAD_VALUE; 357 break; 358 } 359 360 // check parameter and initialization 361 if (error == B_OK && icon 362 && (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) { 363 error = B_BAD_VALUE; 364 } 365 if (error == B_OK && InitCheck() != B_OK) 366 error = B_NO_INIT; 367 368 // write/remove the attribute 369 if (error == B_OK) { 370 if (icon) { 371 bool otherColorSpace = (icon->ColorSpace() != B_CMAP8); 372 ssize_t written = 0; 373 if (otherColorSpace) { 374 BBitmap bitmap(bounds, B_BITMAP_NO_SERVER_LINK, B_CMAP8); 375 error = bitmap.InitCheck(); 376 if (error == B_OK) 377 error = bitmap.ImportBits(icon); 378 if (error == B_OK) { 379 written = fNode->WriteAttr(attribute, attrType, 0, 380 bitmap.Bits(), attrSize); 381 } 382 } else { 383 written = fNode->WriteAttr(attribute, attrType, 0, 384 icon->Bits(), attrSize); 385 } 386 if (error == B_OK) { 387 if (written < 0) 388 error = written; 389 else if (written != (ssize_t)attrSize) 390 error = B_ERROR; 391 } 392 } else // no icon given => remove 393 error = fNode->RemoveAttr(attribute); 394 } 395 return error; 396 } 397 398 399 // GetIcon 400 /*! \brief Gets the node's icon. 401 402 The icon stored in the node's "BEOS:ICON" attribute is retrieved. 403 The caller is responsible to \c delete[] the returned data if the 404 function was successful. 405 406 \param data A pointer in which a pointer to the icon data 407 will be returned. 408 \param size A pointer in which the size of the found icon data 409 will be returned. 410 \param type A pointer in which the type of the found icon data 411 will be returned. 412 \return 413 - \c B_OK: Everything went fine. 414 - \c B_NO_INIT: The object is not properly initialized. 415 - \c B_BAD_VALUE: \c NULL \a data, \c NULL size or \c NULL \a type. 416 - \c B_NO_MEMORY: No memory to allocate the data buffer. 417 - other error codes 418 */ 419 status_t 420 BNodeInfo::GetIcon(uint8** data, size_t* size, type_code* type) const 421 { 422 // check params 423 if (!data || !size || !type) 424 return B_BAD_VALUE; 425 426 // check initialization 427 if (InitCheck() != B_OK) 428 return B_NO_INIT; 429 430 // get the attribute info and check type and size of the attr contents 431 attr_info attrInfo; 432 status_t ret = fNode->GetAttrInfo(kNIIconAttribute, &attrInfo); 433 if (ret < B_OK) 434 return ret; 435 436 // chicken out on unrealisticly large attributes 437 if (attrInfo.size > 128 * 1024) 438 return B_ERROR; 439 440 // fill the params 441 *type = attrInfo.type; 442 *size = attrInfo.size; 443 *data = new (nothrow) uint8[*size]; 444 445 if (!*data) 446 return B_NO_MEMORY; 447 448 // featch the data 449 ssize_t read = fNode->ReadAttr(kNIIconAttribute, *type, 0, *data, *size); 450 if (read != attrInfo.size) { 451 delete[] *data; 452 *data = NULL; 453 return B_ERROR; 454 } 455 456 return B_OK; 457 } 458 459 // SetIcon 460 /*! \brief Sets the node's icon. 461 462 The icon is stored in the node's "BEOS:ICON" attribute. 463 464 If \a data is \c NULL, the respective attribute is removed. 465 466 \param data A pointer to valid vector icon data. 467 May be \c NULL. 468 \param size Specifies the size of the provided data buffer. 469 \return 470 - \c B_OK: Everything went fine. 471 - \c B_NO_INIT: The object is not properly initialized. 472 - other error codes 473 */ 474 status_t 475 BNodeInfo::SetIcon(const uint8* data, size_t size) 476 { 477 // check initialization 478 if (InitCheck() != B_OK) 479 return B_NO_INIT; 480 481 status_t error = B_OK; 482 483 // write/remove the attribute 484 if (data && size > 0) { 485 ssize_t written = fNode->WriteAttr(kNIIconAttribute, 486 B_VECTOR_ICON_TYPE, 487 0, data, size); 488 if (written < 0) 489 error = (status_t)written; 490 else if (written != (ssize_t)size) 491 error = B_ERROR; 492 } else // no icon given => remove 493 error = fNode->RemoveAttr(kNIIconAttribute); 494 495 return error; 496 } 497 498 // GetPreferredApp 499 /*! \brief Gets the node's preferred application. 500 501 Writes the contents of the "BEOS:PREF_APP" attribute into the supplied 502 buffer \a signature. The preferred application is identifief by its 503 signature. 504 505 \param signature A pointer to a pre-allocated character buffer of size 506 \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the 507 preferred application shall be written. 508 \param verb Specifies the type of access the preferred application is 509 requested for. Currently only \c B_OPEN is meaningful. 510 \return 511 - \c B_OK: Everything went fine. 512 - \c B_NO_INIT: The object is not properly initialized. 513 - \c B_BAD_VALUE: \c NULL \a signature or bad app_verb \a verb. 514 - other error codes 515 */ 516 status_t 517 BNodeInfo::GetPreferredApp(char *signature, app_verb verb) const 518 { 519 // check parameter and initialization 520 status_t error = (signature && verb == B_OPEN ? B_OK : B_BAD_VALUE); 521 if (error == B_OK && InitCheck() != B_OK) 522 error = B_NO_INIT; 523 524 // get the attribute info and check type and length of the attr contents 525 attr_info attrInfo; 526 if (error == B_OK) 527 error = fNode->GetAttrInfo(kNIPreferredAppAttribute, &attrInfo); 528 if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE) 529 error = B_BAD_TYPE; 530 if (error == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH) 531 error = B_BAD_DATA; 532 533 // read the data 534 if (error == B_OK) { 535 ssize_t read = fNode->ReadAttr(kNIPreferredAppAttribute, attrInfo.type, 536 0, signature, attrInfo.size); 537 if (read < 0) 538 error = read; 539 else if (read != attrInfo.size) 540 error = B_ERROR; 541 542 if (error == B_OK) { 543 // attribute strings doesn't have to be null terminated 544 signature[min_c(attrInfo.size, B_MIME_TYPE_LENGTH - 1)] = '\0'; 545 } 546 } 547 return error; 548 } 549 550 // SetPreferredApp 551 /*! \brief Sets the node's preferred application. 552 553 The supplied string is written into the node's "BEOS:PREF_APP" attribute. 554 555 If \a signature is \c NULL, the respective attribute is removed. 556 557 \param signature The signature of the preferred application to be set. 558 Must not be longer than \c B_MIME_TYPE_LENGTH (including the 559 terminating null). May be \c NULL. 560 \param verb Specifies the type of access the preferred application shall 561 be set for. Currently only \c B_OPEN is meaningful. 562 \return 563 - \c B_OK: Everything went fine. 564 - \c B_NO_INIT: The object is not properly initialized. 565 - \c B_BAD_VALUE: \c NULL \a signature, \a signature is longer than 566 \c B_MIME_TYPE_LENGTH or bad app_verb \a verb. 567 - other error codes 568 */ 569 status_t 570 BNodeInfo::SetPreferredApp(const char *signature, app_verb verb) 571 { 572 // check parameters and initialization 573 status_t error = (verb == B_OPEN ? B_OK : B_BAD_VALUE); 574 if (error == B_OK && signature && strlen(signature) >= B_MIME_TYPE_LENGTH) 575 error = B_BAD_VALUE; 576 if (error == B_OK && InitCheck() != B_OK) 577 error = B_NO_INIT; 578 579 // write/remove the attribute 580 if (error == B_OK) { 581 if (signature) { 582 size_t toWrite = strlen(signature) + 1; 583 ssize_t written = fNode->WriteAttr(kNIPreferredAppAttribute, 584 B_MIME_STRING_TYPE, 0, 585 signature, toWrite); 586 if (written < 0) 587 error = written; 588 else if (written != (ssize_t)toWrite) 589 error = B_ERROR; 590 } else 591 error = fNode->RemoveAttr(kNIPreferredAppAttribute); 592 } 593 return error; 594 } 595 596 // GetAppHint 597 /*! \brief Returns a hint in form of and entry_ref to the application that 598 shall be used to open this node. 599 600 The path contained in the node's "BEOS:PPATH" attribute is converted into 601 an entry_ref and returned in \a ref. 602 603 \param ref A pointer to a pre-allocated entry_ref into which the requested 604 app hint shall be written. 605 \return 606 - \c B_OK: Everything went fine. 607 - \c B_NO_INIT: The object is not properly initialized. 608 - \c B_BAD_VALUE: \c NULL \a ref. 609 - other error codes 610 */ 611 status_t 612 BNodeInfo::GetAppHint(entry_ref *ref) const 613 { 614 // check parameter and initialization 615 status_t error = (ref ? B_OK : B_BAD_VALUE); 616 if (error == B_OK && InitCheck() != B_OK) 617 error = B_NO_INIT; 618 619 // get the attribute info and check type and length of the attr contents 620 attr_info attrInfo; 621 if (error == B_OK) 622 error = fNode->GetAttrInfo(kNIAppHintAttribute, &attrInfo); 623 // NOTE: The attribute type should be B_STRING_TYPE, but R5 uses 624 // B_MIME_STRING_TYPE. 625 if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE) 626 error = B_BAD_TYPE; 627 if (error == B_OK && attrInfo.size > B_PATH_NAME_LENGTH) 628 error = B_BAD_DATA; 629 630 // read the data 631 if (error == B_OK) { 632 char path[B_PATH_NAME_LENGTH]; 633 ssize_t read = fNode->ReadAttr(kNIAppHintAttribute, attrInfo.type, 0, 634 path, attrInfo.size); 635 if (read < 0) 636 error = read; 637 else if (read != attrInfo.size) 638 error = B_ERROR; 639 // get the entry_ref for the path 640 if (error == B_OK) { 641 // attribute strings doesn't have to be null terminated 642 path[min_c(attrInfo.size, B_PATH_NAME_LENGTH - 1)] = '\0'; 643 error = get_ref_for_path(path, ref); 644 } 645 } 646 return error; 647 } 648 649 // SetAppHint 650 /*! \brief Sets the node's app hint. 651 652 The supplied entry_ref is converted into a path and stored in the node's 653 "BEOS:PPATH" attribute. 654 655 If \a ref is \c NULL, the respective attribute is removed. 656 657 \param ref A pointer to an entry_ref referring to the application. 658 May be \c NULL. 659 \return 660 - \c B_OK: Everything went fine. 661 - \c B_NO_INIT: The object is not properly initialized. 662 - \c B_BAD_VALUE: \c NULL \a ref. 663 - other error codes 664 */ 665 status_t 666 BNodeInfo::SetAppHint(const entry_ref *ref) 667 { 668 // check parameter and initialization 669 status_t error = B_OK; 670 if (error == B_OK && InitCheck() != B_OK) 671 error = B_NO_INIT; 672 673 // write/remove the attribute 674 if (error == B_OK) { 675 if (ref) { 676 BPath path; 677 error = path.SetTo(ref); 678 if (error == B_OK) { 679 size_t toWrite = strlen(path.Path()) + 1; 680 ssize_t written = fNode->WriteAttr(kNIAppHintAttribute, 681 B_MIME_STRING_TYPE, 0, 682 path.Path(), toWrite); 683 if (written < 0) 684 error = written; 685 else if (written != (ssize_t)toWrite) 686 error = B_ERROR; 687 } 688 } else 689 error = fNode->RemoveAttr(kNIAppHintAttribute); 690 } 691 return error; 692 } 693 694 // GetTrackerIcon 695 /*! \brief Gets the icon which tracker displays. 696 697 This method tries real hard to find an icon for the node: 698 - If the node has no type, return the icon for B_FILE_MIME_TYPE if it's a 699 regular file, for B_DIRECTORY_MIME_TYPE if it's a directory, etc. from 700 the MIME database. Even, if the node has an own icon! 701 - Ask GetIcon(). 702 - Get the preferred application and ask the MIME database, if that 703 application has a special icon for the node's file type. 704 - Ask the MIME database whether there is an icon for the node's file type. 705 - Ask the MIME database for the preferred application for the node's 706 file type and whether this application has a special icon for the type. 707 - Return the icon for whatever type of node (file/dir/etc.) from the MIME database. 708 This list is processed in the given order and the icon the first 709 successful attempt provides is returned. In case none of them yields an 710 icon, this method fails. This is very unlikely though. 711 712 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 713 to store the requested icon (16x16 for the mini and 32x32 for the 714 large icon). 715 \param iconSize Specifies the size of the icon to be retrieved: \c B_MINI_ICON 716 for the mini and \c B_LARGE_ICON for the large icon. 717 \return 718 - \c B_OK: Everything went fine. 719 - \c B_NO_INIT: The object is not properly initialized. 720 - \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a iconSize or bitmap 721 dimensions (\a icon) and icon size (\a iconSize) do not match. 722 - other error codes 723 */ 724 status_t 725 BNodeInfo::GetTrackerIcon(BBitmap *icon, icon_size iconSize) const 726 { 727 if (!icon) 728 return B_BAD_VALUE; 729 730 // set some icon size related variables 731 status_t error = B_OK; 732 BRect bounds; 733 switch (iconSize) { 734 case B_MINI_ICON: 735 bounds.Set(0, 0, 15, 15); 736 break; 737 case B_LARGE_ICON: 738 bounds.Set(0, 0, 31, 31); 739 break; 740 default: 741 // error = B_BAD_VALUE; 742 // NOTE: added to be less strict and support scaled icons 743 bounds = icon->Bounds(); 744 break; 745 } 746 747 // check parameters and initialization 748 if (error == B_OK 749 && (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) { 750 error = B_BAD_VALUE; 751 } 752 if (error == B_OK && InitCheck() != B_OK) 753 error = B_NO_INIT; 754 755 bool success = false; 756 757 // get node MIME type, and, if that fails, the generic icon 758 char mimeString[B_MIME_TYPE_LENGTH]; 759 if (error == B_OK) { 760 if (GetType(mimeString) != B_OK) { 761 struct stat stat; 762 error = fNode->GetStat(&stat); 763 if (error == B_OK) { 764 // no type available -- get the icon for the appropriate type (file/dir/etc.) 765 BMimeType type; 766 if (S_ISREG(stat.st_mode)) { 767 // is it an application (executable) or just a regular file? 768 if ((stat.st_mode & S_IXUSR) != 0) 769 type.SetTo(B_APP_MIME_TYPE); 770 else 771 type.SetTo(B_FILE_MIME_TYPE); 772 } else if (S_ISDIR(stat.st_mode)) { 773 // it's either a volume or just a standard directory 774 fs_info info; 775 if (fs_stat_dev(stat.st_dev, &info) == 0 && stat.st_ino == info.root) 776 type.SetTo(B_VOLUME_MIME_TYPE); 777 else 778 type.SetTo(B_DIRECTORY_MIME_TYPE); 779 } else if (S_ISLNK(stat.st_mode)) 780 type.SetTo(B_SYMLINK_MIME_TYPE); 781 782 success = (type.GetIcon(icon, iconSize) == B_OK); 783 // NOTE: if there is an icon but getting it failes for some reason, 784 // the error is not reported, and the fall back retrieval methods 785 // are still tried. (IAW, we can't differentiate the reason for error.) 786 } 787 } 788 } 789 790 // Ask GetIcon(). 791 if (error == B_OK && !success) 792 success = (GetIcon(icon, iconSize) == B_OK); 793 794 // Get the preferred application and ask the MIME database, if that 795 // application has a special icon for the node's file type. 796 if (error == B_OK && !success) { 797 char signature[B_MIME_TYPE_LENGTH]; 798 if (GetPreferredApp(signature) == B_OK) { 799 BMimeType type(signature); 800 success = (type.GetIconForType(mimeString, icon, iconSize) == B_OK); 801 } 802 } 803 804 // Ask the MIME database whether there is an icon for the node's file type. 805 BMimeType nodeType; 806 if (error == B_OK && !success) { 807 nodeType.SetTo(mimeString); 808 success = (nodeType.GetIcon(icon, iconSize) == B_OK); 809 } 810 811 // Ask the MIME database for the preferred application for the node's 812 // file type and whether this application has a special icon for the type. 813 if (error == B_OK && !success) { 814 char signature[B_MIME_TYPE_LENGTH]; 815 if (nodeType.GetPreferredApp(signature) == B_OK) { 816 BMimeType type(signature); 817 success = (type.GetIconForType(mimeString, icon, iconSize) == B_OK); 818 } 819 } 820 821 // Return the icon for "application/octet-stream" from the MIME database. 822 if (error == B_OK && !success) { 823 // get the "application/octet-stream" icon 824 BMimeType type(B_FILE_MIME_TYPE); 825 error = type.GetIcon(icon, iconSize); 826 success = (error == B_OK); 827 } 828 return error; 829 } 830 831 // GetTrackerIcon 832 /*! \brief Gets the icon which tracker displays for the node referred to by 833 the supplied entry_ref. 834 835 This methods works similar to the non-static version. The first argument 836 \a ref identifies the node in question. 837 838 \param ref An entry_ref referring to the node for which the icon shall be 839 retrieved. 840 \param icon A pointer to a pre-allocated BBitmap of the correct dimension 841 to store the requested icon (16x16 for the mini and 32x32 for the 842 large icon). 843 \param iconSize Specifies the size of the icon to be retrieved: \c B_MINI_ICON 844 for the mini and \c B_LARGE_ICON for the large icon. 845 \return 846 - \c B_OK: Everything went fine. 847 - \c B_NO_INIT: The object is not properly initialized. 848 - \c B_BAD_VALUE: \c NULL ref or \a icon, unsupported icon size \a iconSize or 849 bitmap dimensions (\a icon) and icon size (\a iconSize) do not match. 850 - other error codes 851 */ 852 status_t 853 BNodeInfo::GetTrackerIcon(const entry_ref *ref, BBitmap *icon, icon_size iconSize) 854 { 855 // check ref param 856 status_t error = (ref ? B_OK : B_BAD_VALUE); 857 858 // init a BNode 859 BNode node; 860 if (error == B_OK) 861 error = node.SetTo(ref); 862 863 // init a BNodeInfo 864 BNodeInfo nodeInfo; 865 if (error == B_OK) 866 error = nodeInfo.SetTo(&node); 867 868 // let the non-static GetTrackerIcon() do the dirty work 869 if (error == B_OK) 870 error = nodeInfo.GetTrackerIcon(icon, iconSize); 871 return error; 872 } 873 874 // TODO: just here for providing binary compatibility 875 // (for example "Guido" needs this) 876 extern "C" 877 status_t 878 GetTrackerIcon__9BNodeInfoP9entry_refP7BBitmap9icon_size( 879 BNodeInfo *nodeInfo, entry_ref* ref, 880 BBitmap* bitmap, icon_size iconSize) 881 { 882 // NOTE: nodeInfo is ignored - maybe that's wrong! 883 return BNodeInfo::GetTrackerIcon(ref, bitmap, iconSize); 884 } 885 886 void 887 BNodeInfo::_ReservedNodeInfo1() 888 { 889 } 890 891 void 892 BNodeInfo::_ReservedNodeInfo2() 893 { 894 } 895 896 void 897 BNodeInfo::_ReservedNodeInfo3() 898 { 899 } 900 901 // = 902 /*! \brief Privatized assignment operator to prevent usage. 903 */ 904 BNodeInfo & 905 BNodeInfo::operator=(const BNodeInfo &nodeInfo) 906 { 907 return *this; 908 } 909 910 // copy constructor 911 /*! \brief Privatized copy constructor to prevent usage. 912 */ 913 BNodeInfo::BNodeInfo(const BNodeInfo &) 914 { 915 } 916 917 918 // #pragma mark - 919 920 namespace BPrivate { 921 922 /*! 923 Private function used by Tracker. Should be moved into the Tracker sources. 924 */ 925 extern bool 926 CheckNodeIconHintPrivate(const BNode *node, bool checkMiniIconOnly) 927 { 928 attr_info info; 929 if (node->GetAttrInfo(kNIMiniIconAttribute, &info) != B_OK && checkMiniIconOnly) 930 return false; 931 932 if (node->GetAttrInfo(kNILargeIconAttribute, &info) != B_OK) 933 return false; 934 935 return true; 936 } 937 938 } // namespace BPrivate 939