2000-06-06 05:53:49 +00:00
|
|
|
/**************************************************************************
|
2016-08-29 15:10:49 +00:00
|
|
|
* winio.c -- This file is part of GNU nano. *
|
2000-06-06 05:53:49 +00:00
|
|
|
* *
|
2009-12-02 03:36:22 +00:00
|
|
|
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
2014-04-30 20:18:26 +00:00
|
|
|
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
2016-08-29 13:14:18 +00:00
|
|
|
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
|
|
|
* *
|
2016-08-29 15:10:49 +00:00
|
|
|
* GNU nano is free software: you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published *
|
|
|
|
* by the Free Software Foundation, either version 3 of the License, *
|
|
|
|
* or (at your option) any later version. *
|
2000-06-06 05:53:49 +00:00
|
|
|
* *
|
2016-08-29 15:10:49 +00:00
|
|
|
* GNU nano is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
|
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
|
|
* See the GNU General Public License for more details. *
|
2000-06-06 05:53:49 +00:00
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
2016-08-29 15:10:49 +00:00
|
|
|
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
2000-06-06 05:53:49 +00:00
|
|
|
* *
|
|
|
|
**************************************************************************/
|
|
|
|
|
2005-12-08 02:47:10 +00:00
|
|
|
#include "proto.h"
|
2016-05-20 10:59:57 +00:00
|
|
|
#include "revision.h"
|
2002-09-13 18:14:04 +00:00
|
|
|
|
2016-09-08 19:00:51 +00:00
|
|
|
#ifdef __linux__
|
2016-07-29 07:15:07 +00:00
|
|
|
#include <sys/ioctl.h>
|
2016-08-11 10:37:11 +00:00
|
|
|
#endif
|
2016-07-29 07:15:07 +00:00
|
|
|
|
2005-11-01 18:35:47 +00:00
|
|
|
#include <stdio.h>
|
2000-06-06 05:53:49 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
2000-11-24 20:45:14 +00:00
|
|
|
#include <unistd.h>
|
2002-06-13 00:40:19 +00:00
|
|
|
#include <ctype.h>
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2016-05-20 10:59:57 +00:00
|
|
|
#ifdef REVISION
|
|
|
|
#define BRANDING REVISION
|
|
|
|
#else
|
|
|
|
#define BRANDING PACKAGE_STRING
|
|
|
|
#endif
|
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
static int *key_buffer = NULL;
|
2007-01-01 05:15:32 +00:00
|
|
|
/* The keystroke buffer, containing all the keystrokes we
|
|
|
|
* haven't handled yet at a given point. */
|
2004-12-04 17:41:52 +00:00
|
|
|
static size_t key_buffer_len = 0;
|
2006-05-26 03:22:44 +00:00
|
|
|
/* The length of the keystroke buffer. */
|
2016-07-11 12:21:38 +00:00
|
|
|
static bool solitary = FALSE;
|
|
|
|
/* Whether an Esc arrived by itself -- not as leader of a sequence. */
|
2005-06-25 20:56:36 +00:00
|
|
|
static int statusblank = 0;
|
2016-05-15 09:17:55 +00:00
|
|
|
/* The number of keystrokes left before we blank the statusbar. */
|
2016-05-04 10:18:21 +00:00
|
|
|
static bool suppress_cursorpos = FALSE;
|
2016-05-23 19:34:02 +00:00
|
|
|
/* Should we skip constant position display for one keystroke? */
|
2016-07-12 19:05:09 +00:00
|
|
|
#ifdef USING_OLD_NCURSES
|
2015-09-05 09:14:24 +00:00
|
|
|
static bool seen_wide = FALSE;
|
|
|
|
/* Whether we've seen a multicolumn character in the current line. */
|
2016-07-12 19:05:09 +00:00
|
|
|
#endif
|
2000-06-06 23:04:06 +00:00
|
|
|
|
2004-05-01 01:21:38 +00:00
|
|
|
/* Control character compatibility:
|
|
|
|
*
|
2016-07-22 13:57:20 +00:00
|
|
|
* - Ctrl-H is Backspace under ASCII, ANSI, VT100, and VT220.
|
|
|
|
* - Ctrl-I is Tab under ASCII, ANSI, VT100, VT220, and VT320.
|
|
|
|
* - Ctrl-M is Enter under ASCII, ANSI, VT100, VT220, and VT320.
|
|
|
|
* - Ctrl-Q is XON under ASCII, ANSI, VT100, VT220, and VT320.
|
|
|
|
* - Ctrl-S is XOFF under ASCII, ANSI, VT100, VT220, and VT320.
|
2016-08-01 10:56:05 +00:00
|
|
|
* - Ctrl-8 (Ctrl-?) is Delete under ASCII, ANSI, VT100, and VT220,
|
|
|
|
* but is Backspace under VT320.
|
2004-05-01 01:21:38 +00:00
|
|
|
*
|
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
|
2007-04-04 20:36:56 +00:00
|
|
|
* console, the FreeBSD console, the Mach console, xterm, rxvt, Eterm,
|
2016-07-22 13:57:20 +00:00
|
|
|
* and Terminal, and some for iTerm2. Among these, there are several
|
|
|
|
* conflicts and omissions, outlined as follows:
|
2004-05-01 01:21:38 +00:00
|
|
|
*
|
|
|
|
* - 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
|
2006-07-31 23:29:22 +00:00
|
|
|
* omitted. (Same as above.) */
|
2004-04-23 18:02:37 +00:00
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
/* Read in a sequence of keystrokes from win and save them in the
|
2006-05-26 03:22:44 +00:00
|
|
|
* keystroke buffer. This should only be called when the keystroke
|
|
|
|
* buffer is empty. */
|
2005-07-13 20:18:46 +00:00
|
|
|
void get_key_buffer(WINDOW *win)
|
2004-08-25 16:37:06 +00:00
|
|
|
{
|
2006-03-19 19:26:52 +00:00
|
|
|
int input;
|
2016-05-17 20:12:28 +00:00
|
|
|
size_t errcount = 0;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
|
|
|
/* If the keystroke buffer isn't empty, get out. */
|
|
|
|
if (key_buffer != NULL)
|
|
|
|
return;
|
|
|
|
|
2005-07-26 14:42:57 +00:00
|
|
|
/* Just before reading in the first character, display any pending
|
|
|
|
* screen updates. */
|
|
|
|
doupdate();
|
|
|
|
|
2014-04-15 11:25:29 +00:00
|
|
|
/* Read in the first character using whatever mode we're in. */
|
2016-05-17 20:12:28 +00:00
|
|
|
input = wgetch(win);
|
|
|
|
|
2016-05-18 09:14:17 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-12-14 19:37:03 +00:00
|
|
|
if (the_window_resized) {
|
2016-06-29 13:53:08 +00:00
|
|
|
ungetch(input);
|
2016-12-14 19:37:03 +00:00
|
|
|
regenerate_screen();
|
2016-05-18 09:14:17 +00:00
|
|
|
input = KEY_WINCH;
|
2016-06-29 13:53:08 +00:00
|
|
|
}
|
2016-05-18 09:14:17 +00:00
|
|
|
#endif
|
|
|
|
|
2016-05-17 20:12:28 +00:00
|
|
|
if (input == ERR && nodelay_mode)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (input == ERR) {
|
|
|
|
/* If we've failed to get a character MAX_BUF_SIZE times in a row,
|
|
|
|
* assume our input source is gone and die gracefully. We could
|
|
|
|
* check if errno is set to EIO ("Input/output error") and die in
|
|
|
|
* that case, but it's not always set properly. Argh. */
|
|
|
|
if (++errcount == MAX_BUF_SIZE)
|
|
|
|
handle_hupterm(0);
|
|
|
|
|
2015-05-28 13:02:29 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-12-14 19:37:03 +00:00
|
|
|
if (the_window_resized) {
|
|
|
|
regenerate_screen();
|
2016-05-17 20:12:28 +00:00
|
|
|
input = KEY_WINCH;
|
|
|
|
break;
|
2009-01-24 22:40:41 +00:00
|
|
|
}
|
2016-05-17 20:12:28 +00:00
|
|
|
#endif
|
|
|
|
input = wgetch(win);
|
2015-05-28 13:02:29 +00:00
|
|
|
}
|
2004-02-16 20:32:40 +00:00
|
|
|
|
2007-05-25 16:54:06 +00:00
|
|
|
/* Increment the length of the keystroke buffer, and save the value
|
|
|
|
* of the keystroke at the end of it. */
|
2004-12-04 17:41:52 +00:00
|
|
|
key_buffer_len++;
|
2005-01-12 03:25:57 +00:00
|
|
|
key_buffer = (int *)nmalloc(sizeof(int));
|
|
|
|
key_buffer[0] = input;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
2015-05-28 13:02:29 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
/* If we got SIGWINCH, get out immediately since the win argument is
|
|
|
|
* no longer valid. */
|
|
|
|
if (input == KEY_WINCH)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
/* Read in the remaining characters using non-blocking input. */
|
|
|
|
nodelay(win, TRUE);
|
|
|
|
|
|
|
|
while (TRUE) {
|
2005-01-12 03:25:57 +00:00
|
|
|
input = wgetch(win);
|
2004-12-12 19:04:56 +00:00
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
/* If there aren't any more characters, stop reading. */
|
2005-01-12 03:25:57 +00:00
|
|
|
if (input == ERR)
|
2004-12-04 17:41:52 +00:00
|
|
|
break;
|
|
|
|
|
2007-05-25 16:54:06 +00:00
|
|
|
/* Otherwise, increment the length of the keystroke buffer, and
|
|
|
|
* save the value of the keystroke at the end of it. */
|
2004-12-04 17:41:52 +00:00
|
|
|
key_buffer_len++;
|
2005-01-12 03:25:57 +00:00
|
|
|
key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
|
|
|
|
sizeof(int));
|
|
|
|
key_buffer[key_buffer_len - 1] = input;
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
|
|
|
|
2016-05-05 19:44:45 +00:00
|
|
|
/* Restore waiting mode if it was on. */
|
|
|
|
if (!nodelay_mode)
|
|
|
|
nodelay(win, FALSE);
|
2005-03-16 14:39:42 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2015-06-11 19:01:28 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
2015-12-22 20:24:50 +00:00
|
|
|
fprintf(stderr, "\nget_key_buffer(): the sequence of hex codes:");
|
2015-06-11 19:01:28 +00:00
|
|
|
for (i = 0; i < key_buffer_len; i++)
|
|
|
|
fprintf(stderr, " %3x", key_buffer[i]);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
2005-03-16 14:39:42 +00:00
|
|
|
#endif
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
2003-08-17 02:48:43 +00:00
|
|
|
|
2006-05-26 03:22:44 +00:00
|
|
|
/* Return the length of the keystroke buffer. */
|
2005-07-13 20:18:46 +00:00
|
|
|
size_t get_key_buffer_len(void)
|
2004-12-04 17:41:52 +00:00
|
|
|
{
|
|
|
|
return key_buffer_len;
|
|
|
|
}
|
|
|
|
|
2006-05-26 03:22:44 +00:00
|
|
|
/* Add the keystrokes in input to the keystroke buffer. */
|
2005-01-12 03:25:57 +00:00
|
|
|
void unget_input(int *input, size_t input_len)
|
2004-12-04 17:41:52 +00:00
|
|
|
{
|
|
|
|
/* If input is empty, get out. */
|
2005-01-12 03:25:57 +00:00
|
|
|
if (input_len == 0)
|
2004-12-04 17:41:52 +00:00
|
|
|
return;
|
|
|
|
|
2006-05-26 03:22:44 +00:00
|
|
|
/* If adding input would put the keystroke buffer beyond maximum
|
|
|
|
* capacity, only add enough of input to put it at maximum
|
2004-12-04 17:41:52 +00:00
|
|
|
* capacity. */
|
2005-01-12 03:25:57 +00:00
|
|
|
if (key_buffer_len + input_len < key_buffer_len)
|
|
|
|
input_len = (size_t)-1 - key_buffer_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2006-05-26 03:22:44 +00:00
|
|
|
/* Add the length of input to the length of the keystroke buffer,
|
|
|
|
* and reallocate the keystroke buffer so that it has enough room
|
|
|
|
* for input. */
|
2005-01-12 03:25:57 +00:00
|
|
|
key_buffer_len += input_len;
|
|
|
|
key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
|
|
|
|
sizeof(int));
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2006-05-26 03:22:44 +00:00
|
|
|
/* If the keystroke buffer wasn't empty before, move its beginning
|
|
|
|
* forward far enough so that we can add input to its beginning. */
|
2005-01-12 03:25:57 +00:00
|
|
|
if (key_buffer_len > input_len)
|
|
|
|
memmove(key_buffer + input_len, key_buffer,
|
|
|
|
(key_buffer_len - input_len) * sizeof(int));
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2006-05-26 03:22:44 +00:00
|
|
|
/* Copy input to the beginning of the keystroke buffer. */
|
2005-01-12 03:25:57 +00:00
|
|
|
memcpy(key_buffer, input, input_len * sizeof(int));
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
|
|
|
|
2016-07-23 12:01:38 +00:00
|
|
|
/* Put the character given in kbinput back into the input stream. If it
|
|
|
|
* is a Meta key, also insert an Escape character in front of it. */
|
|
|
|
void unget_kbinput(int kbinput, bool metakey)
|
2004-12-04 17:41:52 +00:00
|
|
|
{
|
2005-01-12 03:25:57 +00:00
|
|
|
unget_input(&kbinput, 1);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2014-06-30 18:04:33 +00:00
|
|
|
if (metakey) {
|
2016-08-01 10:56:05 +00:00
|
|
|
kbinput = ESC_CODE;
|
2005-01-12 03:25:57 +00:00
|
|
|
unget_input(&kbinput, 1);
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Try to read input_len codes from the keystroke buffer. If the
|
2006-05-26 03:22:44 +00:00
|
|
|
* keystroke buffer is empty and win isn't NULL, try to read in more
|
2016-08-01 12:05:42 +00:00
|
|
|
* codes from win and add them to the keystroke buffer before doing
|
2016-05-02 19:58:43 +00:00
|
|
|
* anything else. If the keystroke buffer is (still) empty, return NULL. */
|
2005-01-12 03:25:57 +00:00
|
|
|
int *get_input(WINDOW *win, size_t input_len)
|
2004-12-04 17:41:52 +00:00
|
|
|
{
|
2005-01-12 03:25:57 +00:00
|
|
|
int *input;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-05-02 19:58:43 +00:00
|
|
|
if (key_buffer_len == 0 && win != NULL)
|
|
|
|
get_key_buffer(win);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-05-02 19:58:43 +00:00
|
|
|
if (key_buffer_len == 0)
|
|
|
|
return NULL;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Limit the request to the number of available codes in the buffer. */
|
2004-12-04 17:41:52 +00:00
|
|
|
if (input_len > key_buffer_len)
|
|
|
|
input_len = key_buffer_len;
|
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Copy input_len codes from the head of the keystroke buffer. */
|
2005-01-12 03:25:57 +00:00
|
|
|
input = (int *)nmalloc(input_len * sizeof(int));
|
|
|
|
memcpy(input, key_buffer, input_len * sizeof(int));
|
2016-08-01 12:05:42 +00:00
|
|
|
key_buffer_len -= input_len;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* If the keystroke buffer is now empty, mark it as such. */
|
2004-12-04 17:41:52 +00:00
|
|
|
if (key_buffer_len == 0) {
|
|
|
|
free(key_buffer);
|
|
|
|
key_buffer = NULL;
|
|
|
|
} else {
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Trim from the buffer the codes that were copied. */
|
2004-12-04 17:41:52 +00:00
|
|
|
memmove(key_buffer, key_buffer + input_len, key_buffer_len *
|
2005-01-12 03:25:57 +00:00
|
|
|
sizeof(int));
|
|
|
|
key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
|
|
|
|
sizeof(int));
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return input;
|
2003-08-17 02:48:43 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 20:45:41 +00:00
|
|
|
/* Read in a single keystroke, ignoring any that are invalid. */
|
2014-06-30 18:04:33 +00:00
|
|
|
int get_kbinput(WINDOW *win)
|
2004-12-04 17:41:52 +00:00
|
|
|
{
|
2016-08-30 07:40:51 +00:00
|
|
|
int kbinput = ERR;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-06-24 20:45:41 +00:00
|
|
|
/* Extract one keystroke from the input stream. */
|
2016-08-30 07:40:51 +00:00
|
|
|
while (kbinput == ERR)
|
|
|
|
kbinput = parse_kbinput(win);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-07-13 15:38:28 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "after parsing: kbinput = %d, meta_key = %s\n",
|
|
|
|
kbinput, meta_key ? "TRUE" : "FALSE");
|
|
|
|
#endif
|
|
|
|
|
2016-06-24 20:45:41 +00:00
|
|
|
/* If we read from the edit window, blank the statusbar if needed. */
|
2006-05-22 01:29:30 +00:00
|
|
|
if (win == edit)
|
2006-05-21 21:23:21 +00:00
|
|
|
check_statusblank();
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
return kbinput;
|
|
|
|
}
|
|
|
|
|
2016-06-24 20:45:41 +00:00
|
|
|
/* Extract a single keystroke from the input stream. Translate escape
|
|
|
|
* sequences and extended keypad codes into their corresponding values.
|
2016-07-13 14:22:56 +00:00
|
|
|
* Set meta_key to TRUE when appropriate. Supported extended keypad values
|
2016-06-24 20:45:41 +00:00
|
|
|
* are: [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
|
|
|
|
* the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
|
|
|
|
* the function keys (F1-F16), and the numeric keypad with NumLock off. */
|
2014-06-30 18:04:33 +00:00
|
|
|
int parse_kbinput(WINDOW *win)
|
2003-08-17 02:48:43 +00:00
|
|
|
{
|
2005-01-03 19:56:56 +00:00
|
|
|
static int escapes = 0, byte_digits = 0;
|
2016-04-02 10:13:24 +00:00
|
|
|
static bool double_esc = FALSE;
|
2016-07-13 10:09:49 +00:00
|
|
|
int *kbinput, keycode, retval = ERR;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
2014-06-30 18:04:33 +00:00
|
|
|
meta_key = FALSE;
|
2016-04-24 09:28:28 +00:00
|
|
|
shift_held = FALSE;
|
2003-08-17 02:48:43 +00:00
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
/* Read in a character. */
|
2016-04-16 09:57:05 +00:00
|
|
|
kbinput = get_input(win, 1);
|
|
|
|
|
|
|
|
if (kbinput == NULL && nodelay_mode)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (kbinput == NULL)
|
2009-01-24 22:40:41 +00:00
|
|
|
kbinput = get_input(win, 1);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-07-13 10:09:49 +00:00
|
|
|
keycode = *kbinput;
|
|
|
|
free(kbinput);
|
|
|
|
|
2016-07-13 15:38:28 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "before parsing: keycode = %d, escapes = %d, byte_digits = %d\n",
|
|
|
|
keycode, escapes, byte_digits);
|
|
|
|
#endif
|
|
|
|
|
2016-07-13 16:08:44 +00:00
|
|
|
if (keycode == ERR)
|
|
|
|
return ERR;
|
|
|
|
|
2016-08-01 10:56:05 +00:00
|
|
|
if (keycode == ESC_CODE) {
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Increment the escape counter, but trim an overabundance. */
|
|
|
|
escapes++;
|
|
|
|
if (escapes > 3)
|
|
|
|
escapes = 1;
|
|
|
|
/* Take note when an Esc arrived by itself. */
|
|
|
|
solitary = (escapes == 1 && key_buffer_len == 0);
|
|
|
|
return ERR;
|
2016-07-13 16:08:44 +00:00
|
|
|
}
|
|
|
|
|
2016-07-13 16:26:45 +00:00
|
|
|
switch (escapes) {
|
|
|
|
case 0:
|
|
|
|
/* One non-escape: normal input mode. */
|
|
|
|
retval = keycode;
|
|
|
|
break;
|
|
|
|
case 1:
|
2016-08-06 17:51:52 +00:00
|
|
|
if (keycode >= 0x80)
|
|
|
|
retval = keycode;
|
|
|
|
else if ((keycode != 'O' && keycode != 'o' && keycode != '[') ||
|
2016-08-01 10:56:05 +00:00
|
|
|
key_buffer_len == 0 || *key_buffer == ESC_CODE) {
|
2016-07-13 16:26:45 +00:00
|
|
|
/* One escape followed by a single non-escape:
|
|
|
|
* meta key sequence mode. */
|
|
|
|
if (!solitary || (keycode >= 0x20 && keycode < 0x7F))
|
|
|
|
meta_key = TRUE;
|
|
|
|
retval = tolower(keycode);
|
|
|
|
} else
|
|
|
|
/* One escape followed by a non-escape, and there
|
|
|
|
* are more codes waiting: escape sequence mode. */
|
|
|
|
retval = parse_escape_sequence(win, keycode);
|
2016-08-01 12:05:42 +00:00
|
|
|
escapes = 0;
|
2016-07-13 16:26:45 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (double_esc) {
|
2016-11-18 13:14:36 +00:00
|
|
|
/* An "ESC ESC [ X" sequence from Option+arrow, or
|
|
|
|
* an "ESC ESC [ x" sequence from Shift+Alt+arrow. */
|
2016-07-13 16:26:45 +00:00
|
|
|
switch (keycode) {
|
|
|
|
case 'A':
|
|
|
|
retval = KEY_HOME;
|
|
|
|
break;
|
|
|
|
case 'B':
|
|
|
|
retval = KEY_END;
|
|
|
|
break;
|
|
|
|
case 'C':
|
2016-11-23 19:45:45 +00:00
|
|
|
retval = CONTROL_RIGHT;
|
2016-07-13 16:26:45 +00:00
|
|
|
break;
|
|
|
|
case 'D':
|
2016-11-23 19:45:45 +00:00
|
|
|
retval = CONTROL_LEFT;
|
2016-07-13 16:26:45 +00:00
|
|
|
break;
|
2016-11-30 10:05:07 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-11-18 13:14:36 +00:00
|
|
|
case 'a':
|
|
|
|
retval = shiftaltup;
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
retval = shiftaltdown;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
retval = shiftaltright;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
retval = shiftaltleft;
|
|
|
|
break;
|
2016-11-30 10:05:07 +00:00
|
|
|
#endif
|
2016-07-13 16:26:45 +00:00
|
|
|
}
|
|
|
|
double_esc = FALSE;
|
|
|
|
escapes = 0;
|
2016-07-15 19:53:46 +00:00
|
|
|
} else if (key_buffer_len == 0) {
|
2016-07-13 16:26:45 +00:00
|
|
|
if (('0' <= keycode && keycode <= '2' &&
|
|
|
|
byte_digits == 0) || ('0' <= keycode &&
|
|
|
|
keycode <= '9' && byte_digits > 0)) {
|
|
|
|
/* Two escapes followed by one or more decimal
|
|
|
|
* digits, and there aren't any other codes
|
|
|
|
* waiting: byte sequence mode. If the range
|
|
|
|
* of the byte sequence is limited to 2XX (the
|
|
|
|
* first digit is between '0' and '2' and the
|
|
|
|
* others between '0' and '9', interpret it. */
|
|
|
|
int byte;
|
|
|
|
|
|
|
|
byte_digits++;
|
|
|
|
byte = get_byte_kbinput(keycode);
|
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* If the decimal byte value is complete, convert it and
|
|
|
|
* put the obtained byte(s) back into the input buffer. */
|
2016-07-13 16:26:45 +00:00
|
|
|
if (byte != ERR) {
|
|
|
|
char *byte_mb;
|
|
|
|
int byte_mb_len, *seq, i;
|
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Convert the decimal code to one or two bytes. */
|
|
|
|
byte_mb = make_mbchar((long)byte, &byte_mb_len);
|
2016-07-13 16:26:45 +00:00
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
seq = (int *)nmalloc(byte_mb_len * sizeof(int));
|
2016-07-13 16:26:45 +00:00
|
|
|
|
|
|
|
for (i = 0; i < byte_mb_len; i++)
|
|
|
|
seq[i] = (unsigned char)byte_mb[i];
|
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Insert the byte(s) into the input buffer. */
|
2016-07-13 16:26:45 +00:00
|
|
|
unget_input(seq, byte_mb_len);
|
|
|
|
|
|
|
|
free(byte_mb);
|
|
|
|
free(seq);
|
2016-08-01 12:05:42 +00:00
|
|
|
|
|
|
|
byte_digits = 0;
|
|
|
|
escapes = 0;
|
2006-05-30 20:51:15 +00:00
|
|
|
}
|
2016-07-13 16:26:45 +00:00
|
|
|
} else {
|
|
|
|
if (byte_digits == 0)
|
|
|
|
/* Two escapes followed by a non-decimal
|
|
|
|
* digit (or a decimal digit that would
|
|
|
|
* create a byte sequence greater than 2XX)
|
|
|
|
* and there aren't any other codes waiting:
|
|
|
|
* control character sequence mode. */
|
|
|
|
retval = get_control_kbinput(keycode);
|
|
|
|
else {
|
|
|
|
/* An invalid digit in the middle of a byte
|
|
|
|
* sequence: reset the byte sequence counter
|
|
|
|
* and save the code we got as the result. */
|
|
|
|
byte_digits = 0;
|
2016-07-13 10:09:49 +00:00
|
|
|
retval = keycode;
|
2016-07-13 16:26:45 +00:00
|
|
|
}
|
2016-08-01 12:05:42 +00:00
|
|
|
escapes = 0;
|
2016-07-13 16:26:45 +00:00
|
|
|
}
|
|
|
|
} else if (keycode == '[' && key_buffer_len > 0 &&
|
2016-11-18 13:14:36 +00:00
|
|
|
(('A' <= *key_buffer && *key_buffer <= 'D') ||
|
|
|
|
('a' <= *key_buffer && *key_buffer <= 'd'))) {
|
|
|
|
/* An iTerm2/Eterm/rxvt sequence: ^[ ^[ [ X. */
|
2016-07-13 16:26:45 +00:00
|
|
|
double_esc = TRUE;
|
|
|
|
} else {
|
|
|
|
/* Two escapes followed by a non-escape, and there are more
|
|
|
|
* codes waiting: combined meta and escape sequence mode. */
|
|
|
|
retval = parse_escape_sequence(win, keycode);
|
2016-08-01 12:05:42 +00:00
|
|
|
meta_key = TRUE;
|
|
|
|
escapes = 0;
|
2005-01-12 03:25:57 +00:00
|
|
|
}
|
2016-07-13 16:26:45 +00:00
|
|
|
break;
|
|
|
|
case 3:
|
2016-07-15 19:53:46 +00:00
|
|
|
if (key_buffer_len == 0)
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Three escapes followed by a non-escape, and no
|
|
|
|
* other codes are waiting: normal input mode. */
|
|
|
|
retval = keycode;
|
|
|
|
else
|
|
|
|
/* Three escapes followed by a non-escape, and more
|
|
|
|
* codes are waiting: combined control character and
|
|
|
|
* escape sequence mode. First interpret the escape
|
|
|
|
* sequence, then the result as a control sequence. */
|
|
|
|
retval = get_control_kbinput(
|
|
|
|
parse_escape_sequence(win, keycode));
|
2016-08-01 12:05:42 +00:00
|
|
|
escapes = 0;
|
2016-07-13 16:26:45 +00:00
|
|
|
break;
|
|
|
|
}
|
2003-08-17 02:48:43 +00:00
|
|
|
|
2016-07-13 16:08:44 +00:00
|
|
|
if (retval == ERR)
|
|
|
|
return ERR;
|
|
|
|
|
2016-07-31 16:29:57 +00:00
|
|
|
if (retval == controlleft)
|
2016-10-11 08:50:04 +00:00
|
|
|
return CONTROL_LEFT;
|
2016-07-31 16:29:57 +00:00
|
|
|
else if (retval == controlright)
|
2016-10-11 08:50:04 +00:00
|
|
|
return CONTROL_RIGHT;
|
2016-07-31 16:29:57 +00:00
|
|
|
else if (retval == controlup)
|
2016-10-11 08:50:04 +00:00
|
|
|
return CONTROL_UP;
|
2016-07-31 16:29:57 +00:00
|
|
|
else if (retval == controldown)
|
2016-10-11 08:50:04 +00:00
|
|
|
return CONTROL_DOWN;
|
2016-09-08 19:00:51 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-04-24 09:28:28 +00:00
|
|
|
else if (retval == shiftcontrolleft) {
|
|
|
|
shift_held = TRUE;
|
2016-12-22 10:42:13 +00:00
|
|
|
return CONTROL_LEFT;
|
2016-04-24 09:28:28 +00:00
|
|
|
} else if (retval == shiftcontrolright) {
|
|
|
|
shift_held = TRUE;
|
2016-12-22 10:42:13 +00:00
|
|
|
return CONTROL_RIGHT;
|
2016-04-24 09:28:28 +00:00
|
|
|
} else if (retval == shiftcontrolup) {
|
|
|
|
shift_held = TRUE;
|
2016-12-22 10:42:13 +00:00
|
|
|
return CONTROL_UP;
|
2016-04-24 09:28:28 +00:00
|
|
|
} else if (retval == shiftcontroldown) {
|
|
|
|
shift_held = TRUE;
|
2016-12-22 10:42:13 +00:00
|
|
|
return CONTROL_DOWN;
|
2016-04-24 09:28:28 +00:00
|
|
|
} else if (retval == shiftaltleft) {
|
|
|
|
shift_held = TRUE;
|
2016-12-22 10:42:13 +00:00
|
|
|
return KEY_HOME;
|
2016-04-24 09:28:28 +00:00
|
|
|
} else if (retval == shiftaltright) {
|
|
|
|
shift_held = TRUE;
|
2016-12-22 10:42:13 +00:00
|
|
|
return KEY_END;
|
2016-04-24 09:28:28 +00:00
|
|
|
} else if (retval == shiftaltup) {
|
|
|
|
shift_held = TRUE;
|
2016-12-22 10:42:13 +00:00
|
|
|
return KEY_PPAGE;
|
2016-04-24 09:28:28 +00:00
|
|
|
} else if (retval == shiftaltdown) {
|
|
|
|
shift_held = TRUE;
|
2016-12-22 10:42:13 +00:00
|
|
|
return KEY_NPAGE;
|
2016-04-24 09:28:28 +00:00
|
|
|
}
|
2016-07-31 16:29:57 +00:00
|
|
|
#endif
|
|
|
|
|
2016-09-08 19:00:51 +00:00
|
|
|
#ifdef __linux__
|
2016-07-29 07:15:07 +00:00
|
|
|
/* When not running under X, check for the bare arrow keys whether
|
2016-04-24 09:28:28 +00:00
|
|
|
* Shift/Ctrl/Alt are being held together with them. */
|
|
|
|
unsigned char modifiers = 6;
|
|
|
|
|
|
|
|
if (console && ioctl(0, TIOCLINUX, &modifiers) >= 0) {
|
2016-12-22 09:42:49 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
/* Is Shift being held? */
|
|
|
|
if (modifiers & 0x01)
|
|
|
|
shift_held = TRUE;
|
|
|
|
#endif
|
2016-04-24 09:28:28 +00:00
|
|
|
/* Is Ctrl being held? */
|
|
|
|
if (modifiers & 0x04) {
|
2016-07-29 07:15:07 +00:00
|
|
|
if (retval == KEY_UP)
|
2016-12-22 10:42:13 +00:00
|
|
|
return CONTROL_UP;
|
2016-07-29 07:15:07 +00:00
|
|
|
else if (retval == KEY_DOWN)
|
2016-12-22 10:42:13 +00:00
|
|
|
return CONTROL_DOWN;
|
2016-07-29 07:15:07 +00:00
|
|
|
else if (retval == KEY_LEFT)
|
2016-12-22 10:42:13 +00:00
|
|
|
return CONTROL_LEFT;
|
2016-04-24 09:28:28 +00:00
|
|
|
else if (retval == KEY_RIGHT)
|
2016-12-22 10:42:13 +00:00
|
|
|
return CONTROL_RIGHT;
|
2016-07-29 07:15:07 +00:00
|
|
|
}
|
2016-09-08 19:00:51 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-04-24 09:28:28 +00:00
|
|
|
/* Are both Shift and Alt being held? */
|
|
|
|
if ((modifiers & 0x09) == 0x09) {
|
|
|
|
if (retval == KEY_UP)
|
2016-12-22 10:42:13 +00:00
|
|
|
return KEY_PPAGE;
|
2016-04-24 09:28:28 +00:00
|
|
|
else if (retval == KEY_DOWN)
|
2016-12-22 10:42:13 +00:00
|
|
|
return KEY_NPAGE;
|
2016-04-24 09:28:28 +00:00
|
|
|
else if (retval == KEY_LEFT)
|
2016-12-22 10:42:13 +00:00
|
|
|
return KEY_HOME;
|
2016-04-24 09:28:28 +00:00
|
|
|
else if (retval == KEY_RIGHT)
|
2016-12-22 10:42:13 +00:00
|
|
|
return KEY_END;
|
2016-04-24 09:28:28 +00:00
|
|
|
}
|
2016-09-08 19:00:51 +00:00
|
|
|
#endif
|
2016-07-29 07:15:07 +00:00
|
|
|
}
|
2016-09-08 19:00:51 +00:00
|
|
|
#endif /* __linux__ */
|
2016-07-29 07:15:07 +00:00
|
|
|
|
2016-07-13 16:26:45 +00:00
|
|
|
switch (retval) {
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef KEY_SLEFT
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_SLEFT. */
|
|
|
|
case KEY_SLEFT:
|
2016-04-24 09:28:28 +00:00
|
|
|
shift_held = TRUE;
|
2016-09-01 07:46:50 +00:00
|
|
|
return KEY_LEFT;
|
2016-07-11 14:22:30 +00:00
|
|
|
#endif
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef KEY_SRIGHT
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_SRIGHT. */
|
|
|
|
case KEY_SRIGHT:
|
2016-04-24 09:28:28 +00:00
|
|
|
shift_held = TRUE;
|
2016-09-01 07:46:50 +00:00
|
|
|
return KEY_RIGHT;
|
2016-07-11 14:22:30 +00:00
|
|
|
#endif
|
2016-08-30 08:11:29 +00:00
|
|
|
#ifdef KEY_SR
|
2016-07-10 18:49:52 +00:00
|
|
|
#ifdef KEY_SUP
|
2016-07-13 16:26:45 +00:00
|
|
|
/* ncurses and Slang don't support KEY_SUP. */
|
|
|
|
case KEY_SUP:
|
2016-07-11 14:22:30 +00:00
|
|
|
#endif
|
2016-04-24 09:28:28 +00:00
|
|
|
case KEY_SR: /* Scroll backward, on Xfce4-terminal. */
|
|
|
|
shift_held = TRUE;
|
2016-09-01 07:46:50 +00:00
|
|
|
return KEY_UP;
|
2016-08-30 08:11:29 +00:00
|
|
|
#endif
|
|
|
|
#ifdef KEY_SF
|
2016-07-10 18:49:52 +00:00
|
|
|
#ifdef KEY_SDOWN
|
2016-07-13 16:26:45 +00:00
|
|
|
/* ncurses and Slang don't support KEY_SDOWN. */
|
|
|
|
case KEY_SDOWN:
|
2016-07-11 14:22:30 +00:00
|
|
|
#endif
|
2016-04-24 09:28:28 +00:00
|
|
|
case KEY_SF: /* Scroll forward, on Xfce4-terminal. */
|
|
|
|
shift_held = TRUE;
|
2016-09-01 07:46:50 +00:00
|
|
|
return KEY_DOWN;
|
2016-08-30 08:11:29 +00:00
|
|
|
#endif
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef KEY_SHOME
|
2016-07-13 16:26:45 +00:00
|
|
|
/* HP-UX 10-11 and Slang don't support KEY_SHOME. */
|
|
|
|
case KEY_SHOME:
|
2016-07-10 18:01:23 +00:00
|
|
|
#endif
|
2016-08-30 08:11:29 +00:00
|
|
|
case SHIFT_HOME:
|
|
|
|
shift_held = TRUE;
|
2016-07-13 16:26:45 +00:00
|
|
|
case KEY_A1: /* Home (7) on keypad with NumLock off. */
|
2016-09-01 07:46:50 +00:00
|
|
|
return KEY_HOME;
|
2016-07-10 18:49:52 +00:00
|
|
|
#ifdef KEY_SEND
|
2016-07-13 16:26:45 +00:00
|
|
|
/* HP-UX 10-11 and Slang don't support KEY_SEND. */
|
|
|
|
case KEY_SEND:
|
2016-07-10 18:49:52 +00:00
|
|
|
#endif
|
2016-08-30 08:11:29 +00:00
|
|
|
case SHIFT_END:
|
|
|
|
shift_held = TRUE;
|
2016-07-13 16:26:45 +00:00
|
|
|
case KEY_C1: /* End (1) on keypad with NumLock off. */
|
2016-09-01 07:46:50 +00:00
|
|
|
return KEY_END;
|
2016-04-24 09:28:28 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-12-01 15:51:40 +00:00
|
|
|
#ifdef KEY_SPREVIOUS
|
|
|
|
case KEY_SPREVIOUS:
|
|
|
|
#endif
|
|
|
|
case SHIFT_PAGEUP: /* Fake key, from Shift+Alt+Up. */
|
2016-04-24 09:28:28 +00:00
|
|
|
shift_held = TRUE;
|
|
|
|
#endif
|
2016-07-13 16:26:45 +00:00
|
|
|
case KEY_A3: /* PageUp (9) on keypad with NumLock off. */
|
2016-09-01 07:46:50 +00:00
|
|
|
return KEY_PPAGE;
|
2016-04-24 09:28:28 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-12-01 15:51:40 +00:00
|
|
|
#ifdef KEY_SNEXT
|
|
|
|
case KEY_SNEXT:
|
|
|
|
#endif
|
2016-04-24 09:28:28 +00:00
|
|
|
case SHIFT_PAGEDOWN: /* Fake key, from Shift+Alt+Down. */
|
|
|
|
shift_held = TRUE;
|
|
|
|
#endif
|
2016-07-13 16:26:45 +00:00
|
|
|
case KEY_C3: /* PageDown (3) on keypad with NumLock off. */
|
2016-09-01 07:46:50 +00:00
|
|
|
return KEY_NPAGE;
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef KEY_SDC
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_SDC. */
|
|
|
|
case KEY_SDC:
|
2016-07-10 19:36:25 +00:00
|
|
|
#endif
|
2016-08-01 10:56:05 +00:00
|
|
|
case DEL_CODE:
|
2016-07-13 16:26:45 +00:00
|
|
|
if (ISSET(REBIND_DELETE))
|
2016-12-22 11:02:11 +00:00
|
|
|
return the_code_for(do_delete, KEY_DC);
|
2016-07-13 16:26:45 +00:00
|
|
|
else
|
2016-09-01 07:46:50 +00:00
|
|
|
return KEY_BACKSPACE;
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef KEY_SIC
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_SIC. */
|
|
|
|
case KEY_SIC:
|
2016-12-22 11:02:11 +00:00
|
|
|
return the_code_for(do_insertfile_void, KEY_IC);
|
2008-03-11 03:03:53 +00:00
|
|
|
#endif
|
2016-07-10 18:01:23 +00:00
|
|
|
#ifdef KEY_SBEG
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_SBEG. */
|
|
|
|
case KEY_SBEG:
|
2016-07-10 18:01:23 +00:00
|
|
|
#endif
|
2006-07-23 17:25:38 +00:00
|
|
|
#ifdef KEY_BEG
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_BEG. */
|
|
|
|
case KEY_BEG:
|
2016-07-10 18:01:23 +00:00
|
|
|
#endif
|
2016-07-13 16:26:45 +00:00
|
|
|
case KEY_B2: /* Center (5) on keypad with NumLock off. */
|
|
|
|
return ERR;
|
2007-04-18 14:06:34 +00:00
|
|
|
#ifdef KEY_CANCEL
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef KEY_SCANCEL
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_SCANCEL. */
|
|
|
|
case KEY_SCANCEL:
|
2007-04-18 14:06:34 +00:00
|
|
|
#endif
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_CANCEL. */
|
|
|
|
case KEY_CANCEL:
|
2016-12-22 11:02:11 +00:00
|
|
|
return the_code_for(do_cancel, 0x03);
|
2006-07-23 17:25:38 +00:00
|
|
|
#endif
|
2016-07-10 18:01:23 +00:00
|
|
|
#ifdef KEY_SUSPEND
|
2006-07-23 17:25:38 +00:00
|
|
|
#ifdef KEY_SSUSPEND
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_SSUSPEND. */
|
|
|
|
case KEY_SSUSPEND:
|
2006-07-23 17:25:38 +00:00
|
|
|
#endif
|
2016-07-13 16:26:45 +00:00
|
|
|
/* Slang doesn't support KEY_SUSPEND. */
|
|
|
|
case KEY_SUSPEND:
|
2016-12-22 11:02:11 +00:00
|
|
|
return the_code_for(do_suspend_void, KEY_SUSPEND);
|
2006-07-23 17:25:38 +00:00
|
|
|
#endif
|
|
|
|
#ifdef PDCURSES
|
2016-07-13 16:26:45 +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:
|
|
|
|
return ERR;
|
2006-07-23 17:25:38 +00:00
|
|
|
#endif
|
2016-09-06 10:05:22 +00:00
|
|
|
#ifdef KEY_RESIZE
|
|
|
|
/* Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
|
2016-07-13 16:26:45 +00:00
|
|
|
case KEY_RESIZE:
|
|
|
|
return ERR;
|
2015-05-28 13:02:29 +00:00
|
|
|
#endif
|
2016-08-01 12:05:42 +00:00
|
|
|
}
|
2004-05-28 17:23:33 +00:00
|
|
|
|
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
|
2006-07-25 19:23:35 +00:00
|
|
|
* are generated when the keypad doesn't support the needed keys.
|
|
|
|
* Assume that Escape has already been read in. */
|
2015-12-22 19:00:25 +00:00
|
|
|
int convert_sequence(const int *seq, size_t seq_len)
|
2003-08-17 02:48:43 +00:00
|
|
|
{
|
2004-12-04 17:41:52 +00:00
|
|
|
if (seq_len > 1) {
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[0]) {
|
2003-12-24 03:33:09 +00:00
|
|
|
case 'O':
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[1]) {
|
2007-04-04 20:36:56 +00:00
|
|
|
case '1':
|
2016-07-28 19:27:45 +00:00
|
|
|
if (seq_len > 4 && seq[2] == ';') {
|
|
|
|
|
2007-04-04 20:36:56 +00:00
|
|
|
switch (seq[3]) {
|
|
|
|
case '2':
|
2016-07-28 19:35:42 +00:00
|
|
|
switch (seq[4]) {
|
|
|
|
case 'A': /* Esc O 1 ; 2 A == Shift-Up on Terminal. */
|
|
|
|
case 'B': /* Esc O 1 ; 2 B == Shift-Down on Terminal. */
|
|
|
|
case 'C': /* Esc O 1 ; 2 C == Shift-Right on Terminal. */
|
|
|
|
case 'D': /* Esc O 1 ; 2 D == Shift-Left on Terminal. */
|
2016-04-24 09:28:28 +00:00
|
|
|
shift_held = TRUE;
|
2016-07-28 19:35:42 +00:00
|
|
|
return arrow_from_abcd(seq[4]);
|
|
|
|
case 'P': /* Esc O 1 ; 2 P == F13 on Terminal. */
|
|
|
|
return KEY_F(13);
|
|
|
|
case 'Q': /* Esc O 1 ; 2 Q == F14 on Terminal. */
|
|
|
|
return KEY_F(14);
|
|
|
|
case 'R': /* Esc O 1 ; 2 R == F15 on Terminal. */
|
|
|
|
return KEY_F(15);
|
|
|
|
case 'S': /* Esc O 1 ; 2 S == F16 on Terminal. */
|
|
|
|
return KEY_F(16);
|
|
|
|
}
|
2007-04-04 20:36:56 +00:00
|
|
|
break;
|
|
|
|
case '5':
|
2016-07-28 19:35:42 +00:00
|
|
|
switch (seq[4]) {
|
|
|
|
case 'A': /* Esc O 1 ; 5 A == Ctrl-Up on Terminal. */
|
|
|
|
return CONTROL_UP;
|
|
|
|
case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on Terminal. */
|
|
|
|
return CONTROL_DOWN;
|
|
|
|
case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on Terminal. */
|
|
|
|
return CONTROL_RIGHT;
|
|
|
|
case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on Terminal. */
|
|
|
|
return CONTROL_LEFT;
|
|
|
|
}
|
2007-04-04 20:36:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-07-28 19:27:45 +00:00
|
|
|
|
2007-04-04 20:36:56 +00:00
|
|
|
}
|
|
|
|
break;
|
2004-01-23 19:26:17 +00:00
|
|
|
case '2':
|
2004-12-04 17:41:52 +00:00
|
|
|
if (seq_len >= 3) {
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[2]) {
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'P': /* Esc O 2 P == F13 on xterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(13);
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'Q': /* Esc O 2 Q == F14 on xterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(14);
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'R': /* Esc O 2 R == F15 on xterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(15);
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'S': /* Esc O 2 S == F16 on xterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(16);
|
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. */
|
2015-04-28 20:09:40 +00:00
|
|
|
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. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return arrow_from_abcd(seq[1]);
|
2004-04-23 18:02:37 +00:00
|
|
|
case 'E': /* Esc O E == Center (5) on numeric keypad
|
|
|
|
* with NumLock off on xterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_B2;
|
2007-04-04 20:36:56 +00:00
|
|
|
case 'F': /* Esc O F == End on xterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_END;
|
2007-04-04 20:36:56 +00:00
|
|
|
case 'H': /* Esc O H == Home on xterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_HOME;
|
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/
|
2006-05-30 20:51:15 +00:00
|
|
|
* rxvt/Eterm. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_ENTER;
|
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. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(1);
|
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. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(2);
|
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. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(3);
|
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. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(4);
|
2004-10-24 22:51:39 +00:00
|
|
|
case 'T': /* Esc O T == F5 on Mach console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(5);
|
2004-10-24 22:51:39 +00:00
|
|
|
case 'U': /* Esc O U == F6 on Mach console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(6);
|
2004-10-24 22:51:39 +00:00
|
|
|
case 'V': /* Esc O V == F7 on Mach console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(7);
|
2004-10-24 22:51:39 +00:00
|
|
|
case 'W': /* Esc O W == F8 on Mach console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(8);
|
2004-10-24 22:51:39 +00:00
|
|
|
case 'X': /* Esc O X == F9 on Mach console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(9);
|
2004-10-24 22:51:39 +00:00
|
|
|
case 'Y': /* Esc O Y == F10 on Mach console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(10);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'a': /* Esc O a == Ctrl-Up on rxvt. */
|
2016-06-25 13:16:52 +00:00
|
|
|
return CONTROL_UP;
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'b': /* Esc O b == Ctrl-Down on rxvt. */
|
2016-06-25 13:16:52 +00:00
|
|
|
return CONTROL_DOWN;
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'c': /* Esc O c == Ctrl-Right on rxvt. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return CONTROL_RIGHT;
|
2003-12-24 03:33:09 +00:00
|
|
|
case 'd': /* Esc O d == Ctrl-Left on rxvt. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return CONTROL_LEFT;
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return '*';
|
2004-04-23 18:02:37 +00:00
|
|
|
case 'k': /* Esc O k == '+' on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return '+';
|
2004-04-23 18:02:37 +00:00
|
|
|
case 'l': /* Esc O l == ',' on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return ',';
|
2004-04-23 18:02:37 +00:00
|
|
|
case 'm': /* Esc O m == '-' on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return '-';
|
2004-04-23 18:02:37 +00:00
|
|
|
case 'n': /* Esc O n == Delete (.) on numeric keypad
|
2004-06-22 14:30:18 +00:00
|
|
|
* with NumLock off on VT100/VT220/VT320/
|
2007-04-04 20:36:56 +00:00
|
|
|
* xterm/rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_DC;
|
2004-04-23 18:02:37 +00:00
|
|
|
case 'o': /* Esc O o == '/' on numeric keypad with
|
2004-06-22 14:30:18 +00:00
|
|
|
* NumLock off on VT100/VT220/VT320/xterm/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return '/';
|
2004-04-23 18:02:37 +00:00
|
|
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_IC;
|
2004-04-23 18:02:37 +00:00
|
|
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_END;
|
2004-04-23 18:02:37 +00:00
|
|
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_DOWN;
|
2004-04-23 18:02:37 +00:00
|
|
|
case 's': /* Esc O s == PageDown (3) on numeric
|
2004-06-22 14:30:18 +00:00
|
|
|
* keypad with NumLock off on VT100/VT220/
|
2007-04-04 20:36:56 +00:00
|
|
|
* VT320/rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_NPAGE;
|
2004-04-23 18:02:37 +00:00
|
|
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_LEFT;
|
2004-04-23 18:02:37 +00:00
|
|
|
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. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_B2;
|
2004-04-23 18:02:37 +00:00
|
|
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_RIGHT;
|
2004-04-23 18:02:37 +00:00
|
|
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_HOME;
|
2004-04-23 18:02:37 +00:00
|
|
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_UP;
|
2004-04-23 18:02:37 +00:00
|
|
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_PPAGE;
|
2003-12-24 03:33:09 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'o':
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[1]) {
|
2003-12-24 03:33:09 +00:00
|
|
|
case 'a': /* Esc o a == Ctrl-Up on Eterm. */
|
2016-06-25 13:16:52 +00:00
|
|
|
return CONTROL_UP;
|
2003-12-24 03:33:09 +00:00
|
|
|
case 'b': /* Esc o b == Ctrl-Down on Eterm. */
|
2016-06-25 13:16:52 +00:00
|
|
|
return CONTROL_DOWN;
|
2003-12-24 03:33:09 +00:00
|
|
|
case 'c': /* Esc o c == Ctrl-Right on Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return CONTROL_RIGHT;
|
2003-12-24 03:33:09 +00:00
|
|
|
case 'd': /* Esc o d == Ctrl-Left on Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return CONTROL_LEFT;
|
2003-12-24 03:33:09 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '[':
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[1]) {
|
2003-12-24 03:33:09 +00:00
|
|
|
case '1':
|
2016-07-28 19:12:18 +00:00
|
|
|
if (seq_len > 3 && seq[3] == '~') {
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[2]) {
|
2015-04-28 20:09:40 +00:00
|
|
|
case '1': /* Esc [ 1 1 ~ == F1 on rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(1);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '2': /* Esc [ 1 2 ~ == F2 on rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(2);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '3': /* Esc [ 1 3 ~ == F3 on rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(3);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '4': /* Esc [ 1 4 ~ == F4 on rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(4);
|
2004-06-22 14:30:18 +00:00
|
|
|
case '5': /* Esc [ 1 5 ~ == F5 on xterm/
|
|
|
|
* rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(5);
|
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. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(6);
|
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. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(7);
|
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. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(8);
|
2016-07-28 19:12:18 +00:00
|
|
|
}
|
|
|
|
} else if (seq_len > 4 && seq[2] == ';') {
|
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[3]) {
|
2004-02-06 03:07:10 +00:00
|
|
|
case '2':
|
2016-07-28 19:35:42 +00:00
|
|
|
switch (seq[4]) {
|
|
|
|
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. */
|
2016-04-24 09:28:28 +00:00
|
|
|
shift_held = TRUE;
|
2016-07-28 19:35:42 +00:00
|
|
|
return arrow_from_abcd(seq[4]);
|
|
|
|
}
|
2004-02-06 03:07:10 +00:00
|
|
|
break;
|
2016-04-24 09:28:28 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
case '4':
|
|
|
|
/* When the arrow keys are held together with Shift+Meta,
|
|
|
|
* act as if they are Home/End/PgUp/PgDown with Shift. */
|
|
|
|
switch (seq[4]) {
|
|
|
|
case 'A': /* Esc [ 1 ; 4 A == Shift-Alt-Up on xterm. */
|
|
|
|
return SHIFT_PAGEUP;
|
|
|
|
case 'B': /* Esc [ 1 ; 4 B == Shift-Alt-Down on xterm. */
|
|
|
|
return SHIFT_PAGEDOWN;
|
|
|
|
case 'C': /* Esc [ 1 ; 4 C == Shift-Alt-Right on xterm. */
|
2016-08-30 08:11:29 +00:00
|
|
|
return SHIFT_END;
|
2016-04-24 09:28:28 +00:00
|
|
|
case 'D': /* Esc [ 1 ; 4 D == Shift-Alt-Left on xterm. */
|
2016-08-30 08:11:29 +00:00
|
|
|
return SHIFT_HOME;
|
2016-04-24 09:28:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2004-02-06 03:07:10 +00:00
|
|
|
case '5':
|
2016-07-28 19:35:42 +00:00
|
|
|
switch (seq[4]) {
|
|
|
|
case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on xterm. */
|
|
|
|
return CONTROL_UP;
|
|
|
|
case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on xterm. */
|
|
|
|
return CONTROL_DOWN;
|
|
|
|
case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on xterm. */
|
|
|
|
return CONTROL_RIGHT;
|
|
|
|
case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on xterm. */
|
|
|
|
return CONTROL_LEFT;
|
|
|
|
}
|
2004-02-06 03:07:10 +00:00
|
|
|
break;
|
2016-04-24 09:28:28 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
case '6':
|
|
|
|
switch (seq[4]) {
|
|
|
|
case 'A': /* Esc [ 1 ; 6 A == Shift-Ctrl-Up on xterm. */
|
|
|
|
return shiftcontrolup;
|
|
|
|
case 'B': /* Esc [ 1 ; 6 B == Shift-Ctrl-Down on xterm. */
|
|
|
|
return shiftcontroldown;
|
|
|
|
case 'C': /* Esc [ 1 ; 6 C == Shift-Ctrl-Right on xterm. */
|
|
|
|
return shiftcontrolright;
|
|
|
|
case 'D': /* Esc [ 1 ; 6 D == Shift-Ctrl-Left on xterm. */
|
|
|
|
return shiftcontrolleft;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2004-02-06 03:07:10 +00:00
|
|
|
}
|
2016-07-28 19:12:18 +00:00
|
|
|
|
|
|
|
} else if (seq_len > 2 && seq[2] == '~')
|
|
|
|
/* Esc [ 1 ~ == Home on VT320/Linux console. */
|
|
|
|
return KEY_HOME;
|
2004-01-23 19:26:17 +00:00
|
|
|
break;
|
|
|
|
case '2':
|
2016-07-28 19:12:18 +00:00
|
|
|
if (seq_len > 3 && seq[3] == '~') {
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[2]) {
|
2015-04-28 20:09:40 +00:00
|
|
|
case '0': /* Esc [ 2 0 ~ == F9 on VT220/VT320/
|
|
|
|
* Linux console/xterm/rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(9);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '1': /* Esc [ 2 1 ~ == F10 on VT220/VT320/
|
|
|
|
* Linux console/xterm/rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(10);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '3': /* Esc [ 2 3 ~ == F11 on VT220/VT320/
|
|
|
|
* Linux console/xterm/rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(11);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '4': /* Esc [ 2 4 ~ == F12 on VT220/VT320/
|
|
|
|
* Linux console/xterm/rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(12);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '5': /* Esc [ 2 5 ~ == F13 on VT220/VT320/
|
|
|
|
* Linux console/rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(13);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '6': /* Esc [ 2 6 ~ == F14 on VT220/VT320/
|
|
|
|
* Linux console/rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(14);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '8': /* Esc [ 2 8 ~ == F15 on VT220/VT320/
|
|
|
|
* Linux console/rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(15);
|
2015-04-28 20:09:40 +00:00
|
|
|
case '9': /* Esc [ 2 9 ~ == F16 on VT220/VT320/
|
|
|
|
* Linux console/rxvt/Eterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(16);
|
2004-01-23 19:26:17 +00:00
|
|
|
}
|
2016-07-28 19:12:18 +00:00
|
|
|
} else if (seq_len > 2 && seq[2] == '~')
|
|
|
|
/* Esc [ 2 ~ == Insert on VT220/VT320/
|
|
|
|
* Linux console/xterm/Terminal. */
|
|
|
|
return KEY_IC;
|
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/
|
2007-04-04 20:36:56 +00:00
|
|
|
* Linux console/xterm/Terminal. */
|
2016-11-26 19:33:31 +00:00
|
|
|
if (seq_len > 2 && seq[2] == '~')
|
|
|
|
return KEY_DC;
|
|
|
|
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. */
|
2016-11-26 19:33:31 +00:00
|
|
|
if (seq_len > 2 && seq[2] == '~')
|
|
|
|
return KEY_END;
|
|
|
|
break;
|
2004-06-22 14:30:18 +00:00
|
|
|
case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
|
2007-04-04 20:36:56 +00:00
|
|
|
* Linux console/xterm/Terminal;
|
|
|
|
* Esc [ 5 ^ == PageUp on Eterm. */
|
2016-11-26 19:33:31 +00:00
|
|
|
if (seq_len > 2 && (seq[2] == '~' || seq[2] == '^'))
|
|
|
|
return KEY_PPAGE;
|
|
|
|
break;
|
2004-06-22 14:30:18 +00:00
|
|
|
case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
|
2007-04-04 20:36:56 +00:00
|
|
|
* Linux console/xterm/Terminal;
|
2014-06-04 16:02:51 +00:00
|
|
|
* Esc [ 6 ^ == PageDown on Eterm. */
|
2016-11-26 19:33:31 +00:00
|
|
|
if (seq_len > 2 && (seq[2] == '~' || seq[2] == '^'))
|
|
|
|
return KEY_NPAGE;
|
|
|
|
break;
|
2016-11-26 11:25:36 +00:00
|
|
|
case '7': /* Esc [ 7 ~ == Home on Eterm/rxvt,
|
|
|
|
* Esc [ 7 $ == Shift-Home on Eterm/rxvt. */
|
|
|
|
if (seq_len > 2 && seq[2] == '~')
|
|
|
|
return KEY_HOME;
|
|
|
|
else if (seq_len > 2 && seq[2] == '$')
|
|
|
|
return SHIFT_HOME;
|
|
|
|
break;
|
|
|
|
case '8': /* Esc [ 8 ~ == End on Eterm/rxvt.
|
|
|
|
* Esc [ 8 $ == Shift-End on Eterm/rxvt. */
|
|
|
|
if (seq_len > 2 && seq[2] == '~')
|
|
|
|
return KEY_END;
|
|
|
|
else if (seq_len > 2 && seq[2] == '$')
|
|
|
|
return SHIFT_END;
|
|
|
|
break;
|
2004-10-24 22:51:39 +00:00
|
|
|
case '9': /* Esc [ 9 == Delete on Mach console. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_DC;
|
2004-10-24 22:51:39 +00:00
|
|
|
case '@': /* Esc [ @ == Insert on Mach console. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_IC;
|
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/
|
2007-04-18 13:48:37 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
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/
|
2007-04-18 13:48:37 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
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/
|
2007-04-18 13:48:37 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
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/
|
2007-04-18 13:48:37 +00:00
|
|
|
* rxvt/Eterm/Terminal. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return arrow_from_abcd(seq[1]);
|
2004-04-23 18:02:37 +00:00
|
|
|
case 'E': /* Esc [ E == Center (5) on numeric keypad
|
2007-04-04 20:36:56 +00:00
|
|
|
* with NumLock off on FreeBSD console/
|
|
|
|
* Terminal. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_B2;
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'F': /* Esc [ F == End on FreeBSD console/Eterm. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_END;
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'G': /* Esc [ G == PageDown on FreeBSD console. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_NPAGE;
|
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. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_HOME;
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'I': /* Esc [ I == PageUp on FreeBSD console. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_PPAGE;
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'L': /* Esc [ L == Insert on ANSI/FreeBSD console. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_IC;
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'M': /* Esc [ M == F1 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(1);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'N': /* Esc [ N == F2 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(2);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'O':
|
2016-07-28 19:12:18 +00:00
|
|
|
if (seq_len > 2) {
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[2]) {
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'P': /* Esc [ O P == F1 on xterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(1);
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'Q': /* Esc [ O Q == F2 on xterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(2);
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'R': /* Esc [ O R == F3 on xterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(3);
|
2015-04-28 20:09:40 +00:00
|
|
|
case 'S': /* Esc [ O S == F4 on xterm. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(4);
|
2004-01-23 19:26:17 +00:00
|
|
|
}
|
2005-09-25 18:42:05 +00:00
|
|
|
} else
|
2004-06-22 14:30:18 +00:00
|
|
|
/* Esc [ O == F3 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(3);
|
2004-01-23 19:26:17 +00:00
|
|
|
break;
|
|
|
|
case 'P': /* Esc [ P == F4 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(4);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(5);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'R': /* Esc [ R == F6 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(6);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'S': /* Esc [ S == F7 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(7);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'T': /* Esc [ T == F8 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(8);
|
2004-10-24 22:51:39 +00:00
|
|
|
case 'U': /* Esc [ U == PageDown on Mach console. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_NPAGE;
|
2004-10-24 22:51:39 +00:00
|
|
|
case 'V': /* Esc [ V == PageUp on Mach console. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_PPAGE;
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'W': /* Esc [ W == F11 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(11);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'X': /* Esc [ X == F12 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(12);
|
2004-10-24 22:51:39 +00:00
|
|
|
case 'Y': /* Esc [ Y == End on Mach console. */
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_END;
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(14);
|
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. */
|
2015-04-28 20:09:40 +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. */
|
2016-04-24 09:28:28 +00:00
|
|
|
shift_held = TRUE;
|
2015-12-22 20:24:50 +00:00
|
|
|
return arrow_from_abcd(seq[1]);
|
2004-01-23 19:26:17 +00:00
|
|
|
case '[':
|
2016-07-28 19:12:18 +00:00
|
|
|
if (seq_len > 2 ) {
|
2005-01-12 03:25:57 +00:00
|
|
|
switch (seq[2]) {
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'A': /* Esc [ [ A == F1 on Linux
|
|
|
|
* console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(1);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'B': /* Esc [ [ B == F2 on Linux
|
|
|
|
* console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(2);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'C': /* Esc [ [ C == F3 on Linux
|
|
|
|
* console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(3);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'D': /* Esc [ [ D == F4 on Linux
|
|
|
|
* console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(4);
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'E': /* Esc [ [ E == F5 on Linux
|
|
|
|
* console. */
|
2015-12-22 20:24:50 +00:00
|
|
|
return KEY_F(5);
|
2004-01-23 19:26:17 +00:00
|
|
|
}
|
|
|
|
}
|
2003-12-24 03:33:09 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2003-08-17 02:48:43 +00:00
|
|
|
}
|
|
|
|
|
2015-12-22 20:24:50 +00:00
|
|
|
return ERR;
|
2003-08-17 02:48:43 +00:00
|
|
|
}
|
|
|
|
|
2016-07-28 14:19:30 +00:00
|
|
|
/* Return the equivalent arrow-key value for the first four letters
|
|
|
|
* in the alphabet, common to many escape sequences. */
|
2015-12-22 19:00:25 +00:00
|
|
|
int arrow_from_abcd(int kbinput)
|
2004-01-23 19:26:17 +00:00
|
|
|
{
|
|
|
|
switch (tolower(kbinput)) {
|
|
|
|
case 'a':
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_UP;
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'b':
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_DOWN;
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'c':
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_RIGHT;
|
2004-01-23 19:26:17 +00:00
|
|
|
case 'd':
|
2016-07-28 14:19:30 +00:00
|
|
|
return KEY_LEFT;
|
2004-01-23 19:26:17 +00:00
|
|
|
default:
|
|
|
|
return ERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-25 22:10:27 +00:00
|
|
|
/* Interpret the escape sequence in the keystroke buffer, the first
|
2006-07-23 17:54:35 +00:00
|
|
|
* character of which is kbinput. Assume that the keystroke buffer
|
|
|
|
* isn't empty, and that the initial escape has already been read in. */
|
2015-12-22 19:00:25 +00:00
|
|
|
int parse_escape_sequence(WINDOW *win, int kbinput)
|
2006-05-25 22:10:27 +00:00
|
|
|
{
|
|
|
|
int retval, *seq;
|
|
|
|
size_t seq_len;
|
|
|
|
|
|
|
|
/* Put back the non-escape character, get the complete escape
|
|
|
|
* sequence, translate the sequence into its corresponding key
|
|
|
|
* value, and save that as the result. */
|
|
|
|
unget_input(&kbinput, 1);
|
2016-07-15 19:53:46 +00:00
|
|
|
seq_len = key_buffer_len;
|
2006-05-25 22:10:27 +00:00
|
|
|
seq = get_input(NULL, seq_len);
|
2015-12-22 19:00:25 +00:00
|
|
|
retval = convert_sequence(seq, seq_len);
|
2006-05-25 22:10:27 +00:00
|
|
|
|
|
|
|
free(seq);
|
|
|
|
|
2015-12-22 19:00:25 +00:00
|
|
|
/* If we got an unrecognized escape sequence, notify the user. */
|
2006-07-25 19:23:35 +00:00
|
|
|
if (retval == ERR) {
|
2006-07-23 18:00:50 +00:00
|
|
|
if (win == edit) {
|
2016-05-01 08:02:49 +00:00
|
|
|
/* TRANSLATORS: This refers to a sequence of escape codes
|
|
|
|
* (from the keyboard) that nano does not know about. */
|
2016-04-30 15:31:43 +00:00
|
|
|
statusline(ALERT, _("Unknown sequence"));
|
2016-05-14 20:14:37 +00:00
|
|
|
suppress_cursorpos = FALSE;
|
2016-05-19 18:43:08 +00:00
|
|
|
lastmessage = HUSH;
|
2016-05-14 20:14:37 +00:00
|
|
|
if (currmenu == MMAIN) {
|
|
|
|
reset_cursor();
|
|
|
|
curs_set(1);
|
|
|
|
}
|
2006-07-23 17:54:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-25 22:10:27 +00:00
|
|
|
#ifdef DEBUG
|
2015-12-22 19:00:25 +00:00
|
|
|
fprintf(stderr, "parse_escape_sequence(): kbinput = %d, seq_len = %lu, retval = %d\n",
|
|
|
|
kbinput, (unsigned long)seq_len, retval);
|
2006-05-25 22:10:27 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2006-05-27 15:52:26 +00:00
|
|
|
/* Translate a byte sequence: turn a three-digit decimal number (from
|
|
|
|
* 000 to 255) into its corresponding byte value. */
|
2006-05-10 13:41:53 +00:00
|
|
|
int get_byte_kbinput(int kbinput)
|
2004-05-28 17:23:33 +00:00
|
|
|
{
|
2005-01-12 03:25:57 +00:00
|
|
|
static int byte_digits = 0, byte = 0;
|
2004-12-04 17:41:52 +00:00
|
|
|
int retval = ERR;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
2005-01-03 19:56:56 +00:00
|
|
|
/* Increment the byte digit counter. */
|
|
|
|
byte_digits++;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
2005-01-03 19:56:56 +00:00
|
|
|
switch (byte_digits) {
|
2004-12-04 17:41:52 +00:00
|
|
|
case 1:
|
2006-05-27 15:52:26 +00:00
|
|
|
/* First digit: This must be from zero to two. Put it in
|
|
|
|
* the 100's position of the byte sequence holder. */
|
2005-01-03 19:56:56 +00:00
|
|
|
if ('0' <= kbinput && kbinput <= '2')
|
2006-05-27 15:52:26 +00:00
|
|
|
byte = (kbinput - '0') * 100;
|
2004-12-04 17:41:52 +00:00
|
|
|
else
|
2006-05-27 15:52:26 +00:00
|
|
|
/* This isn't the start of a byte sequence. Return this
|
|
|
|
* character as the result. */
|
2004-12-04 17:41:52 +00:00
|
|
|
retval = kbinput;
|
|
|
|
break;
|
|
|
|
case 2:
|
2006-05-27 15:52:26 +00:00
|
|
|
/* Second digit: This must be from zero to five if the first
|
|
|
|
* was two, and may be any decimal value if the first was
|
|
|
|
* zero or one. Put it in the 10's position of the byte
|
|
|
|
* sequence holder. */
|
2005-01-12 03:25:57 +00:00
|
|
|
if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
|
|
|
|
'6' <= kbinput && kbinput <= '9'))
|
|
|
|
byte += (kbinput - '0') * 10;
|
2004-12-04 17:41:52 +00:00
|
|
|
else
|
2006-05-27 15:52:26 +00:00
|
|
|
/* This isn't the second digit of a byte sequence.
|
|
|
|
* Return this character as the result. */
|
2004-12-04 17:41:52 +00:00
|
|
|
retval = kbinput;
|
|
|
|
break;
|
|
|
|
case 3:
|
2006-05-27 15:52:26 +00:00
|
|
|
/* Third digit: This must be from zero to five if the first
|
2014-04-15 11:25:29 +00:00
|
|
|
* was two and the second was five, and may be any decimal
|
|
|
|
* value otherwise. Put it in the 1's position of the byte
|
|
|
|
* sequence holder. */
|
2005-01-12 03:25:57 +00:00
|
|
|
if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
|
|
|
|
'6' <= kbinput && kbinput <= '9')) {
|
2006-05-30 20:51:15 +00:00
|
|
|
byte += kbinput - '0';
|
2014-04-15 11:25:29 +00:00
|
|
|
/* The byte sequence is complete. */
|
2005-01-12 03:25:57 +00:00
|
|
|
retval = byte;
|
2005-01-03 19:56:56 +00:00
|
|
|
} else
|
2006-05-27 15:52:26 +00:00
|
|
|
/* This isn't the third digit of a byte sequence.
|
|
|
|
* Return this character as the result. */
|
2004-12-04 17:41:52 +00:00
|
|
|
retval = kbinput;
|
|
|
|
break;
|
2005-01-03 19:56:56 +00:00
|
|
|
default:
|
2006-05-27 15:52:26 +00:00
|
|
|
/* If there are more than three digits, return this
|
|
|
|
* character as the result. (Maybe we should produce an
|
|
|
|
* error instead?) */
|
2005-01-03 19:56:56 +00:00
|
|
|
retval = kbinput;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we have a result, reset the byte digit counter and the byte
|
|
|
|
* sequence holder. */
|
|
|
|
if (retval != ERR) {
|
|
|
|
byte_digits = 0;
|
2005-01-12 03:25:57 +00:00
|
|
|
byte = 0;
|
2005-01-03 19:56:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2005-01-12 03:25:57 +00:00
|
|
|
fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval);
|
2005-01-03 19:56:56 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2006-05-27 17:39:19 +00:00
|
|
|
#ifdef ENABLE_UTF8
|
2006-05-28 17:30:28 +00:00
|
|
|
/* If the character in kbinput is a valid hexadecimal digit, multiply it
|
2016-06-24 13:39:03 +00:00
|
|
|
* by factor and add the result to uni, and return ERR to signify okay. */
|
2006-05-28 17:30:28 +00:00
|
|
|
long add_unicode_digit(int kbinput, long factor, long *uni)
|
|
|
|
{
|
|
|
|
if ('0' <= kbinput && kbinput <= '9')
|
|
|
|
*uni += (kbinput - '0') * factor;
|
|
|
|
else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
|
|
|
|
*uni += (tolower(kbinput) - 'a' + 10) * factor;
|
|
|
|
else
|
2016-06-24 13:39:03 +00:00
|
|
|
/* The character isn't hexadecimal; give it as the result. */
|
|
|
|
return (long)kbinput;
|
2006-05-28 17:30:28 +00:00
|
|
|
|
2016-06-24 13:39:03 +00:00
|
|
|
return ERR;
|
2006-05-28 17:30:28 +00:00
|
|
|
}
|
|
|
|
|
2005-08-08 23:47:28 +00:00
|
|
|
/* Translate a Unicode sequence: turn a six-digit hexadecimal number
|
2006-05-27 15:52:26 +00:00
|
|
|
* (from 000000 to 10FFFF, case-insensitive) into its corresponding
|
2005-08-08 23:47:28 +00:00
|
|
|
* multibyte value. */
|
2016-07-24 10:34:56 +00:00
|
|
|
long get_unicode_kbinput(WINDOW *win, int kbinput)
|
2005-01-03 19:56:56 +00:00
|
|
|
{
|
2005-08-08 23:03:25 +00:00
|
|
|
static int uni_digits = 0;
|
|
|
|
static long uni = 0;
|
|
|
|
long retval = ERR;
|
2005-01-03 19:56:56 +00:00
|
|
|
|
2005-08-08 23:47:28 +00:00
|
|
|
/* Increment the Unicode digit counter. */
|
2005-08-01 19:12:05 +00:00
|
|
|
uni_digits++;
|
2005-01-03 19:56:56 +00:00
|
|
|
|
2005-08-01 19:12:05 +00:00
|
|
|
switch (uni_digits) {
|
2005-01-03 19:56:56 +00:00
|
|
|
case 1:
|
2016-07-24 11:44:16 +00:00
|
|
|
/* The first digit must be zero or one. Put it in the
|
|
|
|
* 0x100000's position of the Unicode sequence holder.
|
|
|
|
* Otherwise, return the character itself as the result. */
|
|
|
|
if (kbinput == '0' || kbinput == '1')
|
2006-05-27 15:52:26 +00:00
|
|
|
uni = (kbinput - '0') * 0x100000;
|
2005-08-08 23:47:28 +00:00
|
|
|
else
|
|
|
|
retval = kbinput;
|
|
|
|
break;
|
|
|
|
case 2:
|
2016-07-24 11:44:16 +00:00
|
|
|
/* The second digit must be zero if the first was one, but
|
|
|
|
* may be any hexadecimal value if the first was zero. */
|
|
|
|
if (kbinput == '0' || uni == 0)
|
2006-05-27 15:52:26 +00:00
|
|
|
retval = add_unicode_digit(kbinput, 0x10000, &uni);
|
2005-08-08 23:47:28 +00:00
|
|
|
else
|
|
|
|
retval = kbinput;
|
|
|
|
break;
|
|
|
|
case 3:
|
2016-07-24 11:44:16 +00:00
|
|
|
/* Later digits may be any hexadecimal value. */
|
2006-05-27 15:52:26 +00:00
|
|
|
retval = add_unicode_digit(kbinput, 0x1000, &uni);
|
2005-01-03 19:56:56 +00:00
|
|
|
break;
|
2005-08-08 23:47:28 +00:00
|
|
|
case 4:
|
2006-05-27 15:52:26 +00:00
|
|
|
retval = add_unicode_digit(kbinput, 0x100, &uni);
|
2004-12-04 17:41:52 +00:00
|
|
|
break;
|
2005-08-08 23:47:28 +00:00
|
|
|
case 5:
|
2006-05-27 15:52:26 +00:00
|
|
|
retval = add_unicode_digit(kbinput, 0x10, &uni);
|
2005-01-03 19:56:56 +00:00
|
|
|
break;
|
2005-08-08 23:47:28 +00:00
|
|
|
case 6:
|
2006-05-27 15:52:26 +00:00
|
|
|
retval = add_unicode_digit(kbinput, 0x1, &uni);
|
2016-07-24 11:44:16 +00:00
|
|
|
/* If also the sixth digit was a valid hexadecimal value, then
|
|
|
|
* the Unicode sequence is complete, so return it. */
|
2006-05-27 15:52:26 +00:00
|
|
|
if (retval == ERR)
|
2005-08-01 19:12:05 +00:00
|
|
|
retval = uni;
|
2004-12-04 17:41:52 +00:00
|
|
|
break;
|
|
|
|
}
|
2004-05-28 17:23:33 +00:00
|
|
|
|
2016-07-24 10:34:56 +00:00
|
|
|
/* Show feedback only when editing, not when at a prompt. */
|
2016-07-24 11:15:45 +00:00
|
|
|
if (retval == ERR && win == edit) {
|
2016-07-24 10:34:56 +00:00
|
|
|
char partial[7] = "......";
|
|
|
|
|
|
|
|
/* Construct the partial result, right-padding it with dots. */
|
|
|
|
snprintf(partial, uni_digits + 1, "%06lX", uni);
|
|
|
|
partial[uni_digits] = '.';
|
|
|
|
|
|
|
|
/* TRANSLATORS: This is shown while a six-digit hexadecimal
|
|
|
|
* Unicode character code (%s) is being typed in. */
|
|
|
|
statusline(HUSH, _("Unicode Input: %s"), partial);
|
|
|
|
}
|
2004-11-29 00:30:07 +00:00
|
|
|
|
2004-05-28 17:23:33 +00:00
|
|
|
#ifdef DEBUG
|
2016-07-24 11:15:45 +00:00
|
|
|
fprintf(stderr, "get_unicode_kbinput(): kbinput = %d, uni_digits = %d, uni = %ld, retval = %ld\n",
|
|
|
|
kbinput, uni_digits, uni, retval);
|
2004-05-28 17:23:33 +00:00
|
|
|
#endif
|
|
|
|
|
2016-07-24 11:15:45 +00:00
|
|
|
/* If we have an end result, reset the Unicode digit counter. */
|
|
|
|
if (retval != ERR)
|
|
|
|
uni_digits = 0;
|
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
return retval;
|
|
|
|
}
|
2006-05-27 17:39:19 +00:00
|
|
|
#endif /* ENABLE_UTF8 */
|
2006-05-27 15:52:26 +00:00
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
/* Translate a control character sequence: turn an ASCII non-control
|
|
|
|
* character into its corresponding control character. */
|
|
|
|
int get_control_kbinput(int kbinput)
|
|
|
|
{
|
|
|
|
int retval;
|
|
|
|
|
2016-05-17 09:33:21 +00:00
|
|
|
/* Ctrl-Space (Ctrl-2, Ctrl-@, Ctrl-`) */
|
2006-05-27 15:52:26 +00:00
|
|
|
if (kbinput == ' ' || kbinput == '2')
|
2016-08-01 10:56:05 +00:00
|
|
|
retval = 0;
|
2006-04-28 18:26:07 +00:00
|
|
|
/* Ctrl-/ (Ctrl-7, Ctrl-_) */
|
|
|
|
else if (kbinput == '/')
|
2016-08-01 10:56:05 +00:00
|
|
|
retval = 31;
|
2006-04-28 18:26:07 +00:00
|
|
|
/* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-/, Ctrl-_) */
|
2004-12-04 17:41:52 +00:00
|
|
|
else if ('3' <= kbinput && kbinput <= '7')
|
|
|
|
retval = kbinput - 24;
|
|
|
|
/* Ctrl-8 (Ctrl-?) */
|
2006-05-27 15:52:26 +00:00
|
|
|
else if (kbinput == '8' || kbinput == '?')
|
2016-08-01 10:56:05 +00:00
|
|
|
retval = DEL_CODE;
|
2006-05-20 17:19:09 +00:00
|
|
|
/* Ctrl-@ (Ctrl-Space, Ctrl-2, Ctrl-`) to Ctrl-_ (Ctrl-/, Ctrl-7) */
|
|
|
|
else if ('@' <= kbinput && kbinput <= '_')
|
2006-05-27 15:52:26 +00:00
|
|
|
retval = kbinput - '@';
|
2006-04-28 18:26:07 +00:00
|
|
|
/* Ctrl-` (Ctrl-2, Ctrl-Space, Ctrl-@) to Ctrl-~ (Ctrl-6, Ctrl-^) */
|
|
|
|
else if ('`' <= kbinput && kbinput <= '~')
|
2006-05-27 15:52:26 +00:00
|
|
|
retval = kbinput - '`';
|
2004-12-04 17:41:52 +00:00
|
|
|
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
|
|
|
|
2006-05-26 03:22:44 +00:00
|
|
|
/* Put the output-formatted characters in output back into the keystroke
|
|
|
|
* buffer, so that they can be parsed and displayed as output again. */
|
2005-01-12 03:25:57 +00:00
|
|
|
void unparse_kbinput(char *output, size_t output_len)
|
2005-01-02 22:35:31 +00:00
|
|
|
{
|
2005-01-12 03:25:57 +00:00
|
|
|
int *input;
|
|
|
|
size_t i;
|
2005-01-02 22:35:31 +00:00
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
if (output_len == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
input = (int *)nmalloc(output_len * sizeof(int));
|
2006-12-02 23:39:16 +00:00
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
for (i = 0; i < output_len; i++)
|
|
|
|
input[i] = (int)output[i];
|
2006-12-02 23:39:16 +00:00
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
unget_input(input, output_len);
|
2006-12-02 23:39:16 +00:00
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
free(input);
|
2005-01-02 22:35:31 +00:00
|
|
|
}
|
|
|
|
|
2005-01-12 03:25:57 +00:00
|
|
|
/* Read in a stream of characters verbatim, and return the length of the
|
2004-12-04 17:41:52 +00:00
|
|
|
* 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
|
2005-08-10 21:22:15 +00:00
|
|
|
* them in verbatim, and turn the keypad off if necessary so that we
|
|
|
|
* don't get extended keypad values. */
|
2004-12-04 17:41:52 +00:00
|
|
|
if (ISSET(PRESERVE))
|
|
|
|
disable_flow_control();
|
2005-08-10 21:22:15 +00:00
|
|
|
if (!ISSET(REBIND_KEYPAD))
|
|
|
|
keypad(win, FALSE);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-12-27 11:20:20 +00:00
|
|
|
/* Read in one keycode, or one or two escapes. */
|
2004-12-04 17:41:52 +00:00
|
|
|
retval = parse_verbatim_kbinput(win, kbinput_len);
|
2004-05-28 17:23:33 +00:00
|
|
|
|
2016-12-27 11:20:20 +00:00
|
|
|
/* If the code is invalid in the current mode, discard it. */
|
|
|
|
if ((*retval == '\n' && as_an_at) || (*retval == '\0' && !as_an_at)) {
|
|
|
|
*kbinput_len = 0;
|
|
|
|
beep();
|
|
|
|
}
|
|
|
|
|
2004-05-28 17:23:33 +00:00
|
|
|
/* Turn flow control characters back on if necessary and turn the
|
2005-08-10 21:22:15 +00:00
|
|
|
* keypad back on if necessary now that we're done. */
|
2004-05-28 17:23:33 +00:00
|
|
|
if (ISSET(PRESERVE))
|
|
|
|
enable_flow_control();
|
2016-07-16 20:11:14 +00:00
|
|
|
/* Use the global window pointers, because a resize may have freed
|
|
|
|
* the data that the win parameter points to. */
|
|
|
|
if (!ISSET(REBIND_KEYPAD)) {
|
|
|
|
keypad(edit, TRUE);
|
|
|
|
keypad(bottomwin, TRUE);
|
|
|
|
}
|
2004-05-28 17:23:33 +00:00
|
|
|
|
2004-12-04 17:41:52 +00:00
|
|
|
return retval;
|
2004-05-28 17:23:33 +00:00
|
|
|
}
|
|
|
|
|
2016-11-18 13:14:36 +00:00
|
|
|
/* Read in one control character (or an iTerm/Eterm/rxvt double Escape),
|
|
|
|
* or convert a series of six digits into a Unicode codepoint. Return
|
|
|
|
* in count either 1 (for a control character or the first byte of a
|
|
|
|
* multibyte sequence), or 2 (for an iTerm/Eterm/rxvt double Escape). */
|
2016-07-16 17:44:24 +00:00
|
|
|
int *parse_verbatim_kbinput(WINDOW *win, size_t *count)
|
2004-05-28 17:23:33 +00:00
|
|
|
{
|
2016-07-16 17:44:24 +00:00
|
|
|
int *kbinput;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Read in the first code. */
|
2014-05-13 20:14:01 +00:00
|
|
|
while ((kbinput = get_input(win, 1)) == NULL)
|
|
|
|
;
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-07-25 15:28:54 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-07-16 20:11:14 +00:00
|
|
|
/* When the window was resized, abort and return nothing. */
|
|
|
|
if (*kbinput == KEY_WINCH) {
|
|
|
|
free(kbinput);
|
2016-07-16 17:44:24 +00:00
|
|
|
*count = 0;
|
2016-07-16 20:11:14 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2016-07-25 15:28:54 +00:00
|
|
|
#endif
|
2016-07-16 20:11:14 +00:00
|
|
|
|
2006-05-27 17:39:19 +00:00
|
|
|
#ifdef ENABLE_UTF8
|
2006-05-28 16:25:15 +00:00
|
|
|
if (using_utf8()) {
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Check whether the first code is a valid starter digit: 0 or 1. */
|
2016-07-24 10:34:56 +00:00
|
|
|
long uni = get_unicode_kbinput(win, *kbinput);
|
2006-05-28 16:25:15 +00:00
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* If the first code isn't the digit 0 nor 1, put it back. */
|
2006-05-28 16:25:15 +00:00
|
|
|
if (uni != ERR)
|
|
|
|
unget_input(kbinput, 1);
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Otherwise, continue reading in digits until we have a complete
|
|
|
|
* Unicode value, and put back the corresponding byte(s). */
|
2006-05-28 16:25:15 +00:00
|
|
|
else {
|
|
|
|
char *uni_mb;
|
|
|
|
int uni_mb_len, *seq, i;
|
|
|
|
|
|
|
|
while (uni == ERR) {
|
2016-07-17 10:00:33 +00:00
|
|
|
free(kbinput);
|
2014-05-13 20:14:01 +00:00
|
|
|
while ((kbinput = get_input(win, 1)) == NULL)
|
|
|
|
;
|
2016-07-24 10:34:56 +00:00
|
|
|
uni = get_unicode_kbinput(win, *kbinput);
|
2006-05-28 16:25:15 +00:00
|
|
|
}
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Convert the Unicode value to a multibyte sequence. */
|
2006-05-28 16:25:15 +00:00
|
|
|
uni_mb = make_mbchar(uni, &uni_mb_len);
|
2006-05-27 17:39:19 +00:00
|
|
|
|
2006-05-28 16:25:15 +00:00
|
|
|
seq = (int *)nmalloc(uni_mb_len * sizeof(int));
|
2006-05-27 17:39:19 +00:00
|
|
|
|
2006-05-28 16:25:15 +00:00
|
|
|
for (i = 0; i < uni_mb_len; i++)
|
|
|
|
seq[i] = (unsigned char)uni_mb[i];
|
2004-05-28 17:23:33 +00:00
|
|
|
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Insert the multibyte sequence into the input buffer. */
|
2006-05-28 16:25:15 +00:00
|
|
|
unget_input(seq, uni_mb_len);
|
2006-05-27 15:52:26 +00:00
|
|
|
|
2006-05-28 16:25:15 +00:00
|
|
|
free(seq);
|
|
|
|
free(uni_mb);
|
2004-12-04 17:41:52 +00:00
|
|
|
}
|
2006-05-28 16:25:15 +00:00
|
|
|
} else
|
2006-05-28 17:09:49 +00:00
|
|
|
#endif /* ENABLE_UTF8 */
|
2016-08-01 12:05:42 +00:00
|
|
|
/* Put back the first code. */
|
2006-05-28 16:25:15 +00:00
|
|
|
unget_input(kbinput, 1);
|
2004-12-04 17:41:52 +00:00
|
|
|
|
2006-12-02 17:22:21 +00:00
|
|
|
free(kbinput);
|
|
|
|
|
2016-07-16 17:44:24 +00:00
|
|
|
*count = 1;
|
2004-05-28 17:23:33 +00:00
|
|
|
|
2016-11-18 13:14:36 +00:00
|
|
|
/* If this is an iTerm/Eterm/rxvt double escape, take both Escapes. */
|
2016-07-16 17:44:24 +00:00
|
|
|
if (key_buffer_len > 3 && *key_buffer == ESC_CODE &&
|
|
|
|
key_buffer[1] == ESC_CODE && key_buffer[2] == '[')
|
|
|
|
*count = 2;
|
|
|
|
|
|
|
|
return get_input(NULL, *count);
|
2004-05-28 17:23:33 +00:00
|
|
|
}
|
|
|
|
|
2003-11-28 19:47:42 +00:00
|
|
|
#ifndef DISABLE_MOUSE
|
2007-12-08 04:21:15 +00:00
|
|
|
/* Handle any mouse event that may have occurred. We currently handle
|
2007-05-29 17:01:12 +00:00
|
|
|
* releases/clicks of the first mouse button. If allow_shortcuts is
|
|
|
|
* TRUE, releasing/clicking on a visible shortcut will put back the
|
|
|
|
* keystroke associated with that shortcut. If NCURSES_MOUSE_VERSION is
|
|
|
|
* at least 2, we also currently handle presses of the fourth mouse
|
|
|
|
* button (upward rolls of the mouse wheel) by putting back the
|
|
|
|
* keystrokes to move up, and presses of the fifth mouse button
|
|
|
|
* (downward rolls of the mouse wheel) by putting back the keystrokes to
|
2007-12-08 04:21:15 +00:00
|
|
|
* move down. We also store the coordinates of a mouse event that needs
|
|
|
|
* to be handled in mouse_x and mouse_y, relative to the entire screen.
|
|
|
|
* Return -1 on error, 0 if the mouse event needs to be handled, 1 if
|
|
|
|
* it's been handled by putting back keystrokes that need to be handled.
|
|
|
|
* or 2 if it's been ignored. Assume that KEY_MOUSE has already been
|
|
|
|
* read in. */
|
2007-05-20 23:41:56 +00:00
|
|
|
int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
|
2003-11-28 19:47:42 +00:00
|
|
|
{
|
|
|
|
MEVENT mevent;
|
2007-12-08 04:21:15 +00:00
|
|
|
bool in_bottomwin;
|
2008-03-05 07:34:01 +00:00
|
|
|
subnfunc *f;
|
2003-11-28 19:47:42 +00:00
|
|
|
|
|
|
|
*mouse_x = -1;
|
|
|
|
*mouse_y = -1;
|
|
|
|
|
|
|
|
/* First, get the actual mouse event. */
|
|
|
|
if (getmouse(&mevent) == ERR)
|
2007-05-20 23:41:56 +00:00
|
|
|
return -1;
|
2003-11-28 19:47:42 +00:00
|
|
|
|
2007-05-20 23:41:56 +00:00
|
|
|
/* Save the screen coordinates where the mouse event took place. */
|
2016-10-20 08:44:29 +00:00
|
|
|
*mouse_x = mevent.x - margin;
|
2007-05-20 23:41:56 +00:00
|
|
|
*mouse_y = mevent.y;
|
2007-05-15 18:04:25 +00:00
|
|
|
|
2007-12-08 04:21:15 +00:00
|
|
|
in_bottomwin = wenclose(bottomwin, *mouse_y, *mouse_x);
|
|
|
|
|
2007-06-28 18:31:13 +00:00
|
|
|
/* Handle releases/clicks of the first mouse button. */
|
2007-05-29 17:01:12 +00:00
|
|
|
if (mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED)) {
|
2007-05-15 18:04:25 +00:00
|
|
|
/* If we're allowing shortcuts, the current shortcut list is
|
|
|
|
* being displayed on the last two lines of the screen, and the
|
2007-05-29 17:01:12 +00:00
|
|
|
* first mouse button was released on/clicked inside it, we need
|
|
|
|
* to figure out which shortcut was released on/clicked and put
|
|
|
|
* back the equivalent keystroke(s) for it. */
|
2007-12-08 04:21:15 +00:00
|
|
|
if (allow_shortcuts && !ISSET(NO_HELP) && in_bottomwin) {
|
2007-05-22 17:20:28 +00:00
|
|
|
int i;
|
|
|
|
/* The width of all the shortcuts, except for the last
|
|
|
|
* two, in the shortcut list in bottomwin. */
|
|
|
|
int j;
|
2014-05-09 11:44:17 +00:00
|
|
|
/* The calculated index number of the clicked item. */
|
2016-08-27 08:12:05 +00:00
|
|
|
size_t number;
|
|
|
|
/* The number of available shortcuts in the current menu. */
|
2007-05-15 18:04:25 +00:00
|
|
|
|
2007-12-08 04:21:15 +00:00
|
|
|
/* Translate the mouse event coordinates so that they're
|
|
|
|
* relative to bottomwin. */
|
|
|
|
wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE);
|
|
|
|
|
|
|
|
/* Handle releases/clicks of the first mouse button on the
|
|
|
|
* statusbar elsewhere. */
|
|
|
|
if (*mouse_y == 0) {
|
|
|
|
/* Restore the untranslated mouse event coordinates, so
|
|
|
|
* that they're relative to the entire screen again. */
|
2016-10-20 08:44:29 +00:00
|
|
|
*mouse_x = mevent.x - margin;
|
2007-12-08 04:21:15 +00:00
|
|
|
*mouse_y = mevent.y;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2007-05-22 17:20:28 +00:00
|
|
|
|
2016-08-27 08:03:34 +00:00
|
|
|
/* Determine how many shortcuts are being shown. */
|
2016-08-27 08:12:05 +00:00
|
|
|
number = length_of_list(currmenu);
|
2004-08-26 01:43:16 +00:00
|
|
|
|
2016-08-27 08:12:05 +00:00
|
|
|
if (number > MAIN_VISIBLE)
|
|
|
|
number = MAIN_VISIBLE;
|
2006-04-18 16:13:35 +00:00
|
|
|
|
2007-05-15 18:04:25 +00:00
|
|
|
/* Calculate the width of all of the shortcuts in the list
|
|
|
|
* except for the last two, which are longer by (COLS % i)
|
|
|
|
* columns so as to not waste space. */
|
2016-08-27 08:12:05 +00:00
|
|
|
if (number < 2)
|
2007-05-15 18:04:25 +00:00
|
|
|
i = COLS / (MAIN_VISIBLE / 2);
|
|
|
|
else
|
2016-08-27 08:12:05 +00:00
|
|
|
i = COLS / ((number / 2) + (number % 2));
|
2007-05-15 18:04:25 +00:00
|
|
|
|
2014-05-09 11:44:17 +00:00
|
|
|
/* Calculate the one-based index in the shortcut list. */
|
|
|
|
j = (*mouse_x / i) * 2 + *mouse_y;
|
2007-05-15 18:04:25 +00:00
|
|
|
|
2014-05-09 11:44:17 +00:00
|
|
|
/* Adjust the index if we hit the last two wider ones. */
|
2016-08-27 08:12:05 +00:00
|
|
|
if ((j > number) && (*mouse_x % i < COLS % i))
|
2007-05-15 18:04:25 +00:00
|
|
|
j -= 2;
|
2014-04-16 08:24:32 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Calculated %i as index in shortcut list, currmenu = %x.\n", j, currmenu);
|
|
|
|
#endif
|
2007-05-29 17:01:12 +00:00
|
|
|
/* Ignore releases/clicks of the first mouse button beyond
|
|
|
|
* the last shortcut. */
|
2016-08-27 08:12:05 +00:00
|
|
|
if (j > number)
|
2007-05-20 23:41:56 +00:00
|
|
|
return 2;
|
2007-05-15 18:04:25 +00:00
|
|
|
|
2014-04-16 08:24:32 +00:00
|
|
|
/* Go through the list of functions to determine which
|
|
|
|
* shortcut in the current menu we released/clicked on. */
|
2014-05-09 11:44:17 +00:00
|
|
|
for (f = allfuncs; f != NULL; f = f->next) {
|
2014-06-27 20:01:27 +00:00
|
|
|
if ((f->menus & currmenu) == 0)
|
2014-05-09 11:44:17 +00:00
|
|
|
continue;
|
|
|
|
if (first_sc_for(currmenu, f->scfunc) == NULL)
|
2014-06-27 20:01:27 +00:00
|
|
|
continue;
|
2014-05-09 11:44:17 +00:00
|
|
|
/* Tick off an actually shown shortcut. */
|
|
|
|
j -= 1;
|
2014-04-16 08:24:32 +00:00
|
|
|
if (j == 0)
|
|
|
|
break;
|
2008-03-11 04:52:57 +00:00
|
|
|
}
|
2014-04-16 08:24:32 +00:00
|
|
|
#ifdef DEBUG
|
2014-04-21 13:07:18 +00:00
|
|
|
fprintf(stderr, "Stopped on func %ld present in menus %x\n", (long)f->scfunc, f->menus);
|
2014-04-16 08:24:32 +00:00
|
|
|
#endif
|
2008-03-11 04:52:57 +00:00
|
|
|
|
2014-04-16 08:24:32 +00:00
|
|
|
/* And put the corresponding key into the keyboard buffer. */
|
2008-03-05 07:34:01 +00:00
|
|
|
if (f != NULL) {
|
2014-06-27 20:01:27 +00:00
|
|
|
const sc *s = first_sc_for(currmenu, f->scfunc);
|
2016-07-24 19:49:07 +00:00
|
|
|
unget_kbinput(s->keycode, s->meta);
|
2007-05-15 18:04:25 +00:00
|
|
|
}
|
2014-06-11 18:04:36 +00:00
|
|
|
return 1;
|
2007-05-15 18:04:25 +00:00
|
|
|
} else
|
2007-05-29 17:01:12 +00:00
|
|
|
/* Handle releases/clicks of the first mouse button that
|
|
|
|
* aren't on the current shortcut list elsewhere. */
|
2007-05-20 23:41:56 +00:00
|
|
|
return 0;
|
2003-11-28 19:47:42 +00:00
|
|
|
}
|
2007-05-15 18:04:25 +00:00
|
|
|
#if NCURSES_MOUSE_VERSION >= 2
|
|
|
|
/* Handle presses of the fourth mouse button (upward rolls of the
|
2007-05-20 23:41:56 +00:00
|
|
|
* mouse wheel) and presses of the fifth mouse button (downward
|
|
|
|
* rolls of the mouse wheel) . */
|
|
|
|
else if (mevent.bstate & (BUTTON4_PRESSED | BUTTON5_PRESSED)) {
|
2007-12-08 16:59:13 +00:00
|
|
|
bool in_edit = wenclose(edit, *mouse_y, *mouse_x);
|
2007-05-20 23:41:56 +00:00
|
|
|
|
2007-12-08 04:21:15 +00:00
|
|
|
if (in_bottomwin)
|
|
|
|
/* Translate the mouse event coordinates so that they're
|
|
|
|
* relative to bottomwin. */
|
|
|
|
wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE);
|
2007-05-22 17:20:28 +00:00
|
|
|
|
2007-12-08 04:21:15 +00:00
|
|
|
if (in_edit || (in_bottomwin && *mouse_y == 0)) {
|
2007-12-08 16:59:13 +00:00
|
|
|
int i;
|
|
|
|
|
2007-05-20 23:41:56 +00:00
|
|
|
/* One upward roll of the mouse wheel is equivalent to
|
|
|
|
* moving up three lines, and one downward roll of the mouse
|
|
|
|
* wheel is equivalent to moving down three lines. */
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
unget_kbinput((mevent.bstate & BUTTON4_PRESSED) ?
|
2016-07-23 12:01:38 +00:00
|
|
|
KEY_PPAGE : KEY_NPAGE, FALSE);
|
2007-05-20 23:41:56 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
/* Ignore presses of the fourth mouse button and presses of
|
|
|
|
* the fifth mouse buttons that aren't on the edit window or
|
|
|
|
* the statusbar. */
|
|
|
|
return 2;
|
2007-05-15 18:04:25 +00:00
|
|
|
}
|
|
|
|
#endif
|
2007-06-28 16:38:00 +00:00
|
|
|
|
|
|
|
/* Ignore all other mouse events. */
|
|
|
|
return 2;
|
2003-11-28 19:47:42 +00:00
|
|
|
}
|
2004-08-25 15:39:10 +00:00
|
|
|
#endif /* !DISABLE_MOUSE */
|
|
|
|
|
2014-04-14 09:22:29 +00:00
|
|
|
/* Return the shortcut that corresponds to the values of kbinput (the
|
|
|
|
* key itself) and meta_key (whether the key is a meta sequence). The
|
|
|
|
* returned shortcut will be the first in the list that corresponds to
|
|
|
|
* the given sequence. */
|
2014-07-01 10:41:10 +00:00
|
|
|
const sc *get_shortcut(int *kbinput)
|
2004-08-25 15:39:10 +00:00
|
|
|
{
|
2008-03-05 07:34:01 +00:00
|
|
|
sc *s;
|
2004-08-25 15:39:10 +00:00
|
|
|
|
2004-11-27 06:43:06 +00:00
|
|
|
#ifdef DEBUG
|
2016-07-18 10:44:34 +00:00
|
|
|
fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s -- ",
|
|
|
|
*kbinput, meta_key ? "TRUE" : "FALSE");
|
2004-11-27 06:43:06 +00:00
|
|
|
#endif
|
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
for (s = sclist; s != NULL; s = s->next) {
|
2016-07-24 19:49:07 +00:00
|
|
|
if ((s->menus & currmenu) && *kbinput == s->keycode &&
|
2016-07-23 12:42:40 +00:00
|
|
|
meta_key == s->meta) {
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef DEBUG
|
2016-07-18 10:44:34 +00:00
|
|
|
fprintf (stderr, "matched seq '%s' (menu is %x from %x)\n",
|
|
|
|
s->keystr, currmenu, s->menus);
|
2008-03-05 07:34:01 +00:00
|
|
|
#endif
|
2005-01-08 06:16:19 +00:00
|
|
|
return s;
|
2004-08-25 15:39:10 +00:00
|
|
|
}
|
|
|
|
}
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef DEBUG
|
2016-07-18 10:44:34 +00:00
|
|
|
fprintf (stderr, "matched nothing\n");
|
2008-03-05 07:34:01 +00:00
|
|
|
#endif
|
2004-08-25 15:39:10 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-07-10 02:37:38 +00:00
|
|
|
/* Move to (x, y) in win, and display a line of n spaces with the
|
|
|
|
* current attributes. */
|
2017-01-12 16:48:33 +00:00
|
|
|
void blank_row(WINDOW *win, int y, int x, int n)
|
2005-07-10 02:37:38 +00:00
|
|
|
{
|
|
|
|
wmove(win, y, x);
|
2007-04-19 03:15:04 +00:00
|
|
|
|
2005-07-10 02:37:38 +00:00
|
|
|
for (; n > 0; n--)
|
|
|
|
waddch(win, ' ');
|
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Blank the first line of the top portion of the window. */
|
2004-05-18 01:20:36 +00:00
|
|
|
void blank_titlebar(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2017-01-12 16:48:33 +00:00
|
|
|
blank_row(topwin, 0, 0, COLS);
|
2002-09-06 20:35:28 +00:00
|
|
|
}
|
|
|
|
|
2006-07-28 17:06:27 +00:00
|
|
|
/* Blank all the lines of the middle portion of the window, i.e. the
|
2005-12-08 07:09:08 +00:00
|
|
|
* edit window. */
|
2000-06-06 05:53:49 +00:00
|
|
|
void blank_edit(void)
|
|
|
|
{
|
2017-01-12 16:48:33 +00:00
|
|
|
int row;
|
2007-04-19 03:15:04 +00:00
|
|
|
|
2017-01-12 16:48:33 +00:00
|
|
|
for (row = 0; row < editwinrows; row++)
|
|
|
|
blank_row(edit, row, 0, COLS);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Blank the first line of the bottom portion of the window. */
|
2000-06-06 05:53:49 +00:00
|
|
|
void blank_statusbar(void)
|
|
|
|
{
|
2017-01-12 16:48:33 +00:00
|
|
|
blank_row(bottomwin, 0, 0, COLS);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* If the NO_HELP flag isn't set, blank the last two lines of the bottom
|
|
|
|
* portion of the window. */
|
2005-03-17 17:56:48 +00:00
|
|
|
void blank_bottombars(void)
|
|
|
|
{
|
2016-08-15 17:44:49 +00:00
|
|
|
if (!ISSET(NO_HELP) && LINES > 4) {
|
2017-01-12 16:48:33 +00:00
|
|
|
blank_row(bottomwin, 1, 0, COLS);
|
|
|
|
blank_row(bottomwin, 2, 0, COLS);
|
2005-03-17 17:56:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Check if the number of keystrokes needed to blank the statusbar has
|
|
|
|
* been pressed. If so, blank the statusbar, unless constant cursor
|
2016-05-15 09:36:51 +00:00
|
|
|
* position display is on and we are in the editing screen. */
|
2004-09-30 22:07:21 +00:00
|
|
|
void check_statusblank(void)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2016-05-15 09:36:51 +00:00
|
|
|
if (statusblank == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
statusblank--;
|
|
|
|
|
|
|
|
/* When editing and 'constantshow' is active, skip the blanking. */
|
|
|
|
if (currmenu == MMAIN && ISSET(CONST_UPDATE))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (statusblank == 0) {
|
|
|
|
blank_statusbar();
|
|
|
|
wnoutrefresh(bottomwin);
|
|
|
|
reset_cursor();
|
|
|
|
wnoutrefresh(edit);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
2016-08-15 17:44:49 +00:00
|
|
|
|
|
|
|
/* If the subwindows overlap, make sure to show the edit window now. */
|
|
|
|
if (LINES == 1)
|
|
|
|
edit_refresh();
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
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
|
2016-06-14 17:56:16 +00:00
|
|
|
* extending for at most span columns. start_col is zero-based. span
|
|
|
|
* is one-based, so span == 0 means you get "" returned. The returned
|
2016-12-18 08:40:09 +00:00
|
|
|
* string is dynamically allocated, and should be freed. If isdata is
|
2004-12-23 17:43:27 +00:00
|
|
|
* TRUE, the caller might put "$" at the beginning or end of the line if
|
|
|
|
* it's too long. */
|
2016-06-14 17:56:16 +00:00
|
|
|
char *display_string(const char *buf, size_t start_col, size_t span,
|
2016-12-18 08:40:09 +00:00
|
|
|
bool isdata)
|
2003-09-16 01:16:49 +00:00
|
|
|
{
|
|
|
|
size_t start_index;
|
2004-12-24 15:45:36 +00:00
|
|
|
/* Index in buf of the first character shown. */
|
2003-09-16 01:16:49 +00:00
|
|
|
size_t column;
|
2004-12-24 15:45:36 +00:00
|
|
|
/* Screen column that start_index corresponds to. */
|
2003-09-16 01:16:49 +00:00
|
|
|
char *converted;
|
|
|
|
/* The string we return. */
|
|
|
|
size_t index;
|
|
|
|
/* Current position in converted. */
|
2005-01-12 03:25:57 +00:00
|
|
|
|
2016-12-18 08:40:09 +00:00
|
|
|
/* If this is data, make room for the "$" at the end of the line. */
|
|
|
|
if (isdata && !ISSET(SOFTWRAP) && strlenpt(buf) > start_col + span)
|
2016-06-14 17:56:16 +00:00
|
|
|
span--;
|
2005-01-05 06:09:34 +00:00
|
|
|
|
2016-06-14 17:56:16 +00:00
|
|
|
if (span == 0)
|
2003-09-16 01:16:49 +00:00
|
|
|
return mallocstrcpy(NULL, "");
|
|
|
|
|
|
|
|
start_index = actual_x(buf, start_col);
|
|
|
|
column = strnlenpt(buf, start_index);
|
2004-12-23 17:43:27 +00:00
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
assert(column <= start_col);
|
2004-12-23 17:43:27 +00:00
|
|
|
|
2016-06-05 10:53:02 +00:00
|
|
|
/* Allocate enough space to hold the entire converted buffer. */
|
|
|
|
converted = charalloc(strlen(buf) * (mb_cur_max() + tabsize) + 1);
|
2005-01-05 16:59:49 +00:00
|
|
|
|
2003-09-16 01:16:49 +00:00
|
|
|
index = 0;
|
2016-07-12 19:05:09 +00:00
|
|
|
#ifdef USING_OLD_NCURSES
|
2015-09-05 09:14:24 +00:00
|
|
|
seen_wide = FALSE;
|
2016-07-12 19:05:09 +00:00
|
|
|
#endif
|
2016-06-05 19:10:07 +00:00
|
|
|
buf += start_index;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
2016-06-05 19:10:07 +00:00
|
|
|
if (*buf != '\0' && *buf != '\t' &&
|
2016-12-18 08:40:09 +00:00
|
|
|
(column < start_col || (isdata && column > 0))) {
|
2016-06-05 19:10:07 +00:00
|
|
|
/* We don't display the complete first character as it starts to
|
2004-12-23 17:43:27 +00:00
|
|
|
* the left of the screen. */
|
2016-06-05 19:10:07 +00:00
|
|
|
if (is_cntrl_mbchar(buf)) {
|
2004-12-24 17:52:17 +00:00
|
|
|
if (column < start_col) {
|
2016-12-18 08:40:09 +00:00
|
|
|
converted[index++] = control_mbrep(buf, isdata);
|
2016-06-29 18:37:28 +00:00
|
|
|
start_col++;
|
2016-06-05 19:10:07 +00:00
|
|
|
buf += parse_mbchar(buf, NULL, NULL);
|
2004-12-23 17:43:27 +00:00
|
|
|
}
|
2005-01-03 06:56:38 +00:00
|
|
|
}
|
2005-07-17 02:40:07 +00:00
|
|
|
#ifdef ENABLE_UTF8
|
2016-06-05 19:10:07 +00:00
|
|
|
else if (using_utf8() && mbwidth(buf) == 2) {
|
2006-05-19 17:50:01 +00:00
|
|
|
if (column >= start_col) {
|
|
|
|
converted[index++] = ' ';
|
|
|
|
start_col++;
|
|
|
|
}
|
|
|
|
|
2005-01-05 06:09:34 +00:00
|
|
|
converted[index++] = ' ';
|
2004-12-27 23:35:25 +00:00
|
|
|
start_col++;
|
2005-01-12 03:25:57 +00:00
|
|
|
|
2016-06-05 19:10:07 +00:00
|
|
|
buf += parse_mbchar(buf, NULL, NULL);
|
2004-12-23 17:43:27 +00:00
|
|
|
}
|
2005-01-03 06:56:38 +00:00
|
|
|
#endif
|
2004-12-23 17:43:27 +00:00
|
|
|
}
|
|
|
|
|
2016-06-05 19:10:07 +00:00
|
|
|
while (*buf != '\0') {
|
2016-06-06 11:20:04 +00:00
|
|
|
int charlength, charwidth = 1;
|
2016-06-06 10:48:26 +00:00
|
|
|
|
2016-06-05 19:10:07 +00:00
|
|
|
if (*buf == ' ') {
|
2016-05-30 08:41:11 +00:00
|
|
|
/* Show a space as a visible character, or as a space. */
|
|
|
|
#ifndef NANO_TINY
|
|
|
|
if (ISSET(WHITESPACE_DISPLAY)) {
|
|
|
|
int i = whitespace_len[0];
|
|
|
|
|
|
|
|
while (i < whitespace_len[0] + whitespace_len[1])
|
|
|
|
converted[index++] = whitespace[i++];
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
converted[index++] = ' ';
|
|
|
|
start_col++;
|
2016-06-06 10:48:26 +00:00
|
|
|
buf++;
|
|
|
|
continue;
|
2016-06-05 19:10:07 +00:00
|
|
|
} else if (*buf == '\t') {
|
2016-05-30 08:45:46 +00:00
|
|
|
/* Show a tab as a visible character, or as as a space. */
|
2015-08-09 16:05:50 +00:00
|
|
|
#ifndef NANO_TINY
|
2005-03-10 22:52:21 +00:00
|
|
|
if (ISSET(WHITESPACE_DISPLAY)) {
|
2016-05-30 08:45:46 +00:00
|
|
|
int i = 0;
|
2005-03-10 22:52:21 +00:00
|
|
|
|
2016-05-30 08:45:46 +00:00
|
|
|
while (i < whitespace_len[0])
|
|
|
|
converted[index++] = whitespace[i++];
|
2005-03-10 22:52:21 +00:00
|
|
|
} else
|
2004-05-29 16:25:30 +00:00
|
|
|
#endif
|
2007-04-19 03:15:04 +00:00
|
|
|
converted[index++] = ' ';
|
2004-12-23 17:43:27 +00:00
|
|
|
start_col++;
|
2016-05-30 08:45:46 +00:00
|
|
|
/* Fill the tab up with the required number of spaces. */
|
2004-12-27 23:21:34 +00:00
|
|
|
while (start_col % tabsize != 0) {
|
2003-09-16 01:16:49 +00:00
|
|
|
converted[index++] = ' ';
|
2004-12-23 17:43:27 +00:00
|
|
|
start_col++;
|
|
|
|
}
|
2016-06-06 10:48:26 +00:00
|
|
|
buf++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-06-06 11:20:04 +00:00
|
|
|
charlength = length_of_char(buf, &charwidth);
|
2016-06-06 10:48:26 +00:00
|
|
|
|
2016-06-29 18:37:28 +00:00
|
|
|
/* If buf contains a control character, represent it. */
|
2016-06-06 10:48:26 +00:00
|
|
|
if (is_cntrl_mbchar(buf)) {
|
2003-09-16 01:16:49 +00:00
|
|
|
converted[index++] = '^';
|
2016-12-18 08:40:09 +00:00
|
|
|
converted[index++] = control_mbrep(buf, isdata);
|
2016-06-29 18:37:28 +00:00
|
|
|
start_col += 2;
|
2016-06-06 10:48:26 +00:00
|
|
|
buf += charlength;
|
|
|
|
continue;
|
|
|
|
}
|
2005-07-26 06:13:45 +00:00
|
|
|
|
2016-06-06 10:48:26 +00:00
|
|
|
/* If buf contains a valid non-control character, simply copy it. */
|
|
|
|
if (charlength > 0) {
|
|
|
|
for (; charlength > 0; charlength--)
|
|
|
|
converted[index++] = *(buf++);
|
2016-06-05 19:18:32 +00:00
|
|
|
|
2016-06-06 11:20:04 +00:00
|
|
|
start_col += charwidth;
|
2016-07-12 19:05:09 +00:00
|
|
|
#ifdef USING_OLD_NCURSES
|
2016-06-06 11:20:04 +00:00
|
|
|
if (charwidth > 1)
|
2016-06-05 19:18:32 +00:00
|
|
|
seen_wide = TRUE;
|
2016-07-12 19:05:09 +00:00
|
|
|
#endif
|
2016-06-06 10:48:26 +00:00
|
|
|
continue;
|
2004-12-23 17:43:27 +00:00
|
|
|
}
|
|
|
|
|
2016-06-06 10:48:26 +00:00
|
|
|
/* Represent an invalid sequence with the Replacement Character. */
|
|
|
|
converted[index++] = '\xEF';
|
|
|
|
converted[index++] = '\xBF';
|
|
|
|
converted[index++] = '\xBD';
|
|
|
|
|
|
|
|
start_col += 1;
|
|
|
|
buf++;
|
|
|
|
|
|
|
|
/* For invalid codepoints, skip extra bytes. */
|
|
|
|
if (charlength < -1)
|
|
|
|
buf += charlength + 7;
|
2003-09-16 01:16:49 +00:00
|
|
|
}
|
|
|
|
|
2006-10-29 21:14:53 +00:00
|
|
|
/* Null-terminate converted. */
|
2006-02-03 03:58:49 +00:00
|
|
|
converted[index] = '\0';
|
2005-01-05 19:05:04 +00:00
|
|
|
|
2016-06-14 17:56:16 +00:00
|
|
|
/* Make sure converted takes up no more than span columns. */
|
|
|
|
index = actual_x(converted, span);
|
2004-12-23 17:43:27 +00:00
|
|
|
null_at(&converted, index);
|
2005-01-05 19:05:04 +00:00
|
|
|
|
2004-12-23 17:43:27 +00:00
|
|
|
return converted;
|
2003-09-16 01:16:49 +00:00
|
|
|
}
|
|
|
|
|
2006-07-09 00:52:16 +00:00
|
|
|
/* If path is NULL, we're in normal editing mode, so display the current
|
|
|
|
* version of nano, the current filename, and whether the current file
|
|
|
|
* has been modified on the titlebar. If path isn't NULL, we're in the
|
|
|
|
* file browser, and path contains the directory to start the file
|
|
|
|
* browser in, so display the current version of nano and the contents
|
|
|
|
* of path on the titlebar. */
|
2003-02-13 22:25:01 +00:00
|
|
|
void titlebar(const char *path)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2016-04-29 08:42:20 +00:00
|
|
|
size_t verlen, prefixlen, pathlen, statelen;
|
|
|
|
/* The width of the different titlebar elements, in columns. */
|
|
|
|
size_t pluglen = 0;
|
|
|
|
/* The width that "Modified" would take up. */
|
|
|
|
size_t offset = 0;
|
|
|
|
/* The position at which the center part of the titlebar starts. */
|
|
|
|
const char *prefix = "";
|
|
|
|
/* What is shown before the path -- "File:", "DIR:", or "". */
|
|
|
|
const char *state = "";
|
|
|
|
/* The state of the current buffer -- "Modified", "View", or "". */
|
2016-12-17 20:54:36 +00:00
|
|
|
char *caption;
|
|
|
|
/* The presentable form of the pathname. */
|
2004-05-23 21:11:14 +00:00
|
|
|
|
2016-08-15 17:44:49 +00:00
|
|
|
/* If the screen is too small, there is no titlebar. */
|
|
|
|
if (topwin == NULL)
|
|
|
|
return;
|
|
|
|
|
2005-07-08 20:09:16 +00:00
|
|
|
assert(path != NULL || openfile->filename != NULL);
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2016-07-12 07:35:48 +00:00
|
|
|
wattron(topwin, interface_color_pair[TITLE_BAR]);
|
2006-07-02 18:29:49 +00:00
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
blank_titlebar();
|
2016-12-20 18:27:41 +00:00
|
|
|
as_an_at = FALSE;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2016-04-29 08:42:20 +00:00
|
|
|
/* Do as Pico: if there is not enough width available for all items,
|
|
|
|
* first sacrifice the version string, then eat up the side spaces,
|
|
|
|
* then sacrifice the prefix, and only then start dottifying. */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2016-04-29 08:42:20 +00:00
|
|
|
/* Figure out the path, prefix and state strings. */
|
2005-07-10 02:37:38 +00:00
|
|
|
#ifndef DISABLE_BROWSER
|
2004-05-23 21:11:14 +00:00
|
|
|
if (path != NULL)
|
|
|
|
prefix = _("DIR:");
|
|
|
|
else
|
|
|
|
#endif
|
2016-04-29 08:42:20 +00:00
|
|
|
{
|
|
|
|
if (openfile->filename[0] == '\0')
|
|
|
|
path = _("New Buffer");
|
|
|
|
else {
|
|
|
|
path = openfile->filename;
|
|
|
|
prefix = _("File:");
|
|
|
|
}
|
2004-05-23 21:11:14 +00:00
|
|
|
|
2016-04-29 08:42:20 +00:00
|
|
|
if (openfile->modified)
|
|
|
|
state = _("Modified");
|
|
|
|
else if (ISSET(VIEW_MODE))
|
|
|
|
state = _("View");
|
2004-12-23 17:43:27 +00:00
|
|
|
|
2016-04-29 08:42:20 +00:00
|
|
|
pluglen = strlenpt(_("Modified")) + 1;
|
|
|
|
}
|
2004-12-23 17:43:27 +00:00
|
|
|
|
2016-04-29 08:42:20 +00:00
|
|
|
/* Determine the widths of the four elements, including their padding. */
|
|
|
|
verlen = strlenpt(BRANDING) + 3;
|
|
|
|
prefixlen = strlenpt(prefix);
|
|
|
|
if (prefixlen > 0)
|
|
|
|
prefixlen++;
|
|
|
|
pathlen= strlenpt(path);
|
|
|
|
statelen = strlenpt(state) + 2;
|
|
|
|
if (statelen > 2) {
|
|
|
|
pathlen++;
|
|
|
|
pluglen = 0;
|
2004-05-23 21:11:14 +00:00
|
|
|
}
|
|
|
|
|
2016-04-29 08:42:20 +00:00
|
|
|
/* Only print the version message when there is room for it. */
|
|
|
|
if (verlen + prefixlen + pathlen + pluglen + statelen <= COLS)
|
|
|
|
mvwaddstr(topwin, 0, 2, BRANDING);
|
|
|
|
else {
|
|
|
|
verlen = 2;
|
|
|
|
/* If things don't fit yet, give up the placeholder. */
|
|
|
|
if (verlen + prefixlen + pathlen + pluglen + statelen > COLS)
|
|
|
|
pluglen = 0;
|
|
|
|
/* If things still don't fit, give up the side spaces. */
|
|
|
|
if (verlen + prefixlen + pathlen + pluglen + statelen > COLS) {
|
|
|
|
verlen = 0;
|
|
|
|
statelen -= 2;
|
2004-05-23 21:11:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-29 08:42:20 +00:00
|
|
|
/* If we have side spaces left, center the path name. */
|
|
|
|
if (verlen > 0)
|
|
|
|
offset = verlen + (COLS - (verlen + pluglen + statelen) -
|
|
|
|
(prefixlen + pathlen)) / 2;
|
2005-03-24 22:28:25 +00:00
|
|
|
|
2016-04-29 08:42:20 +00:00
|
|
|
/* Only print the prefix when there is room for it. */
|
|
|
|
if (verlen + prefixlen + pathlen + pluglen + statelen <= COLS) {
|
|
|
|
mvwaddstr(topwin, 0, offset, prefix);
|
|
|
|
if (prefixlen > 0)
|
|
|
|
waddstr(topwin, " ");
|
|
|
|
} else
|
|
|
|
wmove(topwin, 0, offset);
|
|
|
|
|
|
|
|
/* Print the full path if there's room; otherwise, dottify it. */
|
2016-12-17 20:54:36 +00:00
|
|
|
if (pathlen + pluglen + statelen <= COLS) {
|
|
|
|
caption = display_string(path, 0, pathlen, FALSE);
|
|
|
|
waddstr(topwin, caption);
|
|
|
|
free(caption);
|
|
|
|
} else if (5 + statelen <= COLS) {
|
2016-04-29 08:42:20 +00:00
|
|
|
waddstr(topwin, "...");
|
2016-12-17 20:54:36 +00:00
|
|
|
caption = display_string(path, 3 + pathlen - COLS + statelen,
|
2016-04-29 08:42:20 +00:00
|
|
|
COLS - statelen, FALSE);
|
2016-12-17 20:54:36 +00:00
|
|
|
waddstr(topwin, caption);
|
|
|
|
free(caption);
|
2004-05-23 21:11:14 +00:00
|
|
|
}
|
2001-04-30 11:28:46 +00:00
|
|
|
|
2016-04-29 08:42:20 +00:00
|
|
|
/* Right-align the state if there's room; otherwise, trim it. */
|
|
|
|
if (statelen > 0 && statelen <= COLS)
|
|
|
|
mvwaddstr(topwin, 0, COLS - statelen, state);
|
|
|
|
else if (statelen > 0)
|
|
|
|
mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
|
|
|
|
|
2016-07-12 07:35:48 +00:00
|
|
|
wattroff(topwin, interface_color_pair[TITLE_BAR]);
|
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();
|
2005-07-26 14:42:57 +00:00
|
|
|
wnoutrefresh(edit);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2016-04-30 15:31:43 +00:00
|
|
|
/* Display a normal message on the statusbar, quietly. */
|
|
|
|
void statusbar(const char *msg)
|
|
|
|
{
|
|
|
|
statusline(HUSH, msg);
|
|
|
|
}
|
|
|
|
|
2016-11-27 21:01:54 +00:00
|
|
|
/* Warn the user on the statusbar and pause for a moment, so that the
|
|
|
|
* message can be noticed and read. */
|
|
|
|
void warn_and_shortly_pause(const char *msg)
|
|
|
|
{
|
|
|
|
statusbar(msg);
|
|
|
|
beep();
|
|
|
|
napms(1800);
|
|
|
|
}
|
|
|
|
|
2016-05-04 10:18:21 +00:00
|
|
|
/* Display a message on the statusbar, and set suppress_cursorpos to
|
2005-06-28 19:49:15 +00:00
|
|
|
* TRUE, so that the message won't be immediately overwritten if
|
|
|
|
* constant cursor position display is on. */
|
2016-05-19 18:43:08 +00:00
|
|
|
void statusline(message_type importance, const char *msg, ...)
|
2004-05-18 01:20:36 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
2016-08-22 08:50:51 +00:00
|
|
|
char *compound, *message;
|
2017-01-08 11:05:42 +00:00
|
|
|
size_t start_col;
|
2016-08-15 20:25:52 +00:00
|
|
|
bool bracketed;
|
2015-08-09 16:05:50 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
|
|
|
|
|
|
|
|
UNSET(WHITESPACE_DISPLAY);
|
2005-10-27 03:35:42 +00:00
|
|
|
#endif
|
2004-05-18 01:20:36 +00:00
|
|
|
|
|
|
|
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(). */
|
2006-06-03 17:31:52 +00:00
|
|
|
if (isendwin()) {
|
2004-05-18 01:20:36 +00:00
|
|
|
vfprintf(stderr, msg, ap);
|
|
|
|
va_end(ap);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-19 18:43:08 +00:00
|
|
|
/* If there already was an alert message, ignore lesser ones. */
|
|
|
|
if ((lastmessage == ALERT && importance != ALERT) ||
|
|
|
|
(lastmessage == MILD && importance == HUSH))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Delay another alert message, to allow an earlier one to be noticed. */
|
|
|
|
if (lastmessage == ALERT)
|
2016-04-30 15:31:43 +00:00
|
|
|
napms(1200);
|
|
|
|
|
2016-05-19 18:43:08 +00:00
|
|
|
if (importance == ALERT)
|
2016-04-30 15:31:43 +00:00
|
|
|
beep();
|
2016-05-19 18:43:08 +00:00
|
|
|
|
|
|
|
lastmessage = importance;
|
2016-04-30 15:31:43 +00:00
|
|
|
|
2016-02-06 11:18:27 +00:00
|
|
|
/* Turn the cursor off while fiddling in the statusbar. */
|
|
|
|
curs_set(0);
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
blank_statusbar();
|
|
|
|
|
2016-08-22 08:50:51 +00:00
|
|
|
/* Construct the message out of all the arguments. */
|
|
|
|
compound = charalloc(mb_cur_max() * (COLS + 1));
|
|
|
|
vsnprintf(compound, mb_cur_max() * (COLS + 1), msg, ap);
|
2005-10-27 03:35:42 +00:00
|
|
|
va_end(ap);
|
2016-08-22 08:50:51 +00:00
|
|
|
message = display_string(compound, 0, COLS, FALSE);
|
|
|
|
free(compound);
|
2015-08-09 16:05:50 +00:00
|
|
|
|
2017-01-08 11:05:42 +00:00
|
|
|
start_col = (COLS - strlenpt(message)) / 2;
|
|
|
|
bracketed = (start_col > 1);
|
2004-05-18 01:20:36 +00:00
|
|
|
|
2017-01-08 11:05:42 +00:00
|
|
|
wmove(bottomwin, 0, (bracketed ? start_col - 2 : start_col));
|
2016-07-12 07:35:48 +00:00
|
|
|
wattron(bottomwin, interface_color_pair[STATUS_BAR]);
|
2016-08-15 20:25:52 +00:00
|
|
|
if (bracketed)
|
|
|
|
waddstr(bottomwin, "[ ");
|
2016-08-22 08:50:51 +00:00
|
|
|
waddstr(bottomwin, message);
|
|
|
|
free(message);
|
2016-08-15 20:25:52 +00:00
|
|
|
if (bracketed)
|
|
|
|
waddstr(bottomwin, " ]");
|
2016-07-12 07:35:48 +00:00
|
|
|
wattroff(bottomwin, interface_color_pair[STATUS_BAR]);
|
2016-02-23 12:37:10 +00:00
|
|
|
|
2016-05-23 19:34:02 +00:00
|
|
|
/* Push the message to the screen straightaway. */
|
2005-10-27 03:35:42 +00:00
|
|
|
wnoutrefresh(bottomwin);
|
2016-05-23 19:34:02 +00:00
|
|
|
doupdate();
|
2004-05-18 01:20:36 +00:00
|
|
|
|
2016-05-04 10:18:21 +00:00
|
|
|
suppress_cursorpos = TRUE;
|
2005-06-17 22:33:15 +00:00
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-08-22 08:50:51 +00:00
|
|
|
if (old_whitespace)
|
|
|
|
SET(WHITESPACE_DISPLAY);
|
|
|
|
|
|
|
|
/* If doing quick blanking, blank the statusbar after just one keystroke.
|
|
|
|
* Otherwise, blank it after twenty-six keystrokes, as Pico does. */
|
2016-05-15 08:57:25 +00:00
|
|
|
if (ISSET(QUICK_BLANK))
|
|
|
|
statusblank = 1;
|
|
|
|
else
|
2005-06-17 19:06:25 +00:00
|
|
|
#endif
|
2016-05-15 08:57:25 +00:00
|
|
|
statusblank = 26;
|
2004-05-18 01:20:36 +00:00
|
|
|
}
|
|
|
|
|
2015-12-04 21:11:10 +00:00
|
|
|
/* Display the shortcut list corresponding to menu on the last two rows
|
|
|
|
* of the bottom portion of the window. */
|
2008-03-05 07:34:01 +00:00
|
|
|
void bottombars(int menu)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2016-08-27 08:12:05 +00:00
|
|
|
size_t number, itemwidth, i;
|
2008-03-05 07:34:01 +00:00
|
|
|
subnfunc *f;
|
|
|
|
const sc *s;
|
2002-02-15 19:17:02 +00:00
|
|
|
|
2015-04-07 14:16:07 +00:00
|
|
|
/* Set the global variable to the given menu. */
|
|
|
|
currmenu = menu;
|
|
|
|
|
2016-08-15 17:44:49 +00:00
|
|
|
if (ISSET(NO_HELP) || LINES < 5)
|
2000-06-06 05:53:49 +00:00
|
|
|
return;
|
|
|
|
|
2016-08-27 08:03:34 +00:00
|
|
|
/* Determine how many shortcuts there are to show. */
|
2016-08-27 08:12:05 +00:00
|
|
|
number = length_of_list(menu);
|
2002-05-12 19:52:15 +00:00
|
|
|
|
2016-08-27 08:12:05 +00:00
|
|
|
if (number > MAIN_VISIBLE)
|
|
|
|
number = MAIN_VISIBLE;
|
2004-05-13 17:28:03 +00:00
|
|
|
|
2016-08-15 10:55:03 +00:00
|
|
|
/* Compute the width of each keyname-plus-explanation pair. */
|
2016-08-27 08:12:05 +00:00
|
|
|
itemwidth = COLS / ((number / 2) + (number % 2));
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2016-08-15 10:55:03 +00:00
|
|
|
/* If there is no room, don't print anything. */
|
2016-08-27 08:12:05 +00:00
|
|
|
if (itemwidth == 0)
|
2016-08-15 10:55:03 +00:00
|
|
|
return;
|
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
blank_bottombars();
|
2001-06-14 02:54:22 +00:00
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef DEBUG
|
2016-08-27 08:12:05 +00:00
|
|
|
fprintf(stderr, "In bottombars, number of items == \"%d\"\n", (int) number);
|
2008-03-05 07:34:01 +00:00
|
|
|
#endif
|
2005-05-02 21:48:34 +00:00
|
|
|
|
2016-08-27 08:12:05 +00:00
|
|
|
for (f = allfuncs, i = 0; i < number && f != NULL; f = f->next) {
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef DEBUG
|
2014-06-27 20:01:27 +00:00
|
|
|
fprintf(stderr, "Checking menu items....");
|
2008-03-05 07:34:01 +00:00
|
|
|
#endif
|
2014-06-27 20:01:27 +00:00
|
|
|
if ((f->menus & menu) == 0)
|
2008-03-05 07:34:01 +00:00
|
|
|
continue;
|
2004-10-25 15:00:38 +00:00
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef DEBUG
|
2014-06-27 20:01:27 +00:00
|
|
|
fprintf(stderr, "found one! f->menus = %x, desc = \"%s\"\n", f->menus, f->desc);
|
2008-03-05 07:34:01 +00:00
|
|
|
#endif
|
2014-06-27 20:01:27 +00:00
|
|
|
s = first_sc_for(menu, f->scfunc);
|
|
|
|
if (s == NULL) {
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Whoops, guess not, no shortcut key found for func!\n");
|
|
|
|
#endif
|
2014-06-27 20:01:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
2016-08-27 08:12:05 +00:00
|
|
|
|
|
|
|
wmove(bottomwin, 1 + i % 2, (i / 2) * itemwidth);
|
2008-03-05 07:34:01 +00:00
|
|
|
#ifdef DEBUG
|
2014-06-27 20:01:27 +00:00
|
|
|
fprintf(stderr, "Calling onekey with keystr \"%s\" and desc \"%s\"\n", s->keystr, f->desc);
|
2008-03-05 07:34:01 +00:00
|
|
|
#endif
|
2016-08-27 08:12:05 +00:00
|
|
|
onekey(s->keystr, _(f->desc), itemwidth + (COLS % itemwidth));
|
2014-06-27 20:01:27 +00:00
|
|
|
i++;
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
2001-04-30 11:28:46 +00:00
|
|
|
|
2016-10-12 11:56:48 +00:00
|
|
|
/* Defeat a VTE bug by moving the cursor and forcing a screen update. */
|
|
|
|
wmove(bottomwin, 0, 0);
|
2004-05-23 21:11:14 +00:00
|
|
|
wnoutrefresh(bottomwin);
|
2016-10-12 11:56:48 +00:00
|
|
|
doupdate();
|
|
|
|
|
2004-05-23 21:11:14 +00:00
|
|
|
reset_cursor();
|
2005-07-26 14:42:57 +00:00
|
|
|
wnoutrefresh(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
|
2016-03-23 20:21:36 +00:00
|
|
|
* to write at most length characters, even if length is very small and
|
2004-05-23 21:11:14 +00:00
|
|
|
* keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
|
|
|
|
* the whole string! We do not bother padding the entry with blanks. */
|
2016-03-23 20:21:36 +00:00
|
|
|
void onekey(const char *keystroke, const char *desc, int length)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2005-01-07 22:37:01 +00:00
|
|
|
assert(keystroke != NULL && desc != NULL);
|
|
|
|
|
2016-07-12 07:35:48 +00:00
|
|
|
wattron(bottomwin, interface_color_pair[KEY_COMBO]);
|
2016-03-23 20:21:36 +00:00
|
|
|
waddnstr(bottomwin, keystroke, actual_x(keystroke, length));
|
2016-07-12 07:35:48 +00:00
|
|
|
wattroff(bottomwin, interface_color_pair[KEY_COMBO]);
|
2004-12-24 00:43:41 +00:00
|
|
|
|
2016-03-23 20:21:36 +00:00
|
|
|
length -= strlenpt(keystroke) + 1;
|
2004-12-24 00:43:41 +00:00
|
|
|
|
2016-03-23 20:21:36 +00:00
|
|
|
if (length > 0) {
|
2002-09-06 20:35:28 +00:00
|
|
|
waddch(bottomwin, ' ');
|
2016-07-12 07:35:48 +00:00
|
|
|
wattron(bottomwin, interface_color_pair[FUNCTION_TAG]);
|
2016-03-23 20:21:36 +00:00
|
|
|
waddnstr(bottomwin, desc, actual_x(desc, length));
|
2016-07-12 07:35:48 +00:00
|
|
|
wattroff(bottomwin, interface_color_pair[FUNCTION_TAG]);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-23 20:04:33 +00:00
|
|
|
/* Redetermine current_y from the position of current relative to edittop,
|
|
|
|
* and put the cursor in the edit window at (current_y, current_x). */
|
2002-08-21 16:10:37 +00:00
|
|
|
void reset_cursor(void)
|
|
|
|
{
|
2016-03-23 19:48:44 +00:00
|
|
|
size_t xpt = xplustabs();
|
2006-05-26 03:02:50 +00:00
|
|
|
|
2014-06-09 20:26:54 +00:00
|
|
|
#ifndef NANO_TINY
|
2009-08-17 07:52:10 +00:00
|
|
|
if (ISSET(SOFTWRAP)) {
|
2016-03-23 20:04:33 +00:00
|
|
|
filestruct *line = openfile->edittop;
|
2009-11-11 06:00:33 +00:00
|
|
|
openfile->current_y = 0;
|
|
|
|
|
2016-03-23 20:04:33 +00:00
|
|
|
while (line != NULL && line != openfile->current) {
|
2016-10-20 08:44:29 +00:00
|
|
|
openfile->current_y += strlenpt(line->data) / editwincols + 1;
|
2016-03-23 20:04:33 +00:00
|
|
|
line = line->next;
|
|
|
|
}
|
2016-10-20 08:44:29 +00:00
|
|
|
openfile->current_y += xpt / editwincols;
|
2016-03-23 20:04:33 +00:00
|
|
|
|
2009-08-17 07:52:10 +00:00
|
|
|
if (openfile->current_y < editwinrows)
|
2016-10-20 08:44:29 +00:00
|
|
|
wmove(edit, openfile->current_y, xpt % editwincols + margin);
|
2014-06-09 20:26:54 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2009-08-17 07:52:10 +00:00
|
|
|
openfile->current_y = openfile->current->lineno -
|
2016-03-23 20:04:33 +00:00
|
|
|
openfile->edittop->lineno;
|
2009-08-17 07:52:10 +00:00
|
|
|
|
|
|
|
if (openfile->current_y < editwinrows)
|
2016-10-20 08:44:29 +00:00
|
|
|
wmove(edit, openfile->current_y, xpt - get_page_start(xpt) + margin);
|
2009-08-17 07:52:10 +00:00
|
|
|
}
|
2002-08-21 16:10:37 +00:00
|
|
|
}
|
2002-07-19 01:08:59 +00:00
|
|
|
|
2005-10-27 20:10:45 +00:00
|
|
|
/* edit_draw() takes care of the job of actually painting a line into
|
2017-01-12 17:00:54 +00:00
|
|
|
* the edit window. fileptr is the line to be painted, at row row of
|
2005-10-27 20:10:45 +00:00
|
|
|
* the window. converted is the actual string to be written to the
|
|
|
|
* window, with tabs and control characters replaced by strings of
|
2017-01-08 09:20:57 +00:00
|
|
|
* regular characters. from_col is the column number of the first
|
2005-10-27 20:10:45 +00:00
|
|
|
* character of this page. That is, the first character of converted
|
2017-01-08 09:20:57 +00:00
|
|
|
* corresponds to character number actual_x(fileptr->data, from_col) of the
|
2005-10-27 20:10:45 +00:00
|
|
|
* line. */
|
2017-01-09 17:25:25 +00:00
|
|
|
void edit_draw(filestruct *fileptr, const char *converted,
|
2017-01-12 17:00:54 +00:00
|
|
|
int row, size_t from_col)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2014-04-04 11:59:03 +00:00
|
|
|
#if !defined(NANO_TINY) || !defined(DISABLE_COLOR)
|
2017-01-08 09:20:57 +00:00
|
|
|
size_t from_x = actual_x(fileptr->data, from_col);
|
2003-09-16 01:16:49 +00:00
|
|
|
/* The position in fileptr->data of the leftmost character
|
|
|
|
* that displays at least partially on the window. */
|
2017-01-08 09:20:57 +00:00
|
|
|
size_t till_x = actual_x(fileptr->data, from_col + editwincols - 1) + 1;
|
2003-09-16 01:16:49 +00:00
|
|
|
/* The position in fileptr->data of the first character that is
|
2017-01-08 20:31:49 +00:00
|
|
|
* completely off the window to the right. Note that till_x
|
|
|
|
* might be beyond the null terminator of the string. */
|
2001-12-02 04:55:44 +00:00
|
|
|
#endif
|
|
|
|
|
2005-07-13 20:18:46 +00:00
|
|
|
assert(openfile != NULL && fileptr != NULL && converted != NULL);
|
2016-10-20 08:44:29 +00:00
|
|
|
assert(strlenpt(converted) <= editwincols);
|
|
|
|
|
|
|
|
#ifdef ENABLE_LINENUMBERS
|
2017-01-08 20:31:49 +00:00
|
|
|
/* If line numbering is switched on, put a line number in front of
|
2016-10-21 12:31:37 +00:00
|
|
|
* the text -- but only for the parts that are not softwrapped. */
|
|
|
|
if (margin > 0) {
|
2016-10-20 08:07:48 +00:00
|
|
|
wattron(edit, interface_color_pair[LINE_NUMBER]);
|
2016-12-09 17:51:41 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-01-08 10:49:59 +00:00
|
|
|
if (ISSET(SOFTWRAP) && from_x != 0)
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwprintw(edit, row, 0, "%*s", margin - 1, " ");
|
2016-12-09 17:51:41 +00:00
|
|
|
else
|
|
|
|
#endif
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwprintw(edit, row, 0, "%*ld", margin - 1, (long)fileptr->lineno);
|
2016-10-20 08:07:48 +00:00
|
|
|
wattroff(edit, interface_color_pair[LINE_NUMBER]);
|
2016-10-20 08:44:29 +00:00
|
|
|
}
|
|
|
|
#endif
|
2003-09-16 01:16:49 +00:00
|
|
|
|
2017-01-12 17:00:54 +00:00
|
|
|
/* First simply write the converted line -- afterward we'll add colors
|
|
|
|
* and the marking highlight on just the pieces that need it. */
|
|
|
|
mvwaddstr(edit, row, margin, converted);
|
2014-06-04 16:02:51 +00:00
|
|
|
|
2016-07-12 19:05:09 +00:00
|
|
|
#ifdef USING_OLD_NCURSES
|
2014-06-04 16:02:51 +00:00
|
|
|
/* Tell ncurses to really redraw the line without trying to optimize
|
|
|
|
* for what it thinks is already there, because it gets it wrong in
|
|
|
|
* the case of a wide character in column zero. See bug #31743. */
|
2015-09-05 09:14:24 +00:00
|
|
|
if (seen_wide)
|
2017-01-12 17:00:54 +00:00
|
|
|
wredrawln(edit, row, 1);
|
2014-05-28 01:35:51 +00:00
|
|
|
#endif
|
2001-12-02 04:55:44 +00:00
|
|
|
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
2017-01-08 20:31:49 +00:00
|
|
|
/* If color syntaxes are available and turned on, apply them. */
|
2005-07-13 20:18:46 +00:00
|
|
|
if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
|
2016-03-13 20:13:16 +00:00
|
|
|
const colortype *varnish = openfile->colorstrings;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
2015-11-29 13:20:08 +00:00
|
|
|
/* If there are multiline regexes, make sure there is a cache. */
|
|
|
|
if (openfile->syntax->nmultis > 0)
|
|
|
|
alloc_multidata_if_needed(fileptr);
|
|
|
|
|
2017-01-08 20:31:49 +00:00
|
|
|
/* Iterate through all the coloring regexes. */
|
2016-03-13 20:13:16 +00:00
|
|
|
for (; varnish != NULL; varnish = varnish->next) {
|
2017-01-08 21:04:43 +00:00
|
|
|
size_t index = 0;
|
|
|
|
/* Where in the line we currently begin looking for a match. */
|
2017-01-18 18:53:51 +00:00
|
|
|
int linelen;
|
|
|
|
/* The length of the line we are currently looking at. */
|
2017-01-08 11:32:24 +00:00
|
|
|
int start_col;
|
2017-01-08 20:31:49 +00:00
|
|
|
/* The starting column of a piece to paint. Zero-based. */
|
2015-06-14 18:06:36 +00:00
|
|
|
int paintlen = 0;
|
2017-01-08 20:31:49 +00:00
|
|
|
/* The number of characters to paint. */
|
|
|
|
const char *thetext;
|
|
|
|
/* The place in converted from where painting starts. */
|
2017-01-20 18:44:46 +00:00
|
|
|
regmatch_t match, startmatch, endmatch;
|
|
|
|
/* Match positions of the full, start and end regexes. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
2005-12-08 07:24:54 +00:00
|
|
|
/* Two notes about regexec(). A return value of zero means
|
|
|
|
* that there is a match. Also, rm_eo is the first
|
|
|
|
* non-matching character after the match. */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
2017-01-08 20:31:49 +00:00
|
|
|
wattron(edit, varnish->attributes);
|
|
|
|
|
2016-03-13 20:13:16 +00:00
|
|
|
/* First case: varnish is a single-line expression. */
|
|
|
|
if (varnish->end == NULL) {
|
2017-01-08 21:04:43 +00:00
|
|
|
/* We increment index 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
|
2006-05-26 11:58:37 +00:00
|
|
|
* want to ignore them, so that we can highlight e.g. C
|
|
|
|
* strings correctly. */
|
2017-01-08 21:04:43 +00:00
|
|
|
while (index < till_x) {
|
2003-09-16 01:16:49 +00:00
|
|
|
/* Note the fifth parameter to regexec(). It says
|
|
|
|
* not to match the beginning-of-line character
|
2017-01-08 21:04:43 +00:00
|
|
|
* unless index is zero. If regexec() returns
|
2006-05-26 11:58:37 +00:00
|
|
|
* REG_NOMATCH, there are no more matches in the
|
|
|
|
* line. */
|
2017-01-08 21:04:43 +00:00
|
|
|
if (regexec(varnish->start, &fileptr->data[index], 1,
|
2017-01-20 18:44:46 +00:00
|
|
|
&match, (index == 0) ? 0 : REG_NOTBOL) != 0)
|
2002-01-19 16:52:34 +00:00
|
|
|
break;
|
2017-01-08 20:31:49 +00:00
|
|
|
|
2017-01-20 18:20:30 +00:00
|
|
|
/* If the match is of length zero, skip it. */
|
2017-01-20 18:44:46 +00:00
|
|
|
if (match.rm_so == match.rm_eo) {
|
2017-01-20 18:20:30 +00:00
|
|
|
index = move_mbright(fileptr->data,
|
2017-01-20 18:44:46 +00:00
|
|
|
index + match.rm_eo);
|
2017-01-08 21:04:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-01-08 20:31:49 +00:00
|
|
|
/* Translate the match to the beginning of the line. */
|
2017-01-20 18:44:46 +00:00
|
|
|
match.rm_so += index;
|
|
|
|
match.rm_eo += index;
|
|
|
|
index = match.rm_eo;
|
2006-06-21 20:51:36 +00:00
|
|
|
|
2017-01-20 18:44:46 +00:00
|
|
|
/* If the matching part is not visible, skip it. */
|
|
|
|
if (match.rm_eo <= from_x || match.rm_so >= till_x)
|
2017-01-08 21:04:43 +00:00
|
|
|
continue;
|
|
|
|
|
2017-01-20 18:44:46 +00:00
|
|
|
start_col = (match.rm_so <= from_x) ?
|
|
|
|
0 : strnlenpt(fileptr->data,
|
|
|
|
match.rm_so) - from_col;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
thetext = converted + actual_x(converted, start_col);
|
2005-01-03 22:23:00 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
paintlen = actual_x(thetext, strnlenpt(fileptr->data,
|
2017-01-20 18:44:46 +00:00
|
|
|
match.rm_eo) - from_col - start_col);
|
2005-01-03 22:23:00 +00:00
|
|
|
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwaddnstr(edit, row, margin + start_col,
|
2017-01-08 20:31:49 +00:00
|
|
|
thetext, paintlen);
|
2002-01-19 01:59:37 +00:00
|
|
|
}
|
2017-01-08 21:04:43 +00:00
|
|
|
goto tail_of_loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Second case: varnish is a multiline expression. */
|
2017-01-09 10:49:35 +00:00
|
|
|
const filestruct *start_line = fileptr->prev;
|
|
|
|
/* The first line before fileptr that matches 'start'. */
|
|
|
|
const filestruct *end_line = fileptr;
|
|
|
|
/* The line that matches 'end'. */
|
|
|
|
|
|
|
|
/* First see if the multidata was maybe already calculated. */
|
|
|
|
if (fileptr->multidata[varnish->id] == CNONE)
|
|
|
|
goto tail_of_loop;
|
|
|
|
else if (fileptr->multidata[varnish->id] == CWHOLELINE) {
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwaddnstr(edit, row, margin, converted, -1);
|
2017-01-09 10:49:35 +00:00
|
|
|
goto tail_of_loop;
|
|
|
|
} else if (fileptr->multidata[varnish->id] == CBEGINBEFORE) {
|
|
|
|
regexec(varnish->end, fileptr->data, 1, &endmatch, 0);
|
2017-01-20 18:44:46 +00:00
|
|
|
/* If the part to be coloured is not visible, skip it. */
|
2017-01-09 10:49:35 +00:00
|
|
|
if (endmatch.rm_eo <= from_x)
|
2015-12-01 12:49:17 +00:00
|
|
|
goto tail_of_loop;
|
2017-01-09 10:49:35 +00:00
|
|
|
paintlen = actual_x(converted, strnlenpt(fileptr->data,
|
2017-01-08 09:20:57 +00:00
|
|
|
endmatch.rm_eo) - from_col);
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwaddnstr(edit, row, margin, converted, paintlen);
|
2017-01-09 10:49:35 +00:00
|
|
|
goto tail_of_loop;
|
|
|
|
}
|
2006-06-21 20:51:36 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
/* There is no precalculated multidata, or it is CENDAFTER or
|
|
|
|
* CSTARTENDHERE. In all cases, find out what to paint. */
|
|
|
|
|
|
|
|
/* When the multidata is unitialized, assume CNONE until one
|
|
|
|
* of the steps below concludes otherwise. */
|
|
|
|
if (fileptr->multidata[varnish->id] == -1)
|
|
|
|
fileptr->multidata[varnish->id] = CNONE;
|
|
|
|
|
|
|
|
/* First check if the beginning of the line is colored by a
|
|
|
|
* start on an earlier line, and an end on this line or later.
|
|
|
|
*
|
|
|
|
* So: 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 a line after start_line that
|
|
|
|
* matches the end. If that line is not before fileptr, then
|
|
|
|
* paint the beginning of this line. */
|
|
|
|
|
|
|
|
while (start_line != NULL && regexec(varnish->start,
|
|
|
|
start_line->data, 1, &startmatch, 0) == REG_NOMATCH) {
|
|
|
|
/* There is no start; but if there is an end on this line,
|
|
|
|
* there is no need to look for starts on earlier lines. */
|
|
|
|
if (regexec(varnish->end, start_line->data, 0, NULL, 0) == 0)
|
2015-12-01 12:35:48 +00:00
|
|
|
goto step_two;
|
2017-01-09 10:49:35 +00:00
|
|
|
start_line = start_line->prev;
|
|
|
|
}
|
2015-12-01 12:35:48 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
/* If no start was found, skip to the next step. */
|
|
|
|
if (start_line == NULL)
|
|
|
|
goto step_two;
|
|
|
|
|
|
|
|
/* If a found start has been qualified as an end earlier,
|
|
|
|
* believe it and skip to the next step. */
|
|
|
|
if (start_line->multidata != NULL &&
|
2016-03-13 20:13:16 +00:00
|
|
|
(start_line->multidata[varnish->id] == CBEGINBEFORE ||
|
|
|
|
start_line->multidata[varnish->id] == CSTARTENDHERE))
|
2017-01-09 10:49:35 +00:00
|
|
|
goto step_two;
|
2015-06-14 17:56:44 +00:00
|
|
|
|
2017-01-18 18:53:51 +00:00
|
|
|
linelen = strlen(start_line->data);
|
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
/* Now start_line is the first line before fileptr containing
|
|
|
|
* a start match. Is there a start on that line not followed
|
|
|
|
* by an end on that line? */
|
|
|
|
while (TRUE) {
|
2017-01-20 12:31:18 +00:00
|
|
|
/* Begin searching for an end after the start match. */
|
2017-01-20 09:58:15 +00:00
|
|
|
index += startmatch.rm_eo;
|
2017-01-20 12:31:18 +00:00
|
|
|
/* If the start match is zero-length, don't get stuck. */
|
2017-01-20 18:20:30 +00:00
|
|
|
if (startmatch.rm_so == startmatch.rm_eo) {
|
|
|
|
index = move_mbright(start_line->data, index);
|
|
|
|
if (index > linelen)
|
2017-01-18 18:53:51 +00:00
|
|
|
break;
|
2017-01-20 18:20:30 +00:00
|
|
|
}
|
2017-01-20 12:31:18 +00:00
|
|
|
/* If there is no end after this last start, good. */
|
2017-01-20 09:58:15 +00:00
|
|
|
if (regexec(varnish->end, start_line->data + index,
|
|
|
|
0, NULL, REG_NOTBOL) == REG_NOMATCH)
|
2017-01-09 10:49:35 +00:00
|
|
|
break;
|
2017-01-20 12:31:18 +00:00
|
|
|
/* If there is no later start on this line, next step. */
|
2017-01-09 10:49:35 +00:00
|
|
|
if (regexec(varnish->start, start_line->data + index,
|
2016-06-25 17:59:19 +00:00
|
|
|
1, &startmatch, REG_NOTBOL) == REG_NOMATCH)
|
2015-12-01 13:33:45 +00:00
|
|
|
goto step_two;
|
2017-01-09 10:49:35 +00:00
|
|
|
}
|
|
|
|
/* Indeed, there is a start without an end on that line. */
|
|
|
|
|
2017-01-09 17:25:25 +00:00
|
|
|
/* We've already checked that there is no end between the start
|
|
|
|
* and the current line. But is there an end after the start
|
2017-01-09 10:49:35 +00:00
|
|
|
* at all? We don't paint unterminated starts. */
|
|
|
|
while (end_line != NULL && regexec(varnish->end, end_line->data,
|
|
|
|
1, &endmatch, 0) == REG_NOMATCH)
|
|
|
|
end_line = end_line->next;
|
|
|
|
|
2017-01-09 18:14:51 +00:00
|
|
|
/* If there is no end, there is nothing to paint. */
|
2017-01-09 10:49:35 +00:00
|
|
|
if (end_line == NULL)
|
2017-01-09 18:14:51 +00:00
|
|
|
goto tail_of_loop;
|
2002-09-27 14:21:59 +00:00
|
|
|
|
2017-01-20 20:27:49 +00:00
|
|
|
/* If the end is on a later line, paint whole line, and be done. */
|
2017-01-09 10:49:35 +00:00
|
|
|
if (end_line != fileptr) {
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwaddnstr(edit, row, margin, converted, -1);
|
2017-01-09 10:49:35 +00:00
|
|
|
fileptr->multidata[varnish->id] = CWHOLELINE;
|
2015-06-14 15:58:57 +00:00
|
|
|
#ifdef DEBUG
|
2017-01-12 17:00:54 +00:00
|
|
|
fprintf(stderr, " Marking for id %i row %i as CWHOLELINE\n", varnish->id, row);
|
2015-06-14 15:58:57 +00:00
|
|
|
#endif
|
2017-01-09 10:49:35 +00:00
|
|
|
goto tail_of_loop;
|
2017-01-20 20:27:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Only if it is visible, paint the part to be coloured. */
|
|
|
|
if (endmatch.rm_eo > from_x) {
|
2017-01-09 10:49:35 +00:00
|
|
|
paintlen = actual_x(converted, strnlenpt(fileptr->data,
|
2017-01-08 09:20:57 +00:00
|
|
|
endmatch.rm_eo) - from_col);
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwaddnstr(edit, row, margin, converted, paintlen);
|
2017-01-20 20:27:49 +00:00
|
|
|
}
|
|
|
|
fileptr->multidata[varnish->id] = CBEGINBEFORE;
|
2015-06-14 15:58:57 +00:00
|
|
|
#ifdef DEBUG
|
2017-01-12 17:00:54 +00:00
|
|
|
fprintf(stderr, " Marking for id %i row %i as CBEGINBEFORE\n", varnish->id, row);
|
2015-06-14 15:58:57 +00:00
|
|
|
#endif
|
2006-05-08 15:57:04 +00:00
|
|
|
step_two:
|
2017-01-09 10:49:35 +00:00
|
|
|
/* Second step: look for starts on this line, but begin
|
|
|
|
* looking only after an end match, if there is one. */
|
|
|
|
index = (paintlen == 0) ? 0 : endmatch.rm_eo;
|
2015-12-01 13:33:45 +00:00
|
|
|
|
2017-01-18 18:53:51 +00:00
|
|
|
linelen = strlen(fileptr->data);
|
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
while (regexec(varnish->start, fileptr->data + index,
|
2017-01-08 21:04:43 +00:00
|
|
|
1, &startmatch, (index == 0) ?
|
2017-01-07 19:42:37 +00:00
|
|
|
0 : REG_NOTBOL) == 0) {
|
2017-01-09 10:49:35 +00:00
|
|
|
/* Translate the match to be relative to the
|
|
|
|
* beginning of the line. */
|
|
|
|
startmatch.rm_so += index;
|
|
|
|
startmatch.rm_eo += index;
|
2015-12-01 13:33:45 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
start_col = (startmatch.rm_so <= from_x) ?
|
2015-12-01 13:33:45 +00:00
|
|
|
0 : strnlenpt(fileptr->data,
|
2017-01-08 09:20:57 +00:00
|
|
|
startmatch.rm_so) - from_col;
|
2005-01-03 22:23:00 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
thetext = converted + actual_x(converted, start_col);
|
2002-09-27 14:21:59 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
if (regexec(varnish->end, fileptr->data + startmatch.rm_eo,
|
|
|
|
1, &endmatch, (startmatch.rm_eo == 0) ?
|
2015-12-01 13:33:45 +00:00
|
|
|
0 : REG_NOTBOL) == 0) {
|
2017-01-09 10:49:35 +00:00
|
|
|
/* Translate the end match to be relative to
|
|
|
|
* the beginning of the line. */
|
|
|
|
endmatch.rm_so += startmatch.rm_eo;
|
|
|
|
endmatch.rm_eo += startmatch.rm_eo;
|
2017-01-09 17:25:25 +00:00
|
|
|
/* Only paint the match if it is visible on screen and
|
|
|
|
* it is more than zero characters long. */
|
2017-01-09 10:49:35 +00:00
|
|
|
if (endmatch.rm_eo > from_x &&
|
2017-01-07 19:42:37 +00:00
|
|
|
endmatch.rm_eo > startmatch.rm_so) {
|
2017-01-09 10:49:35 +00:00
|
|
|
paintlen = actual_x(thetext, strnlenpt(fileptr->data,
|
2017-01-08 11:32:24 +00:00
|
|
|
endmatch.rm_eo) - from_col - start_col);
|
2005-01-24 21:51:07 +00:00
|
|
|
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwaddnstr(edit, row, margin + start_col,
|
2017-01-09 10:49:35 +00:00
|
|
|
thetext, paintlen);
|
2017-01-03 20:18:24 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
fileptr->multidata[varnish->id] = CSTARTENDHERE;
|
2015-06-14 15:58:57 +00:00
|
|
|
#ifdef DEBUG
|
2017-01-12 17:00:54 +00:00
|
|
|
fprintf(stderr, " Marking for id %i row %i as CSTARTENDHERE\n", varnish->id, row);
|
2015-06-14 15:58:57 +00:00
|
|
|
#endif
|
2017-01-08 21:04:43 +00:00
|
|
|
}
|
2017-01-09 10:49:35 +00:00
|
|
|
index = endmatch.rm_eo;
|
2017-01-20 18:20:30 +00:00
|
|
|
/* If the end match is of length zero, step ahead. */
|
|
|
|
if (endmatch.rm_so == endmatch.rm_eo) {
|
|
|
|
index = move_mbright(fileptr->data, index);
|
|
|
|
if (index > linelen)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
2017-01-09 10:49:35 +00:00
|
|
|
}
|
2017-01-08 21:04:43 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
/* There is no end on this line. But maybe on later lines? */
|
|
|
|
end_line = fileptr->next;
|
2006-05-08 15:57:04 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
while (end_line != NULL && regexec(varnish->end, end_line->data,
|
|
|
|
0, NULL, 0) == REG_NOMATCH)
|
|
|
|
end_line = end_line->next;
|
2005-01-03 22:23:00 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
/* If there is no end, we're done with this regex. */
|
|
|
|
if (end_line == NULL)
|
|
|
|
break;
|
2005-01-03 22:23:00 +00:00
|
|
|
|
2017-01-09 10:49:35 +00:00
|
|
|
/* Paint the rest of the line. */
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwaddnstr(edit, row, margin + start_col, thetext, -1);
|
2017-01-09 10:49:35 +00:00
|
|
|
fileptr->multidata[varnish->id] = CENDAFTER;
|
2015-06-14 15:58:57 +00:00
|
|
|
#ifdef DEBUG
|
2017-01-12 17:00:54 +00:00
|
|
|
fprintf(stderr, " Marking for id %i row %i as CENDAFTER\n", varnish->id, row);
|
2015-06-14 15:58:57 +00:00
|
|
|
#endif
|
2017-01-09 10:49:35 +00:00
|
|
|
/* We've painted to the end of the line, so don't
|
|
|
|
* bother checking for any more starts. */
|
|
|
|
break;
|
2005-03-10 20:55:11 +00:00
|
|
|
}
|
2015-12-01 12:49:17 +00:00
|
|
|
tail_of_loop:
|
2016-07-17 13:29:07 +00:00
|
|
|
wattroff(edit, varnish->attributes);
|
2005-03-10 20:55:11 +00:00
|
|
|
}
|
2002-09-27 14:21:59 +00:00
|
|
|
}
|
2014-04-04 11:59:03 +00:00
|
|
|
#endif /* !DISABLE_COLOR */
|
2001-12-02 04:55:44 +00:00
|
|
|
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-06-14 09:06:04 +00:00
|
|
|
/* If the mark is on, and fileptr is at least partially selected, we
|
|
|
|
* need to paint it. */
|
|
|
|
if (openfile->mark_set &&
|
|
|
|
(fileptr->lineno <= openfile->mark_begin->lineno ||
|
|
|
|
fileptr->lineno <= openfile->current->lineno) &&
|
|
|
|
(fileptr->lineno >= openfile->mark_begin->lineno ||
|
|
|
|
fileptr->lineno >= openfile->current->lineno)) {
|
|
|
|
const filestruct *top, *bot;
|
|
|
|
/* The lines where the marked region begins and ends. */
|
|
|
|
size_t top_x, bot_x;
|
|
|
|
/* The x positions where the marked region begins and ends. */
|
2017-01-08 11:32:24 +00:00
|
|
|
int start_col;
|
2017-01-08 12:01:45 +00:00
|
|
|
/* The column where painting starts. Zero-based. */
|
|
|
|
const char *thetext;
|
|
|
|
/* The place in converted from where painting starts. */
|
|
|
|
int paintlen = -1;
|
|
|
|
/* The number of characters to paint. Negative means "all". */
|
2002-09-27 14:21:59 +00:00
|
|
|
|
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
|
|
|
|
2017-01-08 09:20:57 +00:00
|
|
|
if (top->lineno < fileptr->lineno || top_x < from_x)
|
|
|
|
top_x = from_x;
|
|
|
|
if (bot->lineno > fileptr->lineno || bot_x > till_x)
|
|
|
|
bot_x = till_x;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
2017-01-08 11:32:24 +00:00
|
|
|
/* Only paint if the marked part of the line is on this page. */
|
2017-01-08 09:20:57 +00:00
|
|
|
if (top_x < till_x && bot_x > from_x) {
|
2017-01-08 11:32:24 +00:00
|
|
|
/* Compute on which screen column to start painting. */
|
|
|
|
start_col = strnlenpt(fileptr->data, top_x) - from_col;
|
2003-09-16 01:16:49 +00:00
|
|
|
|
2017-01-08 12:01:45 +00:00
|
|
|
thetext = converted + actual_x(converted, start_col);
|
2005-01-24 21:51:07 +00:00
|
|
|
|
2017-01-08 12:01:45 +00:00
|
|
|
/* If the end of the mark is onscreen, compute how many
|
|
|
|
* characters to paint. Otherwise, just paint all. */
|
|
|
|
if (bot_x < till_x) {
|
|
|
|
size_t end_col = strnlenpt(fileptr->data, bot_x) - from_col;
|
|
|
|
paintlen = actual_x(thetext, end_col - start_col);
|
|
|
|
}
|
2005-01-03 22:23:00 +00:00
|
|
|
|
2014-05-04 08:53:06 +00:00
|
|
|
wattron(edit, hilite_attribute);
|
2017-01-12 17:00:54 +00:00
|
|
|
mvwaddnstr(edit, row, margin + start_col, thetext, paintlen);
|
2014-05-04 08:53:06 +00:00
|
|
|
wattroff(edit, hilite_attribute);
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
2001-11-29 02:42:27 +00:00
|
|
|
}
|
2005-11-15 03:17:35 +00:00
|
|
|
#endif /* !NANO_TINY */
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2017-01-12 23:55:22 +00:00
|
|
|
/* Redraw the line at fileptr. The line will be displayed so that the
|
|
|
|
* character with the given index is visible -- if necessary, the line
|
|
|
|
* will be horizontally scrolled. In softwrap mode, however, the entire
|
|
|
|
* line will be displayed. Likely values of index are current_x or zero.
|
|
|
|
* Return the number of additional rows consumed (when softwrapping). */
|
2009-08-17 07:52:10 +00:00
|
|
|
int update_line(filestruct *fileptr, size_t index)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2017-01-12 17:00:54 +00:00
|
|
|
int row = 0;
|
2017-01-09 17:25:25 +00:00
|
|
|
/* The row in the edit window we will be updating. */
|
2002-09-27 14:21:59 +00:00
|
|
|
char *converted;
|
2017-01-09 17:25:25 +00:00
|
|
|
/* The data of the line with tabs and control characters expanded. */
|
2017-01-12 17:25:50 +00:00
|
|
|
size_t from_col = 0;
|
|
|
|
/* From which column a horizontally scrolled line is displayed. */
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2014-06-09 20:26:54 +00:00
|
|
|
#ifndef NANO_TINY
|
2009-08-17 07:52:10 +00:00
|
|
|
if (ISSET(SOFTWRAP)) {
|
2017-01-12 17:25:50 +00:00
|
|
|
filestruct *line = openfile->edittop;
|
2014-06-09 20:26:54 +00:00
|
|
|
|
2017-01-13 16:47:55 +00:00
|
|
|
/* Find out on which screen row the target line should be shown. */
|
2017-01-12 17:25:50 +00:00
|
|
|
while (line != fileptr && line != NULL) {
|
|
|
|
row += (strlenpt(line->data) / editwincols) + 1;
|
|
|
|
line = line->next;
|
|
|
|
}
|
2009-08-17 07:52:10 +00:00
|
|
|
} else
|
2014-06-09 20:26:54 +00:00
|
|
|
#endif
|
2017-01-12 17:00:54 +00:00
|
|
|
row = fileptr->lineno - openfile->edittop->lineno;
|
2009-08-17 07:52:10 +00:00
|
|
|
|
2016-12-28 16:22:05 +00:00
|
|
|
/* If the line is offscreen, don't even try to display it. */
|
2017-01-12 17:00:54 +00:00
|
|
|
if (row < 0 || row >= editwinrows)
|
2016-12-28 16:22:05 +00:00
|
|
|
return 0;
|
2000-06-16 04:25:30 +00:00
|
|
|
|
2017-01-13 18:11:11 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-01-13 18:18:08 +00:00
|
|
|
if (ISSET(SOFTWRAP)) {
|
2014-06-10 19:07:47 +00:00
|
|
|
size_t full_length = strlenpt(fileptr->data);
|
2017-01-13 18:25:16 +00:00
|
|
|
int starting_row = row;
|
2017-01-12 17:25:50 +00:00
|
|
|
|
2017-01-13 18:11:11 +00:00
|
|
|
for (from_col = 0; from_col <= full_length &&
|
|
|
|
row < editwinrows; from_col += editwincols) {
|
2017-01-12 23:55:22 +00:00
|
|
|
/* First, blank out the row. */
|
2017-01-13 18:11:11 +00:00
|
|
|
blank_row(edit, row, 0, COLS);
|
2009-08-17 07:52:10 +00:00
|
|
|
|
|
|
|
/* Expand the line, replacing tabs with spaces, and control
|
2014-05-13 20:14:01 +00:00
|
|
|
* characters with their displayed forms. */
|
2017-01-12 17:25:50 +00:00
|
|
|
converted = display_string(fileptr->data, from_col, editwincols, TRUE);
|
2017-01-13 16:47:55 +00:00
|
|
|
|
2017-01-12 17:00:54 +00:00
|
|
|
/* Draw the line. */
|
2017-01-13 18:11:11 +00:00
|
|
|
edit_draw(fileptr, converted, row++, from_col);
|
2014-05-13 20:14:01 +00:00
|
|
|
free(converted);
|
2009-08-17 07:52:10 +00:00
|
|
|
}
|
2017-01-13 18:11:11 +00:00
|
|
|
|
2017-01-13 18:25:16 +00:00
|
|
|
return (row - starting_row);
|
2009-08-17 07:52:10 +00:00
|
|
|
}
|
2017-01-13 16:47:55 +00:00
|
|
|
#endif
|
2017-01-12 23:55:22 +00:00
|
|
|
|
2017-01-13 18:18:08 +00:00
|
|
|
/* First, blank out the row. */
|
|
|
|
blank_row(edit, row, 0, COLS);
|
|
|
|
|
|
|
|
/* Next, find out from which column to start displaying the line. */
|
|
|
|
from_col = get_page_start(strnlenpt(fileptr->data, index));
|
|
|
|
|
|
|
|
/* Expand the line, replacing tabs with spaces, and control
|
|
|
|
* characters with their displayed forms. */
|
|
|
|
converted = display_string(fileptr->data, from_col, editwincols, TRUE);
|
|
|
|
|
|
|
|
/* Draw the line. */
|
|
|
|
edit_draw(fileptr, converted, row, from_col);
|
|
|
|
free(converted);
|
|
|
|
|
|
|
|
if (from_col > 0)
|
|
|
|
mvwaddch(edit, row, margin, '$');
|
|
|
|
if (strlenpt(fileptr->data) > from_col + editwincols)
|
|
|
|
mvwaddch(edit, row, COLS - 1, '$');
|
|
|
|
|
2017-01-13 18:25:16 +00:00
|
|
|
return 1;
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2016-07-26 17:47:00 +00:00
|
|
|
/* Check whether old_column and new_column are on different "pages" (or that
|
|
|
|
* the mark is on), which means that the relevant line needs to be redrawn. */
|
|
|
|
bool need_horizontal_scroll(const size_t old_column, const size_t new_column)
|
2004-05-28 20:44:09 +00:00
|
|
|
{
|
2005-11-15 03:17:35 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-07-26 17:47:00 +00:00
|
|
|
if (openfile->mark_set)
|
|
|
|
return TRUE;
|
|
|
|
else
|
2004-05-28 20:44:09 +00:00
|
|
|
#endif
|
2016-07-26 17:47:00 +00:00
|
|
|
return (get_page_start(old_column) != get_page_start(new_column));
|
2004-05-28 20:44:09 +00:00
|
|
|
}
|
|
|
|
|
2017-01-12 20:31:08 +00:00
|
|
|
/* Determine how many file lines we can display, accounting for softwraps. */
|
2017-01-12 16:33:46 +00:00
|
|
|
void compute_maxlines(void)
|
2009-11-13 13:48:56 +00:00
|
|
|
{
|
2016-12-08 15:56:16 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
if (ISSET(SOFTWRAP)) {
|
2016-12-09 11:47:00 +00:00
|
|
|
filestruct *line = openfile->edittop;
|
2017-01-12 20:31:08 +00:00
|
|
|
int row = 0;
|
2016-12-08 15:56:16 +00:00
|
|
|
|
2017-01-12 16:33:46 +00:00
|
|
|
maxlines = 0;
|
2016-12-09 11:47:00 +00:00
|
|
|
|
2017-01-12 20:31:08 +00:00
|
|
|
while (row < editwinrows && line != NULL) {
|
|
|
|
row += (strlenpt(line->data) / editwincols) + 1;
|
2016-12-09 11:47:00 +00:00
|
|
|
line = line->next;
|
2017-01-12 16:33:46 +00:00
|
|
|
maxlines++;
|
2016-12-08 15:56:16 +00:00
|
|
|
}
|
2009-11-13 13:48:56 +00:00
|
|
|
|
2017-01-12 20:31:08 +00:00
|
|
|
if (row < editwinrows)
|
|
|
|
maxlines += (editwinrows - row);
|
2009-11-13 13:48:56 +00:00
|
|
|
#ifdef DEBUG
|
2017-01-12 16:33:46 +00:00
|
|
|
fprintf(stderr, "recomputed: maxlines = %d\n", maxlines);
|
2009-11-13 13:48:56 +00:00
|
|
|
#endif
|
2016-12-08 15:56:16 +00:00
|
|
|
} else
|
|
|
|
#endif /* !NANO_TINY */
|
2017-01-12 16:33:46 +00:00
|
|
|
maxlines = editwinrows;
|
2009-11-13 13:48:56 +00:00
|
|
|
}
|
|
|
|
|
2004-05-28 20:44:09 +00:00
|
|
|
/* 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
|
2014-06-23 18:20:12 +00:00
|
|
|
* scrolling. direction is the direction to scroll, either UPWARD or
|
|
|
|
* DOWNWARD, and nlines is the number of lines to scroll. We change
|
2006-07-19 00:14:52 +00:00
|
|
|
* edittop, and assume that current and current_x are up to date. We
|
|
|
|
* also assume that scrollok(edit) is FALSE. */
|
2005-08-01 21:05:29 +00:00
|
|
|
void edit_scroll(scroll_dir direction, ssize_t nlines)
|
2004-05-28 20:44:09 +00:00
|
|
|
{
|
2014-03-17 13:15:50 +00:00
|
|
|
ssize_t i;
|
2009-01-25 07:25:17 +00:00
|
|
|
filestruct *foo;
|
2004-05-28 20:44:09 +00:00
|
|
|
|
2005-07-22 23:17:19 +00:00
|
|
|
/* Part 1: nlines is the number of lines we're going to scroll the
|
|
|
|
* text of the edit window. */
|
|
|
|
|
2004-05-28 20:44:09 +00:00
|
|
|
/* Move the top line of the edit window up or down (depending on the
|
2005-07-16 22:50:30 +00:00
|
|
|
* value of direction) nlines lines, or as many lines as we can if
|
|
|
|
* there are fewer than nlines lines available. */
|
2004-05-28 20:44:09 +00:00
|
|
|
for (i = nlines; i > 0; i--) {
|
2014-06-23 18:20:12 +00:00
|
|
|
if (direction == UPWARD) {
|
2005-11-10 04:27:30 +00:00
|
|
|
if (openfile->edittop == openfile->fileage)
|
2004-05-28 20:44:09 +00:00
|
|
|
break;
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->edittop = openfile->edittop->prev;
|
2004-05-28 20:44:09 +00:00
|
|
|
} else {
|
2005-11-10 04:27:30 +00:00
|
|
|
if (openfile->edittop == openfile->filebot)
|
2004-05-28 20:44:09 +00:00
|
|
|
break;
|
2005-07-08 20:09:16 +00:00
|
|
|
openfile->edittop = openfile->edittop->next;
|
2004-05-28 20:44:09 +00:00
|
|
|
}
|
2014-06-09 20:26:54 +00:00
|
|
|
|
|
|
|
#ifndef NANO_TINY
|
2014-04-15 11:25:29 +00:00
|
|
|
/* Don't over-scroll on long lines. */
|
2014-06-23 18:20:12 +00:00
|
|
|
if (ISSET(SOFTWRAP) && direction == UPWARD) {
|
2016-10-20 08:44:29 +00:00
|
|
|
ssize_t len = strlenpt(openfile->edittop->data) / editwincols;
|
2014-05-16 11:03:04 +00:00
|
|
|
i -= len;
|
2010-01-13 03:21:19 +00:00
|
|
|
if (len > 0)
|
2016-04-25 19:14:18 +00:00
|
|
|
refresh_needed = TRUE;
|
2010-01-13 03:21:19 +00:00
|
|
|
}
|
2014-06-09 20:26:54 +00:00
|
|
|
#endif
|
2004-05-28 20:44:09 +00:00
|
|
|
}
|
|
|
|
|
2005-08-01 21:53:54 +00:00
|
|
|
/* Limit nlines to the number of lines we could scroll. */
|
2005-07-23 21:06:22 +00:00
|
|
|
nlines -= i;
|
2005-08-01 21:17:38 +00:00
|
|
|
|
2016-04-13 11:14:36 +00:00
|
|
|
/* Don't bother scrolling zero lines, nor more than the window can hold. */
|
|
|
|
if (nlines == 0)
|
|
|
|
return;
|
|
|
|
if (nlines >= editwinrows)
|
2016-04-25 19:14:18 +00:00
|
|
|
refresh_needed = TRUE;
|
2016-04-13 11:14:36 +00:00
|
|
|
|
2016-04-25 19:14:18 +00:00
|
|
|
if (refresh_needed == TRUE)
|
2005-08-01 21:17:38 +00:00
|
|
|
return;
|
2005-07-22 23:17:19 +00:00
|
|
|
|
|
|
|
/* Scroll the text of the edit window up or down nlines lines,
|
|
|
|
* depending on the value of direction. */
|
2005-07-22 22:56:03 +00:00
|
|
|
scrollok(edit, TRUE);
|
2014-06-23 18:20:12 +00:00
|
|
|
wscrl(edit, (direction == UPWARD) ? -nlines : nlines);
|
2005-07-22 22:56:03 +00:00
|
|
|
scrollok(edit, FALSE);
|
|
|
|
|
2005-07-22 23:17:19 +00:00
|
|
|
/* Part 2: nlines is the number of lines in the scrolled region of
|
|
|
|
* the edit window that we need to draw. */
|
|
|
|
|
2006-01-10 07:51:49 +00:00
|
|
|
/* If the scrolled region contains only one line, and the line
|
|
|
|
* before it is visible in the edit window, we need to draw it too.
|
|
|
|
* If the scrolled region contains more than one line, and the lines
|
|
|
|
* before and after the scrolled region are visible in the edit
|
|
|
|
* window, we need to draw them too. */
|
|
|
|
nlines += (nlines == 1) ? 1 : 2;
|
2005-08-01 21:53:54 +00:00
|
|
|
|
2005-07-17 22:51:44 +00:00
|
|
|
if (nlines > editwinrows)
|
|
|
|
nlines = editwinrows;
|
2005-07-16 22:50:30 +00:00
|
|
|
|
2017-01-09 17:25:25 +00:00
|
|
|
/* If we scrolled up, we're on the line before the scrolled region. */
|
2005-07-08 20:09:16 +00:00
|
|
|
foo = openfile->edittop;
|
2005-07-14 20:37:01 +00:00
|
|
|
|
2017-01-09 17:25:25 +00:00
|
|
|
/* If we scrolled down, move down to the line before the scrolled region. */
|
2014-06-23 18:20:12 +00:00
|
|
|
if (direction == DOWNWARD) {
|
2005-07-16 22:50:30 +00:00
|
|
|
for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
|
2004-05-28 20:44:09 +00:00
|
|
|
foo = foo->next;
|
|
|
|
}
|
|
|
|
|
2005-07-23 20:39:41 +00:00
|
|
|
/* Draw new lines on any blank lines before or inside the scrolled
|
|
|
|
* region. If we scrolled down and we're on the top line, or if we
|
|
|
|
* scrolled up and we're on the bottom line, the line won't be
|
|
|
|
* blank, so we don't need to draw it unless the mark is on or we're
|
|
|
|
* not on the first page. */
|
|
|
|
for (i = nlines; i > 0 && foo != NULL; i--) {
|
2017-01-09 17:25:25 +00:00
|
|
|
if ((i == nlines && direction == DOWNWARD) ||
|
|
|
|
(i == 1 && direction == UPWARD)) {
|
2016-07-26 17:47:00 +00:00
|
|
|
if (need_horizontal_scroll(openfile->placewewant, 0))
|
2005-07-23 20:39:41 +00:00
|
|
|
update_line(foo, (foo == openfile->current) ?
|
|
|
|
openfile->current_x : 0);
|
|
|
|
} else
|
|
|
|
update_line(foo, (foo == openfile->current) ?
|
2005-07-16 22:50:30 +00:00
|
|
|
openfile->current_x : 0);
|
2005-07-14 18:01:08 +00:00
|
|
|
foo = foo->next;
|
2004-05-28 20:44:09 +00:00
|
|
|
}
|
2017-01-09 17:25:25 +00:00
|
|
|
|
2017-01-12 16:33:46 +00:00
|
|
|
compute_maxlines();
|
2004-05-28 20:44:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Update any lines between old_current and current that need to be
|
2005-07-26 14:26:47 +00:00
|
|
|
* updated. Use this if we've moved without changing any text. */
|
2016-04-10 19:16:19 +00:00
|
|
|
void edit_redraw(filestruct *old_current)
|
2004-05-28 20:44:09 +00:00
|
|
|
{
|
2016-04-10 19:16:19 +00:00
|
|
|
size_t was_pww = openfile->placewewant;
|
|
|
|
|
|
|
|
openfile->placewewant = xplustabs();
|
|
|
|
|
2016-01-24 15:32:13 +00:00
|
|
|
/* If the current line is offscreen, scroll until it's onscreen. */
|
2017-01-12 16:33:46 +00:00
|
|
|
if (openfile->current->lineno >= openfile->edittop->lineno + maxlines ||
|
2016-09-13 08:26:08 +00:00
|
|
|
#ifndef NANO_TINY
|
2017-01-12 16:33:46 +00:00
|
|
|
(openfile->current->lineno == openfile->edittop->lineno + maxlines - 1 &&
|
2016-10-20 08:44:29 +00:00
|
|
|
ISSET(SOFTWRAP) && strlenpt(openfile->current->data) >= editwincols) ||
|
2016-09-13 08:26:08 +00:00
|
|
|
#endif
|
2016-04-25 18:05:21 +00:00
|
|
|
openfile->current->lineno < openfile->edittop->lineno) {
|
2016-10-20 19:11:11 +00:00
|
|
|
adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : FLOWING);
|
2016-04-25 19:14:18 +00:00
|
|
|
refresh_needed = TRUE;
|
2016-10-20 19:18:17 +00:00
|
|
|
return;
|
2016-04-25 18:05:21 +00:00
|
|
|
}
|
2005-08-01 21:05:29 +00:00
|
|
|
|
2006-05-26 03:04:24 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-01-24 15:32:13 +00:00
|
|
|
/* If the mark is on, update all lines between old_current and current. */
|
|
|
|
if (openfile->mark_set) {
|
|
|
|
filestruct *foo = old_current;
|
2005-07-14 18:01:08 +00:00
|
|
|
|
2016-01-24 15:32:13 +00:00
|
|
|
while (foo != openfile->current) {
|
2004-05-28 20:44:09 +00:00
|
|
|
update_line(foo, 0);
|
2005-07-16 02:12:18 +00:00
|
|
|
|
2016-01-24 15:32:13 +00:00
|
|
|
foo = (foo->lineno > openfile->current->lineno) ?
|
|
|
|
foo->prev : foo->next;
|
|
|
|
}
|
2016-04-27 15:45:36 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
/* Otherwise, update old_current only if it differs from current
|
|
|
|
* and was horizontally scrolled. */
|
|
|
|
if (old_current != openfile->current && get_page_start(was_pww) > 0)
|
|
|
|
update_line(old_current, 0);
|
2016-04-11 18:40:21 +00:00
|
|
|
|
|
|
|
/* Update current if we've changed page, or if it differs from
|
|
|
|
* old_current and needs to be horizontally scrolled. */
|
2016-07-26 17:47:00 +00:00
|
|
|
if (need_horizontal_scroll(was_pww, openfile->placewewant) ||
|
2016-07-26 09:47:53 +00:00
|
|
|
(old_current != openfile->current &&
|
2016-04-11 18:40:21 +00:00
|
|
|
get_page_start(openfile->placewewant) > 0))
|
2005-07-08 20:09:16 +00:00
|
|
|
update_line(openfile->current, openfile->current_x);
|
2004-05-28 20:44:09 +00:00
|
|
|
}
|
|
|
|
|
2005-07-26 14:26:47 +00:00
|
|
|
/* Refresh the screen without changing the position of lines. Use this
|
|
|
|
* if we've moved and changed text. */
|
2000-06-06 05:53:49 +00:00
|
|
|
void edit_refresh(void)
|
|
|
|
{
|
2016-12-23 11:51:04 +00:00
|
|
|
filestruct *line;
|
|
|
|
int row = 0;
|
2005-07-16 22:47:12 +00:00
|
|
|
|
2017-01-12 16:33:46 +00:00
|
|
|
/* Figure out what maxlines should really be. */
|
|
|
|
compute_maxlines();
|
2009-11-13 13:48:56 +00:00
|
|
|
|
2016-10-20 20:04:38 +00:00
|
|
|
/* If the current line is out of view, get it back on screen. */
|
2005-07-08 20:09:16 +00:00
|
|
|
if (openfile->current->lineno < openfile->edittop->lineno ||
|
2017-01-12 16:33:46 +00:00
|
|
|
openfile->current->lineno >= openfile->edittop->lineno + maxlines) {
|
2009-11-16 04:28:40 +00:00
|
|
|
#ifdef DEBUG
|
2017-01-12 16:33:46 +00:00
|
|
|
fprintf(stderr, "edit-refresh: line = %ld, edittop = %ld and maxlines = %d\n",
|
|
|
|
(long)openfile->current->lineno, (long)openfile->edittop->lineno, maxlines);
|
2009-11-16 04:28:40 +00:00
|
|
|
#endif
|
2016-10-20 19:11:11 +00:00
|
|
|
adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : STATIONARY);
|
2009-11-16 04:28:40 +00:00
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2004-02-24 20:41:39 +00:00
|
|
|
#ifdef DEBUG
|
2016-12-02 16:37:11 +00:00
|
|
|
fprintf(stderr, "edit-refresh: now edittop = %ld\n", (long)openfile->edittop->lineno);
|
2004-02-24 20:41:39 +00:00
|
|
|
#endif
|
2001-10-22 03:15:31 +00:00
|
|
|
|
2016-12-23 11:51:04 +00:00
|
|
|
line = openfile->edittop;
|
|
|
|
|
|
|
|
while (row < editwinrows && line != NULL) {
|
|
|
|
if (line == openfile->current)
|
2017-01-13 18:25:16 +00:00
|
|
|
row += update_line(line, openfile->current_x);
|
2016-12-23 11:51:04 +00:00
|
|
|
else
|
2017-01-13 18:25:16 +00:00
|
|
|
row += update_line(line, 0);
|
2016-12-23 11:51:04 +00:00
|
|
|
line = line->next;
|
2005-07-16 22:47:12 +00:00
|
|
|
}
|
|
|
|
|
2016-12-23 11:51:04 +00:00
|
|
|
while (row < editwinrows)
|
2017-01-12 16:48:33 +00:00
|
|
|
blank_row(edit, row++, 0, COLS);
|
2005-07-16 22:47:12 +00:00
|
|
|
|
|
|
|
reset_cursor();
|
2005-07-26 14:42:57 +00:00
|
|
|
wnoutrefresh(edit);
|
2016-10-21 11:52:40 +00:00
|
|
|
|
|
|
|
refresh_needed = FALSE;
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2016-04-07 11:58:51 +00:00
|
|
|
/* Move edittop so that current is on the screen. manner says how it
|
|
|
|
* should be moved: CENTERING means that current should end up in the
|
|
|
|
* middle of the screen, STATIONARY means that it should stay at the
|
|
|
|
* same vertical position, and FLOWING means that it should scroll no
|
|
|
|
* more than needed to bring current into view. */
|
2016-10-20 19:11:11 +00:00
|
|
|
void adjust_viewport(update_type manner)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2016-04-16 09:38:39 +00:00
|
|
|
int goal = 0;
|
2005-07-16 22:47:12 +00:00
|
|
|
|
2016-04-07 11:58:51 +00:00
|
|
|
/* If manner is CENTERING, move edittop half the number of window
|
|
|
|
* lines back from current. If manner is STATIONARY, move edittop
|
|
|
|
* back current_y lines if current_y is in range of the screen,
|
|
|
|
* 0 lines if current_y is below zero, or (editwinrows - 1) lines
|
|
|
|
* if current_y is too big. This puts current at the same place
|
|
|
|
* on the screen as before, or at the top or bottom if current_y is
|
|
|
|
* beyond either. If manner is FLOWING, move edittop back 0 lines
|
|
|
|
* or (editwinrows - 1) lines, depending or where current has moved.
|
|
|
|
* This puts the cursor on the first or the last line. */
|
|
|
|
if (manner == CENTERING)
|
2010-01-04 19:00:55 +00:00
|
|
|
goal = editwinrows / 2;
|
2016-04-07 11:58:51 +00:00
|
|
|
else if (manner == FLOWING) {
|
2016-09-15 08:43:49 +00:00
|
|
|
if (openfile->current->lineno >= openfile->edittop->lineno) {
|
2016-04-07 11:58:51 +00:00
|
|
|
goal = editwinrows - 1;
|
2016-09-15 08:43:49 +00:00
|
|
|
#ifndef NANO_TINY
|
|
|
|
if (ISSET(SOFTWRAP))
|
2016-10-20 08:44:29 +00:00
|
|
|
goal -= strlenpt(openfile->current->data) / editwincols;
|
2016-09-15 08:43:49 +00:00
|
|
|
#endif
|
|
|
|
}
|
2016-04-07 11:58:51 +00:00
|
|
|
} else {
|
2005-07-16 22:47:12 +00:00
|
|
|
goal = openfile->current_y;
|
2004-08-26 18:07:58 +00:00
|
|
|
|
2005-07-16 22:47:12 +00:00
|
|
|
/* Limit goal to (editwinrows - 1) lines maximum. */
|
2010-01-04 19:00:55 +00:00
|
|
|
if (goal > editwinrows - 1)
|
|
|
|
goal = editwinrows - 1;
|
2002-07-19 01:08:59 +00:00
|
|
|
}
|
2004-08-27 17:02:05 +00:00
|
|
|
|
2016-04-16 09:38:39 +00:00
|
|
|
openfile->edittop = openfile->current;
|
|
|
|
|
|
|
|
while (goal > 0 && openfile->edittop->prev != NULL) {
|
|
|
|
openfile->edittop = openfile->edittop->prev;
|
2016-10-20 20:04:38 +00:00
|
|
|
goal--;
|
2014-06-09 20:26:54 +00:00
|
|
|
#ifndef NANO_TINY
|
2016-09-15 08:43:49 +00:00
|
|
|
if (ISSET(SOFTWRAP)) {
|
2016-10-20 08:44:29 +00:00
|
|
|
goal -= strlenpt(openfile->edittop->data) / editwincols;
|
2016-09-15 08:43:49 +00:00
|
|
|
if (goal < 0)
|
|
|
|
openfile->edittop = openfile->edittop->next;
|
|
|
|
}
|
2014-06-09 20:26:54 +00:00
|
|
|
#endif
|
2009-09-13 04:50:44 +00:00
|
|
|
}
|
2010-01-13 03:21:19 +00:00
|
|
|
#ifdef DEBUG
|
2016-10-20 19:11:11 +00:00
|
|
|
fprintf(stderr, "adjust_viewport(): setting edittop to lineno %ld\n", (long)openfile->edittop->lineno);
|
2010-01-13 03:21:19 +00:00
|
|
|
#endif
|
2017-01-12 16:33:46 +00:00
|
|
|
compute_maxlines();
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Unconditionally redraw the entire screen. */
|
2005-06-18 15:49:17 +00:00
|
|
|
void total_redraw(void)
|
2002-09-06 20:35:28 +00:00
|
|
|
{
|
2007-12-18 15:55:48 +00:00
|
|
|
#ifdef USE_SLANG
|
|
|
|
/* Slang curses emulation brain damage, part 4: Slang doesn't define
|
|
|
|
* curscr. */
|
|
|
|
SLsmg_touch_screen();
|
|
|
|
SLsmg_refresh();
|
|
|
|
#else
|
2005-07-10 02:37:38 +00:00
|
|
|
wrefresh(curscr);
|
2007-12-18 15:55:48 +00:00
|
|
|
#endif
|
2005-03-17 17:56:48 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Unconditionally redraw the entire screen, and then refresh it using
|
|
|
|
* the current file. */
|
2005-03-17 17:56:48 +00:00
|
|
|
void total_refresh(void)
|
|
|
|
{
|
2005-06-18 15:49:17 +00:00
|
|
|
total_redraw();
|
2002-09-06 20:35:28 +00:00
|
|
|
titlebar(NULL);
|
2004-12-04 17:41:52 +00:00
|
|
|
edit_refresh();
|
2008-03-05 07:34:01 +00:00
|
|
|
bottombars(currmenu);
|
2002-09-06 20:35:28 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Display the main shortcut list on the last two rows of the bottom
|
|
|
|
* portion of the window. */
|
2002-09-06 20:35:28 +00:00
|
|
|
void display_main_list(void)
|
|
|
|
{
|
2014-04-04 11:59:03 +00:00
|
|
|
#ifndef DISABLE_COLOR
|
2016-05-30 07:09:36 +00:00
|
|
|
if (openfile->syntax &&
|
|
|
|
(openfile->syntax->formatter || openfile->syntax->linter))
|
2015-01-03 07:24:17 +00:00
|
|
|
set_lint_or_format_shortcuts();
|
2014-02-24 10:18:15 +00:00
|
|
|
else
|
|
|
|
set_spell_shortcuts();
|
|
|
|
#endif
|
|
|
|
|
2008-03-05 07:34:01 +00:00
|
|
|
bottombars(MMAIN);
|
2002-09-06 20:35:28 +00:00
|
|
|
}
|
|
|
|
|
2005-06-28 20:04:14 +00:00
|
|
|
/* If constant is TRUE, we display the current cursor position only if
|
2016-05-04 10:18:21 +00:00
|
|
|
* suppress_cursorpos is FALSE. If constant is FALSE, we display the
|
|
|
|
* position always. In any case we reset suppress_cursorpos to FALSE. */
|
2004-08-25 15:39:10 +00:00
|
|
|
void do_cursorpos(bool constant)
|
2000-06-06 05:53:49 +00:00
|
|
|
{
|
2016-12-11 10:24:48 +00:00
|
|
|
char saved_byte;
|
|
|
|
size_t sum, cur_xpt = xplustabs() + 1;
|
2005-07-08 20:09:16 +00:00
|
|
|
size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
|
2005-06-28 20:04:14 +00:00
|
|
|
int linepct, colpct, charpct;
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2005-07-31 18:51:51 +00:00
|
|
|
assert(openfile->fileage != NULL && openfile->current != NULL);
|
2001-11-29 03:43:08 +00:00
|
|
|
|
2016-05-04 10:18:21 +00:00
|
|
|
/* Determine the size of the file up to the cursor. */
|
2016-12-11 10:24:48 +00:00
|
|
|
saved_byte = openfile->current->data[openfile->current_x];
|
2005-07-31 20:15:01 +00:00
|
|
|
openfile->current->data[openfile->current_x] = '\0';
|
2005-08-01 02:18:05 +00:00
|
|
|
|
2016-12-11 10:24:48 +00:00
|
|
|
sum = get_totsize(openfile->fileage, openfile->current);
|
2005-08-01 02:18:05 +00:00
|
|
|
|
2016-12-11 10:24:48 +00:00
|
|
|
openfile->current->data[openfile->current_x] = saved_byte;
|
2016-12-11 10:18:28 +00:00
|
|
|
|
|
|
|
/* When not at EOF, subtract 1 for an overcounted newline. */
|
|
|
|
if (openfile->current != openfile->filebot)
|
2016-12-11 10:24:48 +00:00
|
|
|
sum--;
|
2002-01-25 21:59:02 +00:00
|
|
|
|
2016-05-04 10:18:21 +00:00
|
|
|
/* If the position needs to be suppressed, don't suppress it next time. */
|
2016-05-14 19:49:19 +00:00
|
|
|
if (suppress_cursorpos && constant) {
|
2016-05-04 10:18:21 +00:00
|
|
|
suppress_cursorpos = FALSE;
|
2016-05-14 19:49:19 +00:00
|
|
|
return;
|
2003-01-28 01:16:47 +00:00
|
|
|
}
|
2000-06-06 05:53:49 +00:00
|
|
|
|
2016-05-04 10:18:21 +00:00
|
|
|
/* Display the current cursor position on the statusbar. */
|
2015-07-10 17:25:51 +00:00
|
|
|
linepct = 100 * openfile->current->lineno / openfile->filebot->lineno;
|
2005-06-28 20:04:14 +00:00
|
|
|
colpct = 100 * cur_xpt / cur_lenpt;
|
2016-12-11 10:24:48 +00:00
|
|
|
charpct = (openfile->totsize == 0) ? 0 : 100 * sum / openfile->totsize;
|
2005-06-28 20:04:14 +00:00
|
|
|
|
2016-04-30 15:31:43 +00:00
|
|
|
statusline(HUSH,
|
2005-07-25 21:23:11 +00:00
|
|
|
_("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
|
2005-07-08 20:09:16 +00:00
|
|
|
(long)openfile->current->lineno,
|
2005-07-25 21:23:11 +00:00
|
|
|
(long)openfile->filebot->lineno, linepct,
|
2005-06-28 20:04:14 +00:00
|
|
|
(unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
|
2016-12-11 10:24:48 +00:00
|
|
|
(unsigned long)sum, (unsigned long)openfile->totsize, charpct);
|
2016-05-14 19:49:19 +00:00
|
|
|
|
|
|
|
/* Displaying the cursor position should not suppress it next time. */
|
|
|
|
suppress_cursorpos = FALSE;
|
2000-06-06 05:53:49 +00:00
|
|
|
}
|
|
|
|
|
2005-12-08 07:09:08 +00:00
|
|
|
/* Unconditionally display the current cursor position. */
|
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
|
|
|
}
|
|
|
|
|
2009-01-24 22:40:41 +00:00
|
|
|
void enable_nodelay(void)
|
|
|
|
{
|
2014-06-20 10:48:26 +00:00
|
|
|
nodelay_mode = TRUE;
|
|
|
|
nodelay(edit, TRUE);
|
2009-01-24 22:40:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void disable_nodelay(void)
|
|
|
|
{
|
2014-06-20 10:48:26 +00:00
|
|
|
nodelay_mode = FALSE;
|
|
|
|
nodelay(edit, FALSE);
|
2009-01-24 22:40:41 +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. */
|
2016-03-30 12:09:39 +00:00
|
|
|
void spotlight(bool active, const char *word)
|
2000-12-05 11:36:41 +00:00
|
|
|
{
|
2016-03-30 12:18:22 +00:00
|
|
|
size_t word_len = strlenpt(word), room;
|
2002-07-19 01:08:59 +00:00
|
|
|
|
2016-05-30 07:09:36 +00:00
|
|
|
/* Compute the number of columns that are available for the word. */
|
2016-10-20 08:44:29 +00:00
|
|
|
room = editwincols + get_page_start(xplustabs()) - xplustabs();
|
2000-12-05 11:36:41 +00:00
|
|
|
|
2016-03-30 12:18:22 +00:00
|
|
|
assert(room > 0);
|
2005-01-05 05:08:14 +00:00
|
|
|
|
2016-03-30 12:18:22 +00:00
|
|
|
if (word_len > room)
|
|
|
|
room--;
|
2005-01-05 05:08:14 +00:00
|
|
|
|
2000-12-05 11:36:41 +00:00
|
|
|
reset_cursor();
|
2002-01-19 01:59:37 +00:00
|
|
|
|
2016-03-30 12:09:39 +00:00
|
|
|
if (active)
|
2014-05-04 08:53:06 +00:00
|
|
|
wattron(edit, hilite_attribute);
|
2000-12-05 11:36:41 +00:00
|
|
|
|
2006-11-10 20:13:38 +00:00
|
|
|
/* This is so we can show zero-length matches. */
|
2003-12-24 08:17:54 +00:00
|
|
|
if (word_len == 0)
|
2005-06-13 02:22:44 +00:00
|
|
|
waddch(edit, ' ');
|
2003-12-24 08:17:54 +00:00
|
|
|
else
|
2016-03-30 12:18:22 +00:00
|
|
|
waddnstr(edit, word, actual_x(word, room));
|
2003-09-16 01:16:49 +00:00
|
|
|
|
2016-03-30 12:18:22 +00:00
|
|
|
if (word_len > room)
|
2003-09-16 01:16:49 +00:00
|
|
|
waddch(edit, '$');
|
2000-12-05 11:36:41 +00:00
|
|
|
|
2016-03-30 12:09:39 +00:00
|
|
|
if (active)
|
2014-05-04 08:53:06 +00:00
|
|
|
wattroff(edit, hilite_attribute);
|
2016-12-01 14:14:41 +00:00
|
|
|
|
|
|
|
wnoutrefresh(edit);
|
2000-12-05 11:36:41 +00:00
|
|
|
}
|
|
|
|
|
2014-04-03 20:57:44 +00:00
|
|
|
#ifndef DISABLE_EXTRA
|
2015-02-01 09:19:58 +00:00
|
|
|
#define CREDIT_LEN 54
|
|
|
|
#define XLCREDIT_LEN 9
|
2002-07-21 15:44:13 +00:00
|
|
|
|
2005-08-16 03:02:46 +00:00
|
|
|
/* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit)
|
|
|
|
* are FALSE. */
|
2000-11-24 20:45:14 +00:00
|
|
|
void do_credits(void)
|
|
|
|
{
|
2005-08-14 19:25:16 +00:00
|
|
|
bool old_more_space = ISSET(MORE_SPACE);
|
|
|
|
bool old_no_help = ISSET(NO_HELP);
|
2005-06-07 03:20:35 +00:00
|
|
|
int kbinput = ERR, crpos = 0, xlpos = 0;
|
2004-05-18 01:20:36 +00:00
|
|
|
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",
|
2014-12-28 22:27:56 +00:00
|
|
|
"Mark Majeres",
|
2005-08-29 18:29:02 +00:00
|
|
|
"Mike Frysinger",
|
2014-02-24 15:15:51 +00:00
|
|
|
"Benno Schulenberg",
|
2002-01-19 01:59:37 +00:00
|
|
|
"Ken Tyler",
|
|
|
|
"Sven Guckes",
|
|
|
|
"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:" */
|
2014-02-24 15:15:51 +00:00
|
|
|
"Monique, Brielle & Joseph",
|
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",
|
2015-02-01 09:19:58 +00:00
|
|
|
NULL, /* "the many translators and the TP" */
|
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!" */
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
"",
|
2016-01-10 16:18:43 +00:00
|
|
|
"(C) 1999 - 2016",
|
2007-10-11 05:01:32 +00:00
|
|
|
"Free Software Foundation, Inc.",
|
2004-05-18 01:20:36 +00:00
|
|
|
"",
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
"",
|
2016-06-20 17:44:56 +00:00
|
|
|
"https://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"),
|
2015-02-01 09:19:58 +00:00
|
|
|
N_("the many translators and the TP"),
|
2004-07-12 03:10:30 +00:00
|
|
|
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
|
|
|
|
2005-08-14 19:25:16 +00:00
|
|
|
if (!old_more_space || !old_no_help) {
|
|
|
|
SET(MORE_SPACE);
|
|
|
|
SET(NO_HELP);
|
|
|
|
window_init();
|
|
|
|
}
|
|
|
|
|
2000-11-24 20:45:14 +00:00
|
|
|
curs_set(0);
|
|
|
|
nodelay(edit, TRUE);
|
2005-08-14 19:25:16 +00:00
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
blank_titlebar();
|
2000-11-25 18:21:37 +00:00
|
|
|
blank_edit();
|
2004-05-18 01:20:36 +00:00
|
|
|
blank_statusbar();
|
2005-08-14 21:17:37 +00:00
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
wrefresh(topwin);
|
2000-11-25 18:21:37 +00:00
|
|
|
wrefresh(edit);
|
2000-11-24 20:45:14 +00:00
|
|
|
wrefresh(bottomwin);
|
2005-08-14 21:17:37 +00:00
|
|
|
napms(700);
|
2000-11-24 20:45:14 +00:00
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
|
2005-06-07 03:20:35 +00:00
|
|
|
if ((kbinput = wgetch(edit)) != ERR)
|
2004-05-18 01:20:36 +00:00
|
|
|
break;
|
2005-03-15 06:34:09 +00:00
|
|
|
|
2004-05-18 01:20:36 +00:00
|
|
|
if (crpos < CREDIT_LEN) {
|
2005-06-28 07:26:11 +00:00
|
|
|
const char *what;
|
2017-01-08 11:05:42 +00:00
|
|
|
size_t start_col;
|
2004-05-18 01:20:36 +00:00
|
|
|
|
2005-03-15 06:58:02 +00:00
|
|
|
if (credits[crpos] == NULL) {
|
2004-05-18 01:20:36 +00:00
|
|
|
assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
|
2005-03-15 06:58:02 +00:00
|
|
|
|
2005-06-28 07:26:11 +00:00
|
|
|
what = _(xlcredits[xlpos]);
|
2004-05-18 01:20:36 +00:00
|
|
|
xlpos++;
|
2005-03-15 06:58:02 +00:00
|
|
|
} else
|
2005-06-28 07:26:11 +00:00
|
|
|
what = credits[crpos];
|
2005-03-15 06:58:02 +00:00
|
|
|
|
2017-01-08 11:05:42 +00:00
|
|
|
start_col = COLS / 2 - strlenpt(what) / 2 - 1;
|
2005-03-15 06:58:02 +00:00
|
|
|
mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
|
2017-01-08 11:05:42 +00:00
|
|
|
start_col, what);
|
2000-11-24 20:45:14 +00:00
|
|
|
}
|
2005-03-15 06:34:09 +00:00
|
|
|
|
2005-08-14 21:17:37 +00:00
|
|
|
wrefresh(edit);
|
|
|
|
|
|
|
|
if ((kbinput = wgetch(edit)) != ERR)
|
|
|
|
break;
|
2004-05-18 01:20:36 +00:00
|
|
|
napms(700);
|
2005-08-14 21:17:37 +00:00
|
|
|
|
2005-08-14 19:25:16 +00:00
|
|
|
scrollok(edit, TRUE);
|
2005-08-14 21:17:37 +00:00
|
|
|
wscrl(edit, 1);
|
2005-08-14 19:25:16 +00:00
|
|
|
scrollok(edit, FALSE);
|
2004-05-18 01:20:36 +00:00
|
|
|
wrefresh(edit);
|
2005-08-14 21:17:37 +00:00
|
|
|
|
2005-06-07 03:20:35 +00:00
|
|
|
if ((kbinput = wgetch(edit)) != ERR)
|
2000-11-24 20:45:14 +00:00
|
|
|
break;
|
2004-05-18 01:20:36 +00:00
|
|
|
napms(700);
|
2005-08-14 21:17:37 +00:00
|
|
|
|
2005-08-14 19:25:16 +00:00
|
|
|
scrollok(edit, TRUE);
|
2005-08-14 21:17:37 +00:00
|
|
|
wscrl(edit, 1);
|
2005-08-14 19:25:16 +00:00
|
|
|
scrollok(edit, FALSE);
|
2004-05-18 01:20:36 +00:00
|
|
|
wrefresh(edit);
|
2000-11-24 20:45:14 +00:00
|
|
|
}
|
|
|
|
|
2005-06-07 03:20:35 +00:00
|
|
|
if (kbinput != ERR)
|
|
|
|
ungetch(kbinput);
|
|
|
|
|
2016-01-02 16:33:03 +00:00
|
|
|
if (!old_more_space)
|
2005-08-14 19:25:16 +00:00
|
|
|
UNSET(MORE_SPACE);
|
2016-01-02 16:33:03 +00:00
|
|
|
if (!old_no_help)
|
2005-08-14 19:25:16 +00:00
|
|
|
UNSET(NO_HELP);
|
2016-01-02 16:33:03 +00:00
|
|
|
window_init();
|
2005-08-14 19:25:16 +00:00
|
|
|
|
2000-11-24 20:45:14 +00:00
|
|
|
nodelay(edit, FALSE);
|
2005-08-14 19:25:16 +00:00
|
|
|
|
2000-11-24 20:45:14 +00:00
|
|
|
total_refresh();
|
2002-01-19 01:59:37 +00:00
|
|
|
}
|
2014-04-03 20:57:44 +00:00
|
|
|
#endif /* !DISABLE_EXTRA */
|