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-d3aeb78583b8master
parent
81c4e187f5
commit
d24d0a43e8
13
ChangeLog
13
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -12,6 +12,7 @@ nano_SOURCES = chars.c \
|
|||
move.c \
|
||||
nano.c \
|
||||
nano.h \
|
||||
prompt.c \
|
||||
proto.h \
|
||||
rcfile.c \
|
||||
search.c \
|
||||
|
|
|
@ -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;
|
||||
}
|
76
src/proto.h
76
src/proto.h
|
@ -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, ...);
|
||||
|
|
847
src/winio.c
847
src/winio.c
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue