Commit b54155c4 authored by David Lawrence Ramsey's avatar David Lawrence Ramsey
Browse files

massive updates to multibyte/wide character support; deal with multibyte

characters and strings instead of wide characters and strings as much as
possible, and move multibyte/wide character-specific functions into
their own source file, chars.c


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2248 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
No related merge requests found
Showing with 947 additions and 859 deletions
+947 -859
......@@ -87,6 +87,23 @@ CVS code -
do_statusbar_input() and do_statusbar_output(); new functions
keys_to_buffer(), unparse_kbinput(), and
do_statusbar_verbatim_input(). (DLR)
- Yet more steps toward full wide character/multibyte character
support. Overhaul the functions that already have support for
them to work with multibyte strings as much as possible, add
support to a few more functions as well, and move multibyte
character-specific functions to their own source file. New
file chars.c; new functions is_blank_mbchar(),
is_blank_wchar(), is_cntrl_mbchar(), is_cntrl_wchar(),
control_mbrep(), control_wrep(), mbwidth(), mb_cur_max(), and
make_mbchar(); changes to is_blank_char() (moved to chars.c),
is_cntrl_char() (moved to chars.c), parse_char() (renamed
parse_mbchar() and moved to chars.c), do_verbatim_input(),
do_delete(), do_tab(), do_input(), do_output(), get_buffer(),
unget_input(), unget_kbinput(), get_input(), parse_kbinput(),
unparse_kbinput(), parse_verbatim_kbinput(),
do_statusbar_input(), do_statusbar_verbatim_kbinput(),
do_statusbar_output(), and display_string(); removal of
buffer_to_keys() and keys_to_buffer(). (DLR)
- cut.c:
do_cut_text()
- If keep_cutbuffer is FALSE, only blow away the text in the
......@@ -209,6 +226,7 @@ CVS code -
obsolete and it defines a struct termio that we don't use
anywhere. (DLR)
- Typo fixes. (DLR)
- Add checks for iswblank(), mblen(), and wctype.h. (DLR)
- doc/faq.html:
- Remove now-inaccurate note about verbatim input's not working
at prompts, and update its description to mention that it
......@@ -219,6 +237,8 @@ CVS code -
display. Since ASCII is technically only seven bits wide,
characters 128-255 aren't ASCII. (DLR, suggested by Michael
Piefel)
- src/Makefile.am:
- Add chars.c to nano_SOURCES. (DLR)
GNU nano 1.3.5 - 2004.11.22
- General:
......
......@@ -40,7 +40,7 @@ AM_GNU_GETTEXT([external], [need-ngettext])
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h getopt.h libintl.h limits.h regex.h termios.h wchar.h)
AC_CHECK_HEADERS(fcntl.h getopt.h libintl.h limits.h regex.h termios.h wchar.h wctype.h)
AC_CHECK_HEADER(regex.h,
AC_MSG_CHECKING([for broken regexec])
AC_TRY_RUN([
......@@ -291,7 +291,7 @@ AC_MSG_WARN([*** Can not use slang when cross-compiling])),
esac], [AC_MSG_RESULT(no)])
dnl Checks for functions
AC_CHECK_FUNCS(snprintf vsnprintf isblank strcasecmp strncasecmp strcasestr strnlen getline getdelim mbtowc wctomb wcwidth)
AC_CHECK_FUNCS(snprintf vsnprintf isblank iswblank strcasecmp strncasecmp strcasestr strnlen getline getdelim mblen mbtowc wctomb wcwidth)
if test "x$ac_cv_func_snprintf" = "xno" -o "x$ac_cv_func_vsnprintf" = "xno"
then
AM_PATH_GLIB_2_0(2.0.0,,
......@@ -357,9 +357,9 @@ then
LDFLAGS="$LDFLAGS $GLIB_LIBS"
fi
if test "x$CURSES_LIB_WIDE" = "xyes" -a "x$ac_cv_func_mbtowc" = "xyes" -a "x$ac_cv_func_wctomb" = "xyes" -a "x$ac_cv_func_wcwidth" = "xyes"
if test "x$CURSES_LIB_WIDE" = "xyes" -a "x$ac_cv_func_mblen" = "xyes" -a "x$ac_cv_func_mbtowc" = "xyes" -a "x$ac_cv_func_wctomb" = "xyes" -a "x$ac_cv_func_wcwidth" = "xyes"
then
AC_DEFINE(NANO_WIDE, 1, [Define this if your system has wide character support (a wide curses library, mbtowc(), wctomb(), and wcwidth()).])
AC_DEFINE(NANO_WIDE, 1, [Define this if your system has wide character support (a wide curses library, mblen(), mbtowc(), wctomb(), and wcwidth()).])
else
AC_MSG_WARN([Insufficient wide character support found. nano will not be able to support UTF-8.])
fi
......
......@@ -4,7 +4,8 @@ INCLUDES = -Iintl -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
ACLOCAL_AMFLAGS = -I m4
bin_PROGRAMS = nano
nano_SOURCES = color.c \
nano_SOURCES = chars.c \
color.c \
cut.c \
files.c \
global.c \
......
/* $Id$ */
/**************************************************************************
* chars.c *
* *
* Copyright (C) 2005 Chris Allegretta *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
**************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include "proto.h"
#include "nano.h"
#if defined(HAVE_WCHAR_H) && defined(NANO_WIDE)
#include <wchar.h>
#endif
#if defined(HAVE_WCTYPE_H) && defined(NANO_WIDE)
#include <wctype.h>
#endif
/* This function is equivalent to isblank(). */
bool is_blank_char(unsigned char c)
{
return
#ifdef HAVE_ISBLANK
isblank(c)
#else
isspace(c) && (c == '\t' || !is_cntrl_char(c))
#endif
;
}
/* This function is equivalent to isblank() for multibyte characters. */
bool is_blank_mbchar(const char *c)
{
assert(c != NULL);
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
wchar_t wc;
int c_mb_len = mbtowc(&wc, c, MB_CUR_MAX);
if (c_mb_len <= 0) {
mbtowc(NULL, NULL, 0);
wc = (unsigned char)*c;
}
return is_blank_wchar(wc);
} else
#endif
return is_blank_char((unsigned char)*c);
}
#ifdef NANO_WIDE
/* This function is equivalent to isblank() for wide characters. */
bool is_blank_wchar(wchar_t wc)
{
return
#ifdef HAVE_ISWBLANK
iswblank(wc)
#else
iswspace(wc) && (wc == '\t' || !is_cntrl_wchar(wc))
#endif
;
}
#endif
/* This function is equivalent to iscntrl(), except in that it also
* handles control characters with their high bits set. */
bool is_cntrl_char(unsigned char c)
{
return (c < 32) || (127 <= c && c < 160);
}
/* This function is equivalent to iscntrl() for multibyte characters,
* except in that it also handles multibyte control characters with
* their high bits set. */
bool is_cntrl_mbchar(const char *c)
{
assert(c != NULL);
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
wchar_t wc;
int c_mb_len = mbtowc(&wc, c, MB_CUR_MAX);
if (c_mb_len <= 0) {
mbtowc(NULL, NULL, 0);
wc = (unsigned char)*c;
}
return is_cntrl_wchar(wc);
} else
#endif
return is_cntrl_char((unsigned char)*c);
}
#ifdef NANO_WIDE
/* This function is equivalent to iscntrl() for wide characters, except
* in that it also handles wide control characters with their high bits
* set. */
bool is_cntrl_wchar(wchar_t wc)
{
return (0 <= wc && wc < 32) || (127 <= wc && wc < 160);
}
#endif
/* c is a control character. It displays as ^@, ^?, or ^[ch] where ch
* is c + 64. We return that character. */
unsigned char control_rep(unsigned char c)
{
/* Treat newlines embedded in a line as encoded nulls. */
if (c == '\n')
return '@';
else if (c == NANO_CONTROL_8)
return '?';
else
return c + 64;
}
/* c is a multibyte control character. It displays as ^@, ^?, or ^[ch]
* where ch is c + 64. We return that multibyte character. */
char *control_mbrep(const char *c, char *crep, int *crep_len)
{
assert(c != NULL);
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
wchar_t wc, wcrep;
int c_mb_len = mbtowc(&wc, c, MB_CUR_MAX), crep_mb_len;
if (c_mb_len <= 0) {
mbtowc(NULL, NULL, 0);
wc = *c;
}
wcrep = control_wrep(wc);
crep_mb_len = wctomb(crep, wcrep);
if (crep_mb_len <= 0) {
wctomb(NULL, 0);
crep_mb_len = 0;
}
*crep_len = crep_mb_len;
return crep;
} else {
#endif
*crep_len = 1;
crep[0] = control_rep((unsigned char)*c);
return crep;
#ifdef NANO_WIDE
}
#endif
}
#ifdef NANO_WIDE
/* c is a wide control character. It displays as ^@, ^?, or ^[ch] where
* ch is c + 64. We return that wide character. */
wchar_t control_wrep(wchar_t wc)
{
/* Treat newlines embedded in a line as encoded nulls. */
if (wc == '\n')
return '@';
else if (wc == NANO_CONTROL_8)
return '?';
else
return wc + 64;
}
#endif
/* This function is equivalent to wcwidth() for multibyte characters. */
int mbwidth(const char *c)
{
assert(c != NULL);
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
wchar_t wc;
int c_mb_len = mbtowc(&wc, c, MB_CUR_MAX), width;
if (c_mb_len <= 0) {
mbtowc(NULL, NULL, 0);
wc = (unsigned char)*c;
}
width = wcwidth(wc);
if (width == -1)
width++;
return width;
} else
#endif
return 1;
}
/* Return the maximum width in bytes of a multibyte character. */
int mb_cur_max(void)
{
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8))
return MB_CUR_MAX;
else
#endif
return 1;
}
/* Convert the value in chr to a multibyte character with the same
* wide character value as chr. Return the multibyte character and its
* length. */
char *make_mbchar(unsigned int chr, char *chr_mb, int *chr_mb_len)
{
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
*chr_mb_len = wctomb(chr_mb, chr);
if (*chr_mb_len <= 0) {
mbtowc(NULL, NULL, 0);
*chr_mb_len = 1;
chr_mb[0] = (unsigned char)chr;
}
} else {
#endif
*chr_mb_len = 1;
chr_mb[0] = (unsigned char)chr;
#ifdef NANO_WIDE
}
#endif
return chr_mb;
}
/* Parse a multibyte character from buf. Return the number of bytes
* used. If chr isn't NULL, store the multibyte character in it. If
* bad_chr isn't NULL, set it to TRUE if we have a null byte or a bad
* multibyte character. If col isn't NULL, store the new display width
* in it. If *str is '\t', we expect col to have the current display
* width. */
int parse_mbchar(const char *buf, char *chr
#ifdef NANO_WIDE
, bool *bad_chr
#endif
, size_t *col)
{
int buf_mb_len;
assert(buf != NULL);
#ifdef NANO_WIDE
if (bad_chr != NULL)
*bad_chr = FALSE;
if (!ISSET(NO_UTF8)) {
/* Get the number of bytes in the multibyte character. */
buf_mb_len = mblen(buf, MB_CUR_MAX);
/* If buf contains a null byte or an invalid multibyte
* character, interpret buf's first byte and set bad_chr to
* TRUE. */
if (buf_mb_len <= 0) {
mblen(NULL, 0);
buf_mb_len = 1;
if (bad_chr != NULL)
*bad_chr = TRUE;
}
/* Save the multibyte character in chr. */
if (chr != NULL) {
int i;
for (i = 0; i < buf_mb_len; i++)
chr[i] = buf[i];
}
/* Save the column width of the wide character in col. */
if (col != NULL) {
/* If we have a tab, get its width in columns using the
* current value of col. */
if (*buf == '\t')
*col += tabsize - *col % tabsize;
/* If we have a control character, get its width using one
* column for the "^" that will be displayed in front of it,
* and the width in columns of its visible equivalent as
* returned by control_rep(). */
else if (is_cntrl_mbchar(buf)) {
char *ctrl_buf_mb = charalloc(mb_cur_max());
int ctrl_buf_mb_len;
(*col)++;
ctrl_buf_mb = control_mbrep(buf, ctrl_buf_mb,
&ctrl_buf_mb_len);
*col += mbwidth(ctrl_buf_mb);
free(ctrl_buf_mb);
/* If we have a normal character, get its width in columns
* normally. */
} else
*col += mbwidth(buf);
}
} else {
#endif
/* Get the number of bytes in the byte character. */
buf_mb_len = 1;
/* Save the byte character in chr. */
if (chr != NULL)
*chr = *buf;
if (col != NULL) {
/* If we have a tab, get its width in columns using the
* current value of col. */
if (*buf == '\t')
*col += tabsize - *col % tabsize;
/* If we have a control character, it's two columns wide:
* one column for the "^" that will be displayed in front of
* it, and one column for its visible equivalent as returned
* by control_rep(). */
else if (is_cntrl_char((unsigned char)*buf))
*col += 2;
/* If we have a normal character, it's one column wide. */
else
(*col)++;
}
#ifdef NANO_WIDE
}
#endif
return buf_mb_len;
}
......@@ -2175,7 +2175,7 @@ char *input_tab(char *buf, int place, bool *lastwastab, int *newplace,
tmp = matchbuf;
/* skip any leading white space */
while (*tmp && isblank(*tmp))
while (*tmp && is_blank_char(*tmp))
++tmp;
/* Free up any memory already allocated */
......
......@@ -2,7 +2,7 @@
/**************************************************************************
* move.c *
* *
* Copyright (C) 1999-2004 Chris Allegretta *
* Copyright (C) 1999-2005 Chris Allegretta *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2, or (at your option) *
......@@ -58,7 +58,7 @@ void do_home(void)
if (ISSET(SMART_HOME)) {
size_t current_x_save = current_x;
for (current_x = 0; isblank(current->data[current_x]) &&
for (current_x = 0; is_blank_char(current->data[current_x]) &&
current->data[current_x] != '\0'; current_x++)
;
......
......@@ -1144,8 +1144,9 @@ bool open_pipe(const char *command)
void do_verbatim_input(void)
{
int *kbinput; /* Used to hold verbatim input. */
size_t kbinput_len; /* Length of verbatim input. */
int *kbinput;
size_t kbinput_len, i;
char *output;
statusbar(_("Verbatim input"));
......@@ -1153,9 +1154,15 @@ void do_verbatim_input(void)
kbinput = get_verbatim_kbinput(edit, &kbinput_len);
/* Display all the verbatim characters at once. */
do_output(kbinput, kbinput_len);
output = charalloc(kbinput_len + 1);
free(kbinput);
for (i = 0; i < kbinput_len; i++)
output[i] = (char)kbinput[i];
output[i] = '\0';
do_output(output, kbinput_len);
free(output);
}
void do_backspace(void)
......@@ -1178,7 +1185,7 @@ void do_delete(void)
placewewant = xplustabs();
if (current->data[current_x] != '\0') {
int char_len = parse_char(current->data + current_x, NULL
int char_buf_len = parse_mbchar(current->data + current_x, NULL
#ifdef NANO_WIDE
, NULL
#endif
......@@ -1189,15 +1196,15 @@ void do_delete(void)
/* Let's get dangerous. */
charmove(&current->data[current_x],
&current->data[current_x + char_len],
line_len - char_len + 1);
&current->data[current_x + char_buf_len],
line_len - char_buf_len + 1);
null_at(&current->data, current_x + line_len - char_len);
null_at(&current->data, current_x + line_len - char_buf_len);
#ifndef NANO_SMALL
if (current_x < mark_beginx && mark_beginbuf == current)
mark_beginx -= char_len;
mark_beginx -= char_buf_len;
#endif
totsize -= char_len;
totsize -= char_buf_len;
} else if (current != filebot && (current->next != filebot ||
current->data[0] == '\0')) {
/* We can delete the line before filebot only if it is blank: it
......@@ -1251,8 +1258,9 @@ void do_delete(void)
void do_tab(void)
{
int kbinput = '\t';
do_output(&kbinput, 1);
char *kbinput = "\t";
do_output(kbinput, 1);
}
/* Someone hits return *gasp!* */
......@@ -1455,7 +1463,7 @@ bool do_wrap(filestruct *inptr)
wrap_line = inptr->data + i;
for (; i < len; i++, wrap_line++) {
/* Record where the last word ended. */
if (!isblank(*wrap_line))
if (!is_blank_char(*wrap_line))
word_back = i;
/* If we have found a legal wrap point and the current word
* extends too far, then we stop. */
......@@ -1463,7 +1471,7 @@ bool do_wrap(filestruct *inptr)
strnlenpt(inptr->data, word_back + 1) > fill)
break;
/* We record the latest legal wrap point. */
if (word_back != i && !isblank(wrap_line[1]))
if (word_back != i && !is_blank_char(wrap_line[1]))
wrap_loc = i;
}
if (i == len)
......@@ -1536,7 +1544,7 @@ bool do_wrap(filestruct *inptr)
* between after_break and wrap_line. If the line already ends
* in a tab or a space, we don't add a space and decrement
* totsize to account for that. */
if (!isblank(newline[new_line_len - 1]))
if (!is_blank_char(newline[new_line_len - 1]))
strcat(newline, " ");
else
totsize--;
......@@ -2172,7 +2180,7 @@ size_t indent_length(const char *line)
size_t len = 0;
assert(line != NULL);
while (isblank(*line)) {
while (is_blank_char(*line)) {
line++;
len++;
}
......@@ -2200,7 +2208,7 @@ void justify_format(filestruct *line, size_t skip)
assert(line != NULL);
assert(line->data != NULL);
assert(skip < strlen(line->data));
assert(!isblank(line->data[skip]));
assert(!is_blank_char(line->data[skip]));
back = line->data + skip;
for (front = back; ; front++) {
......@@ -2497,10 +2505,10 @@ bool breakable(const char *line, ssize_t goal)
while (*line != '\0' && goal >= 0) {
size_t pos = 0;
if (isblank(*line))
if (is_blank_char(*line))
return TRUE;
line += parse_char(line, NULL
line += parse_mbchar(line, NULL
#ifdef NANO_WIDE
, NULL
#endif
......@@ -2538,7 +2546,7 @@ ssize_t break_line(const char *line, ssize_t goal, bool force)
assert(*line != '\t');
line_len = parse_char(line, NULL
line_len = parse_mbchar(line, NULL
#ifdef NANO_WIDE
, NULL
#endif
......@@ -3468,7 +3476,16 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
if (kbinput != NULL) {
/* Display all the characters in the input buffer at
* once. */
do_output(kbinput, kbinput_len);
char *output = charalloc(kbinput_len + 1);
size_t i;
for (i = 0; i < kbinput_len; i++)
output[i] = (char)kbinput[i];
output[i] = '\0';
do_output(output, kbinput_len);
free(output);
/* Empty the input buffer. */
kbinput_len = 0;
......@@ -3588,55 +3605,45 @@ bool do_mouse(void)
}
#endif /* !DISABLE_MOUSE */
/* The user typed kbinput_len wide characters. Add them to the edit
* buffer as multibyte characters. */
void do_output(int *kbinput, size_t kbinput_len)
/* The user typed kbinput_len multibyte characters. Add them to the
* edit buffer. */
void do_output(char *output, size_t output_len)
{
size_t i, current_len = strlen(current->data);
size_t current_len = strlen(current->data), i = 0;
bool old_constupdate = ISSET(CONSTUPDATE);
bool do_refresh = FALSE;
/* Do we have to call edit_refresh(), or can we get away with
* update_line()? */
char *key =
#ifdef NANO_WIDE
!ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
#endif
charalloc(1);
char *char_buf = charalloc(mb_cur_max());
int char_buf_len;
assert(current != NULL && current->data != NULL);
/* Turn off constant cursor position display. */
UNSET(CONSTUPDATE);
for (i = 0; i < kbinput_len; i++) {
int key_len;
while (i < output_len) {
/* Null to newline, if needed. */
if (kbinput[i] == '\0')
kbinput[i] = '\n';
if (output[i] == '\0')
output[i] = '\n';
/* Newline to Enter, if needed. */
else if (kbinput[i] == '\n') {
else if (output[i] == '\n') {
do_enter();
i++;
continue;
}
/* Interpret the next multibyte character. If it's an invalid
* multibyte character, interpret it as though it's a byte
* character. */
char_buf_len = parse_mbchar(output + i, char_buf
#ifdef NANO_WIDE
/* Change the wide character to its multibyte value. If it's
* invalid, go on to the next character. */
if (!ISSET(NO_UTF8)) {
key_len = wctomb(key, (wchar_t)kbinput[i]);
if (key_len == -1)
continue;
/* Interpret the character as a single-byte sequence. */
} else {
#endif
key_len = 1;
key[0] = (unsigned char)kbinput[i];
#ifdef NANO_WIDE
}
, NULL
#endif
, NULL);
i += char_buf_len;
/* When a character is inserted on the current magicline, it
* means we need a new one! */
......@@ -3644,30 +3651,30 @@ void do_output(int *kbinput, size_t kbinput_len)
new_magicline();
/* More dangerousness fun =) */
current->data = charealloc(current->data,
current_len + (key_len * 2));
current->data = charealloc(current->data, current_len +
(char_buf_len * 2));
assert(current_x <= current_len);
charmove(&current->data[current_x + key_len],
charmove(&current->data[current_x + char_buf_len],
&current->data[current_x],
current_len - current_x + key_len);
charcpy(&current->data[current_x], key, key_len);
current_len += key_len;
totsize += key_len;
current_len - current_x + char_buf_len);
charcpy(&current->data[current_x], char_buf, char_buf_len);
current_len += char_buf_len;
totsize += char_buf_len;
set_modified();
#ifndef NANO_SMALL
/* Note that current_x has not yet been incremented. */
if (current == mark_beginbuf && current_x < mark_beginx)
mark_beginx += key_len;
mark_beginx += char_buf_len;
#endif
do_right(FALSE);
#ifndef DISABLE_WRAPPING
/* If we're wrapping text, we need to call edit_refresh(). */
if (!ISSET(NO_WRAP) && kbinput[i] != '\t') {
if (!ISSET(NO_WRAP) && output[i] != '\t') {
bool do_refresh_save = do_refresh;
do_refresh = do_wrap(current);
......@@ -3692,7 +3699,7 @@ void do_output(int *kbinput, size_t kbinput_len)
if (old_constupdate)
SET(CONSTUPDATE);
free(key);
free(char_buf);
if (do_refresh)
edit_refresh();
......
......@@ -100,12 +100,8 @@
# endif
#endif
/* If no isblank(), strcasecmp(), strncasecmp(), strcasestr(),
* strnlen(), getdelim(), or getline(), use the versions we have. */
#ifndef HAVE_ISBLANK
#define isblank is_blank_char
#endif
/* If no strcasecmp(), strncasecmp(), strcasestr(), strnlen(),
* getdelim(), or getline(), use the versions we have. */
#ifndef HAVE_STRCASECMP
#define strcasecmp nstricmp
#endif
......@@ -161,11 +157,6 @@ typedef enum {
} topmidnone;
/* Structure types. */
typedef struct buffer {
int key;
bool key_code;
} buffer;
typedef struct filestruct {
char *data;
struct filestruct *next; /* Next node. */
......
......@@ -150,6 +150,31 @@ extern char *homedir;
/* Functions we want available. */
/* Public functions in chars.c. */
bool is_blank_char(unsigned char c);
bool is_blank_mbchar(const char *c);
#ifdef NANO_WIDE
bool is_blank_wchar(wchar_t wc);
#endif
bool is_cntrl_char(unsigned char c);
bool is_cntrl_mbchar(const char *c);
#ifdef NANO_WIDE
bool is_cntrl_wchar(wchar_t wc);
#endif
unsigned char control_rep(unsigned char c);
char *control_mbrep(const char *c, char *crep, int *crep_len);
#ifdef NANO_WIDE
wchar_t control_wrep(wchar_t c);
#endif
int mbwidth(const char *c);
int mb_cur_max(void);
char *make_mbchar(unsigned int chr, char *chr_mb, int *chr_mb_len);
int parse_mbchar(const char *buf, char *chr
#ifdef NANO_WIDE
, bool *bad_chr
#endif
, size_t *col);
/* Public functions in color.c. */
#ifdef ENABLE_COLOR
void set_colorpairs(void);
......@@ -396,7 +421,7 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
#ifndef DISABLE_MOUSE
bool do_mouse(void);
#endif
void do_output(int *kbinput, size_t kbinput_len);
void do_output(char *output, size_t output_len);
/* Public functions in rcfile.c. */
#ifdef ENABLE_NANORC
......@@ -470,19 +495,9 @@ int regexec_safe(const regex_t *preg, const char *string, size_t nmatch,
#endif
int regexp_bol_or_eol(const regex_t *preg, const char *string);
#endif
#ifndef HAVE_ISBLANK
int is_blank_char(int c);
#endif
int is_cntrl_char(int c);
bool is_byte_char(int c);
int num_of_digits(int n);
unsigned char control_rep(unsigned char c);
bool is_byte(int c);
bool parse_num(const char *str, ssize_t *val);
int parse_char(const char *buf, int *chr
#ifdef NANO_WIDE
, bool *bad_chr
#endif
, size_t *col);
size_t move_left(const char *buf, size_t pos);
size_t move_right(const char *buf, size_t pos);
void align(char **strp);
......@@ -541,18 +556,16 @@ void reset_kbinput(void);
#endif
void get_buffer(WINDOW *win);
size_t get_buffer_len(void);
int *buffer_to_keys(buffer *input, size_t input_len);
buffer *keys_to_buffer(int *input, size_t input_len);
void unget_input(buffer *input, size_t input_len);
void unget_input(int *input, size_t input_len);
void unget_kbinput(int kbinput, bool meta_key, bool func_key);
buffer *get_input(WINDOW *win, size_t input_len);
int *get_input(WINDOW *win, size_t input_len);
int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key);
int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
#ifndef NANO_SMALL
, bool reset
#endif
);
int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
*ignore_seq);
int get_escape_seq_abcd(int kbinput);
int get_byte_kbinput(int kbinput
......@@ -566,7 +579,7 @@ int get_word_kbinput(int kbinput
#endif
);
int get_control_kbinput(int kbinput);
void unparse_kbinput(size_t pos, int *kbinput, size_t kbinput_len);
void unparse_kbinput(char *output, size_t output_len);
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
#ifndef DISABLE_MOUSE
......@@ -590,7 +603,7 @@ void do_statusbar_backspace(void);
void do_statusbar_delete(void);
void do_statusbar_cut_text(void);
void do_statusbar_verbatim_input(bool *got_enter);
void do_statusbar_output(int *kbinput, size_t kbinput_len, bool
void do_statusbar_output(char *output, size_t output_len, bool
*got_enter);
size_t xplustabs(void);
size_t actual_x(const char *str, size_t xplus);
......
......@@ -126,7 +126,7 @@ void rcfile_error(const char *msg, ...)
/* Parse the next word from the string. Returns NULL if we hit EOL. */
char *parse_next_word(char *ptr)
{
while (!isblank(*ptr) && *ptr != '\n' && *ptr != '\0')
while (!is_blank_char(*ptr) && *ptr != '\n' && *ptr != '\0')
ptr++;
if (*ptr == '\0')
......@@ -135,7 +135,7 @@ char *parse_next_word(char *ptr)
/* Null terminate and advance ptr */
*ptr++ = 0;
while (isblank(*ptr))
while (is_blank_char(*ptr))
ptr++;
return ptr;
......@@ -175,7 +175,7 @@ char *parse_argument(char *ptr)
ptr = last_quote + 1;
}
if (ptr != NULL)
while (isblank(*ptr))
while (is_blank_char(*ptr))
ptr++;
return ptr;
}
......@@ -233,7 +233,7 @@ char *parse_next_regex(char *ptr)
/* Null terminate and advance ptr. */
*ptr++ = '\0';
while (isblank(*ptr))
while (is_blank_char(*ptr))
ptr++;
return ptr;
......@@ -477,7 +477,7 @@ void parse_rcfile(FILE *rcstream)
while (fgets(buf, 1023, rcstream) != 0) {
lineno++;
ptr = buf;
while (isblank(*ptr))
while (is_blank_char(*ptr))
ptr++;
if (*ptr == '\n' || *ptr == '\0')
......
......@@ -33,10 +33,6 @@
#include "proto.h"
#include "nano.h"
#if defined(HAVE_WCHAR_H) && defined(NANO_WIDE)
#include <wchar.h>
#endif
#ifdef HAVE_REGEX_H
#ifdef BROKEN_REGEXEC
int regexec_safe(const regex_t *preg, const char *string, size_t nmatch,
......@@ -56,29 +52,6 @@ int regexp_bol_or_eol(const regex_t *preg, const char *string)
}
#endif /* HAVE_REGEX_H */
#ifndef HAVE_ISBLANK
/* This function is equivalent to isblank(). */
int is_blank_char(int c)
{
return isspace(c) && (!is_cntrl_char(c) || c == '\t');
}
#endif
/* This function is equivalent to iscntrl(), except in that it also
* handles control characters with their high bits set. */
int is_cntrl_char(int c)
{
return (-128 <= c && c < -96) || (0 <= c && c < 32) ||
(127 <= c && c < 160);
}
/* Return TRUE if the character c is in byte range, and FALSE
* otherwise. */
bool is_byte_char(int c)
{
return (unsigned int)c == (unsigned char)c;
}
int num_of_digits(int n)
{
int i = 1;
......@@ -94,17 +67,9 @@ int num_of_digits(int n)
return i;
}
/* c is a control character. It displays as ^@, ^?, or ^[ch] where ch
* is c + 64. We return that character. */
unsigned char control_rep(unsigned char c)
bool is_byte(int c)
{
/* Treat newlines embedded in a line as encoded nulls. */
if (c == '\n')
return '@';
else if (c == NANO_CONTROL_8)
return '?';
else
return c + 64;
return ((unsigned int)c == (unsigned char)c);
}
/* Read a ssize_t from str, and store it in *val (if val is not NULL).
......@@ -128,116 +93,6 @@ bool parse_num(const char *str, ssize_t *val)
return TRUE;
}
/* Parse a multibyte character from buf. Return the number of bytes
* used. If chr isn't NULL, store the wide character in it. If
* bad_chr isn't NULL, set it to TRUE if we have a null byte or a bad
* multibyte character. If col isn't NULL, store the new display width
* in it. If *str is '\t', we expect col to have the current display
* width. */
int parse_char(const char *buf, int *chr
#ifdef NANO_WIDE
, bool *bad_chr
#endif
, size_t *col)
{
int wide_buf, mb_buf_len;
assert(buf != NULL);
#ifdef NANO_WIDE
if (bad_chr != NULL)
*bad_chr = FALSE;
if (!ISSET(NO_UTF8)) {
wchar_t tmp;
/* Get the wide character equivalent of the multibyte
* character. */
mb_buf_len = mbtowc(&tmp, buf, MB_CUR_MAX);
wide_buf = (int)tmp;
/* If buf contains a null byte or an invalid multibyte
* character, interpret buf's first byte as a single-byte
* sequence and set bad_chr to TRUE. */
if (mb_buf_len <= 0) {
mb_buf_len = 1;
wide_buf = (unsigned char)*buf;
if (bad_chr != NULL)
*bad_chr = TRUE;
}
/* Save the wide character in chr. */
if (chr != NULL)
*chr = wide_buf;
/* Save the column width of the wide character in col. */
if (col != NULL) {
/* If we have a tab, get its width in columns using the
* current value of col. */
if (wide_buf == '\t')
*col += tabsize - *col % tabsize;
/* If we have a control character, get its width using one
* column for the "^" that will be displayed in front of it,
* and the width in columns of its visible equivalent as
* returned by control_rep(). */
else if (is_cntrl_char(wide_buf)) {
char *ctrl_mb_buf = charalloc(MB_CUR_MAX);
(*col)++;
wide_buf = control_rep((unsigned char)wide_buf);
if (wctomb(ctrl_mb_buf, (wchar_t)wide_buf) != -1) {
int width = wcwidth((wchar_t)wide_buf);
if (width != -1)
*col += width;
}
else
(*col)++;
free(ctrl_mb_buf);
/* If we have a normal character, get its width in columns
* normally. */
} else {
int width = wcwidth((wchar_t)wide_buf);
if (width != -1)
*col += width;
}
}
} else {
#endif
/* Interpret buf's first character as a single-byte sequence. */
mb_buf_len = 1;
wide_buf = (unsigned char)*buf;
/* Save the single-byte sequence in chr as though it's a wide
* character. */
if (chr != NULL)
*chr = wide_buf;
if (col != NULL) {
/* If we have a tab, get its width in columns using the
* current value of col. */
if (wide_buf == '\t')
*col += tabsize - *col % tabsize;
/* If we have a control character, it's two columns wide:
* one column for the "^" that will be displayed in front of
* it, and one column for its visible equivalent as returned
* by control_rep(). */
else if (is_cntrl_char(wide_buf))
*col += 2;
/* If we have a normal character, it's one column wide. */
else
(*col)++;
}
#ifdef NANO_WIDE
}
#endif
return mb_buf_len;
}
/* Return the index in buf of the beginning of the character before the
* one at pos. */
size_t move_left(const char *buf, size_t pos)
......@@ -249,16 +104,16 @@ size_t move_left(const char *buf, size_t pos)
/* There is no library function to move backward one multibyte
* character. Here is the naive, O(pos) way to do it. */
while (TRUE) {
int mb_buf_len = parse_char(buf + pos - pos_prev, NULL
int buf_mb_len = parse_mbchar(buf + pos - pos_prev, NULL
#ifdef NANO_WIDE
, NULL
#endif
, NULL);
if (pos_prev <= mb_buf_len)
if (pos_prev <= buf_mb_len)
break;
pos_prev -= mb_buf_len;
pos_prev -= buf_mb_len;
}
return pos - pos_prev;
......@@ -268,7 +123,7 @@ size_t move_left(const char *buf, size_t pos)
* one at pos. */
size_t move_right(const char *buf, size_t pos)
{
return pos + parse_char(buf + pos, NULL
return pos + parse_mbchar(buf + pos, NULL
#ifdef NANO_WIDE
, NULL
#endif
......
......@@ -32,11 +32,7 @@
#include "proto.h"
#include "nano.h"
#if defined(HAVE_WCHAR_H) && defined(NANO_WIDE)
#include <wchar.h>
#endif
static buffer *key_buffer = NULL;
static int *key_buffer = NULL;
/* The default keystroke buffer,
* containing all the keystrokes we have
* at a given point. */
......@@ -131,32 +127,18 @@ void reset_kbinput(void)
* default keystroke buffer is empty. */
void get_buffer(WINDOW *win)
{
int input, input_key_code;
int input;
/* If the keystroke buffer isn't empty, get out. */
if (key_buffer != NULL)
return;
/* Read in the first character using blocking input. */
nodelay(win, FALSE);
#ifndef NANO_SMALL
allow_pending_sigwinch(TRUE);
#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
input = wgetch(win);
#ifndef NANO_SMALL
allow_pending_sigwinch(FALSE);
......@@ -166,13 +148,8 @@ void get_buffer(WINDOW *win)
* the keystroke in key, and set key_code to TRUE if the keystroke
* 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 =
#ifdef NANO_WIDE
!ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
#endif
input_key_code;
key_buffer = (int *)nmalloc(sizeof(int));
key_buffer[0] = input;
/* Read in the remaining characters using non-blocking input. */
nodelay(win, TRUE);
......@@ -182,25 +159,10 @@ void get_buffer(WINDOW *win)
allow_pending_sigwinch(TRUE);
#endif
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
wint_t tmp;
input = wgetch(win);
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 (
#ifdef NANO_WIDE
(!ISSET(NO_UTF8) && input_key_code == ERR) ||
#endif
input == ERR)
if (input == ERR)
break;
/* Otherwise, increment the length of the keystroke buffer, save
......@@ -208,14 +170,9 @@ void get_buffer(WINDOW *win)
* 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 =
#ifdef NANO_WIDE
!ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
#endif
input_key_code;
key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
sizeof(int));
key_buffer[key_buffer_len - 1] = input;
#ifndef NANO_SMALL
allow_pending_sigwinch(FALSE);
......@@ -232,121 +189,57 @@ size_t get_buffer_len(void)
return key_buffer_len;
}
/* Return the key values stored in the keystroke buffer input,
* discarding the key_code values in it. */
int *buffer_to_keys(buffer *input, size_t input_len)
{
int *sequence = (int *)nmalloc(input_len * sizeof(int));
size_t i;
for (i = 0; i < input_len; i++)
sequence[i] = input[i].key;
return sequence;
}
/* Return the buffer equivalent of the key values in input, adding
* key_code values of FALSE to all of them. */
buffer *keys_to_buffer(int *input, size_t input_len)
{
buffer *sequence = (buffer *)nmalloc(input_len * sizeof(buffer));
size_t i;
for (i = 0; i < input_len; i++) {
sequence[i].key = input[i];
sequence[i].key_code = FALSE;
}
return sequence;
}
/* Add the contents of the keystroke buffer input to the default
* keystroke buffer. */
void unget_input(buffer *input, size_t input_len)
void unget_input(int *input, size_t input_len)
{
buffer *clean_input = NULL;
size_t clean_input_len = 0;
#ifndef NANO_SMALL
allow_pending_sigwinch(TRUE);
allow_pending_sigwinch(FALSE);
#endif
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
size_t i;
char *key = charalloc(MB_CUR_MAX);
/* Keep all valid wide keystrokes, discarding the others. */
for (i = 0; i < input_len; i++) {
int key_len = input[i].key_code ? 1 :
wctomb(key, (wchar_t)input[i].key);
if (key_len != -1) {
clean_input_len++;
clean_input = (buffer *)nrealloc(clean_input,
clean_input_len * sizeof(buffer));
clean_input[clean_input_len - 1].key = input[i].key;
clean_input[clean_input_len - 1].key_code =
input[i].key_code;
}
}
free(key);
} else {
#endif
clean_input = input;
clean_input_len = input_len;
#ifdef NANO_WIDE
}
#endif
/* If input is empty, get out. */
if (clean_input_len == 0)
if (input_len == 0)
return;
/* If adding input would put the default keystroke buffer beyond
* maximum capacity, only add enough of input to put it at maximum
* capacity. */
if (key_buffer_len + clean_input_len < key_buffer_len)
clean_input_len = (size_t)-1 - key_buffer_len;
if (key_buffer_len + input_len < key_buffer_len)
input_len = (size_t)-1 - key_buffer_len;
/* Add the length of input to the length of the default keystroke
* buffer, and reallocate the default keystroke buffer so that it
* has enough room for input. */
key_buffer_len += clean_input_len;
key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
sizeof(buffer));
key_buffer_len += input_len;
key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
sizeof(int));
/* If the default keystroke buffer wasn't empty before, move its
* beginning forward far enough so that we can add input to its
* beginning. */
if (key_buffer_len > clean_input_len)
memmove(key_buffer + clean_input_len, key_buffer,
(key_buffer_len - clean_input_len) * sizeof(buffer));
if (key_buffer_len > input_len)
memmove(key_buffer + input_len, key_buffer,
(key_buffer_len - input_len) * sizeof(int));
/* Copy input to the beginning of the default keystroke buffer. */
memcpy(key_buffer, clean_input, clean_input_len * sizeof(buffer));
memcpy(key_buffer, input, input_len * sizeof(int));
}
/* Put back the character stored in kbinput. If func_key is TRUE and
* the character is out of byte range, interpret it as an extended
* keypad value. If meta_key is TRUE, put back the Escape character
* after putting back kbinput. */
/* Put back the character stored in kbinput, putting it in byte range
* beforehand. If meta_key is TRUE, put back the Escape character after
* putting back kbinput. If func_key is TRUE, put back the function key
* (a value outside byte range) without putting it in byte range. */
void unget_kbinput(int kbinput, bool meta_key, bool func_key)
{
buffer input;
input.key = kbinput;
input.key_code = (func_key && !is_byte_char(kbinput));
if (!func_key)
kbinput = (char)kbinput;
unget_input(&input, 1);
unget_input(&kbinput, 1);
if (meta_key) {
input.key = NANO_CONTROL_3;
input.key_code = FALSE;
unget_input(&input, 1);
kbinput = NANO_CONTROL_3;
unget_input(&kbinput, 1);
}
}
......@@ -355,9 +248,9 @@ void unget_kbinput(int kbinput, bool meta_key, bool func_key)
* read in more characters from win and add them to the default
* keystroke buffer before doing anything else. If the default
* keystroke buffer is empty and win is NULL, return NULL. */
buffer *get_input(WINDOW *win, size_t input_len)
int *get_input(WINDOW *win, size_t input_len)
{
buffer *input;
int *input;
#ifndef NANO_SMALL
allow_pending_sigwinch(TRUE);
......@@ -382,11 +275,11 @@ buffer *get_input(WINDOW *win, size_t input_len)
* buffer, and allocate the keystroke buffer input so that it
* has enough room for input_len keystrokes. */
key_buffer_len -= input_len;
input = (buffer *)nmalloc(input_len * sizeof(buffer));
input = (int *)nmalloc(input_len * sizeof(int));
/* Copy input_len characters from the beginning of the default
* keystroke buffer into input. */
memcpy(input, key_buffer, input_len * sizeof(buffer));
memcpy(input, key_buffer, input_len * sizeof(int));
/* If the default keystroke buffer is empty, mark it as such. */
if (key_buffer_len == 0) {
......@@ -397,9 +290,9 @@ buffer *get_input(WINDOW *win, size_t input_len)
* are no longer at its beginning. */
} else {
memmove(key_buffer, key_buffer + input_len, key_buffer_len *
sizeof(buffer));
key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
sizeof(buffer));
sizeof(int));
key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
sizeof(int));
}
return input;
......@@ -441,8 +334,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
{
static int escapes = 0, byte_digits = 0;
buffer *kbinput;
int retval = ERR;
int *kbinput, retval = ERR;
#ifndef NANO_SMALL
if (reset) {
......@@ -458,264 +350,258 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
/* Read in a character. */
while ((kbinput = get_input(win, 1)) == NULL);
if (kbinput->key_code || is_byte_char(kbinput->key)) {
/* If we got an extended keypad value or an ASCII character,
* translate it. */
switch (kbinput->key) {
case ERR:
break;
case NANO_CONTROL_3:
/* Increment the escape counter. */
escapes++;
switch (escapes) {
case 1:
/* One escape: wait for more input. */
case 2:
/* Two escapes: wait for more input. */
break;
default:
/* More than two escapes: reset the escape
* counter and wait for more input. */
escapes = 0;
}
break;
switch (*kbinput) {
case ERR:
break;
case NANO_CONTROL_3:
/* Increment the escape counter. */
escapes++;
switch (escapes) {
case 1:
/* One escape: wait for more input. */
case 2:
/* Two escapes: wait for more input. */
break;
default:
/* More than two escapes: reset the escape counter
* and wait for more input. */
escapes = 0;
}
break;
#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
/* Since we don't change the default SIGWINCH handler when
* NANO_SMALL is defined, KEY_RESIZE is never generated.
* Also, Slang and SunOS 5.7-5.9 don't support
* KEY_RESIZE. */
case KEY_RESIZE:
break;
/* Since we don't change the default SIGWINCH handler when
* NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
* Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
case KEY_RESIZE:
break;
#endif
#ifdef PDCURSES
case KEY_SHIFT_L:
case KEY_SHIFT_R:
case KEY_CONTROL_L:
case KEY_CONTROL_R:
case KEY_ALT_L:
case KEY_ALT_R:
break;
case KEY_SHIFT_L:
case KEY_SHIFT_R:
case KEY_CONTROL_L:
case KEY_CONTROL_R:
case KEY_ALT_L:
case KEY_ALT_R:
break;
#endif
default:
switch (escapes) {
case 0:
switch (kbinput->key) {
case NANO_CONTROL_8:
retval = ISSET(REBIND_DELETE) ?
NANO_DELETE_KEY :
NANO_BACKSPACE_KEY;
break;
case KEY_DOWN:
retval = NANO_NEXTLINE_KEY;
break;
case KEY_UP:
retval = NANO_PREVLINE_KEY;
break;
case KEY_LEFT:
retval = NANO_BACK_KEY;
break;
case KEY_RIGHT:
retval = NANO_FORWARD_KEY;
break;
default:
switch (escapes) {
case 0:
switch (*kbinput) {
case NANO_CONTROL_8:
retval = ISSET(REBIND_DELETE) ?
NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
break;
case KEY_DOWN:
retval = NANO_NEXTLINE_KEY;
break;
case KEY_UP:
retval = NANO_PREVLINE_KEY;
break;
case KEY_LEFT:
retval = NANO_BACK_KEY;
break;
case KEY_RIGHT:
retval = NANO_FORWARD_KEY;
break;
#ifdef KEY_HOME
/* HP-UX 10 and 11 don't support
* KEY_HOME. */
case KEY_HOME:
retval = NANO_HOME_KEY;
break;
/* HP-UX 10 and 11 don't support KEY_HOME. */
case KEY_HOME:
retval = NANO_HOME_KEY;
break;
#endif
case KEY_BACKSPACE:
retval = NANO_BACKSPACE_KEY;
break;
case KEY_DC:
retval = ISSET(REBIND_DELETE) ?
NANO_BACKSPACE_KEY :
NANO_DELETE_KEY;
break;
case KEY_IC:
retval = NANO_INSERTFILE_KEY;
break;
case KEY_NPAGE:
retval = NANO_NEXTPAGE_KEY;
break;
case KEY_PPAGE:
retval = NANO_PREVPAGE_KEY;
break;
case KEY_ENTER:
retval = NANO_ENTER_KEY;
break;
case KEY_A1: /* Home (7) on numeric
* keypad with NumLock
* off. */
retval = NANO_HOME_KEY;
break;
case KEY_A3: /* PageUp (9) on numeric
* keypad with NumLock
* off. */
retval = NANO_PREVPAGE_KEY;
break;
case KEY_B2: /* Center (5) on numeric
* keypad with NumLock
* off. */
break;
case KEY_C1: /* End (1) on numeric
* keypad with NumLock
* off. */
retval = NANO_END_KEY;
break;
case KEY_C3: /* PageDown (4) on
* numeric keypad with
* NumLock off. */
retval = NANO_NEXTPAGE_KEY;
break;
case KEY_BACKSPACE:
retval = NANO_BACKSPACE_KEY;
break;
case KEY_DC:
retval = ISSET(REBIND_DELETE) ?
NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
break;
case KEY_IC:
retval = NANO_INSERTFILE_KEY;
break;
case KEY_NPAGE:
retval = NANO_NEXTPAGE_KEY;
break;
case KEY_PPAGE:
retval = NANO_PREVPAGE_KEY;
break;
case KEY_ENTER:
retval = NANO_ENTER_KEY;
break;
case KEY_A1: /* Home (7) on numeric keypad
* with NumLock off. */
retval = NANO_HOME_KEY;
break;
case KEY_A3: /* PageUp (9) on numeric keypad
* with NumLock off. */
retval = NANO_PREVPAGE_KEY;
break;
case KEY_B2: /* Center (5) on numeric keypad
* with NumLock off. */
break;
case KEY_C1: /* End (1) on numeric keypad
* with NumLock off. */
retval = NANO_END_KEY;
break;
case KEY_C3: /* PageDown (4) on numeric
* keypad with NumLock off. */
retval = NANO_NEXTPAGE_KEY;
break;
#ifdef KEY_BEG
/* Slang doesn't support KEY_BEG. */
case KEY_BEG: /* Center (5) on numeric
* keypad with NumLock
* off. */
break;
/* Slang doesn't support KEY_BEG. */
case KEY_BEG: /* Center (5) on numeric keypad
* with NumLock off. */
break;
#endif
#ifdef KEY_END
/* HP-UX 10 and 11 don't support KEY_END. */
case KEY_END:
retval = NANO_END_KEY;
break;
/* HP-UX 10 and 11 don't support KEY_END. */
case KEY_END:
retval = NANO_END_KEY;
break;
#endif
#ifdef KEY_SUSPEND
/* Slang doesn't support KEY_SUSPEND. */
case KEY_SUSPEND:
retval = NANO_SUSPEND_KEY;
break;
/* Slang doesn't support KEY_SUSPEND. */
case KEY_SUSPEND:
retval = NANO_SUSPEND_KEY;
break;
#endif
#ifdef KEY_SLEFT
/* Slang doesn't support KEY_SLEFT. */
case KEY_SLEFT:
retval = NANO_BACK_KEY;
break;
/* Slang doesn't support KEY_SLEFT. */
case KEY_SLEFT:
retval = NANO_BACK_KEY;
break;
#endif
#ifdef KEY_SRIGHT
/* Slang doesn't support KEY_SRIGHT. */
case KEY_SRIGHT:
retval = NANO_FORWARD_KEY;
break;
/* Slang doesn't support KEY_SRIGHT. */
case KEY_SRIGHT:
retval = NANO_FORWARD_KEY;
break;
#endif
default:
retval = kbinput->key;
break;
}
break;
case 1:
/* One escape followed by a non-escape: escape
* sequence mode. Reset the escape counter. If
* there aren't any other keys waiting, we have
* a meta key sequence, so set meta_key to TRUE
* and save the lowercase version of the
* non-escape character as the result. If there
* are other keys waiting, we have a true escape
* sequence, so interpret it. */
escapes = 0;
if (get_buffer_len() == 0) {
*meta_key = TRUE;
retval = tolower(kbinput->key);
} else {
buffer *escape_kbinput;
int *sequence;
size_t seq_len;
bool ignore_seq;
/* Put back the non-escape character, get
* the complete escape sequence, translate
* the sequence into its corresponding key
* value, and save that as the result. */
unget_input(kbinput, 1);
seq_len = get_buffer_len();
escape_kbinput = get_input(NULL, seq_len);
sequence = buffer_to_keys(escape_kbinput,
seq_len);
retval = get_escape_seq_kbinput(sequence,
seq_len, &ignore_seq);
/* If the escape sequence is unrecognized
* and not ignored, put back all of its
* characters except for the initial
* escape. */
if (retval == ERR && !ignore_seq)
unget_input(escape_kbinput, seq_len);
free(escape_kbinput);
}
break;
case 2:
/* Two escapes followed by one or more decimal
* digits: byte sequence mode. If the word
* sequence's range is limited to 2XX (the first
* digit is in the '0' to '2' range and it's the
* first digit, or it's in the '0' to '9' range
* and it's not the first digit), increment the
* byte sequence counter and interpret the
* digit. If the byte sequence's range is not
* limited to 2XX, fall through. */
if (('0' <= kbinput->key && kbinput->key <= '6'
&& byte_digits == 0) ||
('0' <= kbinput->key && kbinput->key <= '9'
&& byte_digits > 0)) {
int byte_kbinput;
byte_digits++;
byte_kbinput = get_byte_kbinput(kbinput->key
default:
retval = *kbinput;
break;
}
break;
case 1:
/* One escape followed by a non-escape: escape
* sequence mode. Reset the escape counter. If
* there aren't any other keys waiting, we have a
* meta key sequence, so set meta_key to TRUE and
* save the lowercase version of the non-escape
* character as the result. If there are other keys
* waiting, we have a true escape sequence, so
* interpret it. */
escapes = 0;
if (get_buffer_len() == 0) {
*meta_key = TRUE;
retval = tolower(*kbinput);
} else {
int *seq;
size_t seq_len;
bool ignore_seq;
/* Put back the non-escape character, get the
* complete escape sequence, translate the
* sequence into its corresponding key value,
* and save that as the result. */
unget_input(kbinput, 1);
seq_len = get_buffer_len();
seq = get_input(NULL, seq_len);
retval = get_escape_seq_kbinput(seq, seq_len,
&ignore_seq);
/* If the escape sequence is unrecognized and
* not ignored, put back all of its characters
* except for the initial escape. */
if (retval == ERR && !ignore_seq)
unget_input(seq, seq_len);
free(seq);
}
break;
case 2:
/* Two escapes followed by one or more decimal
* digits: byte sequence mode. If the word
* sequence's range is limited to 2XX (the first
* digit is in the '0' to '2' range and it's the
* first digit, or it's in the '0' to '9' range and
* it's not the first digit), increment the byte
* sequence counter and interpret the digit. If the
* byte sequence's range is not limited to 2XX, fall
* through. */
if (('0' <= *kbinput && *kbinput <= '6' &&
byte_digits == 0) || ('0' <= *kbinput &&
*kbinput <= '9' && byte_digits > 0)) {
int byte;
byte_digits++;
byte = get_byte_kbinput(*kbinput
#ifndef NANO_SMALL
, FALSE
#endif
);
if (byte_kbinput != ERR) {
/* If we've read in a complete byte
* sequence, reset the byte sequence
* counter and the escape counter,
* and put back the corresponding byte
* value. */
byte_digits = 0;
escapes = 0;
unget_kbinput(byte_kbinput, FALSE,
FALSE);
}
} else {
/* Reset the escape counter. */
if (byte != ERR) {
char *byte_mb = charalloc(mb_cur_max());
int byte_mb_len, *seq, i;
/* If we've read in a complete byte
* sequence, reset the byte sequence counter
* and the escape counter, and put back the
* corresponding byte value. */
byte_digits = 0;
escapes = 0;
if (byte_digits == 0)
/* Two escapes followed by a non-decimal
* digit or a decimal digit that would
* create a byte sequence greater than
* 2XX, and we're not in the middle of a
* byte sequence: control character
* sequence mode. Interpret the control
* sequence and save the corresponding
* control character as the result. */
retval = get_control_kbinput(kbinput->key);
else {
/* If we're in the middle of a word
* sequence, reset the word sequence
* counter and save the character we got
* as the result. */
byte_digits = 0;
retval = kbinput->key;
}
/* Put back the multibyte equivalent of the
* byte value. */
byte_mb = make_mbchar(byte, byte_mb,
&byte_mb_len);
seq = (int *)nmalloc(byte_mb_len *
sizeof(int));
for (i = 0; i < byte_mb_len; i++)
seq[i] = (unsigned char)byte_mb[i];
unget_input(seq, byte_mb_len);
free(seq);
free(byte_mb);
}
break;
}
}
} else {
/* Reset the escape counter. */
escapes = 0;
if (byte_digits == 0)
/* Two escapes followed by a non-decimal
* digit or a decimal digit that would
* create a byte sequence greater than 2XX,
* and we're not in the middle of a byte
* sequence: control character sequence
* mode. Interpret the control sequence and
* save the corresponding control character
* as the result. */
retval = get_control_kbinput(*kbinput);
else {
/* If we're in the middle of a byte
* sequence, reset the byte sequence counter
* and save the character we got as the
* result. */
byte_digits = 0;
retval = *kbinput;
}
}
break;
}
}
/* If we have a result and it's an extended keypad value, set
* func_key to TRUE. */
if (retval != ERR)
*func_key = !is_byte_char(retval);
} else
/* If we didn't get an extended keypad value or an ASCII
* character, leave it as-is. */
retval = kbinput->key;
/* If we have a result and it's an extended keypad value (i.e, a
* value outside of byte range), set func_key to TRUE. */
if (retval != ERR)
*func_key = !is_byte(retval);
#ifdef DEBUG
fprintf(stderr, "parse_kbinput(): kbinput->key = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", kbinput->key, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
#endif
/* Return the result. */
......@@ -729,7 +615,7 @@ int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
* ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
* set ignore_seq to FALSE. Assume that Escape has already been read
* in. */
int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
*ignore_seq)
{
int retval = ERR;
......@@ -737,12 +623,12 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
*ignore_seq = FALSE;
if (seq_len > 1) {
switch (sequence[0]) {
switch (seq[0]) {
case 'O':
switch (sequence[1]) {
switch (seq[1]) {
case '2':
if (seq_len >= 3) {
switch (sequence[2]) {
switch (seq[2]) {
case 'P': /* Esc O 2 P == F13 on
* xterm. */
retval = KEY_F(13);
......@@ -769,7 +655,7 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
* VT100/VT320/xterm. */
case 'D': /* Esc O D == Left on
* VT100/VT320/xterm. */
retval = get_escape_seq_abcd(sequence[1]);
retval = get_escape_seq_abcd(seq[1]);
break;
case 'E': /* Esc O E == Center (5) on numeric keypad
* with NumLock off on xterm. */
......@@ -824,7 +710,7 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
case 'b': /* Esc O b == Ctrl-Down on rxvt. */
case 'c': /* Esc O c == Ctrl-Right on rxvt. */
case 'd': /* Esc O d == Ctrl-Left on rxvt. */
retval = get_escape_seq_abcd(sequence[1]);
retval = get_escape_seq_abcd(seq[1]);
break;
case 'j': /* Esc O j == '*' on numeric keypad with
* NumLock off on VT100/VT220/VT320/xterm/
......@@ -909,20 +795,20 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
}
break;
case 'o':
switch (sequence[1]) {
switch (seq[1]) {
case 'a': /* Esc o a == Ctrl-Up on Eterm. */
case 'b': /* Esc o b == Ctrl-Down on Eterm. */
case 'c': /* Esc o c == Ctrl-Right on Eterm. */
case 'd': /* Esc o d == Ctrl-Left on Eterm. */
retval = get_escape_seq_abcd(sequence[1]);
retval = get_escape_seq_abcd(seq[1]);
break;
}
break;
case '[':
switch (sequence[1]) {
switch (seq[1]) {
case '1':
if (seq_len >= 3) {
switch (sequence[2]) {
switch (seq[2]) {
case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
* Eterm. */
retval = KEY_F(1);
......@@ -960,10 +846,10 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
break;
case ';':
if (seq_len >= 4) {
switch (sequence[3]) {
switch (seq[3]) {
case '2':
if (seq_len >= 5) {
switch (sequence[4]) {
switch (seq[4]) {
case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
* xterm. */
case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
......@@ -972,14 +858,14 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
* xterm. */
case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
* xterm. */
retval = get_escape_seq_abcd(sequence[4]);
retval = get_escape_seq_abcd(seq[4]);
break;
}
}
break;
case '5':
if (seq_len >= 5) {
switch (sequence[4]) {
switch (seq[4]) {
case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
* xterm. */
case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
......@@ -988,7 +874,7 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
* xterm. */
case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
* xterm. */
retval = get_escape_seq_abcd(sequence[4]);
retval = get_escape_seq_abcd(seq[4]);
break;
}
}
......@@ -1005,7 +891,7 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
break;
case '2':
if (seq_len >= 3) {
switch (sequence[2]) {
switch (seq[2]) {
case '0': /* Esc [ 2 0 ~ == F9 on
* VT220/VT320/Linux console/
* xterm/rxvt/Eterm. */
......@@ -1096,7 +982,7 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
* console/FreeBSD console/Mach console/
* rxvt/Eterm. */
retval = get_escape_seq_abcd(sequence[1]);
retval = get_escape_seq_abcd(seq[1]);
break;
case 'E': /* Esc [ E == Center (5) on numeric keypad
* with NumLock off on FreeBSD console. */
......@@ -1130,7 +1016,7 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
break;
case 'O':
if (seq_len >= 3) {
switch (sequence[2]) {
switch (seq[2]) {
case 'P': /* Esc [ O P == F1 on
* xterm. */
retval = KEY_F(1);
......@@ -1191,11 +1077,11 @@ int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
case 'c': /* Esc [ c == Shift-Right on rxvt/
* Eterm. */
case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
retval = get_escape_seq_abcd(sequence[1]);
retval = get_escape_seq_abcd(seq[1]);
break;
case '[':
if (seq_len >= 3) {
switch (sequence[2]) {
switch (seq[2]) {
case 'A': /* Esc [ [ A == F1 on Linux
* console. */
retval = KEY_F(1);
......@@ -1258,13 +1144,13 @@ int get_byte_kbinput(int kbinput
#endif
)
{
static int byte_digits = 0, byte_kbinput = 0;
static int byte_digits = 0, byte = 0;
int retval = ERR;
#ifndef NANO_SMALL
if (reset) {
byte_digits = 0;
byte_kbinput = 0;
byte = 0;
return ERR;
}
#endif
......@@ -1277,9 +1163,9 @@ int get_byte_kbinput(int kbinput
/* One digit: reset the byte sequence holder and add the
* digit we got to the 100's position of the byte sequence
* holder. */
byte_kbinput = 0;
byte = 0;
if ('0' <= kbinput && kbinput <= '2')
byte_kbinput += (kbinput - '0') * 100;
byte += (kbinput - '0') * 100;
else
/* If the character we got isn't a decimal digit, or if
* it is and it would put the byte sequence out of byte
......@@ -1289,10 +1175,9 @@ int get_byte_kbinput(int kbinput
case 2:
/* Two digits: add the digit we got to the 10's position of
* the byte sequence holder. */
if (('0' <= kbinput && kbinput <= '5') ||
(byte_kbinput < 200 && '6' <= kbinput &&
kbinput <= '9'))
byte_kbinput += (kbinput - '0') * 10;
if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
'6' <= kbinput && kbinput <= '9'))
byte += (kbinput - '0') * 10;
else
/* If the character we got isn't a decimal digit, or if
* it is and it would put the byte sequence out of byte
......@@ -1303,11 +1188,10 @@ int get_byte_kbinput(int kbinput
/* Three digits: add the digit we got to the 1's position of
* the byte sequence holder, and save the corresponding word
* value as the result. */
if (('0' <= kbinput && kbinput <= '5') ||
(byte_kbinput < 250 && '6' <= kbinput &&
kbinput <= '9')) {
byte_kbinput += (kbinput - '0');
retval = byte_kbinput;
if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
'6' <= kbinput && kbinput <= '9')) {
byte += (kbinput - '0');
retval = byte;
} else
/* If the character we got isn't a decimal digit, or if
* it is and it would put the word sequence out of word
......@@ -1325,11 +1209,11 @@ int get_byte_kbinput(int kbinput
* sequence holder. */
if (retval != ERR) {
byte_digits = 0;
byte_kbinput = 0;
byte = 0;
}
#ifdef DEBUG
fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte_kbinput = %d, retval = %d\n", kbinput, byte_digits, byte_kbinput, retval);
fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval);
#endif
return retval;
......@@ -1343,13 +1227,13 @@ int get_word_kbinput(int kbinput
#endif
)
{
static int word_digits = 0, word_kbinput = 0;
static int word_digits = 0, word = 0;
int retval = ERR;
#ifndef NANO_SMALL
if (reset) {
word_digits = 0;
word_kbinput = 0;
word = 0;
return ERR;
}
#endif
......@@ -1362,11 +1246,11 @@ int get_word_kbinput(int kbinput
/* One digit: reset the word sequence holder and add the
* digit we got to the 4096's position of the word sequence
* holder. */
word_kbinput = 0;
word = 0;
if ('0' <= kbinput && kbinput <= '9')
word_kbinput += (kbinput - '0') * 4096;
word += (kbinput - '0') * 4096;
else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
word_kbinput += (tolower(kbinput) + 10 - 'a') * 4096;
word += (tolower(kbinput) + 10 - 'a') * 4096;
else
/* If the character we got isn't a hexadecimal digit, or
* if it is and it would put the word sequence out of
......@@ -1377,9 +1261,9 @@ int get_word_kbinput(int kbinput
/* Two digits: add the digit we got to the 256's position of
* the word sequence holder. */
if ('0' <= kbinput && kbinput <= '9')
word_kbinput += (kbinput - '0') * 256;
word += (kbinput - '0') * 256;
else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
word_kbinput += (tolower(kbinput) + 10 - 'a') * 256;
word += (tolower(kbinput) + 10 - 'a') * 256;
else
/* If the character we got isn't a hexadecimal digit, or
* if it is and it would put the word sequence out of
......@@ -1390,9 +1274,9 @@ int get_word_kbinput(int kbinput
/* Three digits: add the digit we got to the 16's position
* of the word sequence holder. */
if ('0' <= kbinput && kbinput <= '9')
word_kbinput += (kbinput - '0') * 16;
word += (kbinput - '0') * 16;
else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
word_kbinput += (tolower(kbinput) + 10 - 'a') * 16;
word += (tolower(kbinput) + 10 - 'a') * 16;
else
/* If the character we got isn't a hexadecimal digit, or
* if it is and it would put the word sequence out of
......@@ -1404,12 +1288,12 @@ int get_word_kbinput(int kbinput
* the word sequence holder, and save the corresponding word
* value as the result. */
if ('0' <= kbinput && kbinput <= '9') {
word_kbinput += (kbinput - '0');
retval = word_kbinput;
word += (kbinput - '0');
retval = word;
} else if ('a' <= tolower(kbinput) &&
tolower(kbinput) <= 'f') {
word_kbinput += (tolower(kbinput) + 10 - 'a');
retval = word_kbinput;
word += (tolower(kbinput) + 10 - 'a');
retval = word;
} else
/* If the character we got isn't a hexadecimal digit, or
* if it is and it would put the word sequence out of
......@@ -1427,11 +1311,11 @@ int get_word_kbinput(int kbinput
* sequence holder. */
if (retval != ERR) {
word_digits = 0;
word_kbinput = 0;
word = 0;
}
#ifdef DEBUG
fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word_kbinput = %d, retval = %d\n", kbinput, word_digits, word_kbinput, retval);
fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word = %d, retval = %d\n", kbinput, word_digits, word, retval);
#endif
return retval;
......@@ -1469,22 +1353,25 @@ int get_control_kbinput(int kbinput)
return retval;
}
/* Put the output-formatted key values in the input buffer kbinput back
* into the default keystroke buffer, starting at position pos, so that
* they can be parsed again. */
void unparse_kbinput(size_t pos, int *kbinput, size_t kbinput_len)
/* Put the output-formatted characters in output back into the default
* keystroke buffer, so that they can be parsed and displayed as output
* again. */
void unparse_kbinput(char *output, size_t output_len)
{
if (pos < kbinput_len - 1) {
size_t seq_len = kbinput_len - (kbinput_len - pos);
buffer *sequence = keys_to_buffer(&kbinput[pos + 1],
seq_len);
int *input;
size_t i;
unget_input(sequence, seq_len);
free(sequence);
}
if (output_len == 0)
return;
input = (int *)nmalloc(output_len * sizeof(int));
for (i = 0; i < output_len; i++)
input[i] = (int)output[i];
unget_input(input, output_len);
free(input);
}
/* Read in a string of characters verbatim, and return the length of the
/* Read in a stream of characters verbatim, and return the length of the
* string in kbinput_len. Assume nodelay(win) is FALSE. */
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
{
......@@ -1509,19 +1396,19 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
return retval;
}
/* Read in a stream of all available characters. Translate the first
* few characters of the input into the corresponding word value if
* possible. After that, leave the input as-is. */
/* Read in a stream of all available characters, and return the length
* of the string in kbinput_len. Translate the first few characters of
* the input into the corresponding word value if possible. After that,
* leave the input as-is. */
int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
{
buffer *kbinput, *sequence;
int word, *retval;
int *kbinput, word, *retval;
/* Read in the first keystroke. */
while ((kbinput = get_input(win, 1)) == NULL);
/* Check whether the first keystroke is a hexadecimal digit. */
word = get_word_kbinput(kbinput->key
word = get_word_kbinput(*kbinput
#ifndef NANO_SMALL
, FALSE
#endif
......@@ -1534,30 +1421,37 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
/* Otherwise, read in keystrokes until we have a complete word
* sequence, and put back the corresponding word value. */
else {
buffer word_kbinput;
char *word_mb = charalloc(mb_cur_max());
int word_mb_len, *seq, i;
while (word == ERR) {
while ((kbinput = get_input(win, 1)) == NULL);
word = get_word_kbinput(kbinput->key
word = get_word_kbinput(*kbinput
#ifndef NANO_SMALL
, FALSE
#endif
);
}
word_kbinput.key = word;
word_kbinput.key_code = FALSE;
/* Put back the multibyte equivalent of the word value. */
word_mb = make_mbchar(word, word_mb, &word_mb_len);
seq = (int *)nmalloc(word_mb_len * sizeof(int));
unget_input(&word_kbinput, 1);
for (i = 0; i < word_mb_len; i++)
seq[i] = (unsigned char)word_mb[i];
unget_input(seq, word_mb_len);
free(seq);
free(word_mb);
}
/* Get the complete sequence, and save the key values in it as the
/* Get the complete sequence, and save the characters in it as the
* result. */
*kbinput_len = get_buffer_len();
sequence = get_input(NULL, *kbinput_len);
retval = buffer_to_keys(sequence, *kbinput_len);
free(sequence);
retval = get_input(NULL, *kbinput_len);
return retval;
}
......@@ -1787,12 +1681,21 @@ int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
* characters in the input buffer if it isn't empty. */
if (*s_or_t == TRUE || get_buffer_len() == 0) {
if (kbinput != NULL) {
bool got_enter;
/* Whether we got the Enter key. */
/* Display all the characters in the input buffer at
* once. */
do_statusbar_output(kbinput, kbinput_len, &got_enter);
char *output = charalloc(kbinput_len + 1);
size_t i;
bool got_enter;
/* Whether we got the Enter key. */
for (i = 0; i < kbinput_len; i++)
output[i] = (char)kbinput[i];
output[i] = '\0';
do_statusbar_output(output, kbinput_len, &got_enter);
free(output);
/* Empty the input buffer. */
kbinput_len = 0;
......@@ -1900,7 +1803,7 @@ void do_statusbar_home(void)
#ifndef NANO_SMALL
if (ISSET(SMART_HOME)) {
size_t statusbar_x_save = statusbar_x;
for (statusbar_x = 0; isblank(answer[statusbar_x]) &&
for (statusbar_x = 0; is_blank_char(answer[statusbar_x]) &&
statusbar_x < statusbar_xend; statusbar_x++)
;
if (statusbar_x == statusbar_x_save ||
......@@ -1939,15 +1842,16 @@ void do_statusbar_backspace(void)
void do_statusbar_delete(void)
{
if (statusbar_x < statusbar_xend) {
int char_len = parse_char(answer + statusbar_x, NULL
int char_buf_len = parse_mbchar(answer + statusbar_x, NULL
#ifdef NANO_WIDE
, NULL
#endif
, NULL);
charmove(answer + statusbar_x, answer + statusbar_x + char_len,
statusbar_xend - statusbar_x - char_len + 1);
statusbar_xend -= char_len;
charmove(answer + statusbar_x, answer + statusbar_x +
char_buf_len, statusbar_xend - statusbar_x -
char_buf_len + 1);
statusbar_xend -= char_buf_len;
}
}
......@@ -1960,8 +1864,9 @@ void do_statusbar_cut_text(void)
void do_statusbar_verbatim_input(bool *got_enter)
{
int *kbinput; /* Used to hold verbatim input. */
size_t kbinput_len; /* Length of verbatim input. */
int *kbinput;
size_t kbinput_len, i;
char *output;
*got_enter = FALSE;
......@@ -1969,73 +1874,69 @@ void do_statusbar_verbatim_input(bool *got_enter)
kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
/* Display all the verbatim characters at once. */
do_statusbar_output(kbinput, kbinput_len, got_enter);
output = charalloc(kbinput_len + 1);
free(kbinput);
for (i = 0; i < kbinput_len; i++)
output[i] = (char)kbinput[i];
output[i] = '\0';
do_statusbar_output(output, kbinput_len, got_enter);
free(output);
}
void do_statusbar_output(int *kbinput, size_t kbinput_len, bool
void do_statusbar_output(char *output, size_t output_len, bool
*got_enter)
{
size_t i;
size_t i = 0;
char *key =
#ifdef NANO_WIDE
!ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
#endif
charalloc(1);
char *char_buf = charalloc(mb_cur_max());
int char_buf_len;
assert(answer != NULL);
*got_enter = FALSE;
for (i = 0; i < kbinput_len; i++) {
int key_len;
while (i < output_len) {
/* Null to newline, if needed. */
if (kbinput[i] == '\0')
kbinput[i] = '\n';
if (output[i] == '\0')
output[i] = '\n';
/* Newline to Enter, if needed. */
else if (kbinput[i] == '\n') {
else if (output[i] == '\n') {
/* Set got_enter to TRUE to indicate that we got the Enter
* key, put back the rest of the keystrokes in kbinput so
* that they can be parsed again, and get out. */
* key, put back the rest of the characters in output so
* that they can be parsed and output again, and get out. */
*got_enter = TRUE;
unparse_kbinput(i, kbinput, kbinput_len);
unparse_kbinput(output + i, output_len - i);
return;
}
/* Interpret the next multibyte character. If it's an invalid
* multibyte character, interpret it as though it's a byte
* character. */
char_buf_len = parse_mbchar(output + i, char_buf
#ifdef NANO_WIDE
/* Change the wide character to its multibyte value. If it's
* invalid, go on to the next character. */
if (!ISSET(NO_UTF8)) {
key_len = wctomb(key, (wchar_t)kbinput[i]);
if (key_len == -1)
continue;
/* Interpret the character as a single-byte sequence. */
} else {
#endif
key_len = 1;
key[0] = (unsigned char)kbinput[i];
#ifdef NANO_WIDE
}
, NULL
#endif
, NULL);
i += char_buf_len;
/* More dangerousness fun =) */
answer = charealloc(answer, statusbar_xend + key_len + 1);
answer = charealloc(answer, statusbar_xend + char_buf_len + 1);
assert(statusbar_x <= statusbar_xend);
charmove(&answer[statusbar_x + key_len], &answer[statusbar_x],
statusbar_xend - statusbar_x + key_len);
charcpy(&answer[statusbar_x], key, key_len);
statusbar_xend += key_len;
charmove(&answer[statusbar_x + char_buf_len],
&answer[statusbar_x], statusbar_xend - statusbar_x +
char_buf_len);
charcpy(&answer[statusbar_x], char_buf, char_buf_len);
statusbar_xend += char_buf_len;
do_statusbar_right();
}
free(key);
free(char_buf);
}
/* Return the placewewant associated with current_x. That is, xplustabs
......@@ -2059,7 +1960,7 @@ size_t actual_x(const char *str, size_t xplus)
assert(str != NULL);
while (*str != '\0') {
int str_len = parse_char(str, NULL
int str_len = parse_mbchar(str, NULL
#ifdef NANO_WIDE
, NULL
#endif
......@@ -2088,7 +1989,7 @@ size_t strnlenpt(const char *str, size_t size)
assert(str != NULL);
while (*str != '\0') {
int str_len = parse_char(str, NULL
int str_len = parse_mbchar(str, NULL
#ifdef NANO_WIDE
, NULL
#endif
......@@ -2170,6 +2071,12 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
size_t index;
/* Current position in converted. */
char *buf_mb = charalloc(mb_cur_max());
int buf_mb_len;
#ifdef NANO_WIDE
bool bad_char;
#endif
/* If dollars is TRUE, make room for the "$" at the end of the
* line. */
if (dollars && len > 0 && strlenpt(buf) > start_col + len)
......@@ -2183,92 +2090,59 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
assert(column <= start_col);
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8))
alloc_len = MB_CUR_MAX * (len + 2);
else
#endif
alloc_len = len + 2;
/* Allocate enough space for the entire line. It should contain
* (len + 2) multibyte characters at most. */
alloc_len = mb_cur_max() * (len + 2);
converted = charalloc(alloc_len + 1);
index = 0;
if (column < start_col || (dollars && column > 0 &&
buf[start_index] != '\t')) {
int wide_buf, mb_buf_len;
/* We don't display all of buf[start_index] since it starts to
* the left of the screen. */
mb_buf_len = parse_char(buf + start_index, &wide_buf
buf_mb_len = parse_mbchar(buf + start_index, buf_mb
#ifdef NANO_WIDE
, NULL
#endif
, NULL);
if (is_cntrl_char(wide_buf)) {
if (is_cntrl_mbchar(buf_mb)) {
if (column < start_col) {
char *ctrl_mb_buf =
#ifdef NANO_WIDE
!ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
#endif
charalloc(1);
int ctrl_mb_buf_len, i;
wide_buf = control_rep((unsigned char)wide_buf);
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8))
ctrl_mb_buf_len = wctomb(ctrl_mb_buf,
(wchar_t)wide_buf);
else {
#endif
ctrl_mb_buf_len = 1;
ctrl_mb_buf[0] = (unsigned char)wide_buf;
#ifdef NANO_WIDE
}
#endif
char *ctrl_buf_mb = charalloc(mb_cur_max());
int ctrl_buf_mb_len, i;
for (i = 0; i < ctrl_mb_buf_len; i++)
converted[index++] = ctrl_mb_buf[i];
ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
&ctrl_buf_mb_len);
free(ctrl_mb_buf);
for (i = 0; i < ctrl_buf_mb_len; i++)
converted[index++] = ctrl_buf_mb[i];
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
int width = wcwidth((wchar_t)wide_buf);
start_col += mbwidth(ctrl_buf_mb);
if (width != -1)
start_col += width;
} else
#endif
start_col++;
free(ctrl_buf_mb);
start_index += mb_buf_len;
start_index += buf_mb_len;
}
}
#ifdef NANO_WIDE
else if (wcwidth((wchar_t)wide_buf) > 1) {
else if (mbwidth(buf_mb) > 1) {
converted[index++] = ' ';
start_col++;
start_index += mb_buf_len;
start_index += buf_mb_len;
}
#endif
}
while (index < alloc_len - 1 && buf[start_index] != '\0') {
int wide_buf, mb_buf_len;
#ifdef NANO_WIDE
bool bad_char;
#endif
mb_buf_len = parse_char(buf + start_index, &wide_buf
buf_mb_len = parse_mbchar(buf + start_index, buf_mb
#ifdef NANO_WIDE
, &bad_char
#endif
, NULL);
if (wide_buf == '\t') {
if (*buf_mb == '\t') {
converted[index++] =
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
......@@ -2282,45 +2156,23 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
/* If buf contains a control character, interpret it. If it
* contains an invalid multibyte control character, interpret
* that character as though it's a normal control character. */
} else if (is_cntrl_char(wide_buf)) {
char *ctrl_mb_buf =
#ifdef NANO_WIDE
!ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
#endif
charalloc(1);
int ctrl_mb_buf_len, i;
} else if (is_cntrl_mbchar(buf_mb)) {
char *ctrl_buf_mb = charalloc(mb_cur_max());
int ctrl_buf_mb_len, i;
converted[index++] = '^';
start_col++;
wide_buf = control_rep((unsigned char)wide_buf);
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8))
ctrl_mb_buf_len = wctomb(ctrl_mb_buf,
(wchar_t)wide_buf);
else {
#endif
ctrl_mb_buf_len = 1;
ctrl_mb_buf[0] = (unsigned char)wide_buf;
#ifdef NANO_WIDE
}
#endif
ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
&ctrl_buf_mb_len);
for (i = 0; i < ctrl_mb_buf_len; i++)
converted[index++] = ctrl_mb_buf[i];
for (i = 0; i < ctrl_buf_mb_len; i++)
converted[index++] = ctrl_buf_mb[i];
free(ctrl_mb_buf);
start_col += mbwidth(ctrl_buf_mb);
#ifdef NANO_WIDE
if (!ISSET(NO_UTF8)) {
int width = wcwidth((wchar_t)wide_buf);
if (width != -1)
start_col += width;
} else
#endif
start_col++;
} else if (wide_buf == ' ') {
free(ctrl_buf_mb);
} else if (*buf_mb == ' ') {
converted[index++] =
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
......@@ -2335,33 +2187,30 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
* character, interpret that character as though it's a
* normal non-control character. */
if (!ISSET(NO_UTF8) && bad_char) {
char *bad_mb_buf = charalloc(MB_CUR_MAX);
int bad_mb_buf_len;
char *bad_buf_mb = charalloc(mb_cur_max());
int bad_buf_mb_len;
bad_buf_mb = make_mbchar((unsigned int)*buf_mb,
bad_buf_mb, &bad_buf_mb_len);
bad_mb_buf_len = wctomb(bad_mb_buf, (wchar_t)wide_buf);
for (i = 0; i < bad_buf_mb_len; i++)
converted[index++] = bad_buf_mb[i];
for (i = 0; i < bad_mb_buf_len; i++)
converted[index++] = bad_mb_buf[i];
start_col += mbwidth(bad_buf_mb);
free(bad_mb_buf);
free(bad_buf_mb);
} else {
#endif
for (i = 0; i < mb_buf_len; i++)
for (i = 0; i < buf_mb_len; i++)
converted[index++] = buf[start_index + i];
start_col += mbwidth(buf_mb);
#ifdef NANO_WIDE
}
if (!ISSET(NO_UTF8)) {
int width = wcwidth((wchar_t)wide_buf);
if (width != -1)
start_col += width;
} else
#endif
start_col++;
}
start_index += mb_buf_len;
start_index += buf_mb_len;
}
if (index < alloc_len - 1)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment