6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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.
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.
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.
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.
36 #include "Utilities.h"
46 #include <BitmapStream.h>
50 #include <IconUtils.h>
53 #include <PopUpMenu.h>
55 #include <StorageDefs.h>
58 #include <VolumeRoster.h>
61 #include "Attributes.h"
62 #include "ContainerWindow.h"
63 #include "MimeTypes.h"
71 extern _IMPEXP_BE
const uint32 LARGE_ICON_TYPE
;
72 extern _IMPEXP_BE
const uint32 MINI_ICON_TYPE
;
77 static const float kMinSeparatorStubX
= 10;
78 static const float kStubToStringSlotX
= 5;
83 const float kExactMatchScore
= INFINITY
;
86 bool gLocalizedNamePreferred
;
90 SecondaryMouseButtonDown(int32 modifiers
, int32 buttons
)
92 return (buttons
& B_SECONDARY_MOUSE_BUTTON
) != 0
93 || ((buttons
& B_PRIMARY_MOUSE_BUTTON
) != 0
94 && (modifiers
& B_CONTROL_KEY
) != 0);
99 HashString(const char* string
, uint32 seed
)
104 while((ch
= *string
++) != 0) {
105 hash
= (hash
<< 7) ^ (hash
>> 24);
115 AttrHashString(const char* string
, uint32 type
)
120 while((c
= *string
++) != 0) {
121 hash
= (hash
<< 7) ^ (hash
>> 24);
134 ValidateStream(BMallocIO
* stream
, uint32 key
, int32 version
)
139 if (stream
->Read(&testKey
, sizeof(uint32
)) <= 0
140 || stream
->Read(&testVersion
, sizeof(int32
)) <= 0) {
144 return testKey
== key
&& testVersion
== version
;
149 DisallowFilenameKeys(BTextView
* textView
)
151 textView
->DisallowChar('/');
156 DisallowMetaKeys(BTextView
* textView
)
158 textView
->DisallowChar(B_TAB
);
159 textView
->DisallowChar(B_ESCAPE
);
160 textView
->DisallowChar(B_INSERT
);
161 textView
->DisallowChar(B_DELETE
);
162 textView
->DisallowChar(B_HOME
);
163 textView
->DisallowChar(B_END
);
164 textView
->DisallowChar(B_PAGE_UP
);
165 textView
->DisallowChar(B_PAGE_DOWN
);
166 textView
->DisallowChar(B_FUNCTION_KEY
);
170 PeriodicUpdatePoses::PeriodicUpdatePoses()
174 fLock
= new Benaphore("PeriodicUpdatePoses");
178 PeriodicUpdatePoses::~PeriodicUpdatePoses()
181 fPoseList
.MakeEmpty();
187 PeriodicUpdatePoses::AddPose(BPose
* pose
, BPoseView
* poseView
,
188 PeriodicUpdateCallback callback
, void* cookie
)
190 periodic_pose
* periodic
= new periodic_pose
;
191 periodic
->pose
= pose
;
192 periodic
->pose_view
= poseView
;
193 periodic
->callback
= callback
;
194 periodic
->cookie
= cookie
;
195 fPoseList
.AddItem(periodic
);
200 PeriodicUpdatePoses::RemovePose(BPose
* pose
, void** cookie
)
202 int32 count
= fPoseList
.CountItems();
203 for (int32 index
= 0; index
< count
; index
++) {
204 if (fPoseList
.ItemAt(index
)->pose
== pose
) {
208 periodic_pose
* periodic
= fPoseList
.RemoveItemAt(index
);
210 *cookie
= periodic
->cookie
;
222 PeriodicUpdatePoses::DoPeriodicUpdate(bool forceRedraw
)
227 int32 count
= fPoseList
.CountItems();
228 for (int32 index
= 0; index
< count
; index
++) {
229 periodic_pose
* periodic
= fPoseList
.ItemAt(index
);
230 if ((periodic
->callback(periodic
->pose
, periodic
->cookie
)
231 || forceRedraw
) && periodic
->pose_view
->LockLooper()) {
232 periodic
->pose_view
->UpdateIcon(periodic
->pose
);
233 periodic
->pose_view
->UnlockLooper();
241 PeriodicUpdatePoses gPeriodicUpdatePoses
;
243 } // namespace BPrivate
247 PoseInfo::EndianSwap(void* castToThis
)
249 PoseInfo
* self
= (PoseInfo
*)castToThis
;
251 PRINT(("swapping PoseInfo\n"));
253 STATIC_ASSERT(sizeof(ino_t
) == sizeof(int64
));
254 self
->fInitedDirectory
= SwapInt64(self
->fInitedDirectory
);
255 swap_data(B_POINT_TYPE
, &self
->fLocation
, sizeof(BPoint
), B_SWAP_ALWAYS
);
257 // do a sanity check on the icon position
258 if (self
->fLocation
.x
< -20000 || self
->fLocation
.x
> 20000
259 || self
->fLocation
.y
< -20000 || self
->fLocation
.y
> 20000) {
260 // position out of range, force autoplcemement
261 PRINT((" rejecting icon position out of range\n"));
262 self
->fInitedDirectory
= -1LL;
263 self
->fLocation
= BPoint(0, 0);
269 PoseInfo::PrintToStream()
271 PRINT(("%s, inode:%" B_PRIx64
", location %f %f\n",
272 fInvisible
? "hidden" : "visible",
273 fInitedDirectory
, fLocation
.x
, fLocation
.y
));
277 // #pragma mark - ExtendedPoseInfo
281 ExtendedPoseInfo::Size() const
283 return sizeof(ExtendedPoseInfo
) + fNumFrames
* sizeof(FrameLocation
);
288 ExtendedPoseInfo::Size(int32 count
)
290 return sizeof(ExtendedPoseInfo
) + count
* sizeof(FrameLocation
);
295 ExtendedPoseInfo::SizeWithHeadroom() const
297 return sizeof(ExtendedPoseInfo
) + (fNumFrames
+ 1) * sizeof(FrameLocation
);
302 ExtendedPoseInfo::SizeWithHeadroom(size_t oldSize
)
304 int32 count
= (ssize_t
)oldSize
- (ssize_t
)sizeof(ExtendedPoseInfo
);
306 count
/= sizeof(FrameLocation
);
310 return Size(count
+ 1);
315 ExtendedPoseInfo::HasLocationForFrame(BRect frame
) const
317 for (int32 index
= 0; index
< fNumFrames
; index
++) {
318 if (fLocations
[index
].fFrame
== frame
)
327 ExtendedPoseInfo::LocationForFrame(BRect frame
) const
329 for (int32 index
= 0; index
< fNumFrames
; index
++) {
330 if (fLocations
[index
].fFrame
== frame
)
331 return fLocations
[index
].fLocation
;
340 ExtendedPoseInfo::SetLocationForFrame(BPoint newLocation
, BRect frame
)
342 for (int32 index
= 0; index
< fNumFrames
; index
++) {
343 if (fLocations
[index
].fFrame
== frame
) {
344 if (fLocations
[index
].fLocation
== newLocation
)
347 fLocations
[index
].fLocation
= newLocation
;
352 fLocations
[fNumFrames
].fFrame
= frame
;
353 fLocations
[fNumFrames
].fLocation
= newLocation
;
354 fLocations
[fNumFrames
].fWorkspaces
= 0xffffffff;
362 ExtendedPoseInfo::EndianSwap(void* castToThis
)
364 ExtendedPoseInfo
* self
= (ExtendedPoseInfo
*)castToThis
;
366 PRINT(("swapping ExtendedPoseInfo\n"));
368 self
->fWorkspaces
= SwapUInt32(self
->fWorkspaces
);
369 self
->fNumFrames
= SwapInt32(self
->fNumFrames
);
371 for (int32 index
= 0; index
< self
->fNumFrames
; index
++) {
372 swap_data(B_POINT_TYPE
, &self
->fLocations
[index
].fLocation
,
373 sizeof(BPoint
), B_SWAP_ALWAYS
);
375 if (self
->fLocations
[index
].fLocation
.x
< -20000
376 || self
->fLocations
[index
].fLocation
.x
> 20000
377 || self
->fLocations
[index
].fLocation
.y
< -20000
378 || self
->fLocations
[index
].fLocation
.y
> 20000) {
379 // position out of range, force autoplcemement
380 PRINT((" rejecting icon position out of range\n"));
381 self
->fLocations
[index
].fLocation
= BPoint(0, 0);
383 swap_data(B_RECT_TYPE
, &self
->fLocations
[index
].fFrame
,
384 sizeof(BRect
), B_SWAP_ALWAYS
);
390 ExtendedPoseInfo::PrintToStream()
395 // #pragma mark - OffscreenBitmap
398 OffscreenBitmap::OffscreenBitmap(BRect frame
)
406 OffscreenBitmap::OffscreenBitmap()
413 OffscreenBitmap::~OffscreenBitmap()
420 OffscreenBitmap::NewBitmap(BRect bounds
)
423 fBitmap
= new(std::nothrow
) BBitmap(bounds
, B_RGB32
, true);
424 if (fBitmap
&& fBitmap
->Lock()) {
425 BView
* view
= new BView(fBitmap
->Bounds(), "", B_FOLLOW_NONE
, 0);
426 fBitmap
->AddChild(view
);
428 BRect clipRect
= view
->Bounds();
430 newClip
.Set(clipRect
);
431 view
->ConstrainClippingRegion(&newClip
);
442 OffscreenBitmap::BeginUsing(BRect frame
)
444 if (!fBitmap
|| fBitmap
->Bounds() != frame
)
453 OffscreenBitmap::DoneUsing()
460 OffscreenBitmap::Bitmap() const
463 ASSERT(fBitmap
->IsLocked());
469 OffscreenBitmap::View() const
472 return fBitmap
->ChildAt(0);
476 // #pragma mark - BPrivate functions
481 // Changes the alpha value of the given bitmap to create a nice
482 // horizontal fade out in the specified region.
483 // "from" is always transparent, "to" opaque.
485 FadeRGBA32Horizontal(uint32
* bits
, int32 width
, int32 height
, int32 from
,
489 if (width
< 0 || height
< 0 || from
< 0 || to
< 0)
492 float change
= 1.f
/ (to
- from
);
499 for (int32 y
= 0; y
< height
; y
++) {
500 float alpha
= change
> 0 ? 0.0f
: 1.0f
;
502 for (int32 x
= from
; x
<= to
; x
++) {
503 if (bits
[x
] & 0xff000000) {
504 uint32 a
= uint32((bits
[x
] >> 24) * alpha
);
505 bits
[x
] = (bits
[x
] & 0x00ffffff) | (a
<< 24);
514 /*! Changes the alpha value of the given bitmap to create a nice
515 vertical fade out in the specified region.
516 "from" is always transparent, "to" opaque.
519 FadeRGBA32Vertical(uint32
* bits
, int32 width
, int32 height
, int32 from
,
523 if (width
< 0 || height
< 0 || from
< 0 || to
< 0)
527 bits
+= width
* (height
- (from
- to
));
529 float change
= 1.f
/ (to
- from
);
536 float alpha
= change
> 0 ? 0.0f
: 1.0f
;
538 for (int32 y
= from
; y
<= to
; y
++) {
539 for (int32 x
= 0; x
< width
; x
++) {
540 if (bits
[x
] & 0xff000000) {
541 uint32 a
= uint32((bits
[x
] >> 24) * alpha
);
542 bits
[x
] = (bits
[x
] & 0x00ffffff) | (a
<< 24);
551 } // namespace BPrivate
554 // #pragma mark - DraggableIcon
557 DraggableIcon::DraggableIcon(BRect rect
, const char* name
,
558 const char* mimeType
, icon_size which
, const BMessage
* message
,
559 BMessenger target
, uint32 resizingMode
, uint32 flags
)
561 BView(rect
, name
, resizingMode
, flags
),
565 fBitmap
= new BBitmap(Bounds(), kDefaultIconDepth
);
566 BMimeType
mime(mimeType
);
567 status_t result
= mime
.GetIcon(fBitmap
, which
);
568 ASSERT(mime
.IsValid());
569 if (result
!= B_OK
) {
570 PRINT(("failed to get icon for %s, %s\n", mimeType
, strerror(result
)));
571 BMimeType
mime(B_FILE_MIMETYPE
);
572 ASSERT(mime
.IsInstalled());
573 mime
.GetIcon(fBitmap
, which
);
578 DraggableIcon::~DraggableIcon()
585 DraggableIcon::SetTarget(BMessenger target
)
592 DraggableIcon::PreferredRect(BPoint offset
, icon_size which
)
594 BRect
rect(0, 0, which
- 1, which
- 1);
595 rect
.OffsetTo(offset
);
601 DraggableIcon::AttachedToWindow()
608 DraggableIcon::MouseDown(BPoint point
)
610 if (!DragStarted(&fMessage
))
613 BRect
rect(Bounds());
614 BBitmap
* dragBitmap
= new BBitmap(rect
, B_RGBA32
, true);
616 BView
* view
= new BView(dragBitmap
->Bounds(), "", B_FOLLOW_NONE
, 0);
617 dragBitmap
->AddChild(view
);
618 view
->SetOrigin(0, 0);
619 BRect
clipRect(view
->Bounds());
621 newClip
.Set(clipRect
);
622 view
->ConstrainClippingRegion(&newClip
);
624 // Transparent draw magic
625 view
->SetHighColor(0, 0, 0, 0);
626 view
->FillRect(view
->Bounds());
627 view
->SetDrawingMode(B_OP_ALPHA
);
628 view
->SetHighColor(0, 0, 0, 128);
629 // set the level of transparency by value
630 view
->SetBlendingMode(B_CONSTANT_ALPHA
, B_ALPHA_COMPOSITE
);
631 view
->DrawBitmap(fBitmap
);
633 dragBitmap
->Unlock();
634 DragMessage(&fMessage
, dragBitmap
, B_OP_ALPHA
, point
, fTarget
.Target(0));
639 DraggableIcon::DragStarted(BMessage
*)
646 DraggableIcon::Draw(BRect
)
648 SetDrawingMode(B_OP_ALPHA
);
649 SetBlendingMode(B_PIXEL_ALPHA
, B_ALPHA_OVERLAY
);
654 // #pragma mark - FlickerFreeStringView
657 FlickerFreeStringView::FlickerFreeStringView(BRect bounds
, const char* name
,
658 const char* text
, uint32 resizingMode
, uint32 flags
)
660 BStringView(bounds
, name
, text
, resizingMode
, flags
),
662 fViewColor(ViewColor()),
663 fLowColor(LowColor()),
664 fOriginalBitmap(NULL
)
669 FlickerFreeStringView::FlickerFreeStringView(BRect bounds
, const char* name
,
670 const char* text
, BBitmap
* inBitmap
, uint32 resizingMode
, uint32 flags
)
672 BStringView(bounds
, name
, text
, resizingMode
, flags
),
674 fViewColor(ViewColor()),
675 fLowColor(LowColor()),
676 fOriginalBitmap(inBitmap
)
681 FlickerFreeStringView::~FlickerFreeStringView()
688 FlickerFreeStringView::Draw(BRect
)
690 BRect
bounds(Bounds());
692 fBitmap
= new OffscreenBitmap(Bounds());
694 BView
* offscreen
= fBitmap
->BeginUsing(bounds
);
696 if (Parent() != NULL
) {
697 fViewColor
= Parent()->ViewColor();
698 fLowColor
= Parent()->ViewColor();
701 offscreen
->SetViewColor(fViewColor
);
702 offscreen
->SetHighColor(HighColor());
703 offscreen
->SetLowColor(fLowColor
);
707 offscreen
->SetFont(&font
);
710 if (fOriginalBitmap
!= NULL
)
711 offscreen
->DrawBitmap(fOriginalBitmap
, Frame(), bounds
);
713 offscreen
->FillRect(bounds
, B_SOLID_LOW
);
715 if (Text() != NULL
) {
719 GetFontHeight(&height
);
722 switch (Alignment()) {
724 case B_ALIGN_HORIZONTAL_UNSET
:
725 case B_ALIGN_USE_FULL_WIDTH
:
727 // If the first char has a negative left edge give it
728 // some more room by shifting that much more to the right.
729 font
.GetEdges(Text(), 1, &eInfo
);
730 loc
.x
= bounds
.left
+ (2 - eInfo
.left
);
736 float width
= StringWidth(Text());
737 float center
= (bounds
.right
- bounds
.left
) / 2;
738 loc
.x
= center
- (width
/2);
744 float width
= StringWidth(Text());
745 loc
.x
= bounds
.right
- width
- 2;
749 loc
.y
= bounds
.bottom
- (1 + height
.descent
);
750 offscreen
->DrawString(Text(), loc
);
753 SetDrawingMode(B_OP_COPY
);
754 DrawBitmap(fBitmap
->Bitmap());
755 fBitmap
->DoneUsing();
760 FlickerFreeStringView::AttachedToWindow()
762 _inherited::AttachedToWindow();
763 if (Parent() != NULL
) {
764 fViewColor
= Parent()->ViewColor();
765 fLowColor
= Parent()->ViewColor();
767 SetViewColor(B_TRANSPARENT_32_BIT
);
768 SetLowColor(B_TRANSPARENT_32_BIT
);
773 FlickerFreeStringView::SetViewColor(rgb_color color
)
775 if (fViewColor
!= color
) {
779 _inherited::SetViewColor(B_TRANSPARENT_32_BIT
);
784 FlickerFreeStringView::SetLowColor(rgb_color color
)
786 if (fLowColor
!= color
) {
790 _inherited::SetLowColor(B_TRANSPARENT_32_BIT
);
794 // #pragma mark - TitledSeparatorItem
797 TitledSeparatorItem::TitledSeparatorItem(const char* label
)
801 _inherited::SetEnabled(false);
805 TitledSeparatorItem::~TitledSeparatorItem()
811 TitledSeparatorItem::SetEnabled(bool)
818 TitledSeparatorItem::GetContentSize(float* width
, float* height
)
820 _inherited::GetContentSize(width
, height
);
825 ShiftMenuBackgroundColor(float by
)
827 return tint_color(ui_color(B_MENU_BACKGROUND_COLOR
), by
);
832 TitledSeparatorItem::Draw()
834 BRect
frame(Frame());
836 BMenu
* parent
= Menu();
837 ASSERT(parent
!= NULL
);
840 get_menu_info(&minfo
);
842 if (minfo
.separator
> 0) {
850 float startX
= frame
.left
;
851 float endX
= frame
.right
;
853 float maxStringWidth
= endX
- startX
- (2 * kMinSeparatorStubX
854 + 2 * kStubToStringSlotX
);
857 // handle case where maxStringWidth turns out negative here
859 BString
truncatedLabel(Label());
860 parent
->TruncateString(&truncatedLabel
, B_TRUNCATE_END
, maxStringWidth
);
862 maxStringWidth
= parent
->StringWidth(truncatedLabel
.String());
864 // first calculate the length of the stub part of the
865 // divider line, so we can use it for secondStartX
866 float firstEndX
= ((endX
- startX
) - maxStringWidth
) / 2
867 - kStubToStringSlotX
;
871 float secondStartX
= endX
- firstEndX
;
873 // now finish calculating firstEndX
878 int32 y
= (int32
) (frame
.top
+ (frame
.bottom
- frame
.top
) / 2);
880 parent
->BeginLineArray(minfo
.separator
== 2 ? 6 : 4);
881 parent
->AddLine(BPoint(frame
.left
, y
), BPoint(firstEndX
, y
),
882 ShiftMenuBackgroundColor(B_DARKEN_1_TINT
));
883 parent
->AddLine(BPoint(secondStartX
, y
), BPoint(frame
.right
, y
),
884 ShiftMenuBackgroundColor(B_DARKEN_1_TINT
));
886 if (minfo
.separator
== 2) {
890 parent
->AddLine(BPoint(frame
.left
,y
), BPoint(firstEndX
, y
),
891 ShiftMenuBackgroundColor(B_DARKEN_1_TINT
));
892 parent
->AddLine(BPoint(secondStartX
,y
), BPoint(frame
.right
, y
),
893 ShiftMenuBackgroundColor(B_DARKEN_1_TINT
));
896 if (minfo
.separator
== 2) {
900 parent
->AddLine(BPoint(frame
.left
, y
), BPoint(firstEndX
, y
),
901 ShiftMenuBackgroundColor(B_DARKEN_1_TINT
));
902 parent
->AddLine(BPoint(secondStartX
, y
), BPoint(frame
.right
, y
),
903 ShiftMenuBackgroundColor(B_DARKEN_1_TINT
));
905 parent
->EndLineArray();
908 parent
->GetFontHeight(&finfo
);
910 parent
->SetLowColor(parent
->ViewColor());
911 BPoint
loc(firstEndX
+ kStubToStringSlotX
,
912 ContentLocation().y
+ finfo
.ascent
);
914 parent
->MovePenTo(loc
+ BPoint(1, 1));
915 parent
->SetHighColor(ShiftMenuBackgroundColor(B_DARKEN_1_TINT
));
916 parent
->DrawString(truncatedLabel
.String());
918 parent
->MovePenTo(loc
);
919 parent
->SetHighColor(ShiftMenuBackgroundColor(B_DISABLED_LABEL_TINT
));
920 parent
->DrawString(truncatedLabel
.String());
926 // #pragma mark - ShortcutFilter
929 ShortcutFilter::ShortcutFilter(uint32 shortcutKey
, uint32 shortcutModifier
,
930 uint32 shortcutWhat
, BHandler
* target
)
932 BMessageFilter(B_KEY_DOWN
),
933 fShortcutKey(shortcutKey
),
934 fShortcutModifier(shortcutModifier
),
935 fShortcutWhat(shortcutWhat
),
942 ShortcutFilter::Filter(BMessage
* message
, BHandler
**)
944 if (message
->what
== B_KEY_DOWN
) {
946 uint32 rawKeyChar
= 0;
950 if (message
->FindInt32("modifiers", (int32
*)&modifiers
) != B_OK
951 || message
->FindInt32("raw_char", (int32
*)&rawKeyChar
) != B_OK
952 || message
->FindInt8("byte", (int8
*)&byte
) != B_OK
953 || message
->FindInt32("key", &key
) != B_OK
) {
954 return B_DISPATCH_MESSAGE
;
957 modifiers
&= B_SHIFT_KEY
| B_COMMAND_KEY
| B_CONTROL_KEY
958 | B_OPTION_KEY
| B_MENU_KEY
;
959 // strip caps lock, etc.
961 if (modifiers
== fShortcutModifier
&& rawKeyChar
== fShortcutKey
) {
962 fTarget
->Looper()->PostMessage(fShortcutWhat
, fTarget
);
963 return B_SKIP_MESSAGE
;
967 // let others deal with this
968 return B_DISPATCH_MESSAGE
;
972 // #pragma mark - BPrivate functions
978 EmbedUniqueVolumeInfo(BMessage
* message
, const BVolume
* volume
)
980 BDirectory rootDirectory
;
984 if (volume
->GetRootDirectory(&rootDirectory
) == B_OK
985 && rootDirectory
.GetCreationTime(&created
) == B_OK
986 && fs_stat_dev(volume
->Device(), &info
) == 0) {
987 message
->AddInt64("creationDate", created
);
988 message
->AddInt64("capacity", volume
->Capacity());
989 message
->AddString("deviceName", info
.device_name
);
990 message
->AddString("volumeName", info
.volume_name
);
991 message
->AddString("fshName", info
.fsh_name
);
997 MatchArchivedVolume(BVolume
* volume
, const BMessage
* message
, int32 index
)
1002 if (message
->FindInt64("creationDate", index
, &created64
) != B_OK
) {
1004 if (message
->FindInt32("creationDate", index
, &created32
) != B_OK
)
1006 created64
= created32
;
1009 time_t created
= created64
;
1011 if (message
->FindInt64("capacity", index
, &capacity
) != B_OK
)
1014 BVolumeRoster roster
;
1020 if (message
->FindString("deviceName", &deviceName
) == B_OK
1021 && message
->FindString("volumeName", &volumeName
) == B_OK
1022 && message
->FindString("fshName", &fshName
) == B_OK
) {
1023 // New style volume identifiers: We have a couple of characteristics,
1024 // and compute a score from them. The volume with the greatest score
1025 // (if over a certain threshold) is the one we're looking for. We
1026 // pick the first volume, in case there is more than one with the
1028 dev_t foundDevice
= -1;
1029 int foundScore
= -1;
1031 while (roster
.GetNextVolume(&tempVolume
) == B_OK
) {
1032 if (tempVolume
.IsPersistent() && tempVolume
.KnowsQuery()) {
1033 // get creation time and fs_info
1035 tempVolume
.GetRootDirectory(&root
);
1038 if (root
.GetCreationTime(&cmpCreated
) == B_OK
1039 && fs_stat_dev(tempVolume
.Device(), &info
) == 0) {
1040 // compute the score
1044 if (created
== cmpCreated
)
1048 if (capacity
== tempVolume
.Capacity())
1052 if (deviceName
== info
.device_name
)
1056 if (volumeName
== info
.volume_name
)
1060 if (fshName
== info
.fsh_name
)
1064 if (score
>= 9 && score
> foundScore
) {
1065 foundDevice
= tempVolume
.Device();
1071 if (foundDevice
>= 0)
1072 return volume
->SetTo(foundDevice
);
1074 // Old style volume identifiers: We have only creation time and
1075 // capacity. Both must match.
1077 while (roster
.GetNextVolume(&tempVolume
) == B_OK
) {
1078 if (tempVolume
.IsPersistent() && tempVolume
.KnowsQuery()) {
1080 tempVolume
.GetRootDirectory(&root
);
1082 root
.GetCreationTime(&cmpCreated
);
1083 if (created
== cmpCreated
&& capacity
== tempVolume
.Capacity()) {
1084 *volume
= tempVolume
;
1091 return B_DEV_BAD_DRIVE_NUM
;
1096 StringFromStream(BString
* string
, BMallocIO
* stream
, bool endianSwap
)
1099 stream
->Read(&length
, sizeof(length
));
1101 length
= SwapInt32(length
);
1103 if (length
< 0 || length
> 10000) {
1104 // TODO: should fail here
1105 PRINT(("problems instatiating a string, length probably wrong %"
1106 B_PRId32
"\n", length
));
1110 char* buffer
= string
->LockBuffer(length
+ 1);
1111 stream
->Read(buffer
, (size_t)length
+ 1);
1112 string
->UnlockBuffer(length
);
1117 StringToStream(const BString
* string
, BMallocIO
* stream
)
1119 int32 length
= string
->Length();
1120 stream
->Write(&length
, sizeof(int32
));
1121 stream
->Write(string
->String(), (size_t)string
->Length() + 1);
1126 ArchiveSize(const BString
* string
)
1128 return string
->Length() + 1 + (ssize_t
)sizeof(int32
);
1133 CountRefs(const BMessage
* message
)
1137 message
->GetInfo("refs", &type
, &count
);
1144 EachEntryRefCommon(BMessage
* message
, entry_ref
*(*func
)(entry_ref
*, void*),
1145 void* passThru
, int32 maxCount
)
1149 message
->GetInfo("refs", &type
, &count
);
1151 if (maxCount
>= 0 && count
> maxCount
)
1154 for (int32 index
= 0; index
< count
; index
++) {
1156 message
->FindRef("refs", index
, &ref
);
1157 entry_ref
* newRef
= (func
)(&ref
, passThru
);
1167 ContainsEntryRef(const BMessage
* message
, const entry_ref
* ref
)
1170 for (int32 index
= 0; (message
->FindRef("refs", index
, &match
) == B_OK
);
1181 EachEntryRef(BMessage
* message
, entry_ref
* (*func
)(entry_ref
*, void*),
1184 return EachEntryRefCommon(message
, func
, passThru
, -1);
1187 typedef entry_ref
*(*EachEntryIteratee
)(entry_ref
*, void *);
1191 EachEntryRef(const BMessage
* message
,
1192 const entry_ref
* (*func
)(const entry_ref
*, void*), void* passThru
)
1194 return EachEntryRefCommon(const_cast<BMessage
*>(message
),
1195 (EachEntryIteratee
)func
, passThru
, -1);
1200 EachEntryRef(BMessage
* message
, entry_ref
* (*func
)(entry_ref
*, void*),
1201 void* passThru
, int32 maxCount
)
1203 return EachEntryRefCommon(message
, func
, passThru
, maxCount
);
1208 EachEntryRef(const BMessage
* message
,
1209 const entry_ref
*(*func
)(const entry_ref
*, void *), void* passThru
,
1212 return EachEntryRefCommon(const_cast<BMessage
*>(message
),
1213 (EachEntryIteratee
)func
, passThru
, maxCount
);
1218 TruncateLeaf(BString
* string
)
1220 for (int32 index
= string
->Length(); index
>= 0; index
--) {
1221 if ((*string
)[index
] == '/') {
1222 string
->Truncate(index
+ 1);
1230 StringToScalar(const char* text
)
1235 char* buffer
= new char [strlen(text
) + 1];
1236 strcpy(buffer
, text
);
1238 if (strstr(buffer
, "k") || strstr(buffer
, "K")) {
1239 val
= strtoll(buffer
, &end
, 10);
1241 } else if (strstr(buffer
, "mb") || strstr(buffer
, "MB")) {
1242 val
= strtoll(buffer
, &end
, 10);
1244 } else if (strstr(buffer
, "gb") || strstr(buffer
, "GB")) {
1245 val
= strtoll(buffer
, &end
, 10);
1247 } else if (strstr(buffer
, "byte") || strstr(buffer
, "BYTE")) {
1248 val
= strtoll(buffer
, &end
, 10);
1251 // no suffix, try plain byte conversion
1252 val
= strtoll(buffer
, &end
, 10);
1261 LineBounds(BPoint where
, float length
, bool vertical
)
1264 rect
.SetLeftTop(where
);
1265 rect
.SetRightBottom(where
+ BPoint(2, 2));
1267 rect
.bottom
= rect
.top
+ length
;
1269 rect
.right
= rect
.left
+ length
;
1275 SeparatorLine::SeparatorLine(BPoint where
, float length
, bool vertical
,
1278 BView(LineBounds(where
, length
, vertical
), name
,
1279 B_FOLLOW_LEFT
| B_FOLLOW_TOP
, B_WILL_DRAW
)
1281 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
1282 SetLowUIColor(B_PANEL_BACKGROUND_COLOR
);
1287 SeparatorLine::Draw(BRect
)
1289 BRect
bounds(Bounds());
1290 rgb_color hiliteColor
= tint_color(ViewColor(), 1.5f
);
1292 bool vertical
= (bounds
.left
> bounds
.right
- 3);
1295 AddLine(bounds
.LeftTop(), bounds
.LeftBottom(), hiliteColor
);
1296 AddLine(bounds
.LeftTop() + BPoint(1, 0),
1297 bounds
.LeftBottom() + BPoint(1, 0), kWhite
);
1299 AddLine(bounds
.LeftTop(), bounds
.RightTop(), hiliteColor
);
1300 AddLine(bounds
.LeftTop() + BPoint(0, 1),
1301 bounds
.RightTop() + BPoint(0, 1), kWhite
);
1308 HexDump(const void* buf
, int32 length
)
1310 const int32 kBytesPerLine
= 16;
1312 unsigned char* buffer
= (unsigned char*)buf
;
1314 for (offset
= 0; ; offset
+= kBytesPerLine
, buffer
+= kBytesPerLine
) {
1315 int32 remain
= length
;
1318 printf( "0x%06x: ", (int)offset
);
1320 for (index
= 0; index
< kBytesPerLine
; index
++) {
1322 printf("%02x%c", buffer
[index
], remain
> 0 ? ',' : ' ');
1329 for (index
= 0; index
< kBytesPerLine
; index
++) {
1331 printf("%c", buffer
[index
] > ' ' ? buffer
[index
] : '.');
1337 length
-= kBytesPerLine
;
1346 EnableNamedMenuItem(BMenu
* menu
, const char* itemName
, bool on
)
1348 BMenuItem
* item
= menu
->FindItem(itemName
);
1350 item
->SetEnabled(on
);
1355 MarkNamedMenuItem(BMenu
* menu
, const char* itemName
, bool on
)
1357 BMenuItem
* item
= menu
->FindItem(itemName
);
1359 item
->SetMarked(on
);
1364 EnableNamedMenuItem(BMenu
* menu
, uint32 commandName
, bool on
)
1366 BMenuItem
* item
= menu
->FindItem(commandName
);
1368 item
->SetEnabled(on
);
1373 MarkNamedMenuItem(BMenu
* menu
, uint32 commandName
, bool on
)
1375 BMenuItem
* item
= menu
->FindItem(commandName
);
1377 item
->SetMarked(on
);
1382 DeleteSubmenu(BMenuItem
* submenuItem
)
1384 if (submenuItem
== NULL
)
1387 BMenu
* menu
= submenuItem
->Submenu();
1392 BMenuItem
* item
= menu
->RemoveItem((int32
)0);
1402 GetAppSignatureFromAttr(BFile
* file
, char* attr
)
1404 // This call is a performance improvement that
1405 // avoids using the BAppFileInfo API when retrieving the
1406 // app signature -- the call is expensive because by default
1407 // the resource fork is scanned to read the attribute
1409 #ifdef B_APP_FILE_INFO_IS_FAST
1410 BAppFileInfo
appFileInfo(file
);
1411 return appFileInfo
.GetSignature(attr
);
1413 ssize_t readResult
= file
->ReadAttr(kAttrAppSignature
, B_MIME_STRING_TYPE
,
1414 0, attr
, B_MIME_TYPE_LENGTH
);
1416 if (readResult
<= 0)
1417 return (status_t
)readResult
;
1420 #endif // B_APP_FILE_INFO_IS_FAST
1425 GetAppIconFromAttr(BFile
* file
, BBitmap
* icon
, icon_size which
)
1427 // This call is a performance improvement that
1428 // avoids using the BAppFileInfo API when retrieving the
1429 // app icons -- the call is expensive because by default
1430 // the resource fork is scanned to read the icons
1432 //#ifdef B_APP_FILE_INFO_IS_FAST
1433 BAppFileInfo
appFileInfo(file
);
1434 return appFileInfo
.GetIcon(icon
, which
);
1437 // const char* attrName = kAttrIcon;
1438 // uint32 type = B_VECTOR_ICON_TYPE;
1440 // // try vector icon
1442 // status_t result = file->GetAttrInfo(attrName, &ainfo);
1444 // if (result == B_OK) {
1445 // uint8 buffer[ainfo.size];
1446 // ssize_t readResult = file->ReadAttr(attrName, type, 0, buffer,
1448 // if (readResult == ainfo.size) {
1449 // if (BIconUtils::GetVectorIcon(buffer, ainfo.size, icon) == B_OK)
1454 // // try again with R5 icons
1455 // attrName = which == B_LARGE_ICON ? kAttrLargeIcon : kAttrMiniIcon;
1456 // type = which == B_LARGE_ICON ? LARGE_ICON_TYPE : MINI_ICON_TYPE;
1458 // result = file->GetAttrInfo(attrName, &ainfo);
1459 // if (result < B_OK)
1462 // uint8 buffer[ainfo.size];
1464 // ssize_t readResult = file->ReadAttr(attrName, type, 0, buffer, ainfo.size);
1465 // if (readResult <= 0)
1466 // return (status_t)readResult;
1468 // if (icon->ColorSpace() != B_CMAP8)
1469 // result = BIconUtils::ConvertFromCMAP8(buffer, which, which, which, icon);
1471 // icon->SetBits(buffer, icon->BitsLength(), 0, B_CMAP8);
1474 //#endif // B_APP_FILE_INFO_IS_FAST
1479 GetFileIconFromAttr(BNode
* node
, BBitmap
* icon
, icon_size which
)
1481 BNodeInfo
fileInfo(node
);
1482 return fileInfo
.GetIcon(icon
, which
);
1487 PrintToStream(rgb_color color
)
1489 printf("r:%x, g:%x, b:%x, a:%x\n",
1490 color
.red
, color
.green
, color
.blue
, color
.alpha
);
1495 EachMenuItem(BMenu
* menu
, bool recursive
, BMenuItem
* (*func
)(BMenuItem
*))
1497 int32 count
= menu
->CountItems();
1498 for (int32 index
= 0; index
< count
; index
++) {
1499 BMenuItem
* item
= menu
->ItemAt(index
);
1500 BMenuItem
* newItem
= (func
)(item
);
1501 if (newItem
!= NULL
)
1505 BMenu
* submenu
= menu
->SubmenuAt(index
);
1506 if (submenu
!= NULL
)
1507 return EachMenuItem(submenu
, true, func
);
1515 extern const BMenuItem
*
1516 EachMenuItem(const BMenu
* menu
, bool recursive
,
1517 BMenuItem
* (*func
)(const BMenuItem
*))
1519 int32 count
= menu
->CountItems();
1520 for (int32 index
= 0; index
< count
; index
++) {
1521 BMenuItem
* item
= menu
->ItemAt(index
);
1522 BMenuItem
* newItem
= (func
)(item
);
1523 if (newItem
!= NULL
)
1527 BMenu
* submenu
= menu
->SubmenuAt(index
);
1528 if (submenu
!= NULL
)
1529 return EachMenuItem(submenu
, true, func
);
1537 // #pragma mark - PositionPassingMenuItem
1540 PositionPassingMenuItem::PositionPassingMenuItem(const char* title
,
1541 BMessage
* message
, char shortcut
, uint32 modifiers
)
1543 BMenuItem(title
, message
, shortcut
, modifiers
)
1548 PositionPassingMenuItem::PositionPassingMenuItem(BMenu
* menu
, BMessage
* message
)
1550 BMenuItem(menu
, message
)
1555 PositionPassingMenuItem::PositionPassingMenuItem(BMessage
* data
)
1563 PositionPassingMenuItem::Instantiate(BMessage
* data
)
1565 if (validate_instantiation(data
, "PositionPassingMenuItem"))
1566 return new PositionPassingMenuItem(data
);
1573 PositionPassingMenuItem::Invoke(BMessage
* message
)
1581 if (message
== NULL
)
1582 message
= Message();
1584 if (message
== NULL
)
1587 BMessage
clone(*message
);
1588 clone
.AddInt32("index", Menu()->IndexOf(this));
1589 clone
.AddInt64("when", system_time());
1590 clone
.AddPointer("source", this);
1592 // embed the invoke location of the menu so that we can create
1593 // a new folder, etc. on the spot
1594 BMenu
* menu
= Menu();
1597 if (!menu
->Supermenu())
1600 menu
= menu
->Supermenu();
1603 // use the window position only, if the item was invoked from the menu
1604 // menu->Window() points to the window the item was invoked from
1605 if (dynamic_cast<BContainerWindow
*>(menu
->Window()) == NULL
) {
1606 LooperAutoLocker
lock(menu
);
1607 if (lock
.IsLocked()) {
1608 BPoint
invokeOrigin(menu
->Window()->Frame().LeftTop());
1609 clone
.AddPoint("be:invoke_origin", invokeOrigin
);
1613 return BInvoker::Invoke(&clone
);
1617 // #pragma mark - BPrivate functions
1623 const char* safeMode
= getenv("SAFEMODE");
1624 return (safeMode
&& strcmp(safeMode
, "yes") == 0);
1629 ComputeTypeAheadScore(const char* text
, const char* match
, bool wordMode
)
1631 // highest score: exact match
1632 const char* found
= strcasestr(text
, match
);
1633 if (found
!= NULL
) {
1635 return kExactMatchScore
;
1637 return 1.f
/ (found
- text
);
1640 // there was no exact match
1642 // second best: all characters at word beginnings
1645 for (int32 j
= 0, k
= 0; match
[j
]; j
++) {
1647 && tolower(text
[k
]) != tolower(match
[j
])) {
1650 if (text
[k
] == '\0') {
1655 bool wordStart
= k
== 0 || isspace(text
[k
- 1]);
1659 bool wordEnd
= !text
[k
+ 1] || isspace(text
[k
+ 1]);
1662 if (match
[j
- 1] == text
[k
- 1])
1666 score
+= 1.f
/ (k
+ 1);
1677 // #pragma mark - throw on error functions.
1681 _ThrowOnError(status_t result
, const char* DEBUG_ONLY(file
),
1682 int32
DEBUG_ONLY(line
))
1684 if (result
!= B_OK
) {
1685 PRINT(("%s at %s:%d\n", strerror(result
), file
, (int)line
));
1692 _ThrowIfNotSize(ssize_t size
, const char* DEBUG_ONLY(file
),
1693 int32
DEBUG_ONLY(line
))
1696 PRINT(("%s at %s:%d\n", strerror((status_t
)size
), file
, (int)line
));
1697 throw (status_t
)size
;
1703 _ThrowOnAssert(bool success
, const char* DEBUG_ONLY(file
),
1704 int32
DEBUG_ONLY(line
))
1707 PRINT(("Assert failed at %s:%d\n", file
, (int)line
));
1712 } // namespace BPrivate