From c13b7f069979db5543f7f74a18c1d9ad541f17a6 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Sat, 1 Jan 2005 07:28:15 +0000 Subject: [PATCH] overhaul the high-level input routines for the statusbar to make them more flexible, among other things, and add UTF-8 support to them in the process; also update the copyright years of the modified files git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@2210 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 32 +++- src/files.c | 6 +- src/global.c | 14 +- src/nano.c | 30 +-- src/proto.h | 19 +- src/winio.c | 513 +++++++++++++++++++++++++++++++-------------------- 6 files changed, 380 insertions(+), 234 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8137dd21..7a9d139e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -45,19 +45,38 @@ CVS code - do_mouse() and moved to nano.c), do_verbatim_input(), do_tab(), main(), and get_ascii_kbinput() (renamed to get_word_kbinput()). The wide version of ncurses is required - in order for output to work properly. (DLR; buffered - input/output based on ideas from mutt 1.4.2.1; double-Escape - input of Unicode characters suggested by Michael Piefel) + in order for wide/multibyte input and output to work properly. + (DLR; buffered input/output based on ideas from mutt 1.4.2.1; + double-Escape input of Unicode characters suggested by Michael + Piefel) - More steps toward wide character/multibyte character support. Movement and cursor display in the edit window should now work properly with files containing multibyte characters, and text - display of such files should work properly some of the time. - New functions control_rep(), parse_char(), move_left(), + display of such files should now work properly as well. New + functions control_rep(), parse_char(), move_left(), move_right(), and display_string_len(); changes to do_left(), do_right(), do_delete(), breakable(), break_line(), do_output(), get_buffer(), unget_input(), actual_x(), strnlenpt(), display_string(), titlebar(), statusbar(), onekey(), and do_credits(). (David Benbennick and DLR) + - Overhaul the high-level input routines for the statusbar to + make them read the shortcut lists for functions instead of + manually running them, to make nanogetstr() less complex, and + to increase flexibility. Note that currshortcut is now used + regardless of #ifdefs. Changes to shortcut_init() and + nanogetstr(); new functions do_statusbar_input(), + do_statusbar_mouse(), do_statusbar_home(), do_statusbar_end(), + do_statusbar_right(), do_statusbar_left(), + do_statusbar_backspace(), do_statusbar_delete(), + do_statusbar_cut_text(), and do_statusbar_output(). (DLR) + - Even more steps toward wide character/multibyte character + support. Movement and (most) cursor display at the statusbar + prompt should now work properly with a string containing + multibyte characters, and text display of such strings should + now (mostly) work properly as well. Changes to + do_statusbar_right(), do_statusbar_left(), + do_statusbar_backspace(), and do_statusbar_delete(). (David + Benbennick and DLR) - cut.c: do_cut_text() - If keep_cutbuffer is FALSE, only blow away the text in the @@ -100,6 +119,9 @@ CVS code - loop if there are no more paragraphs after the current one and the paragraph search left us on the magicline, so as to avoid a segfault. (DLR) + do_input() + - Add finished parameter, used to indicate when we run or try to + run a function associated with a shortcut. (DLR) main() - Try to automatically detect whether UTF-8 support is needed by setting the NO_UTF8 flag if setlocale() returns a string that diff --git a/src/files.c b/src/files.c index 7e6228d6..7598640b 100644 --- a/src/files.c +++ b/src/files.c @@ -2,7 +2,7 @@ /************************************************************************** * files.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) * @@ -1738,9 +1738,7 @@ int do_writeout(bool exiting) static bool did_cred = FALSE; #endif -#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) currshortcut = writefile_list; -#endif if (exiting && filename[0] != '\0' && ISSET(TEMP_FILE)) { retval = write_file(filename, FALSE, 0, FALSE); @@ -2541,9 +2539,7 @@ char *do_browser(const char *inpath) check_statusblank(); -#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE) currshortcut = browser_list; -#endif editline = 0; col = 0; diff --git a/src/global.c b/src/global.c index 4c4d2ec2..0db515ee 100644 --- a/src/global.c +++ b/src/global.c @@ -2,7 +2,7 @@ /************************************************************************** * global.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) * @@ -159,9 +159,7 @@ syntaxtype *syntaxes = NULL; char *syntaxstr = NULL; #endif -#if !defined(DISABLE_BROWSER) || !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE) const shortcut *currshortcut; /* Current shortcut list we're using */ -#endif #ifndef NANO_SMALL toggle *toggles = NULL; @@ -614,12 +612,12 @@ void shortcut_init(bool unjustify) /* Translators: try to keep this string under 10 characters long */ sc_init_one(&whereis_list, NANO_TOOTHERSEARCH_KEY, replace_msg, IFHELP(nano_replace_msg, NANO_NO_KEY), NANO_REPLACE_FKEY, - NANO_NO_KEY, VIEW, do_replace); + NANO_NO_KEY, VIEW, 0); /* Translators: try to keep this string under 10 characters long */ sc_init_one(&whereis_list, NANO_TOGOTOLINE_KEY, go_to_line_msg, IFHELP(nano_gotoline_msg, NANO_NO_KEY), NANO_GOTOLINE_FKEY, - NANO_NO_KEY, VIEW, do_gotoline_void); + NANO_NO_KEY, VIEW, 0); #ifndef DISABLE_JUSTIFY /* Translators: try to keep this string under 10 characters long */ @@ -691,11 +689,11 @@ void shortcut_init(bool unjustify) /* Translators: try to keep this string under 12 characters long */ sc_init_one(&replace_list, NANO_TOOTHERSEARCH_KEY, N_("No Replace"), IFHELP(nano_whereis_msg, NANO_NO_KEY), NANO_REPLACE_FKEY, - NANO_NO_KEY, VIEW, do_search); + NANO_NO_KEY, VIEW, 0); sc_init_one(&replace_list, NANO_TOGOTOLINE_KEY, go_to_line_msg, IFHELP(nano_gotoline_msg, NANO_NO_KEY), NANO_GOTOLINE_FKEY, - NANO_NO_KEY, VIEW, do_gotoline_void); + NANO_NO_KEY, VIEW, 0); #ifndef NANO_SMALL sc_init_one(&replace_list, NANO_NO_KEY, case_sens_msg, @@ -773,7 +771,7 @@ void shortcut_init(bool unjustify) sc_init_one(&gotoline_list, NANO_TOOTHERWHEREIS_KEY, N_("Go To Text"), IFHELP(nano_whereis_msg, NANO_NO_KEY), - NANO_NO_KEY, NANO_NO_KEY, VIEW, do_search); + NANO_NO_KEY, NANO_NO_KEY, VIEW, 0); #ifndef DISABLE_HELP free_shortcutage(&help_list); diff --git a/src/nano.c b/src/nano.c index 755fbefd..559ac14b 100644 --- a/src/nano.c +++ b/src/nano.c @@ -2,7 +2,7 @@ /************************************************************************** * nano.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) * @@ -2718,7 +2718,7 @@ void do_justify(bool full_justify) size_t mark_beginx_save = mark_beginx; #endif int kbinput; - bool meta_key, func_key, s_or_t; + bool meta_key, func_key, s_or_t, finished; /* If we're justifying the entire file, start at the beginning. */ if (full_justify) @@ -2984,7 +2984,7 @@ void do_justify(bool full_justify) /* Now get a keystroke and see if it's unjustify. If not, put back * the keystroke and return. */ - kbinput = do_input(&meta_key, &func_key, &s_or_t, FALSE); + kbinput = do_input(&meta_key, &func_key, &s_or_t, &finished, FALSE); if (!meta_key && !func_key && s_or_t && kbinput == NANO_UNJUSTIFY_KEY) { @@ -3386,7 +3386,7 @@ void terminal_init(void) } int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool - allow_funcs) + *finished, bool allow_funcs) { int input; /* The character we read in. */ @@ -3402,6 +3402,7 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool #endif *s_or_t = FALSE; + *finished = FALSE; /* Read in a character. */ input = get_kbinput(edit, meta_key, func_key); @@ -3477,7 +3478,8 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool if (have_shortcut) { switch (input) { - /* Handle the "universal" edit window shortcuts. */ + /* Handle the "universal" statusbar prompt shortcuts, + * setting ran_s_or_t to TRUE to indicate it. */ case NANO_XON_KEY: statusbar(_("XON ignored, mumble mumble.")); break; @@ -3490,21 +3492,23 @@ int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool do_suspend(0); break; #endif - /* Handle the normal edit window shortcuts. */ + /* Handle the normal edit window shortcuts, setting + * finished to TRUE to indicate that we're done after + * running or trying to run their associated + * functions. */ 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(); } + *finished = TRUE; break; } } @@ -3577,9 +3581,6 @@ bool do_mouse(void) 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; } @@ -4225,6 +4226,9 @@ int main(int argc, char **argv) /* Whether we got a function key. */ bool s_or_t; /* Whether we got a shortcut or toggle. */ + bool ran_s_or_t; + /* Whether we ran a function associated with a + * shortcut. */ /* Make sure the cursor is in the edit window. */ reset_cursor(); @@ -4234,12 +4238,10 @@ int main(int argc, char **argv) if (ISSET(CONSTUPDATE)) do_cursorpos(TRUE); -#if !defined(DISABLE_BROWSER) || !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE) currshortcut = main_list; -#endif /* Read in and interpret characters. */ - do_input(&meta_key, &func_key, &s_or_t, TRUE); + do_input(&meta_key, &func_key, &s_or_t, &ran_s_or_t, TRUE); } assert(FALSE); } diff --git a/src/proto.h b/src/proto.h index cb2d0f14..24419324 100644 --- a/src/proto.h +++ b/src/proto.h @@ -2,7 +2,7 @@ /************************************************************************** * proto.h * * * - * 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) * @@ -122,9 +122,7 @@ extern shortcut *spell_list; extern shortcut *browser_list, *gotodir_list; #endif -#if !defined(DISABLE_BROWSER) || !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE) extern const shortcut *currshortcut; -#endif #ifdef HAVE_REGEX_H extern regex_t search_regexp; @@ -391,7 +389,7 @@ void disable_flow_control(void); void enable_flow_control(void); void terminal_init(void); int do_input(bool *meta_key, bool *func_key, bool *s_or_t, bool - allow_funcs); + *finished, bool allow_funcs); #ifndef DISABLE_MOUSE bool do_mouse(void); #endif @@ -569,6 +567,19 @@ const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool #ifndef NANO_SMALL const toggle *get_toggle(int kbinput, bool meta_key); #endif +int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t, + bool *finished, bool allow_funcs); +#ifndef DISABLE_MOUSE +bool do_statusbar_mouse(void); +#endif +void do_statusbar_home(void); +void do_statusbar_end(void); +void do_statusbar_right(void); +void do_statusbar_left(void); +void do_statusbar_backspace(void); +void do_statusbar_delete(void); +void do_statusbar_cut_text(void); +void do_statusbar_output(int *kbinput, size_t kbinput_len); size_t xplustabs(void); size_t actual_x(const char *str, size_t xplus); size_t strnlenpt(const char *buf, size_t size); diff --git a/src/winio.c b/src/winio.c index d116b899..4cc6c77e 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2,7 +2,7 @@ /************************************************************************** * winio.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) * @@ -46,6 +46,10 @@ static size_t key_buffer_len = 0; static int statusblank = 0; /* The number of keystrokes left after * we call statusbar(), before we * actually blank the statusbar. */ +static size_t statusbar_x = (size_t)-1; + /* The cursor position in answer. */ +static size_t statusbar_xend = 0; + /* The length of answer. */ static bool resetstatuspos = FALSE; /* Should we reset the cursor position * at the statusbar prompt? */ @@ -1609,6 +1613,271 @@ const toggle *get_toggle(int kbinput, bool meta_key) } #endif /* !NANO_SMALL */ +int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t, + bool *finished, 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; + + *s_or_t = FALSE; + *finished = FALSE; + + /* Read in a character. */ + input = get_kbinput(bottomwin, 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(bottomwin, meta_key, func_key); + else + input = ERR; + } +#endif + + /* Check for a shortcut in the current list. */ + s = get_shortcut(currshortcut, &input, meta_key, func_key); + + /* If we got a shortcut from the current list, or a "universal" + * statusbar prompt shortcut, set have_shortcut to TRUE. */ + have_shortcut = (s != NULL || input == NANO_REFRESH_KEY || + input == NANO_HOME_KEY || input == NANO_END_KEY || + input == NANO_FORWARD_KEY || input == NANO_BACK_KEY || + input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY || + input == NANO_CUT_KEY); + + /* Set s_or_t to TRUE if we got a shortcut. */ + *s_or_t = have_shortcut; + + if (allow_funcs) { + if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) { + /* If we're using restricted mode, the filename isn't blank, + * and we're at the "Write File" prompt, disable text + * input. */ + if (!ISSET(RESTRICTED) || filename[0] == '\0' || + currshortcut != writefile_list) { + kbinput_len++; + kbinput = (int *)nrealloc(kbinput, kbinput_len * + sizeof(int)); + kbinput[kbinput_len - 1] = input; + } + } + + /* If we got a shortcut, 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. */ + if (*s_or_t == TRUE || get_buffer_len() == 0) { + if (kbinput != NULL) { + /* Display all the characters in the input buffer at + * once. */ + do_statusbar_output(kbinput, kbinput_len); + + /* Empty the input buffer. */ + kbinput_len = 0; + free(kbinput); + kbinput = NULL; + } + } + + if (have_shortcut) { + switch (input) { + /* Handle the "universal" statusbar prompt shortcuts. */ + case NANO_REFRESH_KEY: + total_refresh(); + break; + case NANO_HOME_KEY: + do_statusbar_home(); + break; + case NANO_END_KEY: + do_statusbar_end(); + break; + case NANO_FORWARD_KEY: + do_statusbar_right(); + break; + case NANO_BACK_KEY: + do_statusbar_left(); + break; + case NANO_BACKSPACE_KEY: + /* If we're using restricted mode, the filename + * isn't blank, and we're at the "Write File" + * prompt, disable Backspace. */ + if (!ISSET(RESTRICTED) || filename[0] == '\0' || + currshortcut != writefile_list) + do_statusbar_backspace(); + break; + case NANO_DELETE_KEY: + /* If we're using restricted mode, the filename + * isn't blank, and we're at the "Write File" + * prompt, disable Delete. */ + if (!ISSET(RESTRICTED) || filename[0] == '\0' || + currshortcut != writefile_list) + do_statusbar_delete(); + break; + case NANO_CUT_KEY: + /* If we're using restricted mode, the filename + * isn't blank, and we're at the "Write File" + * prompt, disable Cut. */ + if (!ISSET(RESTRICTED) || filename[0] == '\0' || + currshortcut != writefile_list) + do_statusbar_cut_text(); + break; + /* Handle the normal statusbar prompt shortcuts, setting + * finished to TRUE to indicate that we're done after + * running or trying to run their associated + * functions. */ + default: + if (s->func != NULL) { + if (ISSET(VIEW_MODE) && !s->viewok) + print_view_warning(); + else + s->func(); + } + *finished = TRUE; + } + } + } + + return input; +} + +#ifndef DISABLE_MOUSE +bool do_statusbar_mouse(void) +{ + /* 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 this function. */ + int mouse_x, mouse_y; + return get_mouseinput(&mouse_x, &mouse_y, TRUE); +} +#endif + +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]) && + statusbar_x < statusbar_xend; statusbar_x++) + ; + if (statusbar_x == statusbar_x_save || + statusbar_x == statusbar_xend) + statusbar_x = 0; + } else +#endif + statusbar_x = 0; +} + +void do_statusbar_end(void) +{ + statusbar_x = statusbar_xend; +} + +void do_statusbar_right(void) +{ + if (statusbar_x < statusbar_xend) + statusbar_x = move_right(answer, statusbar_x); +} + +void do_statusbar_left(void) +{ + if (statusbar_x > 0) + statusbar_x = move_left(answer, statusbar_x); +} + +void do_statusbar_backspace(void) +{ + if (statusbar_x > 0) { + do_statusbar_left(); + do_statusbar_delete(); + } +} + +void do_statusbar_delete(void) +{ + if (statusbar_x < statusbar_xend) { + int char_len = parse_char(answer + statusbar_x, NULL, NULL +#ifdef NANO_WIDE + , NULL +#endif + ); + + charmove(answer + statusbar_x, answer + statusbar_x + char_len, + statusbar_xend - statusbar_x - char_len + 1); + statusbar_xend -= char_len; + } +} + +void do_statusbar_cut_text(void) +{ + null_at(&answer, 0); + statusbar_x = 0; + statusbar_xend = 0; +} + +void do_statusbar_output(int *kbinput, size_t kbinput_len) +{ + size_t i; + + char *key = +#ifdef NANO_WIDE + !ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) : +#endif + charalloc(1); + + assert(answer != NULL); + + for (i = 0; i < kbinput_len; i++) { + int key_len; + + /* Null to newline, if needed. */ + if (kbinput[i] == '\0') + kbinput[i] = '\n'; + /* Newline to Enter, if needed. */ + else if (kbinput[i] == '\n') + /* FIXME: We need to indicate when this happens, so that we + * can break out of the statusbar prompt properly. */ + return; + +#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 + } +#endif + + /* More dangerousness fun =) */ + answer = charealloc(answer, statusbar_xend + key_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; + + do_statusbar_right(); + } + + free(key); +} + /* Return the placewewant associated with current_x. That is, xplustabs * is the zero-based column position of the cursor. Value is no smaller * than current_x. */ @@ -2101,14 +2370,9 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, ) { int kbinput; - bool meta_key, func_key; - static size_t x = (size_t)-1; - /* the cursor position in 'answer' */ - size_t xend; - /* length of 'answer', the status bar text */ + bool meta_key, func_key, s_or_t, finished; bool tabbed = FALSE; /* used by input_tab() */ - const shortcut *t; #ifndef NANO_SMALL /* for history */ @@ -2125,32 +2389,30 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, answer or restored from answer to currentbuf. */ int use_cb = 0; #endif - xend = strlen(def); + statusbar_xend = strlen(def); - /* Only put x at the end of the string if it's uninitialized, if it - would be past the end of the string as it is, or if - resetstatuspos is TRUE. Otherwise, leave it alone. This is so - the cursor position stays at the same place if a prompt-changing - toggle is pressed. */ - if (x == (size_t)-1 || x > xend || resetstatuspos) - x = xend; + /* Only put statusbar_x at the end of the string if it's + * uninitialized, if it would be past the end of the string as it + * is, or if resetstatuspos is TRUE. Otherwise, leave it alone. + * This is so the cursor position stays at the same place if a + * prompt-changing toggle is pressed. */ + if (statusbar_x == (size_t)-1 || statusbar_x > statusbar_xend || + resetstatuspos) + statusbar_x = statusbar_xend; - answer = charealloc(answer, xend + 1); - if (xend > 0) + answer = charealloc(answer, statusbar_xend + 1); + if (statusbar_xend > 0) strcpy(answer, def); else answer[0] = '\0'; -#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE) currshortcut = s; -#endif /* Get the input! */ - nanoget_repaint(buf, answer, x); + nanoget_repaint(buf, answer, statusbar_x); - /* Make sure any editor screen updates are displayed before getting - input */ + /* Refresh the edit window before getting input. */ wnoutrefresh(edit); wrefresh(bottomwin); @@ -2159,105 +2421,22 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, * to files not specified on the command line. In this case, * disable all keys that would change the text if the filename isn't * blank and we're at the "Write File" prompt. */ - while ((kbinput = get_kbinput(bottomwin, &meta_key, &func_key)) != - NANO_CANCEL_KEY && kbinput != NANO_ENTER_KEY) { - for (t = s; t != NULL; t = t->next) { -#ifdef DEBUG - fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput); -#endif + while ((kbinput = do_statusbar_input(&meta_key, &func_key, + &s_or_t, &finished, TRUE)) != NANO_CANCEL_KEY && + kbinput != NANO_ENTER_KEY) { - /* Temporary hack to interpret NANO_HELP_FKEY correctly. */ - if (kbinput == t->funcval) - kbinput = t->ctrlval; - - if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) { - -#ifndef DISABLE_HELP - /* Have to do this here, it would be too late to do it - in statusq() */ - if (kbinput == NANO_HELP_KEY) { - do_help(); - break; - } -#endif -#ifndef NANO_SMALL - /* Have to handle these here too, for the time being */ - if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY) - break; -#endif + /* If we have a shortcut with an associated function, break out + * if we're finished after running the function. */ + if (finished) + break; - return t->ctrlval; - } - } - assert(x <= xend && xend == strlen(answer)); + assert(statusbar_x <= statusbar_xend && + statusbar_xend == strlen(answer)); if (kbinput != '\t') tabbed = FALSE; switch (kbinput) { -#ifndef DISABLE_MOUSE - case KEY_MOUSE: - { - int mouse_x, mouse_y; - get_mouseinput(&mouse_x, &mouse_y, TRUE); - } - break; -#endif - case NANO_REFRESH_KEY: - total_refresh(); - break; - case NANO_HOME_KEY: -#ifndef NANO_SMALL - if (ISSET(SMART_HOME)) { - size_t old_x = x; - - for (x = 0; isblank(answer[x]) && x < xend; x++) - ; - - if (x == old_x || x == xend) - x = 0; - } else -#endif - x = 0; - break; - case NANO_END_KEY: - x = xend; - break; - case NANO_FORWARD_KEY: - if (x < xend) - x++; - break; - case NANO_DELETE_KEY: - /* If we're using restricted mode, the filename isn't blank, - * and we're at the "Write File" prompt, disable Delete. */ - if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) { - if (x < xend) { - charmove(answer + x, answer + x + 1, xend - x); - xend--; - } - } - break; - case NANO_CUT_KEY: - /* If we're using restricted mode, the filename isn't blank, - * and we're at the "Write File" prompt, disable Cut. */ - if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) { - null_at(&answer, 0); - xend = 0; - x = 0; - } - break; - case NANO_BACKSPACE_KEY: - /* If we're using restricted mode, the filename isn't blank, - * and we're at the "Write File" prompt, disable - * Backspace. */ - if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) { - if (x > 0) { - charmove(answer + x - 1, answer + x, xend - x + 1); - x--; - xend--; - } - } - break; case NANO_TAB_KEY: #ifndef NANO_SMALL /* tab history completion */ @@ -2269,8 +2448,8 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, if (history_list->len > 0) { complete = get_history_completion(history_list, answer); - xend = strlen(complete); - x = xend; + statusbar_x = strlen(complete); + statusbar_xend = statusbar_x; answer = mallocstrcpy(answer, complete); } } @@ -2282,18 +2461,15 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, if (allow_tabs) { int shift = 0; - answer = input_tab(answer, x, &tabbed, &shift, list); - xend = strlen(answer); - x += shift; - if (x > xend) - x = xend; + answer = input_tab(answer, statusbar_x, &tabbed, &shift, + list); + statusbar_xend = strlen(answer); + statusbar_x += shift; + if (statusbar_x > statusbar_xend) + statusbar_x = statusbar_xend; } #endif break; - case NANO_BACK_KEY: - if (x > 0) - x--; - break; case NANO_PREVLINE_KEY: #ifndef NANO_SMALL if (history_list != NULL) { @@ -2321,7 +2497,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, answer = mallocstrcpy(answer, currentbuf); free(currentbuf); currentbuf = NULL; - xend = strlen(answer); + statusbar_xend = strlen(answer); use_cb = 0; /* else get older search from the history list and save @@ -2329,12 +2505,12 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, answer */ } else if ((history = get_history_older(history_list)) != NULL) { answer = mallocstrcpy(answer, history); - xend = strlen(history); + statusbar_xend = strlen(history); } else { answer = mallocstrcpy(answer, ""); - xend = 0; + statusbar_xend = 0; } - x = xend; + statusbar_x = statusbar_xend; } #endif break; @@ -2346,7 +2522,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, in answer */ if ((history = get_history_newer(history_list)) != NULL) { answer = mallocstrcpy(answer, history); - xend = strlen(history); + statusbar_xend = strlen(history); /* if there is no newer search, we're here */ @@ -2360,7 +2536,7 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, answer = mallocstrcpy(answer, currentbuf); free(currentbuf); currentbuf = NULL; - xend = strlen(answer); + statusbar_xend = strlen(answer); use_cb = 1; /* otherwise, if currentbuf is NULL and use_cb isn't 2, @@ -2374,53 +2550,24 @@ int nanogetstr(bool allow_tabs, const char *buf, const char *def, currentbuf = mallocstrcpy(currentbuf, answer); answer = mallocstrcpy(answer, ""); } - xend = 0; + statusbar_xend = 0; use_cb = 2; } - x = xend; + statusbar_x = statusbar_xend; } #endif break; - default: - - for (t = s; t != NULL; t = t->next) { -#ifdef DEBUG - fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, - kbinput); -#endif - if (meta_key && (kbinput == t->metaval || kbinput == t->miscval)) - /* We hit a meta key. Do like above. We don't - * just put back the letter and let it get - * caught above cause that screws the - * keypad... */ - return kbinput; - } - - /* If we're using restricted mode, the filename isn't blank, - * and we're at the "Write File" prompt, act as though the - * unhandled character we got is a control character and - * throw it away. */ - if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list)) - break; - answer = charealloc(answer, xend + 2); - charmove(answer + x + 1, answer + x, xend - x + 1); - xend++; - answer[x] = kbinput; - x++; - -#ifdef DEBUG - fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput); -#endif - } /* switch (kbinput) */ + } #ifndef NANO_SMALL last_kbinput = kbinput; #endif - nanoget_repaint(buf, answer, x); + nanoget_repaint(buf, answer, statusbar_x); wrefresh(bottomwin); - } /* while (kbinput ...) */ + } - /* We finished putting in an answer; reset x */ - x = (size_t)-1; + /* We finished putting in an answer, so reset statusbar_x. */ + if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY) + statusbar_x = (size_t)-1; return kbinput; } @@ -2464,36 +2611,6 @@ int statusq(bool allow_tabs, const shortcut *s, const char *def, resetstatuspos = FALSE; switch (ret) { - case NANO_FIRSTLINE_KEY: - case NANO_FIRSTLINE_FKEY: - do_first_line(); - resetstatuspos = TRUE; - break; - case NANO_LASTLINE_KEY: - case NANO_LASTLINE_FKEY: - do_last_line(); - resetstatuspos = TRUE; - break; -#ifndef DISABLE_JUSTIFY - case NANO_PARABEGIN_KEY: - case NANO_PARABEGIN_ALTKEY1: - case NANO_PARABEGIN_ALTKEY2: - do_para_begin(); - resetstatuspos = TRUE; - break; - case NANO_PARAEND_KEY: - case NANO_PARAEND_ALTKEY1: - case NANO_PARAEND_ALTKEY2: - do_para_end(); - resetstatuspos = TRUE; - break; - case NANO_FULLJUSTIFY_KEY: - case NANO_FULLJUSTIFY_ALTKEY: - if (!ISSET(VIEW_MODE)) - do_full_justify(); - resetstatuspos = TRUE; - break; -#endif case NANO_CANCEL_KEY: ret = -1; resetstatuspos = TRUE; -- 2.39.5