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