xref: /haiku/src/kits/locale/Catalog.cpp (revision 03187b607b2b5eec7ee059f1ead09bdba14991fb)
1 /*
2  * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de
3  * Copyright 2003-2004, Oliver Tappe, zooey@hirschkaefer.de
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include <Catalog.h>
8 
9 #include <syslog.h>
10 
11 #include <Application.h>
12 #include <Locale.h>
13 #include <LocaleRoster.h>
14 #include <Node.h>
15 #include <Roster.h>
16 
17 
18 BCatalog* be_catalog = NULL;
19 	// catalog used by translation macros
20 BCatalog* be_app_catalog = NULL;
21 	// app-catalog (useful for accessing app's catalog from inside an add-on,
22 	// since in an add-on, be_catalog will hold the add-on's catalog.
23 
24 
25 //#pragma mark - BCatalog
26 BCatalog::BCatalog()
27 	:
28 	fCatalog(NULL)
29 {
30 }
31 
32 
33 BCatalog::BCatalog(const char *signature, const char *language,
34 	uint32 fingerprint)
35 {
36 	fCatalog = be_locale_roster->LoadCatalog(signature, language, fingerprint);
37 }
38 
39 
40 BCatalog::~BCatalog()
41 {
42 	if (be_catalog == this)
43 		be_app_catalog = be_catalog = NULL;
44 	be_locale_roster->UnloadCatalog(fCatalog);
45 }
46 
47 
48 const char *
49 BCatalog::GetString(const char *string, const char *context, const char *comment)
50 {
51 	const char *translated;
52 	for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
53 		translated = cat->GetString(string, context, comment);
54 		if (translated)
55 			return translated;
56 	}
57 	return string;
58 }
59 
60 
61 const char *
62 BCatalog::GetString(uint32 id)
63 {
64 	const char *translated;
65 	for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
66 		translated = cat->GetString(id);
67 		if (translated)
68 			return translated;
69 	}
70 	return "";
71 }
72 
73 
74 status_t
75 BCatalog::GetData(const char *name, BMessage *msg)
76 {
77 	if (!fCatalog)
78 		return B_NO_INIT;
79 	status_t res;
80 	for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
81 		res = cat->GetData(name, msg);
82 		if (res != B_NAME_NOT_FOUND && res != EOPNOTSUPP)
83 			return res;
84 				// return B_OK if found, or specific error-code
85 	}
86 	return B_NAME_NOT_FOUND;
87 }
88 
89 
90 status_t
91 BCatalog::GetData(uint32 id, BMessage *msg)
92 {
93 	if (!fCatalog)
94 		return B_NO_INIT;
95 	status_t res;
96 	for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
97 		res = cat->GetData(id, msg);
98 		if (res != B_NAME_NOT_FOUND && res != EOPNOTSUPP)
99 			return res;
100 				// return B_OK if found, or specific error-code
101 	}
102 	return B_NAME_NOT_FOUND;
103 }
104 
105 
106 status_t
107 BCatalog::GetAppCatalog(BCatalog* catalog)
108 {
109 	app_info appInfo;
110 	if (!be_app || be_app->GetAppInfo(&appInfo) != B_OK)
111 		return B_ENTRY_NOT_FOUND;
112 	BString sig(appInfo.signature);
113 
114 	// drop supertype from mimetype (should be "application/"):
115 	int32 pos = sig.FindFirst('/');
116 	if (pos >= 0)
117 		sig.Remove(0, pos+1);
118 
119 	// try to fetch fingerprint from app-file (attribute):
120 	uint32 fingerprint = 0;
121 	BNode appNode(&appInfo.ref);
122 	appNode.ReadAttr(BLocaleRoster::kCatFingerprintAttr, B_UINT32_TYPE, 0,
123 		&fingerprint, sizeof(uint32));
124 	// try to load catalog (with given fingerprint):
125 	catalog->fCatalog
126 		= be_locale_roster->LoadCatalog(sig.String(), NULL,	fingerprint);
127 
128 	// load native embedded id-based catalog. If such a catalog exists,
129 	// we can fall back to native strings for id-based access, too.
130 	BCatalogAddOn *embeddedCatalog
131 		= be_locale_roster->LoadEmbeddedCatalog(&appInfo.ref);
132 	if (embeddedCatalog) {
133 		if (!catalog->fCatalog)
134 			// embedded catalog is the only catalog that was found:
135 			catalog->fCatalog = embeddedCatalog;
136 		else {
137 			// append embedded catalog to list of loaded catalogs:
138 			BCatalogAddOn *currCat = catalog->fCatalog;
139 			while (currCat->fNext)
140 				currCat = currCat->fNext;
141 			currCat->fNext = embeddedCatalog;
142 		}
143 	}
144 
145 	// make app-catalog the current catalog for translation-macros:
146 	be_app_catalog = be_catalog = catalog;
147 
148 	return catalog->InitCheck();
149 }
150 
151 
152 //#pragma mark - BCatalogAddOn
153 BCatalogAddOn::BCatalogAddOn(const char *signature, const char *language,
154 	uint32 fingerprint)
155 	:
156 	fInitCheck(B_NO_INIT),
157 	fSignature(signature),
158 	fLanguageName(language),
159 	fFingerprint(fingerprint),
160 	fNext(NULL)
161 {
162 	fLanguageName.ToLower();
163 		// canonicalize language-name to lowercase
164 }
165 
166 
167 BCatalogAddOn::~BCatalogAddOn()
168 {
169 }
170 
171 
172 void
173 BCatalogAddOn::UpdateFingerprint()
174 {
175 	fFingerprint = 0;
176 		// base implementation always yields the same fingerprint,
177 		// which means that no version-mismatch detection is possible.
178 }
179 
180 
181 status_t
182 BCatalogAddOn::InitCheck() const
183 {
184 	return fInitCheck;
185 }
186 
187 
188 bool
189 BCatalogAddOn::CanHaveData() const
190 {
191 	return false;
192 }
193 
194 
195 status_t
196 BCatalogAddOn::GetData(const char *name, BMessage *msg)
197 {
198 	return EOPNOTSUPP;
199 }
200 
201 
202 status_t
203 BCatalogAddOn::GetData(uint32 id, BMessage *msg)
204 {
205 	return EOPNOTSUPP;
206 }
207 
208 
209 status_t
210 BCatalogAddOn::SetString(const char *string, const char *translated,
211 	const char *context, const char *comment)
212 {
213 	return EOPNOTSUPP;
214 }
215 
216 
217 status_t
218 BCatalogAddOn::SetString(int32 id, const char *translated)
219 {
220 	return EOPNOTSUPP;
221 }
222 
223 
224 bool
225 BCatalogAddOn::CanWriteData() const
226 {
227 	return false;
228 }
229 
230 
231 status_t
232 BCatalogAddOn::SetData(const char *name, BMessage *msg)
233 {
234 	return EOPNOTSUPP;
235 }
236 
237 
238 status_t
239 BCatalogAddOn::SetData(uint32 id, BMessage *msg)
240 {
241 	return EOPNOTSUPP;
242 }
243 
244 
245 status_t
246 BCatalogAddOn::ReadFromFile(const char *path)
247 {
248 	return EOPNOTSUPP;
249 }
250 
251 
252 status_t
253 BCatalogAddOn::ReadFromAttribute(entry_ref *appOrAddOnRef)
254 {
255 	return EOPNOTSUPP;
256 }
257 
258 
259 status_t
260 BCatalogAddOn::ReadFromResource(entry_ref *appOrAddOnRef)
261 {
262 	return EOPNOTSUPP;
263 }
264 
265 
266 status_t
267 BCatalogAddOn::WriteToFile(const char *path)
268 {
269 	return EOPNOTSUPP;
270 }
271 
272 
273 status_t
274 BCatalogAddOn::WriteToAttribute(entry_ref *appOrAddOnRef)
275 {
276 	return EOPNOTSUPP;
277 }
278 
279 
280 status_t
281 BCatalogAddOn::WriteToResource(entry_ref *appOrAddOnRef)
282 {
283 	return EOPNOTSUPP;
284 }
285 
286 
287 void BCatalogAddOn::MakeEmpty()
288 {
289 }
290 
291 
292 int32
293 BCatalogAddOn::CountItems() const
294 {
295 	return 0;
296 }
297 
298 
299 //#pragma mark - EditableCatalog
300 namespace BPrivate {
301 EditableCatalog::EditableCatalog(const char *type, const char *signature,
302 	const char *language)
303 {
304 	fCatalog = be_locale_roster->CreateCatalog(type, signature, language);
305 }
306 
307 
308 EditableCatalog::~EditableCatalog()
309 {
310 }
311 
312 
313 status_t
314 EditableCatalog::SetString(const char *string, const char *translated,
315 	const char *context, const char *comment)
316 {
317 	if (!fCatalog)
318 		return B_NO_INIT;
319 	return fCatalog->SetString(string, translated, context, comment);
320 }
321 
322 
323 status_t
324 EditableCatalog::SetString(int32 id, const char *translated)
325 {
326 	if (!fCatalog)
327 		return B_NO_INIT;
328 	return fCatalog->SetString(id, translated);
329 }
330 
331 
332 bool
333 EditableCatalog::CanWriteData() const
334 {
335 	if (!fCatalog)
336 		return false;
337 	return fCatalog->CanWriteData();
338 }
339 
340 
341 status_t
342 EditableCatalog::SetData(const char *name, BMessage *msg)
343 {
344 	if (!fCatalog)
345 		return B_NO_INIT;
346 	return fCatalog->SetData(name, msg);
347 }
348 
349 
350 status_t
351 EditableCatalog::SetData(uint32 id, BMessage *msg)
352 {
353 	if (!fCatalog)
354 		return B_NO_INIT;
355 	return fCatalog->SetData(id, msg);
356 }
357 
358 
359 status_t
360 EditableCatalog::ReadFromFile(const char *path)
361 {
362 	if (!fCatalog)
363 		return B_NO_INIT;
364 	return fCatalog->ReadFromFile(path);
365 }
366 
367 
368 status_t
369 EditableCatalog::ReadFromAttribute(entry_ref *appOrAddOnRef)
370 {
371 	if (!fCatalog)
372 		return B_NO_INIT;
373 	return fCatalog->ReadFromAttribute(appOrAddOnRef);
374 }
375 
376 
377 status_t
378 EditableCatalog::ReadFromResource(entry_ref *appOrAddOnRef)
379 {
380 	if (!fCatalog)
381 		return B_NO_INIT;
382 	return fCatalog->ReadFromResource(appOrAddOnRef);
383 }
384 
385 
386 status_t
387 EditableCatalog::WriteToFile(const char *path)
388 {
389 	if (!fCatalog)
390 		return B_NO_INIT;
391 	return fCatalog->WriteToFile(path);
392 }
393 
394 
395 status_t
396 EditableCatalog::WriteToAttribute(entry_ref *appOrAddOnRef)
397 {
398 	if (!fCatalog)
399 		return B_NO_INIT;
400 	return fCatalog->WriteToAttribute(appOrAddOnRef);
401 }
402 
403 
404 status_t
405 EditableCatalog::WriteToResource(entry_ref *appOrAddOnRef)
406 {
407 	if (!fCatalog)
408 		return B_NO_INIT;
409 	return fCatalog->WriteToResource(appOrAddOnRef);
410 }
411 
412 
413 void EditableCatalog::MakeEmpty()
414 {
415 	if (fCatalog)
416 		fCatalog->MakeEmpty();
417 }
418 
419 
420 } // namespace BPrivate
421