Patch by Takao Fujiwara for popt >= 1.13, which should fix all POPT_fprintf() usage cases where umlauts were broken in --help output at some non-UTF8 locales. Problem is, that some of the applications do not set bind_textdomain_codeset(), so this patch is working around it and likely to get upstream for popt 1.13.1. --- popt-1.13/popthelp.c 2008-01-16 02:19:01.000000000 +0900 +++ popt-1.13/popthelp.c.textdomain 2008-01-25 02:18:08.000000000 +0900 @@ -15,13 +15,6 @@ #include #endif -#define POPT_WCHAR_HACK -#ifdef POPT_WCHAR_HACK -#include /* for mbsrtowcs */ -/*@access mbstate_t @*/ -#endif - - #include "poptint.h" /*@access poptContext@*/ @@ -374,6 +367,16 @@ static void singleOptionHelp(FILE * fp, case POPT_ARG_STRING: *le++ = (opt->longName != NULL ? '=' : ' '); strcpy(le, argDescrip); le += strlen(le); + { const char * scopy = argDescrip; + size_t n = 0; + + while (*scopy != '\0') { + scopy = POPT_next_char (scopy); + n++; + } + + displaypad = (int) (strlen (argDescrip) - n); + } break; default: break; @@ -387,18 +390,17 @@ static void singleOptionHelp(FILE * fp, lelen = strlen(le); le += lelen; -#ifdef POPT_WCHAR_HACK { const char * scopy = argDescrip; - mbstate_t t; - size_t n; + size_t n = 0; - memset ((void *)&t, 0, sizeof (t)); /* In initial state. */ /* Determine number of characters. */ - n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t); + while (*scopy != '\0') { + scopy = POPT_next_char (scopy); + n++; + } displaypad = (int) (lelen-n); } -#endif } if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) *le++ = ']'; @@ -420,6 +422,7 @@ static void singleOptionHelp(FILE * fp, helpLength = strlen(help); while (helpLength > lineLength) { const char * ch; + char * formatted_help = NULL; char format[16]; ch = help + lineLength - 1; @@ -430,9 +433,12 @@ static void singleOptionHelp(FILE * fp, ch = POPT_prev_char (ch); ch++; - sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), (int) indentLength); + formatted_help = xstrdup (help); + formatted_help[ch - help] = '\0'; + sprintf(format, "%%s\n%%%ds", (int) indentLength); /*@-formatconst@*/ - xx = POPT_fprintf(fp, format, help, " "); + xx = POPT_fprintf(fp, format, formatted_help, " "); + free (formatted_help); /*@=formatconst@*/ help = ch; while (_isspaceptr(help) && *help) help++; @@ -594,7 +600,7 @@ static size_t showHelpIntro(poptContext size_t len = (size_t)6; const char * fn; - fprintf(fp, POPT_("Usage:")); + POPT_fprintf(fp, POPT_("Usage:")); if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) { /*@-type@*/ /* LCL: wazzup? */ fn = con->optionStack->argv[0]; @@ -614,9 +620,9 @@ void poptPrintHelp(poptContext con, FILE (void) showHelpIntro(con, fp); if (con->otherHelp) - fprintf(fp, " %s\n", con->otherHelp); + POPT_fprintf(fp, " %s\n", con->otherHelp); else - fprintf(fp, " %s\n", POPT_("[OPTION...]")); + POPT_fprintf(fp, " %s\n", POPT_("[OPTION...]")); if (columns) { columns->cur = maxArgWidth(con->options, NULL); --- popt-1.13/poptint.c 2008-01-16 00:28:39.000000000 +0900 +++ popt-1.13/poptint.c.textdomain 2008-01-25 02:20:34.000000000 +0900 @@ -2,6 +2,35 @@ #include #include "poptint.h" +const char utf8_skip_data[256] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1 +}; + +#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__) +char * +_D_ (const char * dom, const char * str) +{ + char * codeset = NULL; + char * retval = NULL; + + if (!dom) + dom = textdomain (NULL); + codeset = bind_textdomain_codeset (dom, NULL); + bind_textdomain_codeset (dom, "UTF-8"); + retval = dgettext(dom, str); + bind_textdomain_codeset (dom, codeset); + + return retval; +} +#endif + #ifdef HAVE_ICONV static /*@only@*/ /*@null@*/ char * strdup_locale_from_utf8 (/*@null@*/ char *buffer) --- popt-1.13/poptint.h 2008-01-16 02:01:07.000000000 +0900 +++ popt-1.13/poptint.h.textdomain 2008-01-25 01:44:43.000000000 +0900 @@ -104,8 +104,10 @@ struct poptContext_s { #define _(foo) foo #endif +extern const char utf8_skip_data[]; +#define POPT_next_char(p) (char *)((p) + utf8_skip_data[*(const unsigned char *)(p)]) #if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__) -#define D_(dom, str) dgettext(dom, str) +#define D_(dom, str) _D_(dom, str) #define POPT_(foo) D_("popt", foo) #else #define D_(dom, str) str