encodings such as KOI8-R can type properly again. (DLR, found
by Arthur Ivanov)
- Massively overhaul the input and output routines to support
- buffered input and output, the first steps toward wide
- character input and output, and double-Escape/verbatim input
- of double-byte Unicode characters instead of single-byte ASCII
- characters. New functions do_input(), do_mouse(),
- do_output(), is_byte_char(), get_buffer(), get_buffer_len(),
+ buffered input and output, the first steps toward
+ wide/multibyte character input and output, and
+ double-Escape/verbatim input of double-byte Unicode characters
+ instead of single-byte ASCII characters. New functions
+ is_byte_char(), get_buffer(), get_buffer_len(),
buffer_to_keys(), unget_input(), get_input(), parse_kbinput(),
and parse_verbatim_kbinput(); new macro charcpy(); changes to
do_char() (renamed to do_output()), get_edit_input() (renamed
to do_input() and moved to nano.c), get_edit_mouse() (renamed
do_mouse() and moved to nano.c), do_verbatim_input(),
do_tab(), main(), and get_ascii_kbinput() (renamed to
- get_word_kbinput()). (DLR; buffered input/output based on
- ideas from mutt 1.4.2.1; double-Escape input of Unicode
- characters suggested by Michael Piefel)
+ get_word_kbinput()). The wide version of ncurses is required
+ in order for output to work properly. (DLR; buffered
+ input/output based on ideas from mutt 1.4.2.1; double-Escape
+ input of Unicode characters suggested by Michael Piefel)
- cut.c:
do_cut_text()
- If keep_cutbuffer is FALSE, only blow away the text in the
- Add a debug message. (DLR)
- configure.ac:
- Remove specific references to control key shortcuts. (DLR)
+ - Check for the wide version of ncurses, without which multibyte
+ strings don't seem to be displayed properly. (DLR; check for
+ addwstr() in curses to determine whether it has wide character
+ support inspired by mutt 1.4.2.1i's checking for waddnwstr()
+ for the same reason)
- doc/nanorc.sample:
- Add return to the "c-file" regexes. (DLR)
dnl Checks for libraries.
if eval "test x$CURSES_LIB_NAME = x"
then
- AC_CHECK_HEADERS(curses.h ncurses.h)
- AC_CHECK_LIB(ncurses, initscr, [CURSES_LIB="-lncurses" CURSES_LIB_NAME=ncurses])
+ AC_CHECK_HEADERS(ncurses.h)
+ AC_CHECK_LIB(ncursesw, addwstr, [CURSES_LIB="-lncursesw" CURSES_LIB_NAME=ncursesw CURSES_LIB_WIDE="yes"])
+ if eval "test x$CURSES_LIB_NAME = x"
+ then
+ AC_CHECK_LIB(ncurses, initscr, [CURSES_LIB="-lncurses" CURSES_LIB_NAME=ncurses])
+ fi
fi
if eval "test x$CURSES_LIB_NAME = x"
then
- AC_CHECK_LIB(curses, initscr, [CURSES_LIB="-lcurses" CURSES_LIB_NAME=curses])
-fi
-
-if eval "test x$CURSES_LIB_NAME = x"
-then
- AC_CHECK_LIB(termcap, tgetent, [CURSES_LIB="-ltermcap" CURSES_LIB_NAME=termcap])
+ AC_CHECK_HEADERS(curses.h)
+ AC_CHECK_LIB(curses, addwstr, [CURSES_LIB="-lcurses" CURSES_LIB_NAME=curses CURSES_LIB_WIDE="yes"])
+ if eval "test x$CURSES_LIB_NAME = x"
+ then
+ AC_CHECK_LIB(curses, initscr, [CURSES_LIB="-lcurses" CURSES_LIB_NAME=curses])
+ fi
fi
if eval "test x$CURSES_LIB_NAME = x"
then
AC_MSG_WARN([
-*** No termcap lib available, consider getting the official ncurses
+*** No curses lib available. Consider getting the official ncurses
*** distribution from ftp://ftp.gnu.org/pub/gnu/ncurses if you get
*** errors compiling nano.])
else
- AC_MSG_RESULT([Using $CURSES_LIB_NAME as the termcap library])
+ AC_MSG_RESULT([Using $CURSES_LIB_NAME as the curses library])
fi
AC_CHECK_LIB([$CURSES_LIB_NAME], use_default_colors, AC_DEFINE(HAVE_USE_DEFAULT_COLORS, 1, [Define this if your curses library has the use_default_colors command.]))
LDFLAGS="$LDFLAGS $GLIB_LIBS"
fi
+if test "x$CURSES_LIB_WIDE" == "xyes"
+then
+ AC_DEFINE(NANO_WIDE, 1, [Define this if your system has wide character support.])
+else
+ AC_MSG_WARN([No wide character support found. nano will not be able to support UTF-8.])
+fi
+
AC_CONFIG_FILES([
Makefile
doc/Makefile
/* Do we have to call edit_refresh(), or can we get away with
* update_line()? */
- char key[
#ifdef NANO_WIDE
- MB_LEN_MAX
+ char *key =
+ charalloc(MB_CUR_MAX)
#else
- 1
+ charalloc(1)
#endif
- ]; /* The current multibyte character we have. */
- int key_len; /* The length of the current multibyte
- * character. */
+ ;
assert(current != NULL && current->data != NULL);
/* Turn off constant cursor position display. */
UNSET(CONSTUPDATE);
-#ifdef NANO_WIDE
- wctomb(NULL, 0);
-#endif
-
for (i = 0; i < kbinput_len; i++) {
+ int key_len;
+
/* Null to newline, if needed. */
if (kbinput[i] == '\0')
kbinput[i] = '\n';
charcpy(¤t->data[current_x], key, key_len);
current_len += key_len;
/* FIXME: Should totsize be the number of single-byte characters
- * or the number of multibyte characters? Assume for former for
+ * or the number of multibyte characters? Assume the former for
* now. */
totsize += key_len;
set_modified();
#endif
}
-#ifdef NANO_WIDE
- wctomb(NULL, 0);
-#endif
-
/* Turn constant cursor position display back on if it was on
* before. */
if (old_constupdate)
SET(CONSTUPDATE);
+ free(key);
+
if (do_refresh)
edit_refresh();
else
#define VERMSG "GNU nano " VERSION
-/* FIXME: We should be checking for this instead of unconditionally
- * using it. */
-#define NANO_WIDE 1
-
/* If we aren't using ncurses, turn the mouse support off, as it's
* ncurses-specific. */
#ifndef NCURSES_MOUSE_VERSION
* default keystroke buffer is empty. */
void get_buffer(WINDOW *win)
{
- int input;
+ int input, input_key_code;
/* If the keystroke buffer isn't empty, get out. */
if (key_buffer != NULL)
#ifndef NANO_SMALL
allow_pending_sigwinch(TRUE);
#endif
- input = wgetch(win);
+
+#ifdef NANO_WIDE
+ if (!ISSET(NO_UTF8)) {
+ wint_t tmp;
+
+ input_key_code = wget_wch(win, &tmp);
+ input = (int)tmp;
+ } else {
+#endif
+ input = wgetch(win);
+ input_key_code = !is_byte_char(input);
+#ifdef NANO_WIDE
+ }
+#endif
+
#ifndef NANO_SMALL
allow_pending_sigwinch(FALSE);
#endif
/* Increment the length of the keystroke buffer, save the value of
* the keystroke in key, and set key_code to TRUE if the keystroke
- * is an extended keypad value and hence shouldn't be treated as a
- * multibyte character. */
+ * is an extended keypad value or FALSE if it isn't. */
key_buffer_len++;
key_buffer = (buffer *)nmalloc(sizeof(buffer));
key_buffer[0].key = input;
- key_buffer[0].key_code = !is_byte_char(input);
+ key_buffer[0].key_code =
+#ifdef NANO_WIDE
+ !ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
+#endif
+ input_key_code;
/* Read in the remaining characters using non-blocking input. */
nodelay(win, TRUE);
#ifndef NANO_SMALL
allow_pending_sigwinch(TRUE);
#endif
- input = wgetch(win);
-#ifndef NANO_SMALL
- allow_pending_sigwinch(FALSE);
-#endif
+#ifdef NANO_WIDE
+ if (!ISSET(NO_UTF8)) {
+ wint_t tmp;
+
+ input_key_code = wget_wch(win, &tmp);
+ input = (int)tmp;
+ } else {
+#endif
+ input = wgetch(win);
+ input_key_code = !is_byte_char(input);
+#ifdef NANO_WIDE
+ }
+#endif
/* If there aren't any more characters, stop reading. */
- if (input == ERR)
+ if (
+#ifdef NANO_WIDE
+ (!ISSET(NO_UTF8) && input_key_code == ERR) ||
+#endif
+ input == ERR)
break;
/* Otherwise, increment the length of the keystroke buffer, save
* the value of the keystroke in key, and set key_code to TRUE
- * if the keystroke is an extended keypad value and hence
- * shouldn't be treated as a multibyte character. */
+ * if the keystroke is an extended keypad value or FALSE if it
+ * isn't. */
key_buffer_len++;
key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
sizeof(buffer));
key_buffer[key_buffer_len - 1].key = input;
- key_buffer[key_buffer_len - 1].key_code = !is_byte_char(input);
+ key_buffer[key_buffer_len - 1].key_code =
+#ifdef NANO_WIDE
+ !ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
+#endif
+ input_key_code;
+
+#ifndef NANO_SMALL
+ allow_pending_sigwinch(FALSE);
+#endif
}
/* Switch back to non-blocking input. */
nodelay(win, FALSE);
-
-#ifdef NANO_WIDE
- if (!ISSET(NO_UTF8)) {
- size_t i;
- buffer *clean_key_buffer = NULL;
- size_t clean_key_buffer_len = 0;
-
- mbtowc(NULL, NULL, 0);
-
- /* Change all complete and valid multibyte keystrokes to
- * their wide character values, discarding the others. */
- for (i = 0; i < key_buffer_len; i++) {
- wchar_t wide_key;
- int wide_key_len;
-
- if (key_buffer[i].key_code) {
- mbtowc(NULL, NULL, 0);
-
- wide_key_len = 1;
- wide_key = key_buffer[i].key;
- } else
- wide_key_len = mbtowc(&wide_key,
- (const char *)&key_buffer[i].key, 1);
-
- if (wide_key_len != -1) {
- clean_key_buffer_len++;
- clean_key_buffer = (buffer *)nrealloc(clean_key_buffer,
- clean_key_buffer_len * sizeof(buffer));
-
- clean_key_buffer[clean_key_buffer_len - 1].key =
- (int)wide_key;
- clean_key_buffer[clean_key_buffer_len - 1].key_code =
- key_buffer[i].key_code;
- }
- }
-
- mbtowc(NULL, NULL, 0);
-
- /* Replace the default keystroke buffer with the non-(-1)
- * keystroke buffer. */
- key_buffer_len = clean_key_buffer_len;
- free(key_buffer);
- key_buffer = clean_key_buffer;
- }
-#endif
}
/* Return the length of the default keystroke buffer. */
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
size_t i;
-
- wctomb(NULL, 0);
+ char *key = charalloc(MB_CUR_MAX);
/* Keep all valid wide keystrokes, discarding the others. */
for (i = 0; i < input_len; i++) {
- char key[MB_LEN_MAX];
int key_len = input[i].key_code ? 1 :
wctomb(key, (wchar_t)input[i].key);
}
}
- wctomb(NULL, 0);
-
+ free(key);
} else {
#endif
clean_input = input;