diff options
author | Karel Zak <kzak@redhat.com> | 2010-05-07 14:12:26 +0200 |
---|---|---|
committer | Karel Zak <kzak@redhat.com> | 2010-05-07 14:12:26 +0200 |
commit | 5f94ca33cf7772e0c36b5b3e5b1cf1ab01f60180 (patch) | |
tree | ca7fbaf1bc031a50d958993eb52e29407fc6fdd9 | |
parent | 8fda88ed832158741abc9e8fb8215856b9c4ec16 (diff) | |
download | util-linux-5f94ca33cf7772e0c36b5b3e5b1cf1ab01f60180.tar.gz |
cfdisk: support non-ascii characters in input
On Sat, Apr 03, 2010 at 12:58:48PM +0000, Jorge wrote:
> When you want to write changes to disk you're asked for a
> confirmation, like this one:
>
> Are you sure you want to write the partition table to disk? (yes
> or no)
>
> There is no problem on the English version, but when you launch the
> program in Spanish you get this:
>
> ¿Está seguro de que desea escribir la tabla de particiones en el
> disco?
> (sí o no):
>
> You can't type the "í" character. Trying to do so will end in no
> input at all. That is, typing in my keyboard "´" then "i" leads to
> nothing. So you can't write changes to disk, and you must launch the
> program in English for it to operate.
Reported-by: Jorge <yo@jorgesuarezdelis.name>
Addresses: https://bugs.launchpad.net/ubuntu/+source/util-linux/+bug/205327
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r-- | fdisk/Makefile.am | 2 | ||||
-rw-r--r-- | fdisk/cfdisk.c | 55 | ||||
-rw-r--r-- | include/mbsalign.h | 8 | ||||
-rw-r--r-- | lib/mbsalign.c | 34 |
4 files changed, 87 insertions, 12 deletions
diff --git a/fdisk/Makefile.am b/fdisk/Makefile.am index 862fa016..7b87d6cf 100644 --- a/fdisk/Makefile.am +++ b/fdisk/Makefile.am @@ -53,7 +53,7 @@ endif if USE_SLANG sbin_PROGRAMS += cfdisk dist_man_MANS += cfdisk.8 -cfdisk_SOURCES = cfdisk.c $(fdisk_common) +cfdisk_SOURCES = cfdisk.c $(fdisk_common) ../lib/mbsalign.c cfdisk_CFLAGS = $(cflags_blkid) cfdisk_LDADD = -lslang $(ldadd_blkid) else diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c index 8de285b4..b1eaceeb 100644 --- a/fdisk/cfdisk.c +++ b/fdisk/cfdisk.c @@ -83,11 +83,16 @@ #include <blkid.h> #endif +#ifdef HAVE_WIDECHAR +#include <wctype.h> +#endif + #include "nls.h" #include "blkdev.h" #include "xstrncpy.h" #include "common.h" #include "gpt.h" +#include "mbsalign.h" #ifdef __GNU__ #define DEFAULT_DEVICE "/dev/hd0" @@ -407,10 +412,10 @@ fdexit(int ret) { static int get_string(char *str, int len, char *def) { - unsigned char c; - int i = 0; - int x, y; + size_t cells = 0, i = 0; + int x, y, key; int use_def = FALSE; + wint_t c; getyx(stdscr, y, x); clrtoeol(); @@ -424,7 +429,13 @@ get_string(char *str, int len, char *def) { } refresh(); + +#if defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR) + while ((key = get_wch(&c)) != ERR && + c != '\r' && c != '\n' && c != KEY_ENTER) { +#else while ((c = getch()) != '\n' && c != CR) { +#endif switch (c) { case ESC: move(y, x); @@ -433,10 +444,14 @@ get_string(char *str, int len, char *def) { return GS_ESCAPE; case DEL: case '\b': + case KEY_BACKSPACE: if (i > 0) { - str[--i] = 0; - mvaddch(y, x+i, ' '); - move(y, x+i); + cells--; + i = mbs_truncate(str, &cells); + if (i < 0) + return GS_ESCAPE; + mvaddch(y, x + cells, ' '); + move(y, x + cells); } else if (use_def) { clrtoeol(); use_def = FALSE; @@ -444,15 +459,39 @@ get_string(char *str, int len, char *def) { putchar(BELL); break; default: +#if defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR) + if (i < len && iswprint(c)) { + wchar_t wc = (wchar_t) c; + char s[MB_CUR_MAX + 1]; + int sz = wctomb(s, wc); + + if (sz + i < len) { + s[sz] = '\0'; + mvaddnstr(y, x + cells, s, sz); + if (use_def) { + clrtoeol(); + use_def = FALSE; + } + memcpy(str + i, s, sz); + i += sz; + str[i] = '\0'; + cells += wcwidth(wc); + } else + putchar(BELL); + } +#else if (i < len && isprint(c)) { - mvaddch(y, x+i, c); + mvaddch(y, x + cells, c); if (use_def) { clrtoeol(); use_def = FALSE; } str[i++] = c; str[i] = 0; - } else + cells++; + } +#endif + else putchar(BELL); } refresh(); diff --git a/include/mbsalign.h b/include/mbsalign.h index b8a588c2..fd957b39 100644 --- a/include/mbsalign.h +++ b/include/mbsalign.h @@ -38,6 +38,8 @@ enum { #endif }; -size_t -mbsalign (const char *src, char *dest, size_t dest_size, - size_t *width, mbs_align_t align, int flags); +extern size_t mbs_truncate(char *str, size_t *width); + +extern size_t mbsalign (const char *src, char *dest, + size_t dest_size, size_t *width, + mbs_align_t align, int flags); diff --git a/lib/mbsalign.c b/lib/mbsalign.c index c1a5472e..82ffc09c 100644 --- a/lib/mbsalign.c +++ b/lib/mbsalign.c @@ -99,6 +99,40 @@ rpl_wcswidth (const wchar_t *s, size_t n) } #endif +/* Truncate multi-byte string to @width and returns number of + * bytes of the new string @str, and in @width returns number + * of cells. + */ +size_t +mbs_truncate(char *str, size_t *width) +{ + size_t bytes = strlen(str); +#ifdef HAVE_WIDECHAR + size_t sz = mbstowcs(NULL, str, 0); + wchar_t *wcs = NULL; + + if (sz == (size_t) -1) + goto done; + + wcs = malloc((sz + 1) * sizeof(wchar_t)); + if (!wcs) + goto done; + + if (!mbstowcs(wcs, str, sz)) + goto done; + *width = wc_truncate(wcs, *width); + bytes = wcstombs(str, wcs, bytes); +done: + free(wcs); +#else + if (*width < bytes) + bytes = *width; +#endif + if (bytes >= 0) + str[bytes] = '\0'; + return bytes; +} + /* Write N_SPACES space characters to DEST while ensuring nothing is written beyond DEST_END. A terminating NUL is always added to DEST. |