2000-08-06 21:13:45 +00:00
|
|
|
|
/* $Id$ */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
/**************************************************************************
|
|
|
|
|
* winio.c *
|
|
|
|
|
* *
|
2004-01-09 23:04:55 +00:00
|
|
|
|
* Copyright (C) 1999-2004 Chris Allegretta *
|
2000-06-06 05:53:49 +00:00
|
|
|
|
* 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 *
|
2001-10-24 11:33:54 +00:00
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option) *
|
2000-06-06 05:53:49 +00:00
|
|
|
|
* 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
|
|
|
|
* *
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
2004-11-17 23:17:05 +00:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#endif
|
2002-09-13 18:14:04 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <string.h>
|
2000-07-07 05:13:09 +00:00
|
|
|
|
#include <stdlib.h>
|
2000-11-24 20:45:14 +00:00
|
|
|
|
#include <unistd.h>
|
2002-06-13 00:40:19 +00:00
|
|
|
|
#include <ctype.h>
|
2002-05-12 19:52:15 +00:00
|
|
|
|
#include <assert.h>
|
2000-06-06 05:53:49 +00:00
|
|
|
|
#include "proto.h"
|
|
|
|
|
#include "nano.h"
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
static buffer *key_buffer = NULL;
|
|
|
|
|
/* The default keystroke buffer,
|
|
|
|
|
* containing all the keystrokes we have
|
|
|
|
|
* at a given point. */
|
|
|
|
|
static size_t key_buffer_len = 0;
|
|
|
|
|
/* The length of the default keystroke
|
|
|
|
|
* buffer. */
|
|
|
|
|
static int statusblank = 0; /* The number of keystrokes left after
|
2004-09-30 22:07:21 +00:00
|
|
|
|
* we call statusbar(), before we
|
|
|
|
|
* actually blank the statusbar. */
|
2004-10-05 20:11:31 +00:00
|
|
|
|
static bool resetstatuspos = FALSE;
|
|
|
|
|
/* Should we reset the cursor position
|
|
|
|
|
* at the statusbar prompt? */
|
2000-06-06 23:04:06 +00:00
|
|
|
|
|
2004-05-01 01:21:38 +00:00
|
|
|
|
/* Control character compatibility:
|
|
|
|
|
*
|
|
|
|
|
* - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
|
|
|
|
|
* VT100, and VT220.
|
|
|
|
|
* - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
|
|
|
|
|
* VT220, and VT320.
|
|
|
|
|
* - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
|
|
|
|
|
* VT220, and VT320.
|
|
|
|
|
* - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
|
|
|
|
|
* VT220, and VT320.
|
|
|
|
|
* - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
|
|
|
|
|
* VT220, and VT320.
|
2004-05-01 04:13:06 +00:00
|
|
|
|
* - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* ANSI, VT100, and VT220, and which is Backspace under VT320.
|
|
|
|
|
*
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
|
2004-05-01 04:13:06 +00:00
|
|
|
|
* default, xterm assumes it's running on a VT320 and generates Ctrl-8
|
|
|
|
|
* (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* problems for VT100-derived terminals such as the FreeBSD console,
|
2004-05-01 04:13:06 +00:00
|
|
|
|
* which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* on which the VT320 sequences are translated by the keypad to KEY_DC
|
|
|
|
|
* and [nothing]. We work around this conflict via the REBIND_DELETE
|
|
|
|
|
* flag: if it's not set, we assume VT320 compatibility, and if it is,
|
|
|
|
|
* we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
|
|
|
|
|
* Hemel for helping work this conflict out.
|
|
|
|
|
*
|
|
|
|
|
* Escape sequence compatibility:
|
|
|
|
|
*
|
|
|
|
|
* We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
|
2004-10-24 22:51:39 +00:00
|
|
|
|
* console, the FreeBSD console, the Mach console (a.k.a. the Hurd
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* console), xterm, rxvt, and Eterm. Among these, there are several
|
|
|
|
|
* conflicts and omissions, outlined as follows:
|
|
|
|
|
*
|
|
|
|
|
* - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
|
|
|
|
|
* (Ctrl-I is also Tab on ANSI, which we already support.)
|
|
|
|
|
* - PageDown on FreeBSD console == Center (5) on numeric keypad with
|
|
|
|
|
* NumLock off on Linux console; the latter is omitted. (The editing
|
|
|
|
|
* keypad key is more important to have working than the numeric
|
2004-05-28 17:23:33 +00:00
|
|
|
|
* keypad key, because the latter has no value when NumLock is off.)
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
|
|
|
|
|
* latter is omitted. (Mouse input will only work properly if the
|
|
|
|
|
* extended keypad value KEY_MOUSE is generated on mouse events
|
|
|
|
|
* instead of the escape sequence.)
|
2004-10-24 22:51:39 +00:00
|
|
|
|
* - F9 on FreeBSD console == PageDown on Mach console; the former is
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* omitted. (The editing keypad is more important to have working
|
|
|
|
|
* than the function keys, because the functions of the former are not
|
|
|
|
|
* arbitrary and the functions of the latter are.)
|
2004-10-24 22:51:39 +00:00
|
|
|
|
* - F10 on FreeBSD console == PageUp on Mach console; the former is
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* omitted. (Same as above.)
|
2004-10-24 22:51:39 +00:00
|
|
|
|
* - F13 on FreeBSD console == End on Mach console; the former is
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* omitted. (Same as above.)
|
2004-11-01 22:40:02 +00:00
|
|
|
|
* - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
|
|
|
|
|
* omitted. (The arrow keys, with or without modifiers, are more
|
|
|
|
|
* important to have working than the function keys, because the
|
|
|
|
|
* functions of the former are not arbitrary and the functions of the
|
|
|
|
|
* latter are.)
|
|
|
|
|
* - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
|
|
|
|
|
* omitted. (Same as above.)
|
2004-05-01 01:21:38 +00:00
|
|
|
|
*
|
|
|
|
|
* Note that Center (5) on the numeric keypad with NumLock off can also
|
|
|
|
|
* be the Begin key. */
|
2004-04-23 18:02:37 +00:00
|
|
|
|
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* Reset all the input routines that rely on character sequences. */
|
|
|
|
|
void reset_kbinput(void)
|
|
|
|
|
{
|
2004-12-04 17:41:52 +00:00
|
|
|
|
parse_kbinput(NULL, NULL, NULL, TRUE);
|
|
|
|
|
get_word_kbinput(0, TRUE);
|
2004-05-28 17:23:33 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Read in a sequence of keystrokes from win and save them in the
|
|
|
|
|
* default keystroke buffer. This should only be called when the
|
|
|
|
|
* default keystroke buffer is empty. */
|
|
|
|
|
void get_buffer(WINDOW *win)
|
2004-08-25 16:37:06 +00:00
|
|
|
|
{
|
2004-12-04 17:41:52 +00:00
|
|
|
|
int input;
|
|
|
|
|
|
|
|
|
|
/* If the keystroke buffer isn't empty, get out. */
|
|
|
|
|
if (key_buffer != NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Read in the first character using blocking input. */
|
|
|
|
|
nodelay(win, FALSE);
|
2003-08-17 02:48:43 +00:00
|
|
|
|
|
2004-02-16 20:32:40 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
allow_pending_sigwinch(TRUE);
|
|
|
|
|
#endif
|
2004-12-04 17:41:52 +00:00
|
|
|
|
input = wgetch(win);
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
allow_pending_sigwinch(FALSE);
|
|
|
|
|
#endif
|
2004-02-16 20:32:40 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Increment the length of the keystroke buffer, save the value of
|
|
|
|
|
* the keystroke in key, and set key_code to TRUE if the keystroke
|
|
|
|
|
* is an extended keypad value and hence shouldn't be treated as a
|
|
|
|
|
* multibyte character. */
|
|
|
|
|
key_buffer_len++;
|
|
|
|
|
key_buffer = (buffer *)nmalloc(sizeof(buffer));
|
|
|
|
|
key_buffer[0].key = input;
|
|
|
|
|
key_buffer[0].key_code = !is_byte_char(input);
|
2003-08-17 02:48:43 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Read in the remaining characters using non-blocking input. */
|
|
|
|
|
nodelay(win, TRUE);
|
|
|
|
|
|
|
|
|
|
while (TRUE) {
|
2004-02-16 20:32:40 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-12-04 17:41:52 +00:00
|
|
|
|
allow_pending_sigwinch(TRUE);
|
2004-02-16 20:32:40 +00:00
|
|
|
|
#endif
|
2004-12-04 17:41:52 +00:00
|
|
|
|
input = wgetch(win);
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
allow_pending_sigwinch(FALSE);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* If there aren't any more characters, stop reading. */
|
|
|
|
|
if (input == ERR)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Otherwise, increment the length of the keystroke buffer, save
|
|
|
|
|
* the value of the keystroke in key, and set key_code to TRUE
|
|
|
|
|
* if the keystroke is an extended keypad value and hence
|
|
|
|
|
* shouldn't be treated as a multibyte character. */
|
|
|
|
|
key_buffer_len++;
|
|
|
|
|
key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
|
|
|
|
|
sizeof(buffer));
|
|
|
|
|
key_buffer[key_buffer_len - 1].key = input;
|
|
|
|
|
key_buffer[key_buffer_len - 1].key_code = !is_byte_char(input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Switch back to non-blocking input. */
|
|
|
|
|
nodelay(win, FALSE);
|
2004-02-16 20:32:40 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
#ifdef NANO_WIDE
|
|
|
|
|
if (!ISSET(NO_UTF8)) {
|
2004-12-07 17:35:14 +00:00
|
|
|
|
size_t i;
|
2004-12-06 04:14:42 +00:00
|
|
|
|
buffer *clean_key_buffer = NULL;
|
|
|
|
|
size_t clean_key_buffer_len = 0;
|
|
|
|
|
|
2004-12-08 16:52:52 +00:00
|
|
|
|
mbtowc(NULL, NULL, 0);
|
|
|
|
|
|
2004-12-08 15:47:38 +00:00
|
|
|
|
/* Change all complete and valid multibyte keystrokes to
|
|
|
|
|
* their wide character values, discarding the others. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
for (i = 0; i < key_buffer_len; i++) {
|
|
|
|
|
wchar_t wide_key;
|
2004-12-08 15:47:38 +00:00
|
|
|
|
int wide_key_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
|
2004-12-08 15:47:38 +00:00
|
|
|
|
if (key_buffer[i].key_code) {
|
|
|
|
|
wide_key_len = 1;
|
|
|
|
|
wide_key = key_buffer[i].key;
|
|
|
|
|
} else
|
|
|
|
|
wide_key_len = mbtowc(&wide_key,
|
|
|
|
|
(const char *)&key_buffer[i].key, 1);
|
2004-11-16 22:51:07 +00:00
|
|
|
|
|
2004-12-08 15:47:38 +00:00
|
|
|
|
if (wide_key_len != -1) {
|
2004-12-06 04:14:42 +00:00
|
|
|
|
clean_key_buffer_len++;
|
|
|
|
|
clean_key_buffer = (buffer *)nrealloc(clean_key_buffer,
|
|
|
|
|
clean_key_buffer_len * sizeof(buffer));
|
2004-12-04 17:41:52 +00:00
|
|
|
|
|
2004-12-06 04:14:42 +00:00
|
|
|
|
clean_key_buffer[clean_key_buffer_len - 1].key =
|
2004-12-08 15:47:38 +00:00
|
|
|
|
wide_key;
|
2004-12-06 04:14:42 +00:00
|
|
|
|
clean_key_buffer[clean_key_buffer_len - 1].key_code =
|
2004-12-04 17:41:52 +00:00
|
|
|
|
key_buffer[i].key_code;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
}
|
2003-08-17 02:48:43 +00:00
|
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
|
2004-12-08 16:52:52 +00:00
|
|
|
|
mbtowc(NULL, NULL, 0);
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Replace the default keystroke buffer with the non-(-1)
|
|
|
|
|
* keystroke buffer. */
|
2004-12-06 04:14:42 +00:00
|
|
|
|
key_buffer_len = clean_key_buffer_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
free(key_buffer);
|
2004-12-06 04:14:42 +00:00
|
|
|
|
key_buffer = clean_key_buffer;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
2003-08-17 02:48:43 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Return the length of the default keystroke buffer. */
|
|
|
|
|
size_t get_buffer_len(void)
|
|
|
|
|
{
|
|
|
|
|
return key_buffer_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return the key values stored in the keystroke buffer input,
|
|
|
|
|
* discarding the key_code values in it. */
|
|
|
|
|
int *buffer_to_keys(buffer *input, size_t input_len)
|
|
|
|
|
{
|
|
|
|
|
int *sequence = (int *)nmalloc(input_len * sizeof(int));
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < input_len; i++)
|
|
|
|
|
sequence[i] = input[i].key;
|
|
|
|
|
|
|
|
|
|
return sequence;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add the contents of the keystroke buffer input to the default
|
|
|
|
|
* keystroke buffer. */
|
|
|
|
|
void unget_input(buffer *input, size_t input_len)
|
|
|
|
|
{
|
2004-12-06 04:14:42 +00:00
|
|
|
|
buffer *clean_input = NULL;
|
|
|
|
|
size_t clean_input_len = 0;
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
allow_pending_sigwinch(TRUE);
|
|
|
|
|
allow_pending_sigwinch(FALSE);
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
2004-01-27 07:12:47 +00:00
|
|
|
|
|
2004-12-06 04:14:42 +00:00
|
|
|
|
#ifdef NANO_WIDE
|
|
|
|
|
if (!ISSET(NO_UTF8)) {
|
2004-12-07 17:35:14 +00:00
|
|
|
|
size_t i;
|
|
|
|
|
|
2004-12-08 16:52:52 +00:00
|
|
|
|
wctomb(NULL, 0);
|
|
|
|
|
|
2004-12-08 15:47:38 +00:00
|
|
|
|
/* Keep all valid wide keystrokes, discarding the others. */
|
2004-12-06 04:14:42 +00:00
|
|
|
|
for (i = 0; i < input_len; i++) {
|
2004-12-07 22:24:03 +00:00
|
|
|
|
char key[MB_LEN_MAX];
|
2004-12-08 15:47:38 +00:00
|
|
|
|
int key_len = input[i].key_code ? 1 :
|
|
|
|
|
wctomb(key, input[i].key);
|
2004-12-07 22:24:03 +00:00
|
|
|
|
|
2004-12-08 15:47:38 +00:00
|
|
|
|
if (key_len != -1) {
|
2004-12-06 04:14:42 +00:00
|
|
|
|
clean_input_len++;
|
|
|
|
|
clean_input = (buffer *)nrealloc(clean_input,
|
|
|
|
|
clean_input_len * sizeof(buffer));
|
|
|
|
|
|
|
|
|
|
clean_input[clean_input_len - 1].key = input[i].key;
|
|
|
|
|
clean_input[clean_input_len - 1].key_code =
|
|
|
|
|
input[i].key_code;
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-12-08 16:52:52 +00:00
|
|
|
|
|
|
|
|
|
wctomb(NULL, 0);
|
|
|
|
|
|
2004-12-06 04:14:42 +00:00
|
|
|
|
} else {
|
|
|
|
|
#endif
|
|
|
|
|
clean_input = input;
|
|
|
|
|
clean_input_len = input_len;
|
|
|
|
|
#ifdef NANO_WIDE
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* If input is empty, get out. */
|
2004-12-06 04:14:42 +00:00
|
|
|
|
if (clean_input_len == 0)
|
2004-12-04 17:41:52 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* If adding input would put the default keystroke buffer beyond
|
|
|
|
|
* maximum capacity, only add enough of input to put it at maximum
|
|
|
|
|
* capacity. */
|
2004-12-06 04:14:42 +00:00
|
|
|
|
if (key_buffer_len + clean_input_len < key_buffer_len)
|
|
|
|
|
clean_input_len = (size_t)-1 - key_buffer_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
|
|
|
|
|
/* Add the length of input to the length of the default keystroke
|
|
|
|
|
* buffer, and reallocate the default keystroke buffer so that it
|
|
|
|
|
* has enough room for input. */
|
2004-12-06 04:14:42 +00:00
|
|
|
|
key_buffer_len += clean_input_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
|
|
|
|
|
sizeof(buffer));
|
|
|
|
|
|
|
|
|
|
/* If the default keystroke buffer wasn't empty before, move its
|
|
|
|
|
* beginning forward far enough so that we can add input to its
|
|
|
|
|
* beginning. */
|
2004-12-06 04:14:42 +00:00
|
|
|
|
if (key_buffer_len > clean_input_len)
|
|
|
|
|
memmove(key_buffer + clean_input_len, key_buffer,
|
|
|
|
|
(key_buffer_len - clean_input_len) * sizeof(buffer));
|
2004-12-04 17:41:52 +00:00
|
|
|
|
|
|
|
|
|
/* Copy input to the beginning of the default keystroke buffer. */
|
2004-12-06 04:14:42 +00:00
|
|
|
|
memcpy(key_buffer, clean_input, clean_input_len * sizeof(buffer));
|
2004-12-04 17:41:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Put back the character stored in kbinput. If func_key is TRUE and
|
|
|
|
|
* the character is out of byte range, interpret it as an extended
|
|
|
|
|
* keypad value. If meta_key is TRUE, put back the Escape character
|
|
|
|
|
* after putting back kbinput. */
|
|
|
|
|
void unget_kbinput(int kbinput, bool meta_key, bool func_key)
|
|
|
|
|
{
|
|
|
|
|
buffer input;
|
|
|
|
|
|
|
|
|
|
input.key = kbinput;
|
|
|
|
|
input.key_code = (func_key && !is_byte_char(kbinput));
|
|
|
|
|
|
|
|
|
|
unget_input(&input, 1);
|
|
|
|
|
|
|
|
|
|
if (meta_key) {
|
|
|
|
|
input.key = NANO_CONTROL_3;
|
|
|
|
|
input.key_code = FALSE;
|
|
|
|
|
unget_input(&input, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Try to read input_len characters from the default keystroke buffer.
|
|
|
|
|
* If the default keystroke buffer is empty and win isn't NULL, try to
|
|
|
|
|
* read in more characters from win and add them to the default
|
|
|
|
|
* keystroke buffer before doing anything else. If the default
|
|
|
|
|
* keystroke buffer is empty and win is NULL, return NULL. */
|
|
|
|
|
buffer *get_input(WINDOW *win, size_t input_len)
|
|
|
|
|
{
|
|
|
|
|
buffer *input;
|
|
|
|
|
|
2004-02-16 20:32:40 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-12-04 17:41:52 +00:00
|
|
|
|
allow_pending_sigwinch(TRUE);
|
2004-02-16 20:32:40 +00:00
|
|
|
|
allow_pending_sigwinch(FALSE);
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (key_buffer_len == 0) {
|
|
|
|
|
if (win != NULL)
|
|
|
|
|
get_buffer(win);
|
|
|
|
|
|
|
|
|
|
if (key_buffer_len == 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If input_len is greater than the length of the default keystroke
|
|
|
|
|
* buffer, only read the number of characters in the default
|
|
|
|
|
* keystroke buffer. */
|
|
|
|
|
if (input_len > key_buffer_len)
|
|
|
|
|
input_len = key_buffer_len;
|
|
|
|
|
|
|
|
|
|
/* Subtract input_len from the length of the default keystroke
|
|
|
|
|
* buffer, and allocate the keystroke buffer input so that it
|
|
|
|
|
* has enough room for input_len keystrokes. */
|
|
|
|
|
key_buffer_len -= input_len;
|
|
|
|
|
input = (buffer *)nmalloc(input_len * sizeof(buffer));
|
|
|
|
|
|
|
|
|
|
/* Copy input_len characters from the beginning of the default
|
|
|
|
|
* keystroke buffer into input. */
|
|
|
|
|
memcpy(input, key_buffer, input_len * sizeof(buffer));
|
|
|
|
|
|
|
|
|
|
/* If the default keystroke buffer is empty, mark it as such. */
|
|
|
|
|
if (key_buffer_len == 0) {
|
|
|
|
|
free(key_buffer);
|
|
|
|
|
key_buffer = NULL;
|
|
|
|
|
/* If the default keystroke buffer isn't empty, move its
|
|
|
|
|
* beginning forward far enough back so that the keystrokes in input
|
|
|
|
|
* are no longer at its beginning. */
|
|
|
|
|
} else {
|
|
|
|
|
memmove(key_buffer, key_buffer + input_len, key_buffer_len *
|
|
|
|
|
sizeof(buffer));
|
|
|
|
|
key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
|
|
|
|
|
sizeof(buffer));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return input;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Read in a single character. If it's ignored, swallow it and go on.
|
|
|
|
|
* Otherwise, try to translate it from ASCII, meta key sequences, escape
|
|
|
|
|
* sequences, and/or extended keypad values. Set meta_key to TRUE when
|
|
|
|
|
* we get a meta key sequence, and set func_key to TRUE when we get an
|
|
|
|
|
* extended keypad value. Supported extended keypad values consist of
|
|
|
|
|
* [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
|
|
|
|
|
* the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
|
|
|
|
|
* the function keypad (F1-F16), and the numeric keypad with NumLock
|
|
|
|
|
* off. Assume nodelay(win) is FALSE. */
|
|
|
|
|
int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
|
|
|
|
|
{
|
|
|
|
|
int kbinput;
|
|
|
|
|
|
|
|
|
|
/* Read in a character and interpret it. Continue doing this until
|
|
|
|
|
* we get a recognized value or sequence. */
|
|
|
|
|
while ((kbinput = parse_kbinput(win, meta_key, func_key
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
, FALSE
|
|
|
|
|
#endif
|
|
|
|
|
)) == ERR);
|
|
|
|
|
|
|
|
|
|
return kbinput;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Translate ASCII characters, extended keypad values, and escape
|
|
|
|
|
* sequences into their corresponding key values. Set meta_key to TRUE
|
|
|
|
|
* when we get a meta key sequence, and set func_key to TRUE when we get
|
|
|
|
|
* a function key. Assume nodelay(win) is FALSE. */
|
|
|
|
|
int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-08-25 15:39:10 +00:00
|
|
|
|
, bool reset
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
|
|
|
|
)
|
2004-12-04 17:41:52 +00:00
|
|
|
|
|
2003-08-17 02:48:43 +00:00
|
|
|
|
{
|
2004-07-28 20:46:25 +00:00
|
|
|
|
static int escapes = 0;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
static int word_digits = 0;
|
|
|
|
|
buffer *kbinput;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
int retval = ERR;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
|
2004-05-28 17:23:33 +00:00
|
|
|
|
if (reset) {
|
|
|
|
|
escapes = 0;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
word_digits = 0;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
return ERR;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
*meta_key = FALSE;
|
|
|
|
|
*func_key = FALSE;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Read in a character. */
|
|
|
|
|
while ((kbinput = get_input(win, 1)) == NULL);
|
|
|
|
|
|
|
|
|
|
if (kbinput->key_code || is_byte_char(kbinput->key)) {
|
2004-12-06 04:14:42 +00:00
|
|
|
|
/* If we got an extended keypad value or an ASCII character,
|
|
|
|
|
* translate it. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
switch (kbinput->key) {
|
|
|
|
|
case ERR:
|
|
|
|
|
break;
|
|
|
|
|
case NANO_CONTROL_3:
|
|
|
|
|
/* Increment the escape counter. */
|
|
|
|
|
escapes++;
|
|
|
|
|
switch (escapes) {
|
|
|
|
|
case 1:
|
|
|
|
|
/* One escape: wait for more input. */
|
|
|
|
|
case 2:
|
|
|
|
|
/* Two escapes: wait for more input. */
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* More than two escapes: reset the escape
|
|
|
|
|
* counter and wait for more input. */
|
|
|
|
|
escapes = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Since we don't change the default SIGWINCH handler when
|
|
|
|
|
* NANO_SMALL is defined, KEY_RESIZE is never generated.
|
|
|
|
|
* Also, Slang and SunOS 5.7-5.9 don't support
|
|
|
|
|
* KEY_RESIZE. */
|
|
|
|
|
case KEY_RESIZE:
|
|
|
|
|
break;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef PDCURSES
|
2004-12-04 17:41:52 +00:00
|
|
|
|
case KEY_SHIFT_L:
|
|
|
|
|
case KEY_SHIFT_R:
|
|
|
|
|
case KEY_CONTROL_L:
|
|
|
|
|
case KEY_CONTROL_R:
|
|
|
|
|
case KEY_ALT_L:
|
|
|
|
|
case KEY_ALT_R:
|
|
|
|
|
break;
|
2004-06-04 22:28:55 +00:00
|
|
|
|
#endif
|
2004-12-04 17:41:52 +00:00
|
|
|
|
default:
|
|
|
|
|
switch (escapes) {
|
|
|
|
|
case 0:
|
|
|
|
|
switch (kbinput->key) {
|
|
|
|
|
case NANO_CONTROL_8:
|
|
|
|
|
retval = ISSET(REBIND_DELETE) ?
|
|
|
|
|
NANO_DELETE_KEY :
|
|
|
|
|
NANO_BACKSPACE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_DOWN:
|
|
|
|
|
retval = NANO_NEXTLINE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_UP:
|
|
|
|
|
retval = NANO_PREVLINE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_LEFT:
|
|
|
|
|
retval = NANO_BACK_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_RIGHT:
|
|
|
|
|
retval = NANO_FORWARD_KEY;
|
|
|
|
|
break;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
#ifdef KEY_HOME
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* HP-UX 10 and 11 don't support
|
|
|
|
|
* KEY_HOME. */
|
|
|
|
|
case KEY_HOME:
|
|
|
|
|
retval = NANO_HOME_KEY;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
case KEY_BACKSPACE:
|
|
|
|
|
retval = NANO_BACKSPACE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_DC:
|
|
|
|
|
retval = ISSET(REBIND_DELETE) ?
|
|
|
|
|
NANO_BACKSPACE_KEY :
|
|
|
|
|
NANO_DELETE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_IC:
|
|
|
|
|
retval = NANO_INSERTFILE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_NPAGE:
|
|
|
|
|
retval = NANO_NEXTPAGE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_PPAGE:
|
|
|
|
|
retval = NANO_PREVPAGE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_ENTER:
|
|
|
|
|
retval = NANO_ENTER_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_A1: /* Home (7) on numeric
|
|
|
|
|
* keypad with NumLock
|
|
|
|
|
* off. */
|
|
|
|
|
retval = NANO_HOME_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_A3: /* PageUp (9) on numeric
|
|
|
|
|
* keypad with NumLock
|
|
|
|
|
* off. */
|
|
|
|
|
retval = NANO_PREVPAGE_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_B2: /* Center (5) on numeric
|
|
|
|
|
* keypad with NumLock
|
|
|
|
|
* off. */
|
|
|
|
|
break;
|
|
|
|
|
case KEY_C1: /* End (1) on numeric
|
|
|
|
|
* keypad with NumLock
|
|
|
|
|
* off. */
|
|
|
|
|
retval = NANO_END_KEY;
|
|
|
|
|
break;
|
|
|
|
|
case KEY_C3: /* PageDown (4) on
|
|
|
|
|
* numeric keypad with
|
|
|
|
|
* NumLock off. */
|
|
|
|
|
retval = NANO_NEXTPAGE_KEY;
|
|
|
|
|
break;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
#ifdef KEY_BEG
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Slang doesn't support KEY_BEG. */
|
|
|
|
|
case KEY_BEG: /* Center (5) on numeric
|
|
|
|
|
* keypad with NumLock
|
|
|
|
|
* off. */
|
|
|
|
|
break;
|
2004-06-03 20:26:12 +00:00
|
|
|
|
#endif
|
2004-04-23 18:02:37 +00:00
|
|
|
|
#ifdef KEY_END
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* HP-UX 10 and 11 don't support KEY_END. */
|
|
|
|
|
case KEY_END:
|
|
|
|
|
retval = NANO_END_KEY;
|
|
|
|
|
break;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef KEY_SUSPEND
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Slang doesn't support KEY_SUSPEND. */
|
|
|
|
|
case KEY_SUSPEND:
|
|
|
|
|
retval = NANO_SUSPEND_KEY;
|
|
|
|
|
break;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef KEY_SLEFT
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Slang doesn't support KEY_SLEFT. */
|
|
|
|
|
case KEY_SLEFT:
|
|
|
|
|
retval = NANO_BACK_KEY;
|
|
|
|
|
break;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef KEY_SRIGHT
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Slang doesn't support KEY_SRIGHT. */
|
|
|
|
|
case KEY_SRIGHT:
|
|
|
|
|
retval = NANO_FORWARD_KEY;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
default:
|
|
|
|
|
retval = kbinput->key;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
/* One escape followed by a non-escape: escape
|
|
|
|
|
* sequence mode. Reset the escape counter. If
|
|
|
|
|
* there aren't any other keys waiting, we have
|
|
|
|
|
* a meta key sequence, so set meta_key to TRUE
|
|
|
|
|
* and save the lowercase version of the
|
|
|
|
|
* non-escape character as the result. If there
|
|
|
|
|
* are other keys waiting, we have a true escape
|
|
|
|
|
* sequence, so interpret it. */
|
|
|
|
|
escapes = 0;
|
|
|
|
|
if (get_buffer_len() == 0) {
|
|
|
|
|
*meta_key = TRUE;
|
|
|
|
|
retval = tolower(kbinput->key);
|
|
|
|
|
} else {
|
|
|
|
|
buffer *escape_kbinput;
|
|
|
|
|
int *sequence;
|
|
|
|
|
size_t seq_len;
|
|
|
|
|
bool ignore_seq;
|
|
|
|
|
|
|
|
|
|
/* Put back the non-escape character, get
|
|
|
|
|
* the complete escape sequence, translate
|
|
|
|
|
* its key values into the corresponding key
|
|
|
|
|
* value, and save that as the result. */
|
|
|
|
|
unget_input(kbinput, 1);
|
|
|
|
|
seq_len = get_buffer_len();
|
|
|
|
|
escape_kbinput = get_input(NULL, seq_len);
|
|
|
|
|
sequence = buffer_to_keys(escape_kbinput,
|
|
|
|
|
seq_len);
|
|
|
|
|
retval = get_escape_seq_kbinput(sequence,
|
|
|
|
|
seq_len, &ignore_seq);
|
|
|
|
|
|
|
|
|
|
/* If the escape sequence is unrecognized
|
|
|
|
|
* and not ignored, put back all of its
|
|
|
|
|
* characters except for the initial
|
|
|
|
|
* escape. */
|
|
|
|
|
if (retval == ERR && !ignore_seq)
|
|
|
|
|
unget_input(escape_kbinput, seq_len);
|
|
|
|
|
|
|
|
|
|
free(escape_kbinput);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
2004-11-29 00:30:07 +00:00
|
|
|
|
/* Two escapes followed by one or more decimal
|
2004-12-04 17:41:52 +00:00
|
|
|
|
* digits: word sequence mode. If the word
|
|
|
|
|
* sequence's range is limited to 6XXXX (the
|
|
|
|
|
* first digit is in the '0' to '6' range and
|
|
|
|
|
* it's the first digit, or it's in the '0' to
|
|
|
|
|
* '9' range and it's not the first digit),
|
2004-12-06 04:14:42 +00:00
|
|
|
|
* increment the word sequence counter and
|
|
|
|
|
* interpret the digit. If the word sequence's
|
|
|
|
|
* range is not limited to 6XXXX, fall
|
|
|
|
|
* through. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (('0' <= kbinput->key && kbinput->key <= '6'
|
|
|
|
|
&& word_digits == 0) ||
|
|
|
|
|
('0' <= kbinput->key && kbinput->key <= '9'
|
|
|
|
|
&& word_digits > 0)) {
|
2004-12-06 04:14:42 +00:00
|
|
|
|
int word_kbinput;
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
word_digits++;
|
2004-12-06 04:14:42 +00:00
|
|
|
|
word_kbinput = get_word_kbinput(kbinput->key
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-11-29 00:30:07 +00:00
|
|
|
|
, FALSE
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
2004-11-29 00:30:07 +00:00
|
|
|
|
);
|
|
|
|
|
|
2004-12-06 04:14:42 +00:00
|
|
|
|
if (word_kbinput != ERR) {
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* If we've read in a complete word
|
|
|
|
|
* sequence, reset the word sequence
|
2004-12-06 04:14:42 +00:00
|
|
|
|
* counter and the escape counter,
|
|
|
|
|
* and put back the corresponding word
|
|
|
|
|
* value. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
word_digits = 0;
|
2004-11-29 00:30:07 +00:00
|
|
|
|
escapes = 0;
|
2004-12-06 04:14:42 +00:00
|
|
|
|
unget_kbinput(word_kbinput, FALSE,
|
|
|
|
|
FALSE);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* Reset the escape counter. */
|
|
|
|
|
escapes = 0;
|
|
|
|
|
if (word_digits == 0)
|
|
|
|
|
/* Two escapes followed by a non-decimal
|
|
|
|
|
* digit or a decimal digit that would
|
|
|
|
|
* create a word sequence greater than
|
|
|
|
|
* 6XXXX, and we're not in the middle of
|
|
|
|
|
* a word sequence: control character
|
|
|
|
|
* sequence mode. Interpret the control
|
|
|
|
|
* sequence and save the corresponding
|
|
|
|
|
* control character as the result. */
|
|
|
|
|
retval = get_control_kbinput(kbinput->key);
|
|
|
|
|
else {
|
|
|
|
|
/* If we're in the middle of a word
|
|
|
|
|
* sequence, reset the word sequence
|
|
|
|
|
* counter and save the character we got
|
|
|
|
|
* as the result. */
|
|
|
|
|
word_digits = 0;
|
|
|
|
|
retval = kbinput->key;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
}
|
2004-11-29 00:30:07 +00:00
|
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-08-17 02:48:43 +00:00
|
|
|
|
|
2004-12-06 04:14:42 +00:00
|
|
|
|
/* If we have a result and it's an extended keypad value, set
|
|
|
|
|
* func_key to TRUE. */
|
|
|
|
|
if (retval != ERR)
|
|
|
|
|
*func_key = !is_byte_char(retval);
|
|
|
|
|
} else
|
|
|
|
|
/* If we didn't get an extended keypad value or an ASCII
|
|
|
|
|
* character, leave it as-is. */
|
|
|
|
|
retval = kbinput->key;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2004-12-04 17:41:52 +00:00
|
|
|
|
fprintf(stderr, "parse_kbinput(): kbinput->key = %d, meta_key = %d, func_key = %d, escapes = %d, word_digits = %d, retval = %d\n", kbinput->key, (int)*meta_key, (int)*func_key, escapes, word_digits, retval);
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Return the result. */
|
2003-08-17 02:48:43 +00:00
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-27 07:12:47 +00:00
|
|
|
|
/* Translate escape sequences, most of which correspond to extended
|
2004-11-27 23:28:39 +00:00
|
|
|
|
* keypad values, into their corresponding key values. These sequences
|
2004-06-04 18:18:17 +00:00
|
|
|
|
* are generated when the keypad doesn't support the needed keys. If
|
|
|
|
|
* the escape sequence is recognized but we want to ignore it, return
|
|
|
|
|
* ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
|
|
|
|
|
* set ignore_seq to FALSE. Assume that Escape has already been read
|
|
|
|
|
* in. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
|
2004-06-04 18:18:17 +00:00
|
|
|
|
*ignore_seq)
|
2003-08-17 02:48:43 +00:00
|
|
|
|
{
|
2004-05-28 17:23:33 +00:00
|
|
|
|
int retval = ERR;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
|
2004-06-04 18:18:17 +00:00
|
|
|
|
*ignore_seq = FALSE;
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (seq_len > 1) {
|
|
|
|
|
switch (sequence[0]) {
|
2003-12-24 03:33:09 +00:00
|
|
|
|
case 'O':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
switch (sequence[1]) {
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case '2':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (seq_len >= 3) {
|
|
|
|
|
switch (sequence[2]) {
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case 'P': /* Esc O 2 P == F13 on
|
|
|
|
|
* xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(13);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'Q': /* Esc O 2 Q == F14 on
|
|
|
|
|
* xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(14);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-11-01 22:40:02 +00:00
|
|
|
|
case 'R': /* Esc O 2 R == F15 on
|
|
|
|
|
* xterm. */
|
|
|
|
|
retval = KEY_F(15);
|
|
|
|
|
break;
|
|
|
|
|
case 'S': /* Esc O 2 S == F16 on
|
|
|
|
|
* xterm. */
|
|
|
|
|
retval = KEY_F(16);
|
|
|
|
|
break;
|
2004-01-23 19:26:17 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
|
|
|
|
|
case 'B': /* Esc O B == Down on
|
|
|
|
|
* VT100/VT320/xterm. */
|
|
|
|
|
case 'C': /* Esc O C == Right on
|
|
|
|
|
* VT100/VT320/xterm. */
|
|
|
|
|
case 'D': /* Esc O D == Left on
|
|
|
|
|
* VT100/VT320/xterm. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
retval = get_escape_seq_abcd(sequence[1]);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
case 'E': /* Esc O E == Center (5) on numeric keypad
|
|
|
|
|
* with NumLock off on xterm. */
|
2004-06-04 18:18:17 +00:00
|
|
|
|
*ignore_seq = TRUE;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
case 'F': /* Esc O F == End on xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_END_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'H': /* Esc O H == Home on xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_HOME_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
case 'M': /* Esc O M == Enter on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
|
|
|
|
* Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_ENTER_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(1);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(2);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(3);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
|
2004-05-01 01:21:38 +00:00
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(4);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'T': /* Esc O T == F5 on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(5);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'U': /* Esc O U == F6 on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(6);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'V': /* Esc O V == F7 on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(7);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'W': /* Esc O W == F8 on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(8);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'X': /* Esc O X == F9 on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(9);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'Y': /* Esc O Y == F10 on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(10);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'a': /* Esc O a == Ctrl-Up on rxvt. */
|
|
|
|
|
case 'b': /* Esc O b == Ctrl-Down on rxvt. */
|
|
|
|
|
case 'c': /* Esc O c == Ctrl-Right on rxvt. */
|
2003-12-24 03:33:09 +00:00
|
|
|
|
case 'd': /* Esc O d == Ctrl-Left on rxvt. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
retval = get_escape_seq_abcd(sequence[1]);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
case 'j': /* Esc O j == '*' on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = '*';
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'k': /* Esc O k == '+' on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = '+';
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'l': /* Esc O l == ',' on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = '+';
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'm': /* Esc O m == '-' on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = '-';
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'n': /* Esc O n == Delete (.) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* xterm/rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_DELETE_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'o': /* Esc O o == '/' on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = '/';
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'p': /* Esc O p == Insert (0) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_INSERTFILE_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'q': /* Esc O q == End (1) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_END_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'r': /* Esc O r == Down (2) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_NEXTLINE_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 's': /* Esc O s == PageDown (3) on numeric
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* keypad with NumLock off on VT100/VT220/
|
|
|
|
|
* VT320/rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_NEXTPAGE_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 't': /* Esc O t == Left (4) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_BACK_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'u': /* Esc O u == Center (5) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* rxvt/Eterm. */
|
2004-06-04 18:18:17 +00:00
|
|
|
|
*ignore_seq = TRUE;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'v': /* Esc O v == Right (6) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_FORWARD_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'w': /* Esc O w == Home (7) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_HOME_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'x': /* Esc O x == Up (8) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_PREVLINE_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'y': /* Esc O y == PageUp (9) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
|
|
|
|
* rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_PREVPAGE_KEY;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
switch (sequence[1]) {
|
2003-12-24 03:33:09 +00:00
|
|
|
|
case 'a': /* Esc o a == Ctrl-Up on Eterm. */
|
|
|
|
|
case 'b': /* Esc o b == Ctrl-Down on Eterm. */
|
|
|
|
|
case 'c': /* Esc o c == Ctrl-Right on Eterm. */
|
|
|
|
|
case 'd': /* Esc o d == Ctrl-Left on Eterm. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
retval = get_escape_seq_abcd(sequence[1]);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '[':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
switch (sequence[1]) {
|
2003-12-24 03:33:09 +00:00
|
|
|
|
case '1':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (seq_len >= 3) {
|
|
|
|
|
switch (sequence[2]) {
|
2004-06-22 14:30:18 +00:00
|
|
|
|
case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
|
|
|
|
|
* Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(1);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-06-22 14:30:18 +00:00
|
|
|
|
case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
|
|
|
|
|
* Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(2);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-06-22 14:30:18 +00:00
|
|
|
|
case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
|
|
|
|
|
* Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(3);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-06-22 14:30:18 +00:00
|
|
|
|
case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
|
|
|
|
|
* Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(4);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-06-22 14:30:18 +00:00
|
|
|
|
case '5': /* Esc [ 1 5 ~ == F5 on xterm/
|
|
|
|
|
* rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(5);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '7': /* Esc [ 1 7 ~ == F6 on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* xterm/rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(6);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '8': /* Esc [ 1 8 ~ == F7 on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* xterm/rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(7);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '9': /* Esc [ 1 9 ~ == F8 on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* xterm/rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(8);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-02-06 03:07:10 +00:00
|
|
|
|
case ';':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (seq_len >= 4) {
|
|
|
|
|
switch (sequence[3]) {
|
2004-02-06 03:07:10 +00:00
|
|
|
|
case '2':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (seq_len >= 5) {
|
|
|
|
|
switch (sequence[4]) {
|
2004-02-06 03:07:10 +00:00
|
|
|
|
case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
|
|
|
|
|
* xterm. */
|
|
|
|
|
case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
|
|
|
|
|
* xterm. */
|
|
|
|
|
case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
|
|
|
|
|
* xterm. */
|
|
|
|
|
case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
|
|
|
|
|
* xterm. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
retval = get_escape_seq_abcd(sequence[4]);
|
2004-02-06 03:07:10 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '5':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (seq_len >= 5) {
|
|
|
|
|
switch (sequence[4]) {
|
2004-02-06 03:07:10 +00:00
|
|
|
|
case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
|
|
|
|
|
* xterm. */
|
|
|
|
|
case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
|
|
|
|
|
* xterm. */
|
|
|
|
|
case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
|
|
|
|
|
* xterm. */
|
|
|
|
|
case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
|
|
|
|
|
* xterm. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
retval = get_escape_seq_abcd(sequence[4]);
|
2004-02-06 03:07:10 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
default: /* Esc [ 1 ~ == Home on
|
|
|
|
|
* VT320/Linux console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_HOME_KEY;
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '2':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (seq_len >= 3) {
|
|
|
|
|
switch (sequence[2]) {
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '0': /* Esc [ 2 0 ~ == F9 on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* xterm/rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(9);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '1': /* Esc [ 2 1 ~ == F10 on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* xterm/rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(10);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '3': /* Esc [ 2 3 ~ == F11 on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* xterm/rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(11);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '4': /* Esc [ 2 4 ~ == F12 on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* xterm/rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(12);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '5': /* Esc [ 2 5 ~ == F13 on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(13);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '6': /* Esc [ 2 6 ~ == F14 on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* rxvt/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(14);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-11-01 22:40:02 +00:00
|
|
|
|
case '8': /* Esc [ 2 8 ~ == F15 on
|
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* rxvt/Eterm. */
|
|
|
|
|
retval = KEY_F(15);
|
|
|
|
|
break;
|
|
|
|
|
case '9': /* Esc [ 2 9 ~ == F16 on
|
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* rxvt/Eterm. */
|
|
|
|
|
retval = KEY_F(16);
|
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
default: /* Esc [ 2 ~ == Insert on
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* VT220/VT320/Linux console/
|
|
|
|
|
* xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_INSERTFILE_KEY;
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2003-12-24 03:33:09 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2004-06-22 14:30:18 +00:00
|
|
|
|
case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
|
|
|
|
|
* Linux console/xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_DELETE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
|
2003-12-24 03:33:09 +00:00
|
|
|
|
* console/xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_END_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-06-22 14:30:18 +00:00
|
|
|
|
case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
|
|
|
|
|
* Linux console/xterm; Esc [ 5 ^ ==
|
|
|
|
|
* PageUp on Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_PREVPAGE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-06-22 14:30:18 +00:00
|
|
|
|
case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
|
|
|
|
|
* Linux console/xterm; Esc [ 6 ^ ==
|
|
|
|
|
* PageDown on Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_NEXTPAGE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case '7': /* Esc [ 7 ~ == Home on rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_HOME_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case '8': /* Esc [ 8 ~ == End on rxvt. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_END_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case '9': /* Esc [ 9 == Delete on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_DELETE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case '@': /* Esc [ @ == Insert on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_INSERTFILE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
|
2004-10-24 22:51:39 +00:00
|
|
|
|
* console/FreeBSD console/Mach console/
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* rxvt/Eterm. */
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
|
2004-10-24 22:51:39 +00:00
|
|
|
|
* console/FreeBSD console/Mach console/
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* rxvt/Eterm. */
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
|
2004-10-24 22:51:39 +00:00
|
|
|
|
* console/FreeBSD console/Mach console/
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* rxvt/Eterm. */
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
|
2004-10-24 22:51:39 +00:00
|
|
|
|
* console/FreeBSD console/Mach console/
|
2004-06-22 14:30:18 +00:00
|
|
|
|
* rxvt/Eterm. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
retval = get_escape_seq_abcd(sequence[1]);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
case 'E': /* Esc [ E == Center (5) on numeric keypad
|
|
|
|
|
* with NumLock off on FreeBSD console. */
|
2004-06-04 18:18:17 +00:00
|
|
|
|
*ignore_seq = TRUE;
|
2004-04-23 18:02:37 +00:00
|
|
|
|
break;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
case 'F': /* Esc [ F == End on FreeBSD
|
|
|
|
|
* console/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_END_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'G': /* Esc [ G == PageDown on FreeBSD
|
2004-04-23 18:02:37 +00:00
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_NEXTPAGE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
|
2004-10-24 22:51:39 +00:00
|
|
|
|
* console/Mach console/Eterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_HOME_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'I': /* Esc [ I == PageUp on FreeBSD
|
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_PREVPAGE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-05-01 01:21:38 +00:00
|
|
|
|
case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
|
2003-12-24 03:33:09 +00:00
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_INSERTFILE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case 'M': /* Esc [ M == F1 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(1);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'N': /* Esc [ N == F2 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(2);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'O':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (seq_len >= 3) {
|
|
|
|
|
switch (sequence[2]) {
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case 'P': /* Esc [ O P == F1 on
|
|
|
|
|
* xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(1);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'Q': /* Esc [ O Q == F2 on
|
|
|
|
|
* xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(2);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'R': /* Esc [ O R == F3 on
|
|
|
|
|
* xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(3);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'S': /* Esc [ O S == F4 on
|
|
|
|
|
* xterm. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(4);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2004-06-22 14:30:18 +00:00
|
|
|
|
} else {
|
|
|
|
|
/* Esc [ O == F3 on FreeBSD console. */
|
|
|
|
|
retval = KEY_F(3);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'P': /* Esc [ P == F4 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(4);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(5);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'R': /* Esc [ R == F6 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(6);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'S': /* Esc [ S == F7 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(7);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'T': /* Esc [ T == F8 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(8);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'U': /* Esc [ U == PageDown on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_NEXTPAGE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'V': /* Esc [ V == PageUp on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_PREVPAGE_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case 'W': /* Esc [ W == F11 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(11);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'X': /* Esc [ X == F12 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(12);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
|
case 'Y': /* Esc [ Y == End on Mach console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = NANO_END_KEY;
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(14);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
|
2004-01-06 01:45:04 +00:00
|
|
|
|
case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
|
2004-06-22 14:30:18 +00:00
|
|
|
|
case 'c': /* Esc [ c == Shift-Right on rxvt/
|
|
|
|
|
* Eterm. */
|
2004-01-06 01:45:04 +00:00
|
|
|
|
case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
|
2004-12-04 17:41:52 +00:00
|
|
|
|
retval = get_escape_seq_abcd(sequence[1]);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case '[':
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (seq_len >= 3) {
|
|
|
|
|
switch (sequence[2]) {
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case 'A': /* Esc [ [ A == F1 on Linux
|
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(1);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'B': /* Esc [ [ B == F2 on Linux
|
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(2);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'C': /* Esc [ [ C == F3 on Linux
|
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(3);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'D': /* Esc [ [ D == F4 on Linux
|
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(4);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'E': /* Esc [ [ E == F5 on Linux
|
|
|
|
|
* console. */
|
2004-05-28 17:23:33 +00:00
|
|
|
|
retval = KEY_F(5);
|
2004-01-23 19:26:17 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-12-24 03:33:09 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2003-08-17 02:48:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#ifdef DEBUG
|
2004-08-25 15:39:10 +00:00
|
|
|
|
fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
2003-12-24 03:33:09 +00:00
|
|
|
|
|
2004-05-28 17:23:33 +00:00
|
|
|
|
return retval;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-01-23 19:26:17 +00:00
|
|
|
|
/* Return the equivalent arrow key value for the case-insensitive
|
2004-02-07 03:39:48 +00:00
|
|
|
|
* letters A (up), B (down), C (right), and D (left). These are common
|
2004-01-23 19:26:17 +00:00
|
|
|
|
* to many escape sequences. */
|
|
|
|
|
int get_escape_seq_abcd(int kbinput)
|
|
|
|
|
{
|
|
|
|
|
switch (tolower(kbinput)) {
|
|
|
|
|
case 'a':
|
|
|
|
|
return NANO_PREVLINE_KEY;
|
|
|
|
|
case 'b':
|
|
|
|
|
return NANO_NEXTLINE_KEY;
|
|
|
|
|
case 'c':
|
|
|
|
|
return NANO_FORWARD_KEY;
|
|
|
|
|
case 'd':
|
|
|
|
|
return NANO_BACK_KEY;
|
|
|
|
|
default:
|
|
|
|
|
return ERR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Translate a word sequence: turn a three-digit decimal number from
|
|
|
|
|
* 000 to 255 into its corresponding word value. */
|
|
|
|
|
int get_word_kbinput(int kbinput
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
, bool reset
|
|
|
|
|
#endif
|
|
|
|
|
)
|
2004-05-28 17:23:33 +00:00
|
|
|
|
{
|
2004-12-04 17:41:52 +00:00
|
|
|
|
static int word_digits = 0;
|
|
|
|
|
static int word_kbinput = 0;
|
|
|
|
|
int retval = ERR;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
2004-12-04 17:41:52 +00:00
|
|
|
|
if (reset) {
|
|
|
|
|
word_digits = 0;
|
|
|
|
|
word_kbinput = 0;
|
|
|
|
|
return ERR;
|
|
|
|
|
}
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Increment the word digit counter. */
|
|
|
|
|
word_digits++;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
switch (word_digits) {
|
|
|
|
|
case 1:
|
|
|
|
|
/* One digit: reset the word sequence holder and add the
|
|
|
|
|
* digit we got to the 10000's position of the word sequence
|
|
|
|
|
* holder. */
|
|
|
|
|
word_kbinput = 0;
|
|
|
|
|
if ('0' <= kbinput && kbinput <= '6')
|
|
|
|
|
word_kbinput += (kbinput - '0') * 10000;
|
|
|
|
|
else
|
|
|
|
|
/* If the character we got isn't a decimal digit, or if
|
|
|
|
|
* it is and it would put the word sequence out of word
|
|
|
|
|
* range, save it as the result. */
|
|
|
|
|
retval = kbinput;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
/* Two digits: add the digit we got to the 1000's position
|
|
|
|
|
* of the word sequence holder. */
|
|
|
|
|
if (('0' <= kbinput && kbinput <= '5') ||
|
|
|
|
|
(word_kbinput < 60000 && '6' <= kbinput &&
|
|
|
|
|
kbinput <= '9'))
|
|
|
|
|
word_kbinput += (kbinput - '0') * 1000;
|
|
|
|
|
else
|
|
|
|
|
/* If the character we got isn't a decimal digit, or if
|
|
|
|
|
* it is and it would put the word sequence out of word
|
|
|
|
|
* range, save it as the result. */
|
|
|
|
|
retval = kbinput;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
/* Three digits: add the digit we got to the 100's position
|
|
|
|
|
* of the word sequence holder. */
|
|
|
|
|
if (('0' <= kbinput && kbinput <= '5') ||
|
|
|
|
|
(word_kbinput < 65000 && '6' <= kbinput &&
|
|
|
|
|
kbinput <= '9'))
|
|
|
|
|
word_kbinput += (kbinput - '0') * 100;
|
|
|
|
|
else
|
|
|
|
|
/* If the character we got isn't a decimal digit, or if
|
|
|
|
|
* it is and it would put the word sequence out of word
|
|
|
|
|
* range, save it as the result. */
|
|
|
|
|
retval = kbinput;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
/* Four digits: add the digit we got to the 10's position of
|
|
|
|
|
* the word sequence holder. */
|
|
|
|
|
if (('0' <= kbinput && kbinput <= '3') ||
|
|
|
|
|
(word_kbinput < 65500 && '4' <= kbinput &&
|
|
|
|
|
kbinput <= '9'))
|
|
|
|
|
word_kbinput += (kbinput - '0') * 10;
|
|
|
|
|
else
|
|
|
|
|
/* If the character we got isn't a decimal digit, or if
|
|
|
|
|
* it is and it would put the word sequence out of word
|
|
|
|
|
* range, save it as the result. */
|
|
|
|
|
retval = kbinput;
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
/* Five digits: add the digit we got to the 1's position of
|
|
|
|
|
* the word sequence holder, and save the corresponding word
|
|
|
|
|
* value as the result. */
|
|
|
|
|
if (('0' <= kbinput && kbinput <= '5') ||
|
|
|
|
|
(word_kbinput < 65530 && '6' <= kbinput &&
|
|
|
|
|
kbinput <= '9')) {
|
|
|
|
|
word_kbinput += (kbinput - '0');
|
|
|
|
|
retval = word_kbinput;
|
|
|
|
|
} else
|
|
|
|
|
/* If the character we got isn't a decimal digit, or if
|
|
|
|
|
* it is and it would put the word sequence out of word
|
|
|
|
|
* range, save it as the result. */
|
|
|
|
|
retval = kbinput;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* More than three digits: save the character we got as the
|
|
|
|
|
* result. */
|
|
|
|
|
retval = kbinput;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* If we have a result, reset the word digit counter and the word
|
|
|
|
|
* sequence holder. */
|
|
|
|
|
if (retval != ERR) {
|
|
|
|
|
word_digits = 0;
|
|
|
|
|
word_kbinput = 0;
|
|
|
|
|
}
|
2004-11-29 00:30:07 +00:00
|
|
|
|
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#ifdef DEBUG
|
2004-12-04 17:41:52 +00:00
|
|
|
|
fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word_kbinput = %d, retval = %d\n", kbinput, word_digits, word_kbinput, retval);
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Translate a control character sequence: turn an ASCII non-control
|
|
|
|
|
* character into its corresponding control character. */
|
|
|
|
|
int get_control_kbinput(int kbinput)
|
|
|
|
|
{
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
/* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
|
|
|
|
|
if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
|
|
|
|
|
kbinput == '`')
|
|
|
|
|
retval = NANO_CONTROL_SPACE;
|
|
|
|
|
/* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
|
|
|
|
|
else if ('3' <= kbinput && kbinput <= '7')
|
|
|
|
|
retval = kbinput - 24;
|
|
|
|
|
/* Ctrl-8 (Ctrl-?) */
|
|
|
|
|
else if (kbinput == '8' || kbinput == '?')
|
|
|
|
|
retval = NANO_CONTROL_8;
|
|
|
|
|
/* Ctrl-A to Ctrl-_ */
|
|
|
|
|
else if ('A' <= kbinput && kbinput <= '_')
|
|
|
|
|
retval = kbinput - 64;
|
|
|
|
|
/* Ctrl-a to Ctrl-~ */
|
|
|
|
|
else if ('a' <= kbinput && kbinput <= '~')
|
|
|
|
|
retval = kbinput - 96;
|
|
|
|
|
else
|
|
|
|
|
retval = kbinput;
|
|
|
|
|
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#ifdef DEBUG
|
2004-12-04 17:41:52 +00:00
|
|
|
|
fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
return retval;
|
|
|
|
|
}
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Read in a string of characters verbatim, and return the length of the
|
|
|
|
|
* string in kbinput_len. Assume nodelay(win) is FALSE. */
|
|
|
|
|
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
|
|
|
|
|
{
|
|
|
|
|
int *retval;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Turn off flow control characters if necessary so that we can type
|
|
|
|
|
* them in verbatim, and turn the keypad off so that we don't get
|
|
|
|
|
* extended keypad values. */
|
|
|
|
|
if (ISSET(PRESERVE))
|
|
|
|
|
disable_flow_control();
|
|
|
|
|
keypad(win, FALSE);
|
|
|
|
|
|
|
|
|
|
/* Read in a stream of characters and interpret it if possible. */
|
|
|
|
|
retval = parse_verbatim_kbinput(win, kbinput_len);
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
|
|
|
|
/* Turn flow control characters back on if necessary and turn the
|
|
|
|
|
* keypad back on now that we're done. */
|
|
|
|
|
if (ISSET(PRESERVE))
|
|
|
|
|
enable_flow_control();
|
|
|
|
|
keypad(win, TRUE);
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
return retval;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Read in a stream of all available characters. Translate the first
|
|
|
|
|
* few characters of the input into the corresponding word value if
|
|
|
|
|
* possible. After that, leave the input as-is. */
|
|
|
|
|
int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
|
2004-05-28 17:23:33 +00:00
|
|
|
|
{
|
2004-12-04 17:41:52 +00:00
|
|
|
|
buffer *kbinput, *sequence;
|
|
|
|
|
int word, *retval;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Read in the first keystroke. */
|
|
|
|
|
while ((kbinput = get_input(win, 1)) == NULL);
|
|
|
|
|
|
|
|
|
|
/* Check whether the first keystroke is a decimal digit. */
|
|
|
|
|
word = get_word_kbinput(kbinput->key
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-12-04 17:41:52 +00:00
|
|
|
|
, FALSE
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
2004-12-04 17:41:52 +00:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/* If the first keystroke isn't a decimal digit, put back the first
|
|
|
|
|
* keystroke. */
|
|
|
|
|
if (word != ERR)
|
|
|
|
|
unget_input(kbinput, 1);
|
|
|
|
|
/* Otherwise, read in keystrokes until we have a complete word
|
|
|
|
|
* sequence, and put back the corresponding word value. */
|
|
|
|
|
else {
|
|
|
|
|
buffer word_kbinput;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
while (word == ERR) {
|
|
|
|
|
while ((kbinput = get_input(win, 1)) == NULL);
|
|
|
|
|
word = get_word_kbinput(kbinput->key
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-12-04 17:41:52 +00:00
|
|
|
|
, FALSE
|
2004-05-28 17:23:33 +00:00
|
|
|
|
#endif
|
2004-12-04 17:41:52 +00:00
|
|
|
|
);
|
|
|
|
|
}
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
word_kbinput.key = word;
|
|
|
|
|
word_kbinput.key_code = FALSE;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
|
unget_input(&word_kbinput, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the complete sequence, and save the key values in it as the
|
|
|
|
|
* result. */
|
|
|
|
|
*kbinput_len = get_buffer_len();
|
|
|
|
|
sequence = get_input(NULL, *kbinput_len);
|
|
|
|
|
retval = buffer_to_keys(sequence, *kbinput_len);
|
|
|
|
|
free(sequence);
|
2004-05-28 17:23:33 +00:00
|
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-28 19:47:42 +00:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2003-12-24 03:33:09 +00:00
|
|
|
|
/* Check for a mouse event, and if one's taken place, save the
|
|
|
|
|
* coordinates where it took place in mouse_x and mouse_y. After that,
|
2004-07-01 18:59:52 +00:00
|
|
|
|
* assuming allow_shortcuts is FALSE, if the shortcut list on the
|
|
|
|
|
* bottom two lines of the screen is visible and the mouse event took
|
2004-08-25 16:37:06 +00:00
|
|
|
|
* place on it, figure out which shortcut was clicked and put back the
|
|
|
|
|
* equivalent keystroke(s). Return FALSE if no keystrokes were
|
|
|
|
|
* put back, or TRUE if at least one was. Assume that KEY_MOUSE has
|
2004-07-01 18:59:52 +00:00
|
|
|
|
* already been read in. */
|
2004-08-25 15:39:10 +00:00
|
|
|
|
bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
|
2003-11-28 19:47:42 +00:00
|
|
|
|
{
|
|
|
|
|
MEVENT mevent;
|
|
|
|
|
|
|
|
|
|
*mouse_x = -1;
|
|
|
|
|
*mouse_y = -1;
|
|
|
|
|
|
|
|
|
|
/* First, get the actual mouse event. */
|
|
|
|
|
if (getmouse(&mevent) == ERR)
|
2004-07-01 18:59:52 +00:00
|
|
|
|
return FALSE;
|
2003-11-28 19:47:42 +00:00
|
|
|
|
|
|
|
|
|
/* Save the screen coordinates where the mouse event took place. */
|
|
|
|
|
*mouse_x = mevent.x;
|
|
|
|
|
*mouse_y = mevent.y;
|
|
|
|
|
|
2004-08-25 15:39:10 +00:00
|
|
|
|
/* If we're allowing shortcuts, the current shortcut list is being
|
|
|
|
|
* displayed on the last two lines of the screen, and the mouse
|
|
|
|
|
* event took place inside it, we need to figure out which shortcut
|
2004-08-25 16:37:06 +00:00
|
|
|
|
* was clicked and put back the equivalent keystroke(s) for it. */
|
2004-08-25 15:39:10 +00:00
|
|
|
|
if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
|
|
|
|
|
*mouse_y, *mouse_x)) {
|
2003-11-28 19:47:42 +00:00
|
|
|
|
int i, j;
|
2004-07-01 18:59:52 +00:00
|
|
|
|
size_t currslen;
|
2003-11-28 19:47:42 +00:00
|
|
|
|
/* The number of shortcuts in the current shortcut list. */
|
|
|
|
|
const shortcut *s = currshortcut;
|
|
|
|
|
/* The actual shortcut we clicked on, starting at the first
|
|
|
|
|
* one in the current shortcut list. */
|
|
|
|
|
|
|
|
|
|
/* Get the shortcut lists' length. */
|
|
|
|
|
if (currshortcut == main_list)
|
|
|
|
|
currslen = MAIN_VISIBLE;
|
2004-08-26 01:43:16 +00:00
|
|
|
|
else {
|
2003-11-28 19:47:42 +00:00
|
|
|
|
currslen = length_of_list(currshortcut);
|
|
|
|
|
|
2004-08-26 01:43:16 +00:00
|
|
|
|
/* We don't show any more shortcuts than the main list
|
|
|
|
|
* does. */
|
|
|
|
|
if (currslen > MAIN_VISIBLE)
|
|
|
|
|
currslen = MAIN_VISIBLE;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-28 19:47:42 +00:00
|
|
|
|
/* Calculate the width of each shortcut in the list (it's the
|
|
|
|
|
* same for all of them). */
|
|
|
|
|
if (currslen < 2)
|
|
|
|
|
i = COLS / 6;
|
|
|
|
|
else
|
|
|
|
|
i = COLS / ((currslen / 2) + (currslen % 2));
|
|
|
|
|
|
|
|
|
|
/* Calculate the y-coordinates relative to the beginning of
|
|
|
|
|
* bottomwin, i.e, the bottom three lines of the screen. */
|
|
|
|
|
j = *mouse_y - (editwinrows + 3);
|
|
|
|
|
|
|
|
|
|
/* If we're on the statusbar, beyond the end of the shortcut
|
|
|
|
|
* list, or beyond the end of a shortcut on the right side of
|
|
|
|
|
* the screen, don't do anything. */
|
|
|
|
|
if (j < 0 || (*mouse_x / i) >= currslen)
|
2004-08-25 15:39:10 +00:00
|
|
|
|
return FALSE;
|
2003-11-28 19:47:42 +00:00
|
|
|
|
j = (*mouse_x / i) * 2 + j;
|
|
|
|
|
if (j >= currslen)
|
2004-08-25 15:39:10 +00:00
|
|
|
|
return FALSE;
|
2003-11-28 19:47:42 +00:00
|
|
|
|
|
|
|
|
|
/* Go through the shortcut list to determine which shortcut was
|
|
|
|
|
* clicked. */
|
|
|
|
|
for (; j > 0; j--)
|
|
|
|
|
s = s->next;
|
|
|
|
|
|
2004-09-11 21:41:13 +00:00
|
|
|
|
/* And put back the equivalent key. Assume that each shortcut
|
|
|
|
|
* has, at the very least, an equivalent control key, an
|
|
|
|
|
* equivalent primary meta key sequence, or both. */
|
2004-03-19 21:46:34 +00:00
|
|
|
|
if (s->ctrlval != NANO_NO_KEY)
|
2004-12-04 17:41:52 +00:00
|
|
|
|
unget_kbinput(s->ctrlval, FALSE, FALSE);
|
2004-08-26 01:43:16 +00:00
|
|
|
|
else if (s->metaval != NANO_NO_KEY)
|
2004-12-04 17:41:52 +00:00
|
|
|
|
unget_kbinput(s->metaval, TRUE, FALSE);
|
2003-11-28 19:47:42 +00:00
|
|
|
|
|
2004-07-01 18:59:52 +00:00
|
|
|
|
return TRUE;
|
2003-11-28 19:47:42 +00:00
|
|
|
|
}
|
2004-07-01 18:59:52 +00:00
|
|
|
|
return FALSE;
|
2003-11-28 19:47:42 +00:00
|
|
|
|
}
|
2004-08-25 15:39:10 +00:00
|
|
|
|
#endif /* !DISABLE_MOUSE */
|
|
|
|
|
|
2004-11-29 00:30:07 +00:00
|
|
|
|
const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
|
2004-09-27 01:04:50 +00:00
|
|
|
|
*meta_key, bool *func_key)
|
2004-08-25 15:39:10 +00:00
|
|
|
|
{
|
|
|
|
|
const shortcut *s = s_list;
|
|
|
|
|
size_t slen = length_of_list(s_list);
|
|
|
|
|
|
2004-11-27 06:43:06 +00:00
|
|
|
|
#ifdef DEBUG
|
2004-11-29 00:30:07 +00:00
|
|
|
|
fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %d, func_key = %d\n", *kbinput, (int)*meta_key, (int)*func_key);
|
2004-11-27 06:43:06 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-08-25 15:39:10 +00:00
|
|
|
|
/* Check for shortcuts. */
|
|
|
|
|
for (; slen > 0; slen--) {
|
|
|
|
|
/* We've found a shortcut if:
|
|
|
|
|
*
|
|
|
|
|
* 1. The key exists.
|
|
|
|
|
* 2. The key is a control key in the shortcut list.
|
2004-09-27 01:04:50 +00:00
|
|
|
|
* 3. meta_key is TRUE and the key is the primary or
|
|
|
|
|
* miscellaneous meta sequence in the shortcut list.
|
|
|
|
|
* 4. func_key is TRUE and the key is a function key in the
|
|
|
|
|
* shortcut list. */
|
|
|
|
|
|
2004-11-29 00:30:07 +00:00
|
|
|
|
if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
|
|
|
|
|
(*meta_key == TRUE && (*kbinput == s->metaval ||
|
|
|
|
|
*kbinput == s->miscval)) || (*func_key == TRUE &&
|
|
|
|
|
*kbinput == s->funcval))) {
|
2004-08-25 15:39:10 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = s->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Translate the shortcut to either its control key or its meta key
|
|
|
|
|
* equivalent. Assume that the shortcut has an equivalent control
|
2004-09-27 01:04:50 +00:00
|
|
|
|
* key, an equivalent primary meta key sequence, or both. */
|
2004-08-25 15:39:10 +00:00
|
|
|
|
if (slen > 0) {
|
|
|
|
|
if (s->ctrlval != NANO_NO_KEY) {
|
|
|
|
|
*meta_key = FALSE;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
*func_key = FALSE;
|
2004-11-29 00:30:07 +00:00
|
|
|
|
*kbinput = s->ctrlval;
|
2004-08-25 15:39:10 +00:00
|
|
|
|
} else if (s->metaval != NANO_NO_KEY) {
|
|
|
|
|
*meta_key = TRUE;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
*func_key = FALSE;
|
2004-11-29 00:30:07 +00:00
|
|
|
|
*kbinput = s->metaval;
|
2004-08-25 15:39:10 +00:00
|
|
|
|
}
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
const toggle *get_toggle(int kbinput, bool meta_key)
|
|
|
|
|
{
|
|
|
|
|
const toggle *t = toggles;
|
|
|
|
|
|
2004-11-27 06:43:06 +00:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-08-25 15:39:10 +00:00
|
|
|
|
/* Check for toggles. */
|
|
|
|
|
for (; t != NULL; t = t->next) {
|
|
|
|
|
/* We've found a toggle if meta_key is TRUE and the key is in
|
2004-12-05 06:11:01 +00:00
|
|
|
|
* the meta key toggle list. */
|
2004-08-25 15:39:10 +00:00
|
|
|
|
if (meta_key && kbinput == t->val)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
#endif /* !NANO_SMALL */
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* Return the placewewant associated with current_x. That is, xplustabs
|
|
|
|
|
* is the zero-based column position of the cursor. Value is no smaller
|
|
|
|
|
* than current_x. */
|
|
|
|
|
size_t xplustabs(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
return strnlenpt(current->data, current_x);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* actual_x() gives the index in str of the character displayed at
|
|
|
|
|
* column xplus. That is, actual_x() is the largest value such that
|
|
|
|
|
* strnlenpt(str, actual_x(str, xplus)) <= xplus. */
|
|
|
|
|
size_t actual_x(const char *str, size_t xplus)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
size_t i = 0;
|
2004-09-24 21:48:40 +00:00
|
|
|
|
/* The position in str, returned. */
|
2002-07-19 01:08:59 +00:00
|
|
|
|
size_t length = 0;
|
2004-09-24 21:48:40 +00:00
|
|
|
|
/* The screen display width to str[i]. */
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
assert(str != NULL);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
for (; length < xplus && *str != '\0'; i++, str++) {
|
|
|
|
|
if (*str == '\t')
|
2003-09-30 03:31:56 +00:00
|
|
|
|
length += tabsize - (length % tabsize);
|
2004-10-21 22:06:40 +00:00
|
|
|
|
else if (is_cntrl_char(*str))
|
2002-07-19 01:08:59 +00:00
|
|
|
|
length += 2;
|
|
|
|
|
else
|
|
|
|
|
length++;
|
|
|
|
|
}
|
2003-09-16 01:16:49 +00:00
|
|
|
|
assert(length == strnlenpt(str - i, i));
|
|
|
|
|
assert(i <= strlen(str - i));
|
2002-06-13 00:40:19 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (length > xplus)
|
|
|
|
|
i--;
|
2002-06-13 00:40:19 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
return i;
|
2000-06-06 23:04:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-04-05 01:08:14 +00:00
|
|
|
|
/* A strlen() with tabs factored in, similar to xplustabs(). How many
|
2003-09-28 19:15:18 +00:00
|
|
|
|
* columns wide are the first size characters of buf? */
|
2002-07-19 01:08:59 +00:00
|
|
|
|
size_t strnlenpt(const char *buf, size_t size)
|
2000-06-06 23:04:06 +00:00
|
|
|
|
{
|
2002-07-19 01:08:59 +00:00
|
|
|
|
size_t length = 0;
|
|
|
|
|
|
2003-09-28 19:15:18 +00:00
|
|
|
|
assert(buf != NULL);
|
|
|
|
|
for (; *buf != '\0' && size != 0; size--, buf++) {
|
|
|
|
|
if (*buf == '\t')
|
|
|
|
|
length += tabsize - (length % tabsize);
|
2004-10-21 22:06:40 +00:00
|
|
|
|
else if (is_cntrl_char(*buf))
|
2003-09-28 19:15:18 +00:00
|
|
|
|
length += 2;
|
|
|
|
|
else
|
|
|
|
|
length++;
|
|
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
return length;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-09-28 19:15:18 +00:00
|
|
|
|
/* How many columns wide is buf? */
|
2002-07-19 01:08:59 +00:00
|
|
|
|
size_t strlenpt(const char *buf)
|
2002-03-05 19:55:55 +00:00
|
|
|
|
{
|
2004-03-29 23:09:08 +00:00
|
|
|
|
return strnlenpt(buf, (size_t)-1);
|
2002-03-05 19:55:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
|
void blank_titlebar(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2004-05-18 01:20:36 +00:00
|
|
|
|
mvwaddstr(topwin, 0, 0, hblank);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
void blank_edit(void)
|
|
|
|
|
{
|
2004-07-28 20:46:25 +00:00
|
|
|
|
int i;
|
2003-09-29 05:15:24 +00:00
|
|
|
|
for (i = 0; i < editwinrows; i++)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
mvwaddstr(edit, i, 0, hblank);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blank_statusbar(void)
|
|
|
|
|
{
|
|
|
|
|
mvwaddstr(bottomwin, 0, 0, hblank);
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-30 22:07:21 +00:00
|
|
|
|
void check_statusblank(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2004-09-30 22:07:21 +00:00
|
|
|
|
if (statusblank > 1)
|
|
|
|
|
statusblank--;
|
|
|
|
|
else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
|
|
|
|
|
statusblank = 0;
|
2004-05-23 21:11:14 +00:00
|
|
|
|
blank_statusbar();
|
|
|
|
|
wnoutrefresh(bottomwin);
|
|
|
|
|
reset_cursor();
|
|
|
|
|
wrefresh(edit);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
|
void blank_bottombars(void)
|
|
|
|
|
{
|
|
|
|
|
if (!ISSET(NO_HELP)) {
|
|
|
|
|
mvwaddstr(bottomwin, 1, 0, hblank);
|
|
|
|
|
mvwaddstr(bottomwin, 2, 0, hblank);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Convert buf into a string that can be displayed on screen. The
|
|
|
|
|
* caller wants to display buf starting with column start_col, and
|
|
|
|
|
* extending for at most len columns. start_col is zero-based. len is
|
|
|
|
|
* one-based, so len == 0 means you get "" returned. The returned
|
|
|
|
|
* string is dynamically allocated, and should be freed. */
|
2004-05-18 01:20:36 +00:00
|
|
|
|
char *display_string(const char *buf, size_t start_col, size_t len)
|
2003-09-16 01:16:49 +00:00
|
|
|
|
{
|
|
|
|
|
size_t start_index;
|
|
|
|
|
/* Index in buf of first character shown in return value. */
|
|
|
|
|
size_t column;
|
|
|
|
|
/* Screen column start_index corresponds to. */
|
|
|
|
|
size_t end_index;
|
|
|
|
|
/* Index in buf of last character shown in return value. */
|
|
|
|
|
size_t alloc_len;
|
|
|
|
|
/* The length of memory allocated for converted. */
|
|
|
|
|
char *converted;
|
|
|
|
|
/* The string we return. */
|
|
|
|
|
size_t index;
|
|
|
|
|
/* Current position in converted. */
|
|
|
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
|
return mallocstrcpy(NULL, "");
|
|
|
|
|
|
|
|
|
|
start_index = actual_x(buf, start_col);
|
|
|
|
|
column = strnlenpt(buf, start_index);
|
|
|
|
|
assert(column <= start_col);
|
|
|
|
|
end_index = actual_x(buf, start_col + len - 1);
|
|
|
|
|
alloc_len = strnlenpt(buf, end_index + 1) - column;
|
|
|
|
|
if (len > alloc_len + column - start_col)
|
|
|
|
|
len = alloc_len + column - start_col;
|
|
|
|
|
converted = charalloc(alloc_len + 1);
|
|
|
|
|
buf += start_index;
|
|
|
|
|
index = 0;
|
|
|
|
|
|
|
|
|
|
for (; index < alloc_len; buf++) {
|
2004-05-29 16:25:30 +00:00
|
|
|
|
if (*buf == '\t') {
|
|
|
|
|
converted[index++] =
|
|
|
|
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
|
|
|
|
ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
|
|
|
|
|
#endif
|
|
|
|
|
' ';
|
|
|
|
|
while ((column + index) % tabsize)
|
2003-09-16 01:16:49 +00:00
|
|
|
|
converted[index++] = ' ';
|
2004-05-29 16:25:30 +00:00
|
|
|
|
} else if (is_cntrl_char(*buf)) {
|
2003-09-16 01:16:49 +00:00
|
|
|
|
converted[index++] = '^';
|
|
|
|
|
if (*buf == '\n')
|
|
|
|
|
/* Treat newlines embedded in a line as encoded nulls;
|
|
|
|
|
* the line in question should be run through unsunder()
|
|
|
|
|
* before reaching here. */
|
|
|
|
|
converted[index++] = '@';
|
|
|
|
|
else if (*buf == NANO_CONTROL_8)
|
|
|
|
|
converted[index++] = '?';
|
|
|
|
|
else
|
|
|
|
|
converted[index++] = *buf + 64;
|
2004-05-29 16:25:30 +00:00
|
|
|
|
} else if (*buf == ' ')
|
|
|
|
|
converted[index++] =
|
|
|
|
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
|
|
|
|
ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
|
|
|
|
|
#endif
|
|
|
|
|
' ';
|
|
|
|
|
else
|
2003-09-16 01:16:49 +00:00
|
|
|
|
converted[index++] = *buf;
|
|
|
|
|
}
|
|
|
|
|
assert(len <= alloc_len + column - start_col);
|
|
|
|
|
charmove(converted, converted + start_col - column, len);
|
|
|
|
|
null_at(&converted, len);
|
|
|
|
|
|
|
|
|
|
return charealloc(converted, len + 1);
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
|
/* Repaint the statusbar when getting a character in nanogetstr(). buf
|
2003-09-16 01:16:49 +00:00
|
|
|
|
* should be no longer than max(0, COLS - 4).
|
2002-07-19 01:08:59 +00:00
|
|
|
|
*
|
2003-01-13 01:35:15 +00:00
|
|
|
|
* Note that we must turn on A_REVERSE here, since do_help() turns it
|
2002-07-19 01:08:59 +00:00
|
|
|
|
* off! */
|
2003-09-16 01:16:49 +00:00
|
|
|
|
void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
|
2000-10-24 22:25:36 +00:00
|
|
|
|
{
|
2003-09-16 01:16:49 +00:00
|
|
|
|
size_t x_real = strnlenpt(inputbuf, x);
|
|
|
|
|
int wid = COLS - strlen(buf) - 2;
|
2000-11-02 04:40:39 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
assert(0 <= x && x <= strlen(inputbuf));
|
|
|
|
|
|
2001-10-22 03:15:31 +00:00
|
|
|
|
wattron(bottomwin, A_REVERSE);
|
2000-11-02 15:30:24 +00:00
|
|
|
|
blank_statusbar();
|
2003-09-16 01:16:49 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
mvwaddstr(bottomwin, 0, 0, buf);
|
|
|
|
|
waddch(bottomwin, ':');
|
2003-09-16 01:16:49 +00:00
|
|
|
|
|
|
|
|
|
if (COLS > 1)
|
|
|
|
|
waddch(bottomwin, x_real < wid ? ' ' : '$');
|
|
|
|
|
if (COLS > 2) {
|
|
|
|
|
size_t page_start = x_real - x_real % wid;
|
|
|
|
|
char *expanded = display_string(inputbuf, page_start, wid);
|
|
|
|
|
|
|
|
|
|
assert(wid > 0);
|
|
|
|
|
assert(strlen(expanded) <= wid);
|
|
|
|
|
waddstr(bottomwin, expanded);
|
|
|
|
|
free(expanded);
|
|
|
|
|
wmove(bottomwin, 0, COLS - wid + x_real - page_start);
|
|
|
|
|
} else
|
|
|
|
|
wmove(bottomwin, 0, COLS - 1);
|
2001-10-22 03:15:31 +00:00
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
2000-10-24 22:25:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-03-15 20:26:30 +00:00
|
|
|
|
/* Get the input from the keyboard; this should only be called from
|
2002-07-19 01:08:59 +00:00
|
|
|
|
* statusq(). */
|
2004-10-05 20:11:31 +00:00
|
|
|
|
int nanogetstr(bool allow_tabs, const char *buf, const char *def,
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
historyheadtype *history_list,
|
|
|
|
|
#endif
|
2004-10-05 20:11:31 +00:00
|
|
|
|
const shortcut *s
|
2001-01-11 05:30:31 +00:00
|
|
|
|
#ifndef DISABLE_TABCOMP
|
2004-08-01 22:35:31 +00:00
|
|
|
|
, bool *list
|
2000-11-24 14:00:16 +00:00
|
|
|
|
#endif
|
2003-02-13 03:03:49 +00:00
|
|
|
|
)
|
2002-07-19 01:08:59 +00:00
|
|
|
|
{
|
|
|
|
|
int kbinput;
|
2004-09-27 01:04:50 +00:00
|
|
|
|
bool meta_key, func_key;
|
2004-10-30 01:03:15 +00:00
|
|
|
|
static size_t x = (size_t)-1;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* the cursor position in 'answer' */
|
2004-10-30 01:03:15 +00:00
|
|
|
|
size_t xend;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* length of 'answer', the status bar text */
|
2004-08-01 22:35:31 +00:00
|
|
|
|
bool tabbed = FALSE;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* used by input_tab() */
|
|
|
|
|
const shortcut *t;
|
|
|
|
|
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* for history */
|
|
|
|
|
char *history = NULL;
|
2003-01-09 05:29:58 +00:00
|
|
|
|
char *currentbuf = NULL;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
char *complete = NULL;
|
2003-06-14 20:41:34 +00:00
|
|
|
|
int last_kbinput = 0;
|
|
|
|
|
|
|
|
|
|
/* This variable is used in the search history code. use_cb == 0
|
|
|
|
|
means that we're using the existing history and ignoring
|
|
|
|
|
currentbuf. use_cb == 1 means that the entry in answer should be
|
|
|
|
|
moved to currentbuf or restored from currentbuf to answer.
|
|
|
|
|
use_cb == 2 means that the entry in currentbuf should be moved to
|
|
|
|
|
answer or restored from answer to currentbuf. */
|
|
|
|
|
int use_cb = 0;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#endif
|
2002-07-19 01:08:59 +00:00
|
|
|
|
xend = strlen(def);
|
2003-01-16 22:16:38 +00:00
|
|
|
|
|
2004-10-05 02:29:52 +00:00
|
|
|
|
/* Only put x at the end of the string if it's uninitialized, if it
|
2004-10-05 20:11:31 +00:00
|
|
|
|
would be past the end of the string as it is, or if
|
|
|
|
|
resetstatuspos is TRUE. Otherwise, leave it alone. This is so
|
|
|
|
|
the cursor position stays at the same place if a prompt-changing
|
|
|
|
|
toggle is pressed. */
|
2004-10-30 01:03:15 +00:00
|
|
|
|
if (x == (size_t)-1 || x > xend || resetstatuspos)
|
2003-01-16 22:16:38 +00:00
|
|
|
|
x = xend;
|
|
|
|
|
|
2003-04-15 01:15:09 +00:00
|
|
|
|
answer = charealloc(answer, xend + 1);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (xend > 0)
|
|
|
|
|
strcpy(answer, def);
|
|
|
|
|
else
|
|
|
|
|
answer[0] = '\0';
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2003-10-03 20:26:25 +00:00
|
|
|
|
#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
|
2001-04-12 03:01:53 +00:00
|
|
|
|
currshortcut = s;
|
2001-05-21 12:56:25 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
/* Get the input! */
|
2000-11-02 04:40:39 +00:00
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
nanoget_repaint(buf, answer, x);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* Make sure any editor screen updates are displayed before getting
|
|
|
|
|
input */
|
2004-07-01 17:04:23 +00:00
|
|
|
|
wnoutrefresh(edit);
|
|
|
|
|
wrefresh(bottomwin);
|
2000-11-14 17:47:58 +00:00
|
|
|
|
|
2004-05-29 01:20:17 +00:00
|
|
|
|
/* 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. */
|
2004-09-27 01:04:50 +00:00
|
|
|
|
while ((kbinput = get_kbinput(bottomwin, &meta_key, &func_key)) !=
|
2004-09-30 22:07:21 +00:00
|
|
|
|
NANO_CANCEL_KEY && kbinput != NANO_ENTER_KEY) {
|
2002-02-15 19:17:02 +00:00
|
|
|
|
for (t = s; t != NULL; t = t->next) {
|
2001-04-12 03:01:53 +00:00
|
|
|
|
#ifdef DEBUG
|
2003-08-05 19:31:12 +00:00
|
|
|
|
fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
|
2001-04-12 03:01:53 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-03-19 21:46:34 +00:00
|
|
|
|
/* Temporary hack to interpret NANO_HELP_FKEY correctly. */
|
|
|
|
|
if (kbinput == t->funcval)
|
|
|
|
|
kbinput = t->ctrlval;
|
2004-03-04 19:30:53 +00:00
|
|
|
|
|
2004-03-19 21:46:34 +00:00
|
|
|
|
if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) {
|
2000-11-16 06:01:10 +00:00
|
|
|
|
|
2001-10-22 03:15:31 +00:00
|
|
|
|
#ifndef DISABLE_HELP
|
2002-09-06 20:35:28 +00:00
|
|
|
|
/* Have to do this here, it would be too late to do it
|
|
|
|
|
in statusq() */
|
2004-03-04 19:30:53 +00:00
|
|
|
|
if (kbinput == NANO_HELP_KEY) {
|
2001-10-22 03:15:31 +00:00
|
|
|
|
do_help();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2003-11-28 19:47:42 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* Have to handle these here too, for the time being */
|
2004-01-23 19:26:17 +00:00
|
|
|
|
if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY)
|
2003-11-28 19:47:42 +00:00
|
|
|
|
break;
|
|
|
|
|
#endif
|
2003-01-17 21:07:38 +00:00
|
|
|
|
|
2004-03-19 21:46:34 +00:00
|
|
|
|
return t->ctrlval;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-10-30 01:03:15 +00:00
|
|
|
|
assert(x <= xend && xend == strlen(answer));
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2000-11-05 17:54:41 +00:00
|
|
|
|
if (kbinput != '\t')
|
2004-08-01 22:35:31 +00:00
|
|
|
|
tabbed = FALSE;
|
2000-11-05 17:54:41 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
switch (kbinput) {
|
2003-10-03 20:26:25 +00:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2001-04-12 03:01:53 +00:00
|
|
|
|
case KEY_MOUSE:
|
2004-08-25 15:39:10 +00:00
|
|
|
|
{
|
|
|
|
|
int mouse_x, mouse_y;
|
|
|
|
|
get_mouseinput(&mouse_x, &mouse_y, TRUE);
|
|
|
|
|
}
|
2001-04-12 03:01:53 +00:00
|
|
|
|
break;
|
2000-11-16 19:55:30 +00:00
|
|
|
|
#endif
|
2004-09-25 00:45:07 +00:00
|
|
|
|
case NANO_REFRESH_KEY:
|
|
|
|
|
total_refresh();
|
|
|
|
|
break;
|
2001-06-14 02:54:22 +00:00
|
|
|
|
case NANO_HOME_KEY:
|
2004-05-22 20:15:20 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (ISSET(SMART_HOME)) {
|
2004-10-30 01:03:15 +00:00
|
|
|
|
size_t old_x = x;
|
2004-05-22 20:15:20 +00:00
|
|
|
|
|
|
|
|
|
for (x = 0; isblank(answer[x]) && x < xend; x++)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
if (x == old_x || x == xend)
|
|
|
|
|
x = 0;
|
|
|
|
|
} else
|
|
|
|
|
#endif
|
|
|
|
|
x = 0;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
2001-06-14 02:54:22 +00:00
|
|
|
|
case NANO_END_KEY:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
x = xend;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
2001-03-21 15:07:20 +00:00
|
|
|
|
case NANO_FORWARD_KEY:
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (x < xend)
|
|
|
|
|
x++;
|
|
|
|
|
break;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
case NANO_DELETE_KEY:
|
2004-05-29 01:20:17 +00:00
|
|
|
|
/* If we're using restricted mode, the filename isn't blank,
|
|
|
|
|
* and we're at the "Write File" prompt, disable Delete. */
|
2004-04-30 04:49:02 +00:00
|
|
|
|
if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
|
|
|
|
|
if (x < xend) {
|
|
|
|
|
charmove(answer + x, answer + x + 1, xend - x);
|
|
|
|
|
xend--;
|
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
case NANO_CUT_KEY:
|
2004-05-29 01:20:17 +00:00
|
|
|
|
/* If we're using restricted mode, the filename isn't blank,
|
2004-07-23 12:30:40 +00:00
|
|
|
|
* and we're at the "Write File" prompt, disable Cut. */
|
2004-04-30 04:49:02 +00:00
|
|
|
|
if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
|
|
|
|
|
null_at(&answer, 0);
|
|
|
|
|
xend = 0;
|
|
|
|
|
x = 0;
|
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
case NANO_BACKSPACE_KEY:
|
2004-05-29 01:20:17 +00:00
|
|
|
|
/* If we're using restricted mode, the filename isn't blank,
|
|
|
|
|
* and we're at the "Write File" prompt, disable
|
|
|
|
|
* Backspace. */
|
2004-04-30 04:49:02 +00:00
|
|
|
|
if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
|
|
|
|
|
if (x > 0) {
|
|
|
|
|
charmove(answer + x - 1, answer + x, xend - x + 1);
|
|
|
|
|
x--;
|
|
|
|
|
xend--;
|
|
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
}
|
2000-11-05 17:54:41 +00:00
|
|
|
|
break;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
case NANO_TAB_KEY:
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
/* tab history completion */
|
2003-01-13 01:35:15 +00:00
|
|
|
|
if (history_list != NULL) {
|
2003-08-17 02:48:43 +00:00
|
|
|
|
if (!complete || last_kbinput != NANO_TAB_KEY) {
|
2003-01-05 20:41:21 +00:00
|
|
|
|
history_list->current = (historytype *)history_list;
|
|
|
|
|
history_list->len = strlen(answer);
|
|
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
2003-01-13 01:35:15 +00:00
|
|
|
|
if (history_list->len > 0) {
|
2003-01-05 20:41:21 +00:00
|
|
|
|
complete = get_history_completion(history_list, answer);
|
|
|
|
|
xend = strlen(complete);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
x = xend;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
answer = mallocstrcpy(answer, complete);
|
|
|
|
|
}
|
2000-11-06 02:57:22 +00:00
|
|
|
|
}
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef DISABLE_TABCOMP
|
2003-01-17 05:04:17 +00:00
|
|
|
|
else
|
|
|
|
|
#endif
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#endif
|
|
|
|
|
#ifndef DISABLE_TABCOMP
|
2004-10-05 20:11:31 +00:00
|
|
|
|
if (allow_tabs) {
|
2003-01-17 05:04:17 +00:00
|
|
|
|
int shift = 0;
|
|
|
|
|
|
|
|
|
|
answer = input_tab(answer, x, &tabbed, &shift, list);
|
|
|
|
|
xend = strlen(answer);
|
|
|
|
|
x += shift;
|
|
|
|
|
if (x > xend)
|
|
|
|
|
x = xend;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
2001-03-21 15:07:20 +00:00
|
|
|
|
case NANO_BACK_KEY:
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (x > 0)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
x--;
|
|
|
|
|
break;
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case NANO_PREVLINE_KEY:
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2003-01-16 22:16:38 +00:00
|
|
|
|
if (history_list != NULL) {
|
2003-01-09 05:29:58 +00:00
|
|
|
|
|
2003-06-14 20:41:34 +00:00
|
|
|
|
/* if currentbuf is NULL, or if use_cb is 1, currentbuf
|
|
|
|
|
isn't NULL, and currentbuf is different from answer,
|
|
|
|
|
it means that we're scrolling up at the top of the
|
|
|
|
|
search history, and we need to save the current
|
|
|
|
|
answer in currentbuf; do this and reset use_cb to
|
|
|
|
|
0 */
|
2004-07-31 14:10:23 +00:00
|
|
|
|
if (currentbuf == NULL || (use_cb == 1 &&
|
|
|
|
|
strcmp(currentbuf, answer) != 0)) {
|
2003-01-09 05:29:58 +00:00
|
|
|
|
currentbuf = mallocstrcpy(currentbuf, answer);
|
2003-06-14 20:41:34 +00:00
|
|
|
|
use_cb = 0;
|
2003-01-09 05:29:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-06-14 20:41:34 +00:00
|
|
|
|
/* if currentbuf isn't NULL, use_cb is 2, and currentbuf
|
|
|
|
|
is different from answer, it means that we're
|
|
|
|
|
scrolling up at the bottom of the search history, and
|
|
|
|
|
we need to make the string in currentbuf the current
|
|
|
|
|
answer; do this, blow away currentbuf since we don't
|
|
|
|
|
need it anymore, and reset use_cb to 0 */
|
2004-07-31 14:10:23 +00:00
|
|
|
|
if (currentbuf != NULL && use_cb == 2 &&
|
|
|
|
|
strcmp(currentbuf, answer) != 0) {
|
2003-06-14 20:41:34 +00:00
|
|
|
|
answer = mallocstrcpy(answer, currentbuf);
|
|
|
|
|
free(currentbuf);
|
|
|
|
|
currentbuf = NULL;
|
|
|
|
|
xend = strlen(answer);
|
|
|
|
|
use_cb = 0;
|
|
|
|
|
|
|
|
|
|
/* else get older search from the history list and save
|
|
|
|
|
it in answer; if there is no older search, blank out
|
|
|
|
|
answer */
|
|
|
|
|
} else if ((history = get_history_older(history_list)) != NULL) {
|
2003-01-05 20:41:21 +00:00
|
|
|
|
answer = mallocstrcpy(answer, history);
|
|
|
|
|
xend = strlen(history);
|
|
|
|
|
} else {
|
|
|
|
|
answer = mallocstrcpy(answer, "");
|
|
|
|
|
xend = 0;
|
|
|
|
|
}
|
|
|
|
|
x = xend;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2003-01-09 23:43:12 +00:00
|
|
|
|
break;
|
2004-01-23 19:26:17 +00:00
|
|
|
|
case NANO_NEXTLINE_KEY:
|
2003-01-05 20:41:21 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2003-01-16 22:16:38 +00:00
|
|
|
|
if (history_list != NULL) {
|
2003-06-14 20:41:34 +00:00
|
|
|
|
|
|
|
|
|
/* get newer search from the history list and save it
|
|
|
|
|
in answer */
|
2003-01-13 01:35:15 +00:00
|
|
|
|
if ((history = get_history_newer(history_list)) != NULL) {
|
2003-01-05 20:41:21 +00:00
|
|
|
|
answer = mallocstrcpy(answer, history);
|
|
|
|
|
xend = strlen(history);
|
2003-01-09 05:29:58 +00:00
|
|
|
|
|
2003-06-14 20:41:34 +00:00
|
|
|
|
/* if there is no newer search, we're here */
|
|
|
|
|
|
|
|
|
|
/* if currentbuf isn't NULL and use_cb isn't 2, it means
|
|
|
|
|
that we're scrolling down at the bottom of the search
|
|
|
|
|
history and we need to make the string in currentbuf
|
|
|
|
|
the current answer; do this, blow away currentbuf
|
|
|
|
|
since we don't need it anymore, and set use_cb to
|
|
|
|
|
1 */
|
|
|
|
|
} else if (currentbuf != NULL && use_cb != 2) {
|
2003-01-09 05:29:58 +00:00
|
|
|
|
answer = mallocstrcpy(answer, currentbuf);
|
2003-01-16 22:16:38 +00:00
|
|
|
|
free(currentbuf);
|
|
|
|
|
currentbuf = NULL;
|
|
|
|
|
xend = strlen(answer);
|
2003-06-14 20:41:34 +00:00
|
|
|
|
use_cb = 1;
|
|
|
|
|
|
|
|
|
|
/* otherwise, if currentbuf is NULL and use_cb isn't 2,
|
|
|
|
|
it means that we're scrolling down at the bottom of
|
2003-08-11 00:32:45 +00:00
|
|
|
|
the search history and the current answer (if it's
|
|
|
|
|
not blank) needs to be saved in currentbuf; do this,
|
|
|
|
|
blank out answer (if necessary), and set use_cb to
|
|
|
|
|
2 */
|
2003-06-14 20:41:34 +00:00
|
|
|
|
} else if (use_cb != 2) {
|
2003-08-11 00:32:45 +00:00
|
|
|
|
if (answer[0] != '\0') {
|
|
|
|
|
currentbuf = mallocstrcpy(currentbuf, answer);
|
|
|
|
|
answer = mallocstrcpy(answer, "");
|
|
|
|
|
}
|
2003-01-05 20:41:21 +00:00
|
|
|
|
xend = 0;
|
2003-06-14 20:41:34 +00:00
|
|
|
|
use_cb = 2;
|
2003-01-05 20:41:21 +00:00
|
|
|
|
}
|
|
|
|
|
x = xend;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
2001-06-14 02:54:22 +00:00
|
|
|
|
default:
|
|
|
|
|
|
2002-02-15 19:17:02 +00:00
|
|
|
|
for (t = s; t != NULL; t = t->next) {
|
2001-06-14 02:54:22 +00:00
|
|
|
|
#ifdef DEBUG
|
2003-08-05 19:31:12 +00:00
|
|
|
|
fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
|
2002-01-19 01:59:37 +00:00
|
|
|
|
kbinput);
|
2001-06-14 02:54:22 +00:00
|
|
|
|
#endif
|
2004-08-01 22:35:31 +00:00
|
|
|
|
if (meta_key && (kbinput == t->metaval || kbinput == t->miscval))
|
2004-05-24 18:40:41 +00:00
|
|
|
|
/* We hit a meta key. Do like above. We don't
|
2004-08-25 16:37:06 +00:00
|
|
|
|
* just put back the letter and let it get
|
2003-12-24 08:03:54 +00:00
|
|
|
|
* caught above cause that screws the
|
|
|
|
|
* keypad... */
|
|
|
|
|
return kbinput;
|
2001-06-14 02:54:22 +00:00
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-05-29 01:20:17 +00:00
|
|
|
|
/* If we're using restricted mode, the filename isn't blank,
|
|
|
|
|
* and we're at the "Write File" prompt, act as though the
|
|
|
|
|
* unhandled character we got is a control character and
|
|
|
|
|
* throw it away. */
|
2004-04-30 04:49:02 +00:00
|
|
|
|
if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list))
|
2000-06-06 05:53:49 +00:00
|
|
|
|
break;
|
2003-06-14 20:41:34 +00:00
|
|
|
|
answer = charealloc(answer, xend + 2);
|
2003-09-16 02:04:00 +00:00
|
|
|
|
charmove(answer + x + 1, answer + x, xend - x + 1);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
xend++;
|
|
|
|
|
answer[x] = kbinput;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
x++;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2003-08-05 19:31:12 +00:00
|
|
|
|
fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
#endif
|
2003-01-05 20:41:21 +00:00
|
|
|
|
} /* switch (kbinput) */
|
2003-01-05 20:57:07 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2003-01-05 20:41:21 +00:00
|
|
|
|
last_kbinput = kbinput;
|
2003-01-05 20:57:07 +00:00
|
|
|
|
#endif
|
2002-07-19 01:08:59 +00:00
|
|
|
|
nanoget_repaint(buf, answer, x);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wrefresh(bottomwin);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
} /* while (kbinput ...) */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2003-01-17 21:07:38 +00:00
|
|
|
|
/* We finished putting in an answer; reset x */
|
2004-10-30 01:03:15 +00:00
|
|
|
|
x = (size_t)-1;
|
2003-01-17 21:07:38 +00:00
|
|
|
|
|
2004-09-30 22:07:21 +00:00
|
|
|
|
return kbinput;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-10-05 20:11:31 +00:00
|
|
|
|
/* 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. def is any editable text
|
|
|
|
|
* we want to put up by default.
|
|
|
|
|
*
|
|
|
|
|
* New arg tabs tells whether or not to allow tab completion. */
|
|
|
|
|
int statusq(bool allow_tabs, const shortcut *s, const char *def,
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
historyheadtype *which_history,
|
|
|
|
|
#endif
|
|
|
|
|
const char *msg, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
char *foo = charalloc(COLS - 3);
|
|
|
|
|
int ret;
|
|
|
|
|
#ifndef DISABLE_TABCOMP
|
|
|
|
|
bool list = FALSE;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
bottombars(s);
|
|
|
|
|
|
|
|
|
|
va_start(ap, msg);
|
|
|
|
|
vsnprintf(foo, COLS - 4, msg, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
foo[COLS - 4] = '\0';
|
|
|
|
|
|
|
|
|
|
ret = nanogetstr(allow_tabs, foo, def,
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
which_history,
|
|
|
|
|
#endif
|
|
|
|
|
s
|
|
|
|
|
#ifndef DISABLE_TABCOMP
|
|
|
|
|
, &list
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
free(foo);
|
|
|
|
|
resetstatuspos = FALSE;
|
|
|
|
|
|
|
|
|
|
switch (ret) {
|
2004-10-15 01:39:46 +00:00
|
|
|
|
case NANO_FIRSTLINE_KEY:
|
|
|
|
|
case NANO_FIRSTLINE_FKEY:
|
|
|
|
|
do_first_line();
|
|
|
|
|
resetstatuspos = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case NANO_LASTLINE_KEY:
|
|
|
|
|
case NANO_LASTLINE_FKEY:
|
|
|
|
|
do_last_line();
|
|
|
|
|
resetstatuspos = TRUE;
|
|
|
|
|
break;
|
2004-10-05 20:11:31 +00:00
|
|
|
|
#ifndef DISABLE_JUSTIFY
|
2004-10-15 01:39:46 +00:00
|
|
|
|
case NANO_PARABEGIN_KEY:
|
|
|
|
|
case NANO_PARABEGIN_ALTKEY1:
|
|
|
|
|
case NANO_PARABEGIN_ALTKEY2:
|
|
|
|
|
do_para_begin();
|
|
|
|
|
resetstatuspos = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case NANO_PARAEND_KEY:
|
|
|
|
|
case NANO_PARAEND_ALTKEY1:
|
|
|
|
|
case NANO_PARAEND_ALTKEY2:
|
|
|
|
|
do_para_end();
|
|
|
|
|
resetstatuspos = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case NANO_FULLJUSTIFY_KEY:
|
|
|
|
|
case NANO_FULLJUSTIFY_ALTKEY:
|
|
|
|
|
if (!ISSET(VIEW_MODE))
|
|
|
|
|
do_full_justify();
|
|
|
|
|
resetstatuspos = TRUE;
|
|
|
|
|
break;
|
2004-10-05 20:11:31 +00:00
|
|
|
|
#endif
|
2004-10-15 01:39:46 +00:00
|
|
|
|
case NANO_CANCEL_KEY:
|
|
|
|
|
ret = -1;
|
|
|
|
|
resetstatuspos = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case NANO_ENTER_KEY:
|
|
|
|
|
ret = (answer[0] == '\0') ? -2 : 0;
|
|
|
|
|
resetstatuspos = TRUE;
|
|
|
|
|
break;
|
2004-10-05 20:11:31 +00:00
|
|
|
|
}
|
|
|
|
|
blank_statusbar();
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
fprintf(stderr, "I got \"%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
|
|
|
|
|
they're cleared off. */
|
|
|
|
|
if (list)
|
|
|
|
|
edit_refresh();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void statusq_abort(void)
|
|
|
|
|
{
|
|
|
|
|
resetstatuspos = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-13 22:25:01 +00:00
|
|
|
|
void titlebar(const char *path)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2004-12-05 06:02:39 +00:00
|
|
|
|
int space;
|
2004-05-23 21:11:14 +00:00
|
|
|
|
/* The space we have available for display. */
|
|
|
|
|
size_t verlen = strlen(VERMSG) + 1;
|
|
|
|
|
/* The length of the version message. */
|
|
|
|
|
const char *prefix;
|
|
|
|
|
/* "File:", "Dir:", or "New Buffer". Goes before filename. */
|
|
|
|
|
size_t prefixlen;
|
|
|
|
|
/* strlen(prefix) + 1. */
|
|
|
|
|
const char *state;
|
|
|
|
|
/* "Modified", "View", or spaces the length of "Modified".
|
|
|
|
|
* Tells the state of this buffer. */
|
|
|
|
|
size_t statelen = 0;
|
|
|
|
|
/* strlen(state) + 1. */
|
|
|
|
|
char *exppath = NULL;
|
|
|
|
|
/* The file name, expanded for display. */
|
2004-12-05 05:42:46 +00:00
|
|
|
|
size_t exppathlen = 0;
|
2004-05-23 21:11:14 +00:00
|
|
|
|
/* strlen(exppath) + 1. */
|
2004-12-05 05:42:46 +00:00
|
|
|
|
bool newfie = FALSE;
|
2004-05-23 21:11:14 +00:00
|
|
|
|
/* Do we say "New Buffer"? */
|
2004-12-05 05:42:46 +00:00
|
|
|
|
bool dots = FALSE;
|
2004-05-23 21:11:14 +00:00
|
|
|
|
/* Do we put an ellipsis before the path? */
|
|
|
|
|
|
|
|
|
|
assert(path != NULL || filename != NULL);
|
|
|
|
|
assert(COLS >= 0);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
wattron(topwin, A_REVERSE);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
|
blank_titlebar();
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
|
if (COLS <= 5 || COLS - 5 < verlen)
|
|
|
|
|
space = 0;
|
|
|
|
|
else {
|
|
|
|
|
space = COLS - 5 - verlen;
|
2004-05-25 23:34:43 +00:00
|
|
|
|
/* Reserve 2/3 of the screen plus one column for after the
|
|
|
|
|
* version message. */
|
|
|
|
|
if (space < COLS - (COLS / 3) + 1)
|
|
|
|
|
space = COLS - (COLS / 3) + 1;
|
2004-05-23 21:11:14 +00:00
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
|
if (COLS > 4) {
|
2004-05-25 23:34:43 +00:00
|
|
|
|
/* The version message should only take up 1/3 of the screen
|
|
|
|
|
* minus one column. */
|
|
|
|
|
mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
|
2004-05-23 21:11:14 +00:00
|
|
|
|
waddstr(topwin, " ");
|
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
if (ISSET(MODIFIED))
|
2004-05-23 21:11:14 +00:00
|
|
|
|
state = _("Modified");
|
|
|
|
|
else if (path == NULL && ISSET(VIEW_MODE))
|
|
|
|
|
state = _("View");
|
|
|
|
|
else {
|
|
|
|
|
if (space > 0)
|
|
|
|
|
statelen = strnlen(_("Modified"), space - 1) + 1;
|
|
|
|
|
state = &hblank[COLS - statelen];
|
|
|
|
|
}
|
|
|
|
|
statelen = strnlen(state, COLS);
|
|
|
|
|
/* We need a space before state. */
|
|
|
|
|
if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
|
|
|
|
|
statelen++;
|
|
|
|
|
|
|
|
|
|
assert(space >= 0);
|
|
|
|
|
if (space == 0 || statelen >= space)
|
|
|
|
|
goto the_end;
|
|
|
|
|
|
|
|
|
|
#ifndef DISABLE_BROWSER
|
|
|
|
|
if (path != NULL)
|
|
|
|
|
prefix = _("DIR:");
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
if (filename[0] == '\0') {
|
|
|
|
|
prefix = _("New Buffer");
|
2004-12-05 05:42:46 +00:00
|
|
|
|
newfie = TRUE;
|
2004-05-23 21:11:14 +00:00
|
|
|
|
} else
|
|
|
|
|
prefix = _("File:");
|
|
|
|
|
assert(statelen < space);
|
|
|
|
|
prefixlen = strnlen(prefix, space - statelen);
|
2004-12-05 05:42:46 +00:00
|
|
|
|
/* If newfie is FALSE, we need a space after prefix. */
|
|
|
|
|
if (!newfie && prefixlen + statelen < space)
|
2004-05-23 21:11:14 +00:00
|
|
|
|
prefixlen++;
|
|
|
|
|
|
|
|
|
|
if (path == NULL)
|
|
|
|
|
path = filename;
|
2004-12-05 05:42:46 +00:00
|
|
|
|
if (space >= prefixlen + statelen)
|
|
|
|
|
space -= prefixlen + statelen;
|
|
|
|
|
else
|
|
|
|
|
space = 0;
|
2004-05-23 21:11:14 +00:00
|
|
|
|
/* space is now the room we have for the file name. */
|
2004-12-05 05:42:46 +00:00
|
|
|
|
if (!newfie) {
|
2004-05-23 21:11:14 +00:00
|
|
|
|
size_t lenpt = strlenpt(path), start_col;
|
|
|
|
|
|
|
|
|
|
if (lenpt > space)
|
|
|
|
|
start_col = actual_x(path, lenpt - space);
|
|
|
|
|
else
|
|
|
|
|
start_col = 0;
|
|
|
|
|
exppath = display_string(path, start_col, space);
|
|
|
|
|
dots = (lenpt > space);
|
2004-12-05 05:42:46 +00:00
|
|
|
|
exppathlen = strlen(exppath);
|
2004-05-23 21:11:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!dots) {
|
|
|
|
|
/* There is room for the whole filename, so we center it. */
|
2004-12-05 05:42:46 +00:00
|
|
|
|
waddnstr(topwin, hblank, (space - exppathlen) / 3);
|
2004-05-23 21:11:14 +00:00
|
|
|
|
waddnstr(topwin, prefix, prefixlen);
|
2004-12-05 05:42:46 +00:00
|
|
|
|
if (!newfie) {
|
2004-05-23 21:11:14 +00:00
|
|
|
|
assert(strlen(prefix) + 1 == prefixlen);
|
|
|
|
|
waddch(topwin, ' ');
|
|
|
|
|
waddstr(topwin, exppath);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* We will say something like "File: ...ename". */
|
|
|
|
|
waddnstr(topwin, prefix, prefixlen);
|
2004-12-05 05:42:46 +00:00
|
|
|
|
if (space == 0 || newfie)
|
2004-05-23 21:11:14 +00:00
|
|
|
|
goto the_end;
|
|
|
|
|
waddch(topwin, ' ');
|
|
|
|
|
waddnstr(topwin, "...", space);
|
|
|
|
|
if (space <= 3)
|
|
|
|
|
goto the_end;
|
|
|
|
|
space -= 3;
|
2004-12-05 05:42:46 +00:00
|
|
|
|
assert(exppathlen == space + 3);
|
2004-05-23 21:11:14 +00:00
|
|
|
|
waddnstr(topwin, exppath + 3, space);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
the_end:
|
|
|
|
|
free(exppath);
|
|
|
|
|
|
|
|
|
|
if (COLS <= 1 || statelen >= COLS - 1)
|
|
|
|
|
mvwaddnstr(topwin, 0, 0, state, COLS);
|
|
|
|
|
else {
|
|
|
|
|
assert(COLS - statelen - 2 >= 0);
|
|
|
|
|
mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
|
|
|
|
|
mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
|
|
|
|
|
}
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wattroff(topwin, A_REVERSE);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
|
wnoutrefresh(topwin);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
reset_cursor();
|
2004-05-23 21:11:14 +00:00
|
|
|
|
wrefresh(edit);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
|
/* If modified is not already set, set it and update titlebar. */
|
|
|
|
|
void set_modified(void)
|
|
|
|
|
{
|
|
|
|
|
if (!ISSET(MODIFIED)) {
|
|
|
|
|
SET(MODIFIED);
|
|
|
|
|
titlebar(NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void statusbar(const char *msg, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
va_start(ap, msg);
|
|
|
|
|
|
|
|
|
|
/* Curses mode is turned off. If we use wmove() now, it will muck
|
|
|
|
|
* up the terminal settings. So we just use vfprintf(). */
|
|
|
|
|
if (curses_ended) {
|
|
|
|
|
vfprintf(stderr, msg, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Blank out the line. */
|
|
|
|
|
blank_statusbar();
|
|
|
|
|
|
|
|
|
|
if (COLS >= 4) {
|
|
|
|
|
char *bar;
|
|
|
|
|
char *foo;
|
|
|
|
|
size_t start_x = 0, foo_len;
|
2004-05-29 16:25:30 +00:00
|
|
|
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
2004-12-05 04:18:26 +00:00
|
|
|
|
bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
|
2004-05-29 16:25:30 +00:00
|
|
|
|
UNSET(WHITESPACE_DISPLAY);
|
|
|
|
|
#endif
|
2004-05-18 01:20:36 +00:00
|
|
|
|
bar = charalloc(COLS - 3);
|
|
|
|
|
vsnprintf(bar, COLS - 3, msg, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
foo = display_string(bar, 0, COLS - 4);
|
2004-05-29 16:25:30 +00:00
|
|
|
|
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
|
|
|
|
|
if (old_whitespace)
|
|
|
|
|
SET(WHITESPACE_DISPLAY);
|
|
|
|
|
#endif
|
2004-05-18 01:20:36 +00:00
|
|
|
|
free(bar);
|
|
|
|
|
foo_len = strlen(foo);
|
|
|
|
|
start_x = (COLS - foo_len - 4) / 2;
|
|
|
|
|
|
|
|
|
|
wmove(bottomwin, 0, start_x);
|
|
|
|
|
wattron(bottomwin, A_REVERSE);
|
|
|
|
|
|
|
|
|
|
waddstr(bottomwin, "[ ");
|
|
|
|
|
waddstr(bottomwin, foo);
|
|
|
|
|
free(foo);
|
|
|
|
|
waddstr(bottomwin, " ]");
|
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
|
|
|
|
wnoutrefresh(bottomwin);
|
|
|
|
|
reset_cursor();
|
|
|
|
|
wrefresh(edit);
|
|
|
|
|
/* Leave the cursor at its position in the edit window, not
|
|
|
|
|
* in the statusbar. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SET(DISABLE_CURPOS);
|
2004-09-30 22:07:21 +00:00
|
|
|
|
statusblank = 26;
|
2004-05-18 01:20:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-05-12 19:52:15 +00:00
|
|
|
|
void bottombars(const shortcut *s)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2004-05-23 21:11:14 +00:00
|
|
|
|
size_t i, colwidth, slen;
|
2002-02-15 19:17:02 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (ISSET(NO_HELP))
|
|
|
|
|
return;
|
|
|
|
|
|
2002-05-12 19:52:15 +00:00
|
|
|
|
if (s == main_list) {
|
|
|
|
|
slen = MAIN_VISIBLE;
|
2004-05-23 21:11:14 +00:00
|
|
|
|
assert(slen <= length_of_list(s));
|
2004-05-13 17:28:03 +00:00
|
|
|
|
} else {
|
2002-05-12 19:52:15 +00:00
|
|
|
|
slen = length_of_list(s);
|
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
|
/* Don't show any more shortcuts than the main list does. */
|
2004-05-13 17:28:03 +00:00
|
|
|
|
if (slen > MAIN_VISIBLE)
|
|
|
|
|
slen = MAIN_VISIBLE;
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
|
/* There will be this many characters per column. We need at least
|
|
|
|
|
* 3 to display anything properly.*/
|
|
|
|
|
colwidth = COLS / ((slen / 2) + (slen % 2));
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
|
blank_bottombars();
|
2001-06-14 02:54:22 +00:00
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
|
for (i = 0; i < slen; i++, s = s->next) {
|
2004-10-25 15:00:38 +00:00
|
|
|
|
const char *keystr;
|
2001-06-14 02:54:22 +00:00
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
|
/* Yucky sentinel values we can't handle a better way. */
|
2003-01-05 20:57:07 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
2004-05-23 21:11:14 +00:00
|
|
|
|
if (s->ctrlval == NANO_HISTORY_KEY)
|
2004-10-25 15:00:38 +00:00
|
|
|
|
keystr = _("Up");
|
|
|
|
|
else {
|
2003-12-24 03:33:09 +00:00
|
|
|
|
#endif
|
2004-10-25 15:00:38 +00:00
|
|
|
|
char foo[4];
|
|
|
|
|
|
|
|
|
|
if (s->ctrlval == NANO_CONTROL_SPACE)
|
|
|
|
|
strcpy(foo, "^ ");
|
|
|
|
|
else if (s->ctrlval == NANO_CONTROL_8)
|
|
|
|
|
strcpy(foo, "^?");
|
|
|
|
|
/* Normal values. Assume that the shortcut has an
|
|
|
|
|
* equivalent control key, meta key sequence, or both. */
|
|
|
|
|
else if (s->ctrlval != NANO_NO_KEY)
|
|
|
|
|
sprintf(foo, "^%c", s->ctrlval + 64);
|
|
|
|
|
else if (s->metaval != NANO_NO_KEY)
|
|
|
|
|
sprintf(foo, "M-%c", toupper(s->metaval));
|
2004-05-23 21:11:14 +00:00
|
|
|
|
|
2004-10-25 15:00:38 +00:00
|
|
|
|
keystr = foo;
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
|
2004-05-23 21:11:14 +00:00
|
|
|
|
onekey(keystr, s->desc, colwidth);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
|
wnoutrefresh(bottomwin);
|
|
|
|
|
reset_cursor();
|
|
|
|
|
wrefresh(edit);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
|
/* Write a shortcut key to the help area at the bottom of the window.
|
|
|
|
|
* keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
|
|
|
|
|
* to write at most len characters, even if len is very small and
|
|
|
|
|
* keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
|
|
|
|
|
* the whole string! We do not bother padding the entry with blanks. */
|
|
|
|
|
void onekey(const char *keystroke, const char *desc, size_t len)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2004-05-23 21:11:14 +00:00
|
|
|
|
assert(keystroke != NULL && desc != NULL && len >= 0);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
wattron(bottomwin, A_REVERSE);
|
|
|
|
|
waddnstr(bottomwin, keystroke, len);
|
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
2004-05-23 21:11:14 +00:00
|
|
|
|
len -= strlen(keystroke) + 1;
|
2002-09-06 20:35:28 +00:00
|
|
|
|
if (len > 0) {
|
|
|
|
|
waddch(bottomwin, ' ');
|
|
|
|
|
waddnstr(bottomwin, desc, len);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* And so start the display update routines. */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
int check_linenumbers(const filestruct *fileptr)
|
2000-06-21 03:00:43 +00:00
|
|
|
|
{
|
2002-09-27 14:21:59 +00:00
|
|
|
|
int check_line = 0;
|
|
|
|
|
const filestruct *filetmp;
|
2000-06-06 23:04:06 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
|
|
|
|
|
check_line++;
|
|
|
|
|
return check_line;
|
2000-06-06 23:04:06 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
#endif
|
2000-06-06 23:04:06 +00:00
|
|
|
|
|
2003-09-29 05:15:24 +00:00
|
|
|
|
/* nano scrolls horizontally within a line in chunks. This function
|
|
|
|
|
* returns the column number of the first character displayed in the
|
|
|
|
|
* window when the cursor is at the given column. Note that
|
|
|
|
|
* 0 <= column - get_page_start(column) < COLS. */
|
|
|
|
|
size_t get_page_start(size_t column)
|
2002-07-19 01:08:59 +00:00
|
|
|
|
{
|
2003-09-29 05:15:24 +00:00
|
|
|
|
assert(COLS > 0);
|
|
|
|
|
if (column == 0 || column < COLS - 1)
|
|
|
|
|
return 0;
|
|
|
|
|
else if (COLS > 9)
|
2004-01-22 07:25:31 +00:00
|
|
|
|
return column - 7 - (column - 7) % (COLS - 8);
|
2003-09-29 05:15:24 +00:00
|
|
|
|
else if (COLS > 2)
|
|
|
|
|
return column - (COLS - 2);
|
|
|
|
|
else
|
|
|
|
|
return column - (COLS - 1);
|
|
|
|
|
/* The parentheses are necessary to avoid overflow. */
|
2002-07-19 01:08:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-21 16:10:37 +00:00
|
|
|
|
/* Resets current_y, based on the position of current, and puts the
|
2004-09-05 21:40:31 +00:00
|
|
|
|
* cursor in the edit window at (current_y, current_x). */
|
2002-08-21 16:10:37 +00:00
|
|
|
|
void reset_cursor(void)
|
|
|
|
|
{
|
2004-09-05 21:40:31 +00:00
|
|
|
|
/* If we haven't opened any files yet, put the cursor in the top
|
|
|
|
|
* left corner of the edit window and get out. */
|
|
|
|
|
if (edittop == NULL || current == NULL) {
|
|
|
|
|
wmove(edit, 0, 0);
|
2002-08-21 16:10:37 +00:00
|
|
|
|
return;
|
2004-09-05 21:40:31 +00:00
|
|
|
|
}
|
2002-08-21 16:10:37 +00:00
|
|
|
|
|
2004-02-24 20:41:39 +00:00
|
|
|
|
current_y = current->lineno - edittop->lineno;
|
|
|
|
|
if (current_y < editwinrows) {
|
|
|
|
|
size_t x = xplustabs();
|
|
|
|
|
wmove(edit, current_y, x - get_page_start(x));
|
|
|
|
|
}
|
2002-08-21 16:10:37 +00:00
|
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* edit_add() takes care of the job of actually painting a line into the
|
|
|
|
|
* edit window. fileptr is the line to be painted, at row yval of the
|
|
|
|
|
* window. converted is the actual string to be written to the window,
|
|
|
|
|
* with tabs and control characters replaced by strings of regular
|
2004-05-23 21:23:23 +00:00
|
|
|
|
* characters. start is the column number of the first character of
|
|
|
|
|
* this page. That is, the first character of converted corresponds to
|
2003-09-16 01:16:49 +00:00
|
|
|
|
* character number actual_x(fileptr->data, start) of the line. */
|
2004-04-16 05:15:11 +00:00
|
|
|
|
void edit_add(const filestruct *fileptr, const char *converted, int
|
|
|
|
|
yval, size_t start)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2003-09-16 01:16:49 +00:00
|
|
|
|
#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
|
|
|
|
|
size_t startpos = actual_x(fileptr->data, start);
|
|
|
|
|
/* The position in fileptr->data of the leftmost character
|
|
|
|
|
* that displays at least partially on the window. */
|
|
|
|
|
size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
|
|
|
|
|
/* The position in fileptr->data of the first character that is
|
|
|
|
|
* completely off the window to the right.
|
|
|
|
|
*
|
|
|
|
|
* Note that endpos might be beyond the null terminator of the
|
|
|
|
|
* string. */
|
2001-12-02 04:55:44 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
assert(fileptr != NULL && converted != NULL);
|
|
|
|
|
assert(strlen(converted) <= COLS);
|
|
|
|
|
|
2001-12-02 04:55:44 +00:00
|
|
|
|
/* Just paint the string in any case (we'll add color or reverse on
|
2003-09-16 01:16:49 +00:00
|
|
|
|
* just the text that needs it). */
|
|
|
|
|
mvwaddstr(edit, yval, 0, converted);
|
2001-12-02 04:55:44 +00:00
|
|
|
|
|
2001-12-08 19:52:28 +00:00
|
|
|
|
#ifdef ENABLE_COLOR
|
2002-10-13 18:43:45 +00:00
|
|
|
|
if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
|
2002-09-27 14:21:59 +00:00
|
|
|
|
const colortype *tmpcolor = colorstrings;
|
|
|
|
|
|
|
|
|
|
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
|
|
|
|
int x_start;
|
|
|
|
|
/* Starting column for mvwaddnstr. Zero-based. */
|
|
|
|
|
int paintlen;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Number of chars to paint on this line. There are COLS
|
2002-09-27 14:21:59 +00:00
|
|
|
|
* characters on a whole line. */
|
2003-09-16 01:16:49 +00:00
|
|
|
|
regmatch_t startmatch; /* match position for start_regexp */
|
|
|
|
|
regmatch_t endmatch; /* match position for end_regexp */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
|
|
|
|
|
if (tmpcolor->bright)
|
|
|
|
|
wattron(edit, A_BOLD);
|
|
|
|
|
wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Two notes about regexec(). Return value 0 means there is
|
|
|
|
|
* a match. Also, rm_eo is the first non-matching character
|
2002-09-27 14:21:59 +00:00
|
|
|
|
* after the match. */
|
|
|
|
|
|
|
|
|
|
/* First case, tmpcolor is a single-line expression. */
|
2002-01-19 16:52:34 +00:00
|
|
|
|
if (tmpcolor->end == NULL) {
|
2002-09-27 14:21:59 +00:00
|
|
|
|
size_t k = 0;
|
|
|
|
|
|
|
|
|
|
/* We increment k by rm_eo, to move past the end of the
|
2003-09-16 01:16:49 +00:00
|
|
|
|
* last match. Even though two matches may overlap, we
|
|
|
|
|
* want to ignore them, so that we can highlight
|
|
|
|
|
* C-strings correctly. */
|
|
|
|
|
while (k < endpos) {
|
|
|
|
|
/* Note the fifth parameter to regexec(). It says
|
|
|
|
|
* not to match the beginning-of-line character
|
|
|
|
|
* unless k is 0. If regexec() returns REG_NOMATCH,
|
|
|
|
|
* there are no more matches in the line. */
|
2003-02-03 02:56:44 +00:00
|
|
|
|
if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
|
2003-09-16 01:16:49 +00:00
|
|
|
|
&startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
|
2002-01-19 16:52:34 +00:00
|
|
|
|
break;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* Translate the match to the beginning of the line. */
|
|
|
|
|
startmatch.rm_so += k;
|
|
|
|
|
startmatch.rm_eo += k;
|
2002-10-17 02:19:31 +00:00
|
|
|
|
if (startmatch.rm_so == startmatch.rm_eo) {
|
|
|
|
|
startmatch.rm_eo++;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
statusbar(_("Refusing 0 length regex match"));
|
2003-09-16 01:16:49 +00:00
|
|
|
|
} else if (startmatch.rm_so < endpos &&
|
|
|
|
|
startmatch.rm_eo > startpos) {
|
|
|
|
|
if (startmatch.rm_so <= startpos)
|
2002-09-27 14:21:59 +00:00
|
|
|
|
x_start = 0;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
else
|
2004-04-29 06:30:36 +00:00
|
|
|
|
x_start = strnlenpt(fileptr->data,
|
|
|
|
|
startmatch.rm_so) - start;
|
|
|
|
|
paintlen = strnlenpt(fileptr->data,
|
|
|
|
|
startmatch.rm_eo) - start - x_start;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (paintlen > COLS - x_start)
|
|
|
|
|
paintlen = COLS - x_start;
|
|
|
|
|
|
|
|
|
|
assert(0 <= x_start && 0 < paintlen &&
|
|
|
|
|
x_start + paintlen <= COLS);
|
|
|
|
|
mvwaddnstr(edit, yval, x_start,
|
2003-09-16 01:16:49 +00:00
|
|
|
|
converted + x_start, paintlen);
|
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
k = startmatch.rm_eo;
|
2002-01-19 01:59:37 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
} else {
|
|
|
|
|
/* This is a multi-line regexp. There are two steps.
|
|
|
|
|
* First, we have to see if the beginning of the line is
|
|
|
|
|
* colored by a start on an earlier line, and an end on
|
|
|
|
|
* this line or later.
|
|
|
|
|
*
|
|
|
|
|
* We find the first line before fileptr matching the
|
|
|
|
|
* start. If every match on that line is followed by an
|
|
|
|
|
* end, then go to step two. Otherwise, find the next line
|
|
|
|
|
* after start_line matching the end. If that line is not
|
|
|
|
|
* before fileptr, then paint the beginning of this line. */
|
|
|
|
|
|
|
|
|
|
const filestruct *start_line = fileptr->prev;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* the first line before fileptr matching start */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
regoff_t start_col;
|
|
|
|
|
/* where it starts in that line */
|
|
|
|
|
const filestruct *end_line;
|
|
|
|
|
|
|
|
|
|
while (start_line != NULL &&
|
2003-02-03 02:56:44 +00:00
|
|
|
|
regexec(&tmpcolor->start, start_line->data, 1,
|
2003-09-16 01:16:49 +00:00
|
|
|
|
&startmatch, 0) == REG_NOMATCH) {
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* If there is an end on this line, there is no need
|
|
|
|
|
* to look for starts on earlier lines. */
|
2004-04-29 06:30:36 +00:00
|
|
|
|
if (regexec(tmpcolor->end, start_line->data, 0,
|
|
|
|
|
NULL, 0) == 0)
|
2002-09-27 14:21:59 +00:00
|
|
|
|
goto step_two;
|
|
|
|
|
start_line = start_line->prev;
|
|
|
|
|
}
|
|
|
|
|
/* No start found, so skip to the next step. */
|
|
|
|
|
if (start_line == NULL)
|
|
|
|
|
goto step_two;
|
|
|
|
|
/* Now start_line is the first line before fileptr
|
|
|
|
|
* containing a start match. Is there a start on this
|
|
|
|
|
* line not followed by an end on this line? */
|
|
|
|
|
|
|
|
|
|
start_col = 0;
|
2004-03-15 20:26:30 +00:00
|
|
|
|
while (TRUE) {
|
2002-09-27 14:21:59 +00:00
|
|
|
|
start_col += startmatch.rm_so;
|
|
|
|
|
startmatch.rm_eo -= startmatch.rm_so;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
if (regexec(tmpcolor->end,
|
2004-04-29 06:30:36 +00:00
|
|
|
|
start_line->data + start_col + startmatch.rm_eo,
|
2003-09-16 01:16:49 +00:00
|
|
|
|
0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
|
|
|
|
|
REG_NOTBOL) == REG_NOMATCH)
|
|
|
|
|
/* No end found after this start. */
|
2002-01-19 16:52:34 +00:00
|
|
|
|
break;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
start_col++;
|
2003-02-03 02:56:44 +00:00
|
|
|
|
if (regexec(&tmpcolor->start,
|
2004-04-29 06:30:36 +00:00
|
|
|
|
start_line->data + start_col, 1,
|
|
|
|
|
&startmatch, REG_NOTBOL) == REG_NOMATCH)
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* No later start on this line. */
|
|
|
|
|
goto step_two;
|
2002-01-19 16:52:34 +00:00
|
|
|
|
}
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Indeed, there is a start not followed on this line by
|
|
|
|
|
* an end. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
|
|
|
|
|
/* We have already checked that there is no end before
|
|
|
|
|
* fileptr and after the start. Is there an end after
|
2003-09-16 01:16:49 +00:00
|
|
|
|
* the start at all? We don't paint unterminated
|
|
|
|
|
* starts. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
end_line = fileptr;
|
2003-02-03 02:56:44 +00:00
|
|
|
|
while (end_line != NULL &&
|
2004-06-24 22:39:24 +00:00
|
|
|
|
regexec(tmpcolor->end, end_line->data, 1,
|
|
|
|
|
&endmatch, 0) == REG_NOMATCH)
|
2002-09-27 14:21:59 +00:00
|
|
|
|
end_line = end_line->next;
|
|
|
|
|
|
|
|
|
|
/* No end found, or it is too early. */
|
2003-09-16 01:16:49 +00:00
|
|
|
|
if (end_line == NULL ||
|
|
|
|
|
(end_line == fileptr && endmatch.rm_eo <= startpos))
|
2002-09-27 14:21:59 +00:00
|
|
|
|
goto step_two;
|
|
|
|
|
|
|
|
|
|
/* Now paint the start of fileptr. */
|
2003-09-16 01:16:49 +00:00
|
|
|
|
paintlen = end_line != fileptr ? COLS :
|
|
|
|
|
strnlenpt(fileptr->data, endmatch.rm_eo) - start;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (paintlen > COLS)
|
|
|
|
|
paintlen = COLS;
|
|
|
|
|
|
|
|
|
|
assert(0 < paintlen && paintlen <= COLS);
|
2003-09-16 01:16:49 +00:00
|
|
|
|
mvwaddnstr(edit, yval, 0, converted, paintlen);
|
2002-09-27 14:21:59 +00:00
|
|
|
|
|
|
|
|
|
/* We have already painted the whole line. */
|
|
|
|
|
if (paintlen == COLS)
|
|
|
|
|
goto skip_step_two;
|
|
|
|
|
|
2004-05-13 18:04:31 +00:00
|
|
|
|
step_two:
|
|
|
|
|
/* Second step, we look for starts on this line. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
start_col = 0;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
while (start_col < endpos) {
|
2004-04-29 06:30:36 +00:00
|
|
|
|
if (regexec(&tmpcolor->start,
|
|
|
|
|
fileptr->data + start_col, 1, &startmatch,
|
|
|
|
|
start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
|
|
|
|
|
start_col + startmatch.rm_so >= endpos)
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* No more starts on this line. */
|
|
|
|
|
break;
|
|
|
|
|
/* Translate the match to be relative to the
|
|
|
|
|
* beginning of the line. */
|
|
|
|
|
startmatch.rm_so += start_col;
|
|
|
|
|
startmatch.rm_eo += start_col;
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
if (startmatch.rm_so <= startpos)
|
2002-09-27 14:21:59 +00:00
|
|
|
|
x_start = 0;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
else
|
2004-04-29 06:30:36 +00:00
|
|
|
|
x_start = strnlenpt(fileptr->data,
|
|
|
|
|
startmatch.rm_so) - start;
|
|
|
|
|
if (regexec(tmpcolor->end,
|
|
|
|
|
fileptr->data + startmatch.rm_eo, 1, &endmatch,
|
|
|
|
|
startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* Translate the end match to be relative to the
|
2003-09-16 01:16:49 +00:00
|
|
|
|
* beginning of the line. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
endmatch.rm_so += startmatch.rm_eo;
|
|
|
|
|
endmatch.rm_eo += startmatch.rm_eo;
|
|
|
|
|
/* There is an end on this line. But does it
|
2004-05-13 18:04:31 +00:00
|
|
|
|
* appear on this page, and is the match more
|
|
|
|
|
* than zero characters long? */
|
2003-09-16 01:16:49 +00:00
|
|
|
|
if (endmatch.rm_eo > startpos &&
|
2002-09-27 14:21:59 +00:00
|
|
|
|
endmatch.rm_eo > startmatch.rm_so) {
|
2004-04-29 06:30:36 +00:00
|
|
|
|
paintlen = strnlenpt(fileptr->data,
|
|
|
|
|
endmatch.rm_eo) - start - x_start;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (x_start + paintlen > COLS)
|
|
|
|
|
paintlen = COLS - x_start;
|
|
|
|
|
|
|
|
|
|
assert(0 <= x_start && 0 < paintlen &&
|
2004-04-29 06:30:36 +00:00
|
|
|
|
x_start + paintlen <= COLS);
|
2002-09-27 14:21:59 +00:00
|
|
|
|
mvwaddnstr(edit, yval, x_start,
|
2003-09-16 01:16:49 +00:00
|
|
|
|
converted + x_start, paintlen);
|
2002-01-19 16:52:34 +00:00
|
|
|
|
}
|
2004-04-29 06:30:36 +00:00
|
|
|
|
} else {
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* There is no end on this line. But we haven't
|
|
|
|
|
* yet looked for one on later lines. */
|
|
|
|
|
end_line = fileptr->next;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
while (end_line != NULL &&
|
|
|
|
|
regexec(tmpcolor->end, end_line->data, 0,
|
|
|
|
|
NULL, 0) == REG_NOMATCH)
|
2002-09-27 14:21:59 +00:00
|
|
|
|
end_line = end_line->next;
|
|
|
|
|
if (end_line != NULL) {
|
|
|
|
|
assert(0 <= x_start && x_start < COLS);
|
|
|
|
|
mvwaddnstr(edit, yval, x_start,
|
2004-04-29 06:30:36 +00:00
|
|
|
|
converted + x_start, COLS - x_start);
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* We painted to the end of the line, so
|
|
|
|
|
* don't bother checking any more starts. */
|
|
|
|
|
break;
|
2002-01-19 16:52:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
start_col = startmatch.rm_so + 1;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
} /* while start_col < endpos */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
} /* if (tmp_color->end != NULL) */
|
2002-05-12 20:43:49 +00:00
|
|
|
|
|
2003-02-03 02:56:44 +00:00
|
|
|
|
skip_step_two:
|
2002-09-27 14:21:59 +00:00
|
|
|
|
wattroff(edit, A_BOLD);
|
|
|
|
|
wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
|
|
|
|
|
} /* for tmpcolor in colorstrings */
|
|
|
|
|
}
|
2002-01-19 01:59:37 +00:00
|
|
|
|
#endif /* ENABLE_COLOR */
|
2001-12-02 04:55:44 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (ISSET(MARK_ISSET)
|
|
|
|
|
&& (fileptr->lineno <= mark_beginbuf->lineno
|
|
|
|
|
|| fileptr->lineno <= current->lineno)
|
|
|
|
|
&& (fileptr->lineno >= mark_beginbuf->lineno
|
|
|
|
|
|| fileptr->lineno >= current->lineno)) {
|
|
|
|
|
/* fileptr is at least partially selected. */
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
const filestruct *top;
|
|
|
|
|
/* Either current or mark_beginbuf, whichever is first. */
|
|
|
|
|
size_t top_x;
|
|
|
|
|
/* current_x or mark_beginx, corresponding to top. */
|
|
|
|
|
const filestruct *bot;
|
|
|
|
|
size_t bot_x;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
int x_start;
|
|
|
|
|
/* Starting column for mvwaddnstr. Zero-based. */
|
|
|
|
|
int paintlen;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Number of chars to paint on this line. There are COLS
|
2002-09-27 14:21:59 +00:00
|
|
|
|
* characters on a whole line. */
|
|
|
|
|
|
2004-11-05 23:03:03 +00:00
|
|
|
|
mark_order(&top, &top_x, &bot, &bot_x, NULL);
|
2003-09-16 01:16:49 +00:00
|
|
|
|
|
|
|
|
|
if (top->lineno < fileptr->lineno || top_x < startpos)
|
|
|
|
|
top_x = startpos;
|
|
|
|
|
if (bot->lineno > fileptr->lineno || bot_x > endpos)
|
|
|
|
|
bot_x = endpos;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
2003-10-03 04:20:28 +00:00
|
|
|
|
/* The selected bit of fileptr is on this page. */
|
2003-09-16 01:16:49 +00:00
|
|
|
|
if (top_x < endpos && bot_x > startpos) {
|
|
|
|
|
assert(startpos <= top_x);
|
2003-10-03 04:20:28 +00:00
|
|
|
|
|
|
|
|
|
/* x_start is the expanded location of the beginning of the
|
|
|
|
|
* mark minus the beginning of the page. */
|
|
|
|
|
x_start = strnlenpt(fileptr->data, top_x) - start;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
|
|
|
|
|
if (bot_x >= endpos)
|
2003-10-03 04:20:28 +00:00
|
|
|
|
/* If the end of the mark is off the page, paintlen is
|
|
|
|
|
* -1, meaning that everything on the line gets
|
|
|
|
|
* painted. */
|
|
|
|
|
paintlen = -1;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
else
|
2003-10-03 04:20:28 +00:00
|
|
|
|
/* Otherwise, paintlen is the expanded location of the
|
|
|
|
|
* end of the mark minus the expanded location of the
|
|
|
|
|
* beginning of the mark. */
|
2004-04-29 06:30:36 +00:00
|
|
|
|
paintlen = strnlenpt(fileptr->data, bot_x)
|
|
|
|
|
- (x_start + start);
|
2003-10-03 04:20:28 +00:00
|
|
|
|
|
|
|
|
|
/* If x_start is before the beginning of the page, shift
|
|
|
|
|
* paintlen x_start characters to compensate, and put
|
|
|
|
|
* x_start at the beginning of the page. */
|
|
|
|
|
if (x_start < 0) {
|
|
|
|
|
paintlen += x_start;
|
|
|
|
|
x_start = 0;
|
|
|
|
|
}
|
2003-09-16 01:16:49 +00:00
|
|
|
|
|
|
|
|
|
assert(x_start >= 0 && x_start <= strlen(converted));
|
|
|
|
|
|
2000-10-26 01:44:42 +00:00
|
|
|
|
wattron(edit, A_REVERSE);
|
2003-09-16 01:16:49 +00:00
|
|
|
|
mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
|
2000-10-26 01:44:42 +00:00
|
|
|
|
wattroff(edit, A_REVERSE);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2001-11-29 02:42:27 +00:00
|
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
|
#endif /* !NANO_SMALL */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-08 23:24:31 +00:00
|
|
|
|
/* Just update one line in the edit buffer. This is basically a wrapper
|
|
|
|
|
* for edit_add().
|
2003-09-16 01:16:49 +00:00
|
|
|
|
*
|
2004-04-16 05:15:11 +00:00
|
|
|
|
* If fileptr != current, then index is considered 0. The line will be
|
|
|
|
|
* displayed starting with fileptr->data[index]. Likely args are
|
|
|
|
|
* current_x or 0. */
|
2003-09-16 01:16:49 +00:00
|
|
|
|
void update_line(const filestruct *fileptr, size_t index)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2002-09-27 14:21:59 +00:00
|
|
|
|
int line;
|
2004-12-08 23:24:31 +00:00
|
|
|
|
/* The line in the edit window that we want to update. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
char *converted;
|
|
|
|
|
/* fileptr->data converted to have tabs and control characters
|
|
|
|
|
* expanded. */
|
|
|
|
|
size_t page_start;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
assert(fileptr != NULL);
|
2000-06-18 00:11:03 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
line = fileptr->lineno - edittop->lineno;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
/* We assume the line numbers are valid. Is that really true? */
|
|
|
|
|
assert(line < 0 || line == check_linenumbers(fileptr));
|
2000-06-16 04:25:30 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (line < 0 || line >= editwinrows)
|
|
|
|
|
return;
|
2000-06-16 04:25:30 +00:00
|
|
|
|
|
2004-12-08 23:24:31 +00:00
|
|
|
|
/* First, blank out the line. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
mvwaddstr(edit, line, 0, hblank);
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Next, convert variables that index the line to their equivalent
|
|
|
|
|
* positions in the expanded line. */
|
2003-09-29 05:15:24 +00:00
|
|
|
|
index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
page_start = get_page_start(index);
|
2003-01-05 20:41:21 +00:00
|
|
|
|
|
2004-12-08 23:24:31 +00:00
|
|
|
|
/* Expand the line, replacing tabs with spaces, and control
|
|
|
|
|
* characters with their displayed forms. */
|
2003-09-16 01:16:49 +00:00
|
|
|
|
converted = display_string(fileptr->data, page_start, COLS);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-12-08 23:24:31 +00:00
|
|
|
|
/* Paint the line. */
|
2003-09-16 01:16:49 +00:00
|
|
|
|
edit_add(fileptr, converted, line, page_start);
|
2002-09-27 14:21:59 +00:00
|
|
|
|
free(converted);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2002-09-27 14:21:59 +00:00
|
|
|
|
if (page_start > 0)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
mvwaddch(edit, line, 0, '$');
|
2003-09-16 01:16:49 +00:00
|
|
|
|
if (strlenpt(fileptr->data) > page_start + COLS)
|
2002-09-27 14:21:59 +00:00
|
|
|
|
mvwaddch(edit, line, COLS - 1, '$');
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-28 20:44:09 +00:00
|
|
|
|
/* Return a nonzero value if we need an update after moving
|
|
|
|
|
* horizontally. We need one if the mark is on or if old_pww and
|
2004-05-31 14:47:12 +00:00
|
|
|
|
* placewewant are on different pages. */
|
2004-07-28 20:46:25 +00:00
|
|
|
|
int need_horizontal_update(size_t old_pww)
|
2004-05-28 20:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
return
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
ISSET(MARK_ISSET) ||
|
|
|
|
|
#endif
|
|
|
|
|
get_page_start(old_pww) != get_page_start(placewewant);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return a nonzero value if we need an update after moving vertically.
|
|
|
|
|
* We need one if the mark is on or if old_pww and placewewant
|
2004-05-31 14:47:12 +00:00
|
|
|
|
* are on different pages. */
|
2004-07-28 20:46:25 +00:00
|
|
|
|
int need_vertical_update(size_t old_pww)
|
2004-05-28 20:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
return
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
ISSET(MARK_ISSET) ||
|
|
|
|
|
#endif
|
|
|
|
|
get_page_start(old_pww) != get_page_start(placewewant);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Scroll the edit window in the given direction and the given number
|
|
|
|
|
* of lines, and draw new lines on the blank lines left after the
|
|
|
|
|
* scrolling. direction is the direction to scroll, either UP or DOWN,
|
|
|
|
|
* and nlines is the number of lines to scroll. Don't redraw the old
|
|
|
|
|
* topmost or bottommost line (where we assume current is) before
|
|
|
|
|
* scrolling or draw the new topmost or bottommost line after scrolling
|
|
|
|
|
* (where we assume current will be), since we don't know where we are
|
2004-05-31 14:47:12 +00:00
|
|
|
|
* on the page or whether we'll stay there. */
|
2004-05-28 20:44:09 +00:00
|
|
|
|
void edit_scroll(updown direction, int nlines)
|
|
|
|
|
{
|
|
|
|
|
filestruct *foo;
|
|
|
|
|
int i, scroll_rows = 0;
|
|
|
|
|
|
|
|
|
|
/* Scrolling less than one line or more than editwinrows lines is
|
|
|
|
|
* redundant, so don't allow it. */
|
|
|
|
|
if (nlines < 1 || nlines > editwinrows)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Move the top line of the edit window up or down (depending on the
|
|
|
|
|
* value of direction) nlines lines. If there are fewer lines of
|
|
|
|
|
* text than that left, move it to the top or bottom line of the
|
|
|
|
|
* file (depending on the value of direction). Keep track of
|
|
|
|
|
* how many lines we moved in scroll_rows. */
|
|
|
|
|
for (i = nlines; i > 0; i--) {
|
|
|
|
|
if (direction == UP) {
|
|
|
|
|
if (edittop->prev == NULL)
|
|
|
|
|
break;
|
|
|
|
|
edittop = edittop->prev;
|
|
|
|
|
scroll_rows--;
|
|
|
|
|
} else {
|
|
|
|
|
if (edittop->next == NULL)
|
|
|
|
|
break;
|
|
|
|
|
edittop = edittop->next;
|
|
|
|
|
scroll_rows++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Scroll the text on the screen up or down scroll_rows lines,
|
|
|
|
|
* depending on the value of direction. */
|
|
|
|
|
scrollok(edit, TRUE);
|
|
|
|
|
wscrl(edit, scroll_rows);
|
|
|
|
|
scrollok(edit, FALSE);
|
|
|
|
|
|
|
|
|
|
foo = edittop;
|
|
|
|
|
if (direction != UP) {
|
|
|
|
|
int slines = editwinrows - nlines;
|
|
|
|
|
for (; slines > 0 && foo != NULL; slines--)
|
|
|
|
|
foo = foo->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* And draw new lines on the blank top or bottom lines of the edit
|
|
|
|
|
* window, depending on the value of direction. Don't draw the new
|
|
|
|
|
* topmost or new bottommost line. */
|
|
|
|
|
while (scroll_rows != 0 && foo != NULL) {
|
|
|
|
|
if (foo->next != NULL)
|
|
|
|
|
update_line(foo, 0);
|
|
|
|
|
if (direction == UP)
|
|
|
|
|
scroll_rows++;
|
|
|
|
|
else
|
|
|
|
|
scroll_rows--;
|
|
|
|
|
foo = foo->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Update any lines between old_current and current that need to be
|
2004-05-31 14:47:12 +00:00
|
|
|
|
* updated. */
|
2004-07-28 20:46:25 +00:00
|
|
|
|
void edit_redraw(const filestruct *old_current, size_t old_pww)
|
2004-05-28 20:44:09 +00:00
|
|
|
|
{
|
2004-06-01 18:32:36 +00:00
|
|
|
|
int do_refresh = need_vertical_update(0) ||
|
|
|
|
|
need_vertical_update(old_pww);
|
2004-05-28 20:44:09 +00:00
|
|
|
|
const filestruct *foo;
|
|
|
|
|
|
|
|
|
|
/* If either old_current or current is offscreen, refresh the screen
|
|
|
|
|
* and get out. */
|
|
|
|
|
if (old_current->lineno < edittop->lineno || old_current->lineno >=
|
|
|
|
|
edittop->lineno + editwinrows || current->lineno <
|
|
|
|
|
edittop->lineno || current->lineno >= edittop->lineno +
|
|
|
|
|
editwinrows) {
|
|
|
|
|
edit_refresh();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-01 18:32:36 +00:00
|
|
|
|
/* Update old_current and current if we're not on the first page
|
|
|
|
|
* and/or we're not on the same page as before. If the mark is on,
|
|
|
|
|
* update all the lines between old_current and current too. */
|
2004-05-28 20:44:09 +00:00
|
|
|
|
foo = old_current;
|
|
|
|
|
while (foo != current) {
|
|
|
|
|
if (do_refresh)
|
|
|
|
|
update_line(foo, 0);
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
if (!ISSET(MARK_ISSET))
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
if (foo->lineno > current->lineno)
|
|
|
|
|
foo = foo->prev;
|
|
|
|
|
else
|
|
|
|
|
foo = foo->next;
|
|
|
|
|
}
|
|
|
|
|
if (do_refresh)
|
|
|
|
|
update_line(current, current_x);
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
/* Refresh the screen without changing the position of lines. */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
void edit_refresh(void)
|
|
|
|
|
{
|
2003-01-26 19:47:10 +00:00
|
|
|
|
if (current->lineno < edittop->lineno ||
|
|
|
|
|
current->lineno >= edittop->lineno + editwinrows)
|
2004-08-27 17:02:05 +00:00
|
|
|
|
/* Note that edit_update() changes edittop so that it's in range
|
|
|
|
|
* of current. Thus, when it then calls edit_refresh(), there
|
|
|
|
|
* is no danger of getting an infinite loop. */
|
|
|
|
|
edit_update(
|
|
|
|
|
#ifndef NANO_SMALL
|
|
|
|
|
ISSET(SMOOTHSCROLL) ? NONE :
|
|
|
|
|
#endif
|
|
|
|
|
CENTER);
|
2002-12-22 16:30:00 +00:00
|
|
|
|
else {
|
|
|
|
|
int nlines = 0;
|
2004-02-24 20:41:39 +00:00
|
|
|
|
const filestruct *foo = edittop;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-02-24 20:41:39 +00:00
|
|
|
|
#ifdef DEBUG
|
2004-07-28 20:46:25 +00:00
|
|
|
|
fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
|
2004-02-24 20:41:39 +00:00
|
|
|
|
#endif
|
2001-10-22 03:15:31 +00:00
|
|
|
|
|
2002-12-22 16:30:00 +00:00
|
|
|
|
while (nlines < editwinrows) {
|
2004-05-29 03:03:52 +00:00
|
|
|
|
update_line(foo, foo == current ? current_x : 0);
|
2002-12-22 16:30:00 +00:00
|
|
|
|
nlines++;
|
2004-02-24 20:41:39 +00:00
|
|
|
|
if (foo->next == NULL)
|
2002-12-22 16:30:00 +00:00
|
|
|
|
break;
|
2004-02-24 20:41:39 +00:00
|
|
|
|
foo = foo->next;
|
2002-12-22 16:30:00 +00:00
|
|
|
|
}
|
|
|
|
|
while (nlines < editwinrows) {
|
|
|
|
|
mvwaddstr(edit, nlines, 0, hblank);
|
|
|
|
|
nlines++;
|
|
|
|
|
}
|
2004-02-24 20:41:39 +00:00
|
|
|
|
reset_cursor();
|
2002-12-22 16:30:00 +00:00
|
|
|
|
wrefresh(edit);
|
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-08-27 17:02:05 +00:00
|
|
|
|
/* A nice generic routine to update the edit buffer. We keep current in
|
|
|
|
|
* the same place and move edittop to put it in range of current. */
|
2004-08-26 18:07:58 +00:00
|
|
|
|
void edit_update(topmidnone location)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2004-08-26 18:07:58 +00:00
|
|
|
|
filestruct *foo = current;
|
|
|
|
|
|
2002-07-19 01:08:59 +00:00
|
|
|
|
if (location != TOP) {
|
2004-08-27 17:02:05 +00:00
|
|
|
|
/* If location is CENTER, we move edittop up (editwinrows / 2)
|
|
|
|
|
* lines. This puts current at the center of the screen. If
|
|
|
|
|
* location is NONE, we move edittop up current_y lines if
|
|
|
|
|
* current_y is in range of the screen, 0 lines if current_y is
|
|
|
|
|
* less than 0, or (editwinrows - 1) lines if current_y is
|
|
|
|
|
* greater than (editwinrows - 1). This puts current at the
|
|
|
|
|
* same place on the screen as before, or at the top or bottom
|
|
|
|
|
* of the screen if edittop is beyond either. */
|
|
|
|
|
int goal;
|
|
|
|
|
|
|
|
|
|
if (location == CENTER)
|
|
|
|
|
goal = editwinrows / 2;
|
|
|
|
|
else {
|
|
|
|
|
goal = current_y;
|
|
|
|
|
|
|
|
|
|
/* Limit goal to (editwinrows - 1) lines maximum. */
|
|
|
|
|
if (goal > editwinrows - 1)
|
|
|
|
|
goal = editwinrows - 1;
|
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-08-26 18:07:58 +00:00
|
|
|
|
for (; goal > 0 && foo->prev != NULL; goal--)
|
|
|
|
|
foo = foo->prev;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
}
|
2004-08-27 17:02:05 +00:00
|
|
|
|
|
2004-08-26 18:07:58 +00:00
|
|
|
|
edittop = foo;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
edit_refresh();
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-26 15:24:16 +00:00
|
|
|
|
/* Ask a simple yes/no question, specified in msg, on the statusbar.
|
|
|
|
|
* Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
|
|
|
|
|
* and -1 for abort (^C). */
|
2004-10-05 20:11:31 +00:00
|
|
|
|
int do_yesno(bool all, const char *msg)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2003-12-24 03:33:09 +00:00
|
|
|
|
int ok = -2, width = 16;
|
2004-06-12 21:20:33 +00:00
|
|
|
|
const char *yesstr; /* String of yes characters accepted. */
|
|
|
|
|
const char *nostr; /* Same for no. */
|
2002-07-19 01:08:59 +00:00
|
|
|
|
const char *allstr; /* And all, surprise! */
|
2001-04-12 13:24:40 +00:00
|
|
|
|
|
2004-06-26 15:24:16 +00:00
|
|
|
|
/* yesstr, nostr, and allstr are strings of any length. Each string
|
|
|
|
|
* consists of all characters accepted as a valid character for that
|
|
|
|
|
* value. The first value will be the one displayed in the
|
|
|
|
|
* shortcuts. Translators: if possible, specify both the shortcuts
|
|
|
|
|
* for your language and English. For example, in French: "OoYy"
|
|
|
|
|
* for "Oui". */
|
2001-02-16 01:49:31 +00:00
|
|
|
|
yesstr = _("Yy");
|
|
|
|
|
nostr = _("Nn");
|
|
|
|
|
allstr = _("Aa");
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
if (!ISSET(NO_HELP)) {
|
2003-09-16 01:16:49 +00:00
|
|
|
|
char shortstr[3]; /* Temp string for Y, N, A. */
|
2002-05-12 19:52:15 +00:00
|
|
|
|
|
2003-12-24 03:33:09 +00:00
|
|
|
|
if (COLS < 32)
|
|
|
|
|
width = COLS / 2;
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Write the bottom of the screen. */
|
2003-01-28 01:23:40 +00:00
|
|
|
|
blank_bottombars();
|
2001-02-16 01:49:31 +00:00
|
|
|
|
|
2002-05-12 19:52:15 +00:00
|
|
|
|
sprintf(shortstr, " %c", yesstr[0]);
|
2003-01-28 01:23:40 +00:00
|
|
|
|
wmove(bottomwin, 1, 0);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
onekey(shortstr, _("Yes"), width);
|
2001-02-16 01:49:31 +00:00
|
|
|
|
|
|
|
|
|
if (all) {
|
2003-12-24 03:33:09 +00:00
|
|
|
|
wmove(bottomwin, 1, width);
|
2002-05-12 19:52:15 +00:00
|
|
|
|
shortstr[1] = allstr[0];
|
2003-12-24 03:33:09 +00:00
|
|
|
|
onekey(shortstr, _("All"), width);
|
2001-02-16 01:49:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-01-28 01:23:40 +00:00
|
|
|
|
wmove(bottomwin, 2, 0);
|
2002-05-12 19:52:15 +00:00
|
|
|
|
shortstr[1] = nostr[0];
|
2003-12-24 03:33:09 +00:00
|
|
|
|
onekey(shortstr, _("No"), width);
|
2001-02-16 01:49:31 +00:00
|
|
|
|
|
2003-01-28 01:23:40 +00:00
|
|
|
|
wmove(bottomwin, 2, 16);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
onekey("^C", _("Cancel"), width);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2003-01-28 01:23:40 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wattron(bottomwin, A_REVERSE);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
|
|
|
|
blank_statusbar();
|
2003-12-24 03:33:09 +00:00
|
|
|
|
mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
2001-04-30 11:28:46 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
wrefresh(bottomwin);
|
|
|
|
|
|
2003-01-28 01:23:40 +00:00
|
|
|
|
do {
|
2003-12-24 03:33:09 +00:00
|
|
|
|
int kbinput;
|
2004-09-27 01:04:50 +00:00
|
|
|
|
bool meta_key, func_key;
|
2003-10-03 20:26:25 +00:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2003-12-24 03:33:09 +00:00
|
|
|
|
int mouse_x, mouse_y;
|
2001-04-12 13:24:40 +00:00
|
|
|
|
#endif
|
2001-02-16 01:49:31 +00:00
|
|
|
|
|
2004-09-27 01:04:50 +00:00
|
|
|
|
kbinput = get_kbinput(edit, &meta_key, &func_key);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
|
|
|
|
|
if (kbinput == NANO_CANCEL_KEY)
|
2003-01-28 01:23:40 +00:00
|
|
|
|
ok = -1;
|
2003-10-03 20:26:25 +00:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2004-12-04 17:41:52 +00:00
|
|
|
|
/* Look, ma! We get to duplicate lots of code from
|
|
|
|
|
* do_mouse()!! */
|
2003-12-24 03:33:09 +00:00
|
|
|
|
else if (kbinput == KEY_MOUSE) {
|
2004-08-25 15:39:10 +00:00
|
|
|
|
get_mouseinput(&mouse_x, &mouse_y, FALSE);
|
2003-12-24 03:33:09 +00:00
|
|
|
|
|
|
|
|
|
if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
|
2004-12-04 17:41:52 +00:00
|
|
|
|
wenclose(bottomwin, mouse_y, mouse_x) &&
|
|
|
|
|
mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
|
2003-12-24 03:33:09 +00:00
|
|
|
|
int x = mouse_x / width;
|
|
|
|
|
/* Did we click in the first column of shortcuts, or
|
|
|
|
|
* the second? */
|
|
|
|
|
int y = mouse_y - editwinrows - 3;
|
|
|
|
|
/* Did we click in the first row of shortcuts? */
|
|
|
|
|
|
|
|
|
|
assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
|
|
|
|
|
|
|
|
|
|
/* x = 0 means they clicked Yes or No.
|
|
|
|
|
* y = 0 means Yes or All. */
|
|
|
|
|
ok = -2 * x * y + x - y + 1;
|
|
|
|
|
|
|
|
|
|
if (ok == 2 && !all)
|
|
|
|
|
ok = -2;
|
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2003-01-28 01:23:40 +00:00
|
|
|
|
#endif
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Look for the kbinput in the yes, no and (optionally) all
|
2004-06-26 15:24:16 +00:00
|
|
|
|
* strings. */
|
2003-01-28 01:23:40 +00:00
|
|
|
|
else if (strchr(yesstr, kbinput) != NULL)
|
|
|
|
|
ok = 1;
|
|
|
|
|
else if (strchr(nostr, kbinput) != NULL)
|
|
|
|
|
ok = 0;
|
|
|
|
|
else if (all && strchr(allstr, kbinput) != NULL)
|
|
|
|
|
ok = 2;
|
|
|
|
|
} while (ok == -2);
|
|
|
|
|
|
|
|
|
|
return ok;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-02 14:31:03 +00:00
|
|
|
|
void total_refresh(void)
|
2002-09-06 20:35:28 +00:00
|
|
|
|
{
|
|
|
|
|
clearok(topwin, TRUE);
|
2004-05-18 01:20:36 +00:00
|
|
|
|
clearok(edit, TRUE);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
clearok(bottomwin, TRUE);
|
|
|
|
|
wnoutrefresh(topwin);
|
2004-05-18 01:20:36 +00:00
|
|
|
|
wnoutrefresh(edit);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
wnoutrefresh(bottomwin);
|
|
|
|
|
doupdate();
|
|
|
|
|
clearok(topwin, FALSE);
|
2004-05-18 01:20:36 +00:00
|
|
|
|
clearok(edit, FALSE);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
clearok(bottomwin, FALSE);
|
|
|
|
|
titlebar(NULL);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
edit_refresh();
|
|
|
|
|
/* FIXME: bottomwin needs to be refreshed too. */
|
2002-09-06 20:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void display_main_list(void)
|
|
|
|
|
{
|
|
|
|
|
bottombars(main_list);
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-12 03:10:30 +00:00
|
|
|
|
/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
|
|
|
|
|
* display the cursor position. Otherwise, we display it only if the
|
|
|
|
|
* character position changed and DISABLE_CURPOS is not set.
|
2003-01-28 01:16:47 +00:00
|
|
|
|
*
|
2004-05-18 01:20:36 +00:00
|
|
|
|
* If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
|
|
|
|
|
* old_i and old_totsize. That way, we leave the current statusbar
|
|
|
|
|
* alone, but next time we will display. */
|
2004-08-25 15:39:10 +00:00
|
|
|
|
void do_cursorpos(bool constant)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2003-01-28 01:16:47 +00:00
|
|
|
|
const filestruct *fileptr;
|
2004-10-30 01:03:15 +00:00
|
|
|
|
size_t i = 0;
|
|
|
|
|
static size_t old_i = 0;
|
2003-01-28 01:16:47 +00:00
|
|
|
|
static long old_totsize = -1;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2003-01-28 01:16:47 +00:00
|
|
|
|
assert(current != NULL && fileage != NULL && totlines != 0);
|
2001-11-29 03:43:08 +00:00
|
|
|
|
|
|
|
|
|
if (old_totsize == -1)
|
|
|
|
|
old_totsize = totsize;
|
|
|
|
|
|
2003-01-28 01:16:47 +00:00
|
|
|
|
for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
|
|
|
|
|
assert(fileptr != NULL);
|
2002-02-12 01:57:24 +00:00
|
|
|
|
i += strlen(fileptr->data) + 1;
|
2003-01-28 01:16:47 +00:00
|
|
|
|
}
|
2002-02-12 01:57:24 +00:00
|
|
|
|
i += current_x;
|
2002-01-25 21:59:02 +00:00
|
|
|
|
|
2004-07-28 20:46:25 +00:00
|
|
|
|
/* Check whether totsize is correct. Else there is a bug
|
|
|
|
|
* somewhere. */
|
|
|
|
|
assert(current != filebot || i == totsize);
|
|
|
|
|
|
2003-01-28 01:16:47 +00:00
|
|
|
|
if (constant && ISSET(DISABLE_CURPOS)) {
|
|
|
|
|
UNSET(DISABLE_CURPOS);
|
|
|
|
|
old_i = i;
|
|
|
|
|
old_totsize = totsize;
|
2004-07-02 14:31:03 +00:00
|
|
|
|
return;
|
2003-01-28 01:16:47 +00:00
|
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-05-23 21:23:23 +00:00
|
|
|
|
/* If constant is FALSE, display the position on the statusbar
|
2003-09-16 01:16:49 +00:00
|
|
|
|
* unconditionally; otherwise, only display the position when the
|
|
|
|
|
* character values have changed. */
|
2003-01-28 01:16:47 +00:00
|
|
|
|
if (!constant || old_i != i || old_totsize != totsize) {
|
2004-07-28 20:46:25 +00:00
|
|
|
|
size_t xpt = xplustabs() + 1;
|
|
|
|
|
size_t cur_len = strlenpt(current->data) + 1;
|
2003-01-28 01:16:47 +00:00
|
|
|
|
int linepct = 100 * current->lineno / totlines;
|
|
|
|
|
int colpct = 100 * xpt / cur_len;
|
|
|
|
|
int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
|
|
|
|
|
|
|
|
|
|
statusbar(
|
|
|
|
|
_("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
|
|
|
|
|
current->lineno, totlines, linepct,
|
2004-07-28 20:46:25 +00:00
|
|
|
|
(unsigned long)xpt, (unsigned long)cur_len, colpct,
|
2004-10-30 01:03:15 +00:00
|
|
|
|
(unsigned long)i, totsize, bytepct);
|
2003-01-28 01:16:47 +00:00
|
|
|
|
UNSET(DISABLE_CURPOS);
|
2001-11-29 03:43:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
old_i = i;
|
|
|
|
|
old_totsize = totsize;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-02 14:31:03 +00:00
|
|
|
|
void do_cursorpos_void(void)
|
2001-11-29 03:43:08 +00:00
|
|
|
|
{
|
2004-07-02 14:31:03 +00:00
|
|
|
|
do_cursorpos(FALSE);
|
2001-11-29 03:43:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-23 12:30:40 +00:00
|
|
|
|
#ifndef DISABLE_HELP
|
2003-02-10 03:10:03 +00:00
|
|
|
|
/* Calculate the next line of help_text, starting at ptr. */
|
2004-07-23 12:30:40 +00:00
|
|
|
|
int help_line_len(const char *ptr)
|
2003-02-10 03:10:03 +00:00
|
|
|
|
{
|
2004-07-23 12:30:40 +00:00
|
|
|
|
int j = 0;
|
2003-02-10 03:10:03 +00:00
|
|
|
|
|
|
|
|
|
while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
|
|
|
|
|
ptr++;
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
if (j == COLS - 5) {
|
|
|
|
|
/* Don't wrap at the first of two spaces following a period. */
|
|
|
|
|
if (*ptr == ' ' && *(ptr + 1) == ' ')
|
|
|
|
|
j++;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Don't print half a word if we've run out of space. */
|
2003-02-10 03:10:03 +00:00
|
|
|
|
while (*ptr != ' ' && j > 0) {
|
|
|
|
|
ptr--;
|
|
|
|
|
j--;
|
|
|
|
|
}
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Word longer than COLS - 5 chars just gets broken. */
|
2003-02-10 03:10:03 +00:00
|
|
|
|
if (j == 0)
|
|
|
|
|
j = COLS - 5;
|
|
|
|
|
}
|
|
|
|
|
assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
|
|
|
|
|
return j;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-26 15:24:16 +00:00
|
|
|
|
/* Our dynamic, shortcut-list-compliant help function. */
|
2004-07-02 14:31:03 +00:00
|
|
|
|
void do_help(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
|
{
|
2004-05-29 20:38:08 +00:00
|
|
|
|
int line = 0;
|
|
|
|
|
/* The line number in help_text of the first displayed help line.
|
|
|
|
|
* This variable is zero-based. */
|
2004-08-25 15:39:10 +00:00
|
|
|
|
bool no_more = FALSE;
|
2004-06-26 15:24:16 +00:00
|
|
|
|
/* no_more means the end of the help text is shown, so don't go
|
|
|
|
|
* down any more. */
|
2004-08-25 15:39:10 +00:00
|
|
|
|
int kbinput = ERR;
|
2004-09-27 01:04:50 +00:00
|
|
|
|
bool meta_key, func_key;
|
2004-05-29 20:38:08 +00:00
|
|
|
|
|
2004-08-25 15:39:10 +00:00
|
|
|
|
bool old_no_help = ISSET(NO_HELP);
|
2004-05-29 20:38:08 +00:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
|
|
|
|
const shortcut *oldshortcut = currshortcut;
|
|
|
|
|
/* We will set currshortcut to allow clicking on the help
|
2004-06-26 15:24:16 +00:00
|
|
|
|
* screen's shortcut list. */
|
2004-05-29 20:38:08 +00:00
|
|
|
|
#endif
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-06-01 20:38:00 +00:00
|
|
|
|
curs_set(0);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
blank_edit();
|
2001-10-22 03:15:31 +00:00
|
|
|
|
wattroff(bottomwin, A_REVERSE);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
blank_statusbar();
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Set help_text as the string to display. */
|
2001-10-22 03:15:31 +00:00
|
|
|
|
help_init();
|
2002-06-21 03:20:06 +00:00
|
|
|
|
assert(help_text != NULL);
|
2001-10-22 03:15:31 +00:00
|
|
|
|
|
2004-05-29 20:38:08 +00:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2004-06-26 15:24:16 +00:00
|
|
|
|
/* Set currshortcut to allow clicking on the help screen's shortcut
|
2004-05-29 20:38:08 +00:00
|
|
|
|
* list, AFTER help_init(). */
|
2001-04-12 03:01:53 +00:00
|
|
|
|
currshortcut = help_list;
|
2004-05-29 20:38:08 +00:00
|
|
|
|
#endif
|
2001-05-21 12:56:25 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
if (ISSET(NO_HELP)) {
|
2004-06-26 15:24:16 +00:00
|
|
|
|
/* Make sure that the help screen's shortcut list will actually
|
|
|
|
|
* be displayed. */
|
2000-06-21 03:00:43 +00:00
|
|
|
|
UNSET(NO_HELP);
|
2001-01-07 23:02:02 +00:00
|
|
|
|
window_init();
|
2004-05-29 20:38:08 +00:00
|
|
|
|
}
|
|
|
|
|
bottombars(help_list);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
do {
|
2004-05-29 20:38:08 +00:00
|
|
|
|
int i;
|
|
|
|
|
int old_line = line;
|
|
|
|
|
/* We redisplay the help only if it moved. */
|
2003-02-13 22:25:01 +00:00
|
|
|
|
const char *ptr = help_text;
|
2002-06-21 03:20:06 +00:00
|
|
|
|
|
2000-06-06 05:53:49 +00:00
|
|
|
|
switch (kbinput) {
|
2003-10-03 20:26:25 +00:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2004-05-29 20:38:08 +00:00
|
|
|
|
case KEY_MOUSE:
|
2004-08-25 15:39:10 +00:00
|
|
|
|
{
|
|
|
|
|
int mouse_x, mouse_y;
|
|
|
|
|
get_mouseinput(&mouse_x, &mouse_y, TRUE);
|
|
|
|
|
}
|
2004-05-29 20:38:08 +00:00
|
|
|
|
break;
|
2001-04-12 03:01:53 +00:00
|
|
|
|
#endif
|
2004-05-29 20:38:08 +00:00
|
|
|
|
case NANO_NEXTPAGE_KEY:
|
|
|
|
|
case NANO_NEXTPAGE_FKEY:
|
|
|
|
|
if (!no_more)
|
|
|
|
|
line += editwinrows - 2;
|
|
|
|
|
break;
|
|
|
|
|
case NANO_PREVPAGE_KEY:
|
|
|
|
|
case NANO_PREVPAGE_FKEY:
|
|
|
|
|
if (line > 0) {
|
|
|
|
|
line -= editwinrows - 2;
|
|
|
|
|
if (line < 0)
|
|
|
|
|
line = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NANO_PREVLINE_KEY:
|
|
|
|
|
if (line > 0)
|
|
|
|
|
line--;
|
|
|
|
|
break;
|
|
|
|
|
case NANO_NEXTLINE_KEY:
|
|
|
|
|
if (!no_more)
|
|
|
|
|
line++;
|
|
|
|
|
break;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 20:38:08 +00:00
|
|
|
|
if (line == old_line && kbinput != ERR)
|
|
|
|
|
goto skip_redisplay;
|
|
|
|
|
|
|
|
|
|
blank_edit();
|
|
|
|
|
|
|
|
|
|
assert(COLS > 5);
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Calculate where in the text we should be, based on the
|
|
|
|
|
* page. */
|
2004-05-29 20:38:08 +00:00
|
|
|
|
for (i = 0; i < line; i++) {
|
2004-07-23 12:30:40 +00:00
|
|
|
|
ptr += help_line_len(ptr);
|
2003-02-10 03:10:03 +00:00
|
|
|
|
if (*ptr == '\n')
|
2000-06-06 05:53:49 +00:00
|
|
|
|
ptr++;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-10 03:10:03 +00:00
|
|
|
|
for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
|
2004-07-23 12:30:40 +00:00
|
|
|
|
int j = help_line_len(ptr);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
|
|
|
|
mvwaddnstr(edit, i, 0, ptr, j);
|
2003-02-10 03:10:03 +00:00
|
|
|
|
ptr += j;
|
|
|
|
|
if (*ptr == '\n')
|
|
|
|
|
ptr++;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2004-05-29 20:38:08 +00:00
|
|
|
|
no_more = (*ptr == '\0');
|
2003-02-10 03:10:03 +00:00
|
|
|
|
|
2004-05-29 20:38:08 +00:00
|
|
|
|
skip_redisplay:
|
2004-09-27 01:04:50 +00:00
|
|
|
|
kbinput = get_kbinput(edit, &meta_key, &func_key);
|
2004-07-23 12:30:40 +00:00
|
|
|
|
} while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
|
|
|
|
|
kbinput != NANO_EXIT_FKEY);
|
2000-12-18 05:03:16 +00:00
|
|
|
|
|
2004-05-29 20:38:08 +00:00
|
|
|
|
#ifndef DISABLE_MOUSE
|
2001-10-22 03:15:31 +00:00
|
|
|
|
currshortcut = oldshortcut;
|
2004-05-29 20:38:08 +00:00
|
|
|
|
#endif
|
2001-10-22 03:15:31 +00:00
|
|
|
|
|
2004-06-01 19:49:38 +00:00
|
|
|
|
if (old_no_help) {
|
2001-01-07 23:02:02 +00:00
|
|
|
|
blank_bottombars();
|
2000-06-21 03:00:43 +00:00
|
|
|
|
wrefresh(bottomwin);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
SET(NO_HELP);
|
2001-01-07 23:02:02 +00:00
|
|
|
|
window_init();
|
2002-01-19 01:59:37 +00:00
|
|
|
|
} else
|
2002-02-15 19:17:02 +00:00
|
|
|
|
bottombars(currshortcut);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2004-06-01 20:38:00 +00:00
|
|
|
|
curs_set(1);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
edit_refresh();
|
2001-01-06 18:12:43 +00:00
|
|
|
|
|
2004-06-26 15:24:16 +00:00
|
|
|
|
/* The help_init() at the beginning allocated help_text. Since
|
|
|
|
|
* help_text has now been written to the screen, we don't need it
|
|
|
|
|
* anymore. */
|
2002-06-21 03:20:06 +00:00
|
|
|
|
free(help_text);
|
|
|
|
|
help_text = NULL;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
}
|
2004-04-30 04:49:02 +00:00
|
|
|
|
#endif /* !DISABLE_HELP */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Highlight the current word being replaced or spell checked. We
|
|
|
|
|
* expect word to have tabs and control characters expanded. */
|
2002-07-19 01:08:59 +00:00
|
|
|
|
void do_replace_highlight(int highlight_flag, const char *word)
|
2000-12-05 11:36:41 +00:00
|
|
|
|
{
|
2004-07-28 20:46:25 +00:00
|
|
|
|
size_t y = xplustabs();
|
2003-09-16 01:16:49 +00:00
|
|
|
|
size_t word_len = strlen(word);
|
2002-07-19 01:08:59 +00:00
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
y = get_page_start(y) + COLS - y;
|
|
|
|
|
/* Now y is the number of characters we can display on this
|
|
|
|
|
* line. */
|
2000-12-05 11:36:41 +00:00
|
|
|
|
|
|
|
|
|
reset_cursor();
|
2002-01-19 01:59:37 +00:00
|
|
|
|
|
2000-12-05 11:36:41 +00:00
|
|
|
|
if (highlight_flag)
|
|
|
|
|
wattron(edit, A_REVERSE);
|
|
|
|
|
|
2003-12-24 08:29:49 +00:00
|
|
|
|
#ifdef HAVE_REGEX_H
|
2003-12-24 08:17:54 +00:00
|
|
|
|
/* This is so we can show zero-length regexes. */
|
|
|
|
|
if (word_len == 0)
|
|
|
|
|
waddstr(edit, " ");
|
|
|
|
|
else
|
2003-12-24 08:29:49 +00:00
|
|
|
|
#endif
|
2003-12-24 08:17:54 +00:00
|
|
|
|
waddnstr(edit, word, y - 1);
|
2003-09-16 01:16:49 +00:00
|
|
|
|
|
|
|
|
|
if (word_len > y)
|
|
|
|
|
waddch(edit, '$');
|
|
|
|
|
else if (word_len == y)
|
|
|
|
|
waddch(edit, word[word_len - 1]);
|
2000-12-05 11:36:41 +00:00
|
|
|
|
|
|
|
|
|
if (highlight_flag)
|
|
|
|
|
wattroff(edit, A_REVERSE);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-06 20:35:28 +00:00
|
|
|
|
#ifdef DEBUG
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Dump the passed-in file structure to stderr. */
|
|
|
|
|
void dump_buffer(const filestruct *inptr)
|
|
|
|
|
{
|
2002-09-06 20:35:28 +00:00
|
|
|
|
if (inptr == fileage)
|
2003-08-05 19:31:12 +00:00
|
|
|
|
fprintf(stderr, "Dumping file buffer to stderr...\n");
|
2002-09-06 20:35:28 +00:00
|
|
|
|
else if (inptr == cutbuffer)
|
2003-08-05 19:31:12 +00:00
|
|
|
|
fprintf(stderr, "Dumping cutbuffer to stderr...\n");
|
2002-09-06 20:35:28 +00:00
|
|
|
|
else
|
2003-08-05 19:31:12 +00:00
|
|
|
|
fprintf(stderr, "Dumping a buffer to stderr...\n");
|
2002-09-06 20:35:28 +00:00
|
|
|
|
|
|
|
|
|
while (inptr != NULL) {
|
|
|
|
|
fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
|
|
|
|
|
inptr = inptr->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
|
/* Dump the file structure to stderr in reverse. */
|
2003-08-31 16:44:10 +00:00
|
|
|
|
void dump_buffer_reverse(void)
|
|
|
|
|
{
|
2002-09-06 20:35:28 +00:00
|
|
|
|
const filestruct *fileptr = filebot;
|
|
|
|
|
|
|
|
|
|
while (fileptr != NULL) {
|
2004-07-17 20:01:45 +00:00
|
|
|
|
fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
|
2002-09-06 20:35:28 +00:00
|
|
|
|
fileptr = fileptr->prev;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
2000-11-24 20:45:14 +00:00
|
|
|
|
#ifdef NANO_EXTRA
|
2002-11-04 16:05:42 +00:00
|
|
|
|
#define CREDIT_LEN 53
|
2002-07-21 15:44:13 +00:00
|
|
|
|
#define XLCREDIT_LEN 8
|
|
|
|
|
|
2004-01-19 18:15:03 +00:00
|
|
|
|
/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
|
2000-11-24 20:45:14 +00:00
|
|
|
|
void do_credits(void)
|
|
|
|
|
{
|
2004-05-18 01:20:36 +00:00
|
|
|
|
int crpos = 0, xlpos = 0;
|
|
|
|
|
const char *credits[CREDIT_LEN] = {
|
|
|
|
|
NULL, /* "The nano text editor" */
|
|
|
|
|
NULL, /* "version" */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
VERSION,
|
|
|
|
|
"",
|
2004-05-18 01:20:36 +00:00
|
|
|
|
NULL, /* "Brought to you by:" */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
"Chris Allegretta",
|
|
|
|
|
"Jordi Mallach",
|
|
|
|
|
"Adam Rogoyski",
|
|
|
|
|
"Rob Siemborski",
|
|
|
|
|
"Rocco Corsi",
|
2002-02-15 19:17:02 +00:00
|
|
|
|
"David Lawrence Ramsey",
|
2002-11-04 16:05:42 +00:00
|
|
|
|
"David Benbennick",
|
2002-01-19 01:59:37 +00:00
|
|
|
|
"Ken Tyler",
|
|
|
|
|
"Sven Guckes",
|
|
|
|
|
"Florian K<>nig",
|
|
|
|
|
"Pauli Virtanen",
|
|
|
|
|
"Daniele Medri",
|
|
|
|
|
"Clement Laforet",
|
|
|
|
|
"Tedi Heriyanto",
|
|
|
|
|
"Bill Soudan",
|
|
|
|
|
"Christian Weisgerber",
|
|
|
|
|
"Erik Andersen",
|
|
|
|
|
"Big Gaute",
|
|
|
|
|
"Joshua Jensen",
|
|
|
|
|
"Ryan Krebs",
|
|
|
|
|
"Albert Chin",
|
|
|
|
|
"",
|
2004-05-18 01:20:36 +00:00
|
|
|
|
NULL, /* "Special thanks to:" */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
"Plattsburgh State University",
|
|
|
|
|
"Benet Laboratories",
|
|
|
|
|
"Amy Allegretta",
|
|
|
|
|
"Linda Young",
|
|
|
|
|
"Jeremy Robichaud",
|
|
|
|
|
"Richard Kolb II",
|
2004-05-18 01:20:36 +00:00
|
|
|
|
NULL, /* "The Free Software Foundation" */
|
2002-01-19 01:59:37 +00:00
|
|
|
|
"Linus Torvalds",
|
2004-05-18 01:20:36 +00:00
|
|
|
|
NULL, /* "For ncurses:" */
|
2002-03-16 01:03:41 +00:00
|
|
|
|
"Thomas Dickey",
|
|
|
|
|
"Pavel Curtis",
|
|
|
|
|
"Zeyd Ben-Halim",
|
|
|
|
|
"Eric S. Raymond",
|
2004-05-18 01:20:36 +00:00
|
|
|
|
NULL, /* "and anyone else we forgot..." */
|
|
|
|
|
NULL, /* "Thank you for using nano!" */
|
|
|
|
|
"",
|
|
|
|
|
"",
|
|
|
|
|
"",
|
|
|
|
|
"",
|
2004-01-09 23:06:54 +00:00
|
|
|
|
"(c) 1999-2004 Chris Allegretta",
|
2004-05-18 01:20:36 +00:00
|
|
|
|
"",
|
|
|
|
|
"",
|
|
|
|
|
"",
|
|
|
|
|
"",
|
2002-11-04 16:05:42 +00:00
|
|
|
|
"http://www.nano-editor.org/"
|
2000-11-24 20:45:14 +00:00
|
|
|
|
};
|
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
|
const char *xlcredits[XLCREDIT_LEN] = {
|
2004-07-12 03:10:30 +00:00
|
|
|
|
N_("The nano text editor"),
|
|
|
|
|
N_("version"),
|
|
|
|
|
N_("Brought to you by:"),
|
|
|
|
|
N_("Special thanks to:"),
|
|
|
|
|
N_("The Free Software Foundation"),
|
|
|
|
|
N_("For ncurses:"),
|
|
|
|
|
N_("and anyone else we forgot..."),
|
|
|
|
|
N_("Thank you for using nano!")
|
2004-05-18 01:20:36 +00:00
|
|
|
|
};
|
2002-07-21 15:44:13 +00:00
|
|
|
|
|
2000-11-24 20:45:14 +00:00
|
|
|
|
curs_set(0);
|
|
|
|
|
nodelay(edit, TRUE);
|
2004-05-18 01:20:36 +00:00
|
|
|
|
scrollok(edit, TRUE);
|
|
|
|
|
blank_titlebar();
|
2000-11-25 18:21:37 +00:00
|
|
|
|
blank_edit();
|
2004-05-18 01:20:36 +00:00
|
|
|
|
blank_statusbar();
|
|
|
|
|
blank_bottombars();
|
|
|
|
|
wrefresh(topwin);
|
2000-11-25 18:21:37 +00:00
|
|
|
|
wrefresh(edit);
|
2000-11-24 20:45:14 +00:00
|
|
|
|
wrefresh(bottomwin);
|
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
|
for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
|
|
|
|
|
if (wgetch(edit) != ERR)
|
|
|
|
|
break;
|
|
|
|
|
if (crpos < CREDIT_LEN) {
|
|
|
|
|
const char *what = credits[crpos];
|
|
|
|
|
size_t start_x;
|
|
|
|
|
|
|
|
|
|
if (what == NULL) {
|
|
|
|
|
assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
|
2004-05-18 15:23:31 +00:00
|
|
|
|
what = _(xlcredits[xlpos]);
|
2004-05-18 01:20:36 +00:00
|
|
|
|
xlpos++;
|
2000-11-25 18:21:37 +00:00
|
|
|
|
}
|
2004-05-18 01:20:36 +00:00
|
|
|
|
start_x = COLS / 2 - strlen(what) / 2 - 1;
|
2004-12-05 22:24:39 +00:00
|
|
|
|
mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
|
|
|
|
|
what);
|
2000-11-24 20:45:14 +00:00
|
|
|
|
}
|
2004-05-18 01:20:36 +00:00
|
|
|
|
napms(700);
|
|
|
|
|
scroll(edit);
|
|
|
|
|
wrefresh(edit);
|
|
|
|
|
if (wgetch(edit) != ERR)
|
2000-11-24 20:45:14 +00:00
|
|
|
|
break;
|
2004-05-18 01:20:36 +00:00
|
|
|
|
napms(700);
|
|
|
|
|
scroll(edit);
|
|
|
|
|
wrefresh(edit);
|
2000-11-24 20:45:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
|
scrollok(edit, FALSE);
|
2000-11-24 20:45:14 +00:00
|
|
|
|
nodelay(edit, FALSE);
|
|
|
|
|
curs_set(1);
|
|
|
|
|
display_main_list();
|
|
|
|
|
total_refresh();
|
2002-01-19 01:59:37 +00:00
|
|
|
|
}
|
2000-11-24 20:45:14 +00:00
|
|
|
|
#endif
|