tPad drug names by character, not byte - vaccinewars - be a doctor and try to vaccinate the world (HTM) git clone git://src.adamsgaard.dk/vaccinewars (DIR) Log (DIR) Files (DIR) Refs (DIR) README (DIR) LICENSE --- (DIR) commit c3e83bb7dab692ce7febbe46d21261c4a664f6a7 (DIR) parent 0f3258aeb3b48e9d859770c2ba81750fc4460010 (HTM) Author: Ben Webb <ben@salilab.org> Date: Sun, 29 Nov 2020 22:58:32 -0800 Pad drug names by character, not byte If we're in a UTF-8 locale with accented characters, strings might be longer in bytes than in characters; tthis results in drug names not lining up in the curses "drugs here" output. Pad using the length in characters instead to fix this. Diffstat: M src/curses_client/curses_client.c | 25 +++++++++++++++++++++++-- M src/dopewars.c | 3 +++ M src/dopewars.h | 1 + M src/winmain.c | 1 + 4 files changed, 28 insertions(+), 2 deletions(-) --- (DIR) diff --git a/src/curses_client/curses_client.c b/src/curses_client/curses_client.c t@@ -2241,6 +2241,25 @@ char *nice_input(char *prompt, int sy, int sx, gboolean digitsonly, return ReturnString; } +/* Return a blank string long enough to pad `name` out to `pad_len`. + This works with characters, not bytes, if in a UTF-8 locale */ +static char *pad_name(const char *name, guint pad_len) +{ + /* 40 character blank string (must be longer than max value of pad_len) */ + static char *pad = " "; + int slen; + if (LocaleIsUTF8) { + slen = g_utf8_strlen(name, -1); + } else { + slen = strlen(name); + } + if (slen > pad_len || slen > 40) { + return ""; + } else { + return pad + 40 - pad_len + slen; + } +} + static void DisplayDrugsHere(Player *Play) { int NumDrugsHere, i, c; t@@ -2265,8 +2284,9 @@ static void DisplayDrugsHere(Player *Play) c++, i = GetNextDrugIndex(i, Play)) { /* List of individual drug names for selection (%tde="Opium" etc. by default) */ - text = dpg_strdup_printf( _("%c. %-10tde %8P"), 'A' + c, - Drug[i].Name, Play->Drugs[i].Price); + text = dpg_strdup_printf( _("%c. %tde%s %8P"), 'A' + c, + Drug[i].Name, pad_name(Drug[i].Name, 10), + Play->Drugs[i].Price); names = g_slist_append(names, text); } display_select_list(names); t@@ -2654,6 +2674,7 @@ void CursesLoop(struct CMDLINE *cmdline) /* On Windows, force UTF-8 rather than the non-Unicode codepage */ bind_textdomain_codeset(PACKAGE, "UTF-8"); Conv_SetInternalCodeset("UTF-8"); + LocaleIsUTF8 = TRUE; WantUTF8Errors(TRUE); #endif (DIR) diff --git a/src/dopewars.c b/src/dopewars.c t@@ -101,6 +101,7 @@ gboolean Daemonize = TRUE; gchar *WebBrowser = NULL; gint ConfigErrors = 0; +gboolean LocaleIsUTF8 = FALSE; int NumLocation = 0, NumGun = 0, NumCop = 0, NumDrug = 0, NumSubway = 0; int NumPlaying = 0, NumStoppedTo = 0; t@@ -2924,9 +2925,11 @@ int main(int argc, char *argv[]) { struct CMDLINE *cmdline; #ifdef ENABLE_NLS + const char *charset; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + LocaleIsUTF8 = g_get_charset(&charset); #endif WantUTF8Errors(FALSE); g_log_set_handler(NULL, LogMask(), DefaultLogMessage, NULL); (DIR) diff --git a/src/dopewars.h b/src/dopewars.h t@@ -371,6 +371,7 @@ extern GSList *ServerList; extern GScannerConfig ScannerConfig; extern struct LOG Log; extern gint ConfigErrors; +extern gboolean LocaleIsUTF8; GSList *RemovePlayer(Player *Play, GSList *First); Player *GetPlayerByID(guint ID, GSList *First); (DIR) diff --git a/src/winmain.c b/src/winmain.c t@@ -283,6 +283,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + LocaleIsUTF8 = g_get_charset(&charset); #endif /* Informational comment placed at the start of the Windows log file