[gcalctool] Use currency rates from the IMF as well as the ECB to add 24 new rates: AED, BHD, BND, BWP, CLP, COP



commit cfcb0bfc150f45c416f87ce97b4297a75b118752
Author: Robert Ancell <robert ancell canonical com>
Date:   Wed Dec 8 17:25:15 2010 +1100

    Use currency rates from the IMF as well as the ECB to add 24 new rates: AED, BHD, BND, BWP, CLP, COP, DZD, ILS, IRR, KWD, KZT, LKR, LYD, MUR, NPR, OMR, PEN, PKR, QAR, SAR, TND, TTD, UYU, VEF

 NEWS           |    5 +-
 src/currency.c |  423 +++++++++++++++++++++++++++++++++++++++++---------------
 src/currency.h |   97 ++++++++-----
 3 files changed, 370 insertions(+), 155 deletions(-)
---
diff --git a/NEWS b/NEWS
index a42631b..aea84c4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,9 @@
 Overview of changes in gcalctool 5.91.4
 
     * Use new Indian Rupee sign â?¹ (Bug #636587, Carlos Cejudo)
-    * Remove Icelandic krona (ISK) from currency list, it is no longer provided
-      by the ECB.
+    * Use currency rates from the IMF as well as the ECB to add 24 new rates:
+      AED, BHD, BND, BWP, CLP, COP, DZD, ILS, IRR, KWD, KZT, LKR,
+      LYD, MUR, NPR, OMR, PEN, PKR, QAR, SAR, TND, TTD, UYU, VEF   
 
 Overview of changes in gcalctool 5.91.3
 
diff --git a/src/currency.c b/src/currency.c
index a489510..d49d7e4 100644
--- a/src/currency.c
+++ b/src/currency.c
@@ -16,14 +16,23 @@ typedef struct {
     const CurrencyInfo *info;
 } Currency;
 
-static Currency *currencies = NULL;
-static int currency_count = 0;
+static GList *currencies = NULL;
 
-static gboolean downloading_rates = FALSE;
+static gboolean downloading_imf_rates = FALSE, downloading_ecb_rates = FALSE;
 static gboolean loaded_rates = FALSE;
 
-static char*
-get_rate_filepath()
+static char *
+get_imf_rate_filepath()
+{
+    return g_build_filename(g_get_user_cache_dir (),
+                            "gcalctool",
+                            "rms_five.xls",
+                            NULL);
+}
+
+
+static char *
+get_ecb_rate_filepath()
 {
     return g_build_filename(g_get_user_cache_dir (),
                             "gcalctool",
@@ -31,138 +40,313 @@ get_rate_filepath()
                             NULL);
 }
 
-static int
-currency_get_index(const char *short_name)
+
+static Currency *
+add_currency(const gchar *short_name)
 {
+    Currency *c;
     int i;
-    for (i = 0; i < currency_count; i++) {
-        if (!strcmp(short_name, currencies[i].short_name)) {
-            if (mp_is_negative(&currencies[i].value) ||
-                mp_is_zero(&currencies[i].value)) {
-                return -1;
-            } else {
-                return i;
+
+    c = g_malloc0(sizeof(Currency));
+    c->short_name = g_strdup(short_name);
+    for (i = 0; currency_info[i].short_name; i++) {
+        if (strcmp(c->short_name, currency_info[i].short_name) == 0) {
+            c->info = &currency_info[i];
+            break;
+        }
+    }
+    if (!c->info)
+        g_warning("Currency %s is not in the currency table", c->short_name);
+
+    currencies = g_list_append(currencies, c);
+
+    return c;
+}
+
+
+static Currency *
+get_currency(const gchar *short_name)
+{
+    GList *link;
+    for (link = currencies; link; link = link->next) {
+        Currency *c = link->data;
+        if (!strcmp(short_name, c->short_name)) {
+            if (mp_is_negative(&c->value) ||
+                mp_is_zero(&c->value)) {
+                return NULL;
             }
+            else
+                return c;
         }
     }
-    return -1;
+    return NULL;
 }
 
-/* A file needs to be redownloaded if it doesn't exist, or every 7 days.
+
+/* A file needs to be redownloaded if it doesn't exist, or is too old.
  * When an error occur, it probably won't hurt to try to download again.
  */
-static int
-currency_rates_needs_update()
+static gboolean
+file_needs_update(gchar *filename, double max_age)
 {
-    gchar *filename = get_rate_filepath ();
     struct stat buf;
-    if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
-        g_free(filename);
-        return 1;
-    }
 
-    if (g_stat(filename, &buf) == -1) {
-        g_free(filename);
-        return 1;
-    }
-    g_free(filename);
+    if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
+        return TRUE;
 
-    if (difftime(time(NULL), buf.st_mtime) > (60 * 60 * 24 * 7)) {
-        return 1;
-    }
+    if (g_stat(filename, &buf) == -1)
+        return TRUE;
+
+    if (difftime(time(NULL), buf.st_mtime) > max_age)
+        return TRUE;
 
-    return 0;
+    return FALSE;
 }
 
 
 static void
-download_cb(GObject *object, GAsyncResult *result, gpointer user_data)
+download_imf_cb(GObject *object, GAsyncResult *result, gpointer user_data)
 {
     GError *error = NULL;
 
     if (g_file_copy_finish(G_FILE(object), result, &error))
-        g_debug("Rates updated");
+        g_debug("IMF rates updated");
     else
-        g_warning("Couldn't download currency file: %s", error->message);
+        g_warning("Couldn't download IMF currency rate file: %s", error->message);
     g_clear_error(&error);
-    downloading_rates = FALSE;
+    downloading_imf_rates = FALSE;
 }
 
 
 static void
-currency_download_rates()
+download_ecb_cb(GObject *object, GAsyncResult *result, gpointer user_data)
 {
-    gchar *filename, *directory;
-    GFile *source, *dest;
+    GError *error = NULL;
 
-    downloading_rates = TRUE;
-    g_debug("Downloading rates...");
+    if (g_file_copy_finish(G_FILE(object), result, &error))
+        g_debug("ECB rates updated");
+    else
+        g_warning("Couldn't download ECB currency rate file: %s", error->message);
+    g_clear_error(&error);
+    downloading_ecb_rates = FALSE;
+}
+
+
+static void
+download_file(gchar *uri, gchar *filename, GAsyncReadyCallback callback)
+{
+    gchar *directory;
+    GFile *source, *dest;
 
-    filename = get_rate_filepath();
     directory = g_path_get_dirname(filename);
     g_mkdir_with_parents(directory, 0755);
     g_free(directory);
 
-    source = g_file_new_for_uri ("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";);
-    dest = g_file_new_for_path (filename);
-    g_free(filename);
+    source = g_file_new_for_uri(uri);
+    dest = g_file_new_for_path(filename);
 
-    g_file_copy_async (source, dest, G_FILE_COPY_OVERWRITE, G_PRIORITY_DEFAULT, NULL, NULL, NULL, download_cb, NULL);
+    g_file_copy_async(source, dest, G_FILE_COPY_OVERWRITE, G_PRIORITY_DEFAULT, NULL, NULL, NULL, callback, NULL);
     g_object_unref(source);
-    g_object_unref(dest);
+    g_object_unref(dest); 
 }
 
 
 static void
-set_rate (xmlNodePtr node, Currency *cur)
+load_imf_rates()
 {
-    xmlAttrPtr attribute;
-    for (attribute = node->properties; attribute; attribute = attribute->next) {
-        if (strcmp((char *)attribute->name, "currency") == 0) {
-            int i;
-
-            cur->short_name = (char *)xmlNodeGetContent((xmlNodePtr) attribute);
-            for (i = 0; currency_info[i].short_name; i++)
-            {
-                if (strcmp(cur->short_name, currency_info[i].short_name) == 0)
-                {
-                    cur->info = &currency_info[i];
+    gchar *filename;
+    gchar *data, **lines;
+    gsize length;
+    GError *error = NULL;
+    int i;
+    gboolean result, in_data = FALSE;
+    struct 
+    {
+        const gchar *name, *symbol;
+    } name_map[] = 
+    {
+        {"Euro",                "EUR"},
+        {"Japanese Yen",        "JPY"},
+        {"U.K. Pound Sterling", "GBP"},
+        {"U.S. Dollar",         "USD"},
+        {"Algerian Dinar",      "DZD"},
+        {"Australian Dollar",   "AUD"},
+        {"Bahrain Dinar",       "BHD"},
+        {"Botswana Pula",       "BWP"},
+        {"Brazilian Real",      "BRL"},
+        {"Brunei Dollar",       "BND"},
+        {"Canadian Dollar",     "CAD"},
+        {"Chilean Peso",        "CLP"},
+        {"Chinese Yuan",        "CNY"},
+        {"Colombian Peso",      "COP"},
+        {"Czech Koruna",        "CZK"},
+        {"Danish Krone",        "DKK"},
+        {"Hungarian Forint",    "HUF"},
+        {"Icelandic Krona",     "ISK"},
+        {"Indian Rupee",        "INR"},
+        {"Indonesian Rupiah",   "IDR"},
+        {"Iranian Rial",        "IRR"},
+        {"Israeli New Sheqel",  "ILS"},
+        {"Kazakhstani Tenge",   "KZT"},
+        {"Korean Won",          "KRW"},
+        {"Kuwaiti Dinar",       "KWD"},
+        {"Libyan Dinar",        "LYD"},
+        {"Malaysian Ringgit",   "MYR"},
+        {"Mauritian Rupee",     "MUR"},
+        {"Mexican Peso",        "MXN"},
+        {"Nepalese Rupee",      "NPR"},
+        {"New Zealand Dollar",  "NZD"},
+        {"Norwegian Krone",     "NOK"},
+        {"Rial Omani",          "OMR"},
+        {"Pakistani Rupee",     "PKR"},
+        {"Nuevo Sol",           "PEN"},
+        {"Philippine Peso",     "PHP"},
+        {"Polish Zloty",        "PLN"},
+        {"Qatar Riyal",         "QAR"},
+        {"Russian Ruble",       "RUB"},
+        {"Saudi Arabian Riyal", "SAR"},
+        {"Singapore Dollar",    "SGD"},
+        {"South African Rand",  "ZAR"},
+        {"Sri Lanka Rupee",     "LKR"},
+        {"Swedish Krona",       "SEK"},
+        {"Swiss Franc",         "CHF"},
+        {"Thai Baht",           "THB"},
+        {"Trinidad And Tobago Dollar", "TTD"},
+        {"Tunisian Dinar",      "TND"},
+        {"U.A.E. Dirham",       "AED"},
+        {"Peso Uruguayo",       "UYU"},
+        {"Bolivar Fuerte",      "VEF"},
+        {NULL, NULL}
+    };
+
+    filename = get_imf_rate_filepath();
+    result = g_file_get_contents(filename, &data, &length, &error);
+    g_free(filename);
+    if (!result)
+    {
+        g_warning("Failed to read exchange rates: %s", error->message);
+        g_clear_error(&error);
+        return;
+    }
+
+    lines = g_strsplit(data, "\n", 0);
+    g_free(data);
+
+    for (i = 0; lines[i]; i++) {
+        gchar *line, **tokens;
+
+        line = g_strchug(lines[i]);
+      
+        /* Start after first blank line, stop on next */
+        if (line[0] == '\0') {
+            if (!in_data) {
+               in_data = TRUE;
+               continue;
+            }
+            else
+               break;
+        }
+        if (!in_data)
+            continue;
+
+        tokens = g_strsplit(line, "\t", 0);
+        if (strcmp(tokens[0], "Currency") != 0) {
+            gint value_index, name_index;
+
+            for (value_index = 1; tokens[value_index]; value_index++) {
+                gchar *value = g_strchug (tokens[value_index]);
+                if (value[0] != '\0')
                     break;
+            }
+            if (tokens[value_index]) {
+                for (name_index = 0; name_map[name_index].name; name_index++) {
+                    if (strcmp(name_map[name_index].name, tokens[0]) == 0)
+                        break;
                 }
+                if (name_map[name_index].name) {
+                    Currency *c = get_currency(name_map[name_index].symbol);
+                    if (!c) {
+                        g_debug ("Using IMF rate of %s for %s", tokens[value_index], name_map[name_index].symbol);
+                        c = add_currency(name_map[name_index].symbol);
+                    }
+                    mp_set_from_string(tokens[value_index], 10, &c->value);
+                }
+                else
+                    g_warning("Unknown currency '%s'", tokens[0]);
             }
-            if (!cur->info)
-                g_warning("Currency %s is not in the currency table", cur->short_name);
+        }
+        g_strfreev(tokens);
+    }
+    g_strfreev(lines);
+}
+
+
+static void
+set_ecb_rate(xmlNodePtr node, Currency *eur_rate)
+{
+    xmlAttrPtr attribute;
+    gchar *name = NULL, *value = NULL;
+
+    for (attribute = node->properties; attribute; attribute = attribute->next) {
+        if (strcmp((char *)attribute->name, "currency") == 0) {
+            if (name)
+                xmlFree(name);
+            name = (gchar *)xmlNodeGetContent((xmlNodePtr)attribute);
         } else if (strcmp ((char *)attribute->name, "rate") == 0) {
-            char *val = (char *)xmlNodeGetContent ((xmlNodePtr) attribute);
-            mp_set_from_string(val, 10, &(cur->value));
-            xmlFree (val);
+            if (value)
+                xmlFree(value);
+            value = (gchar *)xmlNodeGetContent((xmlNodePtr)attribute);
         }
     }
+
+    /* Use data if value and no rate currently defined */
+    if (name && value && !get_currency(name)) {
+        Currency *c;
+        MPNumber r;
+
+        g_debug ("Using ECB rate of %s for %s", value, name);
+        c = add_currency(name);
+        mp_set_from_string(value, 10, &r);
+        mp_set_from_mp(&eur_rate->value, &c->value);
+        mp_divide(&c->value, &r, &c->value);
+    }
+
+    if (name)
+        xmlFree(name);
+    if (value)
+        xmlFree(value);
 }
 
+
 static void
-currency_load_rates()
+load_ecb_rates()
 {
-    char *filename = get_rate_filepath();
+    Currency *eur_rate;
+    char *filename = get_ecb_rate_filepath();
     xmlDocPtr document;
     xmlXPathContextPtr xpath_ctx;
     xmlXPathObjectPtr xpath_obj;
     int i, len;
 
-    g_return_if_fail(g_file_test(filename, G_FILE_TEST_IS_REGULAR));
+    /* Scale rates to the EUR value */
+    eur_rate = get_currency("EUR");
+    if (!eur_rate) {
+        g_warning("Cannot use ECB rates as don't have EUR rate");
+        return;
+    }
 
     xmlInitParser();
     document = xmlReadFile(filename, NULL, 0);
     g_free (filename);
     if (document == NULL) {
-        fprintf(stderr, "Couldn't parse data file\n");
+        g_error("Couldn't parse ECB rate file %s", filename);
         return;
     }
 
     xpath_ctx = xmlXPathNewContext(document);
     if (xpath_ctx == NULL) {
         xmlFreeDoc(document);
-        fprintf(stderr, "Couldn't create XPath context\n");
+        g_error("Couldn't create XPath context");
         return;
     }
 
@@ -171,52 +355,51 @@ currency_load_rates()
                        BAD_CAST("http://www.ecb.int/vocabulary/2002-08-01/eurofxref";));
     xpath_obj = xmlXPathEvalExpression(BAD_CAST("//xref:Cube[ currency][@rate]"),
                                        xpath_ctx);
-
     if (xpath_obj == NULL) {
         xmlXPathFreeContext(xpath_ctx);
         xmlFreeDoc(document);
         fprintf(stderr, "Couldn't create XPath object\n");
         return;
     }
-
     len = (xpath_obj->nodesetval) ? xpath_obj->nodesetval->nodeNr : 0;
-    currency_count = len + 1;
-    currencies = g_slice_alloc0(sizeof(Currency) * currency_count);
     for (i = 0; i < len; i++) {
-        if (xpath_obj->nodesetval->nodeTab[i]->type == XML_ELEMENT_NODE) {
-            set_rate(xpath_obj->nodesetval->nodeTab[i], &currencies[i]);
-        }
+        if (xpath_obj->nodesetval->nodeTab[i]->type == XML_ELEMENT_NODE)
+            set_ecb_rate(xpath_obj->nodesetval->nodeTab[i], eur_rate);
 
-        // Avoid accessing removed elements
+        /* Avoid accessing removed elements */
         if (xpath_obj->nodesetval->nodeTab[i]->type != XML_NAMESPACE_DECL)
             xpath_obj->nodesetval->nodeTab[i] = NULL;
     }
 
-    currencies[len].short_name = g_strdup("EUR");
-    MPNumber foo;
-    mp_set_from_integer(1, &foo);
-    currencies[len].value = foo;
-    currencies[len].info = currency_get_info("EUR");
-
     xmlXPathFreeObject(xpath_obj);
     xmlXPathFreeContext(xpath_ctx);
     xmlFreeDoc(document);
-    xmlCleanupParser();
+    xmlCleanupParser();  
+}
 
-    for (i = 0; currency_info[i].short_name; i++)
-    {
-       int j;
-       for (j = 0; j < currency_count; j++)
-       {
-           if (currencies[j].info == &currency_info[i])
+
+static void
+load_rates()
+{
+    int i;
+
+    /* Use the IMF provided values and top up with currencies tracked by the ECB and not the IMF */
+    load_imf_rates();
+    load_ecb_rates();
+
+    for (i = 0; currency_info[i].short_name; i++) {
+       GList *link;
+       for (link = currencies; link; link = link->next) {
+           Currency *c = link->data;
+           if (c->info == &currency_info[i])
               break;
        }
-       if (j == currency_count)
-           g_warning("Currency %s is not provided by server", currency_info[i].short_name);
+       if (!link)
+           g_warning("Currency %s is not provided by IMF or ECB", currency_info[i].short_name);
     }
 
     g_debug("Rates loaded");
-    loaded_rates = TRUE;
+    loaded_rates = TRUE;  
 }
 
 
@@ -238,32 +421,44 @@ currency_convert(const MPNumber *from_amount,
                  const char *source_currency, const char *target_currency,
                  MPNumber *to_amount)
 {
-    int from_index, to_index;
+    gchar *path;
+    Currency *from_info, *to_info;
+
+    /* Update rates if necessary */
+    path = get_imf_rate_filepath();
+    if (!downloading_imf_rates && file_needs_update(path, 60 * 60 * 24 * 7)) {
+        downloading_imf_rates = TRUE;
+        g_debug("Downloading rates from the IMF...");
+        download_file("http://www.imf.org/external/np/fin/data/rms_five.aspx?tsvflag=Y";, path, download_imf_cb);
+    }
+    g_free(path);
+    path = get_ecb_rate_filepath();
+    if (!downloading_ecb_rates && file_needs_update(path, 60 * 60 * 24 * 7)) {
+        downloading_ecb_rates = TRUE;
+        g_debug("Downloading rates from the ECB...");
+        download_file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";, path, download_ecb_cb);
+    }
+    g_free(path);
 
-    if (downloading_rates)
+    if (downloading_imf_rates || downloading_ecb_rates)
         return FALSE;
 
-    /* Update currency if necessary */
-    if (currency_rates_needs_update()) {
-        currency_download_rates();
-        return FALSE;
-    }
     if (!loaded_rates)
-        currency_load_rates();
+        load_rates();
   
-    from_index = currency_get_index(source_currency);
-    to_index = currency_get_index(target_currency);
-    if (from_index < 0 || to_index < 0)
+    from_info = get_currency(source_currency);
+    to_info = get_currency(target_currency);
+    if (!from_info || !to_info)
         return FALSE;
 
-    if (mp_is_zero(&currencies[from_index].value) ||
-        mp_is_zero(&currencies[to_index].value)) {
+    if (mp_is_zero(&from_info->value) ||
+        mp_is_zero(&to_info->value)) {
         mp_set_from_integer(0, to_amount);
         return FALSE;
     }
 
-    mp_divide(from_amount, &currencies[from_index].value, to_amount);
-    mp_multiply(to_amount, &currencies[to_index].value, to_amount);
+    mp_divide(from_amount, &to_info->value, to_amount);
+    mp_multiply(to_amount, &from_info->value, to_amount);
 
     return TRUE;
 }
@@ -271,13 +466,13 @@ currency_convert(const MPNumber *from_amount,
 void
 currency_free_resources()
 {
-    int i;
+    GList *link;
 
-    for (i = 0; i < currency_count; i++) {
-        if (currencies[i].short_name != NULL)
-            xmlFree(currencies[i].short_name);
+    for (link = currencies; link; link = link->next) {
+        Currency *c = link->data;
+        g_free(c->short_name);
+        g_free(c);
     }
-    g_slice_free1(currency_count * sizeof(Currency), currencies);
+    g_list_free(currencies);
     currencies = NULL;
-    currency_count = 0;
 }
diff --git a/src/currency.h b/src/currency.h
index e167147..736f554 100644
--- a/src/currency.h
+++ b/src/currency.h
@@ -10,47 +10,66 @@ typedef struct {
     char *symbol;
     char *long_name;
 } CurrencyInfo;
-
-/*
- * List taken from http://www.ecb.int/press/pr/date/2008/html/pr081205.en.html
- * with euro added.
- */
 static const CurrencyInfo currency_info[] = {
-    {"AUD", "$",  N_("Australian dollar")},
-    {"BGN", "лв", N_("Bulgarian lev")},
-    {"BRL", "R$", N_("Brazilian real")},
-    {"CAD", "$",  N_("Canadian dollar")},
-    {"CHF", "Fr", N_("Swiss franc")},
-    {"CNY", "å??", N_("Chinese yuan renminbi")},
-    {"CZK", "KÄ?", N_("Czech koruna")},
-    {"DKK", "kr", N_("Danish krone")},
-    {"EEK", "KR", N_("Estonian kroon")},
-    {"EUR", "â?¬",  N_("Euro")},
-    {"GBP", "£",  N_("Pound sterling")},
-    {"HKD", "$",  N_("Hong Kong dollar")},
-    {"HRK", "kn", N_("Croatian kuna")},
-    {"HUF", "Ft", N_("Hungarian forint")},
-    {"IDR", "Rp", N_("Indonesian rupiah")},
-    {"INR", "â?¹",  N_("Indian rupee")},
-//    {"ISK", "kr", N_("Icelandic krona")}, // NOTE: Used to be provided by the ECB
-    {"JPY", "Â¥",  N_("Japanese yen")},
-    {"KRW", "â?©",  N_("South Korean won")},
-    {"LTL", "Lt", N_("Lithuanian litas")},
-    {"LVL", "Ls", N_("Latvian lats")},
-    {"MXN", "$",  N_("Mexican peso")},
-    {"MYR", "RM", N_("Malaysian ringgit")},
-    {"NOK", "kr", N_("Norwegian krone")},
-    {"NZD", "$",  N_("New Zealand dollar")},
-    {"PHP", "â?±",  N_("Philippine peso")},
-    {"PLN", "zÅ?", N_("Polish zloty")},
-    {"RON", "L",  N_("New Romanian leu")},
+    {"AED", "إ.د",  N_("United Arab Emirates dirham")},
+    {"AUD", "$",    N_("Australian dollar")},
+    {"BGN", "лв",   N_("Bulgarian lev")},
+    {"BHD", ".ب.د", N_("Bahraini dinar")},
+    {"BND", "$",    N_("Brunei dollar")},
+    {"BRL", "R$",   N_("Brazilian real")},
+    {"BWP", "P",    N_("Botswana pula")},
+    {"CAD", "$",    N_("Canadian dollar")},
+    {"CHF", "Fr",   N_("Swiss franc")},
+    {"CLP", "$",    N_("Chilean peso")},
+    {"CNY", "å??",   N_("Chinese yuan renminbi")},
+    {"COP", "$",    N_("Colombian peso")},
+    {"CZK", "KÄ?",   N_("Czech koruna")},
+    {"DKK", "kr",   N_("Danish krone")},
+    {"DZD", "ج.د",  N_("Algerian dinar")},
+    {"EEK", "KR",   N_("Estonian kroon")},
+    {"EUR", "â?¬",    N_("Euro")},
+    {"GBP", "£",    N_("Pound sterling")},
+    {"HKD", "$",    N_("Hong Kong dollar")},
+    {"HRK", "kn",   N_("Croatian kuna")},
+    {"HUF", "Ft",   N_("Hungarian forint")},
+    {"IDR", "Rp",   N_("Indonesian rupiah")},
+    {"ILS", "â?ª",    N_("Israeli new shekel")},
+    {"INR", "â?¹",    N_("Indian rupee")},
+    {"IRR", "ï·¼",    N_("Iranian rial")},
+    {"ISK", "kr",   N_("Icelandic krona")},
+    {"JPY", "Â¥",    N_("Japanese yen")},
+    {"KRW", "â?©",    N_("South Korean won")},
+    {"KWD", "Ù?.د",  N_("Kuwaiti dinar")},
+    {"KZT", "â?¸",    N_("Kazakhstani tenge")},
+    {"LKR", "Rs",   N_("Sri Lankan rupee")},
+    {"LTL", "Lt",   N_("Lithuanian litas")},
+    {"LVL", "Ls",   N_("Latvian lats")},
+    {"LYD", "د.Ù?",  N_("Libyan dinar")},
+    {"MUR", "Rs",   N_("Mauritian rupee")},
+    {"MXN", "$",    N_("Mexican peso")},
+    {"MYR", "RM",   N_("Malaysian ringgit")},
+    {"NOK", "kr",   N_("Norwegian krone")},
+    {"NPR", "Rs",   N_("Nepalese rupee")},
+    {"NZD", "$",    N_("New Zealand dollar")},
+    {"OMR", "ع.ر.", N_("Omani rial")},
+    {"PEN", "S/.",  N_("Peruvian nuevo sol")},
+    {"PHP", "â?±",    N_("Philippine peso")},
+    {"PKR", "Rs",   N_("Pakistani rupee")},
+    {"PLN", "zÅ?",   N_("Polish zloty")},
+    {"QAR", "Ù?.ر",  N_("Qatari riyal")},
+    {"RON", "L",    N_("New Romanian leu")},
     {"RUB", "Ñ?Ñ?б.", N_("Russian rouble")},
-    {"SEK", "kr", N_("Swedish krona")},
-    {"SGD", "$",  N_("Singapore dollar")},
-    {"THB", "฿",  N_("Thai baht")},
-    {"TRY", "TL", N_("New Turkish lira")},
-    {"USD", "$",  N_("US dollar")},
-    {"ZAR", "R",  N_("South African rand")},
+    {"SAR", "س.ر",  N_("Saudi riyal")},
+    {"SEK", "kr",   N_("Swedish krona")},
+    {"SGD", "$",    N_("Singapore dollar")},
+    {"THB", "฿",    N_("Thai baht")},
+    {"TND", "ت.د",  N_("Tunisian dinar")},
+    {"TRY", "TL",   N_("New Turkish lira")},
+    {"TTD", "$",    N_("Trinidad and Tobago dollar")},
+    {"USD", "$",    N_("US dollar")},
+    {"UYU", "$",    N_("Uruguayan peso")},
+    {"VEF", "Bs F", N_("Venezuelan bolívar")},
+    {"ZAR", "R",    N_("South African rand")},
     {NULL, NULL}
 };
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]