static HASH *Translations = NULL;
static HASH *Charsets = NULL;
+static HASH *CharsetAliases = NULL;
static CHARSET *mutt_new_charset(void)
{
CHARSET *chs;
chs = safe_malloc(sizeof(CHARSET));
- chs->name = NULL;
chs->map = NULL;
return chs;
{
CHARSET *chs = *chsp;
- safe_free((void **) &chs->name);
safe_free((void **) &chs->map);
safe_free((void **) chsp);
}
int i;
chs = mutt_new_charset();
- chs->name = safe_strdup(name);
-
+
snprintf(path, sizeof(path), "%s/charsets/%s", SHAREDIR, name);
if((fp = fopen(path, "r")) == NULL)
goto bail;
if(strcmp(buffer, CHARSET_MAGIC) != 0)
goto bail;
- chs->map = safe_malloc(sizeof(UNICODE_MAP));
+ chs->map = safe_malloc(sizeof(CHARSET_MAP));
for(i = 0; i < 256; i++)
{
return chs;
}
+static HASH *load_charset_aliases(void)
+{
+ FILE *fp;
+ char buffer[LONG_STRING];
+ char *t;
+ HASH *charset_aliases;
+
+ sprintf(buffer, "%s/charsets/charsets.alias", SHAREDIR);
+ if(!(fp = fopen(buffer, "r")))
+ return NULL;
+
+ charset_aliases = hash_create(256);
+
+ while(fgets(buffer, sizeof(buffer), fp))
+ {
+ if((t = strchr(buffer, '\n')))
+ *t = '\0';
+
+ if(!(t = strchr(buffer, ' ')))
+ continue;
+
+ *t++ = '\0';
+ hash_insert(charset_aliases, safe_strdup(buffer), safe_strdup(t), 1);
+ }
+ fclose(fp);
+ return charset_aliases;
+}
+
static void init_charsets()
{
if(Charsets) return;
- Charsets = hash_create(128);
- Translations = hash_create(256);
+ Charsets = hash_create(128);
+ Translations = hash_create(256);
+ CharsetAliases = load_charset_aliases();
}
CHARSET *mutt_get_charset(const char *name)
{
CHARSET *charset;
char buffer[SHORT_STRING];
+ char *real_charset;
init_charsets();
canonical_charset(buffer, sizeof(buffer), name);
- if(!(charset = hash_find(Charsets, buffer)))
+
+ if(!CharsetAliases || !(real_charset = hash_find(CharsetAliases, buffer)))
+ real_charset = buffer;
+
+ if(!(charset = hash_find(Charsets, real_charset)))
{
- charset = load_charset(buffer);
- hash_insert(Charsets, buffer, charset, 0);
+ charset = load_charset(real_charset);
+ hash_insert(Charsets, safe_strdup(real_charset), charset, 1);
}
return charset;
}
-static int translate_char(UNICODE_MAP *to, int ch)
+static int translate_char(CHARSET_MAP *to, int ch)
{
int i;
return '?';
}
-UNICODE_MAP *build_translation(UNICODE_MAP *from, UNICODE_MAP *to)
+CHARSET_MAP *build_translation(CHARSET_MAP *from, CHARSET_MAP *to)
{
int i;
- UNICODE_MAP *map = safe_malloc(sizeof(UNICODE_MAP));
+ CHARSET_MAP *map = safe_malloc(sizeof(CHARSET_MAP));
for(i = 0; i < 256; i++)
(*map)[i] = translate_char(to, (*from)[i]);
return map;
}
-UNICODE_MAP *mutt_get_translation(const char *_from, const char *_to)
+CHARSET_MAP *mutt_get_translation(const char *_from, const char *_to)
{
- char from[SHORT_STRING];
- char to[SHORT_STRING];
+ char from_canon[SHORT_STRING];
+ char to_canon[SHORT_STRING];
char key[SHORT_STRING];
+ char *from, *to;
CHARSET *from_cs, *to_cs;
- UNICODE_MAP *map;
+ CHARSET_MAP *map;
if(!_from || !_to)
return NULL;
init_charsets();
- canonical_charset(from, sizeof(from), _from);
- canonical_charset(to, sizeof(to), _to);
+ canonical_charset(from_canon, sizeof(from_canon), _from);
+ canonical_charset(to_canon, sizeof(to_canon), _to);
+
+ if(!CharsetAliases || !(from = hash_find(CharsetAliases, from_canon)))
+ from = from_canon;
+ if(!CharsetAliases || !(to = hash_find(CharsetAliases, to_canon)))
+ to = to_canon;
/* quick check for the identity mapping */
- if((*from == *to) && !strcmp(from, to))
+ if((from == to) || ((*from == *to) && !strcmp(from, to)))
return NULL;
snprintf(key, sizeof(key), "%s %s", from, to);
return NULL;
map = build_translation(from_cs->map, to_cs->map);
- hash_insert(Translations, key, map, 0);
+ hash_insert(Translations, safe_strdup(key), map, 1);
}
return map;
}
-int mutt_display_char(int ch, UNICODE_MAP *map)
+unsigned char mutt_display_char(unsigned char ch, CHARSET_MAP *map)
{
- if (!map || (ch <= 0) || (ch > 255))
+ if (!map || !ch)
return ch;
-
- return (*map)[ch];
+
+ return (unsigned char) (*map)[ch];
}
-int mutt_display_string(char *str, UNICODE_MAP *map)
+int mutt_display_string(char *str, CHARSET_MAP *map)
{
if(!map)
return -1;
typedef int MAP[256];
+typedef struct alias
+{
+ char *charset;
+ struct alias *next;
+} ALIAS;
+
typedef struct
{
char *charset;
char escape_char;
char comment_char;
short is_valid;
+ ALIAS *aliases;
MAP map;
} CHARMAP;
m->escape_char = '\\';
m->comment_char = '#';
m->is_valid = 0;
+
+ m->aliases = NULL;
for(i = 0; i < 256; i++)
m->map[i] = -1;
static void charmap_free(CHARMAP **cp)
{
+ ALIAS *p, *q;
+
if(!cp || !*cp)
return ;
+ for(p = (*cp)->aliases; p; p = q)
+ {
+ q = p->next;
+ safe_free((void **) &p->charset);
+ safe_free((void **) &p);
+ }
+
safe_free((void **) &(*cp)->charset);
safe_free((void **) cp);
return;
}
+static void add_alias(CHARMAP *m, const char *alias)
+{
+ ALIAS *aptr;
+
+ aptr = safe_malloc(sizeof(ALIAS));
+ aptr->charset = safe_strdup(alias);
+ canonical_charset(aptr->charset, strlen(aptr->charset) + 1, aptr->charset);
+ aptr->next = m->aliases;
+ m->aliases = aptr;
+}
+
static CHARMAP *parse_charmap_header(FILE *fp, const char *prefix)
{
char buffer[1024];
break;
if(*buffer == m->comment_char)
+ {
+ if((t = strtok(buffer + 1, "\t ")) && !strcasecmp(t, "alias"))
+ {
+ while((t = strtok(NULL, "\t, ")))
+ add_alias(m, t);
+ }
continue;
+ }
if(!(t = strtok(buffer, "\t ")))
continue;
{
FILE *fp;
CHARMAP *m;
+ ALIAS *aptr;
int i;
char buffer[1024];
if((fp = fopen(buffer, "w")))
{
- printf("%s\n", m->charset);
write_charmap(fp, m);
+
+ printf("charset %s\n", m->charset);
+ for(aptr = m->aliases; aptr; aptr = aptr->next)
+ {
+ if(strcmp(aptr->charset, m->charset))
+ printf("alias %s %s\n", aptr->charset, m->charset);
+ }
+
fclose(fp);
}
else
if (istext)
{
- UNICODE_MAP *map;
+ CHARSET_MAP *map;
map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset);
}
}
- state_putc(mutt_display_char(c, map), s);
+ state_putc(mutt_display_char((unsigned char) c, map), s);
if(c == '\n')
lbreak = 1;
}
{
long len = b->length;
int ch, lbreak = 1;
- UNICODE_MAP *map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset);
+ CHARSET_MAP *map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset);
while (len > 0)
{
}
if(ch != EOF)
- state_putc(istext ? mutt_display_char(ch, map) : ch, s);
+ state_putc(istext ? mutt_display_char((unsigned char) ch, map) : ch, s);
if(ch == '\n')
lbreak = 1;
long len = b->length;
char buf[5];
int c1, c2, c3, c4, ch, cr = 0, i;
- UNICODE_MAP *map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset);
+ CHARSET_MAP *map = mutt_get_translation(mutt_get_parameter("charset", b->parameter), Charset);
buf[4] = 0;
cr = 1;
else
{
- state_putc(istext ? mutt_display_char(ch, map) : ch, s);
+ state_putc(istext ? mutt_display_char((unsigned char) ch, map) : ch, s);
if (ch == '\n' && s->prefix) state_puts (s->prefix, s);
}
cr = 1;
else
{
- state_putc(istext ? mutt_display_char(ch, map) : ch, s);
+ state_putc(istext ? mutt_display_char((unsigned char)ch, map) : ch, s);
if (ch == '\n' && s->prefix)
state_puts (s->prefix, s);
}
cr = 1;
else
{
- state_putc(istext ? mutt_display_char(ch, map) : ch, s);
+ state_putc(istext ? mutt_display_char((unsigned char) ch, map) : ch, s);
if (ch == '\n' && s->prefix)
state_puts (s->prefix, s);
}