xref: /haiku/src/apps/aboutsystem/AboutSystem.cpp (revision 546208a53940a26c6379c48a7854ade1a8250fc5)
1 /*
2  * Copyright 2005-2011, Haiku, Inc.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		René Gollent
8  *		Wim van der Meer <WPJvanderMeer@gmail.com>
9  */
10 
11 
12 #include <ctype.h>
13 #include <stdio.h>
14 #include <time.h>
15 #include <unistd.h>
16 
17 #include <algorithm>
18 #include <map>
19 #include <string>
20 
21 #include <AppFileInfo.h>
22 #include <Application.h>
23 #include <Bitmap.h>
24 #include <DurationFormat.h>
25 #include <File.h>
26 #include <FindDirectory.h>
27 #include <Font.h>
28 #include <fs_attr.h>
29 #include <LayoutBuilder.h>
30 #include <MessageRunner.h>
31 #include <Messenger.h>
32 #include <OS.h>
33 #include <Path.h>
34 #include <Resources.h>
35 #include <Screen.h>
36 #include <ScrollView.h>
37 #include <String.h>
38 #include <StringView.h>
39 #include <TranslationUtils.h>
40 #include <TranslatorFormats.h>
41 #include <View.h>
42 #include <Volume.h>
43 #include <VolumeRoster.h>
44 #include <Window.h>
45 
46 #include <AppMisc.h>
47 #include <AutoDeleter.h>
48 #include <cpu_type.h>
49 #include <system_revision.h>
50 
51 #include <Catalog.h>
52 #include <Language.h>
53 #include <Locale.h>
54 #include <LocaleRoster.h>
55 
56 #include "HyperTextActions.h"
57 #include "HyperTextView.h"
58 #include "Utilities.h"
59 
60 
61 #ifndef LINE_MAX
62 #define LINE_MAX 2048
63 #endif
64 
65 #define SCROLL_CREDITS_VIEW 'mviv'
66 
67 
68 static const char* UptimeToString(char string[], size_t size);
69 static const char* MemSizeToString(char string[], size_t size,
70 	system_info* info);
71 static const char* MemUsageToString(char string[], size_t size,
72 	system_info* info);
73 
74 
75 static const rgb_color kDarkGrey = { 100, 100, 100, 255 };
76 static const rgb_color kHaikuGreen = { 42, 131, 36, 255 };
77 static const rgb_color kHaikuOrange = { 255, 69, 0, 255 };
78 static const rgb_color kHaikuYellow = { 255, 176, 0, 255 };
79 static const rgb_color kLinkBlue = { 80, 80, 200, 255 };
80 static const rgb_color kBeOSBlue = { 0, 0, 200, 255 };
81 static const rgb_color kBeOSRed = { 200, 0, 0, 255 };
82 
83 typedef struct
84 {
85 	const char* languageCode;
86 	const char* names;
87 } Translation;
88 
89 static const Translation gTranslations[] =
90 {
91 	{ "ar",
92 		"Khaled Berraoui - khallebal\n"
93 		"Kendhia\n"
94 	},
95 	{ "be",
96 		"Michael Bulash\n"
97 	},
98 	{ "bg",
99 		"Ognyan Valeri Angelov\n"
100 		"cssvb94\n"
101 	},
102 	{ "cs",
103 		"Pavel Drotár\n"
104 		"Matěj Kocián\n"
105 	},
106 	{ "da",
107 		"Brian Matzon\n"
108 	},
109 	{ "de",
110 		"Colin Günther\n"
111 		"Mirko Israel\n"
112 		"leszek\n"
113 		"Christian Morgenroth\n"
114 		"Aleksas Pantechovskis\n"
115 		"Joachim Seemer - Humdinger\n"
116 		"Matthias Spreiter\n"
117 		"Ivaylo Tsenkov\n"
118 		"svend\n"
119 	},
120 	{ "el",
121 		"Γιάννης Κωνσταντινίδης (Giannis Konstantinidis) - giannisk\n"
122 		"Βαγγέλης Μαμαλάκης (Vaggelis Mamalakis)\n"
123 		"Άλεξ-Π. Νάτσιος (Alex-P. Natsios) - Drakevr\n"
124 	},
125 	{ "eo",
126 		"Travis D. Reed - Dancxjo\n"
127 	},
128 	{ "es",
129 		"Pedro Arregui\n"
130 		"Zola Bridges\n"
131 		"Nicolás C - CapitanPico\n"
132 		"Oscar Carballal - oscarcp\n"
133 		"Miguel Zúñiga González - miguel~1.mx\n"
134 		"Luis Gustavo Lira\n"
135 		"Victor Madariaga\n"
136 		"César Ortiz Pantoja - ccortiz\n"
137 	},
138 	{ "fi",
139 		"Jorma Karvonen - Karvjorm\n"
140 		"Jaakko Leikas - Garjala\n"
141 		"Slavi Stefanov Sotirov\n"
142 	},
143 	{ "fr",
144 		"Jean-Loïc Charroud\n"
145 		"Adrien Destugues - PulkoMandy\n"
146 		"Florent Revest\n"
147 		"Harsh Vardhan\n"
148 	},
149 	{ "hi",
150 		"Abhishek Arora\n"
151 		"Dhruwat Bhagat\n"
152 		"Jayneil Dalal\n"
153 		"Atharva Lath\n"
154 	},
155 	{ "hr",
156 		"Ivica Koli\n"
157 		"Zlatko Sehanović\n"
158 		"zvacet\n"
159 	},
160 	{ "hu",
161 		"Kálmán Kéménczy\n"
162 		"Zoltán Mizsei - miqlas\n"
163 		"Bence Nagy\n"
164 		"Zoltán Szabó - Bird\n"
165 	},
166 	{ "it",
167 		"Andrea Bernardi\n"
168 		"Dario Casalinuovo\n"
169 		"Francesco Franchina\n"
170 		"Lorenzo Frezza\n"
171 		"Mometto Nicola\n"
172 		"Michael Peppers\n"
173 	},
174 	{ "ja",
175 		"Satoshi Eguchi\n"
176 		"Shota Fukumori\n"
177 		"hiromu1996\n"
178 		"Hironori Ichimiya\n"
179 		"Jorge G. Mare - Koki\n"
180 		"Takashi Murai\n"
181 		"nolze\n"
182 		"SHINTA\n"
183 		"thebowseat\n"
184 		"Hiroyuki Tsutsumi\n"
185 		"Hiromu Yakura\n"
186 		"The JPBE.net user group\n"
187 	},
188 	{ "lt",
189 		"Algirdas Buckus\n"
190 		"Simonas Kazlauskas\n"
191 		"Rimas Kudelis\n"
192 	},
193 	{ "nl",
194 		"Floris Kint\n"
195 		"Meanwhile\n"
196 	},
197 	{ "pl",
198 		"Szymon Barczak\n"
199 		"Grzegorz Dąbrowski\n"
200 		"Hubert Hareńczyk\n"
201 		"Krzysztof Miemiec\n"
202 		"Artur Wyszyński\n"
203 	},
204 	{ "pt",
205 		"Marcos Alves - Xeon3D\n"
206 		"Vasco Costa - gluon\n"
207 		"Michael Vinícius de Oliveira - michaelvo\n"
208 	},
209 	{ "ro",
210 		"Victor Carbune\n"
211 		"Silviu Dureanu\n"
212 		"Alexsander Krustev\n"
213 		"Danca Monica\n"
214 		"Florentina Mușat\n"
215 		"Dragos Serban\n"
216 		"Hedeș Cristian Teodor\n"
217 		"Ivaylo Tsenkov\n"
218 		"Călinescu Valentin\n"
219 	},
220 	{ "ru",
221 		"Tatyana Fursic - iceid\n"
222 		"StoroZ Gneva\n"
223 		"Rodastahm Islamov - RISC\n"
224 		"Eugene Katashov - mrNoisy\n"
225 		"Reznikov Sergei - Diver\n"
226 		"Michael Smirnov\n"
227 		"Vladimir Vasilenko\n"
228 	},
229 	{ "sk",
230 		"Ivan Masár\n"
231 	},
232 	{ "sr",
233 		"Nikola Miljković\n"
234 	},
235 	{ "sv",
236 		"Patrik Gissberg\n"
237 		"Johan Holmberg\n"
238 		"Jimmy Olsson - phalax\n"
239 		"Jonas Sundström\n"
240 		"Victor Widell\n"
241 	},
242 	{ "tr",
243 		"Hüseyin Aksu\n"
244 		"Halil İbrahim Azak\n"
245 		"Aras Ergus\n"
246 		"Enes Burhan Kuran\n"
247 		"Ali Rıza Nazlı\n"
248 	},
249 	{ "uk",
250 		"Mariya Pilipchuk\n"
251 		"Alex Rudyk - totish\n"
252 		"Oleg Varunok\n"
253 	},
254 	{ "zh",
255 		"Pengfei Han - kurain\n"
256 	}
257 };
258 
259 #define kNumberOfTranslations (sizeof(gTranslations) / sizeof(Translation))
260 
261 
262 static int
263 TranslationComparator(const void* left, const void* right)
264 {
265 	const Translation* leftTranslation = *(const Translation**)left;
266 	const Translation* rightTranslation = *(const Translation**)right;
267 
268 	BLanguage* language;
269 	BString leftName;
270 	if (BLocaleRoster::Default()->GetLanguage(leftTranslation->languageCode,
271 			&language) == B_OK) {
272 		language->GetName(leftName);
273 		delete language;
274 	} else
275 		leftName = leftTranslation->languageCode;
276 
277 	BString rightName;
278 	if (BLocaleRoster::Default()->GetLanguage(rightTranslation->languageCode,
279 			&language) == B_OK) {
280 		language->GetName(rightName);
281 		delete language;
282 	} else
283 		rightName = rightTranslation->languageCode;
284 
285 	BCollator collator;
286 	BLocale::Default()->GetCollator(&collator);
287 	return collator.Compare(leftName.String(), rightName.String());
288 }
289 
290 
291 class AboutApp : public BApplication {
292 public:
293 							AboutApp();
294 };
295 
296 
297 class AboutWindow : public BWindow {
298 public:
299 							AboutWindow();
300 
301 	virtual	bool			QuitRequested();
302 };
303 
304 
305 class LogoView : public BView {
306 public:
307 							LogoView();
308 	virtual					~LogoView();
309 
310 	virtual	BSize			MinSize();
311 	virtual	BSize			MaxSize();
312 
313 	virtual void			Draw(BRect updateRect);
314 
315 private:
316 			BBitmap*		fLogo;
317 };
318 
319 
320 class CropView : public BView {
321 public:
322 							CropView(BView* target, int32 left, int32 top,
323 								int32 right, int32 bottom);
324 	virtual					~CropView();
325 
326 	virtual	BSize			MinSize();
327 	virtual	BSize			MaxSize();
328 
329 	virtual void			DoLayout();
330 
331 private:
332 			BView*			fTarget;
333 			int32			fCropLeft;
334 			int32			fCropTop;
335 			int32			fCropRight;
336 			int32			fCropBottom;
337 };
338 
339 
340 class AboutView : public BView {
341 public:
342 							AboutView();
343 							~AboutView();
344 
345 	virtual void			AttachedToWindow();
346 	virtual void			Pulse();
347 
348 	virtual void			MessageReceived(BMessage* msg);
349 	virtual void			MouseDown(BPoint point);
350 
351 			void			AddCopyrightEntry(const char* name,
352 								const char* text,
353 								const StringVector& licenses,
354 								const StringVector& sources,
355 								const char* url);
356 			void			AddCopyrightEntry(const char* name,
357 								const char* text, const char* url = NULL);
358 			void			PickRandomHaiku();
359 
360 
361 private:
362 	typedef std::map<std::string, PackageCredit*> PackageCreditMap;
363 
364 private:
365 			BView*			_CreateLabel(const char* name, const char* label);
366 			BView*			_CreateCreditsView();
367 			status_t		_GetLicensePath(const char* license,
368 								BPath& path);
369 			void			_AddCopyrightsFromAttribute();
370 			void			_AddPackageCredit(const PackageCredit& package);
371 			void			_AddPackageCreditEntries();
372 
373 			BStringView*	fMemView;
374 			BTextView*		fUptimeView;
375 			BView*			fInfoView;
376 			HyperTextView*	fCreditsView;
377 
378 			BBitmap*		fLogo;
379 
380 			bigtime_t		fLastActionTime;
381 			BMessageRunner*	fScrollRunner;
382 			PackageCreditMap fPackageCredits;
383 };
384 
385 
386 //	#pragma mark -
387 
388 
389 AboutApp::AboutApp()
390 	: BApplication("application/x-vnd.Haiku-About")
391 {
392 	B_TRANSLATE_MARK_SYSTEM_NAME_VOID("AboutSystem");
393 
394 	AboutWindow *window = new(std::nothrow) AboutWindow();
395 	if (window)
396 		window->Show();
397 }
398 
399 
400 //	#pragma mark -
401 
402 
403 #undef B_TRANSLATION_CONTEXT
404 #define B_TRANSLATION_CONTEXT "AboutWindow"
405 
406 AboutWindow::AboutWindow()
407 	: BWindow(BRect(0, 0, 500, 300), B_TRANSLATE("About this system"),
408 		B_TITLED_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_ZOOMABLE)
409 {
410 	SetLayout(new BGroupLayout(B_VERTICAL));
411 	AddChild(new AboutView());
412 
413 	// Make sure we take the minimal window size into account when centering
414 	BSize size = GetLayout()->MinSize();
415 	ResizeTo(max_c(size.width, Bounds().Width()),
416 		max_c(size.height, Bounds().Height()));
417 
418 	CenterOnScreen();
419 }
420 
421 
422 bool
423 AboutWindow::QuitRequested()
424 {
425 	be_app->PostMessage(B_QUIT_REQUESTED);
426 	return true;
427 }
428 
429 
430 //	#pragma mark - LogoView
431 
432 
433 LogoView::LogoView()
434 	: BView("logo", B_WILL_DRAW)
435 {
436 	fLogo = BTranslationUtils::GetBitmap(B_PNG_FORMAT, "logo.png");
437 	SetViewColor(255, 255, 255);
438 }
439 
440 
441 LogoView::~LogoView()
442 {
443 	delete fLogo;
444 }
445 
446 
447 BSize
448 LogoView::MinSize()
449 {
450 	if (fLogo == NULL)
451 		return BSize(0, 0);
452 
453 	return BSize(fLogo->Bounds().Width(), fLogo->Bounds().Height());
454 }
455 
456 
457 BSize
458 LogoView::MaxSize()
459 {
460 	if (fLogo == NULL)
461 		return BSize(0, 0);
462 
463 	return BSize(B_SIZE_UNLIMITED, fLogo->Bounds().Height());
464 }
465 
466 
467 void
468 LogoView::Draw(BRect updateRect)
469 {
470 	if (fLogo != NULL) {
471 		DrawBitmap(fLogo,
472 			BPoint((Bounds().Width() - fLogo->Bounds().Width()) / 2, 0));
473 	}
474 }
475 
476 
477 //	#pragma mark - CropView
478 
479 
480 CropView::CropView(BView* target, int32 left, int32 top, int32 right,
481 		int32 bottom)
482 	: BView("crop view", 0),
483 	fTarget(target),
484 	fCropLeft(left),
485 	fCropTop(top),
486 	fCropRight(right),
487 	fCropBottom(bottom)
488 {
489 	AddChild(target);
490 }
491 
492 
493 CropView::~CropView()
494 {
495 }
496 
497 
498 BSize
499 CropView::MinSize()
500 {
501 	if (fTarget == NULL)
502 		return BSize();
503 
504 	BSize size = fTarget->MinSize();
505 	if (size.width != B_SIZE_UNSET)
506 		size.width -= fCropLeft + fCropRight;
507 	if (size.height != B_SIZE_UNSET)
508 		size.height -= fCropTop + fCropBottom;
509 
510 	return size;
511 }
512 
513 
514 BSize
515 CropView::MaxSize()
516 {
517 	if (fTarget == NULL)
518 		return BSize();
519 
520 	BSize size = fTarget->MaxSize();
521 	if (size.width != B_SIZE_UNSET)
522 		size.width -= fCropLeft + fCropRight;
523 	if (size.height != B_SIZE_UNSET)
524 		size.height -= fCropTop + fCropBottom;
525 
526 	return size;
527 }
528 
529 
530 void
531 CropView::DoLayout()
532 {
533 	BView::DoLayout();
534 
535 	if (fTarget == NULL)
536 		return;
537 
538 	fTarget->MoveTo(-fCropLeft, -fCropTop);
539 	fTarget->ResizeTo(Bounds().Width() + fCropLeft + fCropRight,
540 		Bounds().Height() + fCropTop + fCropBottom);
541 }
542 
543 
544 //	#pragma mark - AboutView
545 
546 #undef B_TRANSLATION_CONTEXT
547 #define B_TRANSLATION_CONTEXT "AboutView"
548 
549 AboutView::AboutView()
550 	: BView("aboutview", B_WILL_DRAW | B_PULSE_NEEDED),
551 	fLastActionTime(system_time()),
552 	fScrollRunner(NULL)
553 {
554 	// Begin Construction of System Information controls
555 
556 	system_info systemInfo;
557 	get_system_info(&systemInfo);
558 
559 	// Create all the various labels for system infomation
560 
561 	// OS Version
562 
563 	char string[1024];
564 	strlcpy(string, B_TRANSLATE("Unknown"), sizeof(string));
565 
566 	// the version is stored in the BEOS:APP_VERSION attribute of libbe.so
567 	BPath path;
568 	if (find_directory(B_BEOS_LIB_DIRECTORY, &path) == B_OK) {
569 		path.Append("libbe.so");
570 
571 		BAppFileInfo appFileInfo;
572 		version_info versionInfo;
573 		BFile file;
574 		if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK
575 			&& appFileInfo.SetTo(&file) == B_OK
576 			&& appFileInfo.GetVersionInfo(&versionInfo,
577 				B_APP_VERSION_KIND) == B_OK
578 			&& versionInfo.short_info[0] != '\0')
579 			strlcpy(string, versionInfo.short_info, sizeof(string));
580 	}
581 
582 	// Add system revision
583 	const char* haikuRevision = __get_haiku_revision();
584 	if (haikuRevision != NULL) {
585 		strlcat(string, " (", sizeof(string));
586 		strlcat(string, B_TRANSLATE("Revision"), sizeof(string));
587 		strlcat(string, " ", sizeof(string));
588 		strlcat(string, haikuRevision, sizeof(string));
589 		strlcat(string, ")", sizeof(string));
590 	}
591 
592 	BStringView* versionView = new BStringView("ostext", string);
593 	versionView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
594 		B_ALIGN_VERTICAL_UNSET));
595 
596 	// GCC version
597 	BEntry gccFourHybrid("/boot/system/lib/gcc2/libstdc++.r4.so");
598 	BEntry gccTwoHybrid("/boot/system/lib/gcc4/libsupc++.so");
599 	bool isHybrid = gccFourHybrid.Exists() || gccTwoHybrid.Exists();
600 
601 	if (isHybrid) {
602 		snprintf(string, sizeof(string), B_TRANSLATE("GCC %d Hybrid"),
603 			__GNUC__);
604 	} else
605 		snprintf(string, sizeof(string), "GCC %d", __GNUC__);
606 
607 	BStringView* gccView = new BStringView("gcctext", string);
608 	gccView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
609 		B_ALIGN_VERTICAL_UNSET));
610 
611 #if __GNUC__ == 2
612 	if (isHybrid) {
613 		// do now show the GCC version if it's the default
614 		gccView->Hide();
615 	}
616 #endif
617 
618 	// CPU count, type and clock speed
619 	char processorLabel[256];
620 	if (systemInfo.cpu_count > 1) {
621 		snprintf(processorLabel, sizeof(processorLabel),
622 			B_TRANSLATE("%ld Processors:"), systemInfo.cpu_count);
623 	} else
624 		strlcpy(processorLabel, B_TRANSLATE("Processor:"),
625 			sizeof(processorLabel));
626 
627 	BString cpuType;
628 	cpuType << get_cpu_vendor_string(systemInfo.cpu_type)
629 		<< " " << get_cpu_model_string(&systemInfo);
630 
631 	BStringView* cpuView = new BStringView("cputext", cpuType.String());
632 	cpuView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
633 		B_ALIGN_VERTICAL_UNSET));
634 
635 	int32 clockSpeed = get_rounded_cpu_speed();
636 	if (clockSpeed < 1000)
637 		snprintf(string, sizeof(string), B_TRANSLATE("%ld MHz"), clockSpeed);
638 	else
639 		snprintf(string, sizeof(string), B_TRANSLATE("%.2f GHz"),
640 			clockSpeed / 1000.0f);
641 
642 	BStringView* frequencyView = new BStringView("frequencytext", string);
643 	frequencyView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
644 		B_ALIGN_VERTICAL_UNSET));
645 
646 	// RAM
647 	BStringView *memSizeView = new BStringView("ramsizetext",
648 		MemSizeToString(string, sizeof(string), &systemInfo));
649 	memSizeView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
650 		B_ALIGN_VERTICAL_UNSET));
651 	fMemView = new BStringView("ramtext",
652 		MemUsageToString(string, sizeof(string), &systemInfo));
653 	fMemView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
654 		B_ALIGN_VERTICAL_UNSET));
655 
656 	// Kernel build time/date
657 	snprintf(string, sizeof(string), "%s %s",
658 		systemInfo.kernel_build_date, systemInfo.kernel_build_time);
659 
660 	BStringView* kernelView = new BStringView("kerneltext", string);
661 	kernelView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
662 		B_ALIGN_VERTICAL_UNSET));
663 
664 	// Uptime
665 	fUptimeView = new BTextView("uptimetext");
666 	fUptimeView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
667 	fUptimeView->MakeEditable(false);
668 	fUptimeView->MakeSelectable(false);
669 	fUptimeView->SetWordWrap(true);
670 
671 	fUptimeView->SetText(UptimeToString(string, sizeof(string)));
672 
673 	const float offset = 5;
674 
675 	SetLayout(new BGroupLayout(B_HORIZONTAL, 0));
676 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
677 
678 	BLayoutBuilder::Group<>((BGroupLayout*)GetLayout())
679 		.AddGroup(B_VERTICAL, 0)
680 			.Add(new LogoView())
681 			.AddGroup(B_VERTICAL, 0)
682 				.Add(_CreateLabel("oslabel", B_TRANSLATE("Version:")))
683 				.Add(versionView)
684 				.Add(gccView)
685 				.AddStrut(offset)
686 				.Add(_CreateLabel("cpulabel", processorLabel))
687 				.Add(cpuView)
688 				.Add(frequencyView)
689 				.AddStrut(offset)
690 				.Add(_CreateLabel("memlabel", B_TRANSLATE("Memory:")))
691 				.Add(memSizeView)
692 				.Add(fMemView)
693 				.AddStrut(offset)
694 				.Add(_CreateLabel("kernellabel", B_TRANSLATE("Kernel:")))
695 				.Add(kernelView)
696 				.AddStrut(offset)
697 				.Add(_CreateLabel("uptimelabel",
698 					B_TRANSLATE("Time running:")))
699 				.Add(fUptimeView)
700 				.SetInsets(5, 5, 5, 5)
701 			.End()
702 			// TODO: investigate: adding this causes the time to be cut
703 			//.AddGlue()
704 		.End()
705 		.Add(_CreateCreditsView());
706 
707 	float min = fMemView->MinSize().width * 1.1f;
708 	fCreditsView->SetExplicitMinSize(BSize(min, min));
709 }
710 
711 
712 AboutView::~AboutView()
713 {
714 	delete fScrollRunner;
715 }
716 
717 
718 void
719 AboutView::AttachedToWindow()
720 {
721 	BView::AttachedToWindow();
722 	Window()->SetPulseRate(500000);
723 	SetEventMask(B_POINTER_EVENTS);
724 }
725 
726 
727 void
728 AboutView::MouseDown(BPoint point)
729 {
730 	BRect r(92, 26, 105, 31);
731 	if (r.Contains(point))
732 		BMessenger(this).SendMessage('eegg');
733 
734 	if (Bounds().Contains(point)) {
735 		fLastActionTime = system_time();
736 		delete fScrollRunner;
737 		fScrollRunner = NULL;
738 	}
739 }
740 
741 
742 void
743 AboutView::Pulse()
744 {
745 	char string[255];
746 	system_info info;
747 	get_system_info(&info);
748 	fUptimeView->SetText(UptimeToString(string, sizeof(string)));
749 	fMemView->SetText(MemUsageToString(string, sizeof(string), &info));
750 
751 	if (fScrollRunner == NULL
752 		&& system_time() > fLastActionTime + 10000000) {
753 		BMessage message(SCROLL_CREDITS_VIEW);
754 		//fScrollRunner = new BMessageRunner(this, &message, 25000, -1);
755 	}
756 }
757 
758 
759 void
760 AboutView::MessageReceived(BMessage* msg)
761 {
762 	switch (msg->what) {
763 		case SCROLL_CREDITS_VIEW:
764 		{
765 			BScrollBar* scrollBar =
766 				fCreditsView->ScrollBar(B_VERTICAL);
767 			if (scrollBar == NULL)
768 				break;
769 			float max, min;
770 			scrollBar->GetRange(&min, &max);
771 			if (scrollBar->Value() < max)
772 				fCreditsView->ScrollBy(0, 1);
773 
774 			break;
775 		}
776 
777 		case 'eegg':
778 		{
779 			printf("Easter egg\n");
780 			PickRandomHaiku();
781 			break;
782 		}
783 
784 		default:
785 			BView::MessageReceived(msg);
786 			break;
787 	}
788 }
789 
790 
791 void
792 AboutView::AddCopyrightEntry(const char* name, const char* text,
793 	const char* url)
794 {
795 	AddCopyrightEntry(name, text, StringVector(), StringVector(), url);
796 }
797 
798 
799 void
800 AboutView::AddCopyrightEntry(const char* name, const char* text,
801 	const StringVector& licenses, const StringVector& sources,
802 	const char* url)
803 {
804 	BFont font(be_bold_font);
805 	//font.SetSize(be_bold_font->Size());
806 	font.SetFace(B_BOLD_FACE | B_ITALIC_FACE);
807 
808 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuYellow);
809 	fCreditsView->Insert(name);
810 	fCreditsView->Insert("\n");
811 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
812 	fCreditsView->Insert(text);
813 	fCreditsView->Insert("\n");
814 
815 	if (licenses.CountStrings() > 0) {
816 		if (licenses.CountStrings() > 1)
817 			fCreditsView->Insert(B_TRANSLATE("Licenses: "));
818 		else
819 			fCreditsView->Insert(B_TRANSLATE("License: "));
820 
821 		for (int32 i = 0; i < licenses.CountStrings(); i++) {
822 			const char* license = licenses.StringAt(i);
823 
824 			if (i > 0)
825 				fCreditsView->Insert(", ");
826 
827 			BString licenseName;
828 			BString licenseURL;
829 			parse_named_url(license, licenseName, licenseURL);
830 
831 			BPath licensePath;
832 			if (_GetLicensePath(licenseURL, licensePath) == B_OK) {
833 				fCreditsView->InsertHyperText(licenseName,
834 					new OpenFileAction(licensePath.Path()));
835 			} else
836 				fCreditsView->Insert(licenseName);
837 		}
838 
839 		fCreditsView->Insert("\n");
840 	}
841 
842 	if (sources.CountStrings() > 0) {
843 		fCreditsView->Insert(B_TRANSLATE("Source Code: "));
844 
845 		for (int32 i = 0; i < sources.CountStrings(); i++) {
846 			const char* source = sources.StringAt(i);
847 
848 			if (i > 0)
849 				fCreditsView->Insert(", ");
850 
851 			BString urlName;
852 			BString urlAddress;
853 			parse_named_url(source, urlName, urlAddress);
854 
855 			fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL,
856 				&kLinkBlue);
857 			fCreditsView->InsertHyperText(urlName,
858 				new URLAction(urlAddress));
859 		}
860 
861 		fCreditsView->Insert("\n");
862 	}
863 
864 	if (url) {
865 		BString urlName;
866 		BString urlAddress;
867 		parse_named_url(url, urlName, urlAddress);
868 
869 		fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL,
870 			&kLinkBlue);
871 		fCreditsView->InsertHyperText(urlName,
872 			new URLAction(urlAddress));
873 		fCreditsView->Insert("\n");
874 	}
875 	fCreditsView->Insert("\n");
876 }
877 
878 
879 void
880 AboutView::PickRandomHaiku()
881 {
882 	BPath path;
883 	if (find_directory(B_SYSTEM_DATA_DIRECTORY, &path) != B_OK)
884 		path = "/system/data";
885 	path.Append("fortunes");
886 	path.Append("Haiku");
887 
888 	BFile fortunes(path.Path(), B_READ_ONLY);
889 	struct stat st;
890 	if (fortunes.InitCheck() < B_OK)
891 		return;
892 	if (fortunes.GetStat(&st) < B_OK)
893 		return;
894 
895 	char* buff = (char*)malloc((size_t)st.st_size + 1);
896 	if (!buff)
897 		return;
898 	buff[(size_t)st.st_size] = '\0';
899 	BList haikuList;
900 	if (fortunes.Read(buff, (size_t)st.st_size) == (ssize_t)st.st_size) {
901 		char* p = buff;
902 		while (p && *p) {
903 			char* e = strchr(p, '%');
904 			BString* s = new BString(p, e ? (e - p) : -1);
905 			haikuList.AddItem(s);
906 			p = e;
907 			if (p && (*p == '%'))
908 				p++;
909 			if (p && (*p == '\n'))
910 				p++;
911 		}
912 	}
913 	free(buff);
914 	if (haikuList.CountItems() < 1)
915 		return;
916 
917 	BString* s = (BString*)haikuList.ItemAt(rand() % haikuList.CountItems());
918 	BFont font(be_bold_font);
919 	font.SetSize(be_bold_font->Size());
920 	font.SetFace(B_BOLD_FACE | B_ITALIC_FACE);
921 	fCreditsView->SelectAll();
922 	fCreditsView->Delete();
923 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kDarkGrey);
924 	fCreditsView->Insert(s->String());
925 	fCreditsView->Insert("\n");
926 	while ((s = (BString*)haikuList.RemoveItem((int32)0))) {
927 		delete s;
928 	}
929 }
930 
931 
932 BView*
933 AboutView::_CreateLabel(const char* name, const char* label)
934 {
935 	BStringView* labelView = new BStringView(name, label);
936 	labelView->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
937 		B_ALIGN_VERTICAL_UNSET));
938 	labelView->SetFont(be_bold_font);
939 	return labelView;
940 }
941 
942 
943 BView*
944 AboutView::_CreateCreditsView()
945 {
946 	// Begin construction of the credits view
947 	fCreditsView = new HyperTextView("credits");
948 	fCreditsView->SetFlags(fCreditsView->Flags() | B_FRAME_EVENTS);
949 	fCreditsView->SetStylable(true);
950 	fCreditsView->MakeEditable(false);
951 	fCreditsView->SetWordWrap(true);
952 	fCreditsView->SetInsets(5, 5, 5, 5);
953 	fCreditsView->SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
954 
955 	BScrollView* creditsScroller = new BScrollView("creditsScroller",
956 		fCreditsView, B_WILL_DRAW | B_FRAME_EVENTS, false, true,
957 		B_PLAIN_BORDER);
958 
959 	// Haiku copyright
960 	BFont font(be_bold_font);
961 	font.SetSize(font.Size() + 4);
962 
963 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen);
964 	fCreditsView->Insert("Haiku\n");
965 
966 	char string[1024];
967 	time_t time = ::time(NULL);
968 	struct tm* tm = localtime(&time);
969 	int32 year = tm->tm_year + 1900;
970 	if (year < 2008)
971 		year = 2008;
972 	snprintf(string, sizeof(string),
973 		COPYRIGHT_STRING "2001-%ld The Haiku project. ", year);
974 
975 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
976 	fCreditsView->Insert(string);
977 
978 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
979 	fCreditsView->Insert(B_TRANSLATE("The copyright to the Haiku code is "
980 		"property of Haiku, Inc. or of the respective authors where expressly "
981 		"noted in the source. Haiku" B_UTF8_REGISTERED
982 		" and the HAIKU logo" B_UTF8_REGISTERED
983 		" are registered trademarks of Haiku, Inc."
984 		"\n\n"));
985 
986 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kLinkBlue);
987 	fCreditsView->InsertHyperText("http://www.haiku-os.org",
988 		new URLAction("http://www.haiku-os.org"));
989 	fCreditsView->Insert("\n\n");
990 
991 	font.SetSize(be_bold_font->Size());
992 	font.SetFace(B_BOLD_FACE | B_ITALIC_FACE);
993 
994 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange);
995 	fCreditsView->Insert(B_TRANSLATE("Current maintainers:\n"));
996 
997 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
998 	fCreditsView->Insert(
999 		"Ithamar R. Adema\n"
1000 		"Bruno G. Albuquerque\n"
1001 		"Stephan Aßmus\n"
1002 		"Salvatore Benedetto\n"
1003 		"Stefano Ceccherini\n"
1004 		"Rudolf Cornelissen\n"
1005 		"Alexandre Deckner\n"
1006 		"Adrien Destugues\n"
1007 		"Oliver Ruiz Dorantes\n"
1008 		"Axel Dörfler\n"
1009 		"Jérôme Duval\n"
1010 		"René Gollent\n"
1011 		"Bryce Groff\n"
1012 		"Colin Günther\n"
1013 		"Karsten Heimrich\n"
1014 		"Fredrik Holmqvist\n"
1015 		"Philippe Houdoin\n"
1016 		"Maurice Kalinowski\n"
1017 		"Euan Kirkhope\n"
1018 		"Ryan Leavengood\n"
1019 		"Michael Lotz\n"
1020 		"Brecht Machiels\n"
1021 		"Matt Madia\n"
1022 		"Scott McCreary\n"
1023 		"David McPaul\n"
1024 		"Wim van der Meer\n"
1025 		"Fredrik Modéen\n"
1026 		"Marcus Overhagen\n"
1027 		"Michael Pfeiffer\n"
1028 		"François Revol\n"
1029 		"Philippe Saint-Pierre\n"
1030 		"John Scipione\n"
1031 		"Andrej Spielmann\n"
1032 		"Jonas Sundström\n"
1033 		"Oliver Tappe\n"
1034 		"Gerasim Troeglazov\n"
1035 		"Alexander von Gluck IV\n"
1036 		"Ingo Weinhold\n"
1037 		"Alex Wilson\n"
1038 		"Artur Wyszyński\n"
1039 		"Clemens Zeidler\n"
1040 		"Siarzhuk Zharski\n"
1041 		"\n");
1042 
1043 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange);
1044 	fCreditsView->Insert(B_TRANSLATE("Past maintainers:\n"));
1045 
1046 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
1047 	fCreditsView->Insert(
1048 		"Andrew Bachmann\n"
1049 		"Tyler Dauwalder\n"
1050 		"Daniel Furrer\n"
1051 		"Andre Alves Garzia\n"
1052 		"Erik Jaesler\n"
1053 		"Marcin Konicki\n"
1054 		"Waldemar Kornewald\n"
1055 		"Thomas Kurschel\n"
1056 		"Frans Van Nispen\n"
1057 		"Adi Oanca\n"
1058 		"Michael Phipps\n"
1059 		"Niels Sascha Reedijk\n"
1060 		"David Reid\n"
1061 		"Hugo Santos\n"
1062 		"Alexander G. M. Smith\n"
1063 		"Bryan Varner\n"
1064 		"Nathan Whitehorn\n"
1065 		"Michael Wilber\n"
1066 		"Jonathan Yoder\n"
1067 		"Gabe Yoder\n"
1068 		"\n");
1069 
1070 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange);
1071 	fCreditsView->Insert(B_TRANSLATE("Website, marketing & documentation:\n"));
1072 
1073 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
1074 	fCreditsView->Insert(
1075 		"Phil Greenway\n"
1076 		"Gavin James\n"
1077 		"Urias McCullough\n"
1078 		"Niels Sascha Reedijk\n"
1079 		"Joachim Seemer - Humdinger\n"
1080 		"Jonathan Yoder\n"
1081 		"\n");
1082 
1083 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange);
1084 	fCreditsView->Insert(B_TRANSLATE("Contributors:\n"));
1085 
1086 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
1087 	fCreditsView->Insert(
1088 		"Andrea Anzani\n"
1089 		"Sean Bartell\n"
1090 		"Hannah Boneß\n"
1091 		"Andre Braga\n"
1092 		"Michael Bulash\n"
1093 		"Bruce Cameron\n"
1094 		"Jean-Loïc Charroud\n"
1095 		"Greg Crain\n"
1096 		"Michael Davidson\n"
1097 		"David Dengg\n"
1098 		"John Drinkwater\n"
1099 		"Cian Duffy\n"
1100 		"Vincent Duvert\n"
1101 		"Mikael Eiman\n"
1102 		"Fredrik Ekdahl\n"
1103 		"Joshua R. Elsasser\n"
1104 		"Atis Elsts\n"
1105 		"Mark Erben\n"
1106 		"Christian Fasshauer\n"
1107 		"Andreas Färber\n"
1108 		"Janito Ferreira Filho\n"
1109 		"Pier Luigi Fiorini\n"
1110 		"Marc Flerackers\n"
1111 		"Michele Frau - zuMi\n"
1112 		"Deyan Genovski\n"
1113 		"Pete Goodeve\n"
1114 		"Lucian Adrian Grijincu\n"
1115 		"Sean Healy\n"
1116 		"Matthijs Hollemans\n"
1117 		"Mathew Hounsell\n"
1118 		"Morgan Howe\n"
1119 		"Christophe Huriaux\n"
1120 		"Jian Jiang\n"
1121 		"Ma Jie\n"
1122 		"Carwyn Jones\n"
1123 		"Vasilis Kaoutsis\n"
1124 		"James Kim\n"
1125 		"Shintaro Kinugawa\n"
1126 		"Jan Klötzke\n"
1127 		"Kurtis Kopf\n"
1128 		"Tomáš Kučera\n"
1129 		"Luboš Kulič\n"
1130 		"Elad Lahav\n"
1131 		"Anthony Lee\n"
1132 		"Santiago Lema\n"
1133 		"Raynald Lesieur\n"
1134 		"Oscar Lesta\n"
1135 		"Jerome Leveque\n"
1136 		"Brian Luft\n"
1137 		"Christof Lutteroth\n"
1138 		"Graham MacDonald\n"
1139 		"Jorge G. Mare - Koki\n"
1140 		"Jan Matějek\n"
1141 		"Brian Matzon\n"
1142 		"Christopher ML Zumwalt May\n"
1143 		"Andrew McCall\n"
1144 		"Nathan Mentley\n"
1145 		"Marius Middelthon\n"
1146 		"Marco Minutoli\n"
1147 		"Misza\n"
1148 		"Hamish Morrison\n"
1149 		"MrSiggler\n"
1150 		"Takashi Murai\n"
1151 		"Alan Murta\n"
1152 		"Raghuram Nagireddy\n"
1153 		"Kazuho Okui\n"
1154 		"Jeroen Oortwijn - idefix\n"
1155 		"Pahtz\n"
1156 		"Michael Paine\n"
1157 		"Adrian Panasiuk\n"
1158 		"Aleksas Pantechovskis\n"
1159 		"Romain Picard\n"
1160 		"Francesco Piccinno\n"
1161 		"Peter Poláčik\n"
1162 		"David Powell\n"
1163 		"Jeremy Rand\n"
1164 		"Hartmut Reh\n"
1165 		"Daniel Reinhold\n"
1166 		"Chris Roberts\n"
1167 		"Samuel Rodríguez Pérez\n"
1168 		"Thomas Roell\n"
1169 		"Rafael Romo\n"
1170 		"Ralf Schülke\n"
1171 		"Reznikov Sergei\n"
1172 		"Zousar Shaker\n"
1173 		"Caitlin Shaw\n"
1174 		"Geoffry Song\n"
1175 		"Daniel Switkin\n"
1176 		"Atsushi Takamatsu\n"
1177 		"James Urquhart\n"
1178 		"Jason Vandermark\n"
1179 		"Sandor Vroemisse\n"
1180 		"Denis Washington\n"
1181 		"Ulrich Wimboeck\n"
1182 		"Johannes Wischert\n"
1183 		"James Woodcock\n"
1184 		"Hong Yul Yang\n"
1185 		"Gerald Zajac\n"
1186 		"Łukasz Zemczak\n"
1187 		"JiSheng Zhang\n"
1188 		"Zhao Shuai\n");
1189 	fCreditsView->Insert(
1190 		B_TRANSLATE("\n" B_UTF8_ELLIPSIS
1191 			" and probably some more we forgot to mention (sorry!)"
1192 			"\n\n"));
1193 
1194 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange);
1195 	fCreditsView->Insert(B_TRANSLATE("Translations:\n"));
1196 
1197 	BLanguage* lang;
1198 	BString langName;
1199 
1200 	BList sortedTranslations;
1201 	for (uint32 i = 0; i < kNumberOfTranslations; i ++) {
1202 		const Translation* translation = &gTranslations[i];
1203 		sortedTranslations.AddItem((void*)translation);
1204 	}
1205 	sortedTranslations.SortItems(TranslationComparator);
1206 
1207 	for (uint32 i = 0; i < kNumberOfTranslations; i ++) {
1208 		const Translation& translation
1209 			= *(const Translation*)sortedTranslations.ItemAt(i);
1210 
1211 		langName.Truncate(0);
1212 		if (BLocaleRoster::Default()->GetLanguage(translation.languageCode,
1213 				&lang) == B_OK) {
1214 			lang->GetName(langName);
1215 			delete lang;
1216 		} else {
1217 			// We failed to get the localized readable name,
1218 			// go with what we have.
1219 			langName.Append(translation.languageCode);
1220 		}
1221 
1222 		fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen);
1223 		fCreditsView->Insert("\n");
1224 		fCreditsView->Insert(langName);
1225 		fCreditsView->Insert("\n");
1226 		fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
1227 		fCreditsView->Insert(translation.names);
1228 	}
1229 
1230 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuOrange);
1231 	fCreditsView->Insert(B_TRANSLATE("\n\nSpecial thanks to:\n"));
1232 
1233 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
1234 	BString beosCredits(B_TRANSLATE(
1235 		"Be Inc. and its developer team, for having created BeOS!\n\n"));
1236 	int32 beosOffset = beosCredits.FindFirst("BeOS");
1237 	fCreditsView->Insert(beosCredits.String(),
1238 		(beosOffset < 0) ? beosCredits.Length() : beosOffset);
1239 	if (beosOffset > -1) {
1240 		fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kBeOSBlue);
1241 		fCreditsView->Insert("B");
1242 		fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kBeOSRed);
1243 		fCreditsView->Insert("e");
1244 		fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
1245 		beosCredits.Remove(0, beosOffset + 2);
1246 		fCreditsView->Insert(beosCredits.String(), beosCredits.Length());
1247 	}
1248 	fCreditsView->Insert(
1249 		B_TRANSLATE("Travis Geiselbrecht (and his NewOS kernel)\n"));
1250 	fCreditsView->Insert(
1251 		B_TRANSLATE("Michael Phipps (project founder)\n\n"));
1252 	fCreditsView->Insert(
1253 		B_TRANSLATE("The Haiku-Ports team\n"));
1254 	fCreditsView->Insert(
1255 		B_TRANSLATE("The Haikuware team and their bounty program\n"));
1256 	fCreditsView->Insert(
1257 		B_TRANSLATE("The BeGeistert team\n"));
1258 	fCreditsView->Insert(
1259 		B_TRANSLATE("Google & their Google Summer of Code program\n"));
1260 	fCreditsView->Insert(
1261 		B_TRANSLATE("The University of Auckland and Christof Lutteroth\n\n"));
1262 	fCreditsView->Insert(
1263 		B_TRANSLATE("... and the many people making donations!\n\n"));
1264 
1265 	// copyrights for various projects we use
1266 
1267 	BPath mitPath;
1268 	_GetLicensePath("MIT", mitPath);
1269 	BPath lgplPath;
1270 	_GetLicensePath("GNU LGPL v2.1", lgplPath);
1271 
1272 	font.SetSize(be_bold_font->Size() + 4);
1273 	font.SetFace(B_BOLD_FACE);
1274 	fCreditsView->SetFontAndColor(&font, B_FONT_ALL, &kHaikuGreen);
1275 	fCreditsView->Insert(B_TRANSLATE("\nCopyrights\n\n"));
1276 
1277 	fCreditsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kDarkGrey);
1278 	fCreditsView->Insert(B_TRANSLATE("[Click a license name to read the "
1279 		"respective license.]\n\n"));
1280 
1281 	// Haiku license
1282 	BString haikuLicense = B_TRANSLATE_COMMENT("The code that is unique to "
1283 		"Haiku, especially the kernel and all code that applications may link "
1284 		"against, is distributed under the terms of the <MIT license>. "
1285 		"Some system libraries contain third party code distributed under the "
1286 		"<LGPL license>. You can find the copyrights to third party code below."
1287 		"\n\n", "<MIT license> and <LGPL license> aren't variables and can be "
1288 		"translated. However, please, don't remove < and > as they're needed "
1289 		"as placeholders for proper hypertext functionality.");
1290 	int32 licensePart1 = haikuLicense.FindFirst("<");
1291 	int32 licensePart2 = haikuLicense.FindFirst(">");
1292 	int32 licensePart3 = haikuLicense.FindLast("<");
1293 	int32 licensePart4 = haikuLicense.FindLast(">");
1294 	BString part;
1295 	haikuLicense.CopyInto(part, 0, licensePart1);
1296 	fCreditsView->Insert(part);
1297 
1298 	part.Truncate(0);
1299 	haikuLicense.CopyInto(part, licensePart1 + 1, licensePart2 - 1
1300 		- licensePart1);
1301 	fCreditsView->InsertHyperText(part, new OpenFileAction(mitPath.Path()));
1302 
1303 	part.Truncate(0);
1304 	haikuLicense.CopyInto(part, licensePart2 + 1, licensePart3 - 1
1305 		- licensePart2);
1306 	fCreditsView->Insert(part);
1307 
1308 	part.Truncate(0);
1309 	haikuLicense.CopyInto(part, licensePart3 + 1, licensePart4 - 1
1310 		- licensePart3);
1311 	fCreditsView->InsertHyperText(part, new OpenFileAction(lgplPath.Path()));
1312 
1313 	part.Truncate(0);
1314 	haikuLicense.CopyInto(part, licensePart4 + 1, haikuLicense.Length() - 1
1315 		- licensePart4);
1316 	fCreditsView->Insert(part);
1317 
1318 	// GNU copyrights
1319 	AddCopyrightEntry("The GNU Project",
1320 		B_TRANSLATE("Contains software from the GNU Project, "
1321 		"released under the GPL and LGPL licenses:\n"
1322 		"GNU C Library, "
1323 		"GNU coretools, diffutils, findutils, "
1324 		"sharutils, gawk, bison, m4, make, "
1325 		"gdb, wget, ncurses, termcap, "
1326 		"Bourne Again Shell.\n"
1327 		COPYRIGHT_STRING "The Free Software Foundation."),
1328 		StringVector("GNU LGPL v2.1", "GNU GPL v2", "GNU GPL v3", NULL),
1329 		StringVector(),
1330 		"http://www.gnu.org");
1331 
1332 	// FreeBSD copyrights
1333 	AddCopyrightEntry("The FreeBSD Project",
1334 		B_TRANSLATE("Contains software from the FreeBSD Project, "
1335 		"released under the BSD license:\n"
1336 		"cal, ftpd, ping, telnet, "
1337 		"telnetd, traceroute\n"
1338 		COPYRIGHT_STRING "1994-2008 The FreeBSD Project. "
1339 		"All rights reserved."),
1340 		StringVector("BSD (2-clause)", "BSD (3-clause)", "BSD (4-clause)",
1341 			NULL),
1342 		StringVector(),
1343 		"http://www.freebsd.org");
1344 
1345 	// NetBSD copyrights
1346 	AddCopyrightEntry("The NetBSD Project",
1347 		B_TRANSLATE("Contains software developed by the NetBSD "
1348 		"Foundation, Inc. and its contributors:\n"
1349 		"ftp, tput\n"
1350 		COPYRIGHT_STRING "1996-2008 The NetBSD Foundation, Inc. "
1351 		"All rights reserved."),
1352 		"http://www.netbsd.org");
1353 			// TODO: License!
1354 
1355 	// FFMpeg copyrights
1356 	_AddPackageCredit(PackageCredit("FFMpeg libavcodec")
1357 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2000-2007 Fabrice "
1358 			"Bellard, et al."))
1359 		.SetLicenses("GNU LGPL v2.1", "GNU LGPL v2", NULL)
1360 		.SetURL("http://www.ffmpeg.org"));
1361 
1362 	// AGG copyrights
1363 	_AddPackageCredit(PackageCredit("AntiGrain Geometry")
1364 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2002-2006 Maxim "
1365 			"Shemanarev (McSeem)."))
1366 		.SetLicenses("Anti-Grain Geometry", B_TRANSLATE("BSD (3-clause)"),
1367 			"GPC", NULL)
1368 		.SetURL("http://www.antigrain.com"));
1369 
1370 	// PDFLib copyrights
1371 	_AddPackageCredit(PackageCredit("PDFLib")
1372 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1997-2006 PDFlib GmbH and "
1373 			"Thomas Merz. All rights reserved.\n"
1374 			"PDFlib and PDFlib logo are registered trademarks of PDFlib GmbH."))
1375 		.SetLicense("PDFlib Lite")
1376 		.SetURL("http://www.pdflib.com"));
1377 
1378 	// FreeType copyrights
1379 	_AddPackageCredit(PackageCredit("FreeType2")
1380 		.SetCopyright(B_TRANSLATE("Portions of this software are under "
1381 			"copyright.\n"
1382 			COPYRIGHT_STRING "1996-2006 "
1383 			"The FreeType Project. All rights reserved."))
1384 		.SetLicense("FTL")
1385 		.SetURL("http://www.freetype.org"));
1386 
1387 	// Mesa3D (http://www.mesa3d.org) copyrights
1388 	_AddPackageCredit(PackageCredit("Mesa")
1389 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1999-2006 Brian Paul. "
1390 			"Mesa3D Project. All rights reserved."))
1391 		.SetLicense("MIT")
1392 		.SetURL("http://www.mesa3d.org"));
1393 
1394 	// SGI's GLU implementation copyrights
1395 	_AddPackageCredit(PackageCredit("GLU")
1396 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1991-2000 "
1397 			"Silicon Graphics, Inc. All rights reserved."))
1398 		.SetLicense("SGI Free B")
1399 		.SetURL("http://www.sgi.com/products/software/opengl"));
1400 
1401 	// GLUT implementation copyrights
1402 	_AddPackageCredit(PackageCredit("GLUT")
1403 		.SetCopyrights(B_TRANSLATE(COPYRIGHT_STRING "1994-1997 Mark Kilgard. "
1404 			"All rights reserved."),
1405 			COPYRIGHT_STRING "1997 Be Inc.",
1406 			COPYRIGHT_STRING "1999 Jake Hamby.",
1407 			NULL)
1408 		.SetLicense("GLUT (Mark Kilgard)")
1409 		.SetURL("http://www.opengl.org/resources/libraries/glut"));
1410 
1411 	// OpenGroup & DEC (BRegion backend) copyright
1412 	_AddPackageCredit(PackageCredit("BRegion backend (XFree86)")
1413 		.SetCopyrights(COPYRIGHT_STRING "1987-1988, 1998 The Open Group.",
1414 			B_TRANSLATE(COPYRIGHT_STRING "1987-1988 Digital Equipment "
1415 			"Corporation, Maynard, Massachusetts.\n"
1416 			"All rights reserved."),
1417 			NULL)
1418 		.SetLicenses("OpenGroup", "DEC", NULL));
1419 			// TODO: URL
1420 
1421 	// VL-Gothic font
1422 	_AddPackageCredit(PackageCredit("VL-Gothic font")
1423 		.SetCopyrights(B_TRANSLATE(COPYRIGHT_STRING "1990-2003 Wada Laboratory,"
1424 			" the University of Tokyo."), COPYRIGHT_STRING
1425 			"2003-2004 Electronic Font Open Laboratory (/efont/).",
1426 			COPYRIGHT_STRING "2003-2012 M+ FONTS PROJECT.",
1427 			COPYRIGHT_STRING "2006-2012 Daisuke SUZUKI.",
1428 			COPYRIGHT_STRING "2006-2012 Project Vine.",
1429 			B_TRANSLATE("MIT license. All rights reserved."),
1430 			NULL)
1431 		.SetLicense("BSD (3-clause)")
1432 		.SetURL("http://vlgothic.dicey.org/"));
1433 
1434 	// expat copyrights
1435 	_AddPackageCredit(PackageCredit("expat")
1436 		.SetCopyrights(B_TRANSLATE(COPYRIGHT_STRING "1998-2000 Thai "
1437 			"Open Source Software Center Ltd and Clark Cooper."),
1438 			B_TRANSLATE(COPYRIGHT_STRING "2001-2003 Expat maintainers."),
1439 			NULL)
1440 		.SetLicense("Expat")
1441 		.SetURL("http://expat.sourceforge.net"));
1442 
1443 	// zlib copyrights
1444 	_AddPackageCredit(PackageCredit("zlib")
1445 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1995-2004 Jean-loup "
1446 			"Gailly and Mark Adler."))
1447 		.SetLicense("Zlib")
1448 		.SetURL("http://www.zlib.net"));
1449 
1450 	// zip copyrights
1451 	_AddPackageCredit(PackageCredit("Info-ZIP")
1452 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1990-2002 Info-ZIP. "
1453 			"All rights reserved."))
1454 		.SetLicense("Info-ZIP")
1455 		.SetURL("http://www.info-zip.org"));
1456 
1457 	// bzip2 copyrights
1458 	_AddPackageCredit(PackageCredit("bzip2")
1459 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1996-2005 Julian R "
1460 			"Seward. All rights reserved."))
1461 		.SetLicense(B_TRANSLATE("BSD (4-clause)"))
1462 		.SetURL("http://bzip.org"));
1463 
1464 	// lp_solve copyrights
1465 	_AddPackageCredit(PackageCredit("lp_solve")
1466 		.SetCopyright(COPYRIGHT_STRING
1467 			"Michel Berkelaar, Kjell Eikland, Peter Notebaert")
1468 		.SetLicense("GNU LGPL v2.1")
1469 		.SetURL("http://lpsolve.sourceforge.net/"));
1470 
1471 	// OpenEXR copyrights
1472 	_AddPackageCredit(PackageCredit("OpenEXR")
1473 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2002-2005 Industrial "
1474 			"Light & Magic, a division of Lucas Digital Ltd. LLC."))
1475 		.SetLicense(B_TRANSLATE("BSD (3-clause)"))
1476 		.SetURL("http://www.openexr.com"));
1477 
1478 	// Bullet copyrights
1479 	_AddPackageCredit(PackageCredit("Bullet")
1480 		.SetCopyright(COPYRIGHT_STRING "2003-2008 Erwin Coumans")
1481 		.SetLicense("Bullet")
1482 		.SetURL("http://www.bulletphysics.com"));
1483 
1484 	// atftp copyrights
1485 	_AddPackageCredit(PackageCredit("atftp")
1486 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2000 Jean-Pierre "
1487 			"ervbefeL and Remi Lefebvre."))
1488 		.SetLicense("GNU GPL v2")
1489 		.SetURL("http://freecode.com/projects/atftp"));
1490 
1491 	// Netcat copyrights
1492 	_AddPackageCredit(PackageCredit("Netcat")
1493 		.SetCopyright(COPYRIGHT_STRING "1996 Hobbit.")
1494 		.SetLicense("Public Domain")
1495 		.SetURL("http://nc110.sourceforge.net/"));
1496 
1497 	// acpica copyrights
1498 	_AddPackageCredit(PackageCredit("acpica")
1499 		.SetCopyright(COPYRIGHT_STRING "1999-2006 Intel Corp.")
1500 		.SetLicense("Intel (ACPICA)")
1501 		.SetURL("http://www.acpica.org"));
1502 
1503 	// unrar copyrights
1504 	_AddPackageCredit(PackageCredit("unrar")
1505 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2002-2008 Alexander "
1506 			"L. Roshal. All rights reserved."))
1507 		.SetLicense("UnRAR")
1508 		.SetURL("http://www.rarlab.com"));
1509 
1510 	// libpng copyrights
1511 	_AddPackageCredit(PackageCredit("libpng")
1512 		.SetCopyright(COPYRIGHT_STRING "2004, 2006-2008 Glenn "
1513 			"Randers-Pehrson.")
1514 		.SetLicense("LibPNG")
1515 		.SetURL("http://www.libpng.org"));
1516 
1517 	// libjpeg copyrights
1518 	_AddPackageCredit(PackageCredit("libjpeg")
1519 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1994-2009, Thomas G. "
1520 			"Lane, Guido Vollbeding. This software is based in part on the "
1521 			"work of the Independent JPEG Group."))
1522 		.SetLicense("LibJPEG")
1523 		.SetURL("http://www.ijg.org"));
1524 
1525 	// libprint copyrights
1526 	_AddPackageCredit(PackageCredit("libprint")
1527 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1999-2000 Y.Takagi. "
1528 			"All rights reserved.")));
1529 			// TODO: License!
1530 
1531 	// cortex copyrights
1532 	_AddPackageCredit(PackageCredit("Cortex")
1533 		.SetCopyright(COPYRIGHT_STRING "1999-2000 Eric Moon.")
1534 		.SetLicense(B_TRANSLATE("BSD (3-clause)"))
1535 		.SetURL("http://cortex.sourceforge.net/documentation"));
1536 
1537 	// FluidSynth copyrights
1538 	_AddPackageCredit(PackageCredit("FluidSynth")
1539 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2003 Peter Hanappe "
1540 			"and others."))
1541 		.SetLicense("GNU LGPL v2")
1542 		.SetURL("http://www.fluidsynth.org"));
1543 
1544 	// CannaIM copyrights
1545 	_AddPackageCredit(PackageCredit("CannaIM")
1546 		.SetCopyright(COPYRIGHT_STRING "1999 Masao Kawamura.")
1547 		.SetLicense("MIT"));
1548 
1549 	// libxml2, libxslt, libexslt copyrights
1550 	_AddPackageCredit(PackageCredit("libxml2, libxslt")
1551 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1998-2003 Daniel Veillard. "
1552 			"All rights reserved."))
1553 		.SetLicense(B_TRANSLATE("MIT (no promotion)"))
1554 		.SetURL("http://xmlsoft.org"));
1555 
1556 	_AddPackageCredit(PackageCredit("libexslt")
1557 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2001-2002 Thomas Broyer, "
1558 			"Charlie Bozeman and Daniel Veillard. All rights reserved."))
1559 		.SetLicense(B_TRANSLATE("MIT (no promotion)"))
1560 		.SetURL("http://xmlsoft.org"));
1561 
1562 	// Xiph.org Foundation copyrights
1563 	_AddPackageCredit(PackageCredit("Xiph.org Foundation")
1564 		.SetCopyrights("libvorbis, libogg, libtheora, libspeex",
1565 			B_TRANSLATE(COPYRIGHT_STRING "1994-2008 Xiph.Org. "
1566 			"All rights reserved."), NULL)
1567 		.SetLicense(B_TRANSLATE("BSD (3-clause)"))
1568 		.SetURL("http://www.xiph.org"));
1569 
1570 	// The Tcpdump Group
1571 	_AddPackageCredit(PackageCredit("The Tcpdump Group")
1572 		.SetCopyright("tcpdump, libpcap")
1573 		.SetLicense(B_TRANSLATE("BSD (3-clause)"))
1574 		.SetURL("http://www.tcpdump.org"));
1575 
1576 	// Matroska
1577 	_AddPackageCredit(PackageCredit("libmatroska")
1578 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2002-2003 Steve Lhomme. "
1579 			"All rights reserved."))
1580 		.SetLicense("GNU LGPL v2.1")
1581 		.SetURL("http://www.matroska.org"));
1582 
1583 	// BColorQuantizer (originally CQuantizer code)
1584 	_AddPackageCredit(PackageCredit("CQuantizer")
1585 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1996-1997 Jeff Prosise. "
1586 			"All rights reserved."))
1587 		.SetLicense("CQuantizer")
1588 		.SetURL("http://www.xdp.it"));
1589 
1590 	// MAPM (Mike's Arbitrary Precision Math Library) used by DeskCalc
1591 	_AddPackageCredit(PackageCredit("MAPM")
1592 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1999-2007 Michael C. "
1593 			"Ring. All rights reserved."))
1594 		.SetLicense("MAPM")
1595 		.SetURL("http://tc.umn.edu/~ringx004"));
1596 
1597 	// MkDepend 1.7 copyright (Makefile dependency generator)
1598 	_AddPackageCredit(PackageCredit("MkDepend")
1599 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1995-2001 Lars Düning. "
1600 			"All rights reserved."))
1601 		.SetLicense("MkDepend")
1602 		.SetURL("http://bearnip.com/lars/be"));
1603 
1604 	// libhttpd copyright (used as Poorman backend)
1605 	_AddPackageCredit(PackageCredit("libhttpd")
1606 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "1995, 1998-2001 "
1607 			"Jef Poskanzer. All rights reserved."))
1608 		.SetLicense("LibHTTPd")
1609 		.SetURL("http://www.acme.com/software/thttpd/"));
1610 
1611 #ifdef __INTEL__
1612 	// Udis86 copyrights
1613 	_AddPackageCredit(PackageCredit("Udis86")
1614 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2002-2004 "
1615 			"Vivek Mohan. All rights reserved."))
1616 		.SetLicense(B_TRANSLATE("BSD (2-clause)"))
1617 		.SetURL("http://udis86.sourceforge.net"));
1618 #endif
1619 
1620 #ifdef __INTEL__
1621 	// Intel PRO/Wireless 2100 Firmware
1622 	_AddPackageCredit(PackageCredit("Intel PRO/Wireless 2100 Firmware")
1623 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2003-2006 "
1624 			"Intel Corporation. All rights reserved."))
1625 		.SetLicense("Intel (2xxx firmware)")
1626 		.SetURL("http://ipw2100.sourceforge.net/"));
1627 #endif
1628 
1629 #ifdef __INTEL__
1630 	// Intel PRO/Wireless 2200BG Firmware
1631 	_AddPackageCredit(PackageCredit("Intel PRO/Wireless 2200BG Firmware")
1632 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2004-2005 "
1633 			"Intel Corporation. All rights reserved."))
1634 		.SetLicense("Intel (2xxx firmware)")
1635 		.SetURL("http://ipw2200.sourceforge.net/"));
1636 #endif
1637 
1638 #ifdef __INTEL__
1639 	// Intel PRO/Wireless 3945ABG/BG Network Connection Adapter Firmware
1640 	_AddPackageCredit(
1641 		PackageCredit(
1642 			"Intel PRO/Wireless 3945ABG/BG Network Connection Adapter Firmware")
1643 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2006-2007 "
1644 			"Intel Corporation. All rights reserved."))
1645 		.SetLicense("Intel (firmware)")
1646 		.SetURL("http://www.intellinuxwireless.org/"));
1647 #endif
1648 #ifdef __INTEL__
1649 	// Intel Wireless WiFi Link 4965AGN Adapter Firmware
1650 	_AddPackageCredit(
1651 		PackageCredit("Intel Wireless WiFi Link 4965AGN Adapter Firmware")
1652 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2006-2007 "
1653 			"Intel Corporation. All rights reserved."))
1654 		.SetLicense("Intel (firmware)")
1655 		.SetURL("http://www.intellinuxwireless.org/"));
1656 #endif
1657 
1658 #ifdef __INTEL__
1659 	// Marvell 88w8363
1660 	_AddPackageCredit(PackageCredit("Marvell 88w8363")
1661 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2007-2009 "
1662 			"Marvell Semiconductor, Inc. All rights reserved."))
1663 		.SetLicense("Marvell (firmware)")
1664 		.SetURL("http://www.marvell.com/"));
1665 #endif
1666 
1667 #ifdef __INTEL__
1668 	// Ralink Firmware RT2501/RT2561/RT2661
1669 	_AddPackageCredit(PackageCredit("Ralink Firmware RT2501/RT2561/RT2661")
1670 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2007 "
1671 			"Ralink Technology Corporation. All rights reserved."))
1672 		.SetLicense("Ralink (firmware)")
1673 		.SetURL("http://www.ralinktech.com/"));
1674 #endif
1675 
1676 	// Gutenprint
1677 	_AddPackageCredit(PackageCredit("Gutenprint")
1678 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING
1679 			"1999-2010 by the authors of Gutenprint. All rights reserved."))
1680 		.SetLicense("GNU GPL v2")
1681 		.SetURL("http://gutenprint.sourceforge.net/"));
1682 
1683 	// libwebp
1684 	_AddPackageCredit(PackageCredit("libwebp")
1685 		.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING
1686 			"2010-2011 Google Inc. All rights reserved."))
1687 		.SetLicense(B_TRANSLATE("BSD (3-clause)"))
1688 		.SetURL("http://www.webmproject.org/code/#libwebp_webp_image_library"));
1689 
1690 	// GTF
1691 	_AddPackageCredit(PackageCredit("GTF")
1692 		.SetCopyright(B_TRANSLATE("2001 by Andy Ritger based on the "
1693 			"Generalized Timing Formula"))
1694 		.SetLicense(B_TRANSLATE("BSD (3-clause)"))
1695 		.SetURL("http://gtf.sourceforge.net/"));
1696 
1697 	_AddCopyrightsFromAttribute();
1698 	_AddPackageCreditEntries();
1699 
1700 	return new CropView(creditsScroller, 0, 1, 1, 1);
1701 }
1702 
1703 
1704 status_t
1705 AboutView::_GetLicensePath(const char* license, BPath& path)
1706 {
1707 	static const directory_which directoryConstants[] = {
1708 		B_USER_DATA_DIRECTORY,
1709 		B_COMMON_DATA_DIRECTORY,
1710 		B_SYSTEM_DATA_DIRECTORY
1711 	};
1712 	static const int dirCount = 3;
1713 
1714 	for (int i = 0; i < dirCount; i++) {
1715 		struct stat st;
1716 		status_t error = find_directory(directoryConstants[i], &path);
1717 		if (error == B_OK && path.Append("licenses") == B_OK
1718 			&& path.Append(license) == B_OK
1719 			&& lstat(path.Path(), &st) == 0) {
1720 			return B_OK;
1721 		}
1722 	}
1723 
1724 	path.Unset();
1725 	return B_ENTRY_NOT_FOUND;
1726 }
1727 
1728 
1729 void
1730 AboutView::_AddCopyrightsFromAttribute()
1731 {
1732 #ifdef __HAIKU__
1733 	// open the app executable file
1734 	char appPath[B_PATH_NAME_LENGTH];
1735 	int appFD;
1736 	if (BPrivate::get_app_path(appPath) != B_OK
1737 		|| (appFD = open(appPath, O_RDONLY)) < 0) {
1738 		return;
1739 	}
1740 
1741 	// open the attribute
1742 	int attrFD = fs_fopen_attr(appFD, "COPYRIGHTS", B_STRING_TYPE, O_RDONLY);
1743 	close(appFD);
1744 	if (attrFD < 0)
1745 		return;
1746 
1747 	// attach it to a FILE
1748 	FILE* attrFile = fdopen(attrFD, "r");
1749 	if (attrFile == NULL) {
1750 		close(attrFD);
1751 		return;
1752 	}
1753 	CObjectDeleter<FILE, int> _(attrFile, fclose);
1754 
1755 	// read and parse the copyrights
1756 	BMessage package;
1757 	BString fieldName;
1758 	BString fieldValue;
1759 	char lineBuffer[LINE_MAX];
1760 	while (char* line = fgets(lineBuffer, sizeof(lineBuffer), attrFile)) {
1761 		// chop off line break
1762 		size_t lineLen = strlen(line);
1763 		if (lineLen > 0 && line[lineLen - 1] == '\n')
1764 			line[--lineLen] = '\0';
1765 
1766 		// flush previous field, if a new field begins, otherwise append
1767 		if (lineLen == 0 || !isspace(line[0])) {
1768 			// new field -- flush the previous one
1769 			if (fieldName.Length() > 0) {
1770 				fieldValue = trim_string(fieldValue.String(),
1771 					fieldValue.Length());
1772 				package.AddString(fieldName.String(), fieldValue);
1773 				fieldName = "";
1774 			}
1775 		} else if (fieldName.Length() > 0) {
1776 			// append to current field
1777 			fieldValue += line;
1778 			continue;
1779 		} else {
1780 			// bogus line -- ignore
1781 			continue;
1782 		}
1783 
1784 		if (lineLen == 0)
1785 			continue;
1786 
1787 		// parse new field
1788 		char* colon = strchr(line, ':');
1789 		if (colon == NULL) {
1790 			// bogus line -- ignore
1791 			continue;
1792 		}
1793 
1794 		fieldName.SetTo(line, colon - line);
1795 		fieldName = trim_string(line, colon - line);
1796 		if (fieldName.Length() == 0) {
1797 			// invalid field name
1798 			continue;
1799 		}
1800 
1801 		fieldValue = colon + 1;
1802 
1803 		if (fieldName == "Package") {
1804 			// flush the current package
1805 			_AddPackageCredit(PackageCredit(package));
1806 			package.MakeEmpty();
1807 		}
1808 	}
1809 
1810 	// flush current package
1811 	_AddPackageCredit(PackageCredit(package));
1812 #endif
1813 }
1814 
1815 
1816 void
1817 AboutView::_AddPackageCreditEntries()
1818 {
1819 	// sort the packages case-insensitively
1820 	PackageCredit* packages[fPackageCredits.size()];
1821 	int32 count = 0;
1822 	for (PackageCreditMap::iterator it = fPackageCredits.begin();
1823 			it != fPackageCredits.end(); ++it) {
1824 		packages[count++] = it->second;
1825 	}
1826 
1827 	if (count > 1) {
1828 		std::sort(packages, packages + count,
1829 			&PackageCredit::NameLessInsensitive);
1830 	}
1831 
1832 	// add the credits
1833 	for (int32 i = 0; i < count; i++) {
1834 		PackageCredit* package = packages[i];
1835 
1836 		BString text(package->CopyrightAt(0));
1837 		int32 count = package->CountCopyrights();
1838 		for (int32 i = 1; i < count; i++)
1839 			text << "\n" << package->CopyrightAt(i);
1840 
1841 		AddCopyrightEntry(package->PackageName(), text.String(),
1842 			package->Licenses(), package->Sources(), package->URL());
1843 	}
1844 }
1845 
1846 
1847 void
1848 AboutView::_AddPackageCredit(const PackageCredit& package)
1849 {
1850 	if (!package.IsValid())
1851 		return;
1852 
1853 	PackageCreditMap::iterator it = fPackageCredits.find(package.PackageName());
1854 	if (it != fPackageCredits.end()) {
1855 		// If the new package credit isn't "better" than the old one, ignore it.
1856 		PackageCredit* oldPackage = it->second;
1857 		if (!package.IsBetterThan(*oldPackage))
1858 			return;
1859 
1860 		// replace the old credit
1861 		fPackageCredits.erase(it);
1862 		delete oldPackage;
1863 	}
1864 
1865 	fPackageCredits[package.PackageName()] = new PackageCredit(package);
1866 }
1867 
1868 
1869 //	#pragma mark -
1870 
1871 
1872 static const char*
1873 MemSizeToString(char string[], size_t size, system_info* info)
1874 {
1875 	int inaccessibleMemory = int(info->ignored_pages
1876 		* (B_PAGE_SIZE / 1048576.0f) + 0.5f);
1877 	if (inaccessibleMemory > 0) {
1878 		BString message(B_TRANSLATE("%total MiB total, %inaccessible MiB "
1879 			"inaccessible"));
1880 
1881 		snprintf(string, size, "%d", int((info->max_pages
1882 			+ info->ignored_pages) * (B_PAGE_SIZE / 1048576.0f) + 0.5f));
1883 		message.ReplaceFirst("%total", string);
1884 
1885 		snprintf(string, size, "%d", inaccessibleMemory);
1886 		message.ReplaceFirst("%inaccessible", string);
1887 		strncpy(string, message.String(), size);
1888 	} else {
1889 		snprintf(string, size, B_TRANSLATE("%d MiB total"),
1890 			int(info->max_pages * (B_PAGE_SIZE / 1048576.0f) + 0.5f));
1891 	}
1892 
1893 	return string;
1894 }
1895 
1896 
1897 static const char*
1898 MemUsageToString(char string[], size_t size, system_info* info)
1899 {
1900 	snprintf(string, size, B_TRANSLATE("%d MiB used (%d%%)"),
1901 		int(info->used_pages * (B_PAGE_SIZE / 1048576.0f) + 0.5f),
1902 		int(100 * info->used_pages / info->max_pages));
1903 
1904 	return string;
1905 }
1906 
1907 
1908 static const char*
1909 UptimeToString(char string[], size_t size)
1910 {
1911 	BDurationFormat formatter;
1912 	BString str;
1913 
1914 	bigtime_t uptime = system_time();
1915 	bigtime_t now = (bigtime_t)time(NULL) * 1000000;
1916 	formatter.Format(now - uptime, now, &str);
1917 	str.CopyInto(string, 0, size);
1918 	string[std::min((size_t)str.Length(), size)] = '\0';
1919 
1920 	return string;
1921 }
1922 
1923 
1924 int
1925 main()
1926 {
1927 	AboutApp app;
1928 	app.Run();
1929 	return 0;
1930 }
1931 
1932