vfs: check userland buffers before reading them.
[haiku.git] / src / kits / interface / AboutWindow.cpp
blob3f683995b252f72929be28c1daa977ca264967b4
1 /*
2 * Copyright 2007-2015 Haiku, Inc.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Ryan Leavengood <leavengood@gmail.com>
7 * John Scipione <jscipione@gmail.com>
8 * Joseph Groover <looncraz@looncraz.net>
9 */
12 #include <AboutWindow.h>
14 #include <stdarg.h>
15 #include <time.h>
17 #include <Alert.h>
18 #include <AppFileInfo.h>
19 #include <Bitmap.h>
20 #include <Button.h>
21 #include <File.h>
22 #include <Font.h>
23 #include <GroupLayoutBuilder.h>
24 #include <GroupView.h>
25 #include <InterfaceDefs.h>
26 #include <LayoutBuilder.h>
27 #include <Message.h>
28 #include <MessageFilter.h>
29 #include <Point.h>
30 #include <Roster.h>
31 #include <Screen.h>
32 #include <ScrollView.h>
33 #include <Size.h>
34 #include <String.h>
35 #include <StringView.h>
36 #include <SystemCatalog.h>
37 #include <TextView.h>
38 #include <View.h>
39 #include <Window.h>
42 static const float kStripeWidth = 30.0;
44 using BPrivate::gSystemCatalog;
47 #undef B_TRANSLATION_CONTEXT
48 #define B_TRANSLATION_CONTEXT "AboutWindow"
51 namespace BPrivate {
53 class StripeView : public BView {
54 public:
55 StripeView(BBitmap* icon);
56 virtual ~StripeView();
58 virtual void Draw(BRect updateRect);
60 BBitmap* Icon() const { return fIcon; };
61 void SetIcon(BBitmap* icon);
63 private:
64 BBitmap* fIcon;
68 class AboutView : public BGroupView {
69 public:
70 AboutView(const char* name,
71 const char* signature);
72 virtual ~AboutView();
74 virtual void AllAttached();
76 BTextView* InfoView() const { return fInfoView; };
78 BBitmap* Icon();
79 status_t SetIcon(BBitmap* icon);
81 const char* Name();
82 status_t SetName(const char* name);
84 const char* Version();
85 status_t SetVersion(const char* version);
87 private:
88 const char* _GetVersionFromSignature(const char* signature);
89 BBitmap* _GetIconFromSignature(const char* signature);
91 private:
92 BStringView* fNameView;
93 BStringView* fVersionView;
94 BTextView* fInfoView;
95 StripeView* fStripeView;
99 // #pragma mark - StripeView
102 StripeView::StripeView(BBitmap* icon)
104 BView("StripeView", B_WILL_DRAW),
105 fIcon(icon)
107 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
109 float width = 0.0f;
110 if (icon != NULL)
111 width += icon->Bounds().Width() + 32.0f;
113 SetExplicitMinSize(BSize(width, B_SIZE_UNSET));
114 SetExplicitPreferredSize(BSize(width, B_SIZE_UNLIMITED));
118 StripeView::~StripeView()
123 void
124 StripeView::Draw(BRect updateRect)
126 if (fIcon == NULL)
127 return;
129 SetHighColor(ViewColor());
130 FillRect(updateRect);
132 BRect stripeRect = Bounds();
133 stripeRect.right = kStripeWidth;
134 SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
135 FillRect(stripeRect);
137 SetDrawingMode(B_OP_ALPHA);
138 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
139 DrawBitmapAsync(fIcon, BPoint(15.0f, 10.0f));
143 void
144 StripeView::SetIcon(BBitmap* icon)
146 if (fIcon != NULL)
147 delete fIcon;
149 fIcon = icon;
151 float width = 0.0f;
152 if (icon != NULL)
153 width += icon->Bounds().Width() + 32.0f;
155 SetExplicitMinSize(BSize(width, B_SIZE_UNSET));
156 SetExplicitPreferredSize(BSize(width, B_SIZE_UNLIMITED));
160 // #pragma mark - AboutView
163 AboutView::AboutView(const char* appName, const char* signature)
165 BGroupView("AboutView", B_VERTICAL)
167 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
168 fNameView = new BStringView("name", appName);
169 BFont font;
170 fNameView->GetFont(&font);
171 font.SetFace(B_BOLD_FACE);
172 font.SetSize(font.Size() * 2.0);
173 fNameView->SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE
174 | B_FONT_FLAGS);
176 fVersionView = new BStringView("version",
177 _GetVersionFromSignature(signature));
179 rgb_color documentColor = ui_color(B_DOCUMENT_TEXT_COLOR);
180 fInfoView = new BTextView("info", NULL, &documentColor, B_WILL_DRAW);
181 fInfoView->SetExplicitMinSize(BSize(210.0, 160.0));
182 fInfoView->MakeEditable(false);
183 fInfoView->SetWordWrap(true);
184 fInfoView->SetInsets(5.0, 5.0, 5.0, 5.0);
185 fInfoView->SetStylable(true);
187 BScrollView* infoViewScroller = new BScrollView(
188 "infoViewScroller", fInfoView, B_WILL_DRAW | B_FRAME_EVENTS,
189 false, true, B_PLAIN_BORDER);
191 fStripeView = new StripeView(_GetIconFromSignature(signature));
193 const char* ok = B_TRANSLATE_MARK("OK");
194 BButton* closeButton = new BButton("ok",
195 gSystemCatalog.GetString(ok, "AboutWindow"),
196 new BMessage(B_QUIT_REQUESTED));
198 GroupLayout()->SetSpacing(0);
199 BLayoutBuilder::Group<>(this, B_HORIZONTAL, 0)
200 .Add(fStripeView)
201 .AddGroup(B_VERTICAL, B_USE_SMALL_SPACING)
202 .SetInsets(0, B_USE_DEFAULT_SPACING,
203 B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING)
204 .Add(fNameView)
205 .Add(fVersionView)
206 .Add(infoViewScroller)
207 .AddGroup(B_HORIZONTAL, 0)
208 .AddGlue()
209 .Add(closeButton)
210 .End()
211 .End()
212 .AddGlue()
213 .View()->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
218 AboutView::~AboutView()
223 void
224 AboutView::AllAttached()
226 fNameView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
227 fInfoView->SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR);
228 fVersionView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
232 // #pragma mark - AboutView private methods
235 const char*
236 AboutView::_GetVersionFromSignature(const char* signature)
238 if (signature == NULL)
239 return NULL;
241 entry_ref ref;
242 if (be_roster->FindApp(signature, &ref) != B_OK)
243 return NULL;
245 BFile file(&ref, B_READ_ONLY);
246 BAppFileInfo appMime(&file);
247 if (appMime.InitCheck() != B_OK)
248 return NULL;
250 version_info versionInfo;
251 if (appMime.GetVersionInfo(&versionInfo, B_APP_VERSION_KIND) == B_OK) {
252 if (versionInfo.major == 0 && versionInfo.middle == 0
253 && versionInfo.minor == 0) {
254 return NULL;
257 const char* version = B_TRANSLATE_MARK("Version");
258 version = gSystemCatalog.GetString(version, "AboutWindow");
259 BString appVersion(version);
260 appVersion << " " << versionInfo.major << "." << versionInfo.middle;
261 if (versionInfo.minor > 0)
262 appVersion << "." << versionInfo.minor;
264 // Add the version variety
265 const char* variety = NULL;
266 switch (versionInfo.variety) {
267 case B_DEVELOPMENT_VERSION:
268 variety = B_TRANSLATE_MARK("development");
269 break;
270 case B_ALPHA_VERSION:
271 variety = B_TRANSLATE_MARK("alpha");
272 break;
273 case B_BETA_VERSION:
274 variety = B_TRANSLATE_MARK("beta");
275 break;
276 case B_GAMMA_VERSION:
277 variety = B_TRANSLATE_MARK("gamma");
278 break;
279 case B_GOLDEN_MASTER_VERSION:
280 variety = B_TRANSLATE_MARK("gold master");
281 break;
284 if (variety != NULL) {
285 variety = gSystemCatalog.GetString(variety, "AboutWindow");
286 appVersion << "-" << variety;
289 return appVersion.String();
292 return NULL;
296 BBitmap*
297 AboutView::_GetIconFromSignature(const char* signature)
299 if (signature == NULL)
300 return NULL;
302 entry_ref ref;
303 if (be_roster->FindApp(signature, &ref) != B_OK)
304 return NULL;
306 BFile file(&ref, B_READ_ONLY);
307 BAppFileInfo appMime(&file);
308 if (appMime.InitCheck() != B_OK)
309 return NULL;
311 BBitmap* icon = new BBitmap(BRect(0.0, 0.0, 127.0, 127.0), B_RGBA32);
312 if (appMime.GetIcon(icon, (icon_size)128) == B_OK)
313 return icon;
315 delete icon;
316 return NULL;
320 // #pragma mark - AboutView public methods
323 BBitmap*
324 AboutView::Icon()
326 if (fStripeView == NULL)
327 return NULL;
329 return fStripeView->Icon();
333 status_t
334 AboutView::SetIcon(BBitmap* icon)
336 if (fStripeView == NULL)
337 return B_NO_INIT;
339 fStripeView->SetIcon(icon);
341 return B_OK;
345 const char*
346 AboutView::Name()
348 return fNameView->Text();
352 status_t
353 AboutView::SetName(const char* name)
355 fNameView->SetText(name);
357 return B_OK;
361 const char*
362 AboutView::Version()
364 return fVersionView->Text();
368 status_t
369 AboutView::SetVersion(const char* version)
371 fVersionView->SetText(version);
373 return B_OK;
376 } // namespace BPrivate
379 // #pragma mark - BAboutWindow
382 BAboutWindow::BAboutWindow(const char* appName, const char* signature)
384 BWindow(BRect(0.0, 0.0, 200.0, 200.0), appName, B_MODAL_WINDOW,
385 B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_RESIZABLE
386 | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE)
388 SetLayout(new BGroupLayout(B_VERTICAL));
390 const char* about = B_TRANSLATE_MARK("About %app%");
391 about = gSystemCatalog.GetString(about, "AboutWindow");
393 BString title(about);
394 title.ReplaceFirst("%app%", appName);
395 SetTitle(title.String());
397 fAboutView = new BPrivate::AboutView(appName, signature);
398 AddChild(fAboutView);
400 MoveTo(AboutPosition(Frame().Width(), Frame().Height()));
404 BAboutWindow::~BAboutWindow()
406 fAboutView->RemoveSelf();
407 delete fAboutView;
408 fAboutView = NULL;
412 // #pragma mark - BAboutWindow virtual methods
415 void
416 BAboutWindow::Show()
418 if (IsHidden()) {
419 // move to current workspace
420 SetWorkspaces(B_CURRENT_WORKSPACE);
423 BWindow::Show();
427 // #pragma mark - BAboutWindow public methods
430 BPoint
431 BAboutWindow::AboutPosition(float width, float height)
433 BPoint result(100, 100);
435 BWindow* window =
436 dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
438 BScreen screen(window);
439 BRect screenFrame(0, 0, 640, 480);
440 if (screen.IsValid())
441 screenFrame = screen.Frame();
443 // Horizontally, we're smack in the middle
444 result.x = screenFrame.left + (screenFrame.Width() / 2.0) - (width / 2.0);
446 // This is probably sooo wrong, but it looks right on 1024 x 768
447 result.y = screenFrame.top + (screenFrame.Height() / 4.0)
448 - ceil(height / 3.0);
450 return result;
454 void
455 BAboutWindow::AddDescription(const char* description)
457 if (description == NULL)
458 return;
460 AddText(description);
464 void
465 BAboutWindow::AddCopyright(int32 firstCopyrightYear,
466 const char* copyrightHolder, const char** extraCopyrights)
468 BString copyright(B_UTF8_COPYRIGHT " %years% %holder%");
470 // Get current year
471 time_t tp;
472 time(&tp);
473 char currentYear[5];
474 strftime(currentYear, 5, "%Y", localtime(&tp));
475 BString copyrightYears;
476 copyrightYears << firstCopyrightYear;
477 if (copyrightYears != currentYear)
478 copyrightYears << "-" << currentYear;
480 BString text("");
481 if (fAboutView->InfoView()->TextLength() > 0)
482 text << "\n\n";
484 text << copyright;
486 // Fill out the copyright year placeholder
487 text.ReplaceAll("%years%", copyrightYears.String());
489 // Fill in the copyright holder placeholder
490 text.ReplaceAll("%holder%", copyrightHolder);
492 // Add extra copyright strings
493 if (extraCopyrights != NULL) {
494 // Add optional extra copyright information
495 for (int32 i = 0; extraCopyrights[i]; i++)
496 text << "\n" << B_UTF8_COPYRIGHT << " " << extraCopyrights[i];
499 const char* allRightsReserved = B_TRANSLATE_MARK("All Rights Reserved.");
500 allRightsReserved = gSystemCatalog.GetString(allRightsReserved,
501 "AboutWindow");
502 text << "\n " << allRightsReserved;
504 fAboutView->InfoView()->Insert(text.String());
508 void
509 BAboutWindow::AddAuthors(const char** authors)
511 if (authors == NULL)
512 return;
514 const char* writtenBy = B_TRANSLATE_MARK("Written by:");
515 writtenBy = gSystemCatalog.GetString(writtenBy, "AboutWindow");
517 AddText(writtenBy, authors);
521 void
522 BAboutWindow::AddSpecialThanks(const char** thanks)
524 if (thanks == NULL)
525 return;
527 const char* specialThanks = B_TRANSLATE_MARK("Special Thanks:");
528 specialThanks = gSystemCatalog.GetString(specialThanks, "AboutWindow");
530 AddText(specialThanks, thanks);
534 void
535 BAboutWindow::AddVersionHistory(const char** history)
537 if (history == NULL)
538 return;
540 const char* versionHistory = B_TRANSLATE_MARK("Version history:");
541 versionHistory = gSystemCatalog.GetString(versionHistory, "AboutWindow");
543 AddText(versionHistory, history);
547 void
548 BAboutWindow::AddExtraInfo(const char* extraInfo)
550 if (extraInfo == NULL)
551 return;
553 const char* appExtraInfo = B_TRANSLATE_MARK(extraInfo);
554 appExtraInfo = gSystemCatalog.GetString(extraInfo, "AboutWindow");
556 BString extra("");
557 if (fAboutView->InfoView()->TextLength() > 0)
558 extra << "\n\n";
560 extra << appExtraInfo;
562 fAboutView->InfoView()->Insert(extra.String());
566 void
567 BAboutWindow::AddText(const char* header, const char** contents)
569 BTextView* infoView = fAboutView->InfoView();
570 int32 textLength = infoView->TextLength();
571 BString text("");
573 if (textLength > 0) {
574 text << "\n\n";
575 textLength += 2;
578 const char* indent = "";
579 if (header != NULL) {
580 indent = " ";
581 text << header;
584 if (contents != NULL) {
585 text << "\n";
586 for (int32 i = 0; contents[i]; i++)
587 text << indent << contents[i] << "\n";
590 infoView->Insert(text.String());
592 if (contents != NULL && header != NULL) {
593 infoView->SetFontAndColor(textLength, textLength + strlen(header),
594 be_bold_font);
599 BBitmap*
600 BAboutWindow::Icon()
602 return fAboutView->Icon();
606 void
607 BAboutWindow::SetIcon(BBitmap* icon)
609 fAboutView->SetIcon(icon);
613 const char*
614 BAboutWindow::Name()
616 return fAboutView->Name();
620 void
621 BAboutWindow::SetName(const char* name)
623 fAboutView->SetName(name);
627 const char*
628 BAboutWindow::Version()
630 return fAboutView->Version();
634 void
635 BAboutWindow::SetVersion(const char* version)
637 fAboutView->SetVersion(version);
641 // FBC padding
643 void BAboutWindow::_ReservedAboutWindow20() {}
644 void BAboutWindow::_ReservedAboutWindow19() {}
645 void BAboutWindow::_ReservedAboutWindow18() {}
646 void BAboutWindow::_ReservedAboutWindow17() {}
647 void BAboutWindow::_ReservedAboutWindow16() {}
648 void BAboutWindow::_ReservedAboutWindow15() {}
649 void BAboutWindow::_ReservedAboutWindow14() {}
650 void BAboutWindow::_ReservedAboutWindow13() {}
651 void BAboutWindow::_ReservedAboutWindow12() {}
652 void BAboutWindow::_ReservedAboutWindow11() {}
653 void BAboutWindow::_ReservedAboutWindow10() {}
654 void BAboutWindow::_ReservedAboutWindow9() {}
655 void BAboutWindow::_ReservedAboutWindow8() {}
656 void BAboutWindow::_ReservedAboutWindow7() {}
657 void BAboutWindow::_ReservedAboutWindow6() {}
658 void BAboutWindow::_ReservedAboutWindow5() {}
659 void BAboutWindow::_ReservedAboutWindow4() {}
660 void BAboutWindow::_ReservedAboutWindow3() {}
661 void BAboutWindow::_ReservedAboutWindow2() {}
662 void BAboutWindow::_ReservedAboutWindow1() {}