170 lines
3.6 KiB
C
170 lines
3.6 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[300];
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the key associated with a value
|
|
*
|
|
* \param value The value as returned by messages_get
|
|
* \return The key associated with the value or NULL if not found
|
|
*/
|
|
const char *messages_get_key(const char *value)
|
|
{
|
|
const char *key = value - MAX_KEY_LENGTH;
|
|
const char *temp_value = messages_get(key);
|
|
|
|
if (strcmp(value, temp_value) == 0)
|
|
return key;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
}
|