1 /* 2 * Copyright (c) 2005-2008, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 * René Gollent 8 */ 9 10 #include <ctype.h> 11 #include <stdio.h> 12 #include <sys/utsname.h> 13 #include <time.h> 14 15 #include <AppFileInfo.h> 16 #include <Application.h> 17 #include <Bitmap.h> 18 #include <File.h> 19 #include <FindDirectory.h> 20 #include <Font.h> 21 #include <fs_attr.h> 22 #include <MessageRunner.h> 23 #include <Messenger.h> 24 #include <OS.h> 25 #include <Path.h> 26 #include <Query.h> 27 #include <Resources.h> 28 #include <Screen.h> 29 #include <ScrollView.h> 30 #include <String.h> 31 #include <StringView.h> 32 #include <TranslationUtils.h> 33 #include <TranslatorFormats.h> 34 #include <View.h> 35 #include <Volume.h> 36 #include <VolumeRoster.h> 37 #include <Window.h> 38 39 #include <AppMisc.h> 40 #include <AutoDeleter.h> 41 #include <cpu_type.h> 42 43 #include "HyperTextActions.h" 44 #include "HyperTextView.h" 45 #include "Utilities.h" 46 47 48 #define SCROLL_CREDITS_VIEW 'mviv' 49 #define READ_APP_QUERY_ENT 'raqe' 50 51 52 static const char *UptimeToString(char string[], size_t size); 53 static const char *MemUsageToString(char string[], size_t size, 54 system_info *info); 55 56 static const rgb_color kDarkGrey = { 100, 100, 100, 255 }; 57 static const rgb_color kHaikuGreen = { 42, 131, 36, 255 }; 58 static const rgb_color kHaikuOrange = { 255, 69, 0, 255 }; 59 static const rgb_color kHaikuYellow = { 255, 176, 0, 255 }; 60 static const rgb_color kLinkBlue = { 80, 80, 200, 255 }; 61 62 63 class AboutApp : public BApplication { 64 public: 65 AboutApp(void); 66 }; 67 68 class AboutWindow : public BWindow { 69 public: 70 AboutWindow(void); 71 bool QuitRequested(void); 72 }; 73 74 class AboutView : public BView { 75 public: 76 AboutView(const BRect &r); 77 ~AboutView(void); 78 79 virtual void AttachedToWindow(); 80 virtual void Pulse(); 81 82 virtual void FrameResized(float width, float height); 83 virtual void Draw(BRect update); 84 virtual void MessageReceived(BMessage *msg); 85 virtual void MouseDown(BPoint pt); 86 87 void AddCopyrightEntry(const char *name, const char *text, 88 const Licenses& licenses, const char *url); 89 void AddCopyrightEntry(const char *name, const char *text, 90 const char *url = NULL); 91 void AddCopyrightEntry(const BMessage& packageDescription); 92 void PickRandomHaiku(); 93 94 private: 95 void _AddCopyrightsFromAttribute(); 96 97 BStringView *fMemView; 98 BStringView *fUptimeView; 99 BView *fInfoView; 100 HyperTextView *fCreditsView; 101 102 BBitmap *fLogo; 103 104 BPoint fDrawPoint; 105 106 bigtime_t fLastActionTime; 107 BMessageRunner *fScrollRunner; 108 BQuery fAppsQuery; 109 }; 110 111 112 // #pragma mark - 113 114 115 AboutApp::AboutApp(void) 116 : BApplication("application/x-vnd.Haiku-About") 117 { 118 AboutWindow *window = new AboutWindow(); 119 window->Show(); 120 } 121 122 123 // #pragma mark - 124 125 126 AboutWindow::AboutWindow() 127 : BWindow(BRect(0, 0, 500, 300), "About This System", B_TITLED_WINDOW, 128 B_NOT_RESIZABLE | B_NOT_ZOOMABLE) 129 { 130 AboutView *view = new AboutView(Bounds()); 131 AddChild(view); 132 133 // start reading from the app query 134 BMessage msg(READ_APP_QUERY_ENT); 135 BMessenger msgr(view); 136 msgr.SendMessage(&msg); 137 138 MoveTo((BScreen().Frame().Width() - Bounds().Width()) / 2, 139 (BScreen().Frame().Height() - Bounds().Height()) / 2 ); 140 } 141 142 143 bool 144 AboutWindow::QuitRequested() 145 { 146 be_app->PostMessage(B_QUIT_REQUESTED); 147 return true; 148 } 149 150 151 AboutView::AboutView(const BRect &rect) 152 : BView(rect, "aboutview", B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED), 153 fLastActionTime(system_time()), 154 fScrollRunner(NULL) 155 { 156 fLogo = BTranslationUtils::GetBitmap(B_PNG_FORMAT, "haikulogo.png"); 157 if (fLogo) { 158 fDrawPoint.x = (225-fLogo->Bounds().Width()) / 2; 159 fDrawPoint.y = 0; 160 } 161 162 // Begin Construction of System Information controls 163 164 font_height height; 165 float labelHeight, textHeight; 166 167 system_info systemInfo; 168 get_system_info(&systemInfo); 169 170 be_plain_font->GetHeight(&height); 171 textHeight = height.ascent + height.descent + height.leading; 172 173 be_bold_font->GetHeight(&height); 174 labelHeight = height.ascent + height.descent + height.leading; 175 176 BRect r(0, 0, 225, Bounds().bottom); 177 if (fLogo) 178 r.OffsetBy(0, fLogo->Bounds().Height()); 179 180 fInfoView = new BView(r, "infoview", B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, 181 B_WILL_DRAW); 182 fInfoView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 183 fInfoView->SetLowColor(fInfoView->ViewColor()); 184 fInfoView->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); 185 AddChild(fInfoView); 186 187 // Add all the various labels for system infomation 188 189 BStringView *stringView; 190 191 // OS Version 192 r.Set(5, 5, 224, labelHeight + 5); 193 stringView = new BStringView(r, "oslabel", "Version:"); 194 stringView->SetFont(be_bold_font); 195 fInfoView->AddChild(stringView); 196 stringView->ResizeToPreferred(); 197 198 // we update "labelHeight" to the actual height of the string view 199 labelHeight = stringView->Bounds().Height(); 200 201 r.OffsetBy(0, labelHeight); 202 r.bottom = r.top + textHeight; 203 204 char string[1024]; 205 strcpy(string, "Unknown"); 206 207 // the version is stored in the BEOS:APP_VERSION attribute of libbe.so 208 BPath path; 209 if (find_directory(B_BEOS_LIB_DIRECTORY, &path) == B_OK) { 210 path.Append("libbe.so"); 211 212 BAppFileInfo appFileInfo; 213 version_info versionInfo; 214 BFile file; 215 if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK 216 && appFileInfo.SetTo(&file) == B_OK 217 && appFileInfo.GetVersionInfo(&versionInfo, 218 B_APP_VERSION_KIND) == B_OK 219 && versionInfo.short_info[0] != '\0') 220 strcpy(string, versionInfo.short_info); 221 } 222 223 // Add revision from uname() info 224 utsname unameInfo; 225 if (uname(&unameInfo) == 0) { 226 long revision; 227 if (sscanf(unameInfo.version, "r%ld", &revision) == 1) { 228 char version[16]; 229 snprintf(version, sizeof(version), "%ld", revision); 230 strlcat(string, " (Revision ", sizeof(string)); 231 strlcat(string, version, sizeof(string)); 232 strlcat(string, ")", sizeof(string)); 233 } 234 } 235 236 stringView = new BStringView(r, "ostext", string); 237 fInfoView->AddChild(stringView); 238 stringView->ResizeToPreferred(); 239 240 // GCC version 241 #if __GNUC__ != 2 242 r.OffsetBy(0, textHeight); 243 r.bottom = r.top + textHeight; 244 245 snprintf(string, sizeof(string), "GCC %d", __GNUC__); 246 247 stringView = new BStringView(r, "gcctext", string); 248 fInfoView->AddChild(stringView); 249 stringView->ResizeToPreferred(); 250 #endif 251 252 // CPU count, type and clock speed 253 r.OffsetBy(0, textHeight * 1.5); 254 r.bottom = r.top + labelHeight; 255 256 if (systemInfo.cpu_count > 1) 257 sprintf(string, "%ld Processors:", systemInfo.cpu_count); 258 else 259 strcpy(string, "Processor:"); 260 261 stringView = new BStringView(r, "cpulabel", string); 262 stringView->SetFont(be_bold_font); 263 fInfoView->AddChild(stringView); 264 stringView->ResizeToPreferred(); 265 266 BString cpuType; 267 cpuType << get_cpu_vendor_string(systemInfo.cpu_type) 268 << " " << get_cpu_model_string(&systemInfo); 269 270 r.OffsetBy(0, labelHeight); 271 r.bottom = r.top + textHeight; 272 stringView = new BStringView(r, "cputext", cpuType.String()); 273 fInfoView->AddChild(stringView); 274 stringView->ResizeToPreferred(); 275 276 r.OffsetBy(0, textHeight); 277 r.bottom = r.top + textHeight; 278 279 int32 clockSpeed = get_rounded_cpu_speed(); 280 if (clockSpeed < 1000) 281 sprintf(string,"%ld MHz", clockSpeed); 282 else 283 sprintf(string,"%.2f GHz", clockSpeed / 1000.0f); 284 285 stringView = new BStringView(r, "mhztext", string); 286 fInfoView->AddChild(stringView); 287 stringView->ResizeToPreferred(); 288 289 // RAM 290 r.OffsetBy(0, textHeight * 1.5); 291 r.bottom = r.top + labelHeight; 292 stringView = new BStringView(r, "ramlabel", "Memory:"); 293 stringView->SetFont(be_bold_font); 294 fInfoView->AddChild(stringView); 295 stringView->ResizeToPreferred(); 296 297 r.OffsetBy(0, labelHeight); 298 r.bottom = r.top + textHeight; 299 300 fMemView = new BStringView(r, "ramtext", ""); 301 fInfoView->AddChild(fMemView); 302 fMemView->SetText(MemUsageToString(string, sizeof(string), &systemInfo)); 303 304 // Kernel build time/date 305 r.OffsetBy(0, textHeight * 1.5); 306 r.bottom = r.top + labelHeight; 307 stringView = new BStringView(r, "kernellabel", "Kernel:"); 308 stringView->SetFont(be_bold_font); 309 fInfoView->AddChild(stringView); 310 stringView->ResizeToPreferred(); 311 312 r.OffsetBy(0, labelHeight); 313 r.bottom = r.top + textHeight; 314 315 snprintf(string, sizeof(string), "%s %s", 316 systemInfo.kernel_build_date, systemInfo.kernel_build_time); 317 318 stringView = new BStringView(r, "kerneltext", string); 319 fInfoView->AddChild(stringView); 320 stringView->ResizeToPreferred(); 321 322 // Uptime 323 r.OffsetBy(0, textHeight * 1.5); 324 r.bottom = r.top + labelHeight; 325 stringView = new BStringView(r, "uptimelabel", "Time Running:"); 326 stringView->SetFont(be_bold_font); 327 fInfoView->AddChild(stringView); 328 stringView->ResizeToPreferred(); 329 330 r.OffsetBy(0, labelHeight); 331 r.bottom = r.top + textHeight; 332 333 fUptimeView = new BStringView(r, "uptimetext", ""); 334 fInfoView->AddChild(fUptimeView); 335 // string width changes, so we don't do ResizeToPreferred() 336 337 fUptimeView->SetText(UptimeToString(string, sizeof(string))); 338 339 // Begin construction of the credits view 340 r = Bounds(); 341 r.left += fInfoView->Bounds().right + 1; 342 r.right -= B_V_SCROLL_BAR_WIDTH; 343 344 fCreditsView = new HyperTextView(r, "credits", 345 r.OffsetToCopy(0, 0).InsetByCopy(5, 5), B_FOLLOW_ALL); 346 fCreditsView->SetFlags(fCreditsView->Flags() | B_FRAME_EVENTS ); 347 fCreditsView->SetStylable(true); 348 fCreditsView->MakeEditable(false); 349 fCreditsView->MakeSelectable(false); 350 fCreditsView->SetWordWrap(true); 351 352 BScrollView *creditsScroller = new BScrollView("creditsScroller", 353 fCreditsView, B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS, false, true, 354 B_PLAIN_BORDER); 355 AddChild(creditsScroller); 356 357 // Haiku copyright 358 BFont font(be_bold_font); 359 font.SetSize(font.Size() + 4); 360 361 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen); 362 fCreditsView->Insert("Haiku\n"); 363 364 time_t time = ::time(NULL); 365 struct tm* tm = localtime(&time); 366 int32 year = tm->tm_year + 1900; 367 if (year < 2008) 368 year = 2008; 369 snprintf(string, sizeof(string), 370 "Copyright " B_UTF8_COPYRIGHT " 2001-%ld The Haiku project.", year); 371 372 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 373 fCreditsView->Insert(string); 374 375 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 376 fCreditsView->Insert("The copyright to the Haiku code is property of " 377 "Haiku, Inc. or of the respective authors where expressly noted " 378 "in the source." 379 "\n\n"); 380 381 382 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kLinkBlue); 383 fCreditsView->InsertHyperText("http://www.haiku-os.org", 384 new URLAction("http://www.haiku-os.org")); 385 fCreditsView->Insert("\n\n"); 386 387 font.SetSize(be_bold_font->Size()); 388 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 389 390 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 391 fCreditsView->Insert("Current Maintainers:\n"); 392 393 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 394 fCreditsView->Insert( 395 "Ithamar R. Adema\n" 396 "Bruno G. Albuquerque\n" 397 "Stephan Aßmus\n" 398 "Salvatore Benedetto\n" 399 "Stefano Ceccherini\n" 400 "Rudolf Cornelissen\n" 401 "Alexandre Deckner\n" 402 "Oliver Ruiz Dorantes\n" 403 "Axel Dörfler\n" 404 "Jérôme Duval\n" 405 "René Gollent\n" 406 "Karsten Heimrich\n" 407 "Philippe Houdoin\n" 408 "Maurice Kalinowski\n" 409 "Euan Kirkhope\n" 410 "Ryan Leavengood\n" 411 "Michael Lotz\n" 412 "David McPaul\n" 413 "Fredrik Modéen\n" 414 "Marcus Overhagen\n" 415 "Michael Pfeiffer\n" 416 "François Revol\n" 417 "Andrej Spielmann\n" 418 "Oliver Tappe\n" 419 "Gerasim Troeglazov\n" 420 "Ingo Weinhold\n" 421 "Siarzhuk Zharski\n" 422 "\n"); 423 424 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 425 fCreditsView->Insert("Past Maintainers:\n"); 426 427 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 428 fCreditsView->Insert( 429 "Andrew Bachmann\n" 430 "Tyler Dauwalder\n" 431 "Daniel Furrer\n" 432 "Andre Alves Garzia\n" 433 "Erik Jaesler\n" 434 "Marcin Konicki\n" 435 "Waldemar Kornewald\n" 436 "Thomas Kurschel\n" 437 "Frans Van Nispen\n" 438 "Adi Oanca\n" 439 "Michael Phipps\n" 440 "Niels Sascha Reedijk\n" 441 "David Reid\n" 442 "Hugo Santos\n" 443 "Alexander G. M. Smith\n" 444 "Jonas Sundström\n" 445 "Bryan Varner\n" 446 "Nathan Whitehorn\n" 447 "Michael Wilber\n" 448 "Jonathan Yoder\n" 449 "Gabe Yoder\n" 450 "\n"); 451 452 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 453 fCreditsView->Insert("Website, Marketing & Documentation:\n"); 454 455 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 456 fCreditsView->Insert( 457 "Phil Greenway\n" 458 "Gavin James\n" 459 "Urias McCullough\n" 460 "Niels Sascha Reedijk\n" 461 "Jonathan Yoder\n" 462 "\n"); 463 464 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 465 fCreditsView->Insert("Contributors:\n"); 466 467 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 468 fCreditsView->Insert( 469 "Andrea Anzani\n" 470 "Andre Braga\n" 471 "Bruce Cameron\n" 472 "Greg Crain\n" 473 "David Dengg\n" 474 "John Drinkwater\n" 475 "Cian Duffy\n" 476 "Christian Fasshauer\n" 477 "Andreas Färber\n" 478 "Marc Flerackers\n" 479 "Matthijs Hollemans\n" 480 "Mathew Hounsell\n" 481 "Morgan Howe\n" 482 "Carwyn Jones\n" 483 "Vasilis Kaoutsis\n" 484 "James Kim\n" 485 "Shintaro Kinugawa\n" 486 "Jan Klötzke\n" 487 "Kurtis Kopf\n" 488 "Tomáš Kučera\n" 489 "Luboš Kulič\n" 490 "Elad Lahav\n" 491 "Anthony Lee\n" 492 "Santiago Lema\n" 493 "Raynald Lesieur\n" 494 "Oscar Lesta\n" 495 "Jerome Leveque\n" 496 "Christof Lutteroth\n" 497 "Graham MacDonald\n" 498 "Jan Matějek\n" 499 "Brian Matzon\n" 500 "Christopher ML Zumwalt May\n" 501 "Andrew McCall\n" 502 "Scott McCreary\n" 503 "Michele (zuMi)\n" 504 "Marius Middelthon\n" 505 "Marco Minutoli\n" 506 "Misza\n" 507 "MrSiggler\n" 508 "Alan Murta\n" 509 "Pahtz\n" 510 "Michael Paine\n" 511 "David Powell\n" 512 "Jeremy Rand\n" 513 "Hartmut Reh\n" 514 "Daniel Reinhold\n" 515 "Samuel Rodriguez Perez\n" 516 "Thomas Roell\n" 517 "Rafael Romo\n" 518 "Philippe Saint-Pierre\n" 519 "Ralf Schülke\n" 520 "Reznikov Sergei\n" 521 "Zousar Shaker\n" 522 "Daniel Switkin\n" 523 "Atsushi Takamatsu\n" 524 "James Urquhart\n" 525 "Jason Vandermark\n" 526 "Sandor Vroemisse\n" 527 "Denis Washington\n" 528 "Ulrich Wimboeck\n" 529 "James Woodcock\n" 530 "Artur Wyszynski\n" 531 "Gerald Zajac\n" 532 "Łukasz Zemczak\n" 533 "JiSheng Zhang\n" 534 "Zhao Shuai\n" 535 "\n" B_UTF8_ELLIPSIS " and probably some more we forgot to mention " 536 "(sorry!)" 537 "\n\n"); 538 539 540 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange); 541 fCreditsView->Insert("Special Thanks To:\n"); 542 543 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 544 fCreditsView->Insert("Travis Geiselbrecht (and his NewOS kernel)\n"); 545 fCreditsView->Insert("Michael Phipps (project founder)\n\n"); 546 547 // copyrights for various projects we use 548 549 font.SetSize(be_bold_font->Size() + 4); 550 font.SetFace(B_BOLD_FACE); 551 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen); 552 fCreditsView->Insert("\nCopyrights\n\n"); 553 554 // GNU copyrights 555 AddCopyrightEntry("The GNU Project", 556 "Contains software from the GNU Project, " 557 "released under the GPL and LGPL licences:\n" 558 "GNU C Library, " 559 "GNU coretools, diffutils, findutils, " 560 "sharutils, gawk, bison, m4, make, " 561 "gdb, wget, ncurses, termcap, " 562 "Bourne Again Shell.\n" 563 "Copyright " B_UTF8_COPYRIGHT " The Free Software Foundation.", 564 Licenses("GNU LGPL v2.1", "GNU GPL v2", "GNU GPL v3", NULL), 565 "http://www.gnu.org"); 566 567 // FreeBSD copyrights 568 AddCopyrightEntry("The FreeBSD Project", 569 "Contains software from the FreeBSD Project, " 570 "released under the BSD licence:\n" 571 "cal, ftpd, ping, telnet, " 572 "telnetd, traceroute\n" 573 "Copyright " B_UTF8_COPYRIGHT " 1994-2008 The FreeBSD Project. " 574 "All rights reserved.", 575 "http://www.freebsd.org"); 576 577 // NetBSD copyrights 578 AddCopyrightEntry("The NetBSD Project", 579 "Contains software developed by the NetBSD, " 580 "Foundation, Inc. and its contributors:\n" 581 "ftp, tput\n" 582 "Copyright " B_UTF8_COPYRIGHT " 1996-2008 The NetBSD Foundation, Inc. " 583 "All rights reserved.", 584 "http://www.netbsd.org"); 585 586 // FFMpeg copyrights 587 AddCopyrightEntry("FFMpeg libavcodec", 588 "Copyright " B_UTF8_COPYRIGHT " 2000-2007 Fabrice Bellard, et al.", 589 "http://www.ffmpeg.org"); 590 591 // AGG copyrights 592 AddCopyrightEntry("AntiGrain Geometry", 593 "Copyright " B_UTF8_COPYRIGHT " 2002-2006 Maxim Shemanarev (McSeem).", 594 "http://www.antigrain.com"); 595 596 // PDFLib copyrights 597 AddCopyrightEntry("PDFLib", 598 "Copyright " B_UTF8_COPYRIGHT " 1997-2006 PDFlib GmbH and Thomas Merz. " 599 "All rights reserved.\n" 600 "PDFlib and PDFlib logo are registered trademarks of PDFlib GmbH.", 601 "http://www.pdflib.com"); 602 603 // FreeType copyrights 604 AddCopyrightEntry("FreeType2", 605 "Portions of this software are copyright " B_UTF8_COPYRIGHT " 1996-2006 " 606 "The FreeType Project. All rights reserved.", 607 "http://www.freetype.org"); 608 609 // Mesa3D (http://www.mesa3d.org) copyrights 610 AddCopyrightEntry("Mesa", 611 "Copyright " B_UTF8_COPYRIGHT " 1999-2006 Brian Paul. " 612 "Mesa3D project. All rights reserved.", 613 "http://www.mesa3d.org"); 614 615 // SGI's GLU implementation copyrights 616 AddCopyrightEntry("GLU", 617 "Copyright " B_UTF8_COPYRIGHT " 1991-2000 Silicon Graphics, Inc. " 618 "SGI's Software FreeB license. All rights reserved."); 619 620 // GLUT implementation copyrights 621 AddCopyrightEntry("GLUT", 622 "Copyright " B_UTF8_COPYRIGHT " 1994-1997 Mark Kilgard. " 623 "All rights reserved.\n" 624 "Copyright " B_UTF8_COPYRIGHT " 1997 Be Inc.\n" 625 "Copyright " B_UTF8_COPYRIGHT " 1999 Jake Hamby."); 626 627 // OpenGroup & DEC (BRegion backend) copyright 628 AddCopyrightEntry("BRegion backend (XFree86)", 629 "Copyright " B_UTF8_COPYRIGHT " 1987, 1988, 1998 The Open Group.\n" 630 "Copyright " B_UTF8_COPYRIGHT " 1987, 1988 Digital Equipment " 631 "Corporation, Maynard, Massachusetts.\n" 632 "All rights reserved."); 633 634 // Konatu font 635 AddCopyrightEntry("Konatu font", 636 "Copyright " B_UTF8_COPYRIGHT " 2002- MASUDA mitiya.\n" 637 "MIT license. All rights reserved."); 638 639 // expat copyrights 640 AddCopyrightEntry("expat", 641 "Copyright " B_UTF8_COPYRIGHT " 1998, 1999, 2000 Thai Open Source " 642 "Software Center Ltd and Clark Cooper.\n" 643 "Copyright " B_UTF8_COPYRIGHT " 2001, 2002, 2003 Expat maintainers."); 644 645 // zlib copyrights 646 AddCopyrightEntry("zlib", 647 "Copyright " B_UTF8_COPYRIGHT " 1995-2004 Jean-loup Gailly and Mark " 648 "Adler."); 649 650 // zip copyrights 651 AddCopyrightEntry("Info-ZIP", 652 "Copyright " B_UTF8_COPYRIGHT " 1990-2002 Info-ZIP. All rights reserved."); 653 654 // bzip2 copyrights 655 AddCopyrightEntry("bzip2", 656 "Copyright " B_UTF8_COPYRIGHT " 1996-2005 Julian R Seward. All rights " 657 "reserved."); 658 659 // VIM copyrights 660 AddCopyrightEntry("Vi IMproved", 661 "Copyright " B_UTF8_COPYRIGHT " Bram Moolenaar et al."); 662 663 // lp_solve copyrights 664 AddCopyrightEntry("lp_solve", 665 "Copyright " B_UTF8_COPYRIGHT 666 " Michel Berkelaar, Kjell Eikland, Peter Notebaert", 667 "http://lpsolve.sourceforge.net/"); 668 // license: LGPL 669 670 // OpenEXR copyrights 671 AddCopyrightEntry("OpenEXR", 672 "Copyright " B_UTF8_COPYRIGHT " 2002-2005 Industrial Light & Magic, " 673 "a division of Lucas Digital Ltd. LLC."); 674 675 // Bullet copyrights 676 AddCopyrightEntry("Bullet", 677 "Copyright " B_UTF8_COPYRIGHT " 2003-2008 Erwin Coumans", 678 "http://www.bulletphysics.com"); 679 680 // atftp copyrights 681 AddCopyrightEntry("atftp", 682 "Copyright " B_UTF8_COPYRIGHT " 2000 Jean-Pierre Lefebvre and Remi " 683 "Lefebvre"); 684 685 // Netcat copyrights 686 AddCopyrightEntry("Netcat", 687 "Copyright " B_UTF8_COPYRIGHT " 1996 Hobbit"); 688 689 // acpica copyrights 690 AddCopyrightEntry("acpica", 691 "Copyright " B_UTF8_COPYRIGHT " 1999-2006 Intel Corp."); 692 693 // unrar copyrights 694 AddCopyrightEntry("unrar", 695 "Copyright " B_UTF8_COPYRIGHT " 2002-2008 Alexander L. Roshal. " 696 "All rights reserved.", 697 "http://www.rarlab.com"); 698 699 // p7zip copyrights 700 // AddCopyrightEntry("p7zip", 701 // "Copyright " B_UTF8_COPYRIGHT " 2008 Igor Pavlov. " 702 // "All rights reserved."); 703 704 // libpng copyrights 705 AddCopyrightEntry("libpng", 706 "Copyright " B_UTF8_COPYRIGHT " 2004, 2006-2008 Glenn " 707 "Randers-Pehrson."); 708 709 // libprint copyrights 710 AddCopyrightEntry("libprint", 711 "Copyright " B_UTF8_COPYRIGHT " 1999-2000 Y.Takagi. All rights " 712 "reserved."); 713 714 // cortex copyrights 715 AddCopyrightEntry("Cortex", 716 "Copyright " B_UTF8_COPYRIGHT " 1999-2000 Eric Moon."); 717 718 // FluidSynth copyrights 719 AddCopyrightEntry("FluidSynth", 720 "Copyright " B_UTF8_COPYRIGHT " 2003 Peter Hanappe and others."); 721 722 // CannaIM copyrights 723 AddCopyrightEntry("CannaIM", 724 "Copyright " B_UTF8_COPYRIGHT " 1999 Masao Kawamura."); 725 726 // libxml2, libxslt, libexslt copyrights 727 AddCopyrightEntry("libxml2, libxslt", 728 "Copyright " B_UTF8_COPYRIGHT " 1998-2003 Daniel Veillard. " 729 "All rights reserved."); 730 731 AddCopyrightEntry("libexslt", 732 "Copyright " B_UTF8_COPYRIGHT " 2001-2002 Thomas Broyer, Charlie " 733 "Bozeman and Daniel Veillard. All rights reserved."); 734 735 // Xiph.org Foundation copyrights 736 AddCopyrightEntry("Xiph.org Foundation", 737 "libvorbis, libogg, libtheora, libspeex" 738 "Copyright " B_UTF8_COPYRIGHT " 1994-2008 Xiph.Org. " 739 "All rights reserved.", 740 "http://www.xiph.org"); 741 742 // The Tcpdump Group 743 AddCopyrightEntry("The Tcpdump Group", 744 "tcpdump, libpcap", 745 "http://www.tcpdump.org"); 746 747 // Matroska 748 AddCopyrightEntry("libmatroska", 749 "Copyright " B_UTF8_COPYRIGHT " 2002-2003 Steve Lhomme. " 750 "All rights reserved.", 751 "http://www.matroska.org"); 752 753 // BColorQuantizer (originally CQuantizer code) 754 AddCopyrightEntry("CQuantizer", 755 "Copyright " B_UTF8_COPYRIGHT " 1996-1997 Jeff Prosise. " 756 "All rights reserved."); 757 758 // OpenSound 759 // AddCopyrightEntry("OpenSound", 760 // "Copyright " B_UTF8_COPYRIGHT " 1996-2008 4Front Technologies ", 761 // "http://www.opensound.com"); 762 // BSD license 763 764 #ifdef __INTEL__ 765 // Udis86 copyrights 766 AddCopyrightEntry("Udis86", 767 "Copyright " B_UTF8_COPYRIGHT " 2002, 2003, 2004 Vivek Mohan. " 768 "All rights reserved.", 769 "http://udis86.sourceforge.net"); 770 #endif 771 772 _AddCopyrightsFromAttribute(); 773 774 // Build a list of installed applications and show their 775 // long version info. Well-behaved apps usually give 776 // copyright info there. 777 778 font.SetSize(be_bold_font->Size() + 4); 779 font.SetFace(B_BOLD_FACE); 780 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen); 781 fCreditsView->Insert("\nInstalled applications\n\n"); 782 783 BVolume bootVolume; 784 BVolumeRoster().GetBootVolume(&bootVolume); 785 fAppsQuery.SetVolume(&bootVolume); 786 if (fAppsQuery.SetPredicate( 787 "((BEOS:APP_SIG==\"**\")&&(name!=\"*.so\")&&(name!=\"*.rsrc\")&&" 788 "(BEOS:TYPE==\"application/x-vnd.Be-elfexecutable\"))") >= B_OK) { 789 fAppsQuery.Fetch(); 790 } 791 } 792 793 794 AboutView::~AboutView(void) 795 { 796 delete fScrollRunner; 797 } 798 799 800 void 801 AboutView::AttachedToWindow(void) 802 { 803 BView::AttachedToWindow(); 804 Window()->SetPulseRate(500000); 805 SetEventMask(B_POINTER_EVENTS); 806 } 807 808 809 void 810 AboutView::MouseDown(BPoint pt) 811 { 812 BRect r(92, 26, 105, 31); 813 if (r.Contains(pt)) { 814 printf("Easter Egg\n"); 815 PickRandomHaiku(); 816 } 817 818 if (Bounds().Contains(pt)) { 819 fLastActionTime = system_time(); 820 delete fScrollRunner; 821 fScrollRunner = NULL; 822 } 823 } 824 825 826 void 827 AboutView::FrameResized(float width, float height) 828 { 829 BRect r = fCreditsView->Bounds(); 830 r.OffsetTo(B_ORIGIN); 831 r.InsetBy(3, 3); 832 fCreditsView->SetTextRect(r); 833 } 834 835 836 void 837 AboutView::Draw(BRect update) 838 { 839 if (fLogo) 840 DrawBitmap(fLogo, fDrawPoint); 841 } 842 843 844 void 845 AboutView::Pulse(void) 846 { 847 char string[255]; 848 system_info info; 849 get_system_info(&info); 850 fUptimeView->SetText(UptimeToString(string, sizeof(string))); 851 fMemView->SetText(MemUsageToString(string, sizeof(string), &info)); 852 853 if (fScrollRunner == NULL && (system_time() > fLastActionTime + 10000000)) { 854 BMessage message(SCROLL_CREDITS_VIEW); 855 //fScrollRunner = new BMessageRunner(this, &message, 300000, -1); 856 } 857 } 858 859 860 void 861 AboutView::MessageReceived(BMessage *msg) 862 { 863 switch (msg->what) { 864 case SCROLL_CREDITS_VIEW: 865 { 866 BScrollBar *scrollBar = fCreditsView->ScrollBar(B_VERTICAL); 867 if (scrollBar == NULL) 868 break; 869 float max, min; 870 scrollBar->GetRange(&min, &max); 871 if (scrollBar->Value() < max) 872 fCreditsView->ScrollBy(0, 5); 873 874 break; 875 } 876 877 case READ_APP_QUERY_ENT: 878 { 879 BEntry ent; 880 if (fAppsQuery.GetNextEntry(&ent) < B_OK) { 881 fAppsQuery.Clear(); 882 fCreditsView->MakeSelectable(true); 883 break; 884 } 885 BFile file; 886 BPath path; 887 if (ent.Exists() && 888 ent.GetPath(&path) >= B_OK && 889 file.SetTo(&ent, B_READ_ONLY) >= B_OK) { 890 /* filter only apps */ 891 if (strncmp(path.Path(), "/boot/apps", 10) == 0) { 892 BAppFileInfo appFileInfo(&file); 893 uint32 flags; 894 version_info version; 895 if (appFileInfo.InitCheck() >= B_OK && 896 appFileInfo.GetAppFlags(&flags) >= B_OK && 897 appFileInfo.GetVersionInfo(&version, 898 B_APP_VERSION_KIND) >= B_OK) { 899 //printf("AppFileInfo for %s :\n", path.Path()); 900 //printf("flags: %08x\n", flags); 901 BString name; 902 BString info; 903 name << path.Leaf(); 904 if (strlen(version.short_info) && 905 strcmp(version.short_info, path.Leaf())) 906 name << " (" << version.short_info << ")"; 907 /* 908 info << "\tVersion: "; 909 info << version.major << "."; 910 info << version.middle << "."; 911 info << version.minor; 912 char varieties[] = "dabgmf"; 913 if (version.variety > B_FINAL_VERSION) 914 info << "?"; 915 else 916 info << varieties[version.variety]; 917 info << version.internal; 918 info << "\n"; 919 */ 920 info << version.long_info; 921 AddCopyrightEntry(name.String(), info.String()); 922 923 } 924 } 925 } 926 // note for self: read next entry :) 927 BMessage m(READ_APP_QUERY_ENT); 928 BMessenger(this).SendMessage(&m); 929 break; 930 } 931 932 default: 933 BView::MessageReceived(msg); 934 break; 935 } 936 } 937 938 939 void 940 AboutView::AddCopyrightEntry(const char *name, const char *text, 941 const char *url) 942 { 943 AddCopyrightEntry(name, text, NULL, url); 944 } 945 946 947 void 948 AboutView::AddCopyrightEntry(const char *name, const char *text, 949 const Licenses& licenses, const char *url) 950 { 951 BFont font(be_bold_font); 952 //font.SetSize(be_bold_font->Size()); 953 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 954 955 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuYellow); 956 fCreditsView->Insert(name); 957 fCreditsView->Insert("\n"); 958 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey); 959 fCreditsView->Insert(text); 960 fCreditsView->Insert("\n"); 961 962 if (licenses.CountLicenses() > 0) { 963 if (licenses.CountLicenses() > 1) 964 fCreditsView->Insert("Licenses: "); 965 else 966 fCreditsView->Insert("License: "); 967 968 for (int32 i = 0; i < licenses.CountLicenses(); i++) { 969 const char* license = licenses.LicenseAt(i); 970 BString licensePath("/etc/licenses/"); 971 licensePath += license; 972 973 if (i > 0) 974 fCreditsView->Insert(", "); 975 976 fCreditsView->InsertHyperText(license, 977 new OpenFileAction(licensePath)); 978 } 979 980 fCreditsView->Insert("\n"); 981 } 982 983 if (url) { 984 fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kLinkBlue); 985 fCreditsView->InsertHyperText(url, new URLAction(url)); 986 fCreditsView->Insert("\n"); 987 } 988 fCreditsView->Insert("\n"); 989 } 990 991 992 void 993 AboutView::AddCopyrightEntry(const BMessage& packageDescription) 994 { 995 const char* package; 996 const char* copyright; 997 const char* url; 998 999 // package and copyright are mandatory 1000 if (packageDescription.FindString("Package", &package) != B_OK 1001 || packageDescription.FindString("Copyright", ©right) != B_OK) { 1002 return; 1003 } 1004 1005 // URL is optional 1006 if (packageDescription.FindString("URL", &url) != B_OK) 1007 url = NULL; 1008 1009 BString copyrightLine("Copyright " B_UTF8_COPYRIGHT " "); 1010 copyrightLine += copyright; 1011 1012 AddCopyrightEntry(package, copyrightLine.String(), packageDescription, url); 1013 } 1014 1015 1016 void 1017 AboutView::PickRandomHaiku() 1018 { 1019 BFile fortunes( 1020 #ifdef __HAIKU__ 1021 "/etc/fortunes/Haiku", 1022 #else 1023 "data/etc/fortunes/Haiku", 1024 #endif 1025 B_READ_ONLY); 1026 struct stat st; 1027 if (fortunes.InitCheck() < B_OK) 1028 return; 1029 if (fortunes.GetStat(&st) < B_OK) 1030 return; 1031 char *buff = (char *)malloc((size_t)st.st_size + 1); 1032 if (!buff) 1033 return; 1034 buff[(size_t)st.st_size] = '\0'; 1035 BList haikuList; 1036 if (fortunes.Read(buff, (size_t)st.st_size) == (ssize_t)st.st_size) { 1037 char *p = buff; 1038 while (p && *p) { 1039 char *e = strchr(p, '%'); 1040 BString *s = new BString(p, e ? (e - p) : -1); 1041 haikuList.AddItem(s); 1042 p = e; 1043 if (p && (*p == '%')) 1044 p++; 1045 if (p && (*p == '\n')) 1046 p++; 1047 } 1048 } 1049 free(buff); 1050 if (haikuList.CountItems() < 1) 1051 return; 1052 BString *s = (BString *)haikuList.ItemAt(rand() % haikuList.CountItems()); 1053 BFont font(be_bold_font); 1054 font.SetSize(be_bold_font->Size()); 1055 font.SetFace(B_BOLD_FACE | B_ITALIC_FACE); 1056 fCreditsView->SelectAll(); 1057 fCreditsView->Delete(); 1058 fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kDarkGrey); 1059 fCreditsView->Insert(s->String()); 1060 fCreditsView->Insert("\n"); 1061 while ((s = (BString *)haikuList.RemoveItem((int32)0))) { 1062 delete s; 1063 } 1064 } 1065 1066 1067 void 1068 AboutView::_AddCopyrightsFromAttribute() 1069 { 1070 // open the app executable file 1071 char appPath[B_PATH_NAME_LENGTH]; 1072 int appFD; 1073 if (BPrivate::get_app_path(appPath) != B_OK 1074 || (appFD = open(appPath, O_RDONLY)) < 0) { 1075 return; 1076 } 1077 1078 // open the attribute 1079 int attrFD = fs_open_attr(appFD, "COPYRIGHTS", B_STRING_TYPE, O_RDONLY); 1080 close(appFD); 1081 if (attrFD < 0) 1082 return; 1083 1084 // attach it to a FILE 1085 FILE* attrFile = fdopen(attrFD, "r"); 1086 if (attrFile == NULL) { 1087 close(attrFD); 1088 return; 1089 } 1090 CObjectDeleter<FILE, int> _(attrFile, fclose); 1091 1092 // read and parse the copyrights 1093 BMessage package; 1094 BString fieldName; 1095 BString fieldValue; 1096 char lineBuffer[LINE_MAX]; 1097 while (char* line = fgets(lineBuffer, sizeof(lineBuffer), attrFile)) { 1098 // chop off line break 1099 size_t lineLen = strlen(line); 1100 if (lineLen > 0 && line[lineLen - 1] == '\n') 1101 line[--lineLen] = '\0'; 1102 1103 // flush previous field, if a new field begins, otherwise append 1104 if (lineLen == 0 || !isspace(line[0])) { 1105 // new field -- flush the previous one 1106 if (fieldName.Length() > 0) { 1107 fieldValue = trim_string(fieldValue.String(), 1108 fieldValue.Length()); 1109 package.AddString(fieldName.String(), fieldValue); 1110 fieldName = ""; 1111 } 1112 } else if (fieldName.Length() > 0) { 1113 // append to current field 1114 fieldValue += line; 1115 continue; 1116 } else { 1117 // bogus line -- ignore 1118 continue; 1119 } 1120 1121 if (lineLen == 0) 1122 continue; 1123 1124 // parse new field 1125 char* colon = strchr(line, ':'); 1126 if (colon == NULL) { 1127 // bogus line -- ignore 1128 continue; 1129 } 1130 1131 fieldName.SetTo(line, colon - line); 1132 fieldName = trim_string(line, colon - line); 1133 if (fieldName.Length() == 0) { 1134 // invalid field name 1135 continue; 1136 } 1137 1138 fieldValue = colon + 1; 1139 1140 if (fieldName == "Package") { 1141 // flush the current package 1142 AddCopyrightEntry(package); 1143 package.MakeEmpty(); 1144 } 1145 } 1146 1147 // flush current package 1148 AddCopyrightEntry(package); 1149 } 1150 1151 1152 // #pragma mark - 1153 1154 1155 static const char * 1156 MemUsageToString(char string[], size_t size, system_info *info) 1157 { 1158 snprintf(string, size, "%d MB total, %d MB used (%d%%)", 1159 int(info->max_pages / 256.0f + 0.5f), 1160 int(info->used_pages / 256.0f + 0.5f), 1161 int(100 * info->used_pages / info->max_pages)); 1162 1163 return string; 1164 } 1165 1166 1167 static const char * 1168 UptimeToString(char string[], size_t size) 1169 { 1170 int64 days, hours, minutes, seconds, remainder; 1171 int64 systime = system_time(); 1172 1173 days = systime / 86400000000LL; 1174 remainder = systime % 86400000000LL; 1175 1176 hours = remainder / 3600000000LL; 1177 remainder = remainder % 3600000000LL; 1178 1179 minutes = remainder / 60000000; 1180 remainder = remainder % 60000000; 1181 1182 seconds = remainder / 1000000; 1183 1184 char *str = string; 1185 if (days) { 1186 str += snprintf(str, size, "%lld day%s",days, days > 1 ? "s" : ""); 1187 } 1188 if (hours) { 1189 str += snprintf(str, size - strlen(string), "%s%lld hour%s", 1190 str != string ? ", " : "", 1191 hours, hours > 1 ? "s" : ""); 1192 } 1193 if (minutes) { 1194 str += snprintf(str, size - strlen(string), "%s%lld minute%s", 1195 str != string ? ", " : "", 1196 minutes, minutes > 1 ? "s" : ""); 1197 } 1198 1199 if (seconds || str == string) { 1200 // Haiku would be well-known to boot very fast. 1201 // Let's be ready to handle below minute uptime, zero second included ;-) 1202 str += snprintf(str, size - strlen(string), "%s%lld second%s", 1203 str != string ? ", " : "", 1204 seconds, seconds > 1 ? "s" : ""); 1205 } 1206 1207 return string; 1208 } 1209 1210 1211 int 1212 main() 1213 { 1214 AboutApp app; 1215 app.Run(); 1216 return 0; 1217 } 1218 1219