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, const char *comment) 50 { 51 const char *translated; 52 for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) { 53 translated = cat->GetString(string, context, comment); 54 if (translated) 55 return translated; 56 } 57 return string; 58 } 59 60 61 const char * 62 BCatalog::GetString(uint32 id) 63 { 64 const char *translated; 65 for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) { 66 translated = cat->GetString(id); 67 if (translated) 68 return translated; 69 } 70 return ""; 71 } 72 73 74 status_t 75 BCatalog::GetData(const char *name, BMessage *msg) 76 { 77 if (!fCatalog) 78 return B_NO_INIT; 79 status_t res; 80 for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) { 81 res = cat->GetData(name, msg); 82 if (res != B_NAME_NOT_FOUND && res != EOPNOTSUPP) 83 return res; 84 // 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; 100 // return B_OK if found, or specific error-code 101 } 102 return B_NAME_NOT_FOUND; 103 } 104 105 106 status_t 107 BCatalog::GetAppCatalog(BCatalog* catalog) 108 { 109 app_info appInfo; 110 if (!be_app || be_app->GetAppInfo(&appInfo) != B_OK) 111 return B_ENTRY_NOT_FOUND; 112 BString sig(appInfo.signature); 113 114 // drop supertype from mimetype (should be "application/"): 115 int32 pos = sig.FindFirst('/'); 116 if (pos >= 0) 117 sig.Remove(0, pos+1); 118 119 // try to fetch fingerprint from app-file (attribute): 120 uint32 fingerprint = 0; 121 BNode appNode(&appInfo.ref); 122 appNode.ReadAttr(BLocaleRoster::kCatFingerprintAttr, B_UINT32_TYPE, 0, 123 &fingerprint, sizeof(uint32)); 124 // try to load catalog (with given fingerprint): 125 catalog->fCatalog 126 = be_locale_roster->LoadCatalog(sig.String(), NULL, fingerprint); 127 128 // load native embedded id-based catalog. If such a catalog exists, 129 // we can fall back to native strings for id-based access, too. 130 BCatalogAddOn *embeddedCatalog 131 = be_locale_roster->LoadEmbeddedCatalog(&appInfo.ref); 132 if (embeddedCatalog) { 133 if (!catalog->fCatalog) 134 // embedded catalog is the only catalog that was found: 135 catalog->fCatalog = embeddedCatalog; 136 else { 137 // append embedded catalog to list of loaded catalogs: 138 BCatalogAddOn *currCat = catalog->fCatalog; 139 while (currCat->fNext) 140 currCat = currCat->fNext; 141 currCat->fNext = embeddedCatalog; 142 } 143 } 144 145 // make app-catalog the current catalog for translation-macros: 146 be_app_catalog = be_catalog = catalog; 147 148 return catalog->InitCheck(); 149 } 150 151 152 //#pragma mark - BCatalogAddOn 153 BCatalogAddOn::BCatalogAddOn(const char *signature, const char *language, 154 uint32 fingerprint) 155 : 156 fInitCheck(B_NO_INIT), 157 fSignature(signature), 158 fLanguageName(language), 159 fFingerprint(fingerprint), 160 fNext(NULL) 161 { 162 fLanguageName.ToLower(); 163 // canonicalize language-name to lowercase 164 } 165 166 167 BCatalogAddOn::~BCatalogAddOn() 168 { 169 } 170 171 172 void 173 BCatalogAddOn::UpdateFingerprint() 174 { 175 fFingerprint = 0; 176 // base implementation always yields the same fingerprint, 177 // which means that no version-mismatch detection is possible. 178 } 179 180 181 status_t 182 BCatalogAddOn::InitCheck() const 183 { 184 return fInitCheck; 185 } 186 187 188 bool 189 BCatalogAddOn::CanHaveData() const 190 { 191 return false; 192 } 193 194 195 status_t 196 BCatalogAddOn::GetData(const char *name, BMessage *msg) 197 { 198 return EOPNOTSUPP; 199 } 200 201 202 status_t 203 BCatalogAddOn::GetData(uint32 id, BMessage *msg) 204 { 205 return EOPNOTSUPP; 206 } 207 208 209 status_t 210 BCatalogAddOn::SetString(const char *string, const char *translated, 211 const char *context, const char *comment) 212 { 213 return EOPNOTSUPP; 214 } 215 216 217 status_t 218 BCatalogAddOn::SetString(int32 id, const char *translated) 219 { 220 return EOPNOTSUPP; 221 } 222 223 224 bool 225 BCatalogAddOn::CanWriteData() const 226 { 227 return false; 228 } 229 230 231 status_t 232 BCatalogAddOn::SetData(const char *name, BMessage *msg) 233 { 234 return EOPNOTSUPP; 235 } 236 237 238 status_t 239 BCatalogAddOn::SetData(uint32 id, BMessage *msg) 240 { 241 return EOPNOTSUPP; 242 } 243 244 245 status_t 246 BCatalogAddOn::ReadFromFile(const char *path) 247 { 248 return EOPNOTSUPP; 249 } 250 251 252 status_t 253 BCatalogAddOn::ReadFromAttribute(entry_ref *appOrAddOnRef) 254 { 255 return EOPNOTSUPP; 256 } 257 258 259 status_t 260 BCatalogAddOn::ReadFromResource(entry_ref *appOrAddOnRef) 261 { 262 return EOPNOTSUPP; 263 } 264 265 266 status_t 267 BCatalogAddOn::WriteToFile(const char *path) 268 { 269 return EOPNOTSUPP; 270 } 271 272 273 status_t 274 BCatalogAddOn::WriteToAttribute(entry_ref *appOrAddOnRef) 275 { 276 return EOPNOTSUPP; 277 } 278 279 280 status_t 281 BCatalogAddOn::WriteToResource(entry_ref *appOrAddOnRef) 282 { 283 return EOPNOTSUPP; 284 } 285 286 287 void BCatalogAddOn::MakeEmpty() 288 { 289 } 290 291 292 int32 293 BCatalogAddOn::CountItems() const 294 { 295 return 0; 296 } 297 298 299 //#pragma mark - EditableCatalog 300 namespace BPrivate { 301 EditableCatalog::EditableCatalog(const char *type, const char *signature, 302 const char *language) 303 { 304 fCatalog = be_locale_roster->CreateCatalog(type, signature, language); 305 } 306 307 308 EditableCatalog::~EditableCatalog() 309 { 310 } 311 312 313 status_t 314 EditableCatalog::SetString(const char *string, const char *translated, 315 const char *context, const char *comment) 316 { 317 if (!fCatalog) 318 return B_NO_INIT; 319 return fCatalog->SetString(string, translated, context, comment); 320 } 321 322 323 status_t 324 EditableCatalog::SetString(int32 id, const char *translated) 325 { 326 if (!fCatalog) 327 return B_NO_INIT; 328 return fCatalog->SetString(id, translated); 329 } 330 331 332 bool 333 EditableCatalog::CanWriteData() const 334 { 335 if (!fCatalog) 336 return false; 337 return fCatalog->CanWriteData(); 338 } 339 340 341 status_t 342 EditableCatalog::SetData(const char *name, BMessage *msg) 343 { 344 if (!fCatalog) 345 return B_NO_INIT; 346 return fCatalog->SetData(name, msg); 347 } 348 349 350 status_t 351 EditableCatalog::SetData(uint32 id, BMessage *msg) 352 { 353 if (!fCatalog) 354 return B_NO_INIT; 355 return fCatalog->SetData(id, msg); 356 } 357 358 359 status_t 360 EditableCatalog::ReadFromFile(const char *path) 361 { 362 if (!fCatalog) 363 return B_NO_INIT; 364 return fCatalog->ReadFromFile(path); 365 } 366 367 368 status_t 369 EditableCatalog::ReadFromAttribute(entry_ref *appOrAddOnRef) 370 { 371 if (!fCatalog) 372 return B_NO_INIT; 373 return fCatalog->ReadFromAttribute(appOrAddOnRef); 374 } 375 376 377 status_t 378 EditableCatalog::ReadFromResource(entry_ref *appOrAddOnRef) 379 { 380 if (!fCatalog) 381 return B_NO_INIT; 382 return fCatalog->ReadFromResource(appOrAddOnRef); 383 } 384 385 386 status_t 387 EditableCatalog::WriteToFile(const char *path) 388 { 389 if (!fCatalog) 390 return B_NO_INIT; 391 return fCatalog->WriteToFile(path); 392 } 393 394 395 status_t 396 EditableCatalog::WriteToAttribute(entry_ref *appOrAddOnRef) 397 { 398 if (!fCatalog) 399 return B_NO_INIT; 400 return fCatalog->WriteToAttribute(appOrAddOnRef); 401 } 402 403 404 status_t 405 EditableCatalog::WriteToResource(entry_ref *appOrAddOnRef) 406 { 407 if (!fCatalog) 408 return B_NO_INIT; 409 return fCatalog->WriteToResource(appOrAddOnRef); 410 } 411 412 413 void EditableCatalog::MakeEmpty() 414 { 415 if (fCatalog) 416 fCatalog->MakeEmpty(); 417 } 418 419 420 } // namespace BPrivate 421