1/*
2 * Copyright 2008 Ralf Sch��lke, ralf.schuelke@googlemail.com.
3 * Copyright 2014 Haiku, Inc. All rights reserved.
4 *
5 * Distributed under the terms of the MIT License.
6 *
7 * Authors:
8 *		Ralf Sch��lke, ralf.schuelke@googlemail.com
9 *		John Scipione, jscipione@gmail.com
10 */
11
12
13#include "Pairs.h"
14
15#include <stdio.h>
16	// for snprintf()
17#include <stdlib.h>
18
19#include <Alert.h>
20#include <Catalog.h>
21#include <Message.h>
22#include <MimeType.h>
23#include <String.h>
24
25#include "PairsWindow.h"
26
27
28#undef B_TRANSLATION_CONTEXT
29#define B_TRANSLATION_CONTEXT "Pairs"
30
31
32const char* kSignature = "application/x-vnd.Haiku-Pairs";
33
34static const size_t kMinIconCount = 64;
35static const size_t kMaxIconCount = 384;
36
37
38//	#pragma mark - Pairs
39
40
41Pairs::Pairs()
42	:
43	BApplication(kSignature),
44	fWindow(NULL)
45{
46	_GetVectorIcons();
47}
48
49
50Pairs::~Pairs()
51{
52}
53
54
55void
56Pairs::ReadyToRun()
57{
58	fWindow = new PairsWindow();
59	fWindow->Show();
60}
61
62
63void
64Pairs::RefsReceived(BMessage* message)
65{
66	fWindow->PostMessage(message);
67}
68
69
70void
71Pairs::MessageReceived(BMessage* message)
72{
73	BApplication::MessageReceived(message);
74}
75
76
77bool
78Pairs::QuitRequested()
79{
80	// delete vector icons
81	for (IconMap::iterator iter = fIconMap.begin(); iter != fIconMap.end();
82			++iter) {
83		delete fIconMap[iter->first];
84	}
85
86	return true;
87}
88
89
90//	#pragma mark - Pairs private methods
91
92
93void
94Pairs::_GetVectorIcons()
95{
96	// Load vector icons from the MIME type database and add a pointer to them
97	// into a std::map keyed by a generated hash.
98
99	BMessage types;
100	if (BMimeType::GetInstalledTypes("application", &types) != B_OK)
101		return;
102
103	const char* type;
104	for (int32 i = 0; types.FindString("types", i, &type) == B_OK; i++) {
105		BMimeType mimeType(type);
106		if (mimeType.InitCheck() != B_OK)
107			continue;
108
109		uint8* data;
110		size_t size;
111
112		if (mimeType.GetIcon(&data, &size) != B_OK) {
113			// didn't find an icon
114			continue;
115		}
116
117		size_t hash = 0xdeadbeef;
118		for (size_t i = 0; i < size; i++)
119			hash = 31 * hash + data[i];
120
121		if (fIconMap.find(hash) != fIconMap.end()) {
122			// key has already been added to the map
123			delete[] data;
124			continue;
125		}
126
127		vector_icon* icon = (vector_icon*)malloc(sizeof(vector_icon));
128		if (icon == NULL) {
129			delete[] data;
130			free(icon);
131			continue;
132		}
133
134		icon->data = data;
135		icon->size = size;
136
137		// found a vector icon, add it to the list
138		fIconMap[hash] = icon;
139		if (fIconMap.size() >= kMaxIconCount) {
140			// this is enough to choose from, stop eating memory...
141			return;
142		}
143	}
144
145	if (fIconMap.size() < kMinIconCount) {
146		char buffer[512];
147		snprintf(buffer, sizeof(buffer),
148			B_TRANSLATE_COMMENT("Pairs did not find enough vector icons "
149			"to start; it needs at least %zu, found %zu.\n",
150			"Don't translate \"%zu\", but make sure to keep them."),
151			kMinIconCount, fIconMap.size());
152		BString messageString(buffer);
153		BAlert* alert = new BAlert("Fatal", messageString.String(),
154			B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST,
155			B_STOP_ALERT);
156		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
157		alert->Go();
158		exit(1);
159	}
160}
161
162
163//	#pragma mark - main
164
165
166int
167main(void)
168{
169	Pairs pairs;
170	pairs.Run();
171
172	return 0;
173}
174