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