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