const char * I18n_GetString(const char *domain, const char *msgid) { const char *idp; const char *strp; char idBuf[MSG_MAX_ID]; size_t len; GHashTable *source = NULL; MsgCatalog *catalog; MsgState *state = MsgGetState(); /* All message strings must be prefixed by the message ID. */ ASSERT(domain != NULL); ASSERT(msgid != NULL); ASSERT(MsgHasMsgID(msgid)); /* * Find the beginning of the ID (idp) and the string (strp). * The string should have the correct MSG_MAGIC(...)... form. */ idp = msgid + MSG_MAGIC_LEN + 1; strp = strchr(idp, ')') + 1; len = strp - idp - 1; ASSERT(len <= MSG_MAX_ID - 1); memcpy(idBuf, idp, len); idBuf[len] = '\0'; g_static_mutex_lock(&state->lock); catalog = MsgGetCatalog(domain); if (catalog != NULL) { source = catalog->utf8; } if (source != NULL) { const void *retval = NULL; retval = g_hash_table_lookup(source, idBuf); if (NULL != retval) { strp = retval; } } g_static_mutex_unlock(&state->lock); return strp; }
static const void * MsgGetString(const char *domain, const char *msgid, StringEncoding encoding) { const char *idp; const char *strp; char idBuf[MSG_MAX_ID]; size_t len; HashTable *source = NULL; MsgCatalog *catalog; MsgState *state = MsgGetState(); /* All message strings must be prefixed by the message ID. */ ASSERT(domain != NULL); ASSERT(msgid != NULL); ASSERT(MsgHasMsgID(msgid)); #if defined(_WIN32) ASSERT(encoding == STRING_ENCODING_UTF8 || encoding == STRING_ENCODING_UTF16_LE); #else ASSERT(encoding == STRING_ENCODING_UTF8); #endif /* * Find the beginning of the ID (idp) and the string (strp). * The string should have the correct MSG_MAGIC(...)... form. */ idp = msgid + MSG_MAGIC_LEN + 1; strp = strchr(idp, ')') + 1; len = strp - idp - 1; ASSERT_NOT_IMPLEMENTED(len <= MSG_MAX_ID - 1); memcpy(idBuf, idp, len); idBuf[len] = '\0'; /* * This lock is pretty coarse-grained, but a lot of the code below just runs * in exceptional situations, so it should be OK. */ g_static_mutex_lock(&state->lock); catalog = MsgGetCatalog(domain); if (catalog != NULL) { switch (encoding) { case STRING_ENCODING_UTF8: source = catalog->utf8; break; #if defined(_WIN32) case STRING_ENCODING_UTF16_LE: source = catalog->utf16; break; #endif default: NOT_IMPLEMENTED(); } } #if defined(_WIN32) /* * Lazily create the local and UTF-16 dictionaries. This may require also * registering an empty message catalog for the desired domain. */ if (source == NULL && encoding == STRING_ENCODING_UTF16_LE) { catalog = MsgGetCatalog(domain); if (catalog == NULL) { if (domain == NULL) { g_error("Application did not set up a default text domain."); } catalog = g_new0(MsgCatalog, 1); MsgSetCatalog(domain, catalog); } catalog->utf16 = HashTable_Alloc(8, HASH_STRING_KEY, g_free); ASSERT_MEM_ALLOC(catalog->utf16); source = catalog->utf16; } #endif /* * Look up the localized string, converting to requested encoding as needed. */ if (source != NULL) { const void *retval = NULL; if (HashTable_Lookup(source, idBuf, (void **) &retval)) { strp = retval; #if defined(_WIN32) } else if (encoding == STRING_ENCODING_UTF16_LE) { gchar *converted; Bool success; /* * Look up the string in UTF-8, convert it and cache it. */ retval = MsgGetString(domain, msgid, STRING_ENCODING_UTF8); ASSERT(retval); converted = (gchar *) g_utf8_to_utf16(retval, -1, NULL, NULL, NULL); ASSERT(converted != NULL); success = HashTable_Insert(source, idBuf, converted); ASSERT(success); strp = converted; #endif } } g_static_mutex_unlock(&state->lock); return strp; }