From e70cf64faf55b783e92b9e07c6fd6c1da63cdc37 Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Mon, 22 May 2000 09:28:58 +0000 Subject: [PATCH] Make mutt_gettext () a bit more compact. --- charset.c | 10 ++- gettext.c | 212 ++++++++++++++++++++++++------------------------------ 2 files changed, 102 insertions(+), 120 deletions(-) diff --git a/charset.c b/charset.c index 62eac288..262ebcc7 100644 --- a/charset.c +++ b/charset.c @@ -411,12 +411,16 @@ int mutt_convert_string (char **ps, const char *from, const char *to) ib = s, ibl = len + 1; obl = MB_LEN_MAX * ibl; ob = buf = safe_malloc (obl + 1); + mutt_iconv (cd, &ib, &ibl, &ob, &obl, inrepls, outrepl); iconv_close (cd); - free (s); + *ob = '\0'; - *ps = safe_strdup (buf); - free (buf); + + safe_free ((void **) ps); + *ps = buf; + + safe_realloc ((void **) ps, strlen (*ps) + 1); /* avoid copying */ return 0; } else diff --git a/gettext.c b/gettext.c index b6075204..a881ba8f 100644 --- a/gettext.c +++ b/gettext.c @@ -2,6 +2,9 @@ #include #include "mutt.h" + +#include "hash.h" + #include "iconv.h" #include "lib.h" #include "charset.h" @@ -12,148 +15,123 @@ * the conversion. */ -struct gt_hash_elem +/* + * Note: the routines in this file can be invoked before debugfile + * has been opened. When using dprint here, please check if + * debugfile != NULL before. + */ + +static HASH *Messages = NULL; +static char *PoHeader = NULL; +static char *PoCharset = NULL; +static char *MessageCharset = NULL; + +struct msg { - const char *key; + char *key; char *data; - struct gt_hash_elem *next; }; -#define gt_hash_size 127 - static char *get_charset (const char *header) { /* FIXME: the comparison should at least be case-insensitive */ const char f[] = "\nContent-Type: text/plain; charset="; - char *charset, *i, *j; + char *s, *t; - charset = 0; - i = strstr (header, f); - if (i) + if (!header) return NULL; + + if ((s = strstr (header, f))) { - i += sizeof (f)-1; - for (j = i; *j >= 32; j++) + s += sizeof (f)-1; + for (t = s; *t >= 32; t++) ; - charset = safe_malloc (j-i+1); - memcpy (charset, i, j-i); - charset[j-i] = '\0'; + return mutt_substrdup (s, t); } - return charset; + + /* else */ + + return NULL; } -char *mutt_gettext (const char *message) +static void destroy_one_message (void *vp) { - static struct gt_hash_elem **messages = 0; - static char *po_header = 0; - static char *po_charset = 0; - static char *message_charset = 0; - static char *outrepl = "?"; - static iconv_t cd = (iconv_t)-1; - int change_cd = 0; - char *t, *orig; - char *header_msgid = ""; - - /* gettext ("") doesn't work due to __builtin_constant_p optimisation */ - if ((t = gettext (header_msgid)) != po_header) - { - po_header = t; - t = get_charset (po_header); - if (t != po_charset && - (!t || !po_charset || strcmp (t, po_charset))) - { - safe_free ((void **) &po_charset); - po_charset = t; - change_cd = 1; - } - else - safe_free ((void **) &t); - } + struct msg *mp = (struct msg *) vp; + + safe_free ((void **) &mp->key); + safe_free ((void **) &mp->data); +} + +static void destroy_messages (void) +{ + if (Messages) + hash_destroy (&Messages, destroy_one_message); +} - if (message_charset != Charset && - (!message_charset || !Charset || strcmp (message_charset, Charset))) +static void set_po_charset (void) +{ + char *t; + char *empty = ""; + + t = gettext (empty); + + if (mutt_strcmp (t, PoHeader)) { - mutt_str_replace (&message_charset, Charset); - outrepl = mutt_is_utf8 (message_charset) ? "\357\277\275" : "?"; - change_cd = 1; + mutt_str_replace (&PoHeader, t); + safe_free ((void **) &PoCharset); + PoCharset = get_charset (PoHeader); + + destroy_messages (); } +} - if (change_cd) +static void set_message_charset (void) +{ + if (mutt_strcmp (MessageCharset, Charset)) { - if (cd != (iconv_t)-1) - iconv_close (cd); - if (message_charset) - cd = iconv_open (message_charset, po_charset ? po_charset : "UTF-8"); - else - cd = (iconv_t)-1; - - if (messages) - { - int i; - struct gt_hash_elem *p, *pn; - - for (i = 0; i < gt_hash_size; i++) - for (p = messages[i]; p; p = pn) - { - pn = p->next; - safe_free ((void **) &p); - } - - safe_free ((void **) &messages); - } + mutt_str_replace (&MessageCharset, Charset); + destroy_messages (); } +} + + +char *mutt_gettext (const char *message) +{ + char *orig; + struct msg *mp; + + set_po_charset (); + set_message_charset (); + + if (!Messages && MessageCharset) + Messages = hash_create (127); orig = gettext (message); - if (cd == (iconv_t)-1) + if (debugfile) + dprint (2, (debugfile, "mutt_gettext (`%s'): original gettext returned `%s'\n", + message, orig)); + + if (!Messages) return orig; - else + + if ((mp = hash_find (Messages, orig))) { - struct gt_hash_elem *p; - int hash; - char *s, *t; - int n, nn; - const char *ib; - char *ob; - size_t ibl, obl; - - if (!messages) - { - messages = safe_malloc (gt_hash_size * sizeof (*messages)); - memset (messages, 0, gt_hash_size * sizeof (*messages)); - } - hash = (long int)orig % gt_hash_size; /* not very clever */ - for (p = messages[hash]; p && p->key != orig; p = p->next) - ; - if (p) - return p->data; - - n = strlen (orig); - nn = n + 1; - t = safe_malloc (nn); - - ib = orig, ibl = n; - ob = t, obl = n; - for (;;) - { - mutt_iconv (cd, &ib, &ibl, &ob, &obl, 0, outrepl); - if (!ibl || obl > 256) - break; - s = t; - safe_realloc ((void **)&t, nn += n); - ob += t - s; - obl += n; - } - *ob = '\0'; - n = strlen (t); - s = safe_malloc (n+1); - memcpy (s, t, n+1); - safe_free ((void **) &t); - - p = safe_malloc (sizeof (struct gt_hash_elem)); - p->key = orig; - p->data = s; - p->next = messages[hash]; - messages[hash] = p; - return s; + if (debugfile) + dprint (2, (debugfile, "mutt_gettext: cache hit - key = `%s', data = `%s'\n", orig, mp->data)); + return mp->data; } + + /* the message could not be found in the hash */ + mp = safe_malloc (sizeof (struct msg)); + mp->key = safe_strdup (orig); + mp->data = safe_strdup (orig); + mutt_convert_string (&mp->data, PoCharset ? PoCharset : "utf-8", MessageCharset); + + if (debugfile) + dprint (2, (debugfile, "mutt_gettext: conversion done - src = `%s', res = `%s'\n", + mp->key, mp->data)); + + hash_insert (Messages, mp->key, mp, 0); + + return mp->data; } -- 2.40.0