2005-11-01 17:37:44 +00:00
|
|
|
/**************************************************************************
|
2016-08-29 15:10:49 +00:00
|
|
|
* prompt.c -- This file is part of GNU nano. *
|
2005-11-01 17:37:44 +00:00
|
|
|
* *
|
2020-01-15 10:42:38 +00:00
|
|
|
* Copyright (C) 1999-2011, 2013-2020 Free Software Foundation, Inc. *
|
2018-06-01 08:17:42 +00:00
|
|
|
* Copyright (C) 2016, 2018 Benno Schulenberg *
|
2016-08-29 13:14:18 +00:00
|
|
|
* *
|
2016-08-29 15:10:49 +00:00
|
|
|
* GNU nano 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 3 of the License, *
|
|
|
|
* or (at your option) any later version. *
|
2005-11-01 17:37:44 +00:00
|
|
|
* *
|
2016-08-29 15:10:49 +00:00
|
|
|
* GNU nano 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. *
|
2005-11-01 17:37:44 +00:00
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
2016-08-29 15:10:49 +00:00
|
|
|
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
2005-11-01 17:37:44 +00:00
|
|
|
* *
|
|
|
|
**************************************************************************/
|
|
|
|
|
2020-06-20 10:09:31 +00:00
|
|
|
#include "prototypes.h"
|
2005-11-01 17:37:44 +00:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
static char *prompt = NULL;
|
2020-01-16 15:16:31 +00:00
|
|
|
/* The prompt string used for status-bar questions. */
|
2018-07-11 08:55:59 +00:00
|
|
|
static size_t typing_x = HIGHEST_POSITIVE;
|
2018-07-11 08:07:33 +00:00
|
|
|
/* The cursor position in answer. */
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2020-02-14 18:06:39 +00:00
|
|
|
/* Move to the beginning of the answer. */
|
|
|
|
void do_statusbar_home(void)
|
|
|
|
{
|
|
|
|
typing_x = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move to the end of the answer. */
|
|
|
|
void do_statusbar_end(void)
|
|
|
|
{
|
|
|
|
typing_x = strlen(answer);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
/* Move to the next word in the answer. */
|
|
|
|
void do_statusbar_next_word(void)
|
|
|
|
{
|
2020-03-12 11:38:01 +00:00
|
|
|
bool seen_space = !is_word_char(answer + typing_x, FALSE);
|
2020-02-14 18:06:39 +00:00
|
|
|
bool seen_word = !seen_space;
|
|
|
|
|
|
|
|
/* Move forward until we reach either the end or the start of a word,
|
|
|
|
* depending on whether the AFTER_ENDS flag is set or not. */
|
|
|
|
while (answer[typing_x] != '\0') {
|
|
|
|
typing_x = step_right(answer, typing_x);
|
|
|
|
|
|
|
|
if (ISSET(AFTER_ENDS)) {
|
|
|
|
/* If this is a word character, continue; else it's a separator,
|
|
|
|
* and if we've already seen a word, then it's a word end. */
|
2020-03-12 11:38:01 +00:00
|
|
|
if (is_word_char(answer + typing_x, FALSE))
|
2020-02-14 18:06:39 +00:00
|
|
|
seen_word = TRUE;
|
|
|
|
else if (seen_word)
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
/* If this is not a word character, then it's a separator; else
|
|
|
|
* if we've already seen a separator, then it's a word start. */
|
2020-03-12 11:38:01 +00:00
|
|
|
if (!is_word_char(answer + typing_x, FALSE))
|
2020-02-14 18:06:39 +00:00
|
|
|
seen_space = TRUE;
|
|
|
|
else if (seen_space)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move to the previous word in the answer. */
|
|
|
|
void do_statusbar_prev_word(void)
|
|
|
|
{
|
|
|
|
bool seen_a_word = FALSE, step_forward = FALSE;
|
|
|
|
|
|
|
|
/* Move backward until we pass over the start of a word. */
|
|
|
|
while (typing_x != 0) {
|
|
|
|
typing_x = step_left(answer, typing_x);
|
|
|
|
|
2020-03-12 11:38:01 +00:00
|
|
|
if (is_word_char(answer + typing_x, FALSE))
|
2020-02-14 18:06:39 +00:00
|
|
|
seen_a_word = TRUE;
|
|
|
|
else if (seen_a_word) {
|
|
|
|
/* This is space now: we've overshot the start of the word. */
|
|
|
|
step_forward = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (step_forward)
|
|
|
|
/* Move one character forward again to sit on the start of the word. */
|
|
|
|
typing_x = step_right(answer, typing_x);
|
|
|
|
}
|
|
|
|
#endif /* !NANO_TINY */
|
|
|
|
|
|
|
|
/* Move left one character in the answer. */
|
|
|
|
void do_statusbar_left(void)
|
|
|
|
{
|
|
|
|
if (typing_x > 0)
|
|
|
|
typing_x = step_left(answer, typing_x);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move right one character in the answer. */
|
|
|
|
void do_statusbar_right(void)
|
|
|
|
{
|
|
|
|
if (answer[typing_x] != '\0')
|
|
|
|
typing_x = step_right(answer, typing_x);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete one character in the answer. */
|
|
|
|
void do_statusbar_delete(void)
|
|
|
|
{
|
|
|
|
if (answer[typing_x] != '\0') {
|
|
|
|
int charlen = char_length(answer + typing_x);
|
|
|
|
|
|
|
|
memmove(answer + typing_x, answer + typing_x + charlen,
|
|
|
|
strlen(answer) - typing_x - charlen + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Backspace over one character in the answer. */
|
|
|
|
void do_statusbar_backspace(void)
|
|
|
|
{
|
|
|
|
if (typing_x > 0) {
|
|
|
|
typing_x = step_left(answer, typing_x);
|
|
|
|
do_statusbar_delete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Zap some or all text from the answer. */
|
|
|
|
void do_statusbar_cut_text(void)
|
|
|
|
{
|
|
|
|
if (!ISSET(CUT_FROM_CURSOR))
|
|
|
|
typing_x = 0;
|
|
|
|
|
|
|
|
answer[typing_x] = '\0';
|
|
|
|
}
|
|
|
|
|
2020-02-14 18:00:16 +00:00
|
|
|
/* Paste the first line of the cutbuffer into the current answer. */
|
|
|
|
void paste_into_answer(void)
|
|
|
|
{
|
|
|
|
size_t pastelen = strlen(cutbuffer->data);
|
|
|
|
char *fusion = charalloc(strlen(answer) + pastelen + 1);
|
|
|
|
|
|
|
|
/* Concatenate: the current answer before the cursor, the first line
|
|
|
|
* of the cutbuffer, plus the rest of the current answer. */
|
|
|
|
strncpy(fusion, answer, typing_x);
|
|
|
|
strncpy(fusion + typing_x, cutbuffer->data, pastelen);
|
|
|
|
strcpy(fusion + typing_x + pastelen, answer + typing_x);
|
|
|
|
|
|
|
|
free(answer);
|
|
|
|
answer = fusion;
|
|
|
|
typing_x += pastelen;
|
|
|
|
}
|
|
|
|
|
2018-01-27 18:33:03 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2020-01-16 15:16:31 +00:00
|
|
|
/* Handle a mouse click on the status-bar prompt or the shortcut list. */
|
2018-01-27 18:33:03 +00:00
|
|
|
int do_statusbar_mouse(void)
|
|
|
|
{
|
2018-01-27 18:47:00 +00:00
|
|
|
int click_row, click_col;
|
2018-01-27 19:00:14 +00:00
|
|
|
int retval = get_mouseinput(&click_row, &click_col, TRUE);
|
2018-01-27 18:33:03 +00:00
|
|
|
|
2020-01-16 15:16:31 +00:00
|
|
|
/* We can click on the status-bar window text to move the cursor. */
|
2018-01-27 18:47:00 +00:00
|
|
|
if (retval == 0 && wmouse_trafo(bottomwin, &click_row, &click_col, FALSE)) {
|
2019-04-24 06:49:18 +00:00
|
|
|
size_t start_col = breadth(prompt) + 2;
|
2018-01-27 18:33:03 +00:00
|
|
|
|
|
|
|
/* Move to where the click occurred. */
|
2018-07-11 07:56:39 +00:00
|
|
|
if (click_row == 0 && click_col >= start_col)
|
2018-07-11 08:55:59 +00:00
|
|
|
typing_x = actual_x(answer,
|
2018-01-27 18:33:03 +00:00
|
|
|
get_statusbar_page_start(start_col, start_col +
|
2019-04-24 07:08:23 +00:00
|
|
|
wideness(answer, typing_x)) + click_col - start_col);
|
2018-01-27 18:33:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-14 18:06:39 +00:00
|
|
|
/* Insert the given short burst of bytes into the answer. */
|
|
|
|
void inject_into_answer(char *burst, size_t count)
|
|
|
|
{
|
|
|
|
/* First encode any embedded NUL byte as 0x0A. */
|
|
|
|
for (size_t index = 0; index < count; index++)
|
|
|
|
if (burst[index] == '\0')
|
|
|
|
burst[index] = '\n';
|
|
|
|
|
|
|
|
answer = charealloc(answer, strlen(answer) + count + 1);
|
|
|
|
memmove(answer + typing_x + count, answer + typing_x,
|
|
|
|
strlen(answer) - typing_x + 1);
|
|
|
|
strncpy(answer + typing_x, burst , count);
|
|
|
|
|
|
|
|
typing_x += count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get a verbatim keystroke and insert it into the answer. */
|
|
|
|
void do_statusbar_verbatim_input(void)
|
|
|
|
{
|
2020-08-10 05:53:41 +00:00
|
|
|
size_t count = 1;
|
2020-02-14 18:06:39 +00:00
|
|
|
char *bytes;
|
|
|
|
|
|
|
|
bytes = get_verbatim_kbinput(bottomwin, &count);
|
|
|
|
|
2020-07-06 14:28:11 +00:00
|
|
|
if (count > 0)
|
|
|
|
inject_into_answer(bytes, count);
|
|
|
|
else
|
|
|
|
beep();
|
2020-02-14 18:06:39 +00:00
|
|
|
|
|
|
|
free(bytes);
|
|
|
|
}
|
|
|
|
|
2016-08-22 12:05:25 +00:00
|
|
|
/* Read in a keystroke, interpret it if it is a shortcut or toggle, and
|
2018-02-24 18:42:43 +00:00
|
|
|
* return it. Set finished to TRUE if we're done after running
|
2016-12-03 19:37:30 +00:00
|
|
|
* or trying to run a function associated with a shortcut key. */
|
2018-02-24 18:42:43 +00:00
|
|
|
int do_statusbar_input(bool *finished)
|
2005-11-01 17:37:44 +00:00
|
|
|
{
|
2017-12-29 18:27:33 +00:00
|
|
|
int input;
|
|
|
|
/* The character we read in. */
|
2020-02-12 15:58:12 +00:00
|
|
|
static char *puddle = NULL;
|
2017-12-29 18:27:33 +00:00
|
|
|
/* The input buffer. */
|
2020-02-12 15:58:12 +00:00
|
|
|
static size_t depth = 0;
|
2017-12-29 18:27:33 +00:00
|
|
|
/* The length of the input buffer. */
|
2019-04-03 15:34:05 +00:00
|
|
|
const keystruct *shortcut;
|
2017-12-29 18:27:33 +00:00
|
|
|
|
|
|
|
*finished = FALSE;
|
|
|
|
|
|
|
|
/* Read in a character. */
|
|
|
|
input = get_kbinput(bottomwin, VISIBLE);
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2015-05-28 13:02:29 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-12-29 18:27:33 +00:00
|
|
|
if (input == KEY_WINCH)
|
|
|
|
return KEY_WINCH;
|
2015-05-28 13:02:29 +00:00
|
|
|
#endif
|
|
|
|
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2017-12-29 18:27:33 +00:00
|
|
|
/* If we got a mouse click and it was on a shortcut, read in the
|
|
|
|
* shortcut character. */
|
|
|
|
if (input == KEY_MOUSE) {
|
|
|
|
if (do_statusbar_mouse() == 1)
|
|
|
|
input = get_kbinput(bottomwin, BLIND);
|
|
|
|
else
|
|
|
|
return ERR;
|
|
|
|
}
|
2005-11-01 17:37:44 +00:00
|
|
|
#endif
|
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
/* Check for a shortcut in the current list. */
|
2018-02-24 17:20:30 +00:00
|
|
|
shortcut = get_shortcut(&input);
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2020-02-12 11:05:52 +00:00
|
|
|
/* If not a command, discard anything that is not a normal character byte.
|
|
|
|
* Apart from that, only accept input when not in restricted mode, or when
|
|
|
|
* not at the "Write File" prompt, or when there is no filename yet. */
|
2018-02-24 17:20:30 +00:00
|
|
|
if (shortcut == NULL) {
|
2020-02-12 10:46:15 +00:00
|
|
|
if (input < 0x20 || input > 0xFF || meta_key)
|
2017-12-29 18:27:33 +00:00
|
|
|
beep();
|
2020-02-12 10:46:15 +00:00
|
|
|
else if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
|
2017-12-29 18:27:33 +00:00
|
|
|
openfile->filename[0] == '\0') {
|
2020-02-12 15:58:12 +00:00
|
|
|
puddle = charealloc(puddle, depth + 2);
|
|
|
|
puddle[depth++] = (char)input;
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
2005-11-01 17:37:44 +00:00
|
|
|
}
|
2017-12-29 18:27:33 +00:00
|
|
|
|
2020-02-12 11:05:52 +00:00
|
|
|
/* If we got a shortcut, or if there aren't any other keystrokes waiting,
|
|
|
|
* it's time to insert all characters in the input buffer (if not empty)
|
|
|
|
* into the answer, and then clear the input buffer. */
|
2020-02-12 15:58:12 +00:00
|
|
|
if ((shortcut || get_key_buffer_len() == 0) && puddle != NULL) {
|
|
|
|
puddle[depth] = '\0';
|
|
|
|
|
|
|
|
inject_into_answer(puddle, depth);
|
|
|
|
|
|
|
|
free(puddle);
|
|
|
|
puddle = NULL;
|
|
|
|
depth = 0;
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
|
|
|
|
2018-02-24 17:20:30 +00:00
|
|
|
if (shortcut) {
|
2018-02-24 18:31:11 +00:00
|
|
|
if (shortcut->func == do_tab || shortcut->func == do_enter)
|
2017-12-29 18:27:33 +00:00
|
|
|
;
|
2019-02-10 19:17:22 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
|
|
|
else if (shortcut->func == get_history_older_void ||
|
|
|
|
shortcut->func == get_history_newer_void)
|
|
|
|
;
|
|
|
|
#endif
|
2018-02-24 18:31:11 +00:00
|
|
|
else if (shortcut->func == do_left)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_left();
|
2018-02-24 18:31:11 +00:00
|
|
|
else if (shortcut->func == do_right)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_right();
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2020-03-11 18:43:03 +00:00
|
|
|
else if (shortcut->func == to_prev_word)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_prev_word();
|
2020-03-11 18:43:03 +00:00
|
|
|
else if (shortcut->func == to_next_word)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_next_word();
|
2006-04-25 02:35:33 +00:00
|
|
|
#endif
|
2018-02-24 18:31:11 +00:00
|
|
|
else if (shortcut->func == do_home)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_home();
|
2018-02-24 18:31:11 +00:00
|
|
|
else if (shortcut->func == do_end)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_end();
|
|
|
|
/* When in restricted mode at the "Write File" prompt and the
|
|
|
|
* filename isn't blank, disallow any input and deletion. */
|
|
|
|
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE &&
|
|
|
|
openfile->filename[0] != '\0' &&
|
2018-02-24 18:31:11 +00:00
|
|
|
(shortcut->func == do_verbatim_input ||
|
2019-05-03 17:51:15 +00:00
|
|
|
shortcut->func == cut_text ||
|
2019-05-03 17:47:08 +00:00
|
|
|
shortcut->func == paste_text ||
|
2018-02-24 18:31:11 +00:00
|
|
|
shortcut->func == do_delete ||
|
|
|
|
shortcut->func == do_backspace))
|
2017-12-29 18:27:33 +00:00
|
|
|
;
|
2018-02-27 12:18:21 +00:00
|
|
|
#ifdef ENABLE_NANORC
|
2018-03-18 18:17:56 +00:00
|
|
|
else if (shortcut->func == (functionptrtype)implant)
|
2018-02-27 12:34:32 +00:00
|
|
|
implant(shortcut->expansion);
|
2018-02-27 12:18:21 +00:00
|
|
|
#endif
|
2018-02-24 18:31:11 +00:00
|
|
|
else if (shortcut->func == do_verbatim_input)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_verbatim_input();
|
2019-05-03 17:51:15 +00:00
|
|
|
else if (shortcut->func == cut_text)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_cut_text();
|
2018-02-24 18:31:11 +00:00
|
|
|
else if (shortcut->func == do_delete)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_delete();
|
2018-02-24 18:31:11 +00:00
|
|
|
else if (shortcut->func == do_backspace)
|
2017-12-29 18:27:33 +00:00
|
|
|
do_statusbar_backspace();
|
2019-05-03 17:47:08 +00:00
|
|
|
else if (shortcut->func == paste_text) {
|
2017-12-29 18:27:33 +00:00
|
|
|
if (cutbuffer != NULL)
|
2020-02-14 18:00:16 +00:00
|
|
|
paste_into_answer();
|
2017-12-29 18:27:33 +00:00
|
|
|
} else {
|
2018-02-24 18:42:43 +00:00
|
|
|
/* Handle any other shortcut in the current menu, setting finished
|
|
|
|
* to TRUE to indicate that we're done after running or trying to
|
|
|
|
* run its associated function. */
|
2018-03-20 18:56:03 +00:00
|
|
|
if (!ISSET(VIEW_MODE) || okay_for_view(shortcut))
|
2018-02-27 12:34:32 +00:00
|
|
|
shortcut->func();
|
2017-12-29 18:27:33 +00:00
|
|
|
*finished = TRUE;
|
|
|
|
}
|
2016-08-22 12:05:25 +00:00
|
|
|
}
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
return input;
|
2005-11-01 17:37:44 +00:00
|
|
|
}
|
|
|
|
|
2016-08-26 20:46:01 +00:00
|
|
|
/* Return the column number of the first character of the answer that is
|
2020-01-16 15:16:31 +00:00
|
|
|
* displayed in the status bar when the cursor is at the given column,
|
2016-08-26 20:46:01 +00:00
|
|
|
* with the available room for the answer starting at base. Note that
|
|
|
|
* (0 <= column - get_statusbar_page_start(column) < COLS). */
|
|
|
|
size_t get_statusbar_page_start(size_t base, size_t column)
|
2005-11-01 17:37:44 +00:00
|
|
|
{
|
2017-12-29 18:27:33 +00:00
|
|
|
if (column == base || column < COLS - 1)
|
|
|
|
return 0;
|
|
|
|
else if (COLS > base + 2)
|
|
|
|
return column - base - 1 - (column - base - 1) % (COLS - base - 2);
|
|
|
|
else
|
|
|
|
return column - 2;
|
2005-11-01 17:37:44 +00:00
|
|
|
}
|
|
|
|
|
2016-08-28 16:15:20 +00:00
|
|
|
/* Reinitialize the cursor position in the answer. */
|
2018-07-11 09:02:45 +00:00
|
|
|
void put_cursor_at_end_of_answer(void)
|
2016-04-17 13:24:05 +00:00
|
|
|
{
|
2018-07-11 08:55:59 +00:00
|
|
|
typing_x = HIGHEST_POSITIVE;
|
2016-04-17 13:24:05 +00:00
|
|
|
}
|
|
|
|
|
2017-04-17 09:44:04 +00:00
|
|
|
/* Redraw the promptbar and place the cursor at the right spot. */
|
2018-07-11 08:48:27 +00:00
|
|
|
void draw_the_promptbar(void)
|
2005-11-01 17:37:44 +00:00
|
|
|
{
|
2019-04-24 06:49:18 +00:00
|
|
|
size_t base = breadth(prompt) + 2;
|
2017-12-29 18:27:33 +00:00
|
|
|
size_t the_page, end_page, column;
|
|
|
|
char *expanded;
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2019-04-24 07:08:23 +00:00
|
|
|
the_page = get_statusbar_page_start(base, base + wideness(answer, typing_x));
|
2019-04-24 06:49:18 +00:00
|
|
|
end_page = get_statusbar_page_start(base, base + breadth(answer) - 1);
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
/* Color the promptbar over its full width. */
|
|
|
|
wattron(bottomwin, interface_color_pair[TITLE_BAR]);
|
2019-06-25 06:28:10 +00:00
|
|
|
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
mvwaddstr(bottomwin, 0, 0, prompt);
|
|
|
|
waddch(bottomwin, ':');
|
|
|
|
waddch(bottomwin, (the_page == 0) ? ' ' : '<');
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2019-02-27 20:37:53 +00:00
|
|
|
expanded = display_string(answer, the_page, COLS - base, FALSE, TRUE);
|
2017-12-29 18:27:33 +00:00
|
|
|
waddstr(bottomwin, expanded);
|
|
|
|
free(expanded);
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2019-04-24 06:49:18 +00:00
|
|
|
if (base + breadth(answer) != COLS && the_page < end_page)
|
2019-02-06 13:51:53 +00:00
|
|
|
mvwaddch(bottomwin, 0, COLS - 1, '>');
|
2016-08-26 19:42:23 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
2016-02-06 12:12:08 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
/* Work around a cursor-misplacement bug in VTEs. */
|
|
|
|
wmove(bottomwin, 0, 0);
|
|
|
|
wrefresh(bottomwin);
|
2017-04-17 09:44:04 +00:00
|
|
|
|
2018-07-11 09:11:30 +00:00
|
|
|
/* Place the cursor at the right spot. */
|
2019-04-24 07:08:23 +00:00
|
|
|
column = base + wideness(answer, typing_x);
|
2017-12-29 18:27:33 +00:00
|
|
|
wmove(bottomwin, 0, column - get_statusbar_page_start(base, column));
|
|
|
|
wnoutrefresh(bottomwin);
|
2005-11-01 17:37:44 +00:00
|
|
|
}
|
|
|
|
|
2018-07-11 08:07:33 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
/* Remove or add the pipe character at the answer's head. */
|
|
|
|
void add_or_remove_pipe_symbol_from_answer(void)
|
|
|
|
{
|
|
|
|
if (answer[0] == '|') {
|
2019-09-18 13:20:08 +00:00
|
|
|
memmove(answer, answer + 1, strlen(answer) + 1);
|
2018-07-11 08:55:59 +00:00
|
|
|
if (typing_x > 0)
|
|
|
|
typing_x--;
|
2018-07-11 08:07:33 +00:00
|
|
|
} else {
|
|
|
|
answer = charealloc(answer, strlen(answer) + 2);
|
2019-09-18 13:20:08 +00:00
|
|
|
memmove(answer + 1, answer, strlen(answer) + 1);
|
2018-07-11 08:07:33 +00:00
|
|
|
answer[0] = '|';
|
2018-07-11 08:55:59 +00:00
|
|
|
typing_x++;
|
2018-07-11 08:07:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-01-16 15:16:31 +00:00
|
|
|
/* Get a string of input at the status-bar prompt. */
|
2020-06-20 15:15:40 +00:00
|
|
|
functionptrtype acquire_an_answer(int *actual, bool *listed,
|
|
|
|
linestruct **history_list, void (*refresh_func)(void))
|
2005-11-01 17:37:44 +00:00
|
|
|
{
|
2017-12-29 18:27:33 +00:00
|
|
|
int kbinput = ERR;
|
2018-02-24 18:42:43 +00:00
|
|
|
bool finished;
|
2017-12-29 18:27:33 +00:00
|
|
|
functionptrtype func;
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2017-12-29 18:27:33 +00:00
|
|
|
char *history = NULL;
|
|
|
|
/* The current history string. */
|
|
|
|
char *magichistory = NULL;
|
2018-11-05 08:38:07 +00:00
|
|
|
/* The (partial) answer that was typed at the prompt, if any. */
|
2017-05-08 17:15:51 +00:00
|
|
|
#ifdef ENABLE_TABCOMP
|
2020-06-26 17:44:19 +00:00
|
|
|
bool previous_was_tab = FALSE;
|
|
|
|
/* Whether the previous keystroke was an attempt at tab completion. */
|
2020-06-26 17:27:28 +00:00
|
|
|
size_t fragment_length = 0;
|
|
|
|
/* The length of the fragment that the user tries to tab complete. */
|
2005-11-01 17:37:44 +00:00
|
|
|
#endif
|
2017-10-29 18:42:12 +00:00
|
|
|
#endif /* ENABLE_HISTORIES */
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2018-07-11 08:55:59 +00:00
|
|
|
if (typing_x > strlen(answer))
|
|
|
|
typing_x = strlen(answer);
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
while (TRUE) {
|
2018-07-11 08:48:27 +00:00
|
|
|
draw_the_promptbar();
|
|
|
|
|
2018-02-24 18:42:43 +00:00
|
|
|
kbinput = do_statusbar_input(&finished);
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2015-05-28 13:02:29 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-12-29 18:27:33 +00:00
|
|
|
/* If the window size changed, go reformat the prompt string. */
|
|
|
|
if (kbinput == KEY_WINCH) {
|
|
|
|
refresh_func();
|
|
|
|
*actual = KEY_WINCH;
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2017-12-29 18:27:33 +00:00
|
|
|
free(magichistory);
|
2016-08-30 09:14:19 +00:00
|
|
|
#endif
|
2017-12-29 18:27:33 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2016-08-30 09:14:19 +00:00
|
|
|
#endif /* !NANO_TINY */
|
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
func = func_from_key(&kbinput);
|
2008-03-12 04:44:14 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
if (func == do_cancel || func == do_enter)
|
|
|
|
break;
|
2008-03-12 04:44:14 +00:00
|
|
|
|
2017-05-08 17:15:51 +00:00
|
|
|
#ifdef ENABLE_TABCOMP
|
2017-12-29 18:27:33 +00:00
|
|
|
if (func == do_tab) {
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2017-12-29 18:27:33 +00:00
|
|
|
if (history_list != NULL) {
|
2020-06-26 17:44:19 +00:00
|
|
|
if (!previous_was_tab)
|
2020-06-26 17:27:28 +00:00
|
|
|
fragment_length = strlen(answer);
|
2017-12-29 18:27:33 +00:00
|
|
|
|
2020-06-26 17:27:28 +00:00
|
|
|
if (fragment_length > 0) {
|
2017-12-29 18:27:33 +00:00
|
|
|
answer = get_history_completion(history_list,
|
2020-06-26 17:27:28 +00:00
|
|
|
answer, fragment_length);
|
2018-07-11 08:55:59 +00:00
|
|
|
typing_x = strlen(answer);
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
|
|
|
} else
|
2014-06-19 20:05:24 +00:00
|
|
|
#endif
|
2020-06-20 15:15:40 +00:00
|
|
|
/* Allow tab completion of filenames, but not in restricted mode. */
|
|
|
|
if ((currmenu == MINSERTFILE || currmenu == MWRITEFILE ||
|
|
|
|
currmenu == MGOTODIR) && !ISSET(RESTRICTED))
|
2020-06-20 16:40:36 +00:00
|
|
|
answer = input_tab(answer, &typing_x, refresh_func, listed);
|
2017-12-29 18:27:33 +00:00
|
|
|
} else
|
2017-05-08 17:15:51 +00:00
|
|
|
#endif /* ENABLE_TABCOMP */
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2017-12-29 18:27:33 +00:00
|
|
|
if (func == get_history_older_void) {
|
|
|
|
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')
|
|
|
|
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);
|
2018-07-11 08:55:59 +00:00
|
|
|
typing_x = strlen(answer);
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (func == get_history_newer_void) {
|
|
|
|
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);
|
2018-07-11 08:55:59 +00:00
|
|
|
typing_x = strlen(answer);
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
|
|
|
|
2018-11-05 08:38:07 +00:00
|
|
|
/* If we've reached the bottom of the history list, and answer
|
|
|
|
* is blank, and magichistory is set, restore the old answer. */
|
2017-12-29 18:27:33 +00:00
|
|
|
if ((*history_list)->next == NULL &&
|
|
|
|
*answer == '\0' && magichistory != NULL) {
|
|
|
|
answer = mallocstrcpy(answer, magichistory);
|
2018-07-11 08:55:59 +00:00
|
|
|
typing_x = strlen(answer);
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
#endif /* ENABLE_HISTORIES */
|
2020-05-31 17:09:48 +00:00
|
|
|
/* If we ran a function that should not exit from the prompt... */
|
|
|
|
if (func == do_help || func == full_refresh)
|
2017-12-29 18:27:33 +00:00
|
|
|
finished = FALSE;
|
2020-02-05 10:41:31 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
else if (func == do_nothing)
|
|
|
|
finished = FALSE;
|
bindings: allow toggling the help lines at several prompts and in browser
Now the help lines can be toggled not only while editing, but also at
the Read (^R), Write (^O), Execute (^T), Search (^W), Replace (M-R),
Goto (^/), and Yesno prompts, and also in the file browser and when
searching for a file name. The help lines cannot be toggled in the
help viewer, nor when searching in a help text, nor in the linter,
as these three things force the help lines to be on.
Furthermore, the 'nohelp' function can be rebound in all relevant
menus (default binding: M-X).
This fulfills https://savannah.gnu.org/bugs/?58471.
2020-05-31 18:04:15 +00:00
|
|
|
else if (func == do_toggle_void) {
|
|
|
|
TOGGLE(NO_HELP);
|
|
|
|
window_init();
|
|
|
|
focusing = FALSE;
|
|
|
|
refresh_func();
|
|
|
|
bottombars(currmenu);
|
|
|
|
finished = FALSE;
|
|
|
|
}
|
2020-02-05 10:41:31 +00:00
|
|
|
#endif
|
2005-11-08 01:49:14 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
/* 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;
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2017-10-29 18:42:12 +00:00
|
|
|
#if defined(ENABLE_HISTORIES) && defined(ENABLE_TABCOMP)
|
2020-06-26 17:44:19 +00:00
|
|
|
previous_was_tab = (func == do_tab);
|
2005-11-01 17:37:44 +00:00
|
|
|
#endif
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2017-10-29 18:42:12 +00:00
|
|
|
#ifdef ENABLE_HISTORIES
|
2017-12-29 18:27:33 +00:00
|
|
|
/* Set the current position in the history list to the bottom. */
|
|
|
|
if (history_list != NULL) {
|
|
|
|
history_reset(*history_list);
|
|
|
|
free(magichistory);
|
|
|
|
}
|
2005-11-01 17:37:44 +00:00
|
|
|
#endif
|
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
*actual = kbinput;
|
2014-07-02 08:47:09 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
return func;
|
2005-11-01 17:37:44 +00:00
|
|
|
}
|
|
|
|
|
2020-01-16 15:16:31 +00:00
|
|
|
/* Ask a question on the status bar. Return 0 when text was entered,
|
2019-02-20 17:59:15 +00:00
|
|
|
* -1 for a cancelled entry, -2 for a blank string, and the relevant
|
2020-06-20 15:15:40 +00:00
|
|
|
* keycode when a valid shortcut key was pressed. The 'provided'
|
|
|
|
* parameter is the default answer for when simply Enter is typed. */
|
|
|
|
int do_prompt(int menu, const char *provided, linestruct **history_list,
|
|
|
|
void (*refresh_func)(void), const char *msg, ...)
|
2005-11-01 17:37:44 +00:00
|
|
|
{
|
2017-12-29 18:27:33 +00:00
|
|
|
va_list ap;
|
|
|
|
int retval;
|
|
|
|
functionptrtype func = NULL;
|
|
|
|
bool listed = FALSE;
|
2020-01-16 15:16:31 +00:00
|
|
|
/* Save a possible current status-bar x position and prompt. */
|
2018-07-11 08:55:59 +00:00
|
|
|
size_t was_typing_x = typing_x;
|
2017-12-29 18:27:33 +00:00
|
|
|
char *saved_prompt = prompt;
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
bottombars(menu);
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2019-10-15 11:39:03 +00:00
|
|
|
if (answer != provided)
|
|
|
|
answer = mallocstrcpy(answer, provided);
|
2016-08-27 08:48:20 +00:00
|
|
|
|
2016-08-30 07:11:33 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
redo_theprompt:
|
|
|
|
#endif
|
2017-12-29 18:27:33 +00:00
|
|
|
prompt = charalloc((COLS * MAXCHARLEN) + 1);
|
|
|
|
va_start(ap, msg);
|
|
|
|
vsnprintf(prompt, COLS * MAXCHARLEN, msg, ap);
|
|
|
|
va_end(ap);
|
|
|
|
/* Reserve five columns for colon plus angles plus answer, ":<aa>". */
|
|
|
|
prompt[actual_x(prompt, (COLS < 5) ? 0 : COLS - 5)] = '\0';
|
|
|
|
|
2020-05-22 09:58:28 +00:00
|
|
|
lastmessage = VACUUM;
|
|
|
|
|
2020-06-20 15:15:40 +00:00
|
|
|
func = acquire_an_answer(&retval, &listed, history_list, refresh_func);
|
2017-12-29 18:27:33 +00:00
|
|
|
free(prompt);
|
|
|
|
prompt = saved_prompt;
|
2016-08-30 07:11:33 +00:00
|
|
|
|
|
|
|
#ifndef NANO_TINY
|
2017-12-29 18:27:33 +00:00
|
|
|
if (retval == KEY_WINCH)
|
|
|
|
goto redo_theprompt;
|
2016-08-30 07:11:33 +00:00
|
|
|
#endif
|
2005-11-01 18:35:47 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
/* If we're done with this prompt, restore the x position to what
|
|
|
|
* it was at a possible previous prompt. */
|
|
|
|
if (func == do_cancel || func == do_enter)
|
2018-07-11 08:55:59 +00:00
|
|
|
typing_x = was_typing_x;
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
/* If we left the prompt via Cancel or Enter, set the return value
|
|
|
|
* properly. */
|
|
|
|
if (func == do_cancel)
|
|
|
|
retval = -1;
|
|
|
|
else if (func == do_enter)
|
|
|
|
retval = (*answer == '\0') ? -2 : 0;
|
2008-03-05 07:34:01 +00:00
|
|
|
|
2020-05-22 09:58:28 +00:00
|
|
|
if (lastmessage == VACUUM)
|
|
|
|
wipe_statusbar();
|
2005-11-01 17:37:44 +00:00
|
|
|
|
2017-05-08 17:15:51 +00:00
|
|
|
#ifdef ENABLE_TABCOMP
|
2020-06-21 08:02:45 +00:00
|
|
|
/* If possible filename completions are still listed, clear them off. */
|
2017-12-29 18:27:33 +00:00
|
|
|
if (listed)
|
|
|
|
refresh_func();
|
2016-04-26 15:50:25 +00:00
|
|
|
#endif
|
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
return retval;
|
2005-11-01 17:37:44 +00:00
|
|
|
}
|
|
|
|
|
2005-11-03 21:07:24 +00:00
|
|
|
/* Ask a simple Yes/No (and optionally All) question, specified in msg,
|
2020-01-16 15:16:31 +00:00
|
|
|
* on the status bar. Return 1 for Yes, 0 for No, 2 for All (if all is
|
2005-11-03 21:07:24 +00:00
|
|
|
* TRUE when passed in), and -1 for Cancel. */
|
2005-11-07 21:45:44 +00:00
|
|
|
int do_yesno_prompt(bool all, const char *msg)
|
2005-11-03 21:07:24 +00:00
|
|
|
{
|
2019-02-10 15:11:57 +00:00
|
|
|
int choice = -2, width = 16;
|
2018-05-07 09:44:01 +00:00
|
|
|
/* TRANSLATORS: For the next three strings, specify the starting letters
|
|
|
|
* of the translations for "Yes"/"No"/"All". The first letter of each of
|
|
|
|
* these strings MUST be a single-byte letter; others may be multi-byte. */
|
2017-12-29 18:27:33 +00:00
|
|
|
const char *yesstr = _("Yy");
|
|
|
|
const char *nostr = _("Nn");
|
|
|
|
const char *allstr = _("Aa");
|
|
|
|
|
2019-02-10 15:11:57 +00:00
|
|
|
while (choice == -2) {
|
2018-05-23 03:17:27 +00:00
|
|
|
#ifdef ENABLE_NLS
|
2018-05-07 09:44:01 +00:00
|
|
|
char letter[MAXCHARLEN + 1];
|
2018-05-23 03:17:27 +00:00
|
|
|
int index = 0;
|
|
|
|
#endif
|
|
|
|
int kbinput;
|
2017-12-29 18:27:33 +00:00
|
|
|
|
|
|
|
if (!ISSET(NO_HELP)) {
|
|
|
|
char shortstr[MAXCHARLEN + 2];
|
|
|
|
/* Temporary string for (translated) " Y", " N" and " A". */
|
2019-04-03 15:34:05 +00:00
|
|
|
const keystruct *cancelshortcut = first_sc_for(MYESNO, do_cancel);
|
2018-08-05 18:01:47 +00:00
|
|
|
/* The keystroke that is bound to the Cancel function. */
|
2017-12-29 18:27:33 +00:00
|
|
|
|
|
|
|
if (COLS < 32)
|
|
|
|
width = COLS / 2;
|
|
|
|
|
|
|
|
/* Clear the shortcut list from the bottom of the screen. */
|
|
|
|
blank_bottombars();
|
|
|
|
|
|
|
|
/* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */
|
|
|
|
sprintf(shortstr, " %c", yesstr[0]);
|
|
|
|
wmove(bottomwin, 1, 0);
|
|
|
|
post_one_key(shortstr, _("Yes"), width);
|
|
|
|
|
2018-05-13 07:56:12 +00:00
|
|
|
shortstr[1] = nostr[0];
|
|
|
|
wmove(bottomwin, 2, 0);
|
|
|
|
post_one_key(shortstr, _("No"), width);
|
|
|
|
|
2017-12-29 18:27:33 +00:00
|
|
|
if (all) {
|
|
|
|
shortstr[1] = allstr[0];
|
|
|
|
wmove(bottomwin, 1, width);
|
|
|
|
post_one_key(shortstr, _("All"), width);
|
|
|
|
}
|
|
|
|
|
|
|
|
wmove(bottomwin, 2, width);
|
2018-08-05 18:01:47 +00:00
|
|
|
post_one_key(cancelshortcut->keystr, _("Cancel"), width);
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
2015-05-28 13:02:29 +00:00
|
|
|
|
2019-06-25 09:34:04 +00:00
|
|
|
/* Color the promptbar over its full width and display the question. */
|
2017-12-29 18:27:33 +00:00
|
|
|
wattron(bottomwin, interface_color_pair[TITLE_BAR]);
|
2019-06-25 06:28:10 +00:00
|
|
|
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
|
2018-01-25 10:00:19 +00:00
|
|
|
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
|
2017-12-29 18:27:33 +00:00
|
|
|
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
|
|
|
wnoutrefresh(bottomwin);
|
|
|
|
|
|
|
|
currmenu = MYESNO;
|
|
|
|
|
|
|
|
/* When not replacing, show the cursor while waiting for a key. */
|
|
|
|
kbinput = get_kbinput(bottomwin, !all);
|
|
|
|
|
2020-01-26 11:22:49 +00:00
|
|
|
#ifndef NANO_TINY
|
2020-05-21 07:46:13 +00:00
|
|
|
if (kbinput == KEY_WINCH)
|
|
|
|
continue;
|
|
|
|
|
2020-01-26 11:22:49 +00:00
|
|
|
/* Accept the first character of an external paste. */
|
|
|
|
if (bracketed_paste && kbinput == BRACKETED_PASTE_MARKER)
|
|
|
|
kbinput = get_kbinput(bottomwin, BLIND);
|
|
|
|
#endif
|
|
|
|
|
2018-04-19 19:24:03 +00:00
|
|
|
#ifdef ENABLE_NLS
|
2018-05-07 09:44:01 +00:00
|
|
|
letter[index++] = (unsigned char)kbinput;
|
|
|
|
#ifdef ENABLE_UTF8
|
|
|
|
/* If the received code is a UTF-8 starter byte, get also the
|
|
|
|
* continuation bytes and assemble them into one letter. */
|
|
|
|
if (using_utf8() && 0xC0 <= kbinput && kbinput <= 0xF7) {
|
|
|
|
int extras = (kbinput / 16) % 4 + (kbinput <= 0xCF ? 1 : 0);
|
|
|
|
|
|
|
|
while (extras <= get_key_buffer_len() && extras-- > 0)
|
|
|
|
letter[index++] = (unsigned char)get_kbinput(bottomwin, !all);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
letter[index] = '\0';
|
|
|
|
|
|
|
|
/* See if the typed letter is in the Yes, No, or All strings. */
|
|
|
|
if (strstr(yesstr, letter) != NULL)
|
2019-02-10 15:11:57 +00:00
|
|
|
choice = 1;
|
2018-05-07 09:44:01 +00:00
|
|
|
else if (strstr(nostr, letter) != NULL)
|
2019-02-10 15:11:57 +00:00
|
|
|
choice = 0;
|
2018-05-07 09:44:01 +00:00
|
|
|
else if (all && strstr(allstr, letter) != NULL)
|
2019-02-10 15:11:57 +00:00
|
|
|
choice = 2;
|
2018-04-19 19:24:03 +00:00
|
|
|
else
|
2018-05-07 09:44:01 +00:00
|
|
|
#endif /* ENABLE_NLS */
|
2018-04-19 19:24:03 +00:00
|
|
|
if (strchr("Yy", kbinput) != NULL)
|
2019-02-10 15:11:57 +00:00
|
|
|
choice = 1;
|
2018-04-19 19:24:03 +00:00
|
|
|
else if (strchr("Nn", kbinput) != NULL)
|
2019-02-10 15:11:57 +00:00
|
|
|
choice = 0;
|
2018-04-19 19:24:03 +00:00
|
|
|
else if (all && strchr("Aa", kbinput) != NULL)
|
2019-02-10 15:11:57 +00:00
|
|
|
choice = 2;
|
2017-12-29 18:27:33 +00:00
|
|
|
else if (func_from_key(&kbinput) == do_cancel)
|
2019-02-10 15:11:57 +00:00
|
|
|
choice = -1;
|
2019-05-13 17:02:34 +00:00
|
|
|
/* Interpret ^N and ^Q as "No", to allow exiting in anger. */
|
|
|
|
else if (kbinput == '\x0E' || kbinput == '\x11')
|
|
|
|
choice = 0;
|
2019-05-17 09:39:40 +00:00
|
|
|
/* And interpret ^Y as "Yes". */
|
|
|
|
else if (kbinput == '\x19')
|
|
|
|
choice = 1;
|
2017-05-01 18:45:07 +00:00
|
|
|
#ifdef ENABLE_MOUSE
|
2017-12-29 18:27:33 +00:00
|
|
|
else if (kbinput == KEY_MOUSE) {
|
|
|
|
int mouse_x, mouse_y;
|
|
|
|
/* We can click on the Yes/No/All shortcuts to select an answer. */
|
2018-07-14 18:46:50 +00:00
|
|
|
if (get_mouseinput(&mouse_y, &mouse_x, FALSE) == 0 &&
|
2017-12-29 18:27:33 +00:00
|
|
|
wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE) &&
|
|
|
|
mouse_x < (width * 2) && mouse_y > 0) {
|
|
|
|
int x = mouse_x / width;
|
|
|
|
int y = mouse_y - 1;
|
|
|
|
|
|
|
|
/* x == 0 means Yes or No, y == 0 means Yes or All. */
|
2019-02-10 15:11:57 +00:00
|
|
|
choice = -2 * x * y + x - y + 1;
|
2017-12-29 18:27:33 +00:00
|
|
|
|
2019-02-10 15:11:57 +00:00
|
|
|
if (choice == 2 && !all)
|
|
|
|
choice = -2;
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-01 18:45:07 +00:00
|
|
|
#endif /* ENABLE_MOUSE */
|
2020-05-31 17:09:48 +00:00
|
|
|
else if (func_from_key(&kbinput) == full_refresh)
|
|
|
|
full_refresh();
|
bindings: allow toggling the help lines at several prompts and in browser
Now the help lines can be toggled not only while editing, but also at
the Read (^R), Write (^O), Execute (^T), Search (^W), Replace (M-R),
Goto (^/), and Yesno prompts, and also in the file browser and when
searching for a file name. The help lines cannot be toggled in the
help viewer, nor when searching in a help text, nor in the linter,
as these three things force the help lines to be on.
Furthermore, the 'nohelp' function can be rebound in all relevant
menus (default binding: M-X).
This fulfills https://savannah.gnu.org/bugs/?58471.
2020-05-31 18:04:15 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
else if (func_from_key(&kbinput) == do_toggle_void) {
|
|
|
|
TOGGLE(NO_HELP);
|
|
|
|
window_init();
|
|
|
|
titlebar(NULL);
|
|
|
|
focusing = FALSE;
|
|
|
|
edit_refresh();
|
|
|
|
}
|
|
|
|
#endif
|
2020-01-17 23:37:19 +00:00
|
|
|
else
|
|
|
|
beep();
|
2020-01-26 11:22:49 +00:00
|
|
|
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
/* Ignore the rest of an external paste. */
|
|
|
|
while (bracketed_paste)
|
|
|
|
kbinput = get_kbinput(bottomwin, BLIND);
|
|
|
|
#endif
|
2017-12-29 18:27:33 +00:00
|
|
|
}
|
2005-11-03 21:07:24 +00:00
|
|
|
|
2019-02-10 15:11:57 +00:00
|
|
|
return choice;
|
2005-11-03 21:07:24 +00:00
|
|
|
}
|