Compare commits

..

33 Commits
v5.3 ... v5.4

Author SHA1 Message Date
Benno Schulenberg
c3900e90f0 po: update translations and regenerate POT file and PO files 2020-12-02 11:49:28 +01:00
Benno Schulenberg
0f334f8ee4 bump the version number in configure.ac too 2020-12-02 11:39:51 +01:00
Benno Schulenberg
587e6e2c88 bump version numbers and add a news item for the 5.4 release 2020-12-02 11:15:31 +01:00
Benno Schulenberg
a3a1391a51 tweaks: rename two variables, one for contrast, another for visibility
Also normalize two bits of whitespace.
2020-11-30 13:32:22 +01:00
Benno Schulenberg
a4675acdba copyright: update to the current year for significantly changed files 2020-11-30 12:01:47 +01:00
Benno Schulenberg
00ac41f632 weeding: remove another unneeded workaround for VTE
The issue is only reproducible when lying about the width
of the terminal.

It was a workaround for https://savannah.gnu.org/bugs/?49106.
2020-11-28 16:12:20 +01:00
Benno Schulenberg
fe22da6b2a build: exclude a workaround for VTE/Konsole when using a recent ncurses
The workaround was for https://savannah.gnu.org/bugs/?51335
(a cursor-misplacement bug), but both an recent Xfce Terminal
and a recent Konsole appear unaffected by the issue.  So, drop
the workaround for modern systems.
2020-11-27 14:15:42 +01:00
Benno Schulenberg
0c87a4ba41 build: include a workaround for VTE only when using an older libvte
Checking for the actual version of libvte is too complicated, so
assume that libvte is 0.58 or newer (where the problem is fixed)
when ncurses is 6.2 or newer.
2020-11-27 12:31:41 +01:00
Benno Schulenberg
39705c60df weeding: remove a workaround for VTE that is not needed
It was only ever needed when the user lied about the size
of the terminal, which should be considered a user error.

It was a workaround for https://savannah.gnu.org/bugs/?48852.
2020-11-26 20:09:23 +01:00
Benno Schulenberg
9da23799ff tweaks: reshuffle a fragment of code, for clarity 2020-11-26 17:32:30 +01:00
Benno Schulenberg
29276d1d3a help: allow the penultimate item extra space when the number is uneven
This avoids unnecessarily truncating the last help item on the
very bottom row when there is still plenty of room.

This fixes https://savannah.gnu.org/bugs/?59550.

Bug has been visible since at least version 2.5.1.
2020-11-26 17:12:09 +01:00
Benno Schulenberg
13b839734f hellp: show all valid help items also in the Write-Out menu
Subtract one from the count only if all possible items in the menu
have been counted (item == NULL), meaning that the last item in the
Write-Out menu (the 'discard_buffer' function) has been counted too.

This fixes https://savannah.gnu.org/bugs/?59549.

Bug existed since version 4.5, commit b3ace4d8.
2020-11-26 15:37:21 +01:00
Benno Schulenberg
63bb1b62b7 gnulib: update to its current upstream state 2020-11-25 11:22:46 +01:00
Benno Schulenberg
743100feab options: do not spew out the help text when an option is not recognized
When getopt() does not recognize an option, it returns '?', which means
that '-?' cannot be used as a valid option because any invalid option
would be treated the same way as '-?'.

Spewing out the full help text drowns the "invalid option" message at
the beginning.

This fixes https://savannah.gnu.org/bugs/?59530.

Bug existed since version 5.3, commit 5bd92d4c.
2020-11-24 10:09:41 +01:00
Benno Schulenberg
d3d2d324d2 statusbar: properly pluralize the line+word+character count report
This avoids poor wordings such as "Words: 1  Lines: 1  Chars: 1".

Also, display the numbers in a more logical, ascending order: lines
first, words second, characters third.  This is what 'wc' uses, too.
2020-11-21 15:25:23 +01:00
Benno Schulenberg
925a1a11f9 feedback: abort when user tries to open multiple files in tiny version
This fixes https://savannah.gnu.org/bugs/?56227.
2020-11-17 19:08:12 +01:00
Benno Schulenberg
5918ca6cab tweaks: normalize the formatting after the previous two changes 2020-11-17 10:28:28 +01:00
Benno Schulenberg
dc907bfe43 prompt: skip over combining characters also when editing a search string 2020-11-17 10:27:47 +01:00
Benno Schulenberg
687efd210c moving: skip combining characters and other zero-width characters
This makes the cursor move smoothly left and right -- instead of
"stuttering" when passing over a zero-width character.

Pressing <Delete> on a normal (spacing) character also deletes
any zero-width characters after it.  But pressing <Backspace>
while the cursor is placed after a zero-width character, just
deletes that zero-width character.  The latter behavior allows
deleting and retyping just the combining diacritic of a character
instead of the whole character.

This addresses https://savannah.gnu.org/bugs/?50773.
Requested-by: Mike Frysinger <vapier@gentoo.org>
2020-11-17 10:21:50 +01:00
Benno Schulenberg
b7539ea985 weeding: remove a workaround for versions of ncurses before 5.9
(Yes, the test is for 6.0, but the bug was actually fixed in 5.9,
as far as I remember -- I just wasn't sure and didn't want to bother
building different versions of ncurses myself.)
2020-11-15 10:27:22 +01:00
Benno Schulenberg
7d35f71c87 weeding: remove a workaround for early versions of ncurses-6.0
Those versions are more than five years old.  If there are still
machines with those versions, people should upgrade ncurses too
if they want the newest version of nano.
2020-11-15 10:27:22 +01:00
Benno Schulenberg
7f184ee2ba linting: avoid putting the cursor beyond the end of the line
Some linters report a column position (assuming a TAB to be 8 spaces)
instead of a byte index, so make sure that the cursor is not placed
out of bounds when interpreting such a column number as an index.

This fixes https://savannah.gnu.org/bugs/?59419.
Reported-by: Ava McWhorter <qwerty0s.e.m@gmail.com>

Bug existed since version 2.8.1, commit 2439e1e4.
2020-11-06 10:36:08 +01:00
Benno Schulenberg
ec9fc5d320 utils: die when trying to allocate zero bytes
This shouldn't occur, so go down when it does.
2020-10-29 16:18:03 +01:00
Benno Schulenberg
3c2eb96243 tweaks: rename two variables and improve two comments 2020-10-21 12:24:52 +02:00
Benno Schulenberg
de313586ab tweaks: reshuffle three lines and elide braces after the previous change 2020-10-21 11:39:56 +02:00
Benno Schulenberg
e96bda4b9f tweaks: avoid copying an option's argument when there is no need
This takes eight extra calls of copy_of(), but saves ten calls of
free().  But more importantly: it avoids an unneeded copying and
then freeing again of the argument after 'titlecolor' and friends.
2020-10-21 11:37:21 +02:00
Benno Schulenberg
d9944c03c4 docs: adjust for the changed name of the header-file package on Debian
Also, be more complete, reword a few things, and stop mentioning Slang.
2020-10-11 16:44:40 +02:00
Benno Schulenberg
b9d6d547b8 bindings: accept b for scrolling back up in help viewer and file browser
Like in Dillo, and because it could be mnemonic for "Back" and
is directly above the space bar (in a QWERTY layout, at least).
2020-10-11 16:11:21 +02:00
Benno Schulenberg
622b031e27 docs: use standard-compliant HTML entities for the four arrows
HTML 4 knows only the four-letter abbreviations for the arrows.
Use those, so that also browsers with very limited knowledge
(like Dillo) will show the arrows correctly.
2020-10-11 15:58:40 +02:00
Benno Schulenberg
26f5c8b9d5 rcfile: stop accepting 'set view' in a nanorc file, and undocument it
Like --restricted, --view really only makes sense on the command line.
2020-10-10 12:42:20 +02:00
Benno Schulenberg
e1601d2eb5 tweaks: use the standard symbols for the three standard file descriptors
Also, take into account (as elsewhere) that dup2() could fail,
and harmonize their error checks.
2020-10-10 12:32:02 +02:00
Benno Schulenberg
bc14fc35d7 tweaks: reshuffle a line, elide two braces, and adjust the indentation
And improve a comment.
2020-10-08 15:07:03 +02:00
Benno Schulenberg
f660f22623 tweaks: slightly shorten a loop, to place the actual action outside of it
And in the bargain elide a variable, and make it clearer
what the return value is at two early exit points.

[This change makes use of the fact that TRUE (successful write) == 1
and FALSE (failed write) == 0.  But this is already used twenty lines
earlier, for the other call of write_file().]
2020-10-08 15:07:03 +02:00
68 changed files with 15892 additions and 14958 deletions

View File

@@ -1,3 +1,40 @@
Changes between v5.3 and v5.4:
------------------------------
Benno Schulenberg (31):
bindings: accept b for scrolling back up in help viewer and file browser
build: exclude a workaround for VTE/Konsole when using a recent ncurses
build: include a workaround for VTE only when using an older libvte
bump version numbers and add a news item for the 5.4 release
copyright: update to the current year for significantly changed files
docs: adjust for the changed name of the header-file package on Debian
docs: use standard-compliant HTML entities for the four arrows
feedback: abort when user tries to open multiple files in tiny version
gnulib: update to its current upstream state
help: allow the penultimate item extra space when the number is uneven
help: show all valid help items also in the Write-Out menu
linting: avoid putting the cursor beyond the end of the line
moving: skip combining characters and other zero-width characters
options: do not spew out the help text when an option is not recognized
prompt: skip over combining characters also when editing a search string
rcfile: stop accepting 'set view' in a nanorc file, and undocument it
statusbar: properly pluralize the line+word+character count report
tweaks: avoid copying an option's argument when there is no need
tweaks: normalize the formatting after the previous two changes
tweaks: rename two variables and improve two comments
tweaks: rename two variables, one for contrast, another for visibility
tweaks: reshuffle a fragment of code, for clarity
tweaks: reshuffle a line, elide two braces, and adjust the indentation
tweaks: reshuffle three lines and elide braces after the previous change
tweaks: slightly shorten a loop, to place the actual action outside of it
tweaks: use the standard symbols for the three standard file descriptors
utils: die when trying to allocate zero bytes
weeding: remove another unneeded workaround for VTE
weeding: remove a workaround for early versions of ncurses-6.0
weeding: remove a workaround for versions of ncurses before 5.9
weeding: remove a workaround for VTE that is not needed
Changes between v5.2 and v5.3:
------------------------------

View File

@@ -2,6 +2,8 @@ Improvements in GNU nano
========================
Since 5.0:
- The cursor skips over combining characters, <Del> deletes them together
with the character they combine with, but <Bsp> deletes them separately.
- For using libmagic the option --magic or -! or 'set magic' is required.
- With --stateflags the state of some things is shown in the title bar.
- M-Bsp deletes a word leftward.

6
NEWS
View File

@@ -1,3 +1,9 @@
2020.12.02 - GNU nano 5.4 "Terre des hommes"
• Moving the cursor now skips over combining characters (and other
zero-width characters). Deleting a character deletes also any
succeeding zero-width characters, but backspacing deletes just
one character at a time.
2020.10.07 - GNU nano 5.3 "Revolution!"
• Option 'set stateflags' makes nano show the state of auto-indenting,
the mark, hard-wrapping, macro recording, and soft-wrapping in the

15
README
View File

@@ -25,7 +25,7 @@ Overview
How to compile and install nano
Download the latest nano source tarball, then:
Download the latest nano source tarball, and then:
tar -xvf nano-x.y.tar.gz
cd nano-x.y
@@ -33,12 +33,13 @@ How to compile and install nano
make
make install
It's that simple. Use --prefix with configure to override the
default installation directory of /usr/local.
You will need the header files of ncurses installed for ./configure
to succeed -- get them from libncurses-dev (Debian) or ncurses-devel
(Fedora) or a similarly named package. Use --prefix with ./configure
to override the default installation directory of /usr/local.
If you haven't configured with the --disable-nanorc option, after
installation you may want to copy the doc/sample.nanorc file to
your home directory, rename it to ".nanorc", and then edit it
After installation you may want to copy the doc/sample.nanorc file
to your home directory, rename it to ".nanorc", and then edit it
according to your taste.
Web Page
@@ -51,8 +52,10 @@ Mailing Lists
+ info-nano@gnu.org is a very low traffic list used to announce
new nano versions or other important info about the project.
+ help-nano@gnu.org is for those seeking to get help without
wanting to hear about the technical details of its development.
+ nano-devel@gnu.org is the list used by the people that make nano
and a general development discussion list, with moderate traffic.

View File

@@ -22,11 +22,11 @@ packages:
- pkg-config (version >= 0.22)
- texinfo (version >= 4.0)
If you want UTF-8 support, you will also need libncursesw5-dev installed
(version >= 5.7), or libslang2-dev (version >= 2.0) if you use --with-slang.
You will also need to have the header files for ncurses installed,
from libncurses-dev on Debian, ncurses-devel on Fedora, or similar.
These should all be available in your distro's package manager or software
center, or otherwise on any GNU mirror.
These should all be available in your distro's package manager or
software center, or otherwise on any GNU mirror.
Download the source

View File

@@ -2,7 +2,7 @@
# Generate configure & friends for GIT users.
gnulib_url="git://git.sv.gnu.org/gnulib.git"
gnulib_hash="6160ee8e4d2b88d934c3c4c8c5930a75b835723f"
gnulib_hash="387d654cabd7bc1594b1fc8d195cd9b66f820296"
modules="
futimens

View File

@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see https://www.gnu.org/licenses/.
AC_INIT([GNU nano], [5.3], [nano-devel@gnu.org], [nano])
AC_INIT([GNU nano], [5.4], [nano-devel@gnu.org], [nano])
AC_CONFIG_SRCDIR([src/nano.c])
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([1.14])
@@ -608,7 +608,7 @@ fi
if eval "test x$CURSES_LIB_NAME = x"; then
AC_MSG_ERROR([
*** No curses lib was found. Please install the curses header files
*** from libncursesw5-dev (Debian), ncurses-devel (Fedora), or similar.
*** from libncurses-dev (Debian), ncurses-devel (Fedora), or similar.
*** (Or install ncurses from https://ftp.gnu.org/gnu/ncurses/.)])
else
AC_MSG_RESULT([ The curses library to be used is: $CURSES_LIB_NAME])

View File

@@ -79,14 +79,14 @@
<table><tbody>
<tr><td>Ctrl+B &nbsp;&nbsp;</td><td>One character backward</td></tr>
<tr><td>Ctrl+F</td><td>One character forward</td></tr>
<tr><td>Ctrl+<b>&leftarrow;</b></td><td>One word backward</td></tr>
<tr><td>Ctrl+<b>&rightarrow;</b></td><td>One word forward</td></tr>
<tr><td>Ctrl+<b>&larr;</b></td><td>One word backward</td></tr>
<tr><td>Ctrl+<b>&rarr;</b></td><td>One word forward</td></tr>
<tr><td>Ctrl+A</td><td>To start of line</td></tr>
<tr><td>Ctrl+E</td><td>To end of line</td></tr>
<tr><td>Ctrl+P</td><td>One line up</td></tr>
<tr><td>Ctrl+N</td><td>One line down</td></tr>
<tr><td>Ctrl+<b>&uparrow;</b></td><td>To previous block</td></tr>
<tr><td>Ctrl+<b>&downarrow;</b></td><td>To next block</td></tr>
<tr><td>Ctrl+<b>&uarr;</b></td><td>To previous block</td></tr>
<tr><td>Ctrl+<b>&darr;</b></td><td>To next block</td></tr>
<tr><td>Ctrl+Y</td><td>One page up</td></tr>
<tr><td>Ctrl+V</td><td>One page down</td></tr>
<tr><td>Alt+\</td><td>To top of buffer</td></tr>
@@ -98,8 +98,8 @@
<table><tbody>
<tr><td>Alt+G &nbsp;&nbsp;&nbsp;</td><td>Go to specified line</td></tr>
<tr><td>Alt+]</td><td>Go to complementary bracket</td></tr>
<tr><td>Alt+<b>&uparrow;</b></td><td>Scroll viewport up</td></tr>
<tr><td>Alt+<b>&downarrow;</b></td><td>Scroll viewport down</td></tr>
<tr><td>Alt+<b>&uarr;</b></td><td>Scroll viewport up</td></tr>
<tr><td>Alt+<b>&darr;</b></td><td>Scroll viewport down</td></tr>
<tr><td>Alt+&lt;</td><td>Switch to preceding buffer</td></tr>
<tr><td>Alt+&gt;</td><td>Switch to succeeding buffer</td></tr>
</tbody></table>

View File

@@ -89,7 +89,7 @@
<h3><a name="1.3"></a>1.3. Why the name change from TIP?</h3>
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program &quot;establishes a full duplex terminal connection to a remote host&quot;, and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
<h3><a name="1.4"></a>1.4. What is the current version of nano?</h3>
<blockquote><p>The current version of nano <i>should</i> be <b>5.3</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
<blockquote><p>The current version of nano <i>should</i> be <b>5.4</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
<h3><a name="1.5"></a>1.5. I want to read the man page without having to download the program!</h3>
<blockquote><p>Jeez, demanding, aren't we? Okay, look <a href="https://nano-editor.org/dist/latest/nano.1.html">here</a>.</p></blockquote>
<hr width="100%">

View File

@@ -16,7 +16,7 @@
.\" Documentation License along with this program. If not, see
.\" <https://www.gnu.org/licenses/>.
.\"
.TH NANO 1 "version 5.3" "October 2020"
.TH NANO 1 "version 5.4" "December 2020"
.SH NAME
nano \- Nano's ANOther editor, inspired by Pico

View File

@@ -8,8 +8,8 @@
@smallbook
@set EDITION 0.5
@set VERSION 5.3
@set UPDATED October 2020
@set VERSION 5.4
@set UPDATED December 2020
@dircategory Editors
@direntry
@@ -23,7 +23,7 @@
@titlepage
@title GNU @command{nano}
@subtitle a small and friendly text editor
@subtitle version 5.3
@subtitle version 5.4
@author Chris Allegretta
@page
@@ -63,7 +63,7 @@ e-mail: @email{chrisa@@asty.org}@*
@node Top
@top
This manual documents the GNU @command{nano} editor, version 5.3.
This manual documents the GNU @command{nano} editor, version 5.4.
@menu
* Introduction::
@@ -1067,11 +1067,6 @@ Save a file by default in Unix format. This overrides nano's
default behavior of saving a file in the format that it had.
(This option has no effect when you also use @code{set noconvert}.)
@item set view
Disallow file modification: read-only mode.
This mode allows the user to open also other files for viewing,
unless @option{--restricted} is given on the command line.
@anchor{Whitespace}
@item set whitespace "@var{characters}"
Set the two characters used to indicate the presence of tabs and

View File

@@ -16,7 +16,7 @@
.\" Documentation License along with this program. If not, see
.\" <https://www.gnu.org/licenses/>.
.\"
.TH NANORC 5 "version 5.3" "October 2020"
.TH NANORC 5 "version 5.4" "December 2020"
.SH NAME
nanorc \- GNU nano's configuration file
@@ -352,11 +352,6 @@ Save a file by default in Unix format. This overrides nano's
default behavior of saving a file in the format that it had.
(This option has no effect when you also use \fBset noconvert\fR.)
.TP
.B set view
Disallow file modification: read-only mode.
This mode allows the user to open also other files for viewing,
unless \fB\-\-restricted\fR is given on the command line.
.TP
.BI "set whitespace """ characters """
Set the two characters used to indicate the presence of tabs and
spaces. They must be single-column characters. The default pair

View File

@@ -16,7 +16,7 @@
.\" Documentation License along with this program. If not, see
.\" <https://www.gnu.org/licenses/>.
.\"
.TH RNANO 1 "version 5.3" "October 2020"
.TH RNANO 1 "version 5.4" "December 2020"
.SH NAME
rnano \- a restricted nano

View File

@@ -179,9 +179,6 @@
## Snip whitespace at the end of lines when justifying or hard-wrapping.
# set trimblanks
## Disallow file modification. Why would you want this in an rcfile? ;)
# set view
## The two single-column characters used to display the first characters
## of tabs and spaces. 187 in ISO 8859-1 (0000BB in Unicode) and 183 in
## ISO-8859-1 (0000B7 in Unicode) seem to be good values for these.

810
po/bg.po

File diff suppressed because it is too large Load Diff

816
po/ca.po

File diff suppressed because it is too large Load Diff

807
po/cs.po

File diff suppressed because it is too large Load Diff

804
po/da.po

File diff suppressed because it is too large Load Diff

810
po/de.po

File diff suppressed because it is too large Load Diff

812
po/eo.po

File diff suppressed because it is too large Load Diff

808
po/es.po

File diff suppressed because it is too large Load Diff

810
po/eu.po

File diff suppressed because it is too large Load Diff

804
po/fi.po

File diff suppressed because it is too large Load Diff

808
po/fr.po

File diff suppressed because it is too large Load Diff

813
po/ga.po

File diff suppressed because it is too large Load Diff

1487
po/gl.po

File diff suppressed because it is too large Load Diff

1096
po/hr.po

File diff suppressed because it is too large Load Diff

804
po/hu.po

File diff suppressed because it is too large Load Diff

799
po/id.po

File diff suppressed because it is too large Load Diff

804
po/it.po

File diff suppressed because it is too large Load Diff

805
po/ja.po

File diff suppressed because it is too large Load Diff

801
po/ko.po

File diff suppressed because it is too large Load Diff

825
po/ms.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

808
po/nb.po

File diff suppressed because it is too large Load Diff

808
po/nl.po

File diff suppressed because it is too large Load Diff

810
po/nn.po

File diff suppressed because it is too large Load Diff

807
po/pl.po

File diff suppressed because it is too large Load Diff

814
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

819
po/ro.po

File diff suppressed because it is too large Load Diff

813
po/ru.po

File diff suppressed because it is too large Load Diff

816
po/sl.po

File diff suppressed because it is too large Load Diff

1010
po/sr.po

File diff suppressed because it is too large Load Diff

804
po/sv.po

File diff suppressed because it is too large Load Diff

810
po/tr.po

File diff suppressed because it is too large Load Diff

811
po/uk.po

File diff suppressed because it is too large Load Diff

801
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#!/bin/bash
VERSION="5.3"
VERSION="5.4"
./configure -C --enable-tiny && make && ./configure -C &&

View File

@@ -2,7 +2,7 @@
* browser.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2001-2011, 2013-2020 Free Software Foundation, Inc. *
* Copyright (C) 2015-2016 Benno Schulenberg *
* Copyright (C) 2015-2016, 2020 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -30,7 +30,7 @@
static char **filelist = NULL;
/* The list of files to display in the file browser. */
static size_t filelist_len = 0;
static size_t list_length = 0;
/* The number of files in the list. */
static size_t width = 0;
/* The number of files that we can display per screen row. */
@@ -40,14 +40,14 @@ static size_t selected = 0;
/* The currently selected filename in the list; zero-based. */
/* Set filelist to the list of files contained in the directory path,
* set filelist_len to the number of files in that list, set longest to
* set list_length to the number of files in that list, set longest to
* the width in columns of the longest filename in that list (between 15
* and COLS), and set width to the number of files that we can display
* per screen row. And sort the list too. */
void read_the_list(const char *path, DIR *dir)
{
size_t path_len = strlen(path), index = 0;
const struct dirent *nextdir;
size_t i = 0, path_len = strlen(path);
longest = 0;
@@ -58,7 +58,7 @@ void read_the_list(const char *path, DIR *dir)
if (name_len > longest)
longest = name_len;
i++;
index++;
}
/* Put 10 characters' worth of blank space between columns of filenames
@@ -74,32 +74,31 @@ void read_the_list(const char *path, DIR *dir)
rewinddir(dir);
free_chararray(filelist, filelist_len);
free_chararray(filelist, list_length);
filelist_len = i;
list_length = index;
index = 0;
filelist = nmalloc(filelist_len * sizeof(char *));
filelist = nmalloc(list_length * sizeof(char *));
i = 0;
while ((nextdir = readdir(dir)) != NULL && i < filelist_len) {
while ((nextdir = readdir(dir)) != NULL && index < list_length) {
/* Don't show the "." entry. */
if (strcmp(nextdir->d_name, ".") == 0)
continue;
filelist[i] = nmalloc(path_len + strlen(nextdir->d_name) + 1);
sprintf(filelist[i], "%s%s", path, nextdir->d_name);
filelist[index] = nmalloc(path_len + strlen(nextdir->d_name) + 1);
sprintf(filelist[index], "%s%s", path, nextdir->d_name);
i++;
index++;
}
/* Maybe the number of files in the directory changed between the
* first time we scanned and the second. i is the actual length of
* filelist, so record it. */
filelist_len = i;
/* Maybe the number of files in the directory decreased between the
* first time we scanned and the second time. index is the actual
* length of the file list, so record it. */
list_length = index;
/* Sort the list of names. */
qsort(filelist, filelist_len, sizeof(char *), diralphasort);
qsort(filelist, list_length, sizeof(char *), diralphasort);
/* Calculate how many files fit on a line -- feigning room for two
* spaces beyond the right edge, and adding two spaces of padding
@@ -113,7 +112,7 @@ void browser_select_dirname(const char *needle)
{
size_t looking_at = 0;
for (; looking_at < filelist_len; looking_at++) {
for (; looking_at < list_length; looking_at++) {
if (strcmp(filelist[looking_at], needle) == 0) {
selected = looking_at;
break;
@@ -122,12 +121,12 @@ void browser_select_dirname(const char *needle)
/* If the sought name isn't found, move the highlight so that the
* changed selection will be noticed. */
if (looking_at == filelist_len) {
if (looking_at == list_length) {
--selected;
/* Make sure we stay within the available range. */
if (selected >= filelist_len)
selected = filelist_len - 1;
if (selected >= list_length)
selected = list_length - 1;
}
}
@@ -145,7 +144,7 @@ void browser_refresh(void)
blank_edit();
for (size_t index = selected - selected % (editwinrows * width);
index < filelist_len && row < editwinrows; index++) {
index < list_length && row < editwinrows; index++) {
const char *thename = tail(filelist[index]);
/* The filename we display, minus the path. */
size_t namelen = breadth(thename);
@@ -283,13 +282,13 @@ void findfile(const char *needle, bool forwards)
* we've come back to the point where we started. */
while (TRUE) {
if (forwards) {
if (looking_at++ == filelist_len - 1) {
if (looking_at++ == list_length - 1) {
looking_at = 0;
statusbar(_("Search Wrapped"));
}
} else {
if (looking_at-- == 0) {
looking_at = filelist_len - 1;
looking_at = list_length - 1;
statusbar(_("Search Wrapped"));
}
}
@@ -488,8 +487,8 @@ char *browse(char *path)
selected--;
/* If we're beyond the list, select the last filename. */
if (selected > filelist_len - 1)
selected = filelist_len - 1;
if (selected > list_length - 1)
selected = list_length - 1;
/* If we selected the same filename as last time, fake a
* press of the Enter key so that the file is read in. */
@@ -539,19 +538,19 @@ char *browse(char *path)
if (selected > 0)
selected--;
} else if (func == do_right) {
if (selected < filelist_len - 1)
if (selected < list_length - 1)
selected++;
} else if (func == to_prev_word) {
selected -= (selected % width);
} else if (func == to_next_word) {
selected += width - 1 - (selected % width);
if (selected >= filelist_len)
selected = filelist_len - 1;
if (selected >= list_length)
selected = list_length - 1;
} else if (func == do_up) {
if (selected >= width)
selected -= width;
} else if (func == do_down) {
if (selected + width <= filelist_len - 1)
if (selected + width <= list_length - 1)
selected += width;
} else if (func == to_prev_block) {
selected = ((selected / (editwinrows * width)) *
@@ -560,9 +559,9 @@ char *browse(char *path)
selected = ((selected / (editwinrows * width)) *
editwinrows * width) + selected % width +
editwinrows * width - width;
if (selected >= filelist_len)
selected = (filelist_len / width) * width + selected % width;
if (selected >= filelist_len)
if (selected >= list_length)
selected = (list_length / width) * width + selected % width;
if (selected >= list_length)
selected -= width;
} else if (func == do_page_up) {
if (selected < width)
@@ -572,17 +571,17 @@ char *browse(char *path)
else
selected -= editwinrows * width;
} else if (func == do_page_down) {
if (selected + width >= filelist_len - 1)
selected = filelist_len - 1;
else if (selected + editwinrows * width >= filelist_len)
selected = (selected + editwinrows * width - filelist_len) %
width + filelist_len - width;
if (selected + width >= list_length - 1)
selected = list_length - 1;
else if (selected + editwinrows * width >= list_length)
selected = (selected + editwinrows * width - list_length) %
width + list_length - width;
else
selected += editwinrows * width;
} else if (func == to_first_file) {
selected = 0;
} else if (func == to_last_file) {
selected = filelist_len - 1;
selected = list_length - 1;
} else if (func == goto_dir) {
/* Ask for the directory to go to. */
if (do_prompt(MGOTODIR, "", NULL,
@@ -616,7 +615,7 @@ char *browse(char *path)
/* In case the specified directory cannot be entered, select it
* (if it is in the current list) so it will be highlighted. */
for (size_t j = 0; j < filelist_len; j++)
for (size_t j = 0; j < list_length; j++)
if (strcmp(filelist[j], path) == 0)
selected = j;
@@ -690,9 +689,9 @@ char *browse(char *path)
free(path);
free_chararray(filelist, filelist_len);
free_chararray(filelist, list_length);
filelist = NULL;
filelist_len = 0;
list_length = 0;
return chosen;
}

View File

@@ -2,7 +2,7 @@
* chars.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2001-2011, 2013-2020 Free Software Foundation, Inc. *
* Copyright (C) 2016-2019 Benno Schulenberg *
* Copyright (C) 2016-2020 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -197,6 +197,12 @@ int mbwidth(const char *c)
return 1;
}
/* Return TRUE when the given character occupies zero cells. */
bool is_zerowidth(const char *ch)
{
return (use_utf8 && mbwidth(ch) == 0);
}
/* Convert the given Unicode value to a multibyte character, if possible.
* If the conversion succeeds, return the (dynamically allocated) multibyte
* character and its length. Otherwise, return a length of zero. */

View File

@@ -2,7 +2,7 @@
* color.c -- This file is part of GNU nano. *
* *
* Copyright (C) 2001-2011, 2013-2020 Free Software Foundation, Inc. *
* Copyright (C) 2014-2017 Benno Schulenberg *
* Copyright (C) 2014-2017, 2020 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -29,15 +29,6 @@
#endif
#include <string.h>
/* For early versions of ncurses-6.0, use an additional A_PROTECT attribute
* for all colors, in order to work around an ncurses miscoloring bug. */
#if defined(NCURSES_VERSION_MAJOR) && (NCURSES_VERSION_MAJOR == 6) && \
(NCURSES_VERSION_MINOR == 0) && (NCURSES_VERSION_PATCH < 20151017)
#define A_BANDAID A_PROTECT
#else
#define A_BANDAID A_NORMAL
#endif
static bool defaults_allowed = FALSE;
/* Whether ncurses accepts -1 to mean "default color". */
@@ -61,8 +52,7 @@ void set_interface_colorpairs(void)
combo->bg = COLOR_BLACK;
}
init_pair(index + 1, combo->fg, combo->bg);
interface_color_pair[index] = COLOR_PAIR(index + 1) | A_BANDAID |
combo->attributes;
interface_color_pair[index] = COLOR_PAIR(index + 1) | combo->attributes;
} else {
if (index == FUNCTION_TAG || index == SCROLL_BAR)
interface_color_pair[index] = A_NORMAL;
@@ -70,8 +60,7 @@ void set_interface_colorpairs(void)
interface_color_pair[index] = A_REVERSE;
else if (index == ERROR_MESSAGE) {
init_pair(index + 1, COLOR_WHITE, COLOR_RED);
interface_color_pair[index] = COLOR_PAIR(index + 1) |
A_BOLD | A_BANDAID;
interface_color_pair[index] = COLOR_PAIR(index + 1) | A_BOLD;
} else
interface_color_pair[index] = hilite_attribute;
}
@@ -102,7 +91,7 @@ void set_syntax_colorpairs(syntaxtype *sntx)
ink->pairnum = (older != ink) ? older->pairnum : ++number;
ink->attributes |= COLOR_PAIR(ink->pairnum) | A_BANDAID;
ink->attributes |= COLOR_PAIR(ink->pairnum);
}
}

View File

@@ -3,7 +3,7 @@
* *
* Copyright (C) 1999-2011, 2013-2020 Free Software Foundation, Inc. *
* Copyright (C) 2014 Mark Majeres *
* Copyright (C) 2016, 2018, 2019 Benno Schulenberg *
* Copyright (C) 2016, 2018-2020 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -121,7 +121,14 @@ void do_delete(void)
zap_text();
else
#endif
{
do_deletion(DEL);
#ifdef ENABLE_UTF8
while (openfile->current->data[openfile->current_x] != '\0' &&
is_zerowidth(openfile->current->data + openfile->current_x))
do_deletion(DEL);
#endif
}
}
/* Backspace over one character. That is, move the cursor left one
@@ -133,7 +140,10 @@ void do_backspace(void)
zap_text();
else
#endif
if (openfile->current_x > 0 || openfile->current != openfile->filetop) {
if (openfile->current_x > 0) {
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
do_deletion(BACK);
} else if (openfile->current != openfile->filetop) {
do_left();
do_deletion(BACK);
}

View File

@@ -85,10 +85,6 @@
#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
@@ -135,8 +131,6 @@
#define BAD_COLOR -2
#endif
#define STANDARD_INPUT 0
/* Enumeration types. */
typedef enum {
NIX_FILE, DOS_FILE, MAC_FILE

View File

@@ -722,7 +722,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
/* When reading from stdin, restore the terminal and reenter curses mode. */
if (isendwin()) {
if (!isatty(STANDARD_INPUT))
if (!isatty(STDIN_FILENO))
reconnect_and_store_state();
terminal_init();
doupdate();
@@ -966,13 +966,16 @@ bool execute_command(const char *command)
close(from_fd[0]);
/* Connect the write end of the output pipe to the process' output streams. */
dup2(from_fd[1], fileno(stdout));
dup2(from_fd[1], fileno(stderr));
if (dup2(from_fd[1], STDOUT_FILENO) < 0)
exit(3);
if (dup2(from_fd[1], STDERR_FILENO) < 0)
exit(4);
/* If the parent sends text, connect the read end of the
* feeding pipe to the child's input stream. */
if (should_pipe) {
dup2(to_fd[0], fileno(stdin));
if (dup2(to_fd[0], STDIN_FILENO) < 0)
exit(5);
close(to_fd[1]);
}
@@ -980,7 +983,7 @@ bool execute_command(const char *command)
execl(theshell, tail(theshell), "-c", should_pipe ? &command[1] : command, NULL);
/* If the exec call returns, there was an error. */
exit(1);
exit(6);
}
/* Parent: close the unused write end of the pipe. */
@@ -2043,12 +2046,11 @@ bool write_marked_file(const char *name, FILE *stream, bool tmp,
* the buffer is to be discarded. */
int do_writeout(bool exiting, bool withprompt)
{
bool result = FALSE;
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');
/* Whether it's okay to save the file under a different name. */
kind_of_writing_type method = OVERWRITE;
#ifdef ENABLE_EXTRA
static bool did_credits = FALSE;
#endif
@@ -2105,7 +2107,8 @@ int do_writeout(bool exiting, bool withprompt)
if (response < 0) {
statusbar(_("Cancelled"));
break;
free(given);
return 0;
}
func = func_from_key(&response);
@@ -2147,9 +2150,8 @@ int do_writeout(bool exiting, bool withprompt)
continue;
}
#endif
if (func == do_help) {
if (func == do_help)
continue;
}
#ifdef ENABLE_EXTRA
/* If the user pressed Ctrl-X in the edit window, and answered "Y" at
@@ -2163,7 +2165,9 @@ int do_writeout(bool exiting, bool withprompt)
} else
/* TRANSLATORS: Concisely say the screen is too small. */
statusbar(_("Too tiny"));
break;
free(given);
return 0;
}
#endif
@@ -2176,6 +2180,7 @@ int do_writeout(bool exiting, bool withprompt)
full_filename = get_full_path(openfile->filename);
name_exists = (stat((full_answer == NULL) ?
answer : full_answer, &st) != -1);
if (openfile->filename[0] == '\0')
do_warning = name_exists;
else
@@ -2262,23 +2267,19 @@ int do_writeout(bool exiting, bool withprompt)
#endif
}
/* Here's where we allow the selected text to be written to
* a separate file. If we're using restricted mode, this
* function is disabled, since it allows reading from or
* writing to files not specified on the command line. */
#ifndef NANO_TINY
if (openfile->mark && !exiting && withprompt && !ISSET(RESTRICTED))
result = write_marked_file(answer, NULL, FALSE, method);
else
#endif
result = write_file(answer, NULL, FALSE, method, TRUE);
free(given);
break;
}
free(given);
return result ? 1 : 0;
/* When the mark is on (and we've prompted for a name and we're
* not exiting and we're not in restricted mode), then write out
* the marked region; otherwise, write out the whole buffer. */
#ifndef NANO_TINY
if (openfile->mark && withprompt && !exiting && !ISSET(RESTRICTED))
return write_marked_file(answer, NULL, FALSE, method);
else
#endif
return write_file(answer, NULL, FALSE, method, TRUE);
}
/* Write the current buffer to disk, or discard it. */

View File

@@ -477,7 +477,8 @@ size_t shown_entries_for(int menu)
}
/* When --saveonexit is not used, widen the grid of the WriteOut menu. */
if (menu == MWRITEFILE && first_sc_for(menu, discard_buffer) == NULL)
if (menu == MWRITEFILE && item == NULL &&
first_sc_for(menu, discard_buffer) == NULL)
count--;
return count;
@@ -529,6 +530,7 @@ functionptrtype interpret(int *keycode)
return do_findnext;
switch (tolower(*keycode)) {
case 'b':
case '-':
return do_page_up;
case ' ':

View File

@@ -291,6 +291,10 @@ void do_prev_word(bool allow_punct)
/* If at the head of a line now, this surely is a word start. */
if (openfile->current_x == 0)
break;
#ifdef ENABLE_UTF8
} else if (is_zerowidth(openfile->current->data + openfile->current_x)) {
; /* skip */
#endif
} else if (seen_a_word) {
/* This is space now: we've overshot the start of the word. */
step_forward = TRUE;
@@ -339,11 +343,20 @@ bool do_next_word(bool after_ends, bool allow_punct)
if (is_word_char(openfile->current->data + openfile->current_x,
allow_punct))
seen_word = TRUE;
#ifdef ENABLE_UTF8
else if (is_zerowidth(openfile->current->data + openfile->current_x))
; /* skip */
#endif
else if (seen_word)
break;
} else
#endif
{
#ifdef ENABLE_UTF8
if (is_zerowidth(openfile->current->data + openfile->current_x))
; /* skip */
else
#endif
/* If this is not a word character, then it's a separator; else
* if we've already seen a separator, then it's a word start. */
if (!is_word_char(openfile->current->data + openfile->current_x,
@@ -581,10 +594,16 @@ void do_left(void)
{
linestruct *was_current = openfile->current;
if (openfile->current_x > 0)
if (openfile->current_x > 0) {
openfile->current_x = step_left(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->filetop) {
#ifdef ENABLE_UTF8
while (openfile->current_x > 0 &&
is_zerowidth(openfile->current->data + openfile->current_x))
openfile->current_x = step_left(openfile->current->data,
openfile->current_x);
#endif
} else if (openfile->current != openfile->filetop) {
openfile->current = openfile->current->prev;
openfile->current_x = strlen(openfile->current->data);
}
@@ -597,10 +616,16 @@ void do_right(void)
{
linestruct *was_current = openfile->current;
if (openfile->current->data[openfile->current_x] != '\0')
if (openfile->current->data[openfile->current_x] != '\0') {
openfile->current_x = step_right(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->filebot) {
#ifdef ENABLE_UTF8
while (openfile->current->data[openfile->current_x] != '\0' &&
is_zerowidth(openfile->current->data + openfile->current_x))
openfile->current_x = step_right(openfile->current->data,
openfile->current_x);
#endif
} else if (openfile->current != openfile->filebot) {
openfile->current = openfile->current->next;
openfile->current_x = 0;
}

View File

@@ -225,7 +225,7 @@ void restore_terminal(void)
printf("\x1B[?2004l");
fflush(stdout);
#endif
tcsetattr(0, TCSANOW, &original_state);
tcsetattr(STDIN_FILENO, TCSANOW, &original_state);
}
/* Exit normally: restore terminal state and report any startup errors. */
@@ -813,15 +813,14 @@ void reconnect_and_store_state(void)
{
int thetty = open("/dev/tty", O_RDONLY);
if (thetty < 1)
if (thetty < 0 || dup2(thetty, STDIN_FILENO) < 0)
die(_("Could not reconnect stdin to keyboard\n"));
dup2(thetty, STANDARD_INPUT);
close(thetty);
/* If input was not cut short, store the current state of the terminal. */
if (!control_C_was_pressed)
tcgetattr(0, &original_state);
tcgetattr(STDIN_FILENO, &original_state);
}
/* Read whatever comes from standard input into a new buffer. */
@@ -832,7 +831,7 @@ bool scoop_stdin(void)
restore_terminal();
/* When input comes from a terminal, show a helpful message. */
if (isatty(STANDARD_INPUT))
if (isatty(STDIN_FILENO))
fprintf(stderr, _("Reading data from keyboard; "
"type ^D or ^D^D to finish.\n"));
@@ -1801,16 +1800,16 @@ int main(int argc, char **argv)
struct vt_stat dummy;
/* Check whether we're running on a Linux console. */
on_a_vt = (ioctl(1, VT_GETSTATE, &dummy) == 0);
on_a_vt = (ioctl(STDOUT_FILENO, VT_GETSTATE, &dummy) == 0);
#endif
/* Back up the terminal settings so that they can be restored. */
tcgetattr(0, &original_state);
tcgetattr(STDIN_FILENO, &original_state);
/* Get the state of standard input and ensure it uses blocking mode. */
stdin_flags = fcntl(0, F_GETFL, 0);
stdin_flags = fcntl(STDIN_FILENO, F_GETFL, 0);
if (stdin_flags != -1)
fcntl(0, F_SETFL, stdin_flags & ~O_NONBLOCK);
fcntl(STDIN_FILENO, F_SETFL, stdin_flags & ~O_NONBLOCK);
#ifdef ENABLE_UTF8
/* If setting the locale is successful and it uses UTF-8, we need
@@ -1849,7 +1848,7 @@ int main(int argc, char **argv)
SET(RESTRICTED);
while ((optchr = getopt_long(argc, argv, "ABC:DEFGHIJ:KLMNOPQ:RST:UVWX:Y:Z"
"abcdef:ghijklmno:pqr:s:tuvwxyz$?%!", long_options, NULL)) != -1) {
"abcdef:ghijklmno:pqr:s:tuvwxyz$%!", long_options, NULL)) != -1) {
switch (optchr) {
#ifndef NANO_TINY
case 'A':
@@ -2002,7 +2001,6 @@ int main(int argc, char **argv)
break;
#endif
case 'h':
case '?':
usage();
exit(0);
#ifndef NANO_TINY
@@ -2520,6 +2518,9 @@ int main(int argc, char **argv)
if (ISSET(VIEW_MODE))
SET(MULTIBUFFER);
}
#else
if (optind < argc)
die(_("Can open just one file\n"));
#endif
prepare_for_display();

View File

@@ -2,7 +2,7 @@
* prompt.c -- This file is part of GNU nano. *
* *
* Copyright (C) 1999-2011, 2013-2020 Free Software Foundation, Inc. *
* Copyright (C) 2016, 2018 Benno Schulenberg *
* Copyright (C) 2016, 2018, 2020 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -57,9 +57,18 @@ void do_statusbar_next_word(void)
* and if we've already seen a word, then it's a word end. */
if (is_word_char(answer + typing_x, FALSE))
seen_word = TRUE;
#ifdef ENABLE_UTF8
else if (is_zerowidth(answer + typing_x))
; /* skip */
#endif
else if (seen_word)
break;
} else {
#ifdef ENABLE_UTF8
if (is_zerowidth(answer + typing_x))
; /* skip */
else
#endif
/* If this is not a word character, then it's a separator; else
* if we've already seen a separator, then it's a word start. */
if (!is_word_char(answer + typing_x, FALSE))
@@ -81,6 +90,10 @@ void do_statusbar_prev_word(void)
if (is_word_char(answer + typing_x, FALSE))
seen_a_word = TRUE;
#ifdef ENABLE_UTF8
else if (is_zerowidth(answer + typing_x))
; /* skip */
#endif
else if (seen_a_word) {
/* This is space now: we've overshot the start of the word. */
step_forward = TRUE;
@@ -97,15 +110,25 @@ void do_statusbar_prev_word(void)
/* Move left one character in the answer. */
void do_statusbar_left(void)
{
if (typing_x > 0)
if (typing_x > 0) {
typing_x = step_left(answer, typing_x);
#ifdef ENABLE_UTF8
while (typing_x > 0 && is_zerowidth(answer + typing_x))
typing_x = step_left(answer, typing_x);
#endif
}
}
/* Move right one character in the answer. */
void do_statusbar_right(void)
{
if (answer[typing_x] != '\0')
if (answer[typing_x] != '\0') {
typing_x = step_right(answer, typing_x);
#ifdef ENABLE_UTF8
while (answer[typing_x] != '\0' && is_zerowidth(answer + typing_x))
typing_x = step_right(answer, typing_x);
#endif
}
}
/* Delete one character in the answer. */
@@ -116,6 +139,10 @@ void do_statusbar_delete(void)
memmove(answer + typing_x, answer + typing_x + charlen,
strlen(answer) - typing_x - charlen + 1);
#ifdef ENABLE_UTF8
if (is_zerowidth(answer + typing_x))
do_statusbar_delete();
#endif
}
}
@@ -123,8 +150,10 @@ void do_statusbar_delete(void)
void do_statusbar_backspace(void)
{
if (typing_x > 0) {
size_t was_x = typing_x;
typing_x = step_left(answer, typing_x);
do_statusbar_delete();
memmove(answer + typing_x, answer + was_x, strlen(answer) - was_x + 1);
}
}
@@ -378,10 +407,6 @@ void draw_the_promptbar(void)
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
/* Work around a cursor-misplacement bug in VTEs. */
wmove(bottomwin, 0, 0);
wrefresh(bottomwin);
/* Place the cursor at the right spot. */
column = base + wideness(answer, typing_x);
wmove(bottomwin, 0, column - get_statusbar_page_start(base, column));

View File

@@ -204,6 +204,7 @@ bool is_word_char(const char *c, bool allow_punct);
char control_mbrep(const char *c, bool isdata);
#ifdef ENABLE_UTF8
int mbwidth(const char *c);
bool is_zerowidth(const char *ch);
char *make_mbchar(long code, int *length);
#endif
int char_length(const char *pointer);

View File

@@ -95,7 +95,6 @@ static const rcoption rcopts[] = {
{"suspend", SUSPENDABLE}, /* Deprecated; remove in 2022. */
{"suspendable", SUSPENDABLE},
{"tempfile", SAVE_ON_EXIT}, /* Deprecated; remove in 2022. */
{"view", VIEW_MODE},
#ifndef NANO_TINY
{"afterends", AFTER_ENDS},
{"allow_insecure_backup", INSECURE_BACKUP},
@@ -1201,14 +1200,11 @@ colortype *parse_interface_color(char *combostr)
{
colortype *trio = nmalloc(sizeof(colortype));
if (parse_combination(combostr, &trio->fg, &trio->bg, &trio->attributes)) {
free(combostr);
return trio;
} else {
free(combostr);
if (!parse_combination(combostr, &trio->fg, &trio->bg, &trio->attributes)) {
free(trio);
return NULL;
}
} else
return trio;
}
/* Read regex strings enclosed in double quotes from the line pointed at
@@ -1547,8 +1543,6 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
continue;
}
#endif
argument = copy_of(argument);
#ifdef ENABLE_COLOR
if (strcmp(option, "titlecolor") == 0)
color_combo[TITLE_BAR] = parse_interface_color(argument);
@@ -1572,7 +1566,7 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
#endif
#ifdef ENABLE_OPERATINGDIR
if (strcmp(option, "operatingdir") == 0)
operating_dir = argument;
operating_dir = copy_of(argument);
else
#endif
#ifdef ENABLED_WRAPORJUSTIFY
@@ -1581,25 +1575,21 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
jot_error(N_("Requested fill size \"%s\" is invalid"), argument);
fill = -COLUMNS_FROM_EOL;
}
free(argument);
} else
#endif
#ifndef NANO_TINY
if (strcmp(option, "matchbrackets") == 0) {
if (has_blank_char(argument)) {
if (has_blank_char(argument))
jot_error(N_("Non-blank characters required"));
free(argument);
} else if (mbstrlen(argument) % 2 != 0) {
else if (mbstrlen(argument) % 2 != 0)
jot_error(N_("Even number of characters required"));
free(argument);
} else
matchbrackets = argument;
else
matchbrackets = copy_of(argument);
} else if (strcmp(option, "whitespace") == 0) {
if (mbstrlen(argument) != 2 || breadth(argument) != 2) {
if (mbstrlen(argument) != 2 || breadth(argument) != 2)
jot_error(N_("Two single-column characters required"));
free(argument);
} else {
whitespace = argument;
else {
whitespace = copy_of(argument);
whitelen[0] = char_length(whitespace);
whitelen[1] = char_length(whitespace + whitelen[0]);
}
@@ -1607,43 +1597,39 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
#endif
#ifdef ENABLE_JUSTIFY
if (strcmp(option, "punct") == 0) {
if (has_blank_char(argument)) {
if (has_blank_char(argument))
jot_error(N_("Non-blank characters required"));
free(argument);
} else
punct = argument;
else
punct = copy_of(argument);
} else if (strcmp(option, "brackets") == 0) {
if (has_blank_char(argument)) {
if (has_blank_char(argument))
jot_error(N_("Non-blank characters required"));
free(argument);
} else
brackets = argument;
else
brackets = copy_of(argument);
} else if (strcmp(option, "quotestr") == 0)
quotestr = argument;
quotestr = copy_of(argument);
else
#endif
#ifdef ENABLE_SPELLER
if (strcmp(option, "speller") == 0)
alt_speller = argument;
alt_speller = copy_of(argument);
else
#endif
#ifndef NANO_TINY
if (strcmp(option, "backupdir") == 0)
backup_dir = argument;
backup_dir = copy_of(argument);
else if (strcmp(option, "wordchars") == 0)
word_chars = argument;
word_chars = copy_of(argument);
else if (strcmp(option, "guidestripe") == 0) {
if (!parse_num(argument, &stripe_column) || stripe_column <= 0) {
jot_error(N_("Guide column \"%s\" is invalid"), argument);
stripe_column = 0;
}
free(argument);
} else if (strcmp(option, "tabsize") == 0) {
if (!parse_num(argument, &tabsize) || tabsize <= 0) {
jot_error(N_("Requested tab size \"%s\" is invalid"), argument);
tabsize = -1;
}
free(argument);
}
#else
; /* Properly terminate any earlier 'else'. */

View File

@@ -2,7 +2,7 @@
* search.c -- This file is part of GNU nano. *
* *
* Copyright (C) 1999-2011, 2013-2020 Free Software Foundation, Inc. *
* Copyright (C) 2015-2019 Benno Schulenberg *
* Copyright (C) 2015-2020 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *

View File

@@ -2340,11 +2340,11 @@ void do_int_speller(const char *tempfile_name)
exit(6);
/* Connect standard input to the temporary file. */
if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO)
if (dup2(tempfile_fd, STDIN_FILENO) < 0)
exit(7);
/* Connect standard output to the write end of the first pipe. */
if (dup2(spell_fd[1], STDOUT_FILENO) != STDOUT_FILENO)
if (dup2(spell_fd[1], STDOUT_FILENO) < 0)
exit(8);
close(tempfile_fd);
@@ -2365,11 +2365,11 @@ void do_int_speller(const char *tempfile_name)
/* Fork a process to run sort in. */
if ((pid_sort = fork()) == 0) {
/* Connect standard input to the read end of the first pipe. */
if (dup2(spell_fd[0], STDIN_FILENO) != STDIN_FILENO)
if (dup2(spell_fd[0], STDIN_FILENO) < 0)
exit(7);
/* Connect standard output to the write end of the second pipe. */
if (dup2(sort_fd[1], STDOUT_FILENO) != STDOUT_FILENO)
if (dup2(sort_fd[1], STDOUT_FILENO) < 0)
exit(8);
close(spell_fd[0]);
@@ -2387,10 +2387,10 @@ void do_int_speller(const char *tempfile_name)
/* Fork a process to run uniq in. */
if ((pid_uniq = fork()) == 0) {
if (dup2(sort_fd[0], STDIN_FILENO) != STDIN_FILENO)
if (dup2(sort_fd[0], STDIN_FILENO) < 0)
exit(7);
if (dup2(uniq_fd[1], STDOUT_FILENO) != STDOUT_FILENO)
if (dup2(uniq_fd[1], STDOUT_FILENO) < 0)
exit(8);
close(sort_fd[0]);
@@ -2607,9 +2607,9 @@ void do_linter(void)
/* Fork a process to run the linter in. */
if ((pid_lint = fork()) == 0) {
/* Redirect standard output and standard error into the pipe. */
if (dup2(lint_fd[1], STDOUT_FILENO) != STDOUT_FILENO)
if (dup2(lint_fd[1], STDOUT_FILENO) < 0)
exit(7);
if (dup2(lint_fd[1], STDERR_FILENO) != STDERR_FILENO)
if (dup2(lint_fd[1], STDERR_FILENO) < 0)
exit(8);
close(lint_fd[0]);
@@ -2823,7 +2823,10 @@ void do_linter(void)
}
if (tmplint != curlint) {
/* Put the cursor at the reported position, but don't go beyond EOL
* when the second number is a column number instead of an index. */
goto_line_posx(curlint->lineno, curlint->colno - 1);
openfile->current_x = actual_x(openfile->current->data, openfile->placewewant);
titlebar(NULL);
adjust_viewport(CENTERING);
#ifdef ENABLE_LINENUMBERS
@@ -2984,9 +2987,12 @@ void do_wordlinechar_count(void)
openfile->current = was_current;
openfile->current_x = was_x;
/* Display the total word, line, and character counts on the status bar. */
statusline(HUSH, _("%sWords: %zu Lines: %zd Chars: %zu"), openfile->mark ?
_("In Selection: ") : "", words, lines, chars);
/* Report on the status bar the number of lines, words, and characters. */
statusline(HUSH, _("%s%zd %s, %zu %s, %zu %s"),
openfile->mark ? _("In Selection: ") : "",
lines, P_("line", "lines", lines),
words, P_("word", "words", words),
chars, P_("character", "characters", chars));
}
#endif /* !NANO_TINY */

View File

@@ -108,19 +108,19 @@ int digits(ssize_t n)
}
#endif
/* Read an integer from str. If it parses okay, store it in *result
* and return TRUE; otherwise, return FALSE. */
bool parse_num(const char *str, ssize_t *result)
/* Read an integer from the given string. If it parses okay,
* store it in *result and return TRUE; otherwise, return FALSE. */
bool parse_num(const char *string, ssize_t *result)
{
char *first_error;
ssize_t value;
char *excess;
/* The manual page for strtol() says this is required. */
/* Clear the error number so that we can check it afterward. */
errno = 0;
value = (ssize_t)strtol(str, &first_error, 10);
value = (ssize_t)strtol(string, &excess, 10);
if (errno == ERANGE || *str == '\0' || *first_error != '\0')
if (errno == ERANGE || *string == '\0' || *excess != '\0')
return FALSE;
*result = value;
@@ -294,7 +294,10 @@ void *nmalloc(size_t howmuch)
{
void *r = malloc(howmuch);
if (r == NULL && howmuch != 0)
if (howmuch == 0)
die("Allocating zero bytes. Please report a bug.\n");
if (r == NULL)
die(_("Nano is out of memory!\n"));
return r;
@@ -306,7 +309,10 @@ void *nrealloc(void *ptr, size_t howmuch)
{
void *r = realloc(ptr, howmuch);
if (r == NULL && howmuch != 0)
if (howmuch == 0)
die("Allocating zero bytes. Please report a bug.\n");
if (r == NULL)
die(_("Nano is out of memory!\n"));
return r;

View File

@@ -2,7 +2,7 @@
* winio.c -- This file is part of GNU nano. *
* *
* Copyright (C) 1999-2011, 2013-2020 Free Software Foundation, Inc. *
* Copyright (C) 2014-2019 Benno Schulenberg *
* Copyright (C) 2014-2020 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -37,6 +37,11 @@
#define BRANDING PACKAGE_STRING
#endif
/* When having an older ncurses, then most likely libvte is older too. */
#if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH < 20200212)
#define USING_OLDER_LIBVTE yes
#endif
static int *key_buffer = NULL;
/* A buffer for the keystrokes that haven't been handled yet. */
static size_t key_buffer_len = 0;
@@ -51,10 +56,6 @@ static bool linger_after_escape = FALSE;
/* Whether to give ncurses some time to get the next code. */
static int statusblank = 0;
/* The number of keystrokes left before we blank the status bar. */
#ifdef USING_OLD_NCURSES
static bool seen_wide = FALSE;
/* Whether we've seen a multicolumn character in the current line. */
#endif
static bool has_more = FALSE;
/* Whether the current line has more text after the displayed part. */
static bool is_shorter = TRUE;
@@ -840,7 +841,7 @@ int assemble_byte_code(int keycode)
}
/* The second digit may be at most 5 if the first was 2. */
if (digit_count == 2) {
if (digit_count == 2) {
if (byte < 200 || keycode <= '5') {
byte += (keycode - '0') * 10;
return PROCEED;
@@ -1720,9 +1721,6 @@ char *display_string(const char *buf, size_t column, size_t span,
size_t beyond = column + span;
/* The column number just beyond the last shown character. */
#ifdef USING_OLD_NCURSES
seen_wide = FALSE;
#endif
buf += start_index;
/* Allocate enough space for converting the relevant part of the line. */
@@ -1855,11 +1853,6 @@ char *display_string(const char *buf, size_t column, size_t span,
/* If the codepoint is unassigned, assume a width of one. */
column += (charwidth < 0 ? 1 : charwidth);
#ifdef USING_OLD_NCURSES
if (charwidth > 1)
seen_wide = TRUE;
#endif
#endif /* ENABLE_UTF8 */
}
@@ -2138,9 +2131,11 @@ void statusline(message_type importance, const char *msg, ...)
waddstr(bottomwin, " ]");
wattroff(bottomwin, colorpair);
#ifdef USING_OLDER_LIBVTE
/* Defeat a VTE/Konsole bug, where the cursor can go off-limits. */
if (ISSET(CONSTANT_SHOW) && ISSET(NO_HELP))
wmove(bottomwin, 0, 0);
#endif
/* Push the message to the screen straightaway. */
wrefresh(bottomwin);
@@ -2228,6 +2223,8 @@ void bottombars(int menu)
/* Display the first number of shortcuts in the given menu that
* have a key combination assigned to them. */
for (f = allfuncs, index = 0; f != NULL && index < number; f = f->next) {
size_t thiswidth = itemwidth;
if ((f->menus & menu) == 0)
continue;
@@ -2238,13 +2235,19 @@ void bottombars(int menu)
wmove(bottomwin, 1 + index % 2, (index / 2) * itemwidth);
post_one_key(s->keystr, _(f->desc), itemwidth +
((index < number - 2) ? 0 : COLS % itemwidth));
/* When the number is uneven, the penultimate item can be double wide. */
if ((number % 2) == 1 && (index + 2 == number))
thiswidth += itemwidth;
/* For the last two items, use also the remaining slack. */
if (index + 2 >= number)
thiswidth += COLS % itemwidth;
post_one_key(s->keystr, _(f->desc), thiswidth);
index++;
}
/* Defeat a VTE bug by homing the cursor and forcing a screen update. */
wmove(bottomwin, 0, 0);
wrefresh(bottomwin);
}
@@ -2342,13 +2345,6 @@ void draw_row(int row, const char *converted, linestruct *line, size_t from_col)
if (thebar)
mvwaddch(edit, row, COLS - 1, bardata[row]);
#endif
#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. */
if (seen_wide)
wredrawln(edit, row, 1);
#endif
#ifdef ENABLE_COLOR
/* If there are color rules (and coloring is turned on), apply them. */
@@ -2610,6 +2606,7 @@ void draw_row(int row, const char *converted, linestruct *line, size_t from_col)
if (*(converted + target_x) != '\0') {
charlen = collect_char(converted + target_x, striped_char);
target_column = wideness(converted, target_x);
#ifdef USING_OLDER_LIBVTE
} else if (target_column + 1 == editwincols) {
/* Defeat a VTE bug -- see https://sv.gnu.org/bugs/?55896. */
#ifdef ENABLE_UTF8
@@ -2620,6 +2617,7 @@ void draw_row(int row, const char *converted, linestruct *line, size_t from_col)
} else
#endif
striped_char[0] = '.';
#endif
} else
striped_char[0] = ' ';

View File

@@ -7,7 +7,7 @@ comment "#"
color brightred ".*"
# Keywords
color brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(afterends|allow_insecure_backup|atblanks|autoindent|backup|boldtext|breaklonglines|casesensitive|constantshow|cutfromcursor|emptyline|historylog|indicator|jumpyscrolling|linenumbers|locking|magic|mouse|multibuffer|noconvert|nohelp|nonewlines|positionlog|preserve|quickblank|rawsequences|rebinddelete|regexp|saveonexit|showcursor|smarthome|softwrap|stateflags|suspendable|tabstospaces|trimblanks|unix|view|wordbounds|zap)\>"
color brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(afterends|allow_insecure_backup|atblanks|autoindent|backup|boldtext|breaklonglines|casesensitive|constantshow|cutfromcursor|emptyline|historylog|indicator|jumpyscrolling|linenumbers|locking|magic|mouse|multibuffer|noconvert|nohelp|nonewlines|positionlog|preserve|quickblank|rawsequences|rebinddelete|regexp|saveonexit|showcursor|smarthome|softwrap|stateflags|suspendable|tabstospaces|trimblanks|unix|wordbounds|zap)\>"
color yellow "^[[:space:]]*set[[:space:]]+((error|function|key|number|scroller|selected|status|stripe|title)color)[[:space:]]+(bold,)?(italic,)?(bright|light)?(white|black|red|blue|green|yellow|magenta|cyan|normal|pink|purple|mauve|lagoon|mint|lime|peach|orange|latte)?(,(light)?(white|black|red|blue|green|yellow|magenta|cyan|normal|pink|purple|mauve|lagoon|mint|lime|peach|orange|latte))?\>"
color brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|errorcolor|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|scrollercolor|selectedcolor|speller|statuscolor|stripecolor|titlecolor|whitespace|wordchars)[[:space:]]+"
color brightgreen "^[[:space:]]*set[[:space:]]+(fill[[:space:]]+-?[[:digit:]]+|(guidestripe|tabsize)[[:space:]]+[1-9][0-9]*)\>"