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