summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fdisk/Makefile.am2
-rw-r--r--fdisk/cfdisk.c55
-rw-r--r--include/mbsalign.h8
-rw-r--r--lib/mbsalign.c34
4 files changed, 87 insertions, 12 deletions
diff --git a/fdisk/Makefile.am b/fdisk/Makefile.am
index 862fa0162..7b87d6cf5 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 8de285b4c..b1eaceebb 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 b8a588c20..fd957b398 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 c1a5472e8..82ffc09cd 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.