netsurf/utils/messages.c
John Mark Bell f4ecaaed31 [project @ 2005-07-16 14:35:20 by jmb]
- Convert Messages files to UTF-8 encoding.
- Replace local_encoding_name() with platform specific
  utf8_[to,from]_local_encoding() functions - this allows mapping of 8bit
  characters 0x80->0x9f (inclusive).
- All text that is rendered by the RISC OS Wimp is now converted to the system
  local encoding prior to display.
- Lose the horrendous hack that was messages_get_key()
- Menu text is now translated to system local encoding on the fly (if necessary)
  rather than at menu creation time. This allows the system alphabet to change
  under us and our menus remain usable.
- The Languages menu now lists all languages that are present in the LangNames
  file. In the case of selecting the UI language, those languages which are not
  available are shaded.

svn path=/import/netsurf/; revision=1796
2005-07-16 14:35:25 +00:00

153 lines
3.2 KiB
C

/*
* This file is part of NetSurf, http://netsurf.sourceforge.net/
* Licensed under the GNU General Public License,
* http://www.opensource.org/licenses/gpl-license
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
*/
/** \file
* Localised message support (implementation).
*
* Native language messages are loaded from a file and stored hashed by key for
* fast access.
*/
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/utils.h"
/** We store the messages in a fixed-size hash table. */
#define HASH_SIZE 77
/** Maximum length of a key. */
#define MAX_KEY_LENGTH 24
/** Entry in the messages hash table. */
struct messages_entry {
struct messages_entry *next; /**< Next entry in this hash chain. */
char key[MAX_KEY_LENGTH];
char value[1];
};
/** Localised messages hash table. */
static struct messages_entry *messages_table[HASH_SIZE];
static unsigned int messages_hash(const char *s);
/**
* Read keys and values from messages file.
*
* \param path pathname of messages file
*
* The messages are merged with any previously loaded messages. Any keys which
* are present already are replaced with the new value.
*
* Exits through die() in case of error.
*/
void messages_load(const char *path)
{
char s[400];
FILE *fp;
fp = fopen(path, "r");
if (!fp) {
snprintf(s, sizeof s, "Unable to open messages file "
"\"%.100s\": %s", path, strerror(errno));
s[sizeof s - 1] = 0;
LOG(("%s", s));
die(s);
}
while (fgets(s, sizeof s, fp)) {
char *colon, *value;
unsigned int slot;
struct messages_entry *entry;
size_t length;
if (s[0] == 0 || s[0] == '#')
continue;
s[strlen(s) - 1] = 0; /* remove \n at end */
colon = strchr(s, ':');
if (!colon)
continue;
*colon = 0; /* terminate key */
value = colon + 1;
length = strlen(value);
entry = malloc(sizeof *entry + length + 1);
if (!entry) {
snprintf(s, sizeof s, "Not enough memory to load "
"messages file \"%.100s\".", path);
s[sizeof s - 1] = 0;
LOG(("%s", s));
die(s);
}
strncpy(entry->key, s, MAX_KEY_LENGTH);
strcpy(entry->value, value);
slot = messages_hash(entry->key);
entry->next = messages_table[slot];
messages_table[slot] = entry;
}
fclose(fp);
}
/**
* Fast lookup of a message by key.
*
* \param key key of message
* \return value of message, or key if not found
*/
const char *messages_get(const char *key)
{
struct messages_entry *entry;
for (entry = messages_table[messages_hash(key)];
entry && strcasecmp(entry->key, key) != 0;
entry = entry->next)
;
if (!entry)
return key;
return entry->value;
}
/**
* Hash function for keys.
*/
unsigned int messages_hash(const char *s)
{
unsigned int i, z = 0;
if (!s)
return 0;
for (i = 0; i != MAX_KEY_LENGTH && s[i]; i++)
z += s[i] & 0x1f; /* lower 5 bits, case insensitive */
return z % HASH_SIZE;
}
/**
* Dump set of loaded messages.
*/
void messages_dump(void)
{
unsigned int i;
for (i = 0; i != HASH_SIZE; i++) {
struct messages_entry *entry;
for (entry = messages_table[i]; entry; entry = entry->next)
printf("%.20s:%s\n", entry->key, entry->value);
}
}