Index: intl.h =================================================================== --- intl.h (revision 157453) +++ intl.h (working copy) @@ -30,6 +30,8 @@ #include extern void gcc_init_libintl (void); extern size_t gcc_gettext_width (const char *); +extern unsigned int get_aligned_len (const char *, unsigned int, + unsigned int); #else /* Stubs. */ # undef textdomain @@ -41,6 +43,7 @@ # define ngettext(singular,plural,n) fake_ngettext(singular,plural,n) # define gcc_init_libintl() /* nothing */ # define gcc_gettext_width(s) strlen(s) +# define get_aligned_len (s, room, remaining) remaining extern const char *fake_ngettext(const char *singular,const char *plural, unsigned long int n); Index: intl.c =================================================================== --- intl.c (revision 157453) +++ intl.c (working copy) @@ -92,6 +92,7 @@ #if defined HAVE_WCHAR_H && defined HAVE_WORKING_MBSTOWCS && defined HAVE_WCSWIDTH #include +#include /* Returns the width in columns of MSGSTR, which came from gettext. This is for indenting subsequent output. */ @@ -106,6 +107,87 @@ return wcswidth (wmsgstr, nwcs); } +/* Return the number of bytes when converts the wide character WC + to its multibyte representation. */ + +static int +wctomb_nbytes (wchar_t wc) +{ + char *pmb = (char *)xmalloc (MB_CUR_MAX); + int nbytes = wctomb (pmb, wc); + if (pmb) + free (pmb); + return nbytes; +} + +/* Return the length of MSGSTR that can be printed within the width ROOM. */ + +unsigned int +get_aligned_len (const char *msgstr, unsigned int room, + unsigned int remaining) +{ + unsigned int i; + unsigned int len = 0; + unsigned int pos = 0; + int nbytes; + int len_bk; + wchar_t *buf; + unsigned int colwide = 0; + size_t remaining_width; + + size_t nwcs = mbstowcs (0, msgstr, 0); + wchar_t *wmsgstr = XALLOCAVEC (wchar_t, nwcs + 1); + + mbstowcs (wmsgstr, msgstr, nwcs + 1); + remaining_width = wcswidth (wmsgstr, nwcs); + + for (i = 0; i < nwcs; i++) + { + unsigned int maybe_width = colwide + (i - pos); + nbytes = wctomb_nbytes (wmsgstr [i]); + if (maybe_width == remaining_width) + len = remaining; + else if (colwide > room) + { + len = len_bk; + break; + } + else if (colwide == room || maybe_width > room) + break; + else if (nbytes > 1) + { + buf = XALLOCAVEC (wchar_t, i + 2); + wcsncpy (buf, wmsgstr, i + 1); + buf [i + 1] = L'\0'; + len_bk = len; + len = wcstombs (0, buf, 0); + colwide = wcswidth (buf, i + 1); + /* Keep the puncts printed with the previous word. */ + if (iswpunct (wmsgstr [i + 1]) + && iswalpha (wmsgstr [i -1])) + { + i++; + nbytes = wctomb_nbytes (wmsgstr [i]); + if (nbytes > 1) + { + buf = XALLOCAVEC (wchar_t, i + 2); + wcsncpy (buf, wmsgstr, i + 1); + buf [i + 1] = '\0'; + len = wcstombs (0, buf, 0); + colwide = wcswidth (buf, i + 1); + } + else + { + len = len + 1; + colwide = colwide + 1; + } + } + pos = i; + } + } + return len; +} + #else /* no wcswidth */ /* We don't have any way of knowing how wide the string is. Guess @@ -117,6 +199,13 @@ return strlen (msgstr); } +unsigned int +get_aligned_len (const char *msgstr, unsigned int room, + unsigned int remaining) +{ + return remaining; +} + #endif #endif /* ENABLE_NLS */ Index: opts.c =================================================================== --- opts.c (revision 157453) +++ opts.c (working copy) @@ -1158,12 +1158,29 @@ unsigned int columns) { unsigned int col_width = LEFT_COLUMN; - unsigned int remaining, room, len; + unsigned int remaining, room, len, item_col_width; + unsigned int i; remaining = strlen (help); + item_col_width = gcc_gettext_width (item); do { + if (item_width == item_col_width + || item_width == 0) + printf (" %-*.*s", col_width, item_width, item); + else + { + printf (" %s", item); + if (item_col_width < col_width) + { + unsigned int n_spaces = col_width - item_col_width; + const char *space = " "; + for (i = 0; i < n_spaces; i++) + printf ("%s", space); + } + } + room = columns - 3 - MAX (col_width, item_width); if (room > columns) room = 0; @@ -1171,22 +1188,25 @@ if (room < len) { - unsigned int i; - - for (i = 0; help[i]; i++) + if (len != gcc_gettext_width (help)) + len = get_aligned_len (help, room, remaining); + else { - if (i >= room && len != remaining) - break; - if (help[i] == ' ') - len = i; - else if ((help[i] == '-' || help[i] == '/') - && help[i + 1] != ' ' - && i > 0 && ISALPHA (help[i - 1])) - len = i + 1; + for (i = 0; help[i]; i++) + { + if (i >= room && len != remaining) + break; + if (help[i] == ' ') + len = i; + else if ((help[i] == '-' || help[i] == '/') + && help[i + 1] != ' ' + && i > 0 && ISALPHA (help[i - 1])) + len = i + 1; + } } } - printf( " %-*.*s %.*s\n", col_width, item_width, item, len, help); + printf ( " %.*s\n", len, help); item_width = 0; while (help[len] == ' ') len++; @@ -1242,6 +1262,7 @@ unsigned int len; const char *opt; const char *tab; + char *buf; if (include_flags == 0 || ((option->flags & include_flags) != include_flags)) @@ -1278,7 +1299,10 @@ if (tab) { len = tab - help; - opt = help; + buf = (char *)alloca (len + 1); + strncpy (buf, help, len); + buf[len] = '\0'; + opt = buf; help = tab + 1; } else