Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b5d29b8c6 | ||
|
|
b40520b574 | ||
|
|
992533b91e | ||
|
|
f3e8991206 | ||
|
|
df7353b312 | ||
|
|
f311c0af87 | ||
|
|
c88fae3310 | ||
|
|
68cfb08888 | ||
|
|
4cff67fdde | ||
|
|
aefe26d216 | ||
|
|
8eb99e2a1d | ||
|
|
19b6f906cc | ||
|
|
c38ffdc741 | ||
|
|
a472f480a7 | ||
|
|
4416d9c941 | ||
|
|
c073c5ae54 | ||
|
|
fc0ddab349 | ||
|
|
c6dbcf91c3 | ||
|
|
8c7a38596d | ||
|
|
1c2d2a4027 | ||
|
|
1e5614b31b | ||
|
|
04b9b9c78b | ||
|
|
41ad376b70 | ||
|
|
1349c1d02c | ||
|
|
4c566c7903 | ||
|
|
73a07215cc | ||
|
|
bf091be778 | ||
|
|
103dd06347 | ||
|
|
1d4c1e0bfc | ||
|
|
b3fbb7c7ff | ||
|
|
225203d40d | ||
|
|
c2a0c78d9b | ||
|
|
97f4fe26f0 | ||
|
|
ef071255e5 | ||
|
|
afb6a5b86d | ||
|
|
a37cd9f0ef | ||
|
|
6f12992cea | ||
|
|
d88423eaae | ||
|
|
8b28de1313 | ||
|
|
8fa72fb7e7 | ||
|
|
b4babc2036 | ||
|
|
f2150d3f98 | ||
|
|
033376aec0 | ||
|
|
e33a0b6dbe | ||
|
|
0894587305 | ||
|
|
960e848cc7 | ||
|
|
b4737072a6 | ||
|
|
8507dd4bd0 | ||
|
|
62eeda3e9f | ||
|
|
06c806215e | ||
|
|
d2b25120f0 | ||
|
|
0c319f8b4b | ||
|
|
4fcc760158 | ||
|
|
0d5f918453 | ||
|
|
9c7940b599 | ||
|
|
ccfb1eb0f1 | ||
|
|
7e3a9c3aa6 | ||
|
|
a730b25ef9 | ||
|
|
500fef8314 | ||
|
|
29986e95a0 | ||
|
|
4af1da7d95 | ||
|
|
528b79b5f3 | ||
|
|
03a81aa9c5 | ||
|
|
4957c1121d | ||
|
|
d9d8eb2480 | ||
|
|
d9aad9212f | ||
|
|
8b636de1d3 | ||
|
|
aeab800490 | ||
|
|
f8c33e8630 | ||
|
|
b6efea266e | ||
|
|
8686cb3d3d | ||
|
|
91fff2a2c8 | ||
|
|
d6f43bd156 | ||
|
|
ebbe546033 | ||
|
|
cf0eed6c36 | ||
|
|
feacacc46d | ||
|
|
af53c56ec8 | ||
|
|
019d7b34ca | ||
|
|
622995fb12 | ||
|
|
03586c60da | ||
|
|
07a39e8e18 | ||
|
|
1d7c177606 | ||
|
|
2ae490cd8f | ||
|
|
6fda7a7057 | ||
|
|
1e2833e07b | ||
|
|
067b0a3367 | ||
|
|
24b10179a1 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -36,3 +36,4 @@ core
|
||||
|
||||
/nano.spec
|
||||
/src/nano
|
||||
/src/revision.h
|
||||
|
||||
@@ -2,6 +2,10 @@ Improvements in nano
|
||||
====================
|
||||
|
||||
Since 2.6.0:
|
||||
- Ctrl+Up and Ctrl+Down jump to previous or next block of text.
|
||||
- Feedback during Unicode Input (M-V followed by six digits).
|
||||
- The option 'wordchars' for specifying extra word characters.
|
||||
- Hi-bit control characters are shown in a more readable manner.
|
||||
- The ability to use negative numbers at the Go To Line prompt.
|
||||
|
||||
Noteworthy changes since 2.2
|
||||
|
||||
13
NEWS
13
NEWS
@@ -1,3 +1,16 @@
|
||||
2016.07.28 - nano 2.6.2 "Le vent nous portera" adds two new features: the
|
||||
keystrokes Ctrl+Up and Ctrl+Down for jumping between blocks
|
||||
of text, and the option 'wordchars' for specifying which
|
||||
characters (beside alphanumeric ones) should be considered
|
||||
word-forming. Further, it provides feedback during Unicode
|
||||
input (M-V followed by a six-digit hexadecimal number which
|
||||
must start with 0 or 10), avoids a crash when resizing the
|
||||
window during Verbatim input, doesn't drop a keystroke after
|
||||
having been suspended, and replaces the beginning-of-line
|
||||
anchor (^) just once per line. There are also several tiny
|
||||
improvements in screen rendering and key handling. Come get
|
||||
your hair tousled!
|
||||
|
||||
2016.06.27 - nano 2.6.1 "Stampede" is chiefly a translation update, but also
|
||||
adds one little feature (the ability to use negative numbers
|
||||
with Go To Line: -1 meaning the first line from the bottom),
|
||||
|
||||
10
configure.ac
10
configure.ac
@@ -18,7 +18,7 @@
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
|
||||
# USA.
|
||||
|
||||
AC_INIT([nano], [2.6.1], [nano-devel@gnu.org], [nano])
|
||||
AC_INIT([nano], [2.6.2], [nano-devel@gnu.org], [nano])
|
||||
AC_CONFIG_SRCDIR([src/nano.c])
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE
|
||||
@@ -708,16 +708,16 @@ AM_CONDITIONAL(GROFF_HTML, test x$groff_html_support = xyes)
|
||||
AC_CHECK_PROG(haveit, makeinfo, yes, no)
|
||||
AM_CONDITIONAL(HAVE_MAKEINFO, test x$haveit = xyes)
|
||||
|
||||
# Check whether this is a git repository.
|
||||
AC_MSG_CHECKING([whether building from git])
|
||||
if test -d .git ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_PATH_PROG([GIT], [git])
|
||||
REVISION=`($GIT rev-parse --is-inside-work-tree >/dev/null 2>&1) && ($GIT rev-parse --short HEAD)`
|
||||
AC_SUBST(REVISION)
|
||||
AC_DEFINE_UNQUOTED([REVISION],"${REVISION}","Setting REVISION in config.h.")
|
||||
from_git=yes
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
from_git=no
|
||||
fi
|
||||
AM_CONDITIONAL(BUILDING_FROM_GIT, test x$from_git = xyes)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANO 1 "version 2.6.1" "June 2016"
|
||||
.TH NANO 1 "version 2.6.2" "July 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
|
||||
@@ -148,9 +148,14 @@ keystroke instead of 25. Note that \fB\-c\fP overrides this.
|
||||
Show the current version number and exit.
|
||||
.TP
|
||||
.BR \-W ", " \-\-wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as part of a word.
|
||||
.TP
|
||||
.BR "\-X ""\fIcharacters\fB""" ", " "\-\-wordchars=""" \fIcharacters """
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as part of a word. This overrides option
|
||||
\fB\-W\fR (\fB\-\-wordbounds\fR).
|
||||
.TP
|
||||
.BR \-Y\ \fIname\fR ", " \-\-syntax= \fIname
|
||||
Specify the name of the syntax highlighting to use from among the ones
|
||||
defined in the \fInanorc\fP files.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANORC 5 "version 2.6.1" "June 2016"
|
||||
.TH NANORC 5 "version 2.6.2" "July 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.SH NAME
|
||||
@@ -253,8 +253,13 @@ Set the two characters used to indicate the presence of tabs and
|
||||
spaces. They must be single-column characters.
|
||||
.TP
|
||||
.B set wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as parts of words.
|
||||
.TP
|
||||
.B set wordchars \fIstring\fP
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as parts of words. This overrides the option
|
||||
\fBwordbounds\fR.
|
||||
|
||||
.SH SYNTAX HIGHLIGHTING
|
||||
Coloring the different syntactic elements of a file
|
||||
@@ -505,6 +510,13 @@ Moves the cursor to the beginning of the current paragraph.
|
||||
.B endpara
|
||||
Moves the cursor to the end of the current paragraph.
|
||||
.TP
|
||||
.B prevblock
|
||||
Moves the cursor to the beginning of the current or preceding block of text.
|
||||
(Blocks are separated by one or more blank lines.)
|
||||
.TP
|
||||
.B nextblock
|
||||
Moves the cursor to the beginning of the next block of text.
|
||||
.TP
|
||||
.B prevpage
|
||||
Goes up one screenful.
|
||||
.TP
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 2.6.1" "June 2016"
|
||||
.TH RNANO 1 "version 2.6.2" "July 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.SH NAME
|
||||
|
||||
@@ -178,10 +178,15 @@
|
||||
## The default otherwise:
|
||||
# set whitespace ">."
|
||||
|
||||
## Detect word boundaries more accurately by treating punctuation
|
||||
## Detect word boundaries differently by treating punctuation
|
||||
## characters as parts of words.
|
||||
# set wordbounds
|
||||
|
||||
## The characters (besides alphanumeric ones) that should be considered
|
||||
## as parts of words. This option does not have a default value. When
|
||||
## set, it overrides option 'set wordbounds'.
|
||||
# set wordchars "<_>."
|
||||
|
||||
|
||||
## Paint the interface elements of nano.
|
||||
## This is an example; by default there are no colors.
|
||||
|
||||
@@ -20,7 +20,7 @@ color red "[a-z_]+!"
|
||||
color magenta "[A-Z][A-Z_0-9]+"
|
||||
|
||||
# Traits/Enums/Structs/Types/...
|
||||
color magenta "[A-Z][a-z0-9]+"
|
||||
color magenta "[A-Z][A-Za-z0-9]+"
|
||||
|
||||
# Strings
|
||||
color green "\".*\""
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
@smallbook
|
||||
@set EDITION 0.4
|
||||
@set VERSION 2.6.1
|
||||
@set UPDATED June 2016
|
||||
@set VERSION 2.6.2
|
||||
@set UPDATED July 2016
|
||||
|
||||
@dircategory Editors
|
||||
@direntry
|
||||
@@ -21,7 +21,7 @@
|
||||
@titlepage
|
||||
@title @code{nano}
|
||||
@subtitle a small and friendly text editor.
|
||||
@subtitle version 2.6.1
|
||||
@subtitle version 2.6.2
|
||||
|
||||
@author Chris Allegretta
|
||||
@page
|
||||
@@ -231,9 +231,15 @@ Show the current version number and exit.
|
||||
|
||||
@item -W
|
||||
@itemx --wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as parts of words.
|
||||
|
||||
@item -X "@var{characters}"
|
||||
@itemx --wordchars="@var{characters}"
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as parts of words. This overrides option
|
||||
@option{-W} (@option{--wordbounds}).
|
||||
|
||||
@item -Y @var{name}
|
||||
@itemx --syntax=@var{name}
|
||||
Specify a specific syntax from the nanorc files to use for highlighting.
|
||||
@@ -831,9 +837,14 @@ spaces. They must be single-column characters. The default pair
|
||||
for a UTF-8 locale is @t{"»·"}, and for other locales @t{">."}.
|
||||
|
||||
@item set wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as part of a word.
|
||||
|
||||
@item set wordchars "@var{string}"
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as parts of words. This overrides the option
|
||||
@code{wordbounds}.
|
||||
|
||||
@end table
|
||||
|
||||
@node Syntax Highlighting
|
||||
@@ -1091,6 +1102,13 @@ Moves the cursor to the beginning of the current paragraph.
|
||||
@item endpara
|
||||
Moves the cursor to the end of the current paragraph.
|
||||
|
||||
@item prevblock
|
||||
Moves the cursor to the beginning of the current or preceding block of text.
|
||||
(Blocks are separated by one or more blank lines.)
|
||||
|
||||
@item nextblock
|
||||
Moves the cursor to the beginning of the next block of text.
|
||||
|
||||
@item prevpage
|
||||
Goes up one screenful.
|
||||
|
||||
|
||||
982
po/nano.pot
982
po/nano.pot
File diff suppressed because it is too large
Load Diff
847
po/pt_BR.po
847
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
834
po/zh_CN.po
834
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
834
po/zh_TW.po
834
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,21 @@
|
||||
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
|
||||
if BUILDING_FROM_GIT
|
||||
SOMETHING = "REVISION \"$(shell git describe --tags 2>/dev/null)\""
|
||||
else
|
||||
SOMETHING = "NOTHING \"from tarball\""
|
||||
endif
|
||||
|
||||
nano.o: revision.h
|
||||
winio.o: revision.h
|
||||
|
||||
revision.h: update_revision
|
||||
@[ -f $@ ] || touch $@
|
||||
@echo "#define $(SOMETHING)" | cmp -s $@ - || \
|
||||
echo "#define $(SOMETHING)" > $@
|
||||
|
||||
.PHONY: update_revision
|
||||
|
||||
bin_PROGRAMS = nano
|
||||
nano_SOURCES = browser.c \
|
||||
chars.c \
|
||||
|
||||
146
src/browser.c
146
src/browser.c
@@ -46,7 +46,7 @@ static size_t selected = 0;
|
||||
* start browsing from. */
|
||||
char *do_browser(char *path)
|
||||
{
|
||||
char *retval = NULL, *newpath = NULL;
|
||||
char *retval = NULL;
|
||||
int kbinput;
|
||||
char *present_name = NULL;
|
||||
/* The name of the currently selected file, or of the directory we
|
||||
@@ -55,29 +55,19 @@ char *do_browser(char *path)
|
||||
/* The number of the selected file before the current selected file. */
|
||||
functionptrtype func;
|
||||
/* The function of the key the user typed in. */
|
||||
DIR *dir = opendir(path);
|
||||
|
||||
/* If we can't open the given directory, forget it. */
|
||||
if (dir == NULL) {
|
||||
beep();
|
||||
free(path);
|
||||
return NULL;
|
||||
}
|
||||
DIR *dir;
|
||||
/* The directory whose contents we are showing. */
|
||||
|
||||
/* Don't show a cursor in the file list. */
|
||||
curs_set(0);
|
||||
blank_statusbar();
|
||||
bottombars(MBROWSER);
|
||||
|
||||
read_directory_contents:
|
||||
/* We come here when we refresh or select a new directory. */
|
||||
|
||||
/* Start with no key pressed. */
|
||||
kbinput = ERR;
|
||||
path = free_and_assign(path, get_full_path(path));
|
||||
|
||||
path = mallocstrassn(path, get_full_path(newpath ? newpath : path));
|
||||
|
||||
if (path != NULL && newpath != NULL)
|
||||
if (path != NULL)
|
||||
dir = opendir(path);
|
||||
|
||||
if (path == NULL || dir == NULL) {
|
||||
@@ -115,50 +105,26 @@ char *do_browser(char *path)
|
||||
|
||||
old_selected = (size_t)-1;
|
||||
|
||||
free(newpath);
|
||||
newpath = NULL;
|
||||
present_path = mallocstrcpy(present_path, path);
|
||||
|
||||
titlebar(path);
|
||||
|
||||
while (TRUE) {
|
||||
struct stat st;
|
||||
int i;
|
||||
|
||||
/* Make sure that the cursor is off. */
|
||||
curs_set(0);
|
||||
lastmessage = HUSH;
|
||||
|
||||
bottombars(MBROWSER);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH) {
|
||||
/* Remember the selected file, to be able to reselect it. */
|
||||
present_name = strdup(filelist[selected]);
|
||||
|
||||
/* Reopen the current directory. */
|
||||
dir = opendir(path);
|
||||
if (dir != NULL)
|
||||
goto read_directory_contents;
|
||||
|
||||
statusline(ALERT, _("Error reading %s: %s"), path, strerror(errno));
|
||||
kbinput = ERR;
|
||||
}
|
||||
#endif
|
||||
/* Display (or redisplay) the file list if we don't have a key yet,
|
||||
* or the list has changed, or the selected file has changed. */
|
||||
if (kbinput == ERR || old_selected != selected)
|
||||
/* Display (or redisplay) the file list if the list itself or
|
||||
* the selected file has changed. */
|
||||
if (old_selected != selected)
|
||||
browser_refresh();
|
||||
|
||||
old_selected = selected;
|
||||
|
||||
kbinput = get_kbinput(edit);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_MOUSE
|
||||
if (kbinput == KEY_MOUSE) {
|
||||
int mouse_x, mouse_y;
|
||||
@@ -194,15 +160,15 @@ char *do_browser(char *path)
|
||||
|
||||
if (func == total_refresh) {
|
||||
total_redraw();
|
||||
/* Simulate a window resize to force a directory reread. */
|
||||
#ifndef NANO_TINY
|
||||
/* Simulate a window resize to force a directory reread. */
|
||||
kbinput = KEY_WINCH;
|
||||
#endif
|
||||
} else if (func == do_help_void) {
|
||||
#ifndef DISABLE_HELP
|
||||
do_help_void();
|
||||
/* The window dimensions might have changed, so act as if. */
|
||||
#ifndef NANO_TINY
|
||||
/* The window dimensions might have changed, so act as if. */
|
||||
kbinput = KEY_WINCH;
|
||||
#endif
|
||||
#else
|
||||
@@ -214,6 +180,26 @@ char *do_browser(char *path)
|
||||
} else if (func == do_research) {
|
||||
/* Search for another filename. */
|
||||
do_fileresearch();
|
||||
} else if (func == do_left) {
|
||||
if (selected > 0)
|
||||
selected--;
|
||||
} else if (func == do_right) {
|
||||
if (selected < filelist_len - 1)
|
||||
selected++;
|
||||
#ifndef NANO_TINY
|
||||
} else if (func == do_prev_word_void) {
|
||||
selected -= (selected % width);
|
||||
} else if (func == do_next_word_void) {
|
||||
selected += width - 1 - (selected % width);
|
||||
if (selected >= filelist_len)
|
||||
selected = filelist_len - 1;
|
||||
#endif
|
||||
} else if (func == do_up_void) {
|
||||
if (selected >= width)
|
||||
selected -= width;
|
||||
} else if (func == do_down_void) {
|
||||
if (selected + width <= filelist_len - 1)
|
||||
selected += width;
|
||||
} else if (func == do_page_up) {
|
||||
if (selected < width)
|
||||
selected = 0;
|
||||
@@ -235,7 +221,7 @@ char *do_browser(char *path)
|
||||
selected = filelist_len - 1;
|
||||
} else if (func == goto_dir_void) {
|
||||
/* Ask for the directory to go to. */
|
||||
i = do_prompt(TRUE,
|
||||
int i = do_prompt(TRUE,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
FALSE,
|
||||
#endif
|
||||
@@ -245,6 +231,7 @@ char *do_browser(char *path)
|
||||
#endif
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
browser_refresh, _("Go To Directory"));
|
||||
|
||||
/* If the directory begins with a newline (i.e. an
|
||||
* encoded null), treat it as though it's blank. */
|
||||
if (i < 0 || *answer == '\n') {
|
||||
@@ -256,55 +243,41 @@ char *do_browser(char *path)
|
||||
sunder(answer);
|
||||
align(&answer);
|
||||
|
||||
newpath = real_dir_from_tilde(answer);
|
||||
path = free_and_assign(path, real_dir_from_tilde(answer));
|
||||
|
||||
if (newpath[0] != '/') {
|
||||
newpath = charealloc(newpath, strlen(path) +
|
||||
strlen(answer) + 1);
|
||||
sprintf(newpath, "%s%s", path, answer);
|
||||
/* If the given path is relative, join it with the current path. */
|
||||
if (*path != '/') {
|
||||
path = charealloc(path, strlen(present_path) +
|
||||
strlen(answer) + 1);
|
||||
sprintf(path, "%s%s", present_path, answer);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
if (check_operating_dir(newpath, FALSE)) {
|
||||
if (check_operating_dir(path, FALSE)) {
|
||||
/* TRANSLATORS: This refers to the confining effect of the
|
||||
* option --operatingdir, not of --restricted. */
|
||||
statusline(ALERT, _("Can't go outside of %s"),
|
||||
full_operating_dir);
|
||||
free(newpath);
|
||||
newpath = NULL;
|
||||
path = mallocstrcpy(path, present_path);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Snip any trailing slashes, so the name can be compared. */
|
||||
while (strlen(path) > 1 && path[strlen(path) - 1] == '/')
|
||||
path[strlen(path) - 1] = '\0';
|
||||
|
||||
/* In case the specified directory cannot be entered, select it
|
||||
* (if it is in the current list) so it will be highlighted. */
|
||||
for (i = 0; i < filelist_len; i++)
|
||||
if (strcmp(filelist[i], newpath) == 0)
|
||||
if (strcmp(filelist[i], path) == 0)
|
||||
selected = i;
|
||||
|
||||
/* Try opening and reading the specified directory. */
|
||||
goto read_directory_contents;
|
||||
} else if (func == do_up_void) {
|
||||
if (selected >= width)
|
||||
selected -= width;
|
||||
} else if (func == do_down_void) {
|
||||
if (selected + width <= filelist_len - 1)
|
||||
selected += width;
|
||||
#ifndef NANO_TINY
|
||||
} else if (func == do_prev_word_void) {
|
||||
selected -= (selected % width);
|
||||
} else if (func == do_next_word_void) {
|
||||
selected += width - 1 - (selected % width);
|
||||
if (selected >= filelist_len)
|
||||
selected = filelist_len - 1;
|
||||
#endif
|
||||
} else if (func == do_left) {
|
||||
if (selected > 0)
|
||||
selected--;
|
||||
} else if (func == do_right) {
|
||||
if (selected < filelist_len - 1)
|
||||
selected++;
|
||||
} else if (func == do_enter) {
|
||||
/* We can't move up from "/". */
|
||||
struct stat st;
|
||||
|
||||
/* It isn't possible to move up from the root directory. */
|
||||
if (strcmp(filelist[selected], "/..") == 0) {
|
||||
statusline(ALERT, _("Can't move up a directory"));
|
||||
continue;
|
||||
@@ -320,16 +293,15 @@ char *do_browser(char *path)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If for some reason the file is inaccessible, complain. */
|
||||
if (stat(filelist[selected], &st) == -1) {
|
||||
/* We can't open this file for some reason. Complain. */
|
||||
statusline(ALERT, _("Error reading %s: %s"),
|
||||
filelist[selected], strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If it isn't a directory, a file was selected -- we're done. */
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
/* We've successfully opened a file, so we're done. */
|
||||
retval = mallocstrcpy(NULL, filelist[selected]);
|
||||
break;
|
||||
}
|
||||
@@ -340,13 +312,27 @@ char *do_browser(char *path)
|
||||
present_name = striponedir(filelist[selected]);
|
||||
|
||||
/* Try opening and reading the selected directory. */
|
||||
newpath = strdup(filelist[selected]);
|
||||
path = mallocstrcpy(path, filelist[selected]);
|
||||
goto read_directory_contents;
|
||||
} else if (func == do_exit) {
|
||||
/* Exit from the file browser. */
|
||||
break;
|
||||
#ifndef NANO_TINY
|
||||
} else if (kbinput == KEY_WINCH) {
|
||||
;
|
||||
#endif
|
||||
} else
|
||||
unbound_key(kbinput);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the window resized, refresh the file list. */
|
||||
if (kbinput == KEY_WINCH) {
|
||||
/* Remember the selected file, to be able to reselect it. */
|
||||
present_name = mallocstrcpy(NULL, filelist[selected]);
|
||||
/* Reread the contents of the current directory. */
|
||||
goto read_directory_contents;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
titlebar(NULL);
|
||||
@@ -381,7 +367,7 @@ char *do_browse_from(const char *inpath)
|
||||
* at all. If so, we'll just pass the current directory to
|
||||
* do_browser(). */
|
||||
if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
|
||||
path = mallocstrassn(path, striponedir(path));
|
||||
path = free_and_assign(path, striponedir(path));
|
||||
|
||||
if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
|
||||
char * currentdir = charalloc(PATH_MAX + 1);
|
||||
|
||||
215
src/chars.c
215
src/chars.c
@@ -35,12 +35,6 @@
|
||||
|
||||
static bool use_utf8 = FALSE;
|
||||
/* Whether we've enabled UTF-8 support. */
|
||||
static const wchar_t bad_wchar = 0xFFFD;
|
||||
/* If we get an invalid multibyte sequence, we treat it as
|
||||
* Unicode FFFD (Replacement Character), unless we're searching
|
||||
* for a match to it. */
|
||||
static const char *const bad_mbchar = "\xEF\xBF\xBD";
|
||||
static const int bad_mbchar_len = 3;
|
||||
|
||||
/* Enable UTF-8 support. */
|
||||
void utf8_init(void)
|
||||
@@ -110,7 +104,7 @@ bool is_alnum_mbchar(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswalnum(wc);
|
||||
@@ -130,7 +124,7 @@ bool is_blank_mbchar(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswblank(wc);
|
||||
@@ -150,20 +144,9 @@ bool is_ascii_cntrl_char(int c)
|
||||
* handles high-bit control characters. */
|
||||
bool is_cntrl_char(int c)
|
||||
{
|
||||
return (-128 <= c && c < -96) || (0 <= c && c < 32) ||
|
||||
(127 <= c && c < 160);
|
||||
return ((c & 0x60) == 0 || c == 127);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* This function is equivalent to iscntrl() for wide characters, except
|
||||
* in that it also handles wide control characters with their high bits
|
||||
* set. */
|
||||
bool is_cntrl_wchar(wchar_t wc)
|
||||
{
|
||||
return (0 <= wc && wc < 32) || (127 <= wc && wc < 160);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function is equivalent to iscntrl() for multibyte characters,
|
||||
* except in that it also handles multibyte control characters with
|
||||
* their high bits set. */
|
||||
@@ -173,14 +156,8 @@ bool is_cntrl_mbchar(const char *c)
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
}
|
||||
|
||||
return is_cntrl_wchar(wc);
|
||||
return ((c[0] & 0xE0) == 0 || c[0] == 127 ||
|
||||
((signed char)c[0] == -62 && (signed char)c[1] < -96));
|
||||
} else
|
||||
#endif
|
||||
return is_cntrl_char((unsigned char)*c);
|
||||
@@ -197,7 +174,7 @@ bool is_punct_mbchar(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswpunct(wc);
|
||||
@@ -206,103 +183,100 @@ bool is_punct_mbchar(const char *c)
|
||||
return ispunct((unsigned char)*c);
|
||||
}
|
||||
|
||||
/* Return TRUE for a multibyte character found in a word (currently only
|
||||
* an alphanumeric or punctuation character, and only the latter if
|
||||
* allow_punct is TRUE) and FALSE otherwise. */
|
||||
/* Return TRUE when the given multibyte character c is a word-forming
|
||||
* character (that is: alphanumeric, or specified in wordchars, or
|
||||
* punctuation when allow_punct is TRUE), and FALSE otherwise. */
|
||||
bool is_word_mbchar(const char *c, bool allow_punct)
|
||||
{
|
||||
assert(c != NULL);
|
||||
|
||||
return is_alnum_mbchar(c) || (allow_punct ? is_punct_mbchar(c) :
|
||||
FALSE);
|
||||
if (*c == '\0')
|
||||
return FALSE;
|
||||
|
||||
if (is_alnum_mbchar(c))
|
||||
return TRUE;
|
||||
|
||||
if (word_chars != NULL && *word_chars != '\0') {
|
||||
bool wordforming;
|
||||
char *symbol = charalloc(MB_CUR_MAX + 1);
|
||||
int symlen = parse_mbchar(c, symbol, NULL);
|
||||
|
||||
symbol[symlen] = '\0';
|
||||
wordforming = (strstr(word_chars, symbol) != NULL);
|
||||
free(symbol);
|
||||
|
||||
return wordforming;
|
||||
}
|
||||
|
||||
return (allow_punct && is_punct_mbchar(c));
|
||||
}
|
||||
|
||||
/* c is a control character. It displays as ^@, ^?, or ^[ch], where ch
|
||||
* is (c + 64). We return that character. */
|
||||
char control_rep(char c)
|
||||
/* Return the visible representation of control character c. */
|
||||
char control_rep(const signed char c)
|
||||
{
|
||||
assert(is_cntrl_char(c));
|
||||
|
||||
/* Treat newlines embedded in a line as encoded nulls. */
|
||||
/* An embedded newline is an encoded null. */
|
||||
if (c == '\n')
|
||||
return '@';
|
||||
else if (c == NANO_CONTROL_8)
|
||||
return '?';
|
||||
else if (c == -97)
|
||||
return '=';
|
||||
else if (c < 0)
|
||||
return c + 224;
|
||||
else
|
||||
return c + 64;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* c is a wide control character. It displays as ^@, ^?, or ^[ch],
|
||||
* where ch is (c + 64). We return that wide character. */
|
||||
wchar_t control_wrep(wchar_t wc)
|
||||
/* Return the visible representation of multibyte control character c. */
|
||||
char control_mbrep(const char *c)
|
||||
{
|
||||
assert(is_cntrl_wchar(wc));
|
||||
|
||||
/* Treat newlines embedded in a line as encoded nulls. */
|
||||
if (wc == '\n')
|
||||
return '@';
|
||||
else if (wc == NANO_CONTROL_8)
|
||||
return '?';
|
||||
else
|
||||
return wc + 64;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* c is a multibyte control character. It displays as ^@, ^?, or ^[ch],
|
||||
* where ch is (c + 64). We return that multibyte character. */
|
||||
char *control_mbrep(const char *c, char *crep, int *crep_len)
|
||||
{
|
||||
assert(c != NULL && crep != NULL && crep_len != NULL);
|
||||
assert(c != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
|
||||
IGNORE_CALL_RESULT(mbtowc(&wc, c, MB_CUR_MAX));
|
||||
*crep_len = wctomb(crep, control_wrep(wc));
|
||||
if (0 <= c[0] && c[0] <= 127)
|
||||
return control_rep(c[0]);
|
||||
else
|
||||
return control_rep(c[1]);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
*crep_len = 1;
|
||||
*crep = control_rep(*c);
|
||||
}
|
||||
|
||||
return crep;
|
||||
return control_rep(*c);
|
||||
}
|
||||
|
||||
/* c is a multibyte non-control character. We return that multibyte
|
||||
* character. If crep is an invalid multibyte sequence, it will be
|
||||
* replaced with Unicode 0xFFFD (Replacement Character). */
|
||||
char *mbrep(const char *c, char *crep, int *crep_len)
|
||||
/* Assess how many bytes the given (multibyte) character occupies. Return -1
|
||||
* if the byte sequence is invalid, and return the number of bytes minus 8
|
||||
* when it encodes an invalid codepoint. Also, in the second parameter,
|
||||
* return the number of columns that the character occupies. */
|
||||
int length_of_char(const char *c, int *width)
|
||||
{
|
||||
assert(c != NULL && crep != NULL && crep_len != NULL);
|
||||
assert(c != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
int charlen = mbtowc(&wc, c, MB_CUR_MAX);
|
||||
|
||||
/* Reject invalid Unicode characters. */
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0 || !is_valid_unicode(wc)) {
|
||||
/* If the sequence is invalid... */
|
||||
if (charlen < 0) {
|
||||
mbtowc_reset();
|
||||
*crep_len = bad_mbchar_len;
|
||||
strncpy(crep, bad_mbchar, *crep_len);
|
||||
} else {
|
||||
*crep_len = wctomb(crep, wc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*crep_len < 0) {
|
||||
wctomb_reset();
|
||||
*crep_len = 0;
|
||||
}
|
||||
/* If the codepoint is invalid... */
|
||||
if (!is_valid_unicode(wc))
|
||||
return charlen - 8;
|
||||
else {
|
||||
*width = wcwidth(wc);
|
||||
/* If the codepoint is unassigned, assume a width of one. */
|
||||
if (*width < 0)
|
||||
*width = 1;
|
||||
return charlen;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
*crep_len = 1;
|
||||
*crep = *c;
|
||||
}
|
||||
|
||||
return crep;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function is equivalent to wcwidth() for multibyte characters. */
|
||||
@@ -317,15 +291,13 @@ int mbwidth(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 1;
|
||||
}
|
||||
|
||||
width = wcwidth(wc);
|
||||
|
||||
if (width == -1) {
|
||||
wc = bad_wchar;
|
||||
width = wcwidth(wc);
|
||||
}
|
||||
if (width == -1)
|
||||
return 1;
|
||||
|
||||
return width;
|
||||
} else
|
||||
@@ -667,7 +639,6 @@ char *mbrevstrcasestr(const char *haystack, const char *needle, const
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool begin_line = FALSE;
|
||||
size_t rev_start_len, needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL && rev_start != NULL);
|
||||
@@ -682,22 +653,19 @@ char *mbrevstrcasestr(const char *haystack, const char *needle, const
|
||||
|
||||
rev_start_len = mbstrlen(rev_start);
|
||||
|
||||
while (!begin_line) {
|
||||
while (TRUE) {
|
||||
if (rev_start_len >= needle_len &&
|
||||
mbstrncasecmp(rev_start, needle, needle_len) == 0 &&
|
||||
mblen(rev_start, MB_CUR_MAX) > 0)
|
||||
return (char *)rev_start;
|
||||
|
||||
/* If we've reached the head of the haystack, we found nothing. */
|
||||
if (rev_start == haystack)
|
||||
begin_line = TRUE;
|
||||
else {
|
||||
rev_start = haystack + move_mbleft(haystack, rev_start -
|
||||
haystack);
|
||||
rev_start_len++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
rev_start = haystack + move_mbleft(haystack, rev_start - haystack);
|
||||
rev_start_len++;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
return revstrcasestr(haystack, needle, rev_start);
|
||||
@@ -817,11 +785,14 @@ char *revstrpbrk(const char *s, const char *accept, const char
|
||||
{
|
||||
assert(s != NULL && accept != NULL && rev_start != NULL);
|
||||
|
||||
for (; rev_start >= s; rev_start--) {
|
||||
const char *q = (*rev_start == '\0') ? NULL : strchr(accept,
|
||||
*rev_start);
|
||||
if (*rev_start == '\0') {
|
||||
if (rev_start == s)
|
||||
return NULL;
|
||||
rev_start--;
|
||||
}
|
||||
|
||||
if (q != NULL)
|
||||
for (; rev_start >= s; rev_start--) {
|
||||
if (strchr(accept, *rev_start) != NULL)
|
||||
return (char *)rev_start;
|
||||
}
|
||||
|
||||
@@ -837,22 +808,22 @@ char *mbrevstrpbrk(const char *s, const char *accept, const char
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool begin_line = FALSE;
|
||||
|
||||
while (!begin_line) {
|
||||
const char *q = (*rev_start == '\0') ? NULL :
|
||||
mbstrchr(accept, rev_start);
|
||||
|
||||
if (q != NULL)
|
||||
return (char *)rev_start;
|
||||
|
||||
if (*rev_start == '\0') {
|
||||
if (rev_start == s)
|
||||
begin_line = TRUE;
|
||||
else
|
||||
rev_start = s + move_mbleft(s, rev_start - s);
|
||||
return NULL;
|
||||
rev_start = s + move_mbleft(s, rev_start - s);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
while (TRUE) {
|
||||
if (mbstrchr(accept, rev_start) != NULL)
|
||||
return (char *)rev_start;
|
||||
|
||||
/* If we've reached the head of the string, we found nothing. */
|
||||
if (rev_start == s)
|
||||
return NULL;
|
||||
|
||||
rev_start = s + move_mbleft(s, rev_start - s);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
return revstrpbrk(s, accept, rev_start);
|
||||
|
||||
132
src/color.c
132
src/color.c
@@ -38,7 +38,7 @@
|
||||
* for the colors in each syntax. */
|
||||
void set_colorpairs(void)
|
||||
{
|
||||
const syntaxtype *this_syntax = syntaxes;
|
||||
const syntaxtype *sint;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
size_t i;
|
||||
@@ -62,15 +62,14 @@ void set_colorpairs(void)
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
init_pair(i + 1, foreground, background);
|
||||
interface_color_pair[i].bright = bright;
|
||||
interface_color_pair[i].pairnum = COLOR_PAIR(i + 1);
|
||||
interface_color_pair[i] =
|
||||
COLOR_PAIR(i + 1) | (bright ? A_BOLD : A_NORMAL);
|
||||
}
|
||||
else {
|
||||
interface_color_pair[i].bright = FALSE;
|
||||
if (i != FUNCTION_TAG)
|
||||
interface_color_pair[i].pairnum = hilite_attribute;
|
||||
interface_color_pair[i] = hilite_attribute;
|
||||
else
|
||||
interface_color_pair[i].pairnum = A_NORMAL;
|
||||
interface_color_pair[i] = A_NORMAL;
|
||||
}
|
||||
|
||||
free(specified_color_combo[i]);
|
||||
@@ -79,25 +78,25 @@ void set_colorpairs(void)
|
||||
|
||||
/* For each syntax, go through its list of colors and assign each
|
||||
* its pair number, giving identical color pairs the same number. */
|
||||
for (; this_syntax != NULL; this_syntax = this_syntax->next) {
|
||||
colortype *this_color = this_syntax->color;
|
||||
int clr_pair = NUMBER_OF_ELEMENTS + 1;
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
colortype *ink;
|
||||
int new_number = NUMBER_OF_ELEMENTS + 1;
|
||||
|
||||
for (; this_color != NULL; this_color = this_color->next) {
|
||||
const colortype *beforenow = this_syntax->color;
|
||||
for (ink = sint->color; ink != NULL; ink = ink->next) {
|
||||
const colortype *beforenow = sint->color;
|
||||
|
||||
while (beforenow != this_color &&
|
||||
(beforenow->fg != this_color->fg ||
|
||||
beforenow->bg != this_color->bg ||
|
||||
beforenow->bright != this_color->bright))
|
||||
while (beforenow != ink && (beforenow->fg != ink->fg ||
|
||||
beforenow->bg != ink->bg ||
|
||||
beforenow->bright != ink->bright))
|
||||
beforenow = beforenow->next;
|
||||
|
||||
if (beforenow != this_color)
|
||||
this_color->pairnum = beforenow->pairnum;
|
||||
else {
|
||||
this_color->pairnum = clr_pair;
|
||||
clr_pair++;
|
||||
}
|
||||
if (beforenow != ink)
|
||||
ink->pairnum = beforenow->pairnum;
|
||||
else
|
||||
ink->pairnum = new_number++;
|
||||
|
||||
ink->attributes = COLOR_PAIR(ink->pairnum) |
|
||||
(ink->bright ? A_BOLD : A_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,7 +104,7 @@ void set_colorpairs(void)
|
||||
/* Initialize the color information. */
|
||||
void color_init(void)
|
||||
{
|
||||
colortype *tmpcolor = openfile->colorstrings;
|
||||
const colortype *ink;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
|
||||
@@ -121,9 +120,9 @@ void color_init(void)
|
||||
#endif
|
||||
|
||||
/* For each coloring expression, initialize the color pair. */
|
||||
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
||||
foreground = tmpcolor->fg;
|
||||
background = tmpcolor->bg;
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
foreground = ink->fg;
|
||||
background = ink->bg;
|
||||
|
||||
if (foreground == -1 && !using_defaults)
|
||||
foreground = COLOR_WHITE;
|
||||
@@ -131,7 +130,7 @@ void color_init(void)
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
|
||||
init_pair(tmpcolor->pairnum, foreground, background);
|
||||
init_pair(ink->pairnum, foreground, background);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "init_pair(): fg = %hd, bg = %hd\n", foreground, background);
|
||||
#endif
|
||||
@@ -340,42 +339,47 @@ void reset_multis_for_id(filestruct *fileptr, int index)
|
||||
* useful when we don't know how much screen state has changed. */
|
||||
void reset_multis(filestruct *fileptr, bool force)
|
||||
{
|
||||
int nobegin, noend;
|
||||
const colortype *ink;
|
||||
int nobegin = 0, noend = 0;
|
||||
regmatch_t startmatch, endmatch;
|
||||
const colortype *tmpcolor = openfile->colorstrings;
|
||||
|
||||
/* If there is no syntax or no multiline regex, there is nothing to do. */
|
||||
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
|
||||
return;
|
||||
|
||||
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If it's not a multi-line regex, amscray. */
|
||||
if (tmpcolor->end == NULL)
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
|
||||
alloc_multidata_if_needed(fileptr);
|
||||
|
||||
if (force == FALSE) {
|
||||
/* Check whether the multidata still matches the current situation. */
|
||||
nobegin = regexec(tmpcolor->start, fileptr->data, 1, &startmatch, 0);
|
||||
noend = regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
|
||||
if ((fileptr->multidata[tmpcolor->id] == CWHOLELINE ||
|
||||
fileptr->multidata[tmpcolor->id] == CNONE) &&
|
||||
nobegin = regexec(ink->start, fileptr->data, 1, &startmatch, 0);
|
||||
noend = regexec(ink->end, fileptr->data, 1, &endmatch, 0);
|
||||
if ((fileptr->multidata[ink->id] == CWHOLELINE ||
|
||||
fileptr->multidata[ink->id] == CNONE) &&
|
||||
nobegin && noend)
|
||||
continue;
|
||||
else if (fileptr->multidata[tmpcolor->id] == CSTARTENDHERE &&
|
||||
else if (fileptr->multidata[ink->id] == CSTARTENDHERE &&
|
||||
!nobegin && !noend && startmatch.rm_so < endmatch.rm_so)
|
||||
continue;
|
||||
else if (fileptr->multidata[tmpcolor->id] == CBEGINBEFORE &&
|
||||
else if (fileptr->multidata[ink->id] == CBEGINBEFORE &&
|
||||
nobegin && !noend)
|
||||
continue;
|
||||
else if (fileptr->multidata[tmpcolor->id] == CENDAFTER &&
|
||||
else if (fileptr->multidata[ink->id] == CENDAFTER &&
|
||||
!nobegin && noend)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we got here, things have changed. */
|
||||
reset_multis_for_id(fileptr, tmpcolor->id);
|
||||
reset_multis_for_id(fileptr, ink->id);
|
||||
|
||||
/* If start and end are the same, push the resets further. */
|
||||
if (force == FALSE && !nobegin && !noend &&
|
||||
startmatch.rm_so == endmatch.rm_so)
|
||||
reset_multis_for_id(fileptr, ink->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,23 +396,11 @@ void alloc_multidata_if_needed(filestruct *fileptr)
|
||||
}
|
||||
}
|
||||
|
||||
/* Poll the keyboard every second to see if the user starts typing. */
|
||||
bool key_was_pressed(void)
|
||||
{
|
||||
static time_t last_time = 0;
|
||||
|
||||
if (time(NULL) != last_time) {
|
||||
last_time = time(NULL);
|
||||
return (wgetch(edit) != ERR);
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Precalculate the multi-line start and end regex info so we can
|
||||
* speed up rendering (with any hope at all...). */
|
||||
void precalc_multicolorinfo(void)
|
||||
{
|
||||
const colortype *tmpcolor = openfile->colorstrings;
|
||||
const colortype *ink;
|
||||
regmatch_t startmatch, endmatch;
|
||||
filestruct *fileptr, *endptr;
|
||||
|
||||
@@ -418,32 +410,24 @@ void precalc_multicolorinfo(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Entering precalculation of multiline color info\n");
|
||||
#endif
|
||||
/* Let us get keypresses to see if the user is trying to start
|
||||
* editing. Later we may want to throw up a statusbar message
|
||||
* before starting this if it takes too long to do this routine.
|
||||
* For now silently abort if they hit a key. */
|
||||
nodelay(edit, TRUE);
|
||||
|
||||
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If this is not a multi-line regex, skip it. */
|
||||
if (tmpcolor->end == NULL)
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Starting work on color id %d\n", tmpcolor->id);
|
||||
fprintf(stderr, "Starting work on color id %d\n", ink->id);
|
||||
#endif
|
||||
|
||||
for (fileptr = openfile->fileage; fileptr != NULL; fileptr = fileptr->next) {
|
||||
int startx = 0, nostart = 0;
|
||||
|
||||
if (key_was_pressed())
|
||||
goto precalc_cleanup;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "working on lineno %ld... ", (long)fileptr->lineno);
|
||||
#endif
|
||||
alloc_multidata_if_needed(fileptr);
|
||||
|
||||
while ((nostart = regexec(tmpcolor->start, &fileptr->data[startx],
|
||||
1, &startmatch, (startx == 0) ? 0 : REG_NOTBOL)) == 0) {
|
||||
while ((nostart = regexec(ink->start, &fileptr->data[startx], 1,
|
||||
&startmatch, (startx == 0) ? 0 : REG_NOTBOL)) == 0) {
|
||||
/* Look for an end, and start marking how many lines are
|
||||
* encompassed, which should speed up rendering later. */
|
||||
startx += startmatch.rm_eo;
|
||||
@@ -451,14 +435,14 @@ void precalc_multicolorinfo(void)
|
||||
fprintf(stderr, "start found at pos %lu... ", (unsigned long)startx);
|
||||
#endif
|
||||
/* Look first on this line for an end. */
|
||||
if (regexec(tmpcolor->end, &fileptr->data[startx], 1,
|
||||
if (regexec(ink->end, &fileptr->data[startx], 1,
|
||||
&endmatch, (startx == 0) ? 0 : REG_NOTBOL) == 0) {
|
||||
startx += endmatch.rm_eo;
|
||||
/* Step ahead when both start and end are mere anchors. */
|
||||
if (startmatch.rm_so == startmatch.rm_eo &&
|
||||
endmatch.rm_so == endmatch.rm_eo)
|
||||
startx += 1;
|
||||
fileptr->multidata[tmpcolor->id] = CSTARTENDHERE;
|
||||
fileptr->multidata[ink->id] = CSTARTENDHERE;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "end found on this line\n");
|
||||
#endif
|
||||
@@ -470,11 +454,7 @@ void precalc_multicolorinfo(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\nadvancing to line %ld to find end... ", (long)endptr->lineno);
|
||||
#endif
|
||||
/* Check for interrupting keyboard input again. */
|
||||
if (key_was_pressed())
|
||||
goto precalc_cleanup;
|
||||
|
||||
if (regexec(tmpcolor->end, endptr->data, 1, &endmatch, 0) == 0)
|
||||
if (regexec(ink->end, endptr->data, 1, &endmatch, 0) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -489,20 +469,20 @@ void precalc_multicolorinfo(void)
|
||||
#endif
|
||||
/* We found it, we found it, la la la la la. Mark all
|
||||
* the lines in between and the end properly. */
|
||||
fileptr->multidata[tmpcolor->id] = CENDAFTER;
|
||||
fileptr->multidata[ink->id] = CENDAFTER;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "marking line %ld as CENDAFTER\n", (long)fileptr->lineno);
|
||||
#endif
|
||||
for (fileptr = fileptr->next; fileptr != endptr; fileptr = fileptr->next) {
|
||||
alloc_multidata_if_needed(fileptr);
|
||||
fileptr->multidata[tmpcolor->id] = CWHOLELINE;
|
||||
fileptr->multidata[ink->id] = CWHOLELINE;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "marking intermediary line %ld as CWHOLELINE\n", (long)fileptr->lineno);
|
||||
#endif
|
||||
}
|
||||
|
||||
alloc_multidata_if_needed(endptr);
|
||||
fileptr->multidata[tmpcolor->id] = CBEGINBEFORE;
|
||||
fileptr->multidata[ink->id] = CBEGINBEFORE;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "marking line %ld as CBEGINBEFORE\n", (long)fileptr->lineno);
|
||||
#endif
|
||||
@@ -517,13 +497,11 @@ void precalc_multicolorinfo(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "no match\n");
|
||||
#endif
|
||||
fileptr->multidata[tmpcolor->id] = CNONE;
|
||||
fileptr->multidata[ink->id] = CNONE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
precalc_cleanup:
|
||||
nodelay(edit, FALSE);
|
||||
}
|
||||
|
||||
#endif /* !DISABLE_COLOR */
|
||||
|
||||
80
src/files.c
80
src/files.c
@@ -1226,7 +1226,7 @@ void do_insertfile(
|
||||
{
|
||||
/* Make sure the path to the file specified in answer is
|
||||
* tilde-expanded. */
|
||||
answer = mallocstrassn(answer, real_dir_from_tilde(answer));
|
||||
answer = free_and_assign(answer, real_dir_from_tilde(answer));
|
||||
|
||||
/* Save the file specified in answer in the current buffer. */
|
||||
open_buffer(answer, TRUE);
|
||||
@@ -1695,15 +1695,15 @@ int copy_file(FILE *inn, FILE *out)
|
||||
*
|
||||
* tmp means we are writing a temporary file in a secure fashion. We
|
||||
* use it when spell checking or dumping the file on an error. If
|
||||
* append is APPEND, it means we are appending instead of overwriting.
|
||||
* If append is PREPEND, it means we are prepending instead of
|
||||
* method is APPEND, it means we are appending instead of overwriting.
|
||||
* If method is PREPEND, it means we are prepending instead of
|
||||
* overwriting. If nonamechange is TRUE, we don't change the current
|
||||
* filename. nonamechange is ignored if tmp is FALSE, we're appending,
|
||||
* or we're prepending.
|
||||
* filename. nonamechange is irrelevant when appending or prepending,
|
||||
* or when writing a temporary file.
|
||||
*
|
||||
* Return TRUE on success or FALSE on error. */
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
append, bool nonamechange)
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
kind_of_writing_type method, bool nonamechange)
|
||||
{
|
||||
bool retval = FALSE;
|
||||
/* Instead of returning in this function, you should always
|
||||
@@ -1769,7 +1769,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
* only if the file has not been modified by someone else since nano
|
||||
* opened it. */
|
||||
if (ISSET(BACKUP_FILE) && !tmp && realexists && openfile->current_stat &&
|
||||
(append != OVERWRITE || openfile->mark_set ||
|
||||
(method != OVERWRITE || openfile->mark_set ||
|
||||
openfile->current_stat->st_mtime == st.st_mtime)) {
|
||||
int backup_fd;
|
||||
FILE *backup_file;
|
||||
@@ -1948,7 +1948,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
}
|
||||
|
||||
/* If we're prepending, copy the file to a temp file. */
|
||||
if (append == PREPEND) {
|
||||
if (method == PREPEND) {
|
||||
int fd_source;
|
||||
FILE *f_source = NULL;
|
||||
|
||||
@@ -1965,7 +1965,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
tempname = safe_tempfile(&f);
|
||||
|
||||
if (tempname == NULL) {
|
||||
statusline(HUSH, _("Error writing temp file: %s"),
|
||||
statusline(ALERT, _("Error writing temp file: %s"),
|
||||
strerror(errno));
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
@@ -1987,7 +1987,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
}
|
||||
|
||||
if (f_source == NULL || copy_file(f_source, f) != 0) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), tempname,
|
||||
statusline(ALERT, _("Error writing temp file: %s"),
|
||||
strerror(errno));
|
||||
unlink(tempname);
|
||||
goto cleanup_and_exit;
|
||||
@@ -1997,7 +1997,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
if (f_open == NULL) {
|
||||
/* Now open the file in place. Use O_EXCL if tmp is TRUE. This
|
||||
* is copied from joe, because wiggy says so *shrug*. */
|
||||
fd = open(realname, O_WRONLY | O_CREAT | ((append == APPEND) ?
|
||||
fd = open(realname, O_WRONLY | O_CREAT | ((method == APPEND) ?
|
||||
O_APPEND : (tmp ? O_EXCL : O_TRUNC)), S_IRUSR |
|
||||
S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
|
||||
@@ -2006,17 +2006,17 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
|
||||
/* If we couldn't open the file, give up. */
|
||||
if (fd == -1) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
if (tempname != NULL)
|
||||
unlink(tempname);
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
|
||||
f = fdopen(fd, (append == APPEND) ? "ab" : "wb");
|
||||
f = fdopen(fd, (method == APPEND) ? "ab" : "wb");
|
||||
|
||||
if (f == NULL) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
goto cleanup_and_exit;
|
||||
@@ -2040,7 +2040,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
unsunder(fileptr->data, data_len);
|
||||
|
||||
if (size < data_len) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
fclose(f);
|
||||
goto cleanup_and_exit;
|
||||
@@ -2057,7 +2057,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->fmt == DOS_FILE || openfile->fmt == MAC_FILE) {
|
||||
if (putc('\r', f) == EOF) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
fclose(f);
|
||||
goto cleanup_and_exit;
|
||||
@@ -2067,7 +2067,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
if (openfile->fmt != MAC_FILE)
|
||||
#endif
|
||||
if (putc('\n', f) == EOF) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
fclose(f);
|
||||
goto cleanup_and_exit;
|
||||
@@ -2079,7 +2079,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
}
|
||||
|
||||
/* If we're prepending, open the temp file, and append it to f. */
|
||||
if (append == PREPEND) {
|
||||
if (method == PREPEND) {
|
||||
int fd_source;
|
||||
FILE *f_source = NULL;
|
||||
|
||||
@@ -2099,23 +2099,23 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
}
|
||||
|
||||
if (copy_file(f_source, f) == -1) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
|
||||
unlink(tempname);
|
||||
} else if (fclose(f) != 0) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
|
||||
if (!tmp && append == OVERWRITE) {
|
||||
if (method == OVERWRITE && !tmp) {
|
||||
/* If we must set the filename, and it changed, adjust things. */
|
||||
if (!nonamechange && strcmp(openfile->filename, realname) != 0) {
|
||||
#ifndef DISABLE_COLOR
|
||||
char *syntaxname = openfile->syntax ? openfile->syntax->name : "";
|
||||
char *oldname = openfile->syntax ? openfile->syntax->name : "";
|
||||
filestruct *line = openfile->fileage;
|
||||
#endif
|
||||
openfile->filename = mallocstrcpy(openfile->filename, realname);
|
||||
@@ -2125,19 +2125,17 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
color_update();
|
||||
color_init();
|
||||
|
||||
char *newname = openfile->syntax ? openfile->syntax->name : "";
|
||||
|
||||
/* If the syntax changed, discard and recompute the multidata. */
|
||||
if (openfile->syntax &&
|
||||
strcmp(syntaxname, openfile->syntax->name) != 0) {
|
||||
if (strcmp(oldname, newname) != 0) {
|
||||
for (; line != NULL; line = line->next) {
|
||||
free(line->multidata);
|
||||
line->multidata = NULL;
|
||||
}
|
||||
precalc_multicolorinfo();
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
/* If color syntaxes are available and turned on, refresh. */
|
||||
if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX))
|
||||
edit_refresh();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2166,7 +2164,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
/* Write a marked selection from a file out to disk. Return TRUE on
|
||||
* success or FALSE on error. */
|
||||
bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
append_type append)
|
||||
kind_of_writing_type method)
|
||||
{
|
||||
bool retval;
|
||||
bool old_modified = openfile->modified;
|
||||
@@ -2190,7 +2188,7 @@ bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
added_magicline = TRUE;
|
||||
}
|
||||
|
||||
retval = write_file(name, f_open, tmp, append, TRUE);
|
||||
retval = write_file(name, f_open, tmp, method, TRUE);
|
||||
|
||||
/* If we added a magicline, remove it now. */
|
||||
if (added_magicline)
|
||||
@@ -2216,7 +2214,7 @@ int do_writeout(bool exiting)
|
||||
{
|
||||
int i;
|
||||
bool result = FALSE;
|
||||
append_type append = OVERWRITE;
|
||||
kind_of_writing_type method = OVERWRITE;
|
||||
char *given;
|
||||
/* The filename we offer, or what the user typed so far. */
|
||||
bool maychange = (openfile->filename[0] == '\0');
|
||||
@@ -2252,13 +2250,13 @@ int do_writeout(bool exiting)
|
||||
* it allows reading from or writing to files not specified on
|
||||
* the command line. */
|
||||
if (openfile->mark_set && !exiting && !ISSET(RESTRICTED))
|
||||
msg = (append == PREPEND) ? _("Prepend Selection to File") :
|
||||
(append == APPEND) ? _("Append Selection to File") :
|
||||
msg = (method == PREPEND) ? _("Prepend Selection to File") :
|
||||
(method == APPEND) ? _("Append Selection to File") :
|
||||
_("Write Selection to File");
|
||||
else
|
||||
#endif /* !NANO_TINY */
|
||||
msg = (append == PREPEND) ? _("File Name to Prepend to") :
|
||||
(append == APPEND) ? _("File Name to Append to") :
|
||||
msg = (method == PREPEND) ? _("File Name to Prepend to") :
|
||||
(method == APPEND) ? _("File Name to Append to") :
|
||||
_("File Name to Write");
|
||||
|
||||
present_path = mallocstrcpy(present_path, "./");
|
||||
@@ -2334,10 +2332,10 @@ int do_writeout(bool exiting)
|
||||
} else
|
||||
#endif /* !NANO_TINY */
|
||||
if (func == prepend_void) {
|
||||
append = (append == PREPEND) ? OVERWRITE : PREPEND;
|
||||
method = (method == PREPEND) ? OVERWRITE : PREPEND;
|
||||
continue;
|
||||
} else if (func == append_void) {
|
||||
append = (append == APPEND) ? OVERWRITE : APPEND;
|
||||
method = (method == APPEND) ? OVERWRITE : APPEND;
|
||||
continue;
|
||||
} else if (func == do_help_void) {
|
||||
continue;
|
||||
@@ -2362,7 +2360,7 @@ int do_writeout(bool exiting)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (append == OVERWRITE) {
|
||||
if (method == OVERWRITE) {
|
||||
size_t answer_len = strlen(answer);
|
||||
bool name_exists, do_warning;
|
||||
char *full_answer, *full_filename;
|
||||
@@ -2451,10 +2449,10 @@ int do_writeout(bool exiting)
|
||||
* writing to files not specified on the command line. */
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set && !exiting && !ISSET(RESTRICTED))
|
||||
result = write_marked_file(answer, NULL, FALSE, append);
|
||||
result = write_marked_file(answer, NULL, FALSE, method);
|
||||
else
|
||||
#endif
|
||||
result = write_file(answer, NULL, FALSE, append, FALSE);
|
||||
result = write_file(answer, NULL, FALSE, method, FALSE);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
27
src/global.c
27
src/global.c
@@ -46,6 +46,8 @@ message_type lastmessage = HUSH;
|
||||
#ifndef NANO_TINY
|
||||
int controlleft = CONTROL_LEFT;
|
||||
int controlright = CONTROL_RIGHT;
|
||||
int controlup = CONTROL_UP;
|
||||
int controldown = CONTROL_DOWN;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
@@ -124,6 +126,9 @@ size_t quotelen;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
char *word_chars = NULL;
|
||||
/* Nonalphanumeric characters that also form words. */
|
||||
|
||||
bool nodelay_mode = FALSE;
|
||||
/* Are we checking for a cancel wile doing something? */
|
||||
|
||||
@@ -212,7 +217,7 @@ int hilite_attribute = A_REVERSE;
|
||||
char* specified_color_combo[] = {};
|
||||
/* The color combinations as specified in the rcfile. */
|
||||
#endif
|
||||
color_pair interface_color_pair[] = {};
|
||||
int interface_color_pair[] = {};
|
||||
/* The processed color pairs for the interface elements. */
|
||||
|
||||
char *homedir = NULL;
|
||||
@@ -570,6 +575,10 @@ void shortcut_init(void)
|
||||
const char *nano_nextline_msg = N_("Go to next line");
|
||||
const char *nano_home_msg = N_("Go to beginning of current line");
|
||||
const char *nano_end_msg = N_("Go to end of current line");
|
||||
#ifndef NANO_TINY
|
||||
const char *nano_prevblock_msg = N_("Go to previous block of text");
|
||||
const char *nano_nextblock_msg = N_("Go to next block of text");
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
const char *nano_parabegin_msg =
|
||||
N_("Go to beginning of paragraph; then of previous paragraph");
|
||||
@@ -869,6 +878,13 @@ void shortcut_init(void)
|
||||
add_to_funcs(do_down_void, MMAIN|MBROWSER,
|
||||
next_line_tag, IFSCHELP(nano_nextline_msg), BLANKAFTER, VIEW);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
add_to_funcs(do_prev_block, MMAIN,
|
||||
N_("Prev Block"), IFSCHELP(nano_prevblock_msg), TOGETHER, VIEW);
|
||||
add_to_funcs(do_next_block, MMAIN,
|
||||
N_("Next Block"), IFSCHELP(nano_nextblock_msg), TOGETHER, VIEW);
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
add_to_funcs(do_para_begin_void, MMAIN|MWHEREIS,
|
||||
N_("Beg of Par"), IFSCHELP(nano_parabegin_msg), TOGETHER, VIEW);
|
||||
@@ -1130,6 +1146,10 @@ void shortcut_init(void)
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "Up", do_up_void, 0);
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "^N", do_down_void, 0);
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "Down", do_down_void, 0);
|
||||
#ifndef NANO_TINY
|
||||
add_to_sclist(MMAIN, "M-7", do_prev_block, 0);
|
||||
add_to_sclist(MMAIN, "M-8", do_next_block, 0);
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
add_to_sclist(MMAIN, "M-(", do_para_begin_void, 0);
|
||||
add_to_sclist(MMAIN, "M-9", do_para_begin_void, 0);
|
||||
@@ -1450,6 +1470,10 @@ sc *strtosc(const char *input)
|
||||
s->scfunc = do_cut_prev_word;
|
||||
else if (!strcasecmp(input, "cutwordright"))
|
||||
s->scfunc = do_cut_next_word;
|
||||
else if (!strcasecmp(input, "prevblock"))
|
||||
s->scfunc = do_prev_block;
|
||||
else if (!strcasecmp(input, "nextblock"))
|
||||
s->scfunc = do_next_block;
|
||||
else if (!strcasecmp(input, "findbracket"))
|
||||
s->scfunc = do_find_bracket;
|
||||
else if (!strcasecmp(input, "wordcount"))
|
||||
@@ -1669,6 +1693,7 @@ void thanks_for_all_the_fish(void)
|
||||
delwin(edit);
|
||||
delwin(bottomwin);
|
||||
|
||||
free(word_chars);
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
free(quotestr);
|
||||
#ifdef HAVE_REGEX_H
|
||||
|
||||
12
src/help.c
12
src/help.c
@@ -141,6 +141,12 @@ void do_help(void)
|
||||
|
||||
if (func == total_refresh) {
|
||||
total_redraw();
|
||||
} else if (func == do_up_void) {
|
||||
if (line > 0)
|
||||
line--;
|
||||
} else if (func == do_down_void) {
|
||||
if (line + (editwinrows - 1) < last_line)
|
||||
line++;
|
||||
} else if (func == do_page_up) {
|
||||
if (line > editwinrows - 2)
|
||||
line -= editwinrows - 2;
|
||||
@@ -149,12 +155,6 @@ void do_help(void)
|
||||
} else if (func == do_page_down) {
|
||||
if (line + (editwinrows - 1) < last_line)
|
||||
line += editwinrows - 2;
|
||||
} else if (func == do_up_void) {
|
||||
if (line > 0)
|
||||
line--;
|
||||
} else if (func == do_down_void) {
|
||||
if (line + (editwinrows - 1) < last_line)
|
||||
line++;
|
||||
} else if (func == do_first_line) {
|
||||
line = 0;
|
||||
} else if (func == do_last_line) {
|
||||
|
||||
40
src/move.c
40
src/move.c
@@ -210,6 +210,46 @@ void do_para_end_void(void)
|
||||
#endif /* !DISABLE_JUSTIFY */
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Move to the preceding block of text in the file. */
|
||||
void do_prev_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_text = FALSE, seen_text = FALSE;
|
||||
|
||||
/* Skip backward until first blank line after some nonblank line(s). */
|
||||
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
|
||||
openfile->current = openfile->current->prev;
|
||||
is_text = !white_string(openfile->current->data);
|
||||
seen_text = seen_text || is_text;
|
||||
}
|
||||
|
||||
/* Step forward one line again if this one is blank. */
|
||||
if (openfile->current->next != NULL &&
|
||||
white_string(openfile->current->data))
|
||||
openfile->current = openfile->current->next;
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Move to the next block of text in the file. */
|
||||
void do_next_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_white = white_string(openfile->current->data);
|
||||
bool seen_white = is_white;
|
||||
|
||||
/* Skip forward until first nonblank line after some blank line(s). */
|
||||
while (openfile->current->next != NULL && (!seen_white || is_white)) {
|
||||
openfile->current = openfile->current->next;
|
||||
is_white = white_string(openfile->current->data);
|
||||
seen_white = seen_white || is_white;
|
||||
}
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Move to the previous word in the file. If allow_punct is TRUE, treat
|
||||
* punctuation as part of a word. If allow_update is TRUE, update the
|
||||
* screen afterwards. */
|
||||
|
||||
113
src/nano.c
113
src/nano.c
@@ -21,6 +21,7 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "proto.h"
|
||||
#include "revision.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
@@ -688,11 +689,14 @@ void die_save_file(const char *die_filename
|
||||
free(targetname);
|
||||
}
|
||||
|
||||
#define TOP_ROWS (ISSET(MORE_SPACE) ? 1 : 2)
|
||||
#define BOTTOM_ROWS (ISSET(NO_HELP) ? 1 : 3)
|
||||
|
||||
/* Initialize the three window portions nano uses. */
|
||||
void window_init(void)
|
||||
{
|
||||
/* If the screen height is too small, get out. */
|
||||
editwinrows = LINES - 5 + more_space() + no_help();
|
||||
editwinrows = LINES - TOP_ROWS - BOTTOM_ROWS;
|
||||
if (COLS < MIN_EDITOR_COLS || editwinrows < MIN_EDITOR_ROWS)
|
||||
die(_("Window size is too small for nano...\n"));
|
||||
|
||||
@@ -713,10 +717,9 @@ void window_init(void)
|
||||
delwin(bottomwin);
|
||||
|
||||
/* Set up the windows. */
|
||||
topwin = newwin(2 - more_space(), COLS, 0, 0);
|
||||
edit = newwin(editwinrows, COLS, 2 - more_space(), 0);
|
||||
bottomwin = newwin(3 - no_help(), COLS, editwinrows + (2 -
|
||||
more_space()), 0);
|
||||
topwin = newwin(TOP_ROWS, COLS, 0, 0);
|
||||
edit = newwin(editwinrows, COLS, TOP_ROWS, 0);
|
||||
bottomwin = newwin(BOTTOM_ROWS, COLS, TOP_ROWS + editwinrows, 0);
|
||||
|
||||
/* Turn the keypad on for the windows, if necessary. */
|
||||
if (!ISSET(REBIND_KEYPAD)) {
|
||||
@@ -859,6 +862,8 @@ void usage(void)
|
||||
#ifndef NANO_TINY
|
||||
print_opt("-W", "--wordbounds",
|
||||
N_("Detect word boundaries more accurately"));
|
||||
print_opt("-X", "--wordchars",
|
||||
N_("Which other characters are word parts"));
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
if (!ISSET(RESTRICTED))
|
||||
@@ -918,7 +923,7 @@ void usage(void)
|
||||
void version(void)
|
||||
{
|
||||
#ifdef REVISION
|
||||
printf(" nano from git, commit %s (after %s)\n", REVISION, VERSION);
|
||||
printf(" nano from git, %s\n", REVISION);
|
||||
#else
|
||||
printf(_(" nano, version %s\n"), VERSION);
|
||||
#endif
|
||||
@@ -1040,21 +1045,6 @@ void version(void)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Return 1 if the MORE_SPACE flag is set, and 0 otherwise. This is
|
||||
* used to calculate the sizes and Y coordinates of the subwindows. */
|
||||
int more_space(void)
|
||||
{
|
||||
return ISSET(MORE_SPACE) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Return 2 if the NO_HELP flag is set, and 0 otherwise. This is used
|
||||
* to calculate the sizes and Y coordinates of the subwindows, because
|
||||
* having NO_HELP adds two lines to the edit window. */
|
||||
int no_help(void)
|
||||
{
|
||||
return ISSET(NO_HELP) ? 2 : 0;
|
||||
}
|
||||
|
||||
/* Indicate that the current file has no name, in a way that gets the
|
||||
* user's attention. This is used when trying to save a file with no
|
||||
* name with the TEMP_FILE flag set, just before the filename prompt. */
|
||||
@@ -1297,10 +1287,9 @@ RETSIGTYPE do_continue(int signal)
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Perhaps the user resized the window while we slept. Handle it,
|
||||
* and restore the terminal to its previous state and update the
|
||||
* screen in the process. */
|
||||
handle_sigwinch(0);
|
||||
/* Perhaps the user resized the window while we slept. So act as if,
|
||||
* and restore the terminal to its previous state in the process. */
|
||||
regenerate_screen();
|
||||
#else
|
||||
/* Restore the terminal to its previous state. */
|
||||
terminal_init();
|
||||
@@ -1553,9 +1542,10 @@ void unbound_key(int code)
|
||||
if (func_key)
|
||||
statusline(ALERT, _("Unbound key"));
|
||||
else if (meta_key) {
|
||||
if (0x60 < code && code < 0x7B)
|
||||
code -= 0x20;
|
||||
statusline(ALERT, _("Unbound key: M-%c"), code);
|
||||
if (code == '[')
|
||||
statusline(ALERT, _("Unbindable key: M-["));
|
||||
else
|
||||
statusline(ALERT, _("Unbound key: M-%c"), toupper(code));
|
||||
} else if (code < 0x20)
|
||||
statusline(ALERT, _("Unbound key: ^%c"), code + 0x40);
|
||||
else
|
||||
@@ -1569,7 +1559,7 @@ int do_input(bool allow_funcs)
|
||||
{
|
||||
int input;
|
||||
/* The keystroke we read in: a character or a shortcut. */
|
||||
static int *puddle = NULL;
|
||||
static char *puddle = NULL;
|
||||
/* The input buffer for actual characters. */
|
||||
static size_t depth = 0;
|
||||
/* The length of the input buffer. */
|
||||
@@ -1625,9 +1615,9 @@ int do_input(bool allow_funcs)
|
||||
if (ISSET(VIEW_MODE))
|
||||
print_view_warning();
|
||||
else {
|
||||
depth++;
|
||||
puddle = (int *)nrealloc(puddle, depth * sizeof(int));
|
||||
puddle[depth - 1] = input;
|
||||
/* Store the byte, and leave room for a terminating zero. */
|
||||
puddle = charealloc(puddle, depth + 2);
|
||||
puddle[depth++] = (char)input;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1644,18 +1634,10 @@ int do_input(bool allow_funcs)
|
||||
#endif
|
||||
|
||||
if (puddle != NULL) {
|
||||
/* Display all the characters in the input buffer at
|
||||
* once, filtering out control characters. */
|
||||
char *output = charalloc(depth + 1);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < depth; i++)
|
||||
output[i] = (char)puddle[i];
|
||||
output[i] = '\0';
|
||||
|
||||
do_output(output, depth, FALSE);
|
||||
|
||||
free(output);
|
||||
/* Insert all bytes in the input buffer into the edit buffer
|
||||
* at once, filtering out any low control codes. */
|
||||
puddle[depth] = '\0';
|
||||
do_output(puddle, depth, FALSE);
|
||||
|
||||
/* Empty the input buffer. */
|
||||
free(puddle);
|
||||
@@ -1841,8 +1823,8 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
#endif
|
||||
|
||||
while (i < output_len) {
|
||||
/* If control codes are allowed, encode a null as a newline, and
|
||||
* let a newline character create a whole new line. */
|
||||
/* If control codes are allowed, encode a verbatim null as a newline,
|
||||
* and let a verbatim ^J create a whole new line. */
|
||||
if (allow_cntrls) {
|
||||
if (output[i] == '\0')
|
||||
output[i] = '\n';
|
||||
@@ -2003,6 +1985,7 @@ int main(int argc, char **argv)
|
||||
{"smooth", 0, NULL, 'S'},
|
||||
{"quickblank", 0, NULL, 'U'},
|
||||
{"wordbounds", 0, NULL, 'W'},
|
||||
{"wordchars", 1, NULL, 'X'},
|
||||
{"autoindent", 0, NULL, 'i'},
|
||||
{"cut", 0, NULL, 'k'},
|
||||
{"unix", 0, NULL, 'u'},
|
||||
@@ -2048,11 +2031,11 @@ int main(int argc, char **argv)
|
||||
while ((optchr =
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
getopt_long(argc, argv,
|
||||
"ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tuvwxz$",
|
||||
"ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$",
|
||||
long_options, NULL)
|
||||
#else
|
||||
getopt(argc, argv,
|
||||
"ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tuvwxz$")
|
||||
"ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$")
|
||||
#endif
|
||||
) != -1) {
|
||||
switch (optchr) {
|
||||
@@ -2154,6 +2137,9 @@ int main(int argc, char **argv)
|
||||
case 'W':
|
||||
SET(WORD_BOUNDS);
|
||||
break;
|
||||
case 'X':
|
||||
word_chars = mallocstrcpy(word_chars, optarg);
|
||||
break;
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
case 'Y':
|
||||
@@ -2287,6 +2273,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
char *backup_dir_cpy = backup_dir;
|
||||
char *word_chars_cpy = word_chars;
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
char *quotestr_cpy = quotestr;
|
||||
@@ -2305,6 +2292,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
backup_dir = NULL;
|
||||
word_chars = NULL;
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
quotestr = NULL;
|
||||
@@ -2335,6 +2323,10 @@ int main(int argc, char **argv)
|
||||
free(backup_dir);
|
||||
backup_dir = backup_dir_cpy;
|
||||
}
|
||||
if (word_chars_cpy != NULL) {
|
||||
free(word_chars);
|
||||
word_chars = word_chars_cpy;
|
||||
}
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
if (quotestr_cpy != NULL) {
|
||||
@@ -2514,25 +2506,32 @@ int main(int argc, char **argv)
|
||||
#ifndef DISABLE_COLOR
|
||||
set_colorpairs();
|
||||
#else
|
||||
interface_color_pair[TITLE_BAR].pairnum = hilite_attribute;
|
||||
interface_color_pair[STATUS_BAR].pairnum = hilite_attribute;
|
||||
interface_color_pair[KEY_COMBO].pairnum = hilite_attribute;
|
||||
interface_color_pair[FUNCTION_TAG].pairnum = A_NORMAL;
|
||||
interface_color_pair[TITLE_BAR].bright = FALSE;
|
||||
interface_color_pair[STATUS_BAR].bright = FALSE;
|
||||
interface_color_pair[KEY_COMBO].bright = FALSE;
|
||||
interface_color_pair[FUNCTION_TAG].bright = FALSE;
|
||||
interface_color_pair[TITLE_BAR] = hilite_attribute;
|
||||
interface_color_pair[STATUS_BAR] = hilite_attribute;
|
||||
interface_color_pair[KEY_COMBO] = hilite_attribute;
|
||||
interface_color_pair[FUNCTION_TAG] = A_NORMAL;
|
||||
#endif
|
||||
|
||||
#if !defined(NANO_TINY) && defined(HAVE_KEY_DEFINED)
|
||||
const char *keyvalue;
|
||||
/* Ask ncurses for the key codes for Control+Left and Control+Right. */
|
||||
/* Ask ncurses for the key codes for Control+Left/Right/Up/Down. */
|
||||
keyvalue = tigetstr("kLFT5");
|
||||
if (keyvalue != 0 && keyvalue != (char *)-1)
|
||||
controlleft = key_defined(keyvalue);
|
||||
keyvalue = tigetstr("kRIT5");
|
||||
if (keyvalue != 0 && keyvalue != (char *)-1)
|
||||
controlright = key_defined(keyvalue);
|
||||
keyvalue = tigetstr("kUP5");
|
||||
if (keyvalue != 0 && keyvalue != (char *)-1)
|
||||
controlup = key_defined(keyvalue);
|
||||
keyvalue = tigetstr("kDN5");
|
||||
if (keyvalue != 0 && keyvalue != (char *)-1)
|
||||
controldown = key_defined(keyvalue);
|
||||
#endif
|
||||
|
||||
#ifndef USE_SLANG
|
||||
/* Tell ncurses to pass the Esc key quickly. */
|
||||
set_escdelay(50);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
26
src/nano.h
26
src/nano.h
@@ -58,7 +58,7 @@
|
||||
|
||||
/* Macros for flags, indexing each bit in a small array. */
|
||||
#define FLAGS(flag) flags[((flag) / (sizeof(unsigned) * 8))]
|
||||
#define FLAGMASK(flag) (1 << ((flag) % (sizeof(unsigned) * 8)))
|
||||
#define FLAGMASK(flag) ((unsigned)1 << ((flag) % (sizeof(unsigned) * 8)))
|
||||
#define SET(flag) FLAGS(flag) |= FLAGMASK(flag)
|
||||
#define UNSET(flag) FLAGS(flag) &= ~FLAGMASK(flag)
|
||||
#define ISSET(flag) ((FLAGS(flag) & FLAGMASK(flag)) != 0)
|
||||
@@ -92,6 +92,10 @@
|
||||
#include <curses.h>
|
||||
#endif /* CURSES_H */
|
||||
|
||||
#if defined(NCURSES_VERSION_MAJOR) && (NCURSES_VERSION_MAJOR < 6)
|
||||
#define USING_OLD_NCURSES yes
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
/* Native language support. */
|
||||
#ifdef HAVE_LIBINTL_H
|
||||
@@ -173,7 +177,7 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
OVERWRITE, APPEND, PREPEND
|
||||
} append_type;
|
||||
} kind_of_writing_type;
|
||||
|
||||
typedef enum {
|
||||
UPWARD, DOWNWARD
|
||||
@@ -199,14 +203,6 @@ typedef enum {
|
||||
} undo_type;
|
||||
|
||||
/* Structure types. */
|
||||
typedef struct color_pair {
|
||||
int pairnum;
|
||||
/* The color pair number used for this foreground color and
|
||||
* background color. */
|
||||
bool bright;
|
||||
/* Is this color A_BOLD? */
|
||||
} color_pair;
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
typedef struct colortype {
|
||||
short fg;
|
||||
@@ -218,6 +214,8 @@ typedef struct colortype {
|
||||
int pairnum;
|
||||
/* The color pair number used for this foreground color and
|
||||
* background color. */
|
||||
int attributes;
|
||||
/* Pair number and brightness composed into ready-to-use attributes. */
|
||||
int rex_flags;
|
||||
/* The regex compilation flags (with or without REG_ICASE). */
|
||||
char *start_regex;
|
||||
@@ -566,6 +564,8 @@ enum
|
||||
/* Codes for "modified" Arrow keys, beyond KEY_MAX of ncurses. */
|
||||
#define CONTROL_LEFT 0x401
|
||||
#define CONTROL_RIGHT 0x402
|
||||
#define CONTROL_UP 0x403
|
||||
#define CONTROL_DOWN 0x404
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* An imaginary key for when we get a SIGWINCH (window resize). */
|
||||
@@ -604,10 +604,4 @@ enum
|
||||
/* The largest size_t number that doesn't have the high bit set. */
|
||||
#define HIGHEST_POSITIVE ((~(size_t)0) >> 1)
|
||||
|
||||
#ifdef REVISION
|
||||
#define BRANDING PACKAGE_VERSION"-git "REVISION
|
||||
#else
|
||||
#define BRANDING PACKAGE_STRING
|
||||
#endif
|
||||
|
||||
#endif /* !NANO_H */
|
||||
|
||||
85
src/prompt.c
85
src/prompt.c
@@ -131,13 +131,6 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
else if (s->scfunc == total_refresh) {
|
||||
total_redraw();
|
||||
refresh_func();
|
||||
} else if (s->scfunc == do_cut_text_void) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable Cut. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE)
|
||||
do_statusbar_cut_text();
|
||||
} else if (s->scfunc == do_left)
|
||||
do_statusbar_left();
|
||||
else if (s->scfunc == do_right)
|
||||
@@ -152,40 +145,34 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
do_statusbar_home();
|
||||
else if (s->scfunc == do_end)
|
||||
do_statusbar_end();
|
||||
/* When in restricted mode at the "Write File" prompt and the
|
||||
* filename isn't blank, disallow any input and deletion. */
|
||||
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE &&
|
||||
openfile->filename[0] != '\0' &&
|
||||
(s->scfunc == do_verbatim_input ||
|
||||
s->scfunc == do_cut_text_void ||
|
||||
s->scfunc == do_delete ||
|
||||
s->scfunc == do_backspace))
|
||||
;
|
||||
else if (s->scfunc == do_verbatim_input) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable verbatim input. */
|
||||
if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
|
||||
openfile->filename[0] == '\0') {
|
||||
bool got_enter = FALSE;
|
||||
/* Whether we got the Enter key. */
|
||||
bool got_newline = FALSE;
|
||||
/* Whether we got a verbatim ^J. */
|
||||
|
||||
do_statusbar_verbatim_input(&got_enter);
|
||||
do_statusbar_verbatim_input(&got_newline);
|
||||
|
||||
/* If we got the Enter key, remove it from the input
|
||||
* buffer, set input to the key value for Enter, and
|
||||
* set finished to TRUE to indicate that we're done. */
|
||||
if (got_enter) {
|
||||
get_input(NULL, 1);
|
||||
input = sc_seq_or(do_enter, 0);
|
||||
*finished = TRUE;
|
||||
}
|
||||
/* If we got a verbatim ^J, remove it from the input buffer,
|
||||
* fake a press of Enter, and indicate that we're done. */
|
||||
if (got_newline) {
|
||||
get_input(NULL, 1);
|
||||
input = sc_seq_or(do_enter, 0);
|
||||
*finished = TRUE;
|
||||
}
|
||||
} else if (s->scfunc == do_cut_text_void) {
|
||||
do_statusbar_cut_text();
|
||||
} else if (s->scfunc == do_delete) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable Delete. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE)
|
||||
do_statusbar_delete();
|
||||
do_statusbar_delete();
|
||||
} else if (s->scfunc == do_backspace) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable Backspace. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE)
|
||||
do_statusbar_backspace();
|
||||
do_statusbar_backspace();
|
||||
} else {
|
||||
/* Handle any other shortcut in the current menu, setting
|
||||
* ran_func to TRUE if we try to run their associated
|
||||
@@ -236,10 +223,10 @@ int do_statusbar_mouse(void)
|
||||
#endif
|
||||
|
||||
/* The user typed input_len multibyte characters. Add them to the
|
||||
* statusbar prompt, setting got_enter to TRUE if we get a newline,
|
||||
* statusbar prompt, setting got_newline to TRUE if we got a verbatim ^J,
|
||||
* and filtering out ASCII control characters if filtering is TRUE. */
|
||||
void do_statusbar_output(int *the_input, size_t input_len,
|
||||
bool filtering, bool *got_enter)
|
||||
bool filtering, bool *got_newline)
|
||||
{
|
||||
char *output = charalloc(input_len + 1);
|
||||
char *char_buf = charalloc(mb_cur_max());
|
||||
@@ -261,9 +248,9 @@ void do_statusbar_output(int *the_input, size_t input_len,
|
||||
output[i] = '\n';
|
||||
else if (output[i] == '\n') {
|
||||
/* Put back the rest of the characters for reparsing,
|
||||
* indicate that we got the Enter key and get out. */
|
||||
* indicate that we got a ^J and get out. */
|
||||
unparse_kbinput(output + i, input_len - i);
|
||||
*got_enter = TRUE;
|
||||
*got_newline = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -425,9 +412,9 @@ void do_statusbar_prev_word(void)
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Get verbatim input. Set got_enter to TRUE if we got the Enter key as
|
||||
/* Get verbatim input, setting got_newline to TRUE if we get a ^J as
|
||||
* part of the verbatim input. */
|
||||
void do_statusbar_verbatim_input(bool *got_enter)
|
||||
void do_statusbar_verbatim_input(bool *got_newline)
|
||||
{
|
||||
int *kbinput;
|
||||
size_t kbinput_len;
|
||||
@@ -437,7 +424,7 @@ void do_statusbar_verbatim_input(bool *got_enter)
|
||||
|
||||
/* Display all the verbatim characters at once, not filtering out
|
||||
* control characters. */
|
||||
do_statusbar_output(kbinput, kbinput_len, FALSE, got_enter);
|
||||
do_statusbar_output(kbinput, kbinput_len, FALSE, got_newline);
|
||||
}
|
||||
|
||||
/* Return the placewewant associated with statusbar_x, i.e. the
|
||||
@@ -491,9 +478,7 @@ void update_the_statusbar(void)
|
||||
index = strnlenpt(answer, statusbar_x);
|
||||
page_start = get_statusbar_page_start(start_col, start_col + index);
|
||||
|
||||
if (interface_color_pair[TITLE_BAR].bright)
|
||||
wattron(bottomwin, A_BOLD);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
blank_statusbar();
|
||||
|
||||
@@ -505,8 +490,7 @@ void update_the_statusbar(void)
|
||||
waddstr(bottomwin, expanded);
|
||||
free(expanded);
|
||||
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
reset_statusbar_cursor();
|
||||
@@ -855,15 +839,12 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
onekey("^C", _("Cancel"), width);
|
||||
}
|
||||
|
||||
if (interface_color_pair[TITLE_BAR].bright)
|
||||
wattron(bottomwin, A_BOLD);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
blank_statusbar();
|
||||
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
|
||||
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
/* Refresh edit window and statusbar before getting input. */
|
||||
wnoutrefresh(edit);
|
||||
|
||||
43
src/proto.h
43
src/proto.h
@@ -39,6 +39,8 @@ extern message_type lastmessage;
|
||||
#ifndef NANO_TINY
|
||||
extern int controlleft;
|
||||
extern int controlright;
|
||||
extern int controlup;
|
||||
extern int controldown;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
@@ -91,7 +93,10 @@ extern size_t quotelen;
|
||||
#endif
|
||||
#endif /* !DISABLE_JUSTIFY */
|
||||
|
||||
extern char *word_chars;
|
||||
|
||||
extern bool nodelay_mode;
|
||||
|
||||
extern char *answer;
|
||||
|
||||
extern ssize_t tabsize;
|
||||
@@ -142,7 +147,7 @@ extern int hilite_attribute;
|
||||
#ifndef DISABLE_COLOR
|
||||
extern char* specified_color_combo[NUMBER_OF_ELEMENTS];
|
||||
#endif
|
||||
extern color_pair interface_color_pair[NUMBER_OF_ELEMENTS];
|
||||
extern int interface_color_pair[NUMBER_OF_ELEMENTS];
|
||||
|
||||
extern char *homedir;
|
||||
|
||||
@@ -183,18 +188,12 @@ bool is_alnum_mbchar(const char *c);
|
||||
bool is_blank_mbchar(const char *c);
|
||||
bool is_ascii_cntrl_char(int c);
|
||||
bool is_cntrl_char(int c);
|
||||
#ifdef ENABLE_UTF8
|
||||
bool is_cntrl_wchar(wchar_t wc);
|
||||
#endif
|
||||
bool is_cntrl_mbchar(const char *c);
|
||||
bool is_punct_mbchar(const char *c);
|
||||
bool is_word_mbchar(const char *c, bool allow_punct);
|
||||
char control_rep(char c);
|
||||
#ifdef ENABLE_UTF8
|
||||
wchar_t control_wrep(wchar_t wc);
|
||||
#endif
|
||||
char *control_mbrep(const char *c, char *crep, int *crep_len);
|
||||
char *mbrep(const char *c, char *crep, int *crep_len);
|
||||
char control_rep(const signed char c);
|
||||
char control_mbrep(const char *c);
|
||||
int length_of_char(const char *c, int *width);
|
||||
int mbwidth(const char *c);
|
||||
int mb_cur_max(void);
|
||||
char *make_mbchar(long chr, int *chr_mb_len);
|
||||
@@ -320,11 +319,11 @@ int delete_lockfile(const char *lockfilename);
|
||||
int write_lockfile(const char *lockfilename, const char *origfilename, bool modified);
|
||||
#endif
|
||||
int copy_file(FILE *inn, FILE *out);
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
append, bool nonamechange);
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
kind_of_writing_type method, bool nonamechange);
|
||||
#ifndef NANO_TINY
|
||||
bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
append_type append);
|
||||
kind_of_writing_type method);
|
||||
#endif
|
||||
int do_writeout(bool exiting);
|
||||
void do_writeout_void(void);
|
||||
@@ -400,6 +399,8 @@ void do_para_end(bool allow_update);
|
||||
void do_para_end_void(void);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
void do_prev_block(void);
|
||||
void do_next_block(void);
|
||||
void do_prev_word(bool allow_punct, bool allow_update);
|
||||
void do_prev_word_void(void);
|
||||
bool do_next_word(bool allow_punct, bool allow_update);
|
||||
@@ -475,8 +476,6 @@ void print_opt_full(const char *shortflag
|
||||
, const char *desc);
|
||||
void usage(void);
|
||||
void version(void);
|
||||
int more_space(void);
|
||||
int no_help(void);
|
||||
void no_current_file_name_warning(void);
|
||||
void do_exit(void);
|
||||
void close_and_go(void);
|
||||
@@ -515,7 +514,7 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
int do_statusbar_mouse(void);
|
||||
#endif
|
||||
void do_statusbar_output(int *the_input, size_t input_len,
|
||||
bool filtering, bool *got_enter);
|
||||
bool filtering, bool *got_newline);
|
||||
void do_statusbar_home(void);
|
||||
void do_statusbar_end(void);
|
||||
void do_statusbar_left(void);
|
||||
@@ -527,7 +526,7 @@ void do_statusbar_cut_text(void);
|
||||
void do_statusbar_prev_word(void);
|
||||
void do_statusbar_next_word(void);
|
||||
#endif
|
||||
void do_statusbar_verbatim_input(bool *got_enter);
|
||||
void do_statusbar_verbatim_input(bool *got_newline);
|
||||
size_t statusbar_xplustabs(void);
|
||||
size_t get_statusbar_page_start(size_t start_col, size_t column);
|
||||
void reinit_statusbar_x(void);
|
||||
@@ -650,6 +649,7 @@ void do_tab(void);
|
||||
void do_indent(ssize_t cols);
|
||||
void do_indent_void(void);
|
||||
void do_unindent(void);
|
||||
bool white_string(const char *s);
|
||||
void do_undo(void);
|
||||
void do_redo(void);
|
||||
#endif
|
||||
@@ -734,7 +734,7 @@ void *nmalloc(size_t howmuch);
|
||||
void *nrealloc(void *ptr, size_t howmuch);
|
||||
char *mallocstrncpy(char *dest, const char *src, size_t n);
|
||||
char *mallocstrcpy(char *dest, const char *src);
|
||||
char *mallocstrassn(char *dest, char *src);
|
||||
char *free_and_assign(char *dest, char *src);
|
||||
size_t get_page_start(size_t column);
|
||||
size_t xplustabs(void);
|
||||
size_t actual_x(const char *s, size_t column);
|
||||
@@ -773,7 +773,7 @@ int parse_escape_sequence(WINDOW *win, int kbinput);
|
||||
int get_byte_kbinput(int kbinput);
|
||||
#ifdef ENABLE_UTF8
|
||||
long add_unicode_digit(int kbinput, long factor, long *uni);
|
||||
long get_unicode_kbinput(int kbinput);
|
||||
long get_unicode_kbinput(WINDOW *win, int kbinput);
|
||||
#endif
|
||||
int get_control_kbinput(int kbinput);
|
||||
void unparse_kbinput(char *output, size_t output_len);
|
||||
@@ -785,13 +785,12 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
|
||||
const sc *get_shortcut(int *kbinput);
|
||||
void blank_line(WINDOW *win, int y, int x, int n);
|
||||
void blank_titlebar(void);
|
||||
void blank_topbar(void);
|
||||
void blank_edit(void);
|
||||
void blank_statusbar(void);
|
||||
void blank_bottombars(void);
|
||||
void check_statusblank(void);
|
||||
char *display_string(const char *buf, size_t start_col, size_t len, bool
|
||||
dollars);
|
||||
char *display_string(const char *buf, size_t start_col, size_t span,
|
||||
bool dollars);
|
||||
void titlebar(const char *path);
|
||||
extern void set_modified(void);
|
||||
void statusbar(const char *msg);
|
||||
|
||||
15
src/rcfile.c
15
src/rcfile.c
@@ -102,6 +102,7 @@ static const rcoption rcopts[] = {
|
||||
{"unix", MAKE_IT_UNIX},
|
||||
{"whitespace", 0},
|
||||
{"wordbounds", WORD_BOUNDS},
|
||||
{"wordchars", 0},
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
{"titlecolor", 0},
|
||||
@@ -657,7 +658,7 @@ void parse_colors(char *ptr, int rex_flags)
|
||||
/* Now for the fun part. Start adding regexes to individual strings
|
||||
* in the colorstrings array, woo! */
|
||||
while (ptr != NULL && *ptr != '\0') {
|
||||
colortype *newcolor;
|
||||
colortype *newcolor = NULL;
|
||||
/* The container for a color plus its regexes. */
|
||||
bool goodstart;
|
||||
/* Whether the start expression was valid. */
|
||||
@@ -1067,7 +1068,8 @@ void parse_rcfile(FILE *rcstream
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "parse_rcfile(): option name = \"%s\"\n", rcopts[i].name);
|
||||
fprintf(stderr, " Option name = \"%s\"\n", rcopts[i].name);
|
||||
fprintf(stderr, " Flag = %ld\n", rcopts[i].flag);
|
||||
#endif
|
||||
/* First handle unsetting. */
|
||||
if (set == -1) {
|
||||
@@ -1098,7 +1100,7 @@ void parse_rcfile(FILE *rcstream
|
||||
|
||||
option = mallocstrcpy(NULL, option);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "option argument = \"%s\"\n", option);
|
||||
fprintf(stderr, " Option argument = \"%s\"\n", option);
|
||||
#endif
|
||||
/* Make sure the option argument is a valid multibyte string. */
|
||||
if (!is_valid_mbstring(option)) {
|
||||
@@ -1176,6 +1178,9 @@ void parse_rcfile(FILE *rcstream
|
||||
if (strcasecmp(rcopts[i].name, "backupdir") == 0)
|
||||
backup_dir = option;
|
||||
else
|
||||
if (strcasecmp(rcopts[i].name, "wordchars") == 0)
|
||||
word_chars = option;
|
||||
else
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
if (strcasecmp(rcopts[i].name, "speller") == 0)
|
||||
@@ -1191,10 +1196,6 @@ void parse_rcfile(FILE *rcstream
|
||||
free(option);
|
||||
} else
|
||||
assert(FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "flag = %ld\n", rcopts[i].flag);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
|
||||
24
src/search.c
24
src/search.c
@@ -600,14 +600,12 @@ char *replace_line(const char *needle)
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* Step through each replace word and prompt user before replacing.
|
||||
* Parameters real_current and real_current_x are needed in order to
|
||||
/* Step through each occurrence of the search string and prompt the user
|
||||
* before replacing it. We seek for needle, and replace it with answer.
|
||||
* The parameters real_current and real_current_x are needed in order to
|
||||
* allow the cursor position to be updated when a word before the cursor
|
||||
* is replaced by a shorter word.
|
||||
*
|
||||
* needle is the string to seek. We replace it with answer. Return -1
|
||||
* if needle isn't found, else the number of replacements performed. If
|
||||
* canceled isn't NULL, set it to TRUE if we canceled. */
|
||||
* is replaced by a shorter word. Return -1 if needle isn't found, -2 if
|
||||
* the seeking is aborted, else the number of replacements performed. */
|
||||
ssize_t do_replace_loop(
|
||||
#ifndef DISABLE_SPELLER
|
||||
bool whole_word_only,
|
||||
@@ -626,8 +624,8 @@ ssize_t do_replace_loop(
|
||||
/* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
|
||||
* FALSE if (current, current_x) is. */
|
||||
|
||||
/* If the mark is on, frame the region, and turn the mark off. */
|
||||
if (old_mark_set) {
|
||||
/* If the mark is on, frame the region, and turn the mark off. */
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
openfile->mark_set = FALSE;
|
||||
@@ -745,15 +743,13 @@ ssize_t do_replace_loop(
|
||||
}
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
/* Don't find the same zero-length match again. */
|
||||
if (match_len == 0)
|
||||
/* Don't find the same zero-length or BOL match again. */
|
||||
if (match_len == 0 || (*needle == '^' && ISSET(USE_REGEXP)))
|
||||
match_len++;
|
||||
#endif
|
||||
|
||||
/* Set the cursor at the last character of the replacement
|
||||
* text, so searching will resume after the replacement
|
||||
* text. Note that current_x might be set to (size_t)-1
|
||||
* here. */
|
||||
* text, so that searching will continue /after/ it. Note
|
||||
* that current_x might be set to (size_t)-1 here. */
|
||||
#ifndef NANO_TINY
|
||||
if (!ISSET(BACKWARDS_SEARCH))
|
||||
#endif
|
||||
|
||||
@@ -3107,7 +3107,7 @@ void do_spell(void)
|
||||
temp = safe_tempfile(&temp_file);
|
||||
|
||||
if (temp == NULL) {
|
||||
statusline(HUSH, _("Error writing temp file: %s"), strerror(errno));
|
||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3119,7 +3119,7 @@ void do_spell(void)
|
||||
status = write_file(temp, temp_file, TRUE, OVERWRITE, FALSE);
|
||||
|
||||
if (!status) {
|
||||
statusline(HUSH, _("Error writing temp file: %s"), strerror(errno));
|
||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||
free(temp);
|
||||
return;
|
||||
}
|
||||
|
||||
54
src/utils.c
54
src/utils.c
@@ -77,35 +77,33 @@ bool parse_num(const char *str, ssize_t *val)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read two ssize_t's, separated by a comma, from str, and store them in
|
||||
* *line and *column (if they're not both NULL). Return FALSE on error,
|
||||
* or TRUE otherwise. */
|
||||
/* Read two numbers, separated by a comma, from str, and store them in
|
||||
* *line and *column. Return FALSE on error, and TRUE otherwise. */
|
||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
|
||||
{
|
||||
bool retval = TRUE;
|
||||
bool retval;
|
||||
char *firstpart;
|
||||
const char *comma;
|
||||
|
||||
assert(str != NULL);
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
|
||||
comma = strchr(str, ',');
|
||||
comma = strpbrk(str, "m,. /;");
|
||||
|
||||
if (comma != NULL && column != NULL) {
|
||||
if (!parse_num(comma + 1, column))
|
||||
retval = FALSE;
|
||||
}
|
||||
if (comma == NULL)
|
||||
return parse_num(str, line);
|
||||
|
||||
if (line != NULL) {
|
||||
if (comma != NULL) {
|
||||
char *str_line = mallocstrncpy(NULL, str, comma - str + 1);
|
||||
str_line[comma - str] = '\0';
|
||||
if (!parse_num(comma + 1, column))
|
||||
return FALSE;
|
||||
|
||||
if (str_line[0] != '\0' && !parse_num(str_line, line))
|
||||
retval = FALSE;
|
||||
if (comma == str)
|
||||
return TRUE;
|
||||
|
||||
free(str_line);
|
||||
} else if (!parse_num(str, line))
|
||||
retval = FALSE;
|
||||
}
|
||||
firstpart = mallocstrcpy(NULL, str);
|
||||
firstpart[comma - str] = '\0';
|
||||
|
||||
retval = parse_num(firstpart, line);
|
||||
free(firstpart);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -296,8 +294,8 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
|
||||
* word isn't a non-punctuation "word" character, and if we're at
|
||||
* the end of the line or the character after the word isn't a
|
||||
* non-punctuation "word" character, we have a whole word. */
|
||||
retval = (position == 0 || !is_word_mbchar(before, FALSE)) &&
|
||||
(word_end == strlen(buf) || !is_word_mbchar(after, FALSE));
|
||||
retval = (position == 0 || !is_alnum_mbchar(before)) &&
|
||||
(word_end == strlen(buf) || !is_alnum_mbchar(after));
|
||||
|
||||
free(before);
|
||||
free(after);
|
||||
@@ -406,8 +404,8 @@ void *nrealloc(void *ptr, size_t howmuch)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Copy the first n characters of one malloc()ed string to another
|
||||
* pointer. Should be used as: "dest = mallocstrncpy(dest, src, n);". */
|
||||
/* Allocate and copy the first n characters of the given src string, after
|
||||
* freeing the destination. Usage: "dest = mallocstrncpy(dest, src, n);". */
|
||||
char *mallocstrncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
if (src == NULL)
|
||||
@@ -422,17 +420,15 @@ char *mallocstrncpy(char *dest, const char *src, size_t n)
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Copy one malloc()ed string to another pointer. Should be used as:
|
||||
/* Free the dest string and return a malloc'ed copy of src. Should be used as:
|
||||
* "dest = mallocstrcpy(dest, src);". */
|
||||
char *mallocstrcpy(char *dest, const char *src)
|
||||
{
|
||||
return mallocstrncpy(dest, src, (src == NULL) ? 1 : strlen(src) + 1);
|
||||
}
|
||||
|
||||
/* Free the malloc()ed string at dest and return the malloc()ed string
|
||||
* at src. Should be used as: "answer = mallocstrassn(answer,
|
||||
* real_dir_from_tilde(answer));". */
|
||||
char *mallocstrassn(char *dest, char *src)
|
||||
/* Free the string at dest and return the string at src. */
|
||||
char *free_and_assign(char *dest, char *src)
|
||||
{
|
||||
free(dest);
|
||||
return src;
|
||||
|
||||
494
src/winio.c
494
src/winio.c
@@ -21,6 +21,7 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "proto.h"
|
||||
#include "revision.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
@@ -28,17 +29,27 @@
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef REVISION
|
||||
#define BRANDING REVISION
|
||||
#else
|
||||
#define BRANDING PACKAGE_STRING
|
||||
#endif
|
||||
|
||||
static int *key_buffer = NULL;
|
||||
/* The keystroke buffer, containing all the keystrokes we
|
||||
* haven't handled yet at a given point. */
|
||||
static size_t key_buffer_len = 0;
|
||||
/* The length of the keystroke buffer. */
|
||||
static bool solitary = FALSE;
|
||||
/* Whether an Esc arrived by itself -- not as leader of a sequence. */
|
||||
static int statusblank = 0;
|
||||
/* The number of keystrokes left before we blank the statusbar. */
|
||||
static bool suppress_cursorpos = FALSE;
|
||||
/* Should we skip constant position display for one keystroke? */
|
||||
#ifdef USING_OLD_NCURSES
|
||||
static bool seen_wide = FALSE;
|
||||
/* Whether we've seen a multicolumn character in the current line. */
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
static sig_atomic_t last_sigwinch_counter = 0;
|
||||
@@ -57,18 +68,13 @@ bool the_window_resized(void)
|
||||
|
||||
/* Control character compatibility:
|
||||
*
|
||||
* - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
|
||||
* VT100, and VT220.
|
||||
* - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
|
||||
* VT220, and VT320.
|
||||
* - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
|
||||
* VT220, and VT320.
|
||||
* - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
|
||||
* VT220, and VT320.
|
||||
* - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
|
||||
* VT220, and VT320.
|
||||
* - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
|
||||
* ANSI, VT100, and VT220, and which is Backspace under VT320.
|
||||
* - 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.
|
||||
* - Ctrl-8 (Ctrl-?, NANO_CONTROL_8) is Delete under ASCII, ANSI,
|
||||
* VT100, and VT220, but is Backspace under VT320.
|
||||
*
|
||||
* Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
|
||||
* default, xterm assumes it's running on a VT320 and generates Ctrl-8
|
||||
@@ -85,8 +91,8 @@ bool the_window_resized(void)
|
||||
*
|
||||
* We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
|
||||
* console, the FreeBSD console, the Mach console, xterm, rxvt, Eterm,
|
||||
* and Terminal. Among these, there are several conflicts and
|
||||
* omissions, outlined as follows:
|
||||
* and Terminal, and some for iTerm2. Among these, there are several
|
||||
* conflicts and omissions, outlined as follows:
|
||||
*
|
||||
* - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
|
||||
* (Ctrl-I is also Tab on ANSI, which we already support.)
|
||||
@@ -134,8 +140,10 @@ void get_key_buffer(WINDOW *win)
|
||||
input = wgetch(win);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (the_window_resized())
|
||||
if (the_window_resized()) {
|
||||
ungetch(input);
|
||||
input = KEY_WINCH;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (input == ERR && nodelay_mode)
|
||||
@@ -353,6 +361,7 @@ int parse_kbinput(WINDOW *win)
|
||||
/* If there are four consecutive escapes, discard three of them. */
|
||||
if (escapes > 3)
|
||||
escapes = 1;
|
||||
solitary = (escapes == 1 && get_key_buffer_len() == 0);
|
||||
/* Wait for more input. */
|
||||
break;
|
||||
default:
|
||||
@@ -364,10 +373,12 @@ int parse_kbinput(WINDOW *win)
|
||||
case 1:
|
||||
/* Reset the escape counter. */
|
||||
escapes = 0;
|
||||
if (get_key_buffer_len() == 0 || key_buffer[0] == 0x1b) {
|
||||
if ((*kbinput != 'O' && *kbinput != 'o' && *kbinput != '[') ||
|
||||
get_key_buffer_len() == 0 || *key_buffer == 0x1B) {
|
||||
/* One escape followed by a single non-escape:
|
||||
* meta key sequence mode. */
|
||||
meta_key = TRUE;
|
||||
if (!solitary || (*kbinput >= 0x20 && *kbinput < 0x7F))
|
||||
meta_key = TRUE;
|
||||
retval = tolower(*kbinput);
|
||||
} else
|
||||
/* One escape followed by a non-escape, and there
|
||||
@@ -392,9 +403,6 @@ int parse_kbinput(WINDOW *win)
|
||||
retval = controlleft;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
retval = ERR;
|
||||
break;
|
||||
}
|
||||
double_esc = FALSE;
|
||||
escapes = 0;
|
||||
@@ -458,7 +466,8 @@ int parse_kbinput(WINDOW *win)
|
||||
retval = *kbinput;
|
||||
}
|
||||
}
|
||||
} else if (*kbinput=='[') {
|
||||
} else if (*kbinput == '[' && key_buffer_len > 0 &&
|
||||
'A' <= *key_buffer && *key_buffer <= 'D') {
|
||||
/* This is an iTerm2 sequence: ^[ ^[ [ X. */
|
||||
double_esc = TRUE;
|
||||
} else {
|
||||
@@ -490,118 +499,111 @@ int parse_kbinput(WINDOW *win)
|
||||
|
||||
if (retval != ERR) {
|
||||
switch (retval) {
|
||||
case NANO_CONTROL_8:
|
||||
retval = ISSET(REBIND_DELETE) ? sc_seq_or(do_delete, 0) :
|
||||
sc_seq_or(do_backspace, 0);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
#ifdef KEY_SDOWN
|
||||
/* ncurses and Slang don't support KEY_SDOWN. */
|
||||
case KEY_SDOWN:
|
||||
#endif
|
||||
retval = sc_seq_or(do_down_void, *kbinput);
|
||||
break;
|
||||
case KEY_UP:
|
||||
#ifdef KEY_SUP
|
||||
/* ncurses and Slang don't support KEY_SUP. */
|
||||
case KEY_SUP:
|
||||
#endif
|
||||
retval = sc_seq_or(do_up_void, *kbinput);
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
#ifdef KEY_SLEFT
|
||||
/* Slang doesn't support KEY_SLEFT. */
|
||||
case KEY_SLEFT:
|
||||
#endif
|
||||
case KEY_LEFT:
|
||||
retval = sc_seq_or(do_left, *kbinput);
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
#ifdef KEY_SRIGHT
|
||||
/* Slang doesn't support KEY_SRIGHT. */
|
||||
case KEY_SRIGHT:
|
||||
#endif
|
||||
case KEY_RIGHT:
|
||||
retval = sc_seq_or(do_right, *kbinput);
|
||||
break;
|
||||
#ifdef KEY_SUP
|
||||
/* ncurses and Slang don't support KEY_SUP. */
|
||||
case KEY_SUP:
|
||||
#endif
|
||||
case KEY_UP:
|
||||
retval = sc_seq_or(do_up_void, *kbinput);
|
||||
break;
|
||||
#ifdef KEY_SDOWN
|
||||
/* ncurses and Slang don't support KEY_SDOWN. */
|
||||
case KEY_SDOWN:
|
||||
#endif
|
||||
case KEY_DOWN:
|
||||
retval = sc_seq_or(do_down_void, *kbinput);
|
||||
break;
|
||||
#ifdef KEY_SHOME
|
||||
/* HP-UX 10-11 and Slang don't support KEY_SHOME. */
|
||||
case KEY_SHOME:
|
||||
#endif
|
||||
case KEY_A1: /* Home (7) on numeric keypad with
|
||||
* NumLock off. */
|
||||
#ifdef KEY_HOME
|
||||
case KEY_HOME:
|
||||
#endif
|
||||
case KEY_A1: /* Home (7) on keypad with NumLock off. */
|
||||
retval = sc_seq_or(do_home, *kbinput);
|
||||
break;
|
||||
#ifdef KEY_SEND
|
||||
/* HP-UX 10-11 and Slang don't support KEY_SEND. */
|
||||
case KEY_SEND:
|
||||
#endif
|
||||
#ifdef KEY_END
|
||||
case KEY_END:
|
||||
#endif
|
||||
case KEY_C1: /* End (1) on keypad with NumLock off. */
|
||||
retval = sc_seq_or(do_end, *kbinput);
|
||||
break;
|
||||
case KEY_PPAGE:
|
||||
case KEY_A3: /* PageUp (9) on keypad with NumLock off. */
|
||||
retval = sc_seq_or(do_page_up, *kbinput);
|
||||
break;
|
||||
case KEY_NPAGE:
|
||||
case KEY_C3: /* PageDown (3) on keypad with NumLock off. */
|
||||
retval = sc_seq_or(do_page_down, *kbinput);
|
||||
break;
|
||||
|
||||
case KEY_ENTER:
|
||||
retval = sc_seq_or(do_enter, *kbinput);
|
||||
break;
|
||||
case KEY_BACKSPACE:
|
||||
retval = sc_seq_or(do_backspace, *kbinput);
|
||||
break;
|
||||
#ifdef KEY_SDC
|
||||
/* Slang doesn't support KEY_SDC. */
|
||||
case KEY_SDC:
|
||||
#endif
|
||||
case NANO_CONTROL_8:
|
||||
if (ISSET(REBIND_DELETE))
|
||||
retval = sc_seq_or(do_delete, *kbinput);
|
||||
else
|
||||
retval = sc_seq_or(do_backspace, *kbinput);
|
||||
break;
|
||||
#endif
|
||||
#ifdef KEY_SIC
|
||||
/* Slang doesn't support KEY_SIC. */
|
||||
case KEY_SIC:
|
||||
retval = sc_seq_or(do_insertfile_void, *kbinput);
|
||||
break;
|
||||
#endif
|
||||
case KEY_C3: /* PageDown (4) on numeric keypad with
|
||||
* NumLock off. */
|
||||
retval = sc_seq_or(do_page_down, *kbinput);
|
||||
break;
|
||||
case KEY_A3: /* PageUp (9) on numeric keypad with
|
||||
* NumLock off. */
|
||||
retval = sc_seq_or(do_page_up, *kbinput);
|
||||
break;
|
||||
case KEY_ENTER:
|
||||
retval = sc_seq_or(do_enter, *kbinput);
|
||||
break;
|
||||
case KEY_B2: /* Center (5) on numeric keypad with
|
||||
* NumLock off. */
|
||||
retval = ERR;
|
||||
break;
|
||||
case KEY_C1: /* End (1) on numeric keypad with
|
||||
* NumLock off. */
|
||||
#ifdef KEY_SEND
|
||||
/* HP-UX 10-11 and Slang don't support KEY_SEND. */
|
||||
case KEY_SEND:
|
||||
#ifdef KEY_SBEG
|
||||
/* Slang doesn't support KEY_SBEG. */
|
||||
case KEY_SBEG:
|
||||
#endif
|
||||
retval = sc_seq_or(do_end, *kbinput);
|
||||
break;
|
||||
#ifdef KEY_BEG
|
||||
/* Slang doesn't support KEY_BEG. */
|
||||
case KEY_BEG: /* Center (5) on numeric keypad with
|
||||
* NumLock off. */
|
||||
case KEY_BEG:
|
||||
#endif
|
||||
case KEY_B2: /* Center (5) on keypad with NumLock off. */
|
||||
retval = ERR;
|
||||
break;
|
||||
#endif
|
||||
#ifdef KEY_CANCEL
|
||||
/* Slang doesn't support KEY_CANCEL. */
|
||||
case KEY_CANCEL:
|
||||
#ifdef KEY_SCANCEL
|
||||
/* Slang doesn't support KEY_SCANCEL. */
|
||||
case KEY_SCANCEL:
|
||||
#endif
|
||||
/* Slang doesn't support KEY_CANCEL. */
|
||||
case KEY_CANCEL:
|
||||
retval = first_sc_for(currmenu, do_cancel)->seq;
|
||||
break;
|
||||
#endif
|
||||
#ifdef KEY_SBEG
|
||||
/* Slang doesn't support KEY_SBEG. */
|
||||
case KEY_SBEG: /* Center (5) on numeric keypad with
|
||||
* NumLock off. */
|
||||
retval = ERR;
|
||||
break;
|
||||
#endif
|
||||
#ifdef KEY_SUSPEND
|
||||
#ifdef KEY_SSUSPEND
|
||||
/* Slang doesn't support KEY_SSUSPEND. */
|
||||
case KEY_SSUSPEND:
|
||||
retval = sc_seq_or(do_suspend_void, 0);
|
||||
break;
|
||||
#endif
|
||||
#ifdef KEY_SUSPEND
|
||||
/* Slang doesn't support KEY_SUSPEND. */
|
||||
case KEY_SUSPEND:
|
||||
retval = sc_seq_or(do_suspend_void, 0);
|
||||
@@ -633,6 +635,10 @@ int parse_kbinput(WINDOW *win)
|
||||
retval = sc_seq_or(do_prev_word_void, 0);
|
||||
else if (retval == controlright)
|
||||
retval = sc_seq_or(do_next_word_void, 0);
|
||||
else if (retval == controlup)
|
||||
retval = sc_seq_or(do_prev_block, 0);
|
||||
else if (retval == controldown)
|
||||
retval = sc_seq_or(do_next_block, 0);
|
||||
#endif
|
||||
|
||||
/* If our result is an extended keypad value (i.e. a value
|
||||
@@ -694,8 +700,9 @@ int convert_sequence(const int *seq, size_t seq_len)
|
||||
if (seq_len >= 5) {
|
||||
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 arrow_from_abcd(seq[4]);
|
||||
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. */
|
||||
@@ -764,8 +771,9 @@ int convert_sequence(const int *seq, size_t seq_len)
|
||||
case 'Y': /* Esc O Y == F10 on Mach console. */
|
||||
return KEY_F(10);
|
||||
case 'a': /* Esc O a == Ctrl-Up on rxvt. */
|
||||
return CONTROL_UP;
|
||||
case 'b': /* Esc O b == Ctrl-Down on rxvt. */
|
||||
return arrow_from_abcd(seq[1]);
|
||||
return CONTROL_DOWN;
|
||||
case 'c': /* Esc O c == Ctrl-Right on rxvt. */
|
||||
return CONTROL_RIGHT;
|
||||
case 'd': /* Esc O d == Ctrl-Left on rxvt. */
|
||||
@@ -839,8 +847,9 @@ int convert_sequence(const int *seq, size_t seq_len)
|
||||
case 'o':
|
||||
switch (seq[1]) {
|
||||
case 'a': /* Esc o a == Ctrl-Up on Eterm. */
|
||||
return CONTROL_UP;
|
||||
case 'b': /* Esc o b == Ctrl-Down on Eterm. */
|
||||
return arrow_from_abcd(seq[1]);
|
||||
return CONTROL_DOWN;
|
||||
case 'c': /* Esc o c == Ctrl-Right on Eterm. */
|
||||
return CONTROL_RIGHT;
|
||||
case 'd': /* Esc o d == Ctrl-Left on Eterm. */
|
||||
@@ -893,8 +902,9 @@ int convert_sequence(const int *seq, size_t seq_len)
|
||||
if (seq_len >= 5) {
|
||||
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 arrow_from_abcd(seq[4]);
|
||||
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. */
|
||||
@@ -1220,7 +1230,7 @@ long add_unicode_digit(int kbinput, long factor, long *uni)
|
||||
/* Translate a Unicode sequence: turn a six-digit hexadecimal number
|
||||
* (from 000000 to 10FFFF, case-insensitive) into its corresponding
|
||||
* multibyte value. */
|
||||
long get_unicode_kbinput(int kbinput)
|
||||
long get_unicode_kbinput(WINDOW *win, int kbinput)
|
||||
{
|
||||
static int uni_digits = 0;
|
||||
static long uni = 0;
|
||||
@@ -1231,66 +1241,63 @@ long get_unicode_kbinput(int kbinput)
|
||||
|
||||
switch (uni_digits) {
|
||||
case 1:
|
||||
/* First digit: This must be zero or one. Put it in the
|
||||
* 0x100000's position of the Unicode sequence holder. */
|
||||
if ('0' <= kbinput && kbinput <= '1')
|
||||
/* 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')
|
||||
uni = (kbinput - '0') * 0x100000;
|
||||
else
|
||||
/* This isn't the first digit of a Unicode sequence.
|
||||
* Return this character as the result. */
|
||||
retval = kbinput;
|
||||
break;
|
||||
case 2:
|
||||
/* Second digit: This must be zero if the first was one, and
|
||||
* may be any hexadecimal value if the first was zero. Put
|
||||
* it in the 0x10000's position of the Unicode sequence
|
||||
* holder. */
|
||||
if (uni == 0 || '0' == kbinput)
|
||||
/* 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)
|
||||
retval = add_unicode_digit(kbinput, 0x10000, &uni);
|
||||
else
|
||||
/* This isn't the second digit of a Unicode sequence.
|
||||
* Return this character as the result. */
|
||||
retval = kbinput;
|
||||
break;
|
||||
case 3:
|
||||
/* Third digit: This may be any hexadecimal value. Put it
|
||||
* in the 0x1000's position of the Unicode sequence
|
||||
* holder. */
|
||||
/* Later digits may be any hexadecimal value. */
|
||||
retval = add_unicode_digit(kbinput, 0x1000, &uni);
|
||||
break;
|
||||
case 4:
|
||||
/* Fourth digit: This may be any hexadecimal value. Put it
|
||||
* in the 0x100's position of the Unicode sequence
|
||||
* holder. */
|
||||
retval = add_unicode_digit(kbinput, 0x100, &uni);
|
||||
break;
|
||||
case 5:
|
||||
/* Fifth digit: This may be any hexadecimal value. Put it
|
||||
* in the 0x10's position of the Unicode sequence holder. */
|
||||
retval = add_unicode_digit(kbinput, 0x10, &uni);
|
||||
break;
|
||||
case 6:
|
||||
/* Sixth digit: This may be any hexadecimal value. Put it
|
||||
* in the 0x1's position of the Unicode sequence holder. */
|
||||
retval = add_unicode_digit(kbinput, 0x1, &uni);
|
||||
/* If this character is a valid hexadecimal value, then the
|
||||
* Unicode sequence is complete. */
|
||||
/* If also the sixth digit was a valid hexadecimal value, then
|
||||
* the Unicode sequence is complete, so return it. */
|
||||
if (retval == ERR)
|
||||
retval = uni;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we have a result, reset the Unicode digit counter and the
|
||||
* Unicode sequence holder. */
|
||||
if (retval != ERR) {
|
||||
uni_digits = 0;
|
||||
uni = 0;
|
||||
/* Show feedback only when editing, not when at a prompt. */
|
||||
if (retval == ERR && win == edit) {
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "get_unicode_kbinput(): kbinput = %d, uni_digits = %d, uni = %ld, retval = %ld\n", kbinput, uni_digits, uni, retval);
|
||||
fprintf(stderr, "get_unicode_kbinput(): kbinput = %d, uni_digits = %d, uni = %ld, retval = %ld\n",
|
||||
kbinput, uni_digits, uni, retval);
|
||||
#endif
|
||||
|
||||
/* If we have an end result, reset the Unicode digit counter. */
|
||||
if (retval != ERR)
|
||||
uni_digits = 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif /* ENABLE_UTF8 */
|
||||
@@ -1370,8 +1377,12 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
|
||||
* keypad back on if necessary now that we're done. */
|
||||
if (ISSET(PRESERVE))
|
||||
enable_flow_control();
|
||||
if (!ISSET(REBIND_KEYPAD))
|
||||
keypad(win, TRUE);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -1388,11 +1399,20 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
|
||||
while ((kbinput = get_input(win, 1)) == NULL)
|
||||
;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* When the window was resized, abort and return nothing. */
|
||||
if (*kbinput == KEY_WINCH) {
|
||||
*kbinput_len = 0;
|
||||
free(kbinput);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (using_utf8()) {
|
||||
/* Check whether the first keystroke is a valid hexadecimal
|
||||
* digit. */
|
||||
long uni = get_unicode_kbinput(*kbinput);
|
||||
long uni = get_unicode_kbinput(win, *kbinput);
|
||||
|
||||
/* If the first keystroke isn't a valid hexadecimal digit, put
|
||||
* back the first keystroke. */
|
||||
@@ -1406,15 +1426,11 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
|
||||
char *uni_mb;
|
||||
int uni_mb_len, *seq, i;
|
||||
|
||||
if (win == edit)
|
||||
/* TRANSLATORS: This is displayed during the input of a
|
||||
* six-digit hexadecimal Unicode character code. */
|
||||
statusbar(_("Unicode Input"));
|
||||
|
||||
while (uni == ERR) {
|
||||
free(kbinput);
|
||||
while ((kbinput = get_input(win, 1)) == NULL)
|
||||
;
|
||||
uni = get_unicode_kbinput(*kbinput);
|
||||
uni = get_unicode_kbinput(win, *kbinput);
|
||||
}
|
||||
|
||||
/* Put back the multibyte equivalent of the Unicode
|
||||
@@ -1620,21 +1636,22 @@ const sc *get_shortcut(int *kbinput)
|
||||
sc *s;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s -- ", *kbinput, meta_key ? "TRUE" : "FALSE");
|
||||
fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s -- ",
|
||||
*kbinput, meta_key ? "TRUE" : "FALSE");
|
||||
#endif
|
||||
|
||||
for (s = sclist; s != NULL; s = s->next) {
|
||||
if ((s->menus & currmenu) && *kbinput == s->seq
|
||||
&& meta_key == (s->type == META)) {
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "matched seq \"%s\", and btw meta was %d (menu is %x from %x)\n",
|
||||
s->keystr, meta_key, currmenu, s->menus);
|
||||
fprintf (stderr, "matched seq '%s' (menu is %x from %x)\n",
|
||||
s->keystr, currmenu, s->menus);
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "matched nothing, btw meta was %d\n", meta_key);
|
||||
fprintf (stderr, "matched nothing\n");
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
@@ -1656,14 +1673,6 @@ void blank_titlebar(void)
|
||||
blank_line(topwin, 0, 0, COLS);
|
||||
}
|
||||
|
||||
/* If the MORE_SPACE flag isn't set, blank the second line of the top
|
||||
* portion of the window. */
|
||||
void blank_topbar(void)
|
||||
{
|
||||
if (!ISSET(MORE_SPACE))
|
||||
blank_line(topwin, 1, 0, COLS);
|
||||
}
|
||||
|
||||
/* Blank all the lines of the middle portion of the window, i.e. the
|
||||
* edit window. */
|
||||
void blank_edit(void)
|
||||
@@ -1714,86 +1723,58 @@ void check_statusblank(void)
|
||||
|
||||
/* Convert buf into a string that can be displayed on screen. The
|
||||
* caller wants to display buf starting with column start_col, and
|
||||
* extending for at most len columns. start_col is zero-based. len is
|
||||
* one-based, so len == 0 means you get "" returned. The returned
|
||||
* extending for at most span columns. start_col is zero-based. span
|
||||
* is one-based, so span == 0 means you get "" returned. The returned
|
||||
* string is dynamically allocated, and should be freed. If dollars is
|
||||
* TRUE, the caller might put "$" at the beginning or end of the line if
|
||||
* it's too long. */
|
||||
char *display_string(const char *buf, size_t start_col, size_t len, bool
|
||||
dollars)
|
||||
char *display_string(const char *buf, size_t start_col, size_t span,
|
||||
bool dollars)
|
||||
{
|
||||
size_t start_index;
|
||||
/* Index in buf of the first character shown. */
|
||||
size_t column;
|
||||
/* Screen column that start_index corresponds to. */
|
||||
size_t alloc_len;
|
||||
/* The length of memory allocated for converted. */
|
||||
char *converted;
|
||||
/* The string we return. */
|
||||
size_t index;
|
||||
/* Current position in converted. */
|
||||
char *buf_mb;
|
||||
int buf_mb_len;
|
||||
|
||||
/* If dollars is TRUE, make room for the "$" at the end of the
|
||||
* line. */
|
||||
if (dollars && len > 0 && strlenpt(buf) > start_col + len)
|
||||
len--;
|
||||
if (dollars && span > 0 && strlenpt(buf) > start_col + span)
|
||||
span--;
|
||||
|
||||
if (len == 0)
|
||||
if (span == 0)
|
||||
return mallocstrcpy(NULL, "");
|
||||
|
||||
buf_mb = charalloc(mb_cur_max());
|
||||
|
||||
start_index = actual_x(buf, start_col);
|
||||
column = strnlenpt(buf, start_index);
|
||||
|
||||
assert(column <= start_col);
|
||||
|
||||
/* Make sure there's enough room for the initial character, whether
|
||||
* it's a multibyte control character, a non-control multibyte
|
||||
* character, a tab character, or a null terminator. Rationale:
|
||||
*
|
||||
* multibyte control character followed by a null terminator:
|
||||
* 1 byte ('^') + mb_cur_max() bytes + 1 byte ('\0')
|
||||
* multibyte non-control character followed by a null terminator:
|
||||
* mb_cur_max() bytes + 1 byte ('\0')
|
||||
* tab character followed by a null terminator:
|
||||
* mb_cur_max() bytes + (tabsize - 1) bytes + 1 byte ('\0')
|
||||
*
|
||||
* Since tabsize has a minimum value of 1, it can substitute for 1
|
||||
* byte above. */
|
||||
alloc_len = (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
|
||||
converted = charalloc(alloc_len);
|
||||
/* Allocate enough space to hold the entire converted buffer. */
|
||||
converted = charalloc(strlen(buf) * (mb_cur_max() + tabsize) + 1);
|
||||
|
||||
index = 0;
|
||||
#ifdef USING_OLD_NCURSES
|
||||
seen_wide = FALSE;
|
||||
#endif
|
||||
buf += start_index;
|
||||
|
||||
if (buf[start_index] != '\0' && buf[start_index] != '\t' &&
|
||||
if (*buf != '\0' && *buf != '\t' &&
|
||||
(column < start_col || (dollars && column > 0))) {
|
||||
/* We don't display all of buf[start_index] since it starts to
|
||||
/* We don't display the complete first character as it starts to
|
||||
* the left of the screen. */
|
||||
buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
|
||||
|
||||
if (is_cntrl_mbchar(buf_mb)) {
|
||||
if (is_cntrl_mbchar(buf)) {
|
||||
if (column < start_col) {
|
||||
char *character = charalloc(mb_cur_max());
|
||||
int charlen, i;
|
||||
|
||||
character = control_mbrep(buf_mb, character, &charlen);
|
||||
|
||||
for (i = 0; i < charlen; i++)
|
||||
converted[index++] = character[i];
|
||||
|
||||
start_col += mbwidth(character);
|
||||
|
||||
free(character);
|
||||
|
||||
start_index += buf_mb_len;
|
||||
converted[index++] = control_mbrep(buf);
|
||||
start_col++;
|
||||
buf += parse_mbchar(buf, NULL, NULL);
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_UTF8
|
||||
else if (using_utf8() && mbwidth(buf_mb) == 2) {
|
||||
else if (using_utf8() && mbwidth(buf) == 2) {
|
||||
if (column >= start_col) {
|
||||
converted[index++] = ' ';
|
||||
start_col++;
|
||||
@@ -1802,26 +1783,15 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
|
||||
converted[index++] = ' ';
|
||||
start_col++;
|
||||
|
||||
start_index += buf_mb_len;
|
||||
buf += parse_mbchar(buf, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while (buf[start_index] != '\0') {
|
||||
buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
|
||||
while (*buf != '\0') {
|
||||
int charlength, charwidth = 1;
|
||||
|
||||
if (mbwidth(buf + start_index) > 1)
|
||||
seen_wide = TRUE;
|
||||
|
||||
/* Make sure there's enough room for the next character, whether
|
||||
* it's a multibyte control character, a non-control multibyte
|
||||
* character, a tab character, or a null terminator. */
|
||||
if (index + mb_cur_max() + tabsize + 1 >= alloc_len - 1) {
|
||||
alloc_len += (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
|
||||
converted = charealloc(converted, alloc_len);
|
||||
}
|
||||
|
||||
if (*buf_mb == ' ') {
|
||||
if (*buf == ' ') {
|
||||
/* Show a space as a visible character, or as a space. */
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(WHITESPACE_DISPLAY)) {
|
||||
@@ -1833,7 +1803,9 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
|
||||
#endif
|
||||
converted[index++] = ' ';
|
||||
start_col++;
|
||||
} else if (*buf_mb == '\t') {
|
||||
buf++;
|
||||
continue;
|
||||
} else if (*buf == '\t') {
|
||||
/* Show a tab as a visible character, or as as a space. */
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(WHITESPACE_DISPLAY)) {
|
||||
@@ -1850,57 +1822,52 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
|
||||
converted[index++] = ' ';
|
||||
start_col++;
|
||||
}
|
||||
/* If buf contains a control character, interpret it. */
|
||||
} else if (is_cntrl_mbchar(buf_mb)) {
|
||||
char *character = charalloc(mb_cur_max());
|
||||
int charlen, i;
|
||||
|
||||
converted[index++] = '^';
|
||||
start_col++;
|
||||
|
||||
character = control_mbrep(buf_mb, character, &charlen);
|
||||
|
||||
for (i = 0; i < charlen; i++)
|
||||
converted[index++] = character[i];
|
||||
|
||||
start_col += mbwidth(character);
|
||||
|
||||
free(character);
|
||||
/* If buf contains a non-control character, interpret it. If buf
|
||||
* contains an invalid multibyte sequence, display it as such. */
|
||||
} else {
|
||||
char *character = charalloc(mb_cur_max());
|
||||
int charlen, i;
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* Make sure an invalid sequence-starter byte is properly
|
||||
* terminated, so that it doesn't pick up lingering bytes
|
||||
* of any previous content. */
|
||||
if (using_utf8() && buf_mb_len == 1)
|
||||
buf_mb[1] = '\0';
|
||||
#endif
|
||||
character = mbrep(buf_mb, character, &charlen);
|
||||
|
||||
for (i = 0; i < charlen; i++)
|
||||
converted[index++] = character[i];
|
||||
|
||||
start_col += mbwidth(character);
|
||||
|
||||
free(character);
|
||||
buf++;
|
||||
continue;
|
||||
}
|
||||
|
||||
start_index += buf_mb_len;
|
||||
charlength = length_of_char(buf, &charwidth);
|
||||
|
||||
/* If buf contains a control character, represent it. */
|
||||
if (is_cntrl_mbchar(buf)) {
|
||||
converted[index++] = '^';
|
||||
converted[index++] = control_mbrep(buf);
|
||||
start_col += 2;
|
||||
buf += charlength;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If buf contains a valid non-control character, simply copy it. */
|
||||
if (charlength > 0) {
|
||||
for (; charlength > 0; charlength--)
|
||||
converted[index++] = *(buf++);
|
||||
|
||||
start_col += charwidth;
|
||||
#ifdef USING_OLD_NCURSES
|
||||
if (charwidth > 1)
|
||||
seen_wide = TRUE;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
free(buf_mb);
|
||||
|
||||
assert(alloc_len >= index + 1);
|
||||
|
||||
/* Null-terminate converted. */
|
||||
converted[index] = '\0';
|
||||
|
||||
/* Make sure converted takes up no more than len columns. */
|
||||
index = actual_x(converted, len);
|
||||
/* Make sure converted takes up no more than span columns. */
|
||||
index = actual_x(converted, span);
|
||||
null_at(&converted, index);
|
||||
|
||||
return converted;
|
||||
@@ -1929,9 +1896,7 @@ void titlebar(const char *path)
|
||||
|
||||
assert(path != NULL || openfile->filename != NULL);
|
||||
|
||||
if (interface_color_pair[TITLE_BAR].bright)
|
||||
wattron(topwin, A_BOLD);
|
||||
wattron(topwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattron(topwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
blank_titlebar();
|
||||
|
||||
@@ -2018,8 +1983,7 @@ void titlebar(const char *path)
|
||||
else if (statelen > 0)
|
||||
mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
|
||||
|
||||
wattroff(topwin, A_BOLD);
|
||||
wattroff(topwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattroff(topwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
wnoutrefresh(topwin);
|
||||
reset_cursor();
|
||||
@@ -2088,15 +2052,12 @@ void statusline(message_type importance, const char *msg, ...)
|
||||
start_x = (COLS - strlenpt(foo) - 4) / 2;
|
||||
|
||||
wmove(bottomwin, 0, start_x);
|
||||
if (interface_color_pair[STATUS_BAR].bright)
|
||||
wattron(bottomwin, A_BOLD);
|
||||
wattron(bottomwin, interface_color_pair[STATUS_BAR].pairnum);
|
||||
wattron(bottomwin, interface_color_pair[STATUS_BAR]);
|
||||
waddstr(bottomwin, "[ ");
|
||||
waddstr(bottomwin, foo);
|
||||
free(foo);
|
||||
waddstr(bottomwin, " ]");
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[STATUS_BAR].pairnum);
|
||||
wattroff(bottomwin, interface_color_pair[STATUS_BAR]);
|
||||
|
||||
/* Push the message to the screen straightaway. */
|
||||
wnoutrefresh(bottomwin);
|
||||
@@ -2193,23 +2154,17 @@ void onekey(const char *keystroke, const char *desc, int length)
|
||||
{
|
||||
assert(keystroke != NULL && desc != NULL);
|
||||
|
||||
if (interface_color_pair[KEY_COMBO].bright)
|
||||
wattron(bottomwin, A_BOLD);
|
||||
wattron(bottomwin, interface_color_pair[KEY_COMBO].pairnum);
|
||||
wattron(bottomwin, interface_color_pair[KEY_COMBO]);
|
||||
waddnstr(bottomwin, keystroke, actual_x(keystroke, length));
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[KEY_COMBO].pairnum);
|
||||
wattroff(bottomwin, interface_color_pair[KEY_COMBO]);
|
||||
|
||||
length -= strlenpt(keystroke) + 1;
|
||||
|
||||
if (length > 0) {
|
||||
waddch(bottomwin, ' ');
|
||||
if (interface_color_pair[FUNCTION_TAG].bright)
|
||||
wattron(bottomwin, A_BOLD);
|
||||
wattron(bottomwin, interface_color_pair[FUNCTION_TAG].pairnum);
|
||||
wattron(bottomwin, interface_color_pair[FUNCTION_TAG]);
|
||||
waddnstr(bottomwin, desc, actual_x(desc, length));
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[FUNCTION_TAG].pairnum);
|
||||
wattroff(bottomwin, interface_color_pair[FUNCTION_TAG]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2273,7 +2228,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int
|
||||
* marking highlight on just the pieces that need it. */
|
||||
mvwaddstr(edit, line, 0, converted);
|
||||
|
||||
#ifndef USE_SLANG
|
||||
#ifdef USING_OLD_NCURSES
|
||||
/* 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. */
|
||||
@@ -2304,9 +2259,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int
|
||||
regmatch_t endmatch;
|
||||
/* Match position for end_regex. */
|
||||
|
||||
if (varnish->bright)
|
||||
wattron(edit, A_BOLD);
|
||||
wattron(edit, COLOR_PAIR(varnish->pairnum));
|
||||
wattron(edit, varnish->attributes);
|
||||
/* 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. */
|
||||
@@ -2563,8 +2516,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int
|
||||
}
|
||||
}
|
||||
tail_of_loop:
|
||||
wattroff(edit, A_BOLD);
|
||||
wattroff(edit, COLOR_PAIR(varnish->pairnum));
|
||||
wattroff(edit, varnish->attributes);
|
||||
}
|
||||
}
|
||||
#endif /* !DISABLE_COLOR */
|
||||
@@ -3233,10 +3185,8 @@ void do_credits(void)
|
||||
nodelay(edit, TRUE);
|
||||
|
||||
blank_titlebar();
|
||||
blank_topbar();
|
||||
blank_edit();
|
||||
blank_statusbar();
|
||||
blank_bottombars();
|
||||
|
||||
wrefresh(topwin);
|
||||
wrefresh(edit);
|
||||
|
||||
Reference in New Issue
Block a user