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