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