xref: /haiku/src/kits/locale/Catalog.cpp (revision 60c26cd332a044bb9003091b9196cc404ebe5482)
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,
50 	const char *comment)
51 {
52 	const char *translated;
53 	for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
54 		translated = cat->GetString(string, context, comment);
55 		if (translated)
56 			return translated;
57 	}
58 	return string;
59 }
60 
61 
62 const char *
63 BCatalog::GetString(uint32 id)
64 {
65 	const char *translated;
66 	for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
67 		translated = cat->GetString(id);
68 		if (translated)
69 			return translated;
70 	}
71 	return "";
72 }
73 
74 
75 status_t
76 BCatalog::GetData(const char *name, BMessage *msg)
77 {
78 	if (!fCatalog)
79 		return B_NO_INIT;
80 	status_t res;
81 	for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
82 		res = cat->GetData(name, msg);
83 		if (res != B_NAME_NOT_FOUND && res != EOPNOTSUPP)
84 			return res;	// 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;	// return B_OK if found, or specific error-code
100 	}
101 	return B_NAME_NOT_FOUND;
102 }
103 
104 
105 status_t
106 BCatalog::SetCatalog(const char* signature, uint32 fingerprint)
107 {
108 	// TODO: The previous fCatalog is leaked here. (The whole chain, it
109 	// looks like.) We should take care that internal members are always
110 	// properly maintained.
111 	// No other method should touch fCatalog directly, either (constructor for
112 	// example)
113 	fCatalog
114 		= be_locale_roster->LoadCatalog(signature, NULL, fingerprint);
115 
116 	return B_OK;
117 }
118 
119 
120 status_t
121 BCatalog::GetAppCatalog(BCatalog* catalog)
122 {
123 	app_info appInfo;
124 	if (!be_app || be_app->GetAppInfo(&appInfo) != B_OK)
125 		return B_ENTRY_NOT_FOUND;
126 	BString sig(appInfo.signature);
127 
128 	// drop supertype from mimetype (should be "application/"):
129 	int32 pos = sig.FindFirst('/');
130 	if (pos >= 0)
131 		sig.Remove(0, pos+1);
132 
133 	// try to fetch fingerprint from app-file (attribute):
134 	uint32 fingerprint = 0;
135 	BNode appNode(&appInfo.ref);
136 	appNode.ReadAttr(BLocaleRoster::kCatFingerprintAttr, B_UINT32_TYPE, 0,
137 		&fingerprint, sizeof(uint32));
138 	catalog->SetCatalog(sig.String(), fingerprint);
139 	// try to load catalog (with given fingerprint):
140 
141 	// load native embedded id-based catalog. If such a catalog exists,
142 	// we can fall back to native strings for id-based access, too.
143 	BCatalogAddOn *embeddedCatalog
144 		= be_locale_roster->LoadEmbeddedCatalog(&appInfo.ref);
145 	if (embeddedCatalog) {
146 		if (!catalog->fCatalog)
147 			// embedded catalog is the only catalog that was found:
148 			catalog->fCatalog = embeddedCatalog;
149 		else {
150 			// append embedded catalog to list of loaded catalogs:
151 			BCatalogAddOn *currCat = catalog->fCatalog;
152 			while (currCat->fNext)
153 				currCat = currCat->fNext;
154 			currCat->fNext = embeddedCatalog;
155 		}
156 	}
157 
158 	// make app-catalog the current catalog for translation-macros:
159 	be_app_catalog = be_catalog = catalog;
160 
161 	return catalog->InitCheck();
162 }
163 
164 
165 //#pragma mark - BCatalogAddOn
166 BCatalogAddOn::BCatalogAddOn(const char *signature, const char *language,
167 	uint32 fingerprint)
168 	:
169 	fInitCheck(B_NO_INIT),
170 	fSignature(signature),
171 	fLanguageName(language),
172 	fFingerprint(fingerprint),
173 	fNext(NULL)
174 {
175 	fLanguageName.ToLower();
176 		// canonicalize language-name to lowercase
177 }
178 
179 
180 BCatalogAddOn::~BCatalogAddOn()
181 {
182 }
183 
184 
185 void
186 BCatalogAddOn::UpdateFingerprint()
187 {
188 	fFingerprint = 0;
189 		// base implementation always yields the same fingerprint,
190 		// which means that no version-mismatch detection is possible.
191 }
192 
193 
194 status_t
195 BCatalogAddOn::InitCheck() const
196 {
197 	return fInitCheck;
198 }
199 
200 
201 bool
202 BCatalogAddOn::CanHaveData() const
203 {
204 	return false;
205 }
206 
207 
208 status_t
209 BCatalogAddOn::GetData(const char *name, BMessage *msg)
210 {
211 	return EOPNOTSUPP;
212 }
213 
214 
215 status_t
216 BCatalogAddOn::GetData(uint32 id, BMessage *msg)
217 {
218 	return EOPNOTSUPP;
219 }
220 
221 
222 status_t
223 BCatalogAddOn::SetString(const char *string, const char *translated,
224 	const char *context, const char *comment)
225 {
226 	return EOPNOTSUPP;
227 }
228 
229 
230 status_t
231 BCatalogAddOn::SetString(int32 id, const char *translated)
232 {
233 	return EOPNOTSUPP;
234 }
235 
236 
237 bool
238 BCatalogAddOn::CanWriteData() const
239 {
240 	return false;
241 }
242 
243 
244 status_t
245 BCatalogAddOn::SetData(const char *name, BMessage *msg)
246 {
247 	return EOPNOTSUPP;
248 }
249 
250 
251 status_t
252 BCatalogAddOn::SetData(uint32 id, BMessage *msg)
253 {
254 	return EOPNOTSUPP;
255 }
256 
257 
258 status_t
259 BCatalogAddOn::ReadFromFile(const char *path)
260 {
261 	return EOPNOTSUPP;
262 }
263 
264 
265 status_t
266 BCatalogAddOn::ReadFromAttribute(entry_ref *appOrAddOnRef)
267 {
268 	return EOPNOTSUPP;
269 }
270 
271 
272 status_t
273 BCatalogAddOn::ReadFromResource(entry_ref *appOrAddOnRef)
274 {
275 	return EOPNOTSUPP;
276 }
277 
278 
279 status_t
280 BCatalogAddOn::WriteToFile(const char *path)
281 {
282 	return EOPNOTSUPP;
283 }
284 
285 
286 status_t
287 BCatalogAddOn::WriteToAttribute(entry_ref *appOrAddOnRef)
288 {
289 	return EOPNOTSUPP;
290 }
291 
292 
293 status_t
294 BCatalogAddOn::WriteToResource(entry_ref *appOrAddOnRef)
295 {
296 	return EOPNOTSUPP;
297 }
298 
299 
300 void BCatalogAddOn::MakeEmpty()
301 {
302 }
303 
304 
305 int32
306 BCatalogAddOn::CountItems() const
307 {
308 	return 0;
309 }
310 
311 
312 //#pragma mark - EditableCatalog
313 namespace BPrivate {
314 EditableCatalog::EditableCatalog(const char *type, const char *signature,
315 	const char *language)
316 {
317 	fCatalog = be_locale_roster->CreateCatalog(type, signature, language);
318 }
319 
320 
321 EditableCatalog::~EditableCatalog()
322 {
323 }
324 
325 
326 status_t
327 EditableCatalog::SetString(const char *string, const char *translated,
328 	const char *context, const char *comment)
329 {
330 	if (!fCatalog)
331 		return B_NO_INIT;
332 	return fCatalog->SetString(string, translated, context, comment);
333 }
334 
335 
336 status_t
337 EditableCatalog::SetString(int32 id, const char *translated)
338 {
339 	if (!fCatalog)
340 		return B_NO_INIT;
341 	return fCatalog->SetString(id, translated);
342 }
343 
344 
345 bool
346 EditableCatalog::CanWriteData() const
347 {
348 	if (!fCatalog)
349 		return false;
350 	return fCatalog->CanWriteData();
351 }
352 
353 
354 status_t
355 EditableCatalog::SetData(const char *name, BMessage *msg)
356 {
357 	if (!fCatalog)
358 		return B_NO_INIT;
359 	return fCatalog->SetData(name, msg);
360 }
361 
362 
363 status_t
364 EditableCatalog::SetData(uint32 id, BMessage *msg)
365 {
366 	if (!fCatalog)
367 		return B_NO_INIT;
368 	return fCatalog->SetData(id, msg);
369 }
370 
371 
372 status_t
373 EditableCatalog::ReadFromFile(const char *path)
374 {
375 	if (!fCatalog)
376 		return B_NO_INIT;
377 	return fCatalog->ReadFromFile(path);
378 }
379 
380 
381 status_t
382 EditableCatalog::ReadFromAttribute(entry_ref *appOrAddOnRef)
383 {
384 	if (!fCatalog)
385 		return B_NO_INIT;
386 	return fCatalog->ReadFromAttribute(appOrAddOnRef);
387 }
388 
389 
390 status_t
391 EditableCatalog::ReadFromResource(entry_ref *appOrAddOnRef)
392 {
393 	if (!fCatalog)
394 		return B_NO_INIT;
395 	return fCatalog->ReadFromResource(appOrAddOnRef);
396 }
397 
398 
399 status_t
400 EditableCatalog::WriteToFile(const char *path)
401 {
402 	if (!fCatalog)
403 		return B_NO_INIT;
404 	return fCatalog->WriteToFile(path);
405 }
406 
407 
408 status_t
409 EditableCatalog::WriteToAttribute(entry_ref *appOrAddOnRef)
410 {
411 	if (!fCatalog)
412 		return B_NO_INIT;
413 	return fCatalog->WriteToAttribute(appOrAddOnRef);
414 }
415 
416 
417 status_t
418 EditableCatalog::WriteToResource(entry_ref *appOrAddOnRef)
419 {
420 	if (!fCatalog)
421 		return B_NO_INIT;
422 	return fCatalog->WriteToResource(appOrAddOnRef);
423 }
424 
425 
426 void EditableCatalog::MakeEmpty()
427 {
428 	if (fCatalog)
429 		fCatalog->MakeEmpty();
430 }
431 
432 
433 } // namespace BPrivate
434