1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 #include "Attributes.h" 36 #include "MimeTypes.h" 37 #include "Model.h" 38 #include "PoseView.h" 39 #include "Utilities.h" 40 #include "ContainerWindow.h" 41 42 #ifdef __HAIKU__ 43 # include <IconUtils.h> 44 #endif 45 46 #include <Bitmap.h> 47 #include <Debug.h> 48 #include <Directory.h> 49 #include <fs_attr.h> 50 #include <fs_info.h> 51 #include <MenuItem.h> 52 #include <OS.h> 53 #include <PopUpMenu.h> 54 #include <Region.h> 55 #include <StorageDefs.h> 56 #include <TextView.h> 57 #include <Volume.h> 58 #include <VolumeRoster.h> 59 #include <Window.h> 60 61 #include <ctype.h> 62 #include <string.h> 63 #include <stdlib.h> 64 #include <time.h> 65 #include <stdarg.h> 66 67 68 #ifndef _IMPEXP_BE 69 # define _IMPEXP_BE 70 #endif 71 extern _IMPEXP_BE const uint32 LARGE_ICON_TYPE; 72 extern _IMPEXP_BE const uint32 MINI_ICON_TYPE; 73 74 75 FILE *logFile = NULL; 76 77 static const float kMinSeparatorStubX = 10; 78 static const float kStubToStringSlotX = 5; 79 80 81 namespace BPrivate { 82 83 const rgb_color kBlack = {0, 0, 0, 255}; 84 const rgb_color kWhite = {255, 255, 255, 255}; 85 86 87 uint32 88 HashString(const char *string, uint32 seed) 89 { 90 char ch; 91 uint32 result = seed; 92 93 while((ch = *string++) != 0) { 94 result = (result << 7) ^ (result >> 24); 95 result ^= ch; 96 } 97 98 result ^= result << 12; 99 return result; 100 } 101 102 103 uint32 104 AttrHashString(const char *string, uint32 type) 105 { 106 char c; 107 uint32 hash = 0; 108 109 while((c = *string++) != 0) { 110 hash = (hash << 7) ^ (hash >> 24); 111 hash ^= c; 112 } 113 114 hash ^= hash << 12; 115 116 hash &= ~0xff; 117 hash |= type; 118 119 return hash; 120 } 121 122 123 bool 124 ValidateStream(BMallocIO *stream, uint32 key, int32 version) 125 { 126 uint32 testKey; 127 int32 testVersion; 128 129 if (stream->Read(&testKey, sizeof(uint32)) <= 0 130 || stream->Read(&testVersion, sizeof(int32)) <=0) 131 return false; 132 133 return testKey == key && testVersion == version; 134 } 135 136 137 void 138 DisallowFilenameKeys(BTextView *textView) 139 { 140 textView->DisallowChar(':'); 141 textView->DisallowChar('/'); 142 } 143 144 145 void 146 DisallowMetaKeys(BTextView *textView) 147 { 148 textView->DisallowChar(B_TAB); 149 textView->DisallowChar(B_ESCAPE); 150 textView->DisallowChar(B_INSERT); 151 textView->DisallowChar(B_DELETE); 152 textView->DisallowChar(B_HOME); 153 textView->DisallowChar(B_END); 154 textView->DisallowChar(B_PAGE_UP); 155 textView->DisallowChar(B_PAGE_DOWN); 156 textView->DisallowChar(B_FUNCTION_KEY); 157 } 158 159 160 PeriodicUpdatePoses::PeriodicUpdatePoses() 161 : fPoseList(20, true) 162 { 163 fLock = new Benaphore("PeriodicUpdatePoses"); 164 } 165 166 167 PeriodicUpdatePoses::~PeriodicUpdatePoses() 168 { 169 fLock->Lock(); 170 fPoseList.MakeEmpty(); 171 delete fLock; 172 } 173 174 175 void 176 PeriodicUpdatePoses::AddPose(BPose *pose, BPoseView *poseView, 177 PeriodicUpdateCallback callback, void *cookie) 178 { 179 periodic_pose *periodic = new periodic_pose; 180 periodic->pose = pose; 181 periodic->pose_view = poseView; 182 periodic->callback = callback; 183 periodic->cookie = cookie; 184 fPoseList.AddItem(periodic); 185 } 186 187 188 bool 189 PeriodicUpdatePoses::RemovePose(BPose *pose, void **cookie) 190 { 191 int32 count = fPoseList.CountItems(); 192 for (int32 index = 0; index < count; index++) { 193 if (fPoseList.ItemAt(index)->pose == pose) { 194 if (!fLock->Lock()) 195 return false; 196 197 periodic_pose *periodic = fPoseList.RemoveItemAt(index); 198 if (cookie) 199 *cookie = periodic->cookie; 200 delete periodic; 201 fLock->Unlock(); 202 return true; 203 } 204 } 205 206 return false; 207 } 208 209 210 void 211 PeriodicUpdatePoses::DoPeriodicUpdate(bool forceRedraw) 212 { 213 if (!fLock->Lock()) 214 return; 215 216 int32 count = fPoseList.CountItems(); 217 for (int32 index = 0; index < count; index++) { 218 periodic_pose *periodic = fPoseList.ItemAt(index); 219 if (periodic->callback(periodic->pose, periodic->cookie) 220 || forceRedraw) { 221 periodic->pose_view->LockLooper(); 222 periodic->pose_view->UpdateIcon(periodic->pose); 223 periodic->pose_view->UnlockLooper(); 224 } 225 } 226 227 fLock->Unlock(); 228 } 229 230 231 PeriodicUpdatePoses gPeriodicUpdatePoses; 232 233 } // namespace BPrivate 234 235 236 void 237 PoseInfo::EndianSwap(void *castToThis) 238 { 239 PoseInfo *self = (PoseInfo *)castToThis; 240 241 PRINT(("swapping PoseInfo\n")); 242 243 STATIC_ASSERT(sizeof(ino_t) == sizeof(int64)); 244 self->fInitedDirectory = SwapInt64(self->fInitedDirectory); 245 swap_data(B_POINT_TYPE, &self->fLocation, sizeof(BPoint), B_SWAP_ALWAYS); 246 247 // do a sanity check on the icon position 248 if (self->fLocation.x < -20000 || self->fLocation.x > 20000 249 || self->fLocation.y < -20000 || self->fLocation.y > 20000) { 250 // position out of range, force autoplcemement 251 PRINT((" rejecting icon position out of range\n")); 252 self->fInitedDirectory = -1LL; 253 self->fLocation = BPoint(0, 0); 254 } 255 } 256 257 258 void 259 PoseInfo::PrintToStream() 260 { 261 PRINT(("%s, inode:%Lx, location %f %f\n", fInvisible ? "hidden" : "visible", 262 fInitedDirectory, fLocation.x, fLocation.y)); 263 } 264 265 266 // #pragma mark - 267 268 269 size_t 270 ExtendedPoseInfo::Size() const 271 { 272 return sizeof(ExtendedPoseInfo) + fNumFrames * sizeof(FrameLocation); 273 } 274 275 276 size_t 277 ExtendedPoseInfo::Size(int32 count) 278 { 279 return sizeof(ExtendedPoseInfo) + count * sizeof(FrameLocation); 280 } 281 282 283 size_t 284 ExtendedPoseInfo::SizeWithHeadroom() const 285 { 286 return sizeof(ExtendedPoseInfo) + (fNumFrames + 1) * sizeof(FrameLocation); 287 } 288 289 290 size_t 291 ExtendedPoseInfo::SizeWithHeadroom(size_t oldSize) 292 { 293 int32 count = (ssize_t)oldSize - (ssize_t)sizeof(ExtendedPoseInfo); 294 if (count > 0) 295 count /= sizeof(FrameLocation); 296 else 297 count = 0; 298 299 return Size(count + 1); 300 } 301 302 303 bool 304 ExtendedPoseInfo::HasLocationForFrame(BRect frame) const 305 { 306 for (int32 index = 0; index < fNumFrames; index++) { 307 if (fLocations[index].fFrame == frame) 308 return true; 309 } 310 311 return false; 312 } 313 314 315 BPoint 316 ExtendedPoseInfo::LocationForFrame(BRect frame) const 317 { 318 for (int32 index = 0; index < fNumFrames; index++) { 319 if (fLocations[index].fFrame == frame) 320 return fLocations[index].fLocation; 321 } 322 323 TRESPASS(); 324 return BPoint(0, 0); 325 } 326 327 328 bool 329 ExtendedPoseInfo::SetLocationForFrame(BPoint newLocation, BRect frame) 330 { 331 for (int32 index = 0; index < fNumFrames; index++) { 332 if (fLocations[index].fFrame == frame) { 333 if (fLocations[index].fLocation == newLocation) 334 return false; 335 336 fLocations[index].fLocation = newLocation; 337 return true; 338 } 339 } 340 341 fLocations[fNumFrames].fFrame = frame; 342 fLocations[fNumFrames].fLocation = newLocation; 343 fLocations[fNumFrames].fWorkspaces = 0xffffffff; 344 fNumFrames++; 345 return true; 346 } 347 348 349 void 350 ExtendedPoseInfo::EndianSwap(void *castToThis) 351 { 352 ExtendedPoseInfo *self = (ExtendedPoseInfo *)castToThis; 353 354 PRINT(("swapping ExtendedPoseInfo\n")); 355 356 self->fWorkspaces = SwapUInt32(self->fWorkspaces); 357 self->fNumFrames = SwapInt32(self->fNumFrames); 358 359 for (int32 index = 0; index < self->fNumFrames; index++) { 360 swap_data(B_POINT_TYPE, &self->fLocations[index].fLocation, 361 sizeof(BPoint), B_SWAP_ALWAYS); 362 363 if (self->fLocations[index].fLocation.x < -20000 364 || self->fLocations[index].fLocation.x > 20000 365 || self->fLocations[index].fLocation.y < -20000 366 || self->fLocations[index].fLocation.y > 20000) { 367 // position out of range, force autoplcemement 368 PRINT((" rejecting icon position out of range\n")); 369 self->fLocations[index].fLocation = BPoint(0, 0); 370 } 371 swap_data(B_RECT_TYPE, &self->fLocations[index].fFrame, 372 sizeof(BRect), B_SWAP_ALWAYS); 373 } 374 } 375 376 377 void 378 ExtendedPoseInfo::PrintToStream() 379 { 380 } 381 382 383 // #pragma mark - 384 385 386 OffscreenBitmap::OffscreenBitmap(BRect frame) 387 : 388 fBitmap(NULL) 389 { 390 NewBitmap(frame); 391 } 392 393 394 OffscreenBitmap::OffscreenBitmap() 395 : 396 fBitmap(NULL) 397 { 398 } 399 400 401 OffscreenBitmap::~OffscreenBitmap() 402 { 403 delete fBitmap; 404 } 405 406 407 void 408 OffscreenBitmap::NewBitmap(BRect bounds) 409 { 410 delete fBitmap; 411 fBitmap = new BBitmap(bounds, B_RGB32, true); 412 if (fBitmap->Lock()) { 413 BView *view = new BView(fBitmap->Bounds(), "", B_FOLLOW_NONE, 0); 414 fBitmap->AddChild(view); 415 416 BRect clipRect = view->Bounds(); 417 BRegion newClip; 418 newClip.Set(clipRect); 419 view->ConstrainClippingRegion(&newClip); 420 421 fBitmap->Unlock(); 422 } else { 423 delete fBitmap; 424 fBitmap = NULL; 425 } 426 } 427 428 429 BView * 430 OffscreenBitmap::BeginUsing(BRect frame) 431 { 432 if (!fBitmap || fBitmap->Bounds() != frame) 433 NewBitmap(frame); 434 435 fBitmap->Lock(); 436 return View(); 437 } 438 439 440 void 441 OffscreenBitmap::DoneUsing() 442 { 443 fBitmap->Unlock(); 444 } 445 446 447 BBitmap * 448 OffscreenBitmap::Bitmap() const 449 { 450 ASSERT(fBitmap); 451 ASSERT(fBitmap->IsLocked()); 452 return fBitmap; 453 } 454 455 456 BView * 457 OffscreenBitmap::View() const 458 { 459 ASSERT(fBitmap); 460 return fBitmap->ChildAt(0); 461 } 462 463 464 // #pragma mark - 465 466 467 namespace BPrivate { 468 469 /** Changes the alpha value of the given bitmap to create a nice 470 * horizontal fade out in the specified region. 471 * "from" is always transparent, "to" opaque. 472 */ 473 474 void 475 FadeRGBA32Horizontal(uint32 *bits, int32 width, int32 height, int32 from, int32 to) 476 { 477 // check parameters 478 if (width < 0 || height < 0 || from < 0 || to < 0) 479 return; 480 481 float change = 1.f / (to - from); 482 if (from > to) { 483 int32 temp = from; 484 from = to; 485 to = temp; 486 } 487 488 for (int32 y = 0; y < height; y++) { 489 float alpha = change > 0 ? 0.0f : 1.0f; 490 491 for (int32 x = from; x <= to; x++) { 492 if (bits[x] & 0xff000000) { 493 uint32 a = uint32((bits[x] >> 24) * alpha); 494 bits[x] = (bits[x] & 0x00ffffff) | (a << 24); 495 } 496 alpha += change; 497 } 498 bits += width; 499 } 500 } 501 502 503 /** Changes the alpha value of the given bitmap to create a nice 504 * vertical fade out in the specified region. 505 * "from" is always transparent, "to" opaque. 506 */ 507 508 void 509 FadeRGBA32Vertical(uint32 *bits, int32 width, int32 height, int32 from, int32 to) 510 { 511 // check parameters 512 if (width < 0 || height < 0 || from < 0 || to < 0) 513 return; 514 515 if (from > to) 516 bits += width * (height - (from - to)); 517 518 float change = 1.f / (to - from); 519 if (from > to) { 520 int32 temp = from; 521 from = to; 522 to = temp; 523 } 524 525 float alpha = change > 0 ? 0.0f : 1.0f; 526 527 for (int32 y = from; y <= to; y++) { 528 for (int32 x = 0; x < width; x++) { 529 if (bits[x] & 0xff000000) { 530 uint32 a = uint32((bits[x] >> 24) * alpha); 531 bits[x] = (bits[x] & 0x00ffffff) | (a << 24); 532 } 533 } 534 alpha += change; 535 bits += width; 536 } 537 } 538 539 } // namespace BPrivate 540 541 542 // #pragma mark - 543 544 545 DraggableIcon::DraggableIcon(BRect rect, const char *name, const char *mimeType, 546 icon_size size, const BMessage *message, BMessenger target, 547 uint32 resizeMask, uint32 flags) 548 : BView(rect, name, resizeMask, flags), 549 fMessage(*message), 550 fTarget(target) 551 { 552 fBitmap = new BBitmap(Bounds(), kDefaultIconDepth); 553 BMimeType mime(mimeType); 554 status_t error = mime.GetIcon(fBitmap, size); 555 ASSERT(mime.IsValid()); 556 if (error != B_OK) { 557 PRINT(("failed to get icon for %s, %s\n", mimeType, strerror(error))); 558 BMimeType mime(B_FILE_MIMETYPE); 559 ASSERT(mime.IsInstalled()); 560 mime.GetIcon(fBitmap, size); 561 } 562 } 563 564 565 DraggableIcon::~DraggableIcon() 566 { 567 delete fBitmap; 568 } 569 570 571 void 572 DraggableIcon::SetTarget(BMessenger target) 573 { 574 fTarget = target; 575 } 576 577 578 BRect 579 DraggableIcon::PreferredRect(BPoint offset, icon_size size) 580 { 581 BRect result(0, 0, size - 1, size - 1); 582 result.OffsetTo(offset); 583 return result; 584 } 585 586 587 void 588 DraggableIcon::AttachedToWindow() 589 { 590 BView *parent = Parent(); 591 if (parent) { 592 SetViewColor(parent->ViewColor()); 593 SetLowColor(parent->LowColor()); 594 } 595 } 596 597 598 void 599 DraggableIcon::MouseDown(BPoint point) 600 { 601 if (!DragStarted(&fMessage)) 602 return; 603 604 BRect rect(Bounds()); 605 BBitmap *dragBitmap = new BBitmap(rect, B_RGBA32, true); 606 dragBitmap->Lock(); 607 BView *view = new BView(dragBitmap->Bounds(), "", B_FOLLOW_NONE, 0); 608 dragBitmap->AddChild(view); 609 view->SetOrigin(0, 0); 610 BRect clipRect(view->Bounds()); 611 BRegion newClip; 612 newClip.Set(clipRect); 613 view->ConstrainClippingRegion(&newClip); 614 615 // Transparent draw magic 616 view->SetHighColor(0, 0, 0, 0); 617 view->FillRect(view->Bounds()); 618 view->SetDrawingMode(B_OP_ALPHA); 619 view->SetHighColor(0, 0, 0, 128); 620 // set the level of transparency by value 621 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); 622 view->DrawBitmap(fBitmap); 623 view->Sync(); 624 dragBitmap->Unlock(); 625 DragMessage(&fMessage, dragBitmap, B_OP_ALPHA, point, fTarget.Target(0)); 626 } 627 628 629 bool 630 DraggableIcon::DragStarted(BMessage *) 631 { 632 return true; 633 } 634 635 636 void 637 DraggableIcon::Draw(BRect) 638 { 639 #ifdef __HAIKU__ 640 SetDrawingMode(B_OP_ALPHA); 641 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 642 #else 643 SetDrawingMode(B_OP_OVER); 644 #endif 645 DrawBitmap(fBitmap); 646 } 647 648 649 // #pragma mark - 650 651 652 FlickerFreeStringView::FlickerFreeStringView(BRect bounds, const char *name, 653 const char *text, uint32 resizeFlags, uint32 flags) 654 : BStringView(bounds, name, text, resizeFlags, flags), 655 fBitmap(NULL), 656 fOrigBitmap(NULL) 657 { 658 } 659 660 661 FlickerFreeStringView::FlickerFreeStringView(BRect bounds, const char *name, 662 const char *text, BBitmap *inBitmap, uint32 resizeFlags, uint32 flags) 663 : BStringView(bounds, name, text, resizeFlags, flags), 664 fBitmap(NULL), 665 fOrigBitmap(inBitmap) 666 { 667 } 668 669 670 FlickerFreeStringView::~FlickerFreeStringView() 671 { 672 delete fBitmap; 673 } 674 675 676 void 677 FlickerFreeStringView::Draw(BRect) 678 { 679 BRect bounds(Bounds()); 680 if (!fBitmap) 681 fBitmap = new OffscreenBitmap(Bounds()); 682 683 BView *offscreen = fBitmap->BeginUsing(bounds); 684 685 if (Parent()) { 686 fViewColor = Parent()->ViewColor(); 687 fLowColor = Parent()->ViewColor(); 688 } 689 690 offscreen->SetViewColor(fViewColor); 691 offscreen->SetHighColor(HighColor()); 692 offscreen->SetLowColor(fLowColor); 693 694 BFont font; 695 GetFont(&font); 696 offscreen->SetFont(&font); 697 698 offscreen->Sync(); 699 if (fOrigBitmap) 700 offscreen->DrawBitmap(fOrigBitmap, Frame(), bounds); 701 else 702 offscreen->FillRect(bounds, B_SOLID_LOW); 703 704 if (Text()) { 705 BPoint loc; 706 707 font_height height; 708 GetFontHeight(&height); 709 710 edge_info eInfo; 711 switch (Alignment()) { 712 case B_ALIGN_LEFT: 713 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 714 case B_ALIGN_HORIZONTAL_UNSET: 715 case B_ALIGN_USE_FULL_WIDTH: 716 #endif 717 { 718 // If the first char has a negative left edge give it 719 // some more room by shifting that much more to the right. 720 font.GetEdges(Text(), 1, &eInfo); 721 loc.x = bounds.left + (2 - eInfo.left); 722 break; 723 } 724 725 case B_ALIGN_CENTER: 726 { 727 float width = StringWidth(Text()); 728 float center = (bounds.right - bounds.left) / 2; 729 loc.x = center - (width/2); 730 break; 731 } 732 733 case B_ALIGN_RIGHT: 734 { 735 float width = StringWidth(Text()); 736 loc.x = bounds.right - width - 2; 737 break; 738 } 739 } 740 loc.y = bounds.bottom - (1 + height.descent); 741 offscreen->DrawString(Text(), loc); 742 } 743 offscreen->Sync(); 744 SetDrawingMode(B_OP_COPY); 745 DrawBitmap(fBitmap->Bitmap()); 746 fBitmap->DoneUsing(); 747 } 748 749 750 void 751 FlickerFreeStringView::AttachedToWindow() 752 { 753 _inherited::AttachedToWindow(); 754 if (Parent()) { 755 fViewColor = Parent()->ViewColor(); 756 fLowColor = Parent()->ViewColor(); 757 } 758 SetViewColor(B_TRANSPARENT_32_BIT); 759 SetLowColor(B_TRANSPARENT_32_BIT); 760 } 761 762 763 void 764 FlickerFreeStringView::SetViewColor(rgb_color color) 765 { 766 if (fViewColor != color) { 767 fViewColor = color; 768 Invalidate(); 769 } 770 _inherited::SetViewColor(B_TRANSPARENT_32_BIT); 771 } 772 773 774 void 775 FlickerFreeStringView::SetLowColor(rgb_color color) 776 { 777 if (fLowColor != color) { 778 fLowColor = color; 779 Invalidate(); 780 } 781 _inherited::SetLowColor(B_TRANSPARENT_32_BIT); 782 } 783 784 785 // #pragma mark - 786 787 788 TitledSeparatorItem::TitledSeparatorItem(const char *label) 789 : BMenuItem(label, 0) 790 { 791 _inherited::SetEnabled(false); 792 } 793 794 795 TitledSeparatorItem::~TitledSeparatorItem() 796 { 797 } 798 799 800 void 801 TitledSeparatorItem::SetEnabled(bool) 802 { 803 // leave disabled 804 } 805 806 807 void 808 TitledSeparatorItem::GetContentSize(float *width, float *height) 809 { 810 _inherited::GetContentSize(width, height); 811 } 812 813 814 inline rgb_color 815 ShiftMenuBackgroundColor(float by) 816 { 817 return tint_color(ui_color(B_MENU_BACKGROUND_COLOR), by); 818 } 819 820 821 void 822 TitledSeparatorItem::Draw() 823 { 824 BRect frame(Frame()); 825 826 BMenu *parent = Menu(); 827 ASSERT(parent); 828 829 menu_info minfo; 830 get_menu_info(&minfo); 831 832 if (minfo.separator > 0) { 833 frame.left += 10; 834 frame.right -= 10; 835 } else { 836 frame.left += 1; 837 frame.right -= 1; 838 } 839 840 float startX = frame.left; 841 float endX = frame.right; 842 843 float maxStringWidth = endX - startX - (2 * kMinSeparatorStubX 844 + 2 * kStubToStringSlotX); 845 846 // ToDo: 847 // handle case where maxStringWidth turns out negative here 848 849 BString truncatedLabel(Label()); 850 parent->TruncateString(&truncatedLabel, B_TRUNCATE_END, maxStringWidth); 851 852 maxStringWidth = parent->StringWidth(truncatedLabel.String()); 853 854 // first calculate the length of the stub part of the 855 // divider line, so we can use it for secondStartX 856 float firstEndX = ((endX - startX) - maxStringWidth) / 2 - kStubToStringSlotX; 857 if (firstEndX < 0) 858 firstEndX = 0; 859 860 float secondStartX = endX - firstEndX; 861 862 // now finish calculating firstEndX 863 firstEndX += startX; 864 865 parent->PushState(); 866 867 int32 y = (int32) (frame.top + (frame.bottom - frame.top) / 2); 868 869 parent->BeginLineArray(minfo.separator == 2 ? 6 : 4); 870 parent->AddLine(BPoint(frame.left, y), BPoint(firstEndX, y), 871 ShiftMenuBackgroundColor(B_DARKEN_1_TINT)); 872 parent->AddLine(BPoint(secondStartX, y), BPoint(frame.right, y), 873 ShiftMenuBackgroundColor(B_DARKEN_1_TINT)); 874 875 if (minfo.separator == 2) { 876 y++; 877 frame.left++; 878 frame.right--; 879 parent->AddLine(BPoint(frame.left,y), BPoint(firstEndX, y), 880 ShiftMenuBackgroundColor(B_DARKEN_1_TINT)); 881 parent->AddLine(BPoint(secondStartX,y), BPoint(frame.right, y), 882 ShiftMenuBackgroundColor(B_DARKEN_1_TINT)); 883 } 884 y++; 885 if (minfo.separator == 2) { 886 frame.left++; 887 frame.right--; 888 } 889 parent->AddLine(BPoint(frame.left, y), BPoint(firstEndX, y), 890 ShiftMenuBackgroundColor(B_DARKEN_1_TINT)); 891 parent->AddLine(BPoint(secondStartX, y), BPoint(frame.right, y), 892 ShiftMenuBackgroundColor(B_DARKEN_1_TINT)); 893 894 parent->EndLineArray(); 895 896 font_height finfo; 897 parent->GetFontHeight(&finfo); 898 899 parent->SetLowColor(parent->ViewColor()); 900 BPoint loc(firstEndX + kStubToStringSlotX, ContentLocation().y + finfo.ascent); 901 902 parent->MovePenTo(loc + BPoint(1, 1)); 903 parent->SetHighColor(ShiftMenuBackgroundColor(B_DARKEN_1_TINT)); 904 parent->DrawString(truncatedLabel.String()); 905 906 parent->MovePenTo(loc); 907 parent->SetHighColor(ShiftMenuBackgroundColor(B_DISABLED_LABEL_TINT)); 908 parent->DrawString(truncatedLabel.String()); 909 910 parent->PopState(); 911 } 912 913 914 // #pragma mark - 915 916 917 ShortcutFilter::ShortcutFilter(uint32 shortcutKey, uint32 shortcutModifier, 918 uint32 shortcutWhat, BHandler *target) 919 : BMessageFilter(B_KEY_DOWN), 920 fShortcutKey(shortcutKey), 921 fShortcutModifier(shortcutModifier), 922 fShortcutWhat(shortcutWhat), 923 fTarget(target) 924 { 925 } 926 927 928 filter_result 929 ShortcutFilter::Filter(BMessage *message, BHandler **) 930 { 931 if (message->what == B_KEY_DOWN) { 932 uint32 modifiers; 933 uint32 rawKeyChar = 0; 934 uint8 byte = 0; 935 int32 key = 0; 936 937 if (message->FindInt32("modifiers", (int32 *)&modifiers) != B_OK 938 || message->FindInt32("raw_char", (int32 *)&rawKeyChar) != B_OK 939 || message->FindInt8("byte", (int8 *)&byte) != B_OK 940 || message->FindInt32("key", &key) != B_OK) 941 return B_DISPATCH_MESSAGE; 942 943 modifiers &= B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY 944 | B_OPTION_KEY | B_MENU_KEY; 945 // strip caps lock, etc. 946 947 if (modifiers == fShortcutModifier && rawKeyChar == fShortcutKey) { 948 fTarget->Looper()->PostMessage(fShortcutWhat, fTarget); 949 return B_SKIP_MESSAGE; 950 } 951 } 952 953 // let others deal with this 954 return B_DISPATCH_MESSAGE; 955 } 956 957 958 // #pragma mark - 959 960 961 namespace BPrivate { 962 963 void 964 EmbedUniqueVolumeInfo(BMessage *message, const BVolume *volume) 965 { 966 BDirectory rootDirectory; 967 time_t created; 968 fs_info info; 969 970 if (volume->GetRootDirectory(&rootDirectory) == B_OK 971 && rootDirectory.GetCreationTime(&created) == B_OK 972 && fs_stat_dev(volume->Device(), &info) == 0) { 973 message->AddInt32("creationDate", created); 974 message->AddInt64("capacity", volume->Capacity()); 975 message->AddString("deviceName", info.device_name); 976 message->AddString("volumeName", info.volume_name); 977 message->AddString("fshName", info.fsh_name); 978 } 979 } 980 981 982 status_t 983 MatchArchivedVolume(BVolume *result, const BMessage *message, int32 index) 984 { 985 time_t created; 986 off_t capacity; 987 988 if (message->FindInt32("creationDate", index, &created) != B_OK 989 || message->FindInt64("capacity", index, &capacity) != B_OK) 990 return B_ERROR; 991 992 BVolumeRoster roster; 993 BVolume volume; 994 BString deviceName, volumeName, fshName; 995 996 if (message->FindString("deviceName", &deviceName) == B_OK 997 && message->FindString("volumeName", &volumeName) == B_OK 998 && message->FindString("fshName", &fshName) == B_OK) { 999 // New style volume identifiers: We have a couple of characteristics, 1000 // and compute a score from them. The volume with the greatest score 1001 // (if over a certain threshold) is the one we're looking for. We 1002 // pick the first volume, in case there is more than one with the 1003 // same score. 1004 dev_t foundDevice = -1; 1005 int foundScore = -1; 1006 roster.Rewind(); 1007 while (roster.GetNextVolume(&volume) == B_OK) { 1008 if (volume.IsPersistent() && volume.KnowsQuery()) { 1009 // get creation time and fs_info 1010 BDirectory root; 1011 volume.GetRootDirectory(&root); 1012 time_t cmpCreated; 1013 fs_info info; 1014 if (root.GetCreationTime(&cmpCreated) == B_OK 1015 && fs_stat_dev(volume.Device(), &info) == 0) { 1016 // compute the score 1017 int score = 0; 1018 1019 // creation time 1020 if (created == cmpCreated) 1021 score += 5; 1022 // capacity 1023 if (capacity == volume.Capacity()) 1024 score += 4; 1025 // device name 1026 if (deviceName == info.device_name) 1027 score += 3; 1028 // volume name 1029 if (volumeName == info.volume_name) 1030 score += 2; 1031 // fsh name 1032 if (fshName == info.fsh_name) 1033 score += 1; 1034 1035 // check score 1036 if (score >= 9 && score > foundScore) { 1037 foundDevice = volume.Device(); 1038 foundScore = score; 1039 } 1040 } 1041 } 1042 } 1043 if (foundDevice >= 0) 1044 return result->SetTo(foundDevice); 1045 } else { 1046 // Old style volume identifiers: We have only creation time and 1047 // capacity. Both must match. 1048 roster.Rewind(); 1049 while (roster.GetNextVolume(&volume) == B_OK) 1050 if (volume.IsPersistent() && volume.KnowsQuery()) { 1051 BDirectory root; 1052 volume.GetRootDirectory(&root); 1053 time_t cmpCreated; 1054 root.GetCreationTime(&cmpCreated); 1055 if (created == cmpCreated && capacity == volume.Capacity()) { 1056 *result = volume; 1057 return B_OK; 1058 } 1059 } 1060 } 1061 1062 return B_DEV_BAD_DRIVE_NUM; 1063 } 1064 1065 1066 void 1067 StringFromStream(BString *string, BMallocIO *stream, bool endianSwap) 1068 { 1069 int32 length; 1070 stream->Read(&length, sizeof(length)); 1071 if (endianSwap) 1072 length = SwapInt32(length); 1073 1074 if (length < 0 || length > 10000) { 1075 // TODO: should fail here 1076 PRINT(("problems instatiating a string, length probably wrong %d\n", length)); 1077 return; 1078 } 1079 1080 char *buffer = string->LockBuffer(length + 1); 1081 stream->Read(buffer, (size_t)length + 1); 1082 string->UnlockBuffer(length); 1083 } 1084 1085 1086 void 1087 StringToStream(const BString *string, BMallocIO *stream) 1088 { 1089 int32 length = string->Length(); 1090 stream->Write(&length, sizeof(int32)); 1091 stream->Write(string->String(), (size_t)string->Length() + 1); 1092 } 1093 1094 1095 int32 1096 ArchiveSize(const BString *string) 1097 { 1098 return string->Length() + 1 + (ssize_t)sizeof(int32); 1099 } 1100 1101 1102 int32 1103 CountRefs(const BMessage *message) 1104 { 1105 uint32 type; 1106 int32 count; 1107 message->GetInfo("refs", &type, &count); 1108 1109 return count; 1110 } 1111 1112 1113 static entry_ref * 1114 EachEntryRefCommon(BMessage *message, entry_ref *(*func)(entry_ref *, void *), 1115 void *passThru, int32 maxCount) 1116 { 1117 uint32 type; 1118 int32 count; 1119 message->GetInfo("refs", &type, &count); 1120 1121 if (maxCount >= 0 && count > maxCount) 1122 count = maxCount; 1123 1124 for (int32 index = 0; index < count; index++) { 1125 entry_ref ref; 1126 message->FindRef("refs", index, &ref); 1127 entry_ref *result = (func)(&ref, passThru); 1128 if (result) 1129 return result; 1130 } 1131 1132 return NULL; 1133 } 1134 1135 1136 bool 1137 ContainsEntryRef(const BMessage *message, const entry_ref *ref) 1138 { 1139 entry_ref match; 1140 for (int32 index = 0; (message->FindRef("refs", index, &match) == B_OK); index++) { 1141 if (*ref == match) 1142 return true; 1143 } 1144 1145 return false; 1146 } 1147 1148 1149 entry_ref * 1150 EachEntryRef(BMessage *message, entry_ref *(*func)(entry_ref *, void *), 1151 void *passThru) 1152 { 1153 return EachEntryRefCommon(message, func, passThru, -1); 1154 } 1155 1156 typedef entry_ref *(*EachEntryIteratee)(entry_ref *, void *); 1157 1158 const entry_ref * 1159 EachEntryRef(const BMessage *message, const entry_ref *(*func)(const entry_ref *, void *), 1160 void *passThru) 1161 { 1162 return EachEntryRefCommon(const_cast<BMessage *>(message), 1163 (EachEntryIteratee)func, passThru, -1); 1164 } 1165 1166 1167 entry_ref * 1168 EachEntryRef(BMessage *message, entry_ref *(*func)(entry_ref *, void *), 1169 void *passThru, int32 maxCount) 1170 { 1171 return EachEntryRefCommon(message, func, passThru, maxCount); 1172 } 1173 1174 1175 const entry_ref * 1176 EachEntryRef(const BMessage *message, const entry_ref *(*func)(const entry_ref *, void *), 1177 void *passThru, int32 maxCount) 1178 { 1179 return EachEntryRefCommon(const_cast<BMessage *>(message), 1180 (EachEntryIteratee)func, passThru, maxCount); 1181 } 1182 1183 1184 void 1185 TruncateLeaf(BString *string) 1186 { 1187 for (int32 index = string->Length(); index >= 0; index--) { 1188 if ((*string)[index] == '/') { 1189 string->Truncate(index + 1); 1190 return; 1191 } 1192 } 1193 } 1194 1195 1196 int64 1197 StringToScalar(const char *text) 1198 { 1199 char *end; 1200 int64 val; 1201 1202 char *buffer = new char [strlen(text) + 1]; 1203 strcpy(buffer, text); 1204 1205 if (strstr(buffer, "k") || strstr(buffer, "K")) { 1206 val = strtoll(buffer, &end, 10); 1207 val *= kKBSize; 1208 } else if (strstr(buffer, "mb") || strstr(buffer, "MB")) { 1209 val = strtoll(buffer, &end, 10); 1210 val *= kMBSize; 1211 } else if (strstr(buffer, "gb") || strstr(buffer, "GB")) { 1212 val = strtoll(buffer, &end, 10); 1213 val *= kGBSize; 1214 } else if (strstr(buffer, "byte") || strstr(buffer, "BYTE")) { 1215 val = strtoll(buffer, &end, 10); 1216 val *= kGBSize; 1217 } else { 1218 // no suffix, try plain byte conversion 1219 val = strtoll(buffer, &end, 10); 1220 } 1221 1222 delete [] buffer; 1223 return val; 1224 } 1225 1226 #if B_BEOS_VERSION <= B_BEOS_VERSION_MAUI && !defined(__HAIKU__) 1227 1228 bool 1229 operator==(const rgb_color &a, const rgb_color &b) 1230 { 1231 return a.red == b.red 1232 && a.green == b.green 1233 && a.blue == b.blue 1234 && a.alpha == b.alpha; 1235 } 1236 1237 1238 bool 1239 operator!=(const rgb_color &a, const rgb_color &b) 1240 { 1241 return !operator==(a, b); 1242 } 1243 1244 #endif 1245 1246 1247 static BRect 1248 LineBounds(BPoint where, float length, bool vertical) 1249 { 1250 BRect result; 1251 result.SetLeftTop(where); 1252 result.SetRightBottom(where + BPoint(2, 2)); 1253 if (vertical) 1254 result.bottom = result.top + length; 1255 else 1256 result.right = result.left + length; 1257 1258 return result; 1259 } 1260 1261 1262 SeparatorLine::SeparatorLine(BPoint where, float length, bool vertical, const char *name) 1263 : BView(LineBounds(where, length, vertical), name, 1264 B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW) 1265 { 1266 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 1267 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 1268 } 1269 1270 1271 void 1272 SeparatorLine::Draw(BRect) 1273 { 1274 BRect bounds(Bounds()); 1275 rgb_color hiliteColor = tint_color(ViewColor(), 1.5f); 1276 1277 bool vertical = (bounds.left > bounds.right - 3); 1278 BeginLineArray(2); 1279 if (vertical) { 1280 AddLine(bounds.LeftTop(), bounds.LeftBottom(), hiliteColor); 1281 AddLine(bounds.LeftTop() + BPoint(1, 0), bounds.LeftBottom() + BPoint(1, 0), kWhite); 1282 } else { 1283 AddLine(bounds.LeftTop(), bounds.RightTop(), hiliteColor); 1284 AddLine(bounds.LeftTop() + BPoint(0, 1), bounds.RightTop() + BPoint(0, 1), kWhite); 1285 } 1286 EndLineArray(); 1287 } 1288 1289 1290 void 1291 HexDump(const void *buf, int32 length) 1292 { 1293 const int32 kBytesPerLine = 16; 1294 int32 offset; 1295 unsigned char *buffer = (unsigned char *)buf; 1296 1297 for (offset = 0; ; offset += kBytesPerLine, buffer += kBytesPerLine) { 1298 int32 remain = length; 1299 int32 index; 1300 1301 printf( "0x%06x: ", (int)offset); 1302 1303 for (index = 0; index < kBytesPerLine; index++) { 1304 if (remain-- > 0) 1305 printf("%02x%c", buffer[index], remain > 0 ? ',' : ' '); 1306 else 1307 printf(" "); 1308 } 1309 1310 remain = length; 1311 printf(" \'"); 1312 for (index = 0; index < kBytesPerLine; index++) { 1313 if (remain-- > 0) 1314 printf("%c", buffer[index] > ' ' ? buffer[index] : '.'); 1315 else 1316 printf(" "); 1317 } 1318 printf("\'\n"); 1319 1320 length -= kBytesPerLine; 1321 if (length <= 0) 1322 break; 1323 } 1324 fflush(stdout); 1325 } 1326 1327 1328 void 1329 EnableNamedMenuItem(BMenu *menu, const char *itemName, bool on) 1330 { 1331 BMenuItem *item = menu->FindItem(itemName); 1332 if (item) 1333 item->SetEnabled(on); 1334 } 1335 1336 1337 void 1338 MarkNamedMenuItem(BMenu *menu, const char *itemName, bool on) 1339 { 1340 BMenuItem *item = menu->FindItem(itemName); 1341 if (item) 1342 item->SetMarked(on); 1343 } 1344 1345 1346 void 1347 EnableNamedMenuItem(BMenu *menu, uint32 commandName, bool on) 1348 { 1349 BMenuItem *item = menu->FindItem(commandName); 1350 if (item) 1351 item->SetEnabled(on); 1352 } 1353 1354 1355 void 1356 MarkNamedMenuItem(BMenu *menu, uint32 commandName, bool on) 1357 { 1358 BMenuItem *item = menu->FindItem(commandName); 1359 if (item) 1360 item->SetMarked(on); 1361 } 1362 1363 1364 void 1365 DeleteSubmenu(BMenuItem *submenuItem) 1366 { 1367 if (!submenuItem) 1368 return; 1369 1370 BMenu *menu = submenuItem->Submenu(); 1371 if (!menu) 1372 return; 1373 1374 for (;;) { 1375 BMenuItem *item = menu->RemoveItem((int32)0); 1376 if (!item) 1377 return; 1378 1379 delete item; 1380 } 1381 } 1382 1383 1384 status_t 1385 GetAppSignatureFromAttr(BFile *file, char *result) 1386 { 1387 // This call is a performance improvement that 1388 // avoids using the BAppFileInfo API when retrieving the 1389 // app signature -- the call is expensive because by default 1390 // the resource fork is scanned to read the attribute 1391 1392 #ifdef B_APP_FILE_INFO_IS_FAST 1393 BAppFileInfo appFileInfo(file); 1394 return appFileInfo.GetSignature(result); 1395 #else 1396 ssize_t readResult = file->ReadAttr(kAttrAppSignature, B_MIME_STRING_TYPE, 1397 0, result, B_MIME_TYPE_LENGTH); 1398 1399 if (readResult <= 0) 1400 return (status_t)readResult; 1401 1402 return B_OK; 1403 #endif // B_APP_FILE_INFO_IS_FAST 1404 } 1405 1406 1407 status_t 1408 GetAppIconFromAttr(BFile *file, BBitmap *result, icon_size size) 1409 { 1410 // This call is a performance improvement that 1411 // avoids using the BAppFileInfo API when retrieving the 1412 // app icons -- the call is expensive because by default 1413 // the resource fork is scanned to read the icons 1414 1415 //#ifdef B_APP_FILE_INFO_IS_FAST 1416 BAppFileInfo appFileInfo(file); 1417 return appFileInfo.GetIcon(result, size); 1418 //#else 1419 // 1420 // const char *attrName = kAttrIcon; 1421 // uint32 type = B_VECTOR_ICON_TYPE; 1422 // 1423 // // try vector icon 1424 // attr_info ainfo; 1425 // status_t ret = file->GetAttrInfo(attrName, &ainfo); 1426 // 1427 // if (ret == B_OK) { 1428 // uint8 buffer[ainfo.size]; 1429 // ssize_t readResult = file->ReadAttr(attrName, type, 0, buffer, 1430 // ainfo.size); 1431 // if (readResult == ainfo.size) { 1432 // if (BIconUtils::GetVectorIcon(buffer, ainfo.size, result) == B_OK) 1433 // return B_OK; 1434 // } 1435 // } 1436 // 1437 // // try again with R5 icons 1438 // attrName = size == B_LARGE_ICON ? kAttrLargeIcon : kAttrMiniIcon; 1439 // type = size == B_LARGE_ICON ? LARGE_ICON_TYPE : MINI_ICON_TYPE; 1440 // 1441 // ret = file->GetAttrInfo(attrName, &ainfo); 1442 // if (ret < B_OK) 1443 // return ret; 1444 // 1445 // uint8 buffer[ainfo.size]; 1446 // 1447 // ssize_t readResult = file->ReadAttr(attrName, type, 0, buffer, ainfo.size); 1448 // if (readResult <= 0) 1449 // return (status_t)readResult; 1450 // 1451 // if (result->ColorSpace() != B_CMAP8) { 1452 // ret = BIconUtils::ConvertFromCMAP8(buffer, size, size, size, result); 1453 // } else { 1454 // result->SetBits(buffer, result->BitsLength(), 0, B_CMAP8); 1455 // } 1456 // 1457 // return ret; 1458 //#endif // B_APP_FILE_INFO_IS_FAST 1459 } 1460 1461 1462 status_t 1463 GetFileIconFromAttr(BNode *file, BBitmap *result, icon_size size) 1464 { 1465 BNodeInfo fileInfo(file); 1466 return fileInfo.GetIcon(result, size); 1467 } 1468 1469 1470 void 1471 PrintToStream(rgb_color color) 1472 { 1473 printf("r:%x, g:%x, b:%x, a:%x\n", 1474 color.red, color.green, color.blue, color.alpha); 1475 } 1476 1477 1478 extern BMenuItem * 1479 EachMenuItem(BMenu *menu, bool recursive, BMenuItem *(*func)(BMenuItem *)) 1480 { 1481 int32 count = menu->CountItems(); 1482 for (int32 index = 0; index < count; index++) { 1483 BMenuItem *item = menu->ItemAt(index); 1484 BMenuItem *result = (func)(item); 1485 if (result) 1486 return result; 1487 1488 if (recursive) { 1489 BMenu *submenu = menu->SubmenuAt(index); 1490 if (submenu) 1491 return EachMenuItem(submenu, true, func); 1492 } 1493 } 1494 1495 return NULL; 1496 } 1497 1498 1499 extern const BMenuItem * 1500 EachMenuItem(const BMenu *menu, bool recursive, BMenuItem *(*func)(const BMenuItem *)) 1501 { 1502 int32 count = menu->CountItems(); 1503 for (int32 index = 0; index < count; index++) { 1504 BMenuItem *item = menu->ItemAt(index); 1505 BMenuItem *result = (func)(item); 1506 if (result) 1507 return result; 1508 1509 if (recursive) { 1510 BMenu *submenu = menu->SubmenuAt(index); 1511 if (submenu) 1512 return EachMenuItem(submenu, true, func); 1513 } 1514 } 1515 1516 return NULL; 1517 } 1518 1519 1520 PositionPassingMenuItem::PositionPassingMenuItem(const char *title, 1521 BMessage *message, char shortcut, uint32 modifiers) 1522 : BMenuItem(title, message, shortcut, modifiers) 1523 { 1524 } 1525 1526 1527 PositionPassingMenuItem::PositionPassingMenuItem(BMenu *menu, 1528 BMessage *message) 1529 : BMenuItem(menu, message) 1530 { 1531 } 1532 1533 1534 status_t 1535 PositionPassingMenuItem::Invoke(BMessage *message) 1536 { 1537 if (!Menu()) 1538 return B_ERROR; 1539 1540 if (!IsEnabled()) 1541 return B_ERROR; 1542 1543 if (!message) 1544 message = Message(); 1545 1546 if (!message) 1547 return B_BAD_VALUE; 1548 1549 BMessage clone(*message); 1550 clone.AddInt32("index", Menu()->IndexOf(this)); 1551 clone.AddInt64("when", system_time()); 1552 clone.AddPointer("source", this); 1553 1554 // embed the invoke location of the menu so that we can create 1555 // a new folder, etc. on the spot 1556 BMenu *menu = Menu(); 1557 1558 for (;;) { 1559 if (!menu->Supermenu()) 1560 break; 1561 menu = menu->Supermenu(); 1562 } 1563 1564 // use the window position only, if the item was invoked from the menu 1565 // menu->Window() points to the window the item was invoked from 1566 if (dynamic_cast<BContainerWindow *>(menu->Window()) == NULL) { 1567 LooperAutoLocker lock(menu); 1568 if (lock.IsLocked()) { 1569 BPoint invokeOrigin(menu->Window()->Frame().LeftTop()); 1570 clone.AddPoint("be:invoke_origin", invokeOrigin); 1571 } 1572 } 1573 1574 return BInvoker::Invoke(&clone); 1575 } 1576 1577 1578 bool 1579 BootedInSafeMode() 1580 { 1581 const char *safeMode = getenv("SAFEMODE"); 1582 return (safeMode && strcmp(safeMode, "yes") == 0); 1583 } 1584 1585 1586 void 1587 _ThrowOnError(status_t error, const char *DEBUG_ONLY(file), int32 DEBUG_ONLY(line)) 1588 { 1589 if (error != B_OK) { 1590 PRINT(("failing %s at %s:%d\n", strerror(error), file, line)); 1591 throw error; 1592 } 1593 } 1594 1595 1596 void 1597 _ThrowIfNotSize(ssize_t size, const char *DEBUG_ONLY(file), int32 DEBUG_ONLY(line)) 1598 { 1599 if (size < B_OK) { 1600 PRINT(("failing %s at %s:%d\n", strerror(size), file, line)); 1601 throw (status_t)size; 1602 } 1603 } 1604 1605 1606 void 1607 _ThrowOnError(status_t error, const char *DEBUG_ONLY(debugString), 1608 const char *DEBUG_ONLY(file), int32 DEBUG_ONLY(line)) 1609 { 1610 if (error != B_OK) { 1611 PRINT(("failing %s, %s at %s:%d\n", debugString, strerror(error), file, line)); 1612 throw error; 1613 } 1614 } 1615 1616 } // namespace BPrivate 1617