move functions specific to the statusbar prompt to their own source

file, prompt.c, and adjust related variables accordingly


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@3065 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
master
David Lawrence Ramsey 2005-11-01 17:37:44 +00:00
parent 81c4e187f5
commit d24d0a43e8
5 changed files with 930 additions and 884 deletions

View File

@ -17,6 +17,17 @@ CVS code -
get_page_start(). (DLR)
- Move xplustabs(), actual_x(), strnlenpt(), and strlenpt() from
winio.c to utils.c, as they're really utility functions. (DLR)
- Move functions specific to the statusbar prompt to their own
source file, and adjust related variables accordingly. New
file prompt.c; changes to do_statusbar_input(),
do_statusbar_mouse(), do_statusbar_output(),
do_statusbar_home(), do_statusbar_end(), do_statusbar_right(),
do_statusbar_left(), do_statusbar_backspace(),
do_statusbar_delete(), do_statusbar_cut_text(),
do_statusbar_next_word(), do_statusbar_prev_word(),
do_statusbar_verbatim_input(), statusbar_xplustabs(),
get_statusbar_page_start(), nanoget_repaint(), nanogetstr(),
statusq(), and statusq_abort() (all moved to prompt.c). (DLR)
- nano.h:
- Readd MIN_EDITOR_COLS #define. (DLR)
- winio.c:
@ -28,6 +39,8 @@ CVS code -
- doc/nanorc.sample:
- Tweak the "c-file" regex for characters to properly accept
'\"' and reject '"' and '''. (DLR)
- src/Makefile.am:
- Add prompt.c to nano_SOURCES. (DLR)
GNU nano 1.3.9 - 2005.10.23
- General:

View File

@ -12,6 +12,7 @@ nano_SOURCES = chars.c \
move.c \
nano.c \
nano.h \
prompt.c \
proto.h \
rcfile.c \
search.c \

877
src/prompt.c Normal file
View File

@ -0,0 +1,877 @@
/* $Id$ */
/**************************************************************************
* prompt.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., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301, USA. *
* *
**************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdarg.h>
#include <string.h>
#include "proto.h"
static char *prompt = NULL;
/* The prompt string for statusbar
* questions. */
static size_t statusbar_x = (size_t)-1;
/* The cursor position in answer. */
static bool resetstatuspos = FALSE;
/* Should we reset the cursor position
* at the statusbar prompt? */
int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
bool *ran_func, 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;
*ran_func = 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 == TRUE && input == KEY_MOUSE) {
if (do_statusbar_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 ||
#ifndef NANO_SMALL
input == NANO_NEXTWORD_KEY ||
#endif
(*meta_key == TRUE && (
#ifndef NANO_SMALL
input == NANO_PREVWORD_KEY ||
#endif
input == NANO_VERBATIM_KEY)));
/* Set s_or_t to TRUE if we got a shortcut. */
*s_or_t = have_shortcut;
if (allow_funcs) {
/* If we got a character, and it isn't a shortcut or toggle,
* 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) {
/* 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) || openfile->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_key_buffer_len() == 0) {
if (kbinput != NULL) {
/* Display all the characters in the input buffer at
* once, filtering out control characters. */
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,
FALSE);
free(output);
/* 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) || openfile->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) || openfile->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) || openfile->filename[0] ==
'\0' || currshortcut != writefile_list)
do_statusbar_cut_text();
break;
#ifndef NANO_SMALL
case NANO_NEXTWORD_KEY:
do_statusbar_next_word(FALSE);
break;
case NANO_PREVWORD_KEY:
if (*meta_key == TRUE)
do_statusbar_prev_word(FALSE);
break;
#endif
case NANO_VERBATIM_KEY:
if (*meta_key == TRUE) {
/* If we're using restricted mode, the filename
* isn't blank, and we're at the "Write File"
* prompt, disable verbatim input. */
if (!ISSET(RESTRICTED) ||
openfile->filename[0] == '\0' ||
currshortcut != writefile_list) {
bool got_enter;
/* Whether we got the Enter key. */
do_statusbar_verbatim_input(&got_enter);
/* If we got the Enter key, set input to the
* key value for Enter, and set finished to
* TRUE to indicate that we're done. */
if (got_enter) {
input = NANO_ENTER_KEY;
*finished = TRUE;
}
}
break;
}
/* Handle the normal statusbar prompt shortcuts, setting
* ran_func to TRUE if we try to run their associated
* functions and setting finished to TRUE to indicate
* that we're done after trying to run their associated
* functions. */
default:
if (s->func != NULL) {
*ran_func = TRUE;
if (!ISSET(VIEW_MODE) || s->viewok)
s->func();
}
*finished = TRUE;
}
}
}
return input;
}
#ifndef DISABLE_MOUSE
bool do_statusbar_mouse(void)
{
int mouse_x, mouse_y;
bool retval = get_mouseinput(&mouse_x, &mouse_y, TRUE);
if (!retval) {
/* We can click in the statusbar window text to move the
* cursor. */
if (wenclose(bottomwin, mouse_y, mouse_x)) {
size_t start_col = strlenpt(prompt) + 1;
/* Subtract out the sizes of topwin and edit. */
mouse_y -= (2 - no_more_space()) + editwinrows;
/* Move to where the click occurred. */
if (mouse_x > start_col && mouse_y == 0) {
statusbar_x = actual_x(answer,
get_statusbar_page_start(start_col, start_col +
statusbar_xplustabs()) + mouse_x - start_col -
1);
nanoget_repaint(answer, statusbar_x);
}
}
}
return retval;
}
#endif
/* The user typed output_len multibyte characters. Add them to the
* statusbar prompt, setting got_enter to TRUE if we get a newline, and
* filtering out all control characters if allow_cntrls is TRUE. */
void do_statusbar_output(char *output, size_t output_len, bool
*got_enter, bool allow_cntrls)
{
size_t answer_len, i = 0;
char *char_buf = charalloc(mb_cur_max());
int char_buf_len;
assert(answer != NULL);
answer_len = strlen(answer);
*got_enter = FALSE;
while (i < output_len) {
/* If allow_cntrls is FALSE, filter out nulls and newlines,
* since they're control characters. */
if (allow_cntrls) {
/* Null to newline, if needed. */
if (output[i] == '\0')
output[i] = '\n';
/* Newline to Enter, if needed. */
else if (output[i] == '\n') {
/* Set got_enter to TRUE to indicate that we got the
* Enter 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(output + i, output_len - i);
return;
}
}
/* Interpret the next multibyte character. */
char_buf_len = parse_mbchar(output + i, char_buf, NULL);
i += char_buf_len;
/* If allow_cntrls is FALSE, filter out a control character. */
if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
continue;
/* More dangerousness fun =) */
answer = charealloc(answer, answer_len + (char_buf_len * 2));
assert(statusbar_x <= answer_len);
charmove(&answer[statusbar_x + char_buf_len],
&answer[statusbar_x], answer_len - statusbar_x +
char_buf_len);
strncpy(&answer[statusbar_x], char_buf, char_buf_len);
answer_len += char_buf_len;
statusbar_x += char_buf_len;
}
free(char_buf);
}
void do_statusbar_home(void)
{
#ifndef NANO_SMALL
if (ISSET(SMART_HOME)) {
size_t statusbar_x_save = statusbar_x;
statusbar_x = indent_length(answer);
if (statusbar_x == statusbar_x_save ||
statusbar_x == strlen(answer))
statusbar_x = 0;
} else
#endif
statusbar_x = 0;
}
void do_statusbar_end(void)
{
statusbar_x = strlen(answer);
}
void do_statusbar_right(void)
{
if (statusbar_x < strlen(answer))
statusbar_x = move_mbright(answer, statusbar_x);
}
void do_statusbar_left(void)
{
if (statusbar_x > 0)
statusbar_x = move_mbleft(answer, statusbar_x);
}
void do_statusbar_backspace(void)
{
if (statusbar_x > 0) {
do_statusbar_left();
do_statusbar_delete();
}
}
void do_statusbar_delete(void)
{
if (answer[statusbar_x] != '\0') {
int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
NULL);
size_t line_len = strlen(answer + statusbar_x);
assert(statusbar_x < strlen(answer));
charmove(answer + statusbar_x, answer + statusbar_x +
char_buf_len, strlen(answer) - statusbar_x -
char_buf_len + 1);
null_at(&answer, statusbar_x + line_len - char_buf_len);
}
}
/* Move text from the statusbar prompt into oblivion. */
void do_statusbar_cut_text(void)
{
assert(answer != NULL);
#ifndef NANO_SMALL
if (ISSET(CUT_TO_END))
null_at(&answer, statusbar_x);
else {
#endif
null_at(&answer, 0);
statusbar_x = 0;
#ifndef NANO_SMALL
}
#endif
}
#ifndef NANO_SMALL
/* Move to the next word at the statusbar prompt. If allow_punct is
* TRUE, treat punctuation as part of a word. Return TRUE if we started
* on a word, and FALSE otherwise. */
bool do_statusbar_next_word(bool allow_punct)
{
char *char_mb;
int char_mb_len;
bool end_line = FALSE, started_on_word = FALSE;
assert(answer != NULL);
char_mb = charalloc(mb_cur_max());
/* Move forward until we find the character after the last letter of
* the current word. */
while (!end_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);
/* If we've found it, stop moving forward through the current
* line. */
if (!is_word_mbchar(char_mb, allow_punct))
break;
/* If we haven't found it, then we've started on a word, so set
* started_on_word to TRUE. */
started_on_word = TRUE;
if (answer[statusbar_x] == '\0')
end_line = TRUE;
else
statusbar_x += char_mb_len;
}
/* Move forward until we find the first letter of the next word. */
if (answer[statusbar_x] == '\0')
end_line = TRUE;
else
statusbar_x += char_mb_len;
while (!end_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);
/* If we've found it, stop moving forward through the current
* line. */
if (is_word_mbchar(char_mb, allow_punct))
break;
if (answer[statusbar_x] == '\0')
end_line = TRUE;
else
statusbar_x += char_mb_len;
}
free(char_mb);
/* Return whether we started on a word. */
return started_on_word;
}
/* Move to the previous word at the statusbar prompt. If allow_punct is
* TRUE, treat punctuation as part of a word. Return TRUE if we started
* on a word, and FALSE otherwise. */
bool do_statusbar_prev_word(bool allow_punct)
{
char *char_mb;
int char_mb_len;
bool begin_line = FALSE, started_on_word = FALSE;
assert(answer != NULL);
char_mb = charalloc(mb_cur_max());
/* Move backward until we find the character before the first letter
* of the current word. */
while (!begin_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);
/* If we've found it, stop moving backward through the current
* line. */
if (!is_word_mbchar(char_mb, allow_punct))
break;
/* If we haven't found it, then we've started on a word, so set
* started_on_word to TRUE. */
started_on_word = TRUE;
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
}
/* Move backward until we find the last letter of the previous
* word. */
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
while (!begin_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);
/* If we've found it, stop moving backward through the current
* line. */
if (is_word_mbchar(char_mb, allow_punct))
break;
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
}
/* If we've found it, move backward until we find the character
* before the first letter of the previous word. */
if (!begin_line) {
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
while (!begin_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
NULL);
/* If we've found it, stop moving backward through the
* current line. */
if (!is_word_mbchar(char_mb, allow_punct))
break;
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
}
/* If we've found it, move forward to the first letter of the
* previous word. */
if (!begin_line)
statusbar_x += char_mb_len;
}
free(char_mb);
/* Return whether we started on a word. */
return started_on_word;
}
#endif /* !NANO_SMALL */
void do_statusbar_verbatim_input(bool *got_enter)
{
int *kbinput;
size_t kbinput_len, i;
char *output;
*got_enter = FALSE;
/* Read in all the verbatim characters. */
kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
/* Display all the verbatim characters at once, not filtering out
* control characters. */
output = charalloc(kbinput_len + 1);
for (i = 0; i < kbinput_len; i++)
output[i] = (char)kbinput[i];
output[i] = '\0';
do_statusbar_output(output, kbinput_len, got_enter, TRUE);
free(output);
}
/* Return the placewewant associated with statusbar_x, i.e, the
* zero-based column position of the cursor. The value will be no
* smaller than statusbar_x. */
size_t statusbar_xplustabs(void)
{
return strnlenpt(answer, statusbar_x);
}
/* nano scrolls horizontally within a line in chunks. This function
* returns the column number of the first character displayed in the
* statusbar prompt when the cursor is at the given column with the
* prompt ending at start_col. Note that (0 <= column -
* get_statusbar_page_start(column) < COLS). */
size_t get_statusbar_page_start(size_t start_col, size_t column)
{
if (column == start_col || column < COLS - 1)
return 0;
else
return column - start_col - (column - start_col) % (COLS -
start_col - 1);
}
/* Repaint the statusbar when getting a character in nanogetstr(). Note
* that we must turn on A_REVERSE here, since do_help() turns it off! */
void nanoget_repaint(const char *buf, size_t x)
{
size_t start_col, xpt, page_start;
char *expanded;
assert(x <= strlen(buf));
start_col = strlenpt(prompt) + 1;
xpt = strnlenpt(buf, x);
page_start = get_statusbar_page_start(start_col, start_col + xpt);
wattron(bottomwin, A_REVERSE);
blank_statusbar();
mvwaddnstr(bottomwin, 0, 0, prompt, actual_x(prompt, COLS - 2));
waddch(bottomwin, ':');
waddch(bottomwin, (page_start == 0) ? ' ' : '$');
expanded = display_string(buf, page_start, COLS - start_col - 1,
FALSE);
waddstr(bottomwin, expanded);
free(expanded);
wmove(bottomwin, 0, start_col + xpt + 1 - page_start);
wattroff(bottomwin, A_REVERSE);
}
/* Get the input from the keyboard; this should only be called from
* statusq(). */
int nanogetstr(bool allow_tabs, const char *curranswer,
#ifndef NANO_SMALL
filestruct **history_list,
#endif
const shortcut *s
#ifndef DISABLE_TABCOMP
, bool *list
#endif
)
{
int kbinput;
bool meta_key, func_key, s_or_t, ran_func, finished;
size_t curranswer_len;
#ifndef DISABLE_TABCOMP
bool tabbed = FALSE;
/* Whether we've pressed Tab. */
#endif
#ifndef NANO_SMALL
char *history = NULL;
/* The current history string. */
char *magichistory = NULL;
/* The temporary string typed at the bottom of the history, if
* any. */
#ifndef DISABLE_TABCOMP
int last_kbinput = ERR;
/* The key we pressed before the current key. */
size_t complete_len = 0;
/* The length of the original string that we're trying to
* tab complete, if any. */
#endif
#endif /* !NANO_SMALL */
answer = mallocstrcpy(answer, curranswer);
curranswer_len = strlen(answer);
/* Only put statusbar_x at the end of the string if it's
* uninitialized, if it would be past the end of curranswer, 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 > curranswer_len ||
resetstatuspos)
statusbar_x = curranswer_len;
currshortcut = s;
nanoget_repaint(answer, statusbar_x);
/* Refresh the edit window and the statusbar before getting
* input. */
wnoutrefresh(edit);
wnoutrefresh(bottomwin);
/* If we're using restricted mode, we aren't allowed to change the
* name of a file once it has one because that would allow writing
* 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 = do_statusbar_input(&meta_key, &func_key,
&s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
kbinput != NANO_ENTER_KEY) {
assert(statusbar_x <= strlen(answer));
#ifndef DISABLE_TABCOMP
if (kbinput != NANO_TAB_KEY)
tabbed = FALSE;
#endif
switch (kbinput) {
case NANO_TAB_KEY:
#ifndef DISABLE_TABCOMP
#ifndef NANO_SMALL
if (history_list != NULL) {
if (last_kbinput != NANO_TAB_KEY)
complete_len = strlen(answer);
if (complete_len > 0) {
answer = mallocstrcpy(answer,
get_history_completion(history_list,
answer, complete_len));
statusbar_x = strlen(answer);
}
} else
#endif /* !NANO_SMALL */
if (allow_tabs)
answer = input_tab(answer, &statusbar_x, &tabbed,
list);
#endif /* !DISABLE_TABCOMP */
break;
case NANO_PREVLINE_KEY:
#ifndef NANO_SMALL
if (history_list != NULL) {
/* If we're scrolling up at the bottom of the
* history list and answer isn't blank, save answer
* in magichistory. */
if ((*history_list)->next == NULL &&
answer[0] != '\0')
magichistory = mallocstrcpy(magichistory,
answer);
/* Get the older search from the history list and
* save it in answer. If there is no older search,
* don't do anything. */
if ((history =
get_history_older(history_list)) != NULL) {
answer = mallocstrcpy(answer, history);
statusbar_x = strlen(answer);
}
/* This key has a shortcut list entry when it's used
* to move to an older search, which means that
* finished has been set to TRUE. Set it back to
* FALSE here, so that we aren't kicked out of the
* statusbar prompt. */
finished = FALSE;
}
#endif /* !NANO_SMALL */
break;
case NANO_NEXTLINE_KEY:
#ifndef NANO_SMALL
if (history_list != NULL) {
/* Get the newer search from the history list and
* save it in answer. If there is no newer search,
* don't do anything. */
if ((history =
get_history_newer(history_list)) != NULL) {
answer = mallocstrcpy(answer, history);
statusbar_x = strlen(answer);
}
/* If, after scrolling down, we're at the bottom of
* the history list, answer is blank, and
* magichistory is set, save magichistory in
* answer. */
if ((*history_list)->next == NULL &&
answer[0] == '\0' && magichistory != NULL) {
answer = mallocstrcpy(answer, magichistory);
statusbar_x = strlen(answer);
}
}
#endif /* !NANO_SMALL */
break;
}
/* If we have a shortcut with an associated function, break out
* if we're finished after running or trying to run the
* function. */
if (finished)
break;
#if !defined(NANO_SMALL) && !defined(DISABLE_TABCOMP)
last_kbinput = kbinput;
#endif
nanoget_repaint(answer, statusbar_x);
wnoutrefresh(bottomwin);
}
#ifndef NANO_SMALL
/* Set the current position in the history list to the bottom and
* free magichistory, if we need to. */
if (history_list != NULL) {
history_reset(*history_list);
if (magichistory != NULL)
free(magichistory);
}
#endif
/* We finished putting in an answer or ran a normal shortcut's
* associated function, so reset statusbar_x. */
if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
ran_func)
statusbar_x = (size_t)-1;
return kbinput;
}
/* Ask a question on the statusbar. Answer will be stored in answer
* global. Returns -1 on aborted enter, -2 on a blank string, and 0
* otherwise, the valid shortcut key caught. curranswer is any editable
* text that we want to put up by default.
*
* The allow_tabs parameter indicates whether we should allow tabs to be
* interpreted. */
int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
#ifndef NANO_SMALL
filestruct **history_list,
#endif
const char *msg, ...)
{
va_list ap;
int retval;
#ifndef DISABLE_TABCOMP
bool list = FALSE;
#endif
prompt = charealloc(prompt, ((COLS - 4) * mb_cur_max()) + 1);
bottombars(s);
va_start(ap, msg);
vsnprintf(prompt, (COLS - 4) * mb_cur_max(), msg, ap);
va_end(ap);
null_at(&prompt, actual_x(prompt, COLS - 4));
retval = nanogetstr(allow_tabs, curranswer,
#ifndef NANO_SMALL
history_list,
#endif
s
#ifndef DISABLE_TABCOMP
, &list
#endif
);
resetstatuspos = FALSE;
switch (retval) {
case NANO_CANCEL_KEY:
retval = -1;
resetstatuspos = TRUE;
break;
case NANO_ENTER_KEY:
retval = (answer[0] == '\0') ? -2 : 0;
resetstatuspos = TRUE;
break;
}
blank_statusbar();
wnoutrefresh(bottomwin);
#ifdef DEBUG
fprintf(stderr, "answer = \"%s\"\n", answer);
#endif
#ifndef DISABLE_TABCOMP
/* If we've done tab completion, there might be a list of filename
* matches on the edit window at this point. Make sure that they're
* cleared off. */
if (list)
edit_refresh();
#endif
return retval;
}
void statusq_abort(void)
{
resetstatuspos = TRUE;
}

View File

@ -416,6 +416,45 @@ bool do_mouse(void);
#endif
void do_output(char *output, size_t output_len, bool allow_cntrls);
/* Public functions in prompt.c. */
int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
bool *ran_func, bool *finished, bool allow_funcs);
#ifndef DISABLE_MOUSE
bool do_statusbar_mouse(void);
#endif
void do_statusbar_output(char *output, size_t output_len, bool
*got_enter, bool allow_cntrls);
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);
#ifndef NANO_SMALL
bool do_statusbar_next_word(bool allow_punct);
bool do_statusbar_prev_word(bool allow_punct);
#endif
void do_statusbar_verbatim_input(bool *got_enter);
size_t statusbar_xplustabs(void);
size_t get_statusbar_page_start(size_t start_col, size_t column);
void nanoget_repaint(const char *buf, size_t x);
int nanogetstr(bool allow_tabs, const char *curranswer,
#ifndef NANO_SMALL
filestruct **history_list,
#endif
const shortcut *s
#ifndef DISABLE_TABCOMP
, bool *list
#endif
);
int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
#ifndef NANO_SMALL
filestruct **history_list,
#endif
const char *msg, ...);
void statusq_abort(void);
/* Public functions in rcfile.c. */
#ifdef ENABLE_NANORC
void rcfile_error(const char *msg, ...);
@ -617,27 +656,6 @@ 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 *ran_func, bool *finished, bool allow_funcs);
#ifndef DISABLE_MOUSE
bool do_statusbar_mouse(void);
#endif
void do_statusbar_output(char *output, size_t output_len, bool
*got_enter, bool allow_cntrls);
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);
#ifndef NANO_SMALL
bool do_statusbar_next_word(bool allow_punct);
bool do_statusbar_prev_word(bool allow_punct);
#endif
void do_statusbar_verbatim_input(bool *got_enter);
size_t statusbar_xplustabs(void);
size_t get_statusbar_page_start(size_t start_col, size_t column);
void blank_line(WINDOW *win, int y, int x, int n);
void blank_titlebar(void);
void blank_topbar(void);
@ -647,22 +665,6 @@ void blank_bottombars(void);
void check_statusblank(void);
char *display_string(const char *buf, size_t start_col, size_t len, bool
dollars);
void nanoget_repaint(const char *buf, size_t x);
int nanogetstr(bool allow_tabs, const char *curranswer,
#ifndef NANO_SMALL
filestruct **history_list,
#endif
const shortcut *s
#ifndef DISABLE_TABCOMP
, bool *list
#endif
);
int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
#ifndef NANO_SMALL
filestruct **history_list,
#endif
const char *msg, ...);
void statusq_abort(void);
void titlebar(const char *path);
void set_modified(void);
void statusbar(const char *msg, ...);

View File

@ -38,11 +38,6 @@ static int *key_buffer = NULL;
static size_t key_buffer_len = 0;
/* The length of the default keystroke
* buffer. */
static char *prompt = NULL;
/* The prompt string for statusbar
* questions. */
static size_t statusbar_x = (size_t)-1;
/* The cursor position in answer. */
static int statusblank = 0;
/* The number of keystrokes left after
* we call statusbar(), before we
@ -50,9 +45,6 @@ static int statusblank = 0;
static bool disable_cursorpos = FALSE;
/* Should we temporarily disable
* constant cursor position display? */
static bool resetstatuspos = FALSE;
/* Should we reset the cursor position
* at the statusbar prompt? */
/* Control character compatibility:
*
@ -1667,559 +1659,6 @@ 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 *ran_func, 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;
*ran_func = 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 == TRUE && input == KEY_MOUSE) {
if (do_statusbar_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 ||
#ifndef NANO_SMALL
input == NANO_NEXTWORD_KEY ||
#endif
(*meta_key == TRUE && (
#ifndef NANO_SMALL
input == NANO_PREVWORD_KEY ||
#endif
input == NANO_VERBATIM_KEY)));
/* Set s_or_t to TRUE if we got a shortcut. */
*s_or_t = have_shortcut;
if (allow_funcs) {
/* If we got a character, and it isn't a shortcut or toggle,
* 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) {
/* 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) || openfile->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_key_buffer_len() == 0) {
if (kbinput != NULL) {
/* Display all the characters in the input buffer at
* once, filtering out control characters. */
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,
FALSE);
free(output);
/* 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) || openfile->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) || openfile->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) || openfile->filename[0] ==
'\0' || currshortcut != writefile_list)
do_statusbar_cut_text();
break;
#ifndef NANO_SMALL
case NANO_NEXTWORD_KEY:
do_statusbar_next_word(FALSE);
break;
case NANO_PREVWORD_KEY:
if (*meta_key == TRUE)
do_statusbar_prev_word(FALSE);
break;
#endif
case NANO_VERBATIM_KEY:
if (*meta_key == TRUE) {
/* If we're using restricted mode, the filename
* isn't blank, and we're at the "Write File"
* prompt, disable verbatim input. */
if (!ISSET(RESTRICTED) ||
openfile->filename[0] == '\0' ||
currshortcut != writefile_list) {
bool got_enter;
/* Whether we got the Enter key. */
do_statusbar_verbatim_input(&got_enter);
/* If we got the Enter key, set input to the
* key value for Enter, and set finished to
* TRUE to indicate that we're done. */
if (got_enter) {
input = NANO_ENTER_KEY;
*finished = TRUE;
}
}
break;
}
/* Handle the normal statusbar prompt shortcuts, setting
* ran_func to TRUE if we try to run their associated
* functions and setting finished to TRUE to indicate
* that we're done after trying to run their associated
* functions. */
default:
if (s->func != NULL) {
*ran_func = TRUE;
if (!ISSET(VIEW_MODE) || s->viewok)
s->func();
}
*finished = TRUE;
}
}
}
return input;
}
#ifndef DISABLE_MOUSE
bool do_statusbar_mouse(void)
{
int mouse_x, mouse_y;
bool retval = get_mouseinput(&mouse_x, &mouse_y, TRUE);
if (!retval) {
/* We can click in the statusbar window text to move the
* cursor. */
if (wenclose(bottomwin, mouse_y, mouse_x)) {
size_t start_col = strlenpt(prompt) + 1;
/* Subtract out the sizes of topwin and edit. */
mouse_y -= (2 - no_more_space()) + editwinrows;
/* Move to where the click occurred. */
if (mouse_x > start_col && mouse_y == 0) {
statusbar_x = actual_x(answer,
get_statusbar_page_start(start_col, start_col +
statusbar_xplustabs()) + mouse_x - start_col -
1);
nanoget_repaint(answer, statusbar_x);
}
}
}
return retval;
}
#endif
/* The user typed output_len multibyte characters. Add them to the
* statusbar prompt, setting got_enter to TRUE if we get a newline, and
* filtering out all control characters if allow_cntrls is TRUE. */
void do_statusbar_output(char *output, size_t output_len, bool
*got_enter, bool allow_cntrls)
{
size_t answer_len, i = 0;
char *char_buf = charalloc(mb_cur_max());
int char_buf_len;
assert(answer != NULL);
answer_len = strlen(answer);
*got_enter = FALSE;
while (i < output_len) {
/* If allow_cntrls is FALSE, filter out nulls and newlines,
* since they're control characters. */
if (allow_cntrls) {
/* Null to newline, if needed. */
if (output[i] == '\0')
output[i] = '\n';
/* Newline to Enter, if needed. */
else if (output[i] == '\n') {
/* Set got_enter to TRUE to indicate that we got the
* Enter 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(output + i, output_len - i);
return;
}
}
/* Interpret the next multibyte character. */
char_buf_len = parse_mbchar(output + i, char_buf, NULL);
i += char_buf_len;
/* If allow_cntrls is FALSE, filter out a control character. */
if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
continue;
/* More dangerousness fun =) */
answer = charealloc(answer, answer_len + (char_buf_len * 2));
assert(statusbar_x <= answer_len);
charmove(&answer[statusbar_x + char_buf_len],
&answer[statusbar_x], answer_len - statusbar_x +
char_buf_len);
strncpy(&answer[statusbar_x], char_buf, char_buf_len);
answer_len += char_buf_len;
statusbar_x += char_buf_len;
}
free(char_buf);
}
void do_statusbar_home(void)
{
#ifndef NANO_SMALL
if (ISSET(SMART_HOME)) {
size_t statusbar_x_save = statusbar_x;
statusbar_x = indent_length(answer);
if (statusbar_x == statusbar_x_save ||
statusbar_x == strlen(answer))
statusbar_x = 0;
} else
#endif
statusbar_x = 0;
}
void do_statusbar_end(void)
{
statusbar_x = strlen(answer);
}
void do_statusbar_right(void)
{
if (statusbar_x < strlen(answer))
statusbar_x = move_mbright(answer, statusbar_x);
}
void do_statusbar_left(void)
{
if (statusbar_x > 0)
statusbar_x = move_mbleft(answer, statusbar_x);
}
void do_statusbar_backspace(void)
{
if (statusbar_x > 0) {
do_statusbar_left();
do_statusbar_delete();
}
}
void do_statusbar_delete(void)
{
if (answer[statusbar_x] != '\0') {
int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
NULL);
size_t line_len = strlen(answer + statusbar_x);
assert(statusbar_x < strlen(answer));
charmove(answer + statusbar_x, answer + statusbar_x +
char_buf_len, strlen(answer) - statusbar_x -
char_buf_len + 1);
null_at(&answer, statusbar_x + line_len - char_buf_len);
}
}
/* Move text from the statusbar prompt into oblivion. */
void do_statusbar_cut_text(void)
{
assert(answer != NULL);
#ifndef NANO_SMALL
if (ISSET(CUT_TO_END))
null_at(&answer, statusbar_x);
else {
#endif
null_at(&answer, 0);
statusbar_x = 0;
#ifndef NANO_SMALL
}
#endif
}
#ifndef NANO_SMALL
/* Move to the next word at the statusbar prompt. If allow_punct is
* TRUE, treat punctuation as part of a word. Return TRUE if we started
* on a word, and FALSE otherwise. */
bool do_statusbar_next_word(bool allow_punct)
{
char *char_mb;
int char_mb_len;
bool end_line = FALSE, started_on_word = FALSE;
assert(answer != NULL);
char_mb = charalloc(mb_cur_max());
/* Move forward until we find the character after the last letter of
* the current word. */
while (!end_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);
/* If we've found it, stop moving forward through the current
* line. */
if (!is_word_mbchar(char_mb, allow_punct))
break;
/* If we haven't found it, then we've started on a word, so set
* started_on_word to TRUE. */
started_on_word = TRUE;
if (answer[statusbar_x] == '\0')
end_line = TRUE;
else
statusbar_x += char_mb_len;
}
/* Move forward until we find the first letter of the next word. */
if (answer[statusbar_x] == '\0')
end_line = TRUE;
else
statusbar_x += char_mb_len;
while (!end_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);
/* If we've found it, stop moving forward through the current
* line. */
if (is_word_mbchar(char_mb, allow_punct))
break;
if (answer[statusbar_x] == '\0')
end_line = TRUE;
else
statusbar_x += char_mb_len;
}
free(char_mb);
/* Return whether we started on a word. */
return started_on_word;
}
/* Move to the previous word at the statusbar prompt. If allow_punct is
* TRUE, treat punctuation as part of a word. Return TRUE if we started
* on a word, and FALSE otherwise. */
bool do_statusbar_prev_word(bool allow_punct)
{
char *char_mb;
int char_mb_len;
bool begin_line = FALSE, started_on_word = FALSE;
assert(answer != NULL);
char_mb = charalloc(mb_cur_max());
/* Move backward until we find the character before the first letter
* of the current word. */
while (!begin_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);
/* If we've found it, stop moving backward through the current
* line. */
if (!is_word_mbchar(char_mb, allow_punct))
break;
/* If we haven't found it, then we've started on a word, so set
* started_on_word to TRUE. */
started_on_word = TRUE;
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
}
/* Move backward until we find the last letter of the previous
* word. */
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
while (!begin_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL);
/* If we've found it, stop moving backward through the current
* line. */
if (is_word_mbchar(char_mb, allow_punct))
break;
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
}
/* If we've found it, move backward until we find the character
* before the first letter of the previous word. */
if (!begin_line) {
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
while (!begin_line) {
char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
NULL);
/* If we've found it, stop moving backward through the
* current line. */
if (!is_word_mbchar(char_mb, allow_punct))
break;
if (statusbar_x == 0)
begin_line = TRUE;
else
statusbar_x = move_mbleft(answer, statusbar_x);
}
/* If we've found it, move forward to the first letter of the
* previous word. */
if (!begin_line)
statusbar_x += char_mb_len;
}
free(char_mb);
/* Return whether we started on a word. */
return started_on_word;
}
#endif /* !NANO_SMALL */
void do_statusbar_verbatim_input(bool *got_enter)
{
int *kbinput;
size_t kbinput_len, i;
char *output;
*got_enter = FALSE;
/* Read in all the verbatim characters. */
kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
/* Display all the verbatim characters at once, not filtering out
* control characters. */
output = charalloc(kbinput_len + 1);
for (i = 0; i < kbinput_len; i++)
output[i] = (char)kbinput[i];
output[i] = '\0';
do_statusbar_output(output, kbinput_len, got_enter, TRUE);
free(output);
}
/* Return the placewewant associated with statusbar_x, i.e, the
* zero-based column position of the cursor. The value will be no
* smaller than statusbar_x. */
size_t statusbar_xplustabs(void)
{
return strnlenpt(answer, statusbar_x);
}
/* nano scrolls horizontally within a line in chunks. This function
* returns the column number of the first character displayed in the
* statusbar prompt when the cursor is at the given column with the
* prompt ending at start_col. Note that (0 <= column -
* get_statusbar_page_start(column) < COLS). */
size_t get_statusbar_page_start(size_t start_col, size_t column)
{
if (column == start_col || column < COLS - 1)
return 0;
else
return column - start_col - (column - start_col) % (COLS -
start_col - 1);
}
/* Move to (x, y) in win, and display a line of n spaces with the
* current attributes. */
void blank_line(WINDOW *win, int y, int x, int n)
@ -2434,292 +1873,6 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
return converted;
}
/* Repaint the statusbar when getting a character in nanogetstr(). Note
* that we must turn on A_REVERSE here, since do_help() turns it off! */
void nanoget_repaint(const char *buf, size_t x)
{
size_t start_col, xpt, page_start;
char *expanded;
assert(x <= strlen(buf));
start_col = strlenpt(prompt) + 1;
xpt = strnlenpt(buf, x);
page_start = get_statusbar_page_start(start_col, start_col + xpt);
wattron(bottomwin, A_REVERSE);
blank_statusbar();
mvwaddnstr(bottomwin, 0, 0, prompt, actual_x(prompt, COLS - 2));
waddch(bottomwin, ':');
waddch(bottomwin, (page_start == 0) ? ' ' : '$');
expanded = display_string(buf, page_start, COLS - start_col - 1,
FALSE);
waddstr(bottomwin, expanded);
free(expanded);
wmove(bottomwin, 0, start_col + xpt + 1 - page_start);
wattroff(bottomwin, A_REVERSE);
}
/* Get the input from the keyboard; this should only be called from
* statusq(). */
int nanogetstr(bool allow_tabs, const char *curranswer,
#ifndef NANO_SMALL
filestruct **history_list,
#endif
const shortcut *s
#ifndef DISABLE_TABCOMP
, bool *list
#endif
)
{
int kbinput;
bool meta_key, func_key, s_or_t, ran_func, finished;
size_t curranswer_len;
#ifndef DISABLE_TABCOMP
bool tabbed = FALSE;
/* Whether we've pressed Tab. */
#endif
#ifndef NANO_SMALL
char *history = NULL;
/* The current history string. */
char *magichistory = NULL;
/* The temporary string typed at the bottom of the history, if
* any. */
#ifndef DISABLE_TABCOMP
int last_kbinput = ERR;
/* The key we pressed before the current key. */
size_t complete_len = 0;
/* The length of the original string that we're trying to
* tab complete, if any. */
#endif
#endif /* !NANO_SMALL */
answer = mallocstrcpy(answer, curranswer);
curranswer_len = strlen(answer);
/* Only put statusbar_x at the end of the string if it's
* uninitialized, if it would be past the end of curranswer, 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 > curranswer_len ||
resetstatuspos)
statusbar_x = curranswer_len;
currshortcut = s;
nanoget_repaint(answer, statusbar_x);
/* Refresh the edit window and the statusbar before getting
* input. */
wnoutrefresh(edit);
wnoutrefresh(bottomwin);
/* If we're using restricted mode, we aren't allowed to change the
* name of a file once it has one because that would allow writing
* 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 = do_statusbar_input(&meta_key, &func_key,
&s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
kbinput != NANO_ENTER_KEY) {
assert(statusbar_x <= strlen(answer));
#ifndef DISABLE_TABCOMP
if (kbinput != NANO_TAB_KEY)
tabbed = FALSE;
#endif
switch (kbinput) {
case NANO_TAB_KEY:
#ifndef DISABLE_TABCOMP
#ifndef NANO_SMALL
if (history_list != NULL) {
if (last_kbinput != NANO_TAB_KEY)
complete_len = strlen(answer);
if (complete_len > 0) {
answer = mallocstrcpy(answer,
get_history_completion(history_list,
answer, complete_len));
statusbar_x = strlen(answer);
}
} else
#endif /* !NANO_SMALL */
if (allow_tabs)
answer = input_tab(answer, &statusbar_x, &tabbed,
list);
#endif /* !DISABLE_TABCOMP */
break;
case NANO_PREVLINE_KEY:
#ifndef NANO_SMALL
if (history_list != NULL) {
/* If we're scrolling up at the bottom of the
* history list and answer isn't blank, save answer
* in magichistory. */
if ((*history_list)->next == NULL &&
answer[0] != '\0')
magichistory = mallocstrcpy(magichistory,
answer);
/* Get the older search from the history list and
* save it in answer. If there is no older search,
* don't do anything. */
if ((history =
get_history_older(history_list)) != NULL) {
answer = mallocstrcpy(answer, history);
statusbar_x = strlen(answer);
}
/* This key has a shortcut list entry when it's used
* to move to an older search, which means that
* finished has been set to TRUE. Set it back to
* FALSE here, so that we aren't kicked out of the
* statusbar prompt. */
finished = FALSE;
}
#endif /* !NANO_SMALL */
break;
case NANO_NEXTLINE_KEY:
#ifndef NANO_SMALL
if (history_list != NULL) {
/* Get the newer search from the history list and
* save it in answer. If there is no newer search,
* don't do anything. */
if ((history =
get_history_newer(history_list)) != NULL) {
answer = mallocstrcpy(answer, history);
statusbar_x = strlen(answer);
}
/* If, after scrolling down, we're at the bottom of
* the history list, answer is blank, and
* magichistory is set, save magichistory in
* answer. */
if ((*history_list)->next == NULL &&
answer[0] == '\0' && magichistory != NULL) {
answer = mallocstrcpy(answer, magichistory);
statusbar_x = strlen(answer);
}
}
#endif /* !NANO_SMALL */
break;
}
/* If we have a shortcut with an associated function, break out
* if we're finished after running or trying to run the
* function. */
if (finished)
break;
#if !defined(NANO_SMALL) && !defined(DISABLE_TABCOMP)
last_kbinput = kbinput;
#endif
nanoget_repaint(answer, statusbar_x);
wnoutrefresh(bottomwin);
}
#ifndef NANO_SMALL
/* Set the current position in the history list to the bottom and
* free magichistory, if we need to. */
if (history_list != NULL) {
history_reset(*history_list);
if (magichistory != NULL)
free(magichistory);
}
#endif
/* We finished putting in an answer or ran a normal shortcut's
* associated function, so reset statusbar_x. */
if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
ran_func)
statusbar_x = (size_t)-1;
return kbinput;
}
/* Ask a question on the statusbar. Answer will be stored in answer
* global. Returns -1 on aborted enter, -2 on a blank string, and 0
* otherwise, the valid shortcut key caught. curranswer is any editable
* text that we want to put up by default.
*
* The allow_tabs parameter indicates whether we should allow tabs to be
* interpreted. */
int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
#ifndef NANO_SMALL
filestruct **history_list,
#endif
const char *msg, ...)
{
va_list ap;
int retval;
#ifndef DISABLE_TABCOMP
bool list = FALSE;
#endif
prompt = charealloc(prompt, ((COLS - 4) * mb_cur_max()) + 1);
bottombars(s);
va_start(ap, msg);
vsnprintf(prompt, (COLS - 4) * mb_cur_max(), msg, ap);
va_end(ap);
null_at(&prompt, actual_x(prompt, COLS - 4));
retval = nanogetstr(allow_tabs, curranswer,
#ifndef NANO_SMALL
history_list,
#endif
s
#ifndef DISABLE_TABCOMP
, &list
#endif
);
resetstatuspos = FALSE;
switch (retval) {
case NANO_CANCEL_KEY:
retval = -1;
resetstatuspos = TRUE;
break;
case NANO_ENTER_KEY:
retval = (answer[0] == '\0') ? -2 : 0;
resetstatuspos = TRUE;
break;
}
blank_statusbar();
wnoutrefresh(bottomwin);
#ifdef DEBUG
fprintf(stderr, "answer = \"%s\"\n", answer);
#endif
#ifndef DISABLE_TABCOMP
/* If we've done tab completion, there might be a list of filename
* matches on the edit window at this point. Make sure that they're
* cleared off. */
if (list)
edit_refresh();
#endif
return retval;
}
void statusq_abort(void)
{
resetstatuspos = TRUE;
}
void titlebar(const char *path)
{
int space = COLS;