mirror of git://git.sv.gnu.org/nano.git
massive overhaul to support buffered input and output, the first steps
toward proper wide character input and output, etc. git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2157 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
This commit is contained in:
parent
68ebb61fb1
commit
7483571f7f
20
ChangeLog
20
ChangeLog
|
@ -28,6 +28,26 @@ CVS code -
|
||||||
by DLR)
|
by DLR)
|
||||||
- Change references to "open files" to "open file buffers", for
|
- Change references to "open files" to "open file buffers", for
|
||||||
consistency. (DLR)
|
consistency. (DLR)
|
||||||
|
- Add option to disable UTF-8 sequence interpretation:
|
||||||
|
-O/--noutf8 on the command line, Meta-O as a toggle, and
|
||||||
|
"noutf8" in the rcfile. This is so people using single-byte
|
||||||
|
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(), 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)
|
||||||
- cut.c:
|
- cut.c:
|
||||||
do_cut_text()
|
do_cut_text()
|
||||||
- If keep_cutbuffer is FALSE, only blow away the text in the
|
- If keep_cutbuffer is FALSE, only blow away the text in the
|
||||||
|
|
|
@ -2583,7 +2583,7 @@ char *do_browser(const char *inpath)
|
||||||
selected = numents - 1;
|
selected = numents - 1;
|
||||||
else if (selectedbackup == selected)
|
else if (selectedbackup == selected)
|
||||||
/* Put back the 'select' key */
|
/* Put back the 'select' key */
|
||||||
unget_kbinput('s', FALSE);
|
unget_kbinput('s', FALSE, FALSE);
|
||||||
} else {
|
} else {
|
||||||
/* Must be clicking a shortcut */
|
/* Must be clicking a shortcut */
|
||||||
int mouse_x, mouse_y;
|
int mouse_x, mouse_y;
|
||||||
|
|
16
src/global.c
16
src/global.c
|
@ -1074,15 +1074,19 @@ void toggle_init(void)
|
||||||
#ifndef DISABLE_MOUSE
|
#ifndef DISABLE_MOUSE
|
||||||
toggle_init_one(TOGGLE_MOUSE_KEY, N_("Mouse support"), USE_MOUSE);
|
toggle_init_one(TOGGLE_MOUSE_KEY, N_("Mouse support"), USE_MOUSE);
|
||||||
#endif
|
#endif
|
||||||
/* If we're using restricted mode, the no-conversion and backup
|
/* If we're using restricted mode, the DOS/Mac conversion toggle is
|
||||||
* backup toggles are disabled. The former is useless since
|
* disabled. It's useless since inserting files is disabled. */
|
||||||
* inserting files is disabled, and the latter is useless since
|
if (!ISSET(RESTRICTED))
|
||||||
* backups are disabled. */
|
|
||||||
if (!ISSET(RESTRICTED)) {
|
|
||||||
toggle_init_one(TOGGLE_NOCONVERT_KEY,
|
toggle_init_one(TOGGLE_NOCONVERT_KEY,
|
||||||
N_("No conversion from DOS/Mac format"), NO_CONVERT);
|
N_("No conversion from DOS/Mac format"), NO_CONVERT);
|
||||||
|
#ifdef NANO_WIDE
|
||||||
|
toggle_init_one(TOGGLE_NOUTF8_KEY,
|
||||||
|
N_("No conversion from UTF-8 format"), NO_UTF8);
|
||||||
|
#endif
|
||||||
|
/* If we're using restricted mode, the backup toggle is disabled.
|
||||||
|
* It's useless since backups are disabled. */
|
||||||
|
if (!ISSET(RESTRICTED))
|
||||||
toggle_init_one(TOGGLE_BACKUP_KEY, N_("Backup files"), BACKUP_FILE);
|
toggle_init_one(TOGGLE_BACKUP_KEY, N_("Backup files"), BACKUP_FILE);
|
||||||
}
|
|
||||||
toggle_init_one(TOGGLE_SMOOTH_KEY, N_("Smooth scrolling"), SMOOTHSCROLL);
|
toggle_init_one(TOGGLE_SMOOTH_KEY, N_("Smooth scrolling"), SMOOTHSCROLL);
|
||||||
toggle_init_one(TOGGLE_SMARTHOME_KEY, N_("Smart home key"), SMART_HOME);
|
toggle_init_one(TOGGLE_SMARTHOME_KEY, N_("Smart home key"), SMART_HOME);
|
||||||
#ifdef ENABLE_COLOR
|
#ifdef ENABLE_COLOR
|
||||||
|
|
449
src/nano.c
449
src/nano.c
|
@ -929,6 +929,9 @@ void usage(void)
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
print1opt("-N", "--noconvert", N_("Don't convert files from DOS/Mac format"));
|
print1opt("-N", "--noconvert", N_("Don't convert files from DOS/Mac format"));
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef NANO_WIDE
|
||||||
|
print1opt("-O", "--noutf8", N_("Don't convert files from UTF-8 format"));
|
||||||
|
#endif
|
||||||
#ifndef DISABLE_JUSTIFY
|
#ifndef DISABLE_JUSTIFY
|
||||||
print1opt(_("-Q [str]"), _("--quotestr=[str]"), N_("Quoting string, default \"> \""));
|
print1opt(_("-Q [str]"), _("--quotestr=[str]"), N_("Quoting string, default \"> \""));
|
||||||
#endif
|
#endif
|
||||||
|
@ -1146,87 +1149,20 @@ bool open_pipe(const char *command)
|
||||||
}
|
}
|
||||||
#endif /* !NANO_SMALL */
|
#endif /* !NANO_SMALL */
|
||||||
|
|
||||||
/* The user typed a character; add it to the edit buffer. */
|
|
||||||
void do_char(char ch)
|
|
||||||
{
|
|
||||||
size_t current_len = strlen(current->data);
|
|
||||||
#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
|
|
||||||
bool do_refresh = FALSE;
|
|
||||||
/* Do we have to call edit_refresh(), or can we get away with
|
|
||||||
* update_line()? */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ch == '\0') /* Null to newline, if needed. */
|
|
||||||
ch = '\n';
|
|
||||||
else if (ch == '\n') { /* Newline to Enter, if needed. */
|
|
||||||
do_enter();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(current != NULL && current->data != NULL);
|
|
||||||
|
|
||||||
/* When a character is inserted on the current magicline, it means
|
|
||||||
* we need a new one! */
|
|
||||||
if (filebot == current)
|
|
||||||
new_magicline();
|
|
||||||
|
|
||||||
/* More dangerousness fun =) */
|
|
||||||
current->data = charealloc(current->data, current_len + 2);
|
|
||||||
assert(current_x <= current_len);
|
|
||||||
charmove(¤t->data[current_x + 1], ¤t->data[current_x],
|
|
||||||
current_len - current_x + 1);
|
|
||||||
current->data[current_x] = ch;
|
|
||||||
totsize++;
|
|
||||||
set_modified();
|
|
||||||
|
|
||||||
#ifndef NANO_SMALL
|
|
||||||
/* Note that current_x has not yet been incremented. */
|
|
||||||
if (current == mark_beginbuf && current_x < mark_beginx)
|
|
||||||
mark_beginx++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
do_right(FALSE);
|
|
||||||
|
|
||||||
#ifndef DISABLE_WRAPPING
|
|
||||||
/* If we're wrapping text, we need to call edit_refresh(). */
|
|
||||||
if (!ISSET(NO_WRAP) && ch != '\t')
|
|
||||||
do_refresh = do_wrap(current);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_COLOR
|
|
||||||
/* If color syntaxes are turned on, we need to call
|
|
||||||
* edit_refresh(). */
|
|
||||||
if (ISSET(COLOR_SYNTAX))
|
|
||||||
do_refresh = TRUE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
|
|
||||||
if (do_refresh)
|
|
||||||
edit_refresh();
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
update_line(current, current_x);
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_verbatim_input(void)
|
void do_verbatim_input(void)
|
||||||
{
|
{
|
||||||
int *v_kbinput = NULL; /* Used to hold verbatim input. */
|
int *kbinput; /* Used to hold verbatim input. */
|
||||||
size_t v_len; /* Length of verbatim input. */
|
size_t kbinput_len; /* Length of verbatim input. */
|
||||||
size_t i;
|
|
||||||
|
|
||||||
statusbar(_("Verbatim input"));
|
statusbar(_("Verbatim input"));
|
||||||
|
|
||||||
v_kbinput = get_verbatim_kbinput(edit, &v_len, TRUE);
|
/* Read in all the verbatim characters. */
|
||||||
|
kbinput = get_verbatim_kbinput(edit, &kbinput_len);
|
||||||
|
|
||||||
/* Turn on DISABLE_CURPOS while inserting character(s) and turn it
|
/* Display all the verbatim characters at once. */
|
||||||
* off afterwards, so that if constant cursor position display is
|
do_output(kbinput, kbinput_len);
|
||||||
* on, it will be updated properly. */
|
|
||||||
SET(DISABLE_CURPOS);
|
|
||||||
for (i = 0; i < v_len; i++)
|
|
||||||
do_char((char)v_kbinput[i]);
|
|
||||||
UNSET(DISABLE_CURPOS);
|
|
||||||
|
|
||||||
free(v_kbinput);
|
free(kbinput);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_backspace(void)
|
void do_backspace(void)
|
||||||
|
@ -1315,7 +1251,8 @@ void do_delete(void)
|
||||||
|
|
||||||
void do_tab(void)
|
void do_tab(void)
|
||||||
{
|
{
|
||||||
do_char('\t');
|
int kbinput = '\t';
|
||||||
|
do_output(&kbinput, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Someone hits return *gasp!* */
|
/* Someone hits return *gasp!* */
|
||||||
|
@ -2753,7 +2690,7 @@ void do_justify(bool full_justify)
|
||||||
size_t mark_beginx_save = mark_beginx;
|
size_t mark_beginx_save = mark_beginx;
|
||||||
#endif
|
#endif
|
||||||
int kbinput;
|
int kbinput;
|
||||||
bool meta_key, func_key;
|
bool meta_key, func_key, s_or_t;
|
||||||
|
|
||||||
/* If we're justifying the entire file, start at the beginning. */
|
/* If we're justifying the entire file, start at the beginning. */
|
||||||
if (full_justify)
|
if (full_justify)
|
||||||
|
@ -3019,9 +2956,10 @@ void do_justify(bool full_justify)
|
||||||
|
|
||||||
/* Now get a keystroke and see if it's unjustify. If not, put back
|
/* Now get a keystroke and see if it's unjustify. If not, put back
|
||||||
* the keystroke and return. */
|
* the keystroke and return. */
|
||||||
kbinput = get_edit_input(&meta_key, &func_key, FALSE);
|
kbinput = do_input(&meta_key, &func_key, &s_or_t, FALSE);
|
||||||
|
|
||||||
if (!meta_key && !func_key && kbinput == NANO_UNJUSTIFY_KEY) {
|
if (!meta_key && !func_key && s_or_t &&
|
||||||
|
kbinput == NANO_UNJUSTIFY_KEY) {
|
||||||
/* Restore the justify we just did (ungrateful user!). */
|
/* Restore the justify we just did (ungrateful user!). */
|
||||||
current = current_save;
|
current = current_save;
|
||||||
current_x = current_x_save;
|
current_x = current_x_save;
|
||||||
|
@ -3073,7 +3011,7 @@ void do_justify(bool full_justify)
|
||||||
edit_refresh();
|
edit_refresh();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unget_kbinput(kbinput, meta_key);
|
unget_kbinput(kbinput, meta_key, func_key);
|
||||||
|
|
||||||
/* Blow away the text in the justify buffer. */
|
/* Blow away the text in the justify buffer. */
|
||||||
free_filestruct(jusbuffer);
|
free_filestruct(jusbuffer);
|
||||||
|
@ -3418,6 +3356,322 @@ void terminal_init(void)
|
||||||
disable_flow_control();
|
disable_flow_control();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
|
||||||
|
allow_funcs)
|
||||||
|
{
|
||||||
|
int input;
|
||||||
|
/* The character we read in. */
|
||||||
|
static int *kbinput = NULL;
|
||||||
|
/* The input buffer. */
|
||||||
|
static size_t kbinput_len = 0;
|
||||||
|
/* The length of the input buffer. */
|
||||||
|
const shortcut *s;
|
||||||
|
bool have_shortcut;
|
||||||
|
#ifndef NANO_SMALL
|
||||||
|
const toggle *t;
|
||||||
|
bool have_toggle;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*s_or_t = FALSE;
|
||||||
|
|
||||||
|
/* Read in a character. */
|
||||||
|
input = get_kbinput(edit, meta_key, func_key);
|
||||||
|
|
||||||
|
#ifndef DISABLE_MOUSE
|
||||||
|
/* If we got a mouse click and it was on a shortcut, read in the
|
||||||
|
* shortcut character. */
|
||||||
|
if (allow_funcs && func_key && input == KEY_MOUSE) {
|
||||||
|
if (do_mouse())
|
||||||
|
input = get_kbinput(edit, meta_key, func_key);
|
||||||
|
else
|
||||||
|
input = ERR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check for a shortcut in the main list. */
|
||||||
|
s = get_shortcut(main_list, &input, meta_key, func_key);
|
||||||
|
|
||||||
|
/* If we got a shortcut from the main list, or a "universal"
|
||||||
|
* edit window shortcut, set have_shortcut to TRUE. */
|
||||||
|
have_shortcut = (s != NULL || input == NANO_XON_KEY ||
|
||||||
|
input == NANO_XOFF_KEY || input == NANO_SUSPEND_KEY);
|
||||||
|
|
||||||
|
#ifndef NANO_SMALL
|
||||||
|
/* Check for a toggle in the main list. */
|
||||||
|
t = get_toggle(input, *meta_key);
|
||||||
|
|
||||||
|
/* If we got a toggle from the main list, set have_toggle to
|
||||||
|
* TRUE. */
|
||||||
|
have_toggle = (t != NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set s_or_t to TRUE if we got a shortcut or toggle. */
|
||||||
|
*s_or_t = (have_shortcut
|
||||||
|
#ifndef NANO_SMALL
|
||||||
|
|| have_toggle
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
if (allow_funcs) {
|
||||||
|
/* If we got a character, and it isn't a shortcut, toggle, or
|
||||||
|
* control character, it's a normal text character. Display the
|
||||||
|
* warning if we're in view mode, or add the character to the
|
||||||
|
* input buffer if we're not. */
|
||||||
|
if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
|
||||||
|
if (ISSET(VIEW_MODE))
|
||||||
|
print_view_warning();
|
||||||
|
else {
|
||||||
|
kbinput_len++;
|
||||||
|
kbinput = (int *)nrealloc(kbinput, kbinput_len *
|
||||||
|
sizeof(int));
|
||||||
|
kbinput[kbinput_len - 1] = input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we got a shortcut or toggle, or if there aren't any other
|
||||||
|
* characters waiting after the one we read in, we need to
|
||||||
|
* display all the characters in the input buffer if it isn't
|
||||||
|
* empty. Note that it should be empty if we're in view
|
||||||
|
* mode. */
|
||||||
|
if (*s_or_t == TRUE || get_buffer_len() == 0) {
|
||||||
|
if (kbinput != NULL) {
|
||||||
|
/* Display all the characters in the input buffer at
|
||||||
|
* once. */
|
||||||
|
do_output(kbinput, kbinput_len);
|
||||||
|
|
||||||
|
/* Empty the input buffer. */
|
||||||
|
kbinput_len = 0;
|
||||||
|
free(kbinput);
|
||||||
|
kbinput = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_shortcut) {
|
||||||
|
switch (input) {
|
||||||
|
/* Handle the "universal" edit window shortcuts. */
|
||||||
|
case NANO_XON_KEY:
|
||||||
|
statusbar(_("XON ignored, mumble mumble."));
|
||||||
|
break;
|
||||||
|
case NANO_XOFF_KEY:
|
||||||
|
statusbar(_("XOFF ignored, mumble mumble."));
|
||||||
|
break;
|
||||||
|
#ifndef NANO_SMALL
|
||||||
|
case NANO_SUSPEND_KEY:
|
||||||
|
if (ISSET(SUSPEND))
|
||||||
|
do_suspend(0);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
/* Handle the normal edit window shortcuts. */
|
||||||
|
default:
|
||||||
|
/* Blow away the text in the cutbuffer if we aren't
|
||||||
|
* cutting text. */
|
||||||
|
if (s->func != do_cut_text)
|
||||||
|
cutbuffer_reset();
|
||||||
|
|
||||||
|
/* Run the function associated with this shortcut,
|
||||||
|
* if there is one. */
|
||||||
|
if (s->func != NULL) {
|
||||||
|
if (ISSET(VIEW_MODE) && !s->viewok)
|
||||||
|
print_view_warning();
|
||||||
|
else
|
||||||
|
s->func();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef NANO_SMALL
|
||||||
|
else if (have_toggle) {
|
||||||
|
/* Blow away the text in the cutbuffer, since we aren't
|
||||||
|
* cutting text. */
|
||||||
|
cutbuffer_reset();
|
||||||
|
/* Toggle the flag associated with this shortcut. */
|
||||||
|
if (allow_funcs)
|
||||||
|
do_toggle(t);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
/* Blow away the text in the cutbuffer, since we aren't
|
||||||
|
* cutting text. */
|
||||||
|
cutbuffer_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_MOUSE
|
||||||
|
bool do_mouse(void)
|
||||||
|
{
|
||||||
|
int mouse_x, mouse_y;
|
||||||
|
bool retval;
|
||||||
|
|
||||||
|
retval = get_mouseinput(&mouse_x, &mouse_y, TRUE);
|
||||||
|
|
||||||
|
if (!retval) {
|
||||||
|
/* We can click in the edit window to move the cursor. */
|
||||||
|
if (wenclose(edit, mouse_y, mouse_x)) {
|
||||||
|
bool sameline;
|
||||||
|
/* Did they click on the line with the cursor? If they
|
||||||
|
* clicked on the cursor, we set the mark. */
|
||||||
|
size_t xcur;
|
||||||
|
/* The character they clicked on. */
|
||||||
|
|
||||||
|
/* Subtract out the size of topwin. Perhaps we need a
|
||||||
|
* constant somewhere? */
|
||||||
|
mouse_y -= 2;
|
||||||
|
|
||||||
|
sameline = (mouse_y == current_y);
|
||||||
|
|
||||||
|
/* Move to where the click occurred. */
|
||||||
|
for (; current_y < mouse_y && current->next != NULL; current_y++)
|
||||||
|
current = current->next;
|
||||||
|
for (; current_y > mouse_y && current->prev != NULL; current_y--)
|
||||||
|
current = current->prev;
|
||||||
|
|
||||||
|
xcur = actual_x(current->data, get_page_start(xplustabs()) +
|
||||||
|
mouse_x);
|
||||||
|
|
||||||
|
#ifndef NANO_SMALL
|
||||||
|
/* Clicking where the cursor is toggles the mark, as does
|
||||||
|
* clicking beyond the line length with the cursor at the
|
||||||
|
* end of the line. */
|
||||||
|
if (sameline && xcur == current_x) {
|
||||||
|
if (ISSET(VIEW_MODE)) {
|
||||||
|
print_view_warning();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
do_mark();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
current_x = xcur;
|
||||||
|
placewewant = xplustabs();
|
||||||
|
edit_refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* FIXME: If we clicked on a location in the statusbar, the cursor
|
||||||
|
* should move to the location we clicked on. This functionality
|
||||||
|
* should be in do_statusbar_mouse() when it's written. */
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif /* !DISABLE_MOUSE */
|
||||||
|
|
||||||
|
/* The user typed kbinput_len characters. Add them to the edit
|
||||||
|
* buffer. */
|
||||||
|
void do_output(int *kbinput, size_t kbinput_len)
|
||||||
|
{
|
||||||
|
size_t i, current_len = strlen(current->data);
|
||||||
|
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
|
||||||
|
MB_LEN_MAX
|
||||||
|
#else
|
||||||
|
1
|
||||||
|
#endif
|
||||||
|
]; /* The current character we have. */
|
||||||
|
int key_len; /* The length of the current character. */
|
||||||
|
|
||||||
|
assert(current != NULL && current->data != NULL);
|
||||||
|
|
||||||
|
/* Turn off constant cursor position display if it's on. */
|
||||||
|
if (old_constupdate)
|
||||||
|
UNSET(CONSTUPDATE);
|
||||||
|
|
||||||
|
for (i = 0; i < kbinput_len; i++) {
|
||||||
|
#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, kbinput[i]);
|
||||||
|
|
||||||
|
if (key_len == -1)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
/* Interpret the character as a single-byte sequence. */
|
||||||
|
key_len = 1;
|
||||||
|
key[0] = (char)kbinput[i];
|
||||||
|
#ifdef NANO_WIDE
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Null to newline, if needed. */
|
||||||
|
if (key[0] == '\0' && key_len == 1)
|
||||||
|
key[0] = '\n';
|
||||||
|
/* Newline to Enter, if needed. */
|
||||||
|
else if (key[0] == '\n' && key_len == 1) {
|
||||||
|
do_enter();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When a character is inserted on the current magicline, it
|
||||||
|
* means we need a new one! */
|
||||||
|
if (filebot == current)
|
||||||
|
new_magicline();
|
||||||
|
|
||||||
|
/* More dangerousness fun =) */
|
||||||
|
current->data = charealloc(current->data,
|
||||||
|
current_len + key_len + 1);
|
||||||
|
assert(current_x <= current_len);
|
||||||
|
charmove(¤t->data[current_x + key_len],
|
||||||
|
¤t->data[current_x],
|
||||||
|
current_len - current_x + key_len);
|
||||||
|
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
|
||||||
|
* now. */
|
||||||
|
totsize += key_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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < key_len; j++)
|
||||||
|
do_right(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_WRAPPING
|
||||||
|
/* If we're wrapping text, we need to call edit_refresh(). */
|
||||||
|
if (!ISSET(NO_WRAP) && (key[0] != '\t' || key_len != 1)) {
|
||||||
|
bool do_refresh_save = do_refresh;
|
||||||
|
|
||||||
|
do_refresh = do_wrap(current);
|
||||||
|
|
||||||
|
/* If we needed to call edit_refresh() before this, we'll
|
||||||
|
* still need to after this. */
|
||||||
|
if (do_refresh_save)
|
||||||
|
do_refresh = TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_COLOR
|
||||||
|
/* If color syntaxes are turned on, we need to call
|
||||||
|
* edit_refresh(). */
|
||||||
|
if (ISSET(COLOR_SYNTAX))
|
||||||
|
do_refresh = TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turn constant cursor position display back on if it was on. */
|
||||||
|
if (old_constupdate)
|
||||||
|
SET(CONSTUPDATE);
|
||||||
|
|
||||||
|
if (do_refresh)
|
||||||
|
edit_refresh();
|
||||||
|
else
|
||||||
|
update_line(current, current_x);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int optchr;
|
int optchr;
|
||||||
|
@ -3432,9 +3686,6 @@ int main(int argc, char **argv)
|
||||||
/* The old value of the multibuffer option, restored after we
|
/* The old value of the multibuffer option, restored after we
|
||||||
* load all files on the command line. */
|
* load all files on the command line. */
|
||||||
#endif
|
#endif
|
||||||
int kbinput;
|
|
||||||
/* Input from keyboard. */
|
|
||||||
bool meta_key, func_key;
|
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
const struct option long_options[] = {
|
const struct option long_options[] = {
|
||||||
{"help", 0, 0, 'h'},
|
{"help", 0, 0, 'h'},
|
||||||
|
@ -3447,6 +3698,9 @@ int main(int argc, char **argv)
|
||||||
#endif
|
#endif
|
||||||
{"ignorercfiles", 0, 0, 'I'},
|
{"ignorercfiles", 0, 0, 'I'},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef NANO_WIDE
|
||||||
|
{"noutf8", 0, 0, 'O'},
|
||||||
|
#endif
|
||||||
#ifndef DISABLE_JUSTIFY
|
#ifndef DISABLE_JUSTIFY
|
||||||
{"quotestr", 1, 0, 'Q'},
|
{"quotestr", 1, 0, 'Q'},
|
||||||
#endif
|
#endif
|
||||||
|
@ -3510,9 +3764,9 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
while ((optchr =
|
while ((optchr =
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
getopt_long(argc, argv, "h?ABE:FHINQ:RST:VY:Zabcdefgijklmo:pr:s:tvwxz", long_options, NULL)
|
getopt_long(argc, argv, "h?ABE:FHINOQ:RST:VY:Zabcdefgijklmo:pr:s:tvwxz", long_options, NULL)
|
||||||
#else
|
#else
|
||||||
getopt(argc, argv, "h?ABE:FHINQ:RST:VY:Zabcdefgijklmo:pr:s:tvwxz")
|
getopt(argc, argv, "h?ABE:FHINOQ:RST:VY:Zabcdefgijklmo:pr:s:tvwxz")
|
||||||
#endif
|
#endif
|
||||||
) != -1) {
|
) != -1) {
|
||||||
|
|
||||||
|
@ -3556,6 +3810,9 @@ int main(int argc, char **argv)
|
||||||
SET(NO_CONVERT);
|
SET(NO_CONVERT);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case 'O':
|
||||||
|
SET(NO_UTF8);
|
||||||
|
break;
|
||||||
#ifndef DISABLE_JUSTIFY
|
#ifndef DISABLE_JUSTIFY
|
||||||
case 'Q':
|
case 'Q':
|
||||||
quotestr = mallocstrcpy(quotestr, optarg);
|
quotestr = mallocstrcpy(quotestr, optarg);
|
||||||
|
@ -3929,7 +4186,18 @@ int main(int argc, char **argv)
|
||||||
edit_refresh();
|
edit_refresh();
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
|
bool meta_key;
|
||||||
|
/* Whether we got a meta key sequence. */
|
||||||
|
bool func_key;
|
||||||
|
/* Whether we got a function key. */
|
||||||
|
bool s_or_t;
|
||||||
|
/* Whether we got a shortcut or toggle. */
|
||||||
|
|
||||||
|
/* Make sure the cursor is in the edit window. */
|
||||||
reset_cursor();
|
reset_cursor();
|
||||||
|
|
||||||
|
/* If constant cursor position display is on, display the cursor
|
||||||
|
* position. */
|
||||||
if (ISSET(CONSTUPDATE))
|
if (ISSET(CONSTUPDATE))
|
||||||
do_cursorpos(TRUE);
|
do_cursorpos(TRUE);
|
||||||
|
|
||||||
|
@ -3937,17 +4205,8 @@ int main(int argc, char **argv)
|
||||||
currshortcut = main_list;
|
currshortcut = main_list;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
kbinput = get_edit_input(&meta_key, &func_key, TRUE);
|
/* Read in and interpret characters. */
|
||||||
|
do_input(&meta_key, &func_key, &s_or_t, TRUE);
|
||||||
/* Last gasp, stuff that's not in the main lists. */
|
|
||||||
if (kbinput != ERR && !is_cntrl_char(kbinput)) {
|
|
||||||
/* Don't stop unhandled printable sequences, so that people
|
|
||||||
* with odd character sets can type. */
|
|
||||||
if (ISSET(VIEW_MODE))
|
|
||||||
print_view_warning();
|
|
||||||
else
|
|
||||||
do_char(kbinput);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
assert(FALSE);
|
assert(FALSE);
|
||||||
}
|
}
|
||||||
|
|
12
src/nano.h
12
src/nano.h
|
@ -44,6 +44,7 @@
|
||||||
#define charalloc(howmuch) (char *)nmalloc((howmuch) * sizeof(char))
|
#define charalloc(howmuch) (char *)nmalloc((howmuch) * sizeof(char))
|
||||||
#define charealloc(ptr, howmuch) (char *)nrealloc(ptr, (howmuch) * sizeof(char))
|
#define charealloc(ptr, howmuch) (char *)nrealloc(ptr, (howmuch) * sizeof(char))
|
||||||
#define charmove(dest, src, n) memmove(dest, src, (n) * sizeof(char))
|
#define charmove(dest, src, n) memmove(dest, src, (n) * sizeof(char))
|
||||||
|
#define charcpy(dest, src, n) memcpy(dest, src, (n) * sizeof(char))
|
||||||
|
|
||||||
#ifdef BROKEN_REGEXEC
|
#ifdef BROKEN_REGEXEC
|
||||||
#define regexec(preg, string, nmatch, pmatch, eflags) regexec_safe(preg, string, nmatch, pmatch, eflags)
|
#define regexec(preg, string, nmatch, pmatch, eflags) regexec_safe(preg, string, nmatch, pmatch, eflags)
|
||||||
|
@ -134,6 +135,10 @@
|
||||||
|
|
||||||
#define VERMSG "GNU nano " VERSION
|
#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
|
/* If we aren't using ncurses, turn the mouse support off, as it's
|
||||||
* ncurses-specific. */
|
* ncurses-specific. */
|
||||||
#ifndef NCURSES_MOUSE_VERSION
|
#ifndef NCURSES_MOUSE_VERSION
|
||||||
|
@ -158,6 +163,11 @@ typedef enum {
|
||||||
} topmidnone;
|
} topmidnone;
|
||||||
|
|
||||||
/* Structure types. */
|
/* Structure types. */
|
||||||
|
typedef struct buffer {
|
||||||
|
int key;
|
||||||
|
bool key_code;
|
||||||
|
} buffer;
|
||||||
|
|
||||||
typedef struct filestruct {
|
typedef struct filestruct {
|
||||||
char *data;
|
char *data;
|
||||||
struct filestruct *next; /* Next node. */
|
struct filestruct *next; /* Next node. */
|
||||||
|
@ -317,6 +327,7 @@ typedef struct historyheadtype {
|
||||||
#define RESTRICTED (1<<26)
|
#define RESTRICTED (1<<26)
|
||||||
#define SMART_HOME (1<<27)
|
#define SMART_HOME (1<<27)
|
||||||
#define WHITESPACE_DISPLAY (1<<28)
|
#define WHITESPACE_DISPLAY (1<<28)
|
||||||
|
#define NO_UTF8 (1<<29)
|
||||||
|
|
||||||
/* Control key sequences, changing these would be very very bad. */
|
/* Control key sequences, changing these would be very very bad. */
|
||||||
#define NANO_CONTROL_SPACE 0
|
#define NANO_CONTROL_SPACE 0
|
||||||
|
@ -501,6 +512,7 @@ typedef struct historyheadtype {
|
||||||
#define TOGGLE_SYNTAX_KEY NANO_ALT_Y
|
#define TOGGLE_SYNTAX_KEY NANO_ALT_Y
|
||||||
#define TOGGLE_SMARTHOME_KEY NANO_ALT_H
|
#define TOGGLE_SMARTHOME_KEY NANO_ALT_H
|
||||||
#define TOGGLE_WHITESPACE_KEY NANO_ALT_P
|
#define TOGGLE_WHITESPACE_KEY NANO_ALT_P
|
||||||
|
#define TOGGLE_NOUTF8_KEY NANO_ALT_O
|
||||||
#endif /* !NANO_SMALL */
|
#endif /* !NANO_SMALL */
|
||||||
|
|
||||||
#define MAIN_VISIBLE 12
|
#define MAIN_VISIBLE 12
|
||||||
|
|
38
src/proto.h
38
src/proto.h
|
@ -327,7 +327,6 @@ void nano_disabled_msg(void);
|
||||||
RETSIGTYPE cancel_fork(int signal);
|
RETSIGTYPE cancel_fork(int signal);
|
||||||
bool open_pipe(const char *command);
|
bool open_pipe(const char *command);
|
||||||
#endif
|
#endif
|
||||||
void do_char(char ch);
|
|
||||||
void do_verbatim_input(void);
|
void do_verbatim_input(void);
|
||||||
void do_backspace(void);
|
void do_backspace(void);
|
||||||
void do_delete(void);
|
void do_delete(void);
|
||||||
|
@ -391,6 +390,12 @@ void enable_signals(void);
|
||||||
void disable_flow_control(void);
|
void disable_flow_control(void);
|
||||||
void enable_flow_control(void);
|
void enable_flow_control(void);
|
||||||
void terminal_init(void);
|
void terminal_init(void);
|
||||||
|
int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool
|
||||||
|
allow_funcs);
|
||||||
|
#ifndef DISABLE_MOUSE
|
||||||
|
bool do_mouse(void);
|
||||||
|
#endif
|
||||||
|
void do_output(int *kbinput, size_t kbinput_len);
|
||||||
|
|
||||||
/* Public functions in rcfile.c. */
|
/* Public functions in rcfile.c. */
|
||||||
#ifdef ENABLE_NANORC
|
#ifdef ENABLE_NANORC
|
||||||
|
@ -468,6 +473,7 @@ int regexp_bol_or_eol(const regex_t *preg, const char *string);
|
||||||
int is_blank_char(int c);
|
int is_blank_char(int c);
|
||||||
#endif
|
#endif
|
||||||
int is_cntrl_char(int c);
|
int is_cntrl_char(int c);
|
||||||
|
bool is_byte_char(int c);
|
||||||
int num_of_digits(int n);
|
int num_of_digits(int n);
|
||||||
bool parse_num(const char *str, ssize_t *val);
|
bool parse_num(const char *str, ssize_t *val);
|
||||||
void align(char **strp);
|
void align(char **strp);
|
||||||
|
@ -524,29 +530,29 @@ int check_wildcard_match(const char *text, const char *pattern);
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
void reset_kbinput(void);
|
void reset_kbinput(void);
|
||||||
#endif
|
#endif
|
||||||
void unget_kbinput(int kbinput, bool meta_key);
|
void get_buffer(WINDOW *win);
|
||||||
|
size_t get_buffer_len(void);
|
||||||
|
int *buffer_to_keys(buffer *input, size_t input_len);
|
||||||
|
void unget_input(buffer *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_kbinput(WINDOW *win, bool *meta_key, bool *func_key);
|
int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key);
|
||||||
int get_translated_kbinput(int kbinput, bool *escape_seq
|
int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
, bool reset
|
, bool reset
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
int get_ascii_kbinput(int kbinput, int ascii_digits
|
int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
|
||||||
|
*ignore_seq);
|
||||||
|
int get_escape_seq_abcd(int kbinput);
|
||||||
|
int get_word_kbinput(int kbinput
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
, bool reset
|
, bool reset
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
int get_control_kbinput(int kbinput);
|
int get_control_kbinput(int kbinput);
|
||||||
int get_escape_seq_kbinput(const int *escape_seq, size_t es_len, bool
|
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
|
||||||
*ignore_seq);
|
int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
|
||||||
int get_escape_seq_abcd(int kbinput);
|
|
||||||
int *get_verbatim_kbinput(WINDOW *win, size_t *v_len, bool allow_ascii);
|
|
||||||
int get_untranslated_kbinput(int kbinput, size_t position, bool
|
|
||||||
allow_ascii
|
|
||||||
#ifndef NANO_SMALL
|
|
||||||
, bool reset
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
#ifndef DISABLE_MOUSE
|
#ifndef DISABLE_MOUSE
|
||||||
bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
|
bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
|
||||||
#endif
|
#endif
|
||||||
|
@ -555,10 +561,6 @@ const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
|
||||||
#ifndef NANO_SMALL
|
#ifndef NANO_SMALL
|
||||||
const toggle *get_toggle(int kbinput, bool meta_key);
|
const toggle *get_toggle(int kbinput, bool meta_key);
|
||||||
#endif
|
#endif
|
||||||
int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs);
|
|
||||||
#ifndef DISABLE_MOUSE
|
|
||||||
bool get_edit_mouse(void);
|
|
||||||
#endif
|
|
||||||
size_t xplustabs(void);
|
size_t xplustabs(void);
|
||||||
size_t actual_x(const char *str, size_t xplus);
|
size_t actual_x(const char *str, size_t xplus);
|
||||||
size_t strnlenpt(const char *buf, size_t size);
|
size_t strnlenpt(const char *buf, size_t size);
|
||||||
|
|
|
@ -68,6 +68,9 @@ const static rcoption rcopts[] = {
|
||||||
#endif
|
#endif
|
||||||
{"nofollow", NOFOLLOW_SYMLINKS},
|
{"nofollow", NOFOLLOW_SYMLINKS},
|
||||||
{"nohelp", NO_HELP},
|
{"nohelp", NO_HELP},
|
||||||
|
#ifdef NANO_WIDE
|
||||||
|
{"noutf8", NO_UTF8},
|
||||||
|
#endif
|
||||||
#ifndef DISABLE_WRAPPING
|
#ifndef DISABLE_WRAPPING
|
||||||
{"nowrap", NO_WRAP},
|
{"nowrap", NO_WRAP},
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -70,6 +70,13 @@ int is_cntrl_char(int c)
|
||||||
(127 <= c && c < 160);
|
(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 num_of_digits(int n)
|
||||||
{
|
{
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
1434
src/winio.c
1434
src/winio.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue