diff --git a/currency.c b/currency.c index 0dc868118f..b25ff16e89 100644 --- a/currency.c +++ b/currency.c @@ -8,79 +8,48 @@ #include "table/strings.h" #include "date.h" -// exchange rate prefix -// | separator | postfix -// | | Euro year | | -// | | | | | -CurrencySpec _currency_specs[] = { - { 1, ',', CF_NOEURO, "\xA3", "" }, // british pounds - { 2, ',', CF_NOEURO, "$", "" }, // us dollars - { 2, ',', CF_ISEURO, "¤", "" }, // Euro - { 200, ',', CF_NOEURO, "\xA5", "" }, // yen - { 19, ',', 2002, "", " S." }, // austrian schilling - { 57, ',', 2002, "BEF ", "" }, // belgian franc - { 2, ',', CF_NOEURO, "CHF ", "" }, // swiss franc - { 50, ',', CF_NOEURO, "", " Kc" }, // czech koruna // TODO: Should use the "c" with an upside down "^" - { 4, '.', 2002, "DM ", "" }, // deutsche mark - { 10, '.', CF_NOEURO, "", " kr" }, // danish krone - { 200, '.', 2002, "Pts ", "" }, // spanish pesetas - { 8, ',', 2002, "", " mk" }, // finnish markka - { 10, '.', 2002, "FF ", "" }, // french francs - { 480, ',', 2002, "", "Dr." }, // greek drachma - { 376, ',', 2002, "", " Ft" }, // hungarian forint - { 130, '.', CF_NOEURO, "", " Kr" }, // icelandic krona - { 2730, ',', 2002, "", " L." }, // italian lira - { 3, ',', 2002, "NLG ", "" }, // dutch gulden - { 11, '.', CF_NOEURO, "", " Kr" }, // norwegian krone - { 6, ' ', CF_NOEURO, "", " zl" }, // polish zloty - { 6, '.', CF_NOEURO, "", " Lei" }, // romanian Lei - { 5, ' ', CF_NOEURO, "", " p" }, // russian rouble - { 350, '.', CF_NOEURO, "", " SIT" }, // slovenian tolar - { 13, '.', CF_NOEURO, "", " Kr" }, // swedish krona - { 1, ' ', CF_NOEURO, "", "" }, // custom currency + // exchange rate prefix symbol_pos + // | separator | postfix | + // | | Euro year | | | name + // | | | | | | | +const CurrencySpec origin_currency_specs[NUM_CURRENCY] = { + { 1, ',', CF_NOEURO, "\xA3", "", 0, STR_CURR_GBP }, // british pounds + { 2, ',', CF_NOEURO, "$", "", 0, STR_CURR_USD }, // us dollars + { 2, ',', CF_ISEURO, "¤", "", 0, STR_CURR_EUR }, // Euro + { 200, ',', CF_NOEURO, "\xA5", "", 0, STR_CURR_YEN }, // yen + { 19, ',', 2002, "", " S.", 1, STR_CURR_ATS }, // austrian schilling + { 57, ',', 2002, "BEF ", "", 0, STR_CURR_BEF }, // belgian franc + { 2, ',', CF_NOEURO, "CHF ", "", 0, STR_CURR_CHF }, // swiss franc + { 50, ',', CF_NOEURO, "", " Kc", 1, STR_CURR_CZK }, // czech koruna // TODO: Should use the "c" with an upside down "^" + { 4, '.', 2002, "DM ", "", 0, STR_CURR_DEM }, // deutsche mark + { 10, '.', CF_NOEURO, "", " kr", 1, STR_CURR_DKK }, // danish krone + { 200, '.', 2002, "Pts ", "", 0, STR_CURR_ESP }, // spanish pesetas + { 8, ',', 2002, "", " mk", 1, STR_CURR_FIM }, // finnish markka + { 10, '.', 2002, "FF ", "", 0, STR_CURR_FRF }, // french francs + { 480, ',', 2002, "", "Dr.", 1, STR_CURR_GRD }, // greek drachma + { 376, ',', 2002, "", " Ft", 1, STR_CURR_HUF }, // hungarian forint + { 130, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_ISK }, // icelandic krona + { 2730, ',', 2002, "", " L.", 1, STR_CURR_ITL }, // italian lira + { 3, ',', 2002, "NLG ", "", 0, STR_CURR_NLG }, // dutch gulden + { 11, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_NOK }, // norwegian krone + { 6, ' ', CF_NOEURO, "", " zl", 1, STR_CURR_PLN }, // polish zloty + { 6, '.', CF_NOEURO, "", " Lei", 1, STR_CURR_ROL }, // romanian Lei + { 5, ' ', CF_NOEURO, "", " p", 1, STR_CURR_RUR }, // russian rouble + { 350, '.', CF_NOEURO, "", " SIT", 1, STR_CURR_SIT }, // slovenian tolar + { 13, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_SEK }, // swedish krona + { 1, ' ', CF_NOEURO, "", "", 0, STR_CURR_CUSTOM }, // custom currency }; -const StringID _currency_string_list[] = { - STR_CURR_GBP, - STR_CURR_USD, - STR_CURR_EUR, - STR_CURR_YEN, - STR_CURR_ATS, - STR_CURR_BEF, - STR_CURR_CHF, - STR_CURR_CZK, - STR_CURR_DEM, - STR_CURR_DKK, - STR_CURR_ESP, - STR_CURR_FIM, - STR_CURR_FRF, - STR_CURR_GRD, - STR_CURR_HUF, - STR_CURR_ISK, - STR_CURR_ITL, - STR_CURR_NLG, - STR_CURR_NOK, - STR_CURR_PLN, - STR_CURR_ROL, - STR_CURR_RUR, - STR_CURR_SIT, - STR_CURR_SEK, - STR_CURR_CUSTOM, - INVALID_STRING_ID -}; +/* Array of currencies used by the system */ +CurrencySpec _currency_specs[NUM_CURRENCY]; -// NOTE: Make sure both lists are in the same order -// + 1 string list terminator -assert_compile(lengthof(_currency_specs) + 1 == lengthof(_currency_string_list)); - - -// get a mask of the allowed currencies depending on the year +/* get a mask of the allowed currencies depending on the year */ uint GetMaskOfAllowedCurrencies(void) { uint mask = 0; uint i; - for (i = 0; i != lengthof(_currency_specs); i++) { + for (i = 0; i < NUM_CURRENCY; i++) { Year to_euro = _currency_specs[i].to_euro; if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro) continue; @@ -91,7 +60,9 @@ uint GetMaskOfAllowedCurrencies(void) return mask; } - +/** + * Verify if the currency chosen by the user is about to be converted to Euro + **/ void CheckSwitchToEuro(void) { if (_currency_specs[_opt.currency].to_euro != CF_NOEURO && @@ -102,3 +73,31 @@ void CheckSwitchToEuro(void) } } +/** + * Called only from newgrf.c. Will fill _currency_specs array with + * default values from origin_currency_specs + **/ +void ResetCurrencies(void) +{ + memcpy(&_currency_specs, &origin_currency_specs, sizeof(origin_currency_specs)); +} + +/** + * Build a list of currency names StringIDs to use in a dropdown list + * @return Pointer to a (static) array of StringIDs + */ +StringID* BuildCurrencyDropdown(void) +{ + /* Allow room for all currencies, plus a terminator entry */ + static StringID names[CUSTOM_CURRENCY_ID]; + uint i; + + /* Add each name */ + for (i = 0; i < NUM_CURRENCY; i++) { + names[i] = _currency_specs[i].name; + } + /* Terminate the list */ + names[i] = INVALID_STRING_ID; + + return names; +} diff --git a/currency.h b/currency.h index ea5d5436c3..be4273df58 100644 --- a/currency.h +++ b/currency.h @@ -6,6 +6,8 @@ enum { CF_NOEURO = 0, CF_ISEURO = 1, + NUM_CURRENCY = 25, + CUSTOM_CURRENCY_ID = NUM_CURRENCY + 1, }; typedef struct { @@ -14,17 +16,24 @@ typedef struct { Year to_euro; char prefix[16]; char suffix[16]; + /** + * Position of the currency symbol on the amount string. + * 0 = placed before, 1 = placed after + */ + byte symbol_pos; + StringID name; } CurrencySpec; -extern CurrencySpec _currency_specs[]; -extern const StringID _currency_string_list[]; + +extern CurrencySpec _currency_specs[NUM_CURRENCY]; // XXX small hack, but makes the rest of the code a bit nicer to read -#define CUSTOM_CURRENCY_ID 24 #define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID]) #define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency]) uint GetMaskOfAllowedCurrencies(void); void CheckSwitchToEuro(void); +void ResetCurrencies(void); +StringID* BuildCurrencyDropdown(void); #endif /* CURRENCY_H */ diff --git a/newgrf.c b/newgrf.c index cd2e99acf7..7a5dbfb440 100644 --- a/newgrf.c +++ b/newgrf.c @@ -24,7 +24,7 @@ #include "newgrf_text.h" #include "table/sprites.h" #include "date.h" - +#include "currency.h" #include "newgrf_spritegroup.h" /* TTDPatch extended GRF format codec @@ -1088,6 +1088,86 @@ static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, i } break; + case 0x0A: // Currency display names + FOR_EACH_OBJECT { + StringID newone = GetGRFStringID(_cur_grffile->grfid,grf_load_word(&buf)); + + if (newone != STR_UNDEFINED) { + _currency_specs[gvid + i].name = newone; + } + } + break; + + case 0x0B: // Currency multipliers + FOR_EACH_OBJECT { + uint curidx = gvid + i; + uint32 rate = grf_load_dword(&buf); + + if (curidx < NUM_CURRENCY) { + _currency_specs[curidx].rate = rate; + } else { + grfmsg(GMS_WARN, "GlobalVarChangeInfo: Currency multipliers %d out of range, ignoring.", curidx); + } + } + break; + + case 0x0C: // Currency options + FOR_EACH_OBJECT { + uint curidx = gvid +i; + uint16 options = grf_load_word(&buf); + + if (curidx < NUM_CURRENCY) { + _currency_specs[curidx].separator = GB(options, 0, 8); + _currency_specs[curidx].symbol_pos = GB(options, 8, 8); + } else { + grfmsg(GMS_WARN, "GlobalVarChangeInfo: Currency option %d out of range, ignoring.", curidx); + } + } + break; + + case 0x0D: // Currency symbols + FOR_EACH_OBJECT { + uint curidx = gvid +i; + uint32 tempfix = grf_load_dword(&buf); + + if (curidx < NUM_CURRENCY) { + memcpy(_currency_specs[curidx].prefix,&tempfix,4); + _currency_specs[curidx].prefix[4] = 0; + } else { + grfmsg(GMS_WARN, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring.", curidx); + } + } + break; + + case 0x0E: // Currency symbols + FOR_EACH_OBJECT { + uint curidx = gvid +i; + uint32 tempfix = grf_load_dword(&buf); + + if (curidx < NUM_CURRENCY) { + memcpy(&_currency_specs[curidx].suffix,&tempfix,4); + _currency_specs[curidx].suffix[4] = 0; + } else { + grfmsg(GMS_WARN, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring.", curidx); + } + } + break; + + case 0x0F: // Euro introduction datess + FOR_EACH_OBJECT { + uint curidx = gvid +i; + Year year_euro = grf_load_word(&buf); + + if (curidx < NUM_CURRENCY) { + _currency_specs[curidx].to_euro = year_euro; + } else { + grfmsg(GMS_WARN, "GlobalVarChangeInfo: Euro intro date %d out of range, ignoring.", curidx); + } + } + break; + + case 0x09: // Cargo translation table + case 0x10: // 12 * 32 * B Snow line height table default: ret = true; } @@ -1820,6 +1900,11 @@ static void FeatureNewName(byte *buf, int len) break; } + case 0x48 : { // this will allow things like currencies new strings, and everything else + AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, id); + break; + } + default: switch (GB(id, 8, 8)) { case 0xC4: /* Station class name */ @@ -2727,6 +2812,9 @@ static void ResetNewGRFData(void) // Reset price base data ResetPriceBaseMultipliers(); + /* Reset the curencies array */ + ResetCurrencies(); + // Reset station classes ResetStationClasses(); ResetCustomStations(); diff --git a/settings_gui.c b/settings_gui.c index 350b7aa7fb..b98ad4e358 100644 --- a/settings_gui.c +++ b/settings_gui.c @@ -97,7 +97,7 @@ static void GameOptionsWndProc(Window *w, WindowEvent *e) StringID str = STR_02BE_DEFAULT; w->disabled_state = (_vehicle_design_names & 1) ? (++str, 0) : (1 << 21); SetDParam(0, str); - SetDParam(1, _currency_string_list[_opt_ptr->currency]); + SetDParam(1, _currency_specs[_opt_ptr->currency].name); SetDParam(2, STR_UNITS_IMPERIAL + _opt_ptr->units); SetDParam(3, STR_02E9_DRIVE_ON_LEFT + _opt_ptr->road_side); SetDParam(4, STR_TOWNNAME_ORIGINAL_ENGLISH + _opt_ptr->town_name); @@ -115,7 +115,7 @@ static void GameOptionsWndProc(Window *w, WindowEvent *e) case WE_CLICK: switch (e->click.widget) { case 4: case 5: /* Setup currencies dropdown */ - ShowDropDownMenu(w, _currency_string_list, _opt_ptr->currency, 5, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0); + ShowDropDownMenu(w, BuildCurrencyDropdown(), _opt_ptr->currency, 5, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0);; return; case 7: case 8: /* Setup distance unit dropdown */ ShowDropDownMenu(w, _units_dropdown, _opt_ptr->units, 8, 0, 0); diff --git a/strings.c b/strings.c index 041a40ac14..d57d70129c 100644 --- a/strings.c +++ b/strings.c @@ -381,9 +381,11 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 n number = -number; } - // add prefix part - s = spec->prefix; - while (s != spec->prefix + lengthof(spec->prefix) && (c = *s++) != '\0') *buff++ = c; + /* add prefix part, only if it is specified by symbol_pos */ + if (spec->symbol_pos == 0) { + s = spec->prefix; + while (s != spec->prefix + lengthof(spec->prefix) && (c = *(s++)) != '\0') *(buff)++ = c; + } // for huge numbers, compact the number into k or M if (compact) { @@ -411,9 +413,11 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 n if (compact) *buff++ = compact; - // add suffix part - s = spec->suffix; - while (s != spec->suffix + lengthof(spec->suffix) && (c = *s++) != '\0') *buff++ = c; + /* add suffix part, only if it is specified by symbol_pos */ + if (spec->symbol_pos != 0) { + s = spec->suffix; + while (s != spec->suffix + lengthof(spec->suffix) && (c = *(s++)) != '\0') *(buff++) = c; + } return buff; }