Compare commits
96 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25ba7712f7 | ||
|
|
a6b534d760 | ||
|
|
494b191d55 | ||
|
|
450bfa7a75 | ||
|
|
a52ac1375a | ||
|
|
4990713e9e | ||
|
|
c022c4cc6d | ||
|
|
6257dec0a7 | ||
|
|
ea9d49b9d8 | ||
|
|
42c7bfcf8a | ||
|
|
e67d1bfeb8 | ||
|
|
e2f444cfdf | ||
|
|
03b85df4eb | ||
|
|
7db5c2f225 | ||
|
|
603ce231d0 | ||
|
|
940b5eaad1 | ||
|
|
fdd946c02c | ||
|
|
81e5b57d74 | ||
|
|
b568705eec | ||
|
|
fe42eb7a1a | ||
|
|
df7b0a6d97 | ||
|
|
fcf598e797 | ||
|
|
d9cb12f6e3 | ||
|
|
0f23729253 | ||
|
|
3def429290 | ||
|
|
803ea0d7a0 | ||
|
|
9b014876cd | ||
|
|
9ccf85eaa8 | ||
|
|
93fa53c3e8 | ||
|
|
eea3e1f0b2 | ||
|
|
e6e22ea976 | ||
|
|
80c2000f87 | ||
|
|
15a0a129c8 | ||
|
|
51bd04b541 | ||
|
|
18ba7f60c1 | ||
|
|
5c3e00d70a | ||
|
|
6c4c77971e | ||
|
|
67adef8f6c | ||
|
|
ed60e16974 | ||
|
|
47c11ae83d | ||
|
|
8173b1bfbe | ||
|
|
93400ec8a1 | ||
|
|
0d85a798e5 | ||
|
|
d4d534925f | ||
|
|
a1ba7ee786 | ||
|
|
756cd4a4b8 | ||
|
|
1b186fcff3 | ||
|
|
165da9b447 | ||
|
|
aea10ed383 | ||
|
|
8fccb31436 | ||
|
|
89bb88e4f5 | ||
|
|
a58efa70bc | ||
|
|
fe1fecc5da | ||
|
|
87612582ff | ||
|
|
c3a53cffbc | ||
|
|
aeea83703b | ||
|
|
27c8f13fc9 | ||
|
|
c6ddae70f7 | ||
|
|
e4ecd03e3f | ||
|
|
a6dc5c963c | ||
|
|
989e6a9a7e | ||
|
|
c28048d20f | ||
|
|
a24e72f972 | ||
|
|
a29aa31e93 | ||
|
|
8546139997 | ||
|
|
a61586947e | ||
|
|
5e4645b082 | ||
|
|
f9f0a8fd67 | ||
|
|
637a2eeb66 | ||
|
|
13caef2de0 | ||
|
|
61c6d43231 | ||
|
|
a04f6e0165 | ||
|
|
3f494e359d | ||
|
|
8a06f70379 | ||
|
|
2290152743 | ||
|
|
3b657a26a6 | ||
|
|
ff5084479b | ||
|
|
97f4a3f4eb | ||
|
|
1ca1732d32 | ||
|
|
accd2308f1 | ||
|
|
10eec2fe17 | ||
|
|
d69cd759cb | ||
|
|
f261a8aca5 | ||
|
|
bdf64d660b | ||
|
|
2fd30ee095 | ||
|
|
9bc6f1797e | ||
|
|
32e63fe1b8 | ||
|
|
1c074cc8cc | ||
|
|
ebf6228f21 | ||
|
|
4a1db96db8 | ||
|
|
16ee4636bc | ||
|
|
6831b37b43 | ||
|
|
4d16f26ba4 | ||
|
|
4a7bc73e03 | ||
|
|
caf583ec4b | ||
|
|
e20880da21 |
113
ChangeLog
113
ChangeLog
@@ -1,3 +1,116 @@
|
||||
Changes between v6.2 and v6.3:
|
||||
------------------------------
|
||||
|
||||
Benno Schulenberg (41):
|
||||
build: add the --disable-maintainer-mode option to ./configure
|
||||
build: fix compilation for --enable-{tiny,nanorc,color}
|
||||
build: fix compilation when configured with --disable-color
|
||||
build: remove an obsolete check -- the dependent code was deleted
|
||||
bump version numbers and add a news item for the 6.3 release
|
||||
display: suppress spotlight yellow and error red when NO_COLOR is set
|
||||
docs: add an example binding for copying text to the system clipboard
|
||||
execute: clear an anchor only when the whole buffer gets filtered
|
||||
execute: don't crash when an empty buffer is piped through a command
|
||||
execute: stay on the same line number when filtering the whole buffer
|
||||
feedback: show extra warning when writing failed due to "No space left"
|
||||
files: do not change to a higher directory when the working one is gone
|
||||
files: show a warning when the working directory is gone (when used)
|
||||
files: when the working directory exists, still check its accessibility
|
||||
filtering: close all output descriptors, so that 'xsel' will terminate
|
||||
formatting: change cursor position only after saving it in the undo item
|
||||
gnulib: pull in the workaround for a build problem on NetBSD
|
||||
gnulib: update to its current upstream state
|
||||
justify: stay at the same line number when doing a full justification
|
||||
painting: colorize text also after an unterminated start match
|
||||
painting: look for another start match only after the actual end match
|
||||
painting: recalculate the multidata when making large strides or changes
|
||||
painting: stop coloring an extremely long line after 2000 bytes
|
||||
painting: tighten the check for a lacking end match on a colored line
|
||||
syntax: xml: colorize /> properly, and colorize prolog tags differently
|
||||
syntax: xml: colorize user-defined entities differently
|
||||
tweaks: avoid a function call when two plain assignments will do
|
||||
tweaks: change the indentation of a list, to match other indentations
|
||||
tweaks: don't leave an orphaned temporary file behind when writing fails
|
||||
tweaks: elide an unneeded call of strlen()
|
||||
tweaks: exclude the extra truncation warning from the tiny version
|
||||
tweaks: make the triggering of the recalculation of multidata less eager
|
||||
tweaks: move the saving and restoring of flags to where it is needed
|
||||
tweaks: normalize the indentation after the previous change
|
||||
tweaks: prevent the adding of an unwanted newline in a different way
|
||||
tweaks: remove redundant braces, and add two translator hints
|
||||
tweaks: remove some stray spaces before a comma
|
||||
tweaks: simplify a bit of code, eliding two labels and three gotos
|
||||
tweaks: simplify a fragment of code, and fold two lines together
|
||||
tweaks: trim a few comments, rename a function, and reshuffle some code
|
||||
verbatim: with --zero, keep cursor in viewport when it was on bottom row
|
||||
|
||||
Mike Frysinger (1):
|
||||
general: fix building for Windows
|
||||
|
||||
|
||||
Changes between v6.1 and v6.2:
|
||||
------------------------------
|
||||
|
||||
Benno Schulenberg (14):
|
||||
bump version numbers and add a news item for the 6.2 release
|
||||
display: suppress the bottom-bar wiping only when the user is editing
|
||||
linter: adjust the parsing to accommodate for a modern 'pyflakes'
|
||||
syntaxes: fold a couple of regexes together, and improve a few comments
|
||||
tweaks: change the type of a variable, to avoid a compiler warning
|
||||
tweaks: consistently backslash-escape the dash in M-letter keystrokes
|
||||
tweaks: rename a misnamed variable
|
||||
tweaks: rename a variable, reshuffle five lines, and snip two comments
|
||||
tweaks: rename a variable, to be more correct, and adjust two comments
|
||||
tweaks: rename a variable, to be more fitting
|
||||
tweaks: rename two more variables, and drop unneeded initializations
|
||||
tweaks: rename two variables (to get rid of a prefix), and elide a third
|
||||
tweaks: store a result, to avoid calling a function twice
|
||||
tweaks: use an intermediate variable, to avoid using one for two purposes
|
||||
|
||||
|
||||
Changes between v6.0 and v6.1:
|
||||
------------------------------
|
||||
|
||||
Benno Schulenberg (37):
|
||||
build: fix compilation when configured with --enable-tiny
|
||||
build: prevent autopoint from overwriting a newer M4 file from gnulib
|
||||
bump version numbers and add a news item for the 6.1 release
|
||||
copyright: update the last year for significantly changed files
|
||||
copyright: update the years for the FSF
|
||||
docs: mention bindable function 'zero', for toggling the interface bars
|
||||
docs: mention 'set guidestripe' and 'set unix' in the sample nanorc
|
||||
docs: remove obsolete Ctrl+Z from the cheatsheet; mention Alt+X instead
|
||||
files: let ^C cancel the exiting when the file on disk was changed
|
||||
gnulib: update to its current upstream state
|
||||
help: make the description of <Tab> more accurate
|
||||
help: update the description of M-D, to match the actual order of counts
|
||||
input: instead of moving waiting keycodes, just increment a pointer
|
||||
input: suppress any spotlighting when there are more keycodes waiting
|
||||
menus: don't show M-6 in the help lines of any prompt
|
||||
prompt: allow the user to copy the answer to the cutbuffer (with M-6)
|
||||
prompt: let ^K erase text after cursor (if any), otherwise whole answer
|
||||
tweaks: add some feedback to the autogen.sh script, to ease the wait
|
||||
tweaks: add some small, clarifying comments
|
||||
tweaks: adjust a translator hint, to fit the order in the POT file
|
||||
tweaks: drop foreign M-U and M-R from among the sample CUA bindings
|
||||
tweaks: remove a redundant check -- add a different one for symmetry
|
||||
tweaks: remove two redundant checks
|
||||
tweaks: rename a function and its two parameters, for clarity
|
||||
tweaks: rename a function and reshuffle its call
|
||||
tweaks: rename a function, to not contain the name of a variable
|
||||
tweaks: rename another variable, to better fit in with its sisters
|
||||
tweaks: rename a variable and a parameter, to be more descriptive
|
||||
tweaks: rename a variable, away from an abbreviation
|
||||
tweaks: rename a variable, for clarity and contrast
|
||||
tweaks: rename a variable, to make it clearer it refers to a window
|
||||
tweaks: rename two variables, and elide a near-enough duplicate
|
||||
tweaks: reshuffle some sample bindings, to group them differently
|
||||
tweaks: reword two comments, and rename a variable (away from an abbrev)
|
||||
tweaks: stop asking the terminal for its new size -- let ncurses do it
|
||||
tweaks: use some symbolic names instead of unclear numeric values
|
||||
tweaks: when discarding keycodes, don't bother parsing them
|
||||
|
||||
|
||||
Changes between v5.9 and v6.0:
|
||||
------------------------------
|
||||
|
||||
|
||||
25
NEWS
25
NEWS
@@ -1,3 +1,28 @@
|
||||
2022.04.28 - GNU nano 6.3 "Wat zullen we drinken? Wat een dorst!"
|
||||
• For multiline regexes, text is now colored as soon a start match
|
||||
is found, also when there is no end match at all.
|
||||
• The colorizing of any line is stopped after two thousand bytes,
|
||||
to avoid frustrating delays.
|
||||
• When environment variable NO_COLOR is set, the two default colors
|
||||
(yellow for the spotlight, red for error messages) are suppressed
|
||||
when no interface colors are specified in a nanorc file.
|
||||
• Full justification and piping the whole buffer through a command
|
||||
now keep the cursor at the same line number.
|
||||
• Utility 'xsel' can be used to copy a marked region to the system's
|
||||
clipboard. See doc/sample.nanorc for an example.
|
||||
|
||||
2022.02.18 - GNU nano 6.2 "Kamperfoelie"
|
||||
• The file browser clears the prompt bar also when using --minibar.
|
||||
• Linting now works also with a newer 'pyflakes'.
|
||||
|
||||
2022.02.09 - GNU nano 6.1 "Rețelele de socializare sunt ca un frigider"
|
||||
• The behavior of ^K at a prompt has been enhanced: when there is some
|
||||
text after the cursor, just this text is erased. In the most common
|
||||
situation, when the cursor is at the end of the answer, the behavior
|
||||
is as before: the whole answer is erased.
|
||||
• At a prompt, M-6 copies the current answer into the cutbuffer.
|
||||
• Large external pastes into nano are handled more quickly.
|
||||
|
||||
2021.12.15 - GNU nano 6.0 "Humor heeft ook zijn leuke kanten"
|
||||
• Option --zero hides the title bar, status bar and help lines, and
|
||||
uses all rows of the terminal as editing area. The title bar and
|
||||
|
||||
2
README
2
README
@@ -15,7 +15,7 @@ Appearance
|
||||
In rough ASCII graphics, this is what nano's screen looks like:
|
||||
|
||||
____________________________________________________________________
|
||||
| GNU nano 6.0 filename Modified |
|
||||
| GNU nano 6.3 filename Modified |
|
||||
--------------------------------------------------------------------
|
||||
| This is the text window, displaying the contents of a 'buffer', |
|
||||
| the contents of the file you are editing. |
|
||||
|
||||
30
README.GIT
30
README.GIT
@@ -8,19 +8,18 @@ building this needs a bit more care than the official tarballs.
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
To successfully compile GNU nano from git, you'll need the following
|
||||
packages:
|
||||
To successfully compile GNU nano from git, you'll need the following:
|
||||
|
||||
- autoconf (version >= 2.69)
|
||||
- automake (version >= 1.14)
|
||||
- autopoint (version >= 0.18.3)
|
||||
- gcc (version >= 5.0)
|
||||
- gettext (version >= 0.18.3)
|
||||
- git (version >= 2.7.4)
|
||||
- groff (version >= 1.12)
|
||||
- make (any version)
|
||||
- pkg-config (version >= 0.22)
|
||||
- texinfo (version >= 4.0)
|
||||
autoconf (version >= 2.69)
|
||||
automake (version >= 1.14)
|
||||
autopoint (version >= 0.18.3)
|
||||
gcc (version >= 5.0)
|
||||
gettext (version >= 0.18.3)
|
||||
git (version >= 2.7.4)
|
||||
groff (version >= 1.12)
|
||||
make (any version)
|
||||
pkg-config (version >= 0.22)
|
||||
texinfo (version >= 4.0)
|
||||
|
||||
You will also need to have the header files for ncurses installed,
|
||||
from libncurses-dev on Debian, ncurses-devel on Fedora, or similar.
|
||||
@@ -29,14 +28,14 @@ These should all be available in your distro's package manager or
|
||||
software center, or otherwise on any GNU mirror.
|
||||
|
||||
|
||||
Download the source
|
||||
-------------------
|
||||
Clone the source
|
||||
----------------
|
||||
|
||||
To obtain the current nano development branch (called 'master'), use the
|
||||
following command. It will create in your current working directory a
|
||||
subdirectory called 'nano' containing a copy of all of the files:
|
||||
|
||||
$ git clone git://git.savannah.gnu.org/nano.git nano
|
||||
$ git clone git://git.savannah.gnu.org/nano.git
|
||||
|
||||
|
||||
Generate the configure script
|
||||
@@ -84,6 +83,7 @@ Problems?
|
||||
Please submit any bugs you find in the code in git via the bug tracker
|
||||
on Savannah (https://savannah.gnu.org/bugs/?group=nano).
|
||||
|
||||
|
||||
Contributing something
|
||||
----------------------
|
||||
|
||||
|
||||
26
autogen.sh
26
autogen.sh
@@ -2,7 +2,7 @@
|
||||
# Generate configure & friends for GIT users.
|
||||
|
||||
gnulib_url="git://git.sv.gnu.org/gnulib.git"
|
||||
gnulib_hash="135414a7f543e4d40ad0a7cbd51885e159a6e0f4"
|
||||
gnulib_hash="34a93be8aa8a15f5959a1b671ad1285a5d552f4b"
|
||||
|
||||
modules="
|
||||
futimens
|
||||
@@ -36,14 +36,26 @@ fi
|
||||
cd gnulib >/dev/null || exit 1
|
||||
curr_hash=$(git log -1 --format=%H)
|
||||
if [ "${gnulib_hash}" != "${curr_hash}" ]; then
|
||||
echo "Pulling..."
|
||||
git pull
|
||||
git checkout -f ${gnulib_hash}
|
||||
git checkout --force ${gnulib_hash}
|
||||
fi
|
||||
cd .. >/dev/null || exit 1
|
||||
|
||||
rm -rf lib
|
||||
./gnulib/gnulib-tool \
|
||||
--import \
|
||||
${modules}
|
||||
echo "Autopoint..."
|
||||
autopoint --force
|
||||
|
||||
autoreconf -f -i -s
|
||||
rm -rf lib
|
||||
echo "Gnulib-tool..."
|
||||
./gnulib/gnulib-tool --import ${modules}
|
||||
echo
|
||||
|
||||
echo "Aclocal..."
|
||||
aclocal -I m4
|
||||
echo "Autoconf..."
|
||||
autoconf
|
||||
echo "Autoheader..."
|
||||
autoheader
|
||||
echo "Automake..."
|
||||
automake --add-missing
|
||||
echo "Done."
|
||||
|
||||
23
configure.ac
23
configure.ac
@@ -1,6 +1,6 @@
|
||||
# Configuration for GNU nano - a small and user-friendly text editor
|
||||
#
|
||||
# Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2014, 2017 Mike Frysinger
|
||||
#
|
||||
# GNU nano is free software: you can redistribute it and/or modify
|
||||
@@ -16,10 +16,11 @@
|
||||
# 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], [6.0], [nano-devel@gnu.org], [nano])
|
||||
AC_INIT([GNU nano], [6.3], [nano-devel@gnu.org], [nano])
|
||||
AC_CONFIG_SRCDIR([src/nano.c])
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE([1.14])
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
dnl Make sure the ONCE macros are available.
|
||||
@@ -353,6 +354,9 @@ if test "x$enable_utf8" != xno; then
|
||||
AC_CHECK_FUNCS(iswalpha iswalnum iswpunct mbstowcs wctomb)
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS_ONCE(chmod chown fchmod fchown flockfile funlockfile
|
||||
fork fsync geteuid pipe wait waitpid)
|
||||
|
||||
dnl Checks for available flags.
|
||||
|
||||
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"], [], [])
|
||||
@@ -510,21 +514,6 @@ int main(void)
|
||||
*** Can't check need for _XOPEN_SOURCE_EXTENDED when cross-compiling.]))
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether LINES and COLS can be redefined])
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <curses.h>
|
||||
int main(void)
|
||||
{
|
||||
LINES = 80;
|
||||
COLS = 25;
|
||||
return 0;
|
||||
}]])],
|
||||
AC_DEFINE(REDEFINING_MACROS_OK, 1, [Define this if you know your curses library allows LINES and COLS to be redefined to deal with a resizing bug.])
|
||||
AC_MSG_RESULT(yes),
|
||||
AC_MSG_RESULT(no),
|
||||
AC_MSG_WARN([
|
||||
*** Can't check for macro redefinability when cross-compiling.]))
|
||||
|
||||
AS_IF([test "x$enable_libmagic" != "xno"], [
|
||||
AC_CHECK_HEADERS([magic.h])
|
||||
AC_CHECK_LIB(magic, magic_open)
|
||||
|
||||
@@ -118,11 +118,11 @@
|
||||
<tr><td>Alt+A</td><td>Turn the mark on/off</td></tr>
|
||||
<tr><td>Tab</td><td>Indent marked region</td></tr>
|
||||
<tr><td>Shift+Tab </td><td>Unindent marked region</td></tr>
|
||||
<tr><td>Alt+V</td><td>Enter next keystroke verbatim</td></tr>
|
||||
<tr><td>Alt+N</td><td>Turn line numbers on/off</td></tr>
|
||||
<tr><td>Alt+P</td><td>Turn visible whitespace on/off</td></tr>
|
||||
<tr><td>Alt+V</td><td>Enter next keystroke verbatim</td></tr>
|
||||
<tr><td>Alt+X</td><td>Hide or unhide the help lines</td></tr>
|
||||
<tr><td>Ctrl+L</td><td>Refresh the screen</td></tr>
|
||||
<tr><td>Ctrl+Z</td><td>Suspend nano</td></tr>
|
||||
</tbody></table>
|
||||
<br>
|
||||
|
||||
|
||||
@@ -92,7 +92,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 "establishes a full duplex terminal connection to a remote host", 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>6.0</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>6.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>
|
||||
<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%">
|
||||
|
||||
10
doc/nano.1
10
doc/nano.1
@@ -1,4 +1,4 @@
|
||||
.\" Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.
|
||||
.\" Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc.
|
||||
.\"
|
||||
.\" This document is dual-licensed. You may distribute and/or modify it
|
||||
.\" under the terms of either of the following licenses:
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <https://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANO 1 "version 6.0" "December 2021"
|
||||
.TH NANO 1 "version 6.3" "April 2022"
|
||||
|
||||
.SH NAME
|
||||
nano \- Nano's ANOther editor, inspired by Pico
|
||||
@@ -359,7 +359,7 @@ the number of lines in the buffer is displayed after the filename.
|
||||
This number is cleared upon the next keystroke, or replaced with an
|
||||
[i/n] counter when multiple buffers are open.
|
||||
The line plus column numbers and the character code are displayed only when
|
||||
\fB\-\-constantshow\fR is used, and can be toggled on and off with \fBM-C\fR.
|
||||
\fB\-\-constantshow\fR is used, and can be toggled on and off with \fBM\-C\fR.
|
||||
The state flags are displayed only when \fB\-\-stateflags\fR is used.
|
||||
.TP
|
||||
.BR \-0 ", " \-\-zero
|
||||
@@ -367,8 +367,8 @@ Hide all elements of the interface (title bar, status bar, and help lines)
|
||||
and use all rows of the terminal for showing the contents of the buffer.
|
||||
The status bar appears only when there is a significant message,
|
||||
and disappears after 1.5 seconds or upon the next keystroke.
|
||||
With \fBM-Z\fR the title bar plus status bar can be toggled.
|
||||
With \fBM-X\fR the help lines.
|
||||
With \fBM\-Z\fR the title bar plus status bar can be toggled.
|
||||
With \fBM\-X\fR the help lines.
|
||||
.TP
|
||||
.BR \-! ", " \-\-magic
|
||||
When neither the file's name nor its first line give a clue,
|
||||
|
||||
@@ -13,8 +13,8 @@ The complete manual for the GNU nano text editor.
|
||||
|
||||
@smallbook
|
||||
@set EDITION 0.6
|
||||
@set VERSION 6.0
|
||||
@set UPDATED December 2021
|
||||
@set VERSION 6.3
|
||||
@set UPDATED April 2022
|
||||
|
||||
@dircategory Editors
|
||||
@direntry
|
||||
@@ -29,7 +29,7 @@ The complete manual for the GNU nano text editor.
|
||||
|
||||
@title GNU @command{nano}
|
||||
@subtitle a small and friendly text editor
|
||||
@subtitle version 6.0
|
||||
@subtitle version 6.3
|
||||
|
||||
@author Chris Allegretta
|
||||
|
||||
@@ -40,7 +40,7 @@ This manual documents the GNU @command{nano} editor.
|
||||
The contents of this manual are part of the GNU @command{nano} distribution.
|
||||
|
||||
@sp 5
|
||||
Copyright @copyright{} 1999-2009, 2014-2021 Free Software Foundation, Inc.
|
||||
Copyright @copyright{} 1999-2009, 2014-2022 Free Software Foundation, Inc.
|
||||
@sp 1
|
||||
This document is dual-licensed. You may distribute and/or modify it
|
||||
under the terms of either of the following licenses:
|
||||
@@ -76,7 +76,7 @@ For suggesting improvements: @email{nano-devel@@gnu.org}
|
||||
@node Top
|
||||
@top
|
||||
|
||||
This manual documents GNU @command{nano}, version 6.0.
|
||||
This manual documents GNU @command{nano}, version 6.3.
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
@@ -1715,6 +1715,9 @@ Toggles the presence of the two-line list of key bindings at the bottom of the s
|
||||
(This toggle is special: it is available in all menus except the help viewer
|
||||
and the linter. All further toggles are available in the main menu only.)
|
||||
|
||||
@item zero
|
||||
Toggles the presence of title bar and status bar.
|
||||
|
||||
@item constantshow
|
||||
Toggles the constant display of the current line, column, and character positions.
|
||||
|
||||
|
||||
15
doc/nanorc.5
15
doc/nanorc.5
@@ -1,4 +1,4 @@
|
||||
.\" Copyright (C) 2003-2011, 2013-2021 Free Software Foundation, Inc.
|
||||
.\" Copyright (C) 2003-2011, 2013-2022 Free Software Foundation, Inc.
|
||||
.\"
|
||||
.\" This document is dual-licensed. You may distribute and/or modify it
|
||||
.\" under the terms of either of the following licenses:
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <https://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANORC 5 "version 6.0" "December 2021"
|
||||
.TH NANORC 5 "version 6.3" "April 2022"
|
||||
|
||||
.SH NAME
|
||||
nanorc \- GNU nano's configuration file
|
||||
@@ -196,7 +196,7 @@ the number of lines in the buffer is displayed after the filename.
|
||||
This number is cleared upon the next keystroke, or replaced with an
|
||||
[i/n] counter when multiple buffers are open.
|
||||
The line plus column numbers and the character code are displayed only when
|
||||
\fBset constantshow\fR is used, and can be toggled on and off with \fBM-C\fR.
|
||||
\fBset constantshow\fR is used, and can be toggled on and off with \fBM\-C\fR.
|
||||
The state flags are displayed only when \fBset stateflags\fR is used.
|
||||
.TP
|
||||
.B set minicolor \fR[\fBbold,\fR][\fBitalic,\fR]\fIfgcolor\fB,\fIbgcolor\fR
|
||||
@@ -415,8 +415,8 @@ Hide all elements of the interface (title bar, status bar, and help lines)
|
||||
and use all rows of the terminal for showing the contents of the buffer.
|
||||
The status bar appears only when there is a significant message,
|
||||
and disappears after 1.5 seconds or upon the next keystroke.
|
||||
With \fBM-Z\fR the title bar plus status bar can be toggled.
|
||||
With \fBM-X\fR the help lines.
|
||||
With \fBM\-Z\fR the title bar plus status bar can be toggled.
|
||||
With \fBM\-X\fR the help lines.
|
||||
|
||||
.SH SYNTAX HIGHLIGHTING
|
||||
Coloring the different syntactic elements of a file
|
||||
@@ -695,7 +695,7 @@ and characters in the current buffer (or in the marked region).
|
||||
.TP
|
||||
.B execute
|
||||
Prompts for a program to execute. The program's output will be inserted
|
||||
into the current buffer (or into a new buffer when \fBM-F\fR is toggled).
|
||||
into the current buffer (or into a new buffer when \fBM\-F\fR is toggled).
|
||||
.TP
|
||||
.B speller
|
||||
Invokes a spell-checking program, either the default \fBhunspell\fR(1) or GNU
|
||||
@@ -931,6 +931,9 @@ Toggles the presence of the two-line list of key bindings at the bottom of the s
|
||||
(This toggle is special: it is available in all menus except the help viewer
|
||||
and the linter. All further toggles are available in the main menu only.)
|
||||
.TP
|
||||
.B zero
|
||||
Toggles the presence of title bar and status bar.
|
||||
.TP
|
||||
.B constantshow
|
||||
Toggles the constant display of the current line, column, and character positions.
|
||||
.TP
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.\" Copyright (C) 2002-2007, 2014-2021 Free Software Foundation, Inc.
|
||||
.\" Copyright (C) 2002-2007, 2014-2022 Free Software Foundation, Inc.
|
||||
.\"
|
||||
.\" This document is dual-licensed. You may distribute and/or modify it
|
||||
.\" under the terms of either of the following licenses:
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <https://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 6.0" "December 2021"
|
||||
.TH RNANO 1 "version 6.3" "April 2022"
|
||||
|
||||
.SH NAME
|
||||
rnano \- a restricted nano
|
||||
|
||||
@@ -58,6 +58,10 @@
|
||||
## will be the terminal's width minus this number.
|
||||
# set fill -8
|
||||
|
||||
## Draw a vertical stripe at the given column, to help judge text width.
|
||||
## (This option does not have a default value.)
|
||||
# set guidestripe 75
|
||||
|
||||
## Remember the used search/replace strings for the next session.
|
||||
# set historylog
|
||||
|
||||
@@ -176,6 +180,9 @@
|
||||
## Snip whitespace at the end of lines when justifying or hard-wrapping.
|
||||
# set trimblanks
|
||||
|
||||
## Save files by default in Unix format (also when they were DOS or Mac).
|
||||
# set unix
|
||||
|
||||
## 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.
|
||||
@@ -284,13 +291,20 @@
|
||||
# bind Sh-M-U "Oc[1;6D|sed 's/.*/\U&/'
|
||||
" main
|
||||
# bind Sh-M-L "Oc[1;6D|sed 's/.*/\L&/'
|
||||
" main
|
||||
|
||||
## For copying a marked region to the system clipboard:
|
||||
# bind Sh-M-T "|xsel -ib
|
||||
u" main
|
||||
|
||||
## If you would like nano to have keybindings that are more "usual",
|
||||
## such as ^O for Open, ^F for Find, ^H for Help, and ^Q for Quit,
|
||||
## then uncomment these:
|
||||
#bind ^X cut main
|
||||
#bind ^C copy main
|
||||
#bind ^V paste all
|
||||
#bind ^Q exit all
|
||||
#bind ^S savefile main
|
||||
#bind ^W writeout main
|
||||
#bind ^O insert main
|
||||
#set multibuffer
|
||||
@@ -298,24 +312,18 @@
|
||||
#bind ^H exit help
|
||||
#bind ^F whereis all
|
||||
#bind ^G findnext all
|
||||
#bind ^D findprevious all
|
||||
#bind ^R replace main
|
||||
#bind ^X cut main
|
||||
#bind ^C copy main
|
||||
#bind ^V paste all
|
||||
#bind ^P location main
|
||||
#bind ^B wherewas all
|
||||
#bind ^D findprevious all
|
||||
#bind ^R replace main
|
||||
#bind ^Z undo main
|
||||
#bind ^Y redo main
|
||||
#unbind ^K main
|
||||
#unbind ^U all
|
||||
#unbind ^N main
|
||||
#unbind ^Y all
|
||||
#unbind M-J main
|
||||
#unbind M-T main
|
||||
#bind ^A mark main
|
||||
#bind ^P location main
|
||||
#bind ^T gotoline main
|
||||
#bind ^T cutrestoffile execute
|
||||
#bind ^L linter execute
|
||||
#bind M-U undo main
|
||||
#bind M-R redo main
|
||||
#bind ^Z undo main
|
||||
#bind ^T gotodir browser
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# List of available languages.
|
||||
bg ca cs da de eo es eu fi fr ga gl hr hu id is it ja ko ms nb nl pl pt pt_BR ro ru sk sl sr sv tr uk vi zh_CN zh_TW
|
||||
bg ca cs da de eo es eu fi fr ga gl hr hu id is it ja ko ms nb nl pl pt pt_BR ro ru sk sl sq sr sv tr uk vi zh_CN zh_TW
|
||||
|
||||
920
po/nano.pot
920
po/nano.pot
File diff suppressed because it is too large
Load Diff
906
po/pt_BR.po
906
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
918
po/zh_CN.po
918
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
928
po/zh_TW.po
928
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION="6.0"
|
||||
VERSION="6.3"
|
||||
|
||||
./configure -C --enable-tiny && make && ./configure -C &&
|
||||
|
||||
|
||||
145
src/browser.c
145
src/browser.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* browser.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2001-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2015-2016, 2020 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -34,45 +34,43 @@ static size_t list_length = 0;
|
||||
/* The number of files in the list. */
|
||||
static size_t usable_rows = 0;
|
||||
/* The number of screen rows we can use to display the list. */
|
||||
static size_t piles = 0;
|
||||
static int piles = 0;
|
||||
/* The number of files that we can display per screen row. */
|
||||
static size_t longest = 0;
|
||||
/* The number of columns in the longest filename in the list. */
|
||||
static int gauge = 0;
|
||||
/* The width of a 'pile' -- the widest filename plus ten. */
|
||||
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 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 piles to the number of files that we can display
|
||||
* per screen row. And sort the list too. */
|
||||
/* Fill 'filelist' with the names of the files in the given directory, set
|
||||
* 'list_length' to the number of names in that list, set 'gauge' to the
|
||||
* width of the widest filename plus ten, and set 'piles' to the number of
|
||||
* files that can be displayed 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 path_len = strlen(path);
|
||||
const struct dirent *entry;
|
||||
size_t widest = 0;
|
||||
size_t index = 0;
|
||||
|
||||
longest = 0;
|
||||
/* Find the width of the widest filename in the current folder. */
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
size_t span = breadth(entry->d_name);
|
||||
|
||||
/* Find the length of the longest filename in the current folder. */
|
||||
while ((nextdir = readdir(dir)) != NULL) {
|
||||
size_t name_len = breadth(nextdir->d_name);
|
||||
|
||||
if (name_len > longest)
|
||||
longest = name_len;
|
||||
if (span > widest)
|
||||
widest = span;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
/* Put 10 characters' worth of blank space between columns of filenames
|
||||
* in the list whenever possible, as Pico does. */
|
||||
longest += 10;
|
||||
/* Reserve ten columns for blanks plus file size. */
|
||||
gauge = widest + 10;
|
||||
|
||||
/* If needed, make room for ".. (parent dir)". */
|
||||
if (longest < 15)
|
||||
longest = 15;
|
||||
if (gauge < 15)
|
||||
gauge = 15;
|
||||
/* Make sure we're not wider than the window. */
|
||||
if (longest > COLS)
|
||||
longest = COLS;
|
||||
if (gauge > COLS)
|
||||
gauge = COLS;
|
||||
|
||||
rewinddir(dir);
|
||||
|
||||
@@ -83,20 +81,19 @@ void read_the_list(const char *path, DIR *dir)
|
||||
|
||||
filelist = nmalloc(list_length * sizeof(char *));
|
||||
|
||||
while ((nextdir = readdir(dir)) != NULL && index < list_length) {
|
||||
/* Don't show the "." entry. */
|
||||
if (strcmp(nextdir->d_name, ".") == 0)
|
||||
while ((entry = readdir(dir)) != NULL && index < list_length) {
|
||||
/* Don't show the useless dot item. */
|
||||
if (strcmp(entry->d_name, ".") == 0)
|
||||
continue;
|
||||
|
||||
filelist[index] = nmalloc(path_len + strlen(nextdir->d_name) + 1);
|
||||
sprintf(filelist[index], "%s%s", path, nextdir->d_name);
|
||||
filelist[index] = nmalloc(path_len + strlen(entry->d_name) + 1);
|
||||
sprintf(filelist[index], "%s%s", path, entry->d_name);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
/* Maybe the number of files in the directory decreased between
|
||||
* the first time we scanned and the second time. */
|
||||
list_length = index;
|
||||
|
||||
/* Sort the list of names. */
|
||||
@@ -105,33 +102,28 @@ void read_the_list(const char *path, DIR *dir)
|
||||
/* Calculate how many files fit on a line -- feigning room for two
|
||||
* spaces beyond the right edge, and adding two spaces of padding
|
||||
* between columns. */
|
||||
piles = (COLS + 2) / (longest + 2);
|
||||
piles = (COLS + 2) / (gauge + 2);
|
||||
|
||||
usable_rows = editwinrows - (ISSET(ZERO) && LINES > 1 ? 1 : 0);
|
||||
}
|
||||
|
||||
/* Look for needle. If we find it, set selected to its location.
|
||||
* Note that needle must be an exact match for a file in the list. */
|
||||
void browser_select_dirname(const char *needle)
|
||||
/* Reselect the given file or directory name, if it still exists. */
|
||||
void reselect(const char *name)
|
||||
{
|
||||
size_t looking_at = 0;
|
||||
|
||||
for (; looking_at < list_length; looking_at++) {
|
||||
if (strcmp(filelist[looking_at], needle) == 0) {
|
||||
selected = looking_at;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (looking_at < list_length && strcmp(filelist[looking_at], name) != 0)
|
||||
looking_at++;
|
||||
|
||||
/* If the sought name isn't found, move the highlight so that the
|
||||
* changed selection will be noticed. */
|
||||
if (looking_at == list_length) {
|
||||
/* If the sought name was found, select it; otherwise, just move
|
||||
* the highlight so that the changed selection will be noticed,
|
||||
* but make sure to stay within the current available range. */
|
||||
if (looking_at < list_length)
|
||||
selected = looking_at;
|
||||
else if (selected > list_length)
|
||||
selected = list_length - 1;
|
||||
else
|
||||
--selected;
|
||||
|
||||
/* Make sure we stay within the available range. */
|
||||
if (selected >= list_length)
|
||||
selected = list_length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Display at most a screenful of filenames from the gleaned filelist. */
|
||||
@@ -158,11 +150,11 @@ void browser_refresh(void)
|
||||
size_t infomaxlen = 7;
|
||||
/* The maximum length of the file information in columns:
|
||||
* normally seven, but will be twelve for "(parent dir)". */
|
||||
bool dots = (COLS >= 15 && namelen >= longest - infomaxlen);
|
||||
bool dots = (COLS >= 15 && namelen >= gauge - infomaxlen);
|
||||
/* Whether to put an ellipsis before the filename? We don't
|
||||
* waste space on dots when there are fewer than 15 columns. */
|
||||
char *disp = display_string(thename, dots ?
|
||||
namelen + infomaxlen + 4 - longest : 0, longest, FALSE, FALSE);
|
||||
namelen + infomaxlen + 4 - gauge : 0, gauge, FALSE, FALSE);
|
||||
/* The filename (or a fragment of it) in displayable format.
|
||||
* When a fragment, account for dots plus one space padding. */
|
||||
struct stat state;
|
||||
@@ -170,18 +162,18 @@ void browser_refresh(void)
|
||||
/* If this is the selected item, draw its highlighted bar upfront, and
|
||||
* remember its location to be able to place the cursor on it. */
|
||||
if (index == selected) {
|
||||
wattron(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
mvwprintw(edit, row, col, "%*s", longest, " ");
|
||||
wattron(midwin, interface_color_pair[SELECTED_TEXT]);
|
||||
mvwprintw(midwin, row, col, "%*s", gauge, " ");
|
||||
the_row = row;
|
||||
the_column = col;
|
||||
}
|
||||
|
||||
/* If the name is too long, we display something like "...ename". */
|
||||
if (dots)
|
||||
mvwaddstr(edit, row, col, "...");
|
||||
mvwaddstr(edit, row, dots ? col + 3 : col, disp);
|
||||
mvwaddstr(midwin, row, col, "...");
|
||||
mvwaddstr(midwin, row, dots ? col + 3 : col, disp);
|
||||
|
||||
col += longest;
|
||||
col += gauge;
|
||||
|
||||
/* Show information about the file: "--" for symlinks (except when
|
||||
* they point to a directory) and for files that have disappeared,
|
||||
@@ -235,11 +227,11 @@ void browser_refresh(void)
|
||||
infolen = infomaxlen;
|
||||
}
|
||||
|
||||
mvwaddstr(edit, row, col - infolen, info);
|
||||
mvwaddstr(midwin, row, col - infolen, info);
|
||||
|
||||
/* If this is the selected item, finish its highlighting. */
|
||||
if (index == selected)
|
||||
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
wattroff(midwin, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
free(disp);
|
||||
free(info);
|
||||
@@ -247,8 +239,8 @@ void browser_refresh(void)
|
||||
/* Add some space between the columns. */
|
||||
col += 2;
|
||||
|
||||
/* If the next entry will not fit on this row, move to next row. */
|
||||
if (col > COLS - longest) {
|
||||
/* If the next item will not fit on this row, move to next row. */
|
||||
if (col > COLS - gauge) {
|
||||
row++;
|
||||
col = 0;
|
||||
}
|
||||
@@ -256,11 +248,11 @@ void browser_refresh(void)
|
||||
|
||||
/* If requested, put the cursor on the selected item and switch it on. */
|
||||
if (ISSET(SHOW_CURSOR)) {
|
||||
wmove(edit, the_row, the_column);
|
||||
wmove(midwin, the_row, the_column);
|
||||
curs_set(1);
|
||||
}
|
||||
|
||||
wnoutrefresh(edit);
|
||||
wnoutrefresh(midwin);
|
||||
}
|
||||
|
||||
/* Look for the given needle in the list of files. If forwards is TRUE,
|
||||
@@ -447,19 +439,18 @@ char *browse(char *path)
|
||||
}
|
||||
|
||||
if (dir != NULL) {
|
||||
/* Get the file list, and set longest and piles in the process. */
|
||||
/* Get the file list, and set gauge and piles in the process. */
|
||||
read_the_list(path, dir);
|
||||
closedir(dir);
|
||||
dir = NULL;
|
||||
}
|
||||
|
||||
/* If given, reselect the present_name and then discard it. */
|
||||
/* If something was selected before, reselect it;
|
||||
* otherwise, just select the first item (..). */
|
||||
if (present_name != NULL) {
|
||||
browser_select_dirname(present_name);
|
||||
|
||||
reselect(present_name);
|
||||
free(present_name);
|
||||
present_name = NULL;
|
||||
/* Otherwise, select the first file or directory in the list. */
|
||||
} else
|
||||
selected = 0;
|
||||
|
||||
@@ -484,7 +475,7 @@ char *browse(char *path)
|
||||
|
||||
old_selected = selected;
|
||||
|
||||
kbinput = get_kbinput(edit, ISSET(SHOW_CURSOR));
|
||||
kbinput = get_kbinput(midwin, ISSET(SHOW_CURSOR));
|
||||
|
||||
#ifdef ENABLE_MOUSE
|
||||
if (kbinput == KEY_MOUSE) {
|
||||
@@ -492,12 +483,12 @@ char *browse(char *path)
|
||||
|
||||
/* When the user clicked in the file list, select a filename. */
|
||||
if (get_mouseinput(&mouse_y, &mouse_x, TRUE) == 0 &&
|
||||
wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
|
||||
wmouse_trafo(midwin, &mouse_y, &mouse_x, FALSE)) {
|
||||
selected = selected - selected % (usable_rows * piles) +
|
||||
(mouse_y * piles) + (mouse_x / (longest + 2));
|
||||
(mouse_y * piles) + (mouse_x / (gauge + 2));
|
||||
|
||||
/* When beyond end-of-row, select the preceding filename. */
|
||||
if (mouse_x > piles * (longest + 2))
|
||||
if (mouse_x > piles * (gauge + 2))
|
||||
selected--;
|
||||
|
||||
/* When beyond end-of-list, select the last filename. */
|
||||
@@ -718,14 +709,10 @@ char *browse_in(const char *inpath)
|
||||
path = free_and_assign(path, strip_last_component(path));
|
||||
|
||||
if (stat(path, &fileinfo) == -1 || !S_ISDIR(fileinfo.st_mode)) {
|
||||
char *currentdir = nmalloc(PATH_MAX + 1);
|
||||
|
||||
path = free_and_assign(path, getcwd(currentdir, PATH_MAX + 1));
|
||||
path = free_and_assign(path, realpath(".", NULL));
|
||||
|
||||
if (path == NULL) {
|
||||
statusline(MILD, _("The working directory has disappeared"));
|
||||
free(currentdir);
|
||||
beep();
|
||||
statusline(ALERT, _("The working directory has disappeared"));
|
||||
napms(1200);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* chars.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2001-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016-2021 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
|
||||
33
src/color.c
33
src/color.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* color.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2001-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2017, 2020, 2021 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -53,6 +53,7 @@ void set_interface_colorpairs(void)
|
||||
}
|
||||
init_pair(index + 1, combo->fg, combo->bg);
|
||||
interface_color_pair[index] = COLOR_PAIR(index + 1) | combo->attributes;
|
||||
rescind_colors = FALSE;
|
||||
} else {
|
||||
if (index == FUNCTION_TAG || index == SCROLL_BAR)
|
||||
interface_color_pair[index] = A_NORMAL;
|
||||
@@ -72,6 +73,11 @@ void set_interface_colorpairs(void)
|
||||
|
||||
free(color_combo[index]);
|
||||
}
|
||||
|
||||
if (rescind_colors) {
|
||||
interface_color_pair[SPOTLIGHTED] = A_REVERSE;
|
||||
interface_color_pair[ERROR_MESSAGE] = A_REVERSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign a pair number to each of the foreground/background color combinations
|
||||
@@ -255,12 +261,14 @@ void check_the_multis(linestruct *line)
|
||||
if (line->multidata[ink->id] == NOTHING) {
|
||||
if (!astart)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] & (WHOLELINE|WOULDBE)) {
|
||||
if (!astart && !anend)
|
||||
} else if (line->multidata[ink->id] == WHOLELINE) {
|
||||
/* Ensure that a detected start match is not actually an end match. */
|
||||
if (!anend && (!astart || regexec(ink->end, line->data, 1,
|
||||
&endmatch, 0) != 0))
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == JUSTONTHIS) {
|
||||
if (astart && anend && regexec(ink->start, line->data + endmatch.rm_eo,
|
||||
1, &startmatch, 0) != 0)
|
||||
if (astart && anend && regexec(ink->start, line->data + startmatch.rm_eo +
|
||||
endmatch.rm_eo, 1, &startmatch, 0) != 0)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == STARTSHERE) {
|
||||
if (astart && !anend)
|
||||
@@ -272,6 +280,7 @@ void check_the_multis(linestruct *line)
|
||||
|
||||
/* There is a mismatch, so something changed: repaint. */
|
||||
refresh_needed = TRUE;
|
||||
perturbed = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -342,21 +351,17 @@ void precalc_multicolorinfo(void)
|
||||
1, &endmatch, 0) != 0)
|
||||
tailline = tailline->next;
|
||||
|
||||
/* When there is no end match, mark relevant lines as such. */
|
||||
if (tailline == NULL) {
|
||||
for (; line->next != NULL; line = line->next)
|
||||
line->multidata[ink->id] = WOULDBE;
|
||||
line->multidata[ink->id] = WOULDBE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We found it, we found it, la lala lala. Mark the lines. */
|
||||
line->multidata[ink->id] = STARTSHERE;
|
||||
|
||||
// Note that this also advances the line in the main loop.
|
||||
for (line = line->next; line != tailline; line = line->next)
|
||||
line->multidata[ink->id] = WHOLELINE;
|
||||
|
||||
if (tailline == NULL) {
|
||||
line = openfile->filebot;
|
||||
break;
|
||||
}
|
||||
|
||||
tailline->multidata[ink->id] = ENDSHERE;
|
||||
|
||||
/* Look for a possible new start after the end match. */
|
||||
|
||||
17
src/cut.c
17
src/cut.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* cut.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014 Mark Majeres *
|
||||
* Copyright (C) 2016, 2018-2020 Benno Schulenberg *
|
||||
* *
|
||||
@@ -435,9 +435,19 @@ void ingraft_buffer(linestruct *topline)
|
||||
/* Meld a copy of the given buffer into the current file buffer. */
|
||||
void copy_from_buffer(linestruct *somebuffer)
|
||||
{
|
||||
#ifdef ENABLE_COLOR
|
||||
size_t threshold = openfile->edittop->lineno + editwinrows - 1;
|
||||
#endif
|
||||
linestruct *the_copy = copy_buffer(somebuffer);
|
||||
|
||||
ingraft_buffer(the_copy);
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
if (openfile->current->lineno > threshold || ISSET(SOFTWRAP))
|
||||
recook = TRUE;
|
||||
else
|
||||
perturbed = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -485,7 +495,7 @@ void do_snip(bool marked, bool until_eof, bool append)
|
||||
/* When not at the end of a line, move the rest of this line into
|
||||
* the cutbuffer. Otherwise, when not at the end of the buffer,
|
||||
* move just the "line separator" into the cutbuffer. */
|
||||
if (openfile->current_x < strlen(openfile->current->data))
|
||||
if (line->data[openfile->current_x] != '\0')
|
||||
extract_segment(line, openfile->current_x, line, strlen(line->data));
|
||||
else if (openfile->current != openfile->filebot) {
|
||||
extract_segment(line, openfile->current_x, line->next, 0);
|
||||
@@ -509,6 +519,9 @@ void do_snip(bool marked, bool until_eof, bool append)
|
||||
|
||||
set_modified();
|
||||
refresh_needed = TRUE;
|
||||
#ifdef ENABLE_COLOR
|
||||
perturbed = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Move text from the current buffer into the cutbuffer. */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* definitions.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -108,6 +108,14 @@
|
||||
#define BACKWARD FALSE
|
||||
#define FORWARD TRUE
|
||||
|
||||
#define YESORNO FALSE
|
||||
#define YESORALLORNO TRUE
|
||||
|
||||
#define YES 1
|
||||
#define ALL 2
|
||||
#define NO 0
|
||||
#define CANCEL -1
|
||||
|
||||
#define BLIND FALSE
|
||||
#define VISIBLE TRUE
|
||||
|
||||
@@ -162,8 +170,6 @@
|
||||
/* The start regex matches on an earlier line, the end regex on this one. */
|
||||
#define JUSTONTHIS (1<<5)
|
||||
/* Both the start and end regexes match within this line. */
|
||||
#define WOULDBE (1<<6)
|
||||
/* An unpaired start match is on or before this line. */
|
||||
#endif
|
||||
|
||||
/* Basic control codes. */
|
||||
|
||||
216
src/files.c
216
src/files.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* files.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2015-2021 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -33,6 +33,10 @@
|
||||
|
||||
#define RW_FOR_ALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
||||
|
||||
#ifndef HAVE_FSYNC
|
||||
# define fsync(...) 0
|
||||
#endif
|
||||
|
||||
/* Add an item to the circular list of openfile structs. */
|
||||
void make_new_buffer(void)
|
||||
{
|
||||
@@ -143,7 +147,7 @@ const char *locking_suffix = ".swp";
|
||||
* existing version of that file. Return TRUE on success; FALSE otherwise. */
|
||||
bool write_lockfile(const char *lockfilename, const char *filename, bool modified)
|
||||
{
|
||||
#ifdef HAVE_PWD_H
|
||||
#if defined(HAVE_PWD_H) && defined(HAVE_GETEUID)
|
||||
pid_t mypid = getpid();
|
||||
uid_t myuid = geteuid();
|
||||
struct passwd *mypwuid = getpwuid(myuid);
|
||||
@@ -303,14 +307,14 @@ char *do_lockfile(const char *filename, bool ask_the_user)
|
||||
free(postedname);
|
||||
free(pidstring);
|
||||
|
||||
choice = do_yesno_prompt(FALSE, promptstr);
|
||||
choice = ask_user(YESORNO, promptstr);
|
||||
free(promptstr);
|
||||
|
||||
/* When the user cancelled while we're still starting up, quit. */
|
||||
if (choice < 0 && !we_are_running)
|
||||
if (choice == CANCEL && !we_are_running)
|
||||
finish();
|
||||
|
||||
if (choice < 1) {
|
||||
if (choice != YES) {
|
||||
free(lockfilename);
|
||||
wipe_statusbar();
|
||||
return SKIPTHISFILE;
|
||||
@@ -346,8 +350,18 @@ bool has_valid_path(const char *filename)
|
||||
char *parentdir = dirname(namecopy);
|
||||
struct stat parentinfo;
|
||||
bool validity = FALSE;
|
||||
bool gone = FALSE;
|
||||
|
||||
if (stat(parentdir, &parentinfo) == -1) {
|
||||
if (strcmp(parentdir, ".") == 0) {
|
||||
char *currentdir = realpath(".", NULL);
|
||||
|
||||
gone = (currentdir == NULL && errno == ENOENT);
|
||||
free(currentdir);
|
||||
}
|
||||
|
||||
if (gone)
|
||||
statusline(ALERT, _("The working directory has disappeared"));
|
||||
else if (stat(parentdir, &parentinfo) == -1) {
|
||||
if (errno == ENOENT)
|
||||
/* TRANSLATORS: Keep the next ten messages at most 76 characters. */
|
||||
statusline(ALERT, _("Directory '%s' does not exist"), parentdir);
|
||||
@@ -411,7 +425,7 @@ bool open_buffer(const char *filename, bool new_one)
|
||||
free(realname);
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
#elif defined(HAVE_GETEUID)
|
||||
if (new_one && !(fileinfo.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) &&
|
||||
geteuid() == ROOT_UID)
|
||||
statusline(ALERT, _("%s is meant to be read-only"), realname);
|
||||
@@ -675,9 +689,13 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
|
||||
block_sigwinch(TRUE);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FLOCKFILE
|
||||
/* Lock the file before starting to read it, to avoid the overhead
|
||||
* of locking it for each single byte that we read from it. */
|
||||
flockfile(f);
|
||||
#else
|
||||
# define getc_unlocked getc
|
||||
#endif
|
||||
|
||||
control_C_was_pressed = FALSE;
|
||||
|
||||
@@ -741,8 +759,10 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
|
||||
|
||||
errornumber = errno;
|
||||
|
||||
#ifdef HAVE_FUNLOCKFILE
|
||||
/* We are done with the file, unlock it. */
|
||||
funlockfile(f);
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
block_sigwinch(FALSE);
|
||||
@@ -826,12 +846,14 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable)
|
||||
report_size = TRUE;
|
||||
|
||||
/* If we inserted less than a screenful, don't center the cursor. */
|
||||
if (undoable && less_than_a_screenful(was_lineno, was_leftedge))
|
||||
if (undoable && less_than_a_screenful(was_lineno, was_leftedge)) {
|
||||
focusing = FALSE;
|
||||
#ifdef ENABLE_COLOR
|
||||
else if (undoable)
|
||||
precalc_multicolorinfo();
|
||||
perturbed = TRUE;
|
||||
} else if (undoable) {
|
||||
recook = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (undoable)
|
||||
@@ -950,7 +972,9 @@ static pid_t pid_of_command = -1;
|
||||
/* Send an unconditional kill signal to the running external command. */
|
||||
void cancel_the_command(int signal)
|
||||
{
|
||||
#ifdef SIGKILL
|
||||
kill(pid_of_command, SIGKILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Send the text that starts at the given line to file descriptor fd. */
|
||||
@@ -973,10 +997,12 @@ void send_data(const linestruct *line, int fd)
|
||||
/* Execute the given command in a shell. Return TRUE on success. */
|
||||
bool execute_command(const char *command)
|
||||
{
|
||||
#if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAIT)
|
||||
int from_fd[2], to_fd[2];
|
||||
/* The pipes through which text will be written and read. */
|
||||
struct sigaction oldaction, newaction = {{0}};
|
||||
/* Original and temporary handlers for SIGINT. */
|
||||
ssize_t was_lineno = (openfile->mark ? 0 : openfile->current->lineno);
|
||||
const bool should_pipe = (command[0] == '|');
|
||||
FILE *stream;
|
||||
|
||||
@@ -1008,6 +1034,7 @@ bool execute_command(const char *command)
|
||||
if (should_pipe) {
|
||||
if (dup2(to_fd[0], STDIN_FILENO) < 0)
|
||||
exit(5);
|
||||
close(from_fd[1]);
|
||||
close(to_fd[1]);
|
||||
}
|
||||
|
||||
@@ -1054,7 +1081,8 @@ bool execute_command(const char *command)
|
||||
}
|
||||
add_undo(CUT, NULL);
|
||||
do_snip(openfile->mark != NULL, openfile->mark == NULL, FALSE);
|
||||
openfile->filetop->has_anchor = FALSE;
|
||||
if (openfile->filetop->next == NULL)
|
||||
openfile->filetop->has_anchor = FALSE;
|
||||
update_undo(CUT);
|
||||
}
|
||||
|
||||
@@ -1090,8 +1118,11 @@ bool execute_command(const char *command)
|
||||
else
|
||||
read_file(stream, 0, "pipe", TRUE);
|
||||
|
||||
if (should_pipe && !ISSET(MULTIBUFFER))
|
||||
if (should_pipe && !ISSET(MULTIBUFFER)) {
|
||||
if (was_lineno)
|
||||
goto_line_posx(was_lineno, 0);
|
||||
add_undo(COUPLE_END, N_("filtering"));
|
||||
}
|
||||
|
||||
/* Wait for the external command (and possibly data sender) to terminate. */
|
||||
wait(NULL);
|
||||
@@ -1106,6 +1137,9 @@ bool execute_command(const char *command)
|
||||
terminal_init();
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
#endif /* NANO_TINY */
|
||||
|
||||
@@ -1322,106 +1356,36 @@ void do_execute(void)
|
||||
* absolute path (plus filename) when the path exists, and NULL when not. */
|
||||
char *get_full_path(const char *origpath)
|
||||
{
|
||||
char *allocation, *here, *target, *last_slash;
|
||||
char *just_filename = NULL;
|
||||
int attempts = 0;
|
||||
char *untilded, *target, *slash;
|
||||
struct stat fileinfo;
|
||||
bool path_only;
|
||||
|
||||
if (origpath == NULL)
|
||||
return NULL;
|
||||
|
||||
allocation = nmalloc(PATH_MAX + 1);
|
||||
here = getcwd(allocation, PATH_MAX + 1);
|
||||
untilded = real_dir_from_tilde(origpath);
|
||||
target = realpath(untilded, NULL);
|
||||
slash = strrchr(untilded, '/');
|
||||
|
||||
/* If getting the current directory failed, go up one level and try again,
|
||||
* until we find an existing directory, and use that as the current one. */
|
||||
while (here == NULL && attempts < 20) {
|
||||
IGNORE_CALL_RESULT(chdir(".."));
|
||||
here = getcwd(allocation, PATH_MAX + 1);
|
||||
attempts++;
|
||||
}
|
||||
/* If realpath() returned NULL, try without the last component,
|
||||
* as this can be a file that does not exist yet. */
|
||||
if (!target && slash && slash[1]) {
|
||||
*slash = '\0';
|
||||
target = realpath(untilded, NULL);
|
||||
|
||||
/* If we found a directory, make sure its path ends in a slash. */
|
||||
if (here != NULL) {
|
||||
if (strcmp(here, "/") != 0) {
|
||||
here = nrealloc(here, strlen(here) + 2);
|
||||
strcat(here, "/");
|
||||
}
|
||||
} else {
|
||||
here = copy_of("");
|
||||
free(allocation);
|
||||
}
|
||||
|
||||
target = real_dir_from_tilde(origpath);
|
||||
|
||||
/* Determine whether the target path refers to a directory. If statting
|
||||
* target fails, however, assume that it refers to a new, unsaved buffer. */
|
||||
path_only = (stat(target, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode));
|
||||
|
||||
/* If the target is a directory, make sure its path ends in a slash. */
|
||||
if (path_only) {
|
||||
size_t length = strlen(target);
|
||||
|
||||
if (target[length - 1] != '/') {
|
||||
target = nrealloc(target, length + 2);
|
||||
strcat(target, "/");
|
||||
/* Upon success, re-add the last component of the original path. */
|
||||
if (target) {
|
||||
target = nrealloc(target, strlen(target) + strlen(slash + 1) + 1);
|
||||
strcat(target, slash + 1);
|
||||
}
|
||||
}
|
||||
|
||||
last_slash = strrchr(target, '/');
|
||||
|
||||
/* If the target path does not contain a slash, then it is a bare filename
|
||||
* and must therefore be located in the working directory. */
|
||||
if (last_slash == NULL) {
|
||||
just_filename = target;
|
||||
target = here;
|
||||
} else {
|
||||
/* If target contains a filename, separate the two. */
|
||||
if (!path_only) {
|
||||
just_filename = copy_of(last_slash + 1);
|
||||
*(last_slash + 1) = '\0';
|
||||
}
|
||||
|
||||
/* If we can't change to the target directory, give up. Otherwise,
|
||||
* get the canonical path to this target directory. */
|
||||
if (chdir(target) == -1) {
|
||||
free(target);
|
||||
target = NULL;
|
||||
} else {
|
||||
free(target);
|
||||
|
||||
allocation = nmalloc(PATH_MAX + 1);
|
||||
target = getcwd(allocation, PATH_MAX + 1);
|
||||
|
||||
/* If we got a result, make sure it ends in a slash.
|
||||
* Otherwise, ensure that we return NULL. */
|
||||
if (target != NULL) {
|
||||
if (strcmp(target, "/") != 0) {
|
||||
target = nrealloc(target, strlen(target) + 2);
|
||||
strcat(target, "/");
|
||||
}
|
||||
} else {
|
||||
path_only = TRUE;
|
||||
free(allocation);
|
||||
}
|
||||
|
||||
/* Finally, go back to where we were before. We don't check
|
||||
* for an error, since we can't do anything if we get one. */
|
||||
IGNORE_CALL_RESULT(chdir(here));
|
||||
}
|
||||
|
||||
free(here);
|
||||
/* Ensure that a directory path ends with a slash. */
|
||||
if (target && stat(target, &fileinfo) == 0 && S_ISDIR(fileinfo.st_mode)) {
|
||||
target = nrealloc(target, strlen(target) + 2);
|
||||
strcat(target, "/");
|
||||
}
|
||||
|
||||
/* If we were given more than a bare path, concatenate the target path
|
||||
* with the filename portion to get the full, absolute file path. */
|
||||
if (!path_only && target != NULL) {
|
||||
target = nrealloc(target, strlen(target) + strlen(just_filename) + 1);
|
||||
strcat(target, just_filename);
|
||||
}
|
||||
|
||||
free(just_filename);
|
||||
free(untilded);
|
||||
|
||||
return target;
|
||||
}
|
||||
@@ -1653,6 +1617,7 @@ bool make_backup_of(char *realname)
|
||||
if (backup_file == NULL)
|
||||
goto problem;
|
||||
|
||||
#ifdef HAVE_FCHOWN
|
||||
/* Try to change owner and group to those of the original file;
|
||||
* ignore permission errors, as a normal user cannot change the owner. */
|
||||
if (fchown(descriptor, openfile->statinfo->st_uid,
|
||||
@@ -1660,7 +1625,8 @@ bool make_backup_of(char *realname)
|
||||
fclose(backup_file);
|
||||
goto problem;
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef HAVE_FCHMOD
|
||||
/* Set the backup's permissions to those of the original file.
|
||||
* It is not a security issue if this fails, as we have created
|
||||
* the file with just read and write permission for the owner. */
|
||||
@@ -1668,6 +1634,7 @@ bool make_backup_of(char *realname)
|
||||
fclose(backup_file);
|
||||
goto problem;
|
||||
}
|
||||
#endif
|
||||
|
||||
original = fopen(realname, "rb");
|
||||
|
||||
@@ -1732,8 +1699,8 @@ bool make_backup_of(char *realname)
|
||||
* ask the user what to do, because if something goes wrong during the
|
||||
* save of the file itself, its contents may be lost. */
|
||||
/* TRANSLATORS: Try to keep this message at most 76 characters. */
|
||||
if (errno != ENOSPC && do_yesno_prompt(FALSE, _("Cannot make backup; "
|
||||
"continue and save actual file? ")) == 1)
|
||||
if (errno != ENOSPC && ask_user(YESORNO, _("Cannot make backup; "
|
||||
"continue and save actual file? ")) == YES)
|
||||
return TRUE;
|
||||
|
||||
/* TRANSLATORS: The %s is the reason of failure. */
|
||||
@@ -1974,6 +1941,19 @@ bool write_file(const char *name, FILE *thefile, bool normal,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
|
||||
|
||||
cleanup_and_exit:
|
||||
#ifndef NANO_TINY
|
||||
if (errno == ENOSPC && normal) {
|
||||
napms(3200); lastmessage = VACUUM;
|
||||
/* TRANSLATORS: This warns for data loss when the disk is full. */
|
||||
statusline(ALERT, _("File on disk has been truncated!"));
|
||||
napms(3200); lastmessage = VACUUM;
|
||||
/* TRANSLATORS: This is a suggestion to the user,
|
||||
* where "resume" means resuming from suspension.
|
||||
* Try to keep this at most 76 characters. */
|
||||
statusline(ALERT, _("Maybe ^T^Z, make room on disk, resume, then ^S^X"));
|
||||
stat_with_alloc(realname, &openfile->statinfo);
|
||||
}
|
||||
#endif
|
||||
free(tempname);
|
||||
free(realname);
|
||||
return FALSE;
|
||||
@@ -2055,7 +2035,7 @@ bool write_region_to_file(const char *name, FILE *stream, bool normal,
|
||||
get_region(&topline, &top_x, &botline, &bot_x);
|
||||
|
||||
/* When needed, prepare a magic end line for the region. */
|
||||
if (bot_x > 0 && !ISSET(NO_NEWLINES)) {
|
||||
if (normal && bot_x > 0 && !ISSET(NO_NEWLINES)) {
|
||||
stopper = make_new_node(botline);
|
||||
stopper->data = copy_of("");
|
||||
} else
|
||||
@@ -2115,7 +2095,7 @@ int write_it_out(bool exiting, bool withprompt)
|
||||
functionptrtype func;
|
||||
const char *msg;
|
||||
int response = 0;
|
||||
int choice = 0;
|
||||
int choice = NO;
|
||||
#ifndef NANO_TINY
|
||||
const char *formatstr = (openfile->fmt == DOS_FILE) ? _(" [DOS Format]") :
|
||||
(openfile->fmt == MAC_FILE) ? _(" [Mac Format]") : "";
|
||||
@@ -2256,8 +2236,8 @@ int write_it_out(bool exiting, bool withprompt)
|
||||
if (exiting || !openfile->mark)
|
||||
#endif
|
||||
{
|
||||
if (do_yesno_prompt(FALSE, _("Save file under "
|
||||
"DIFFERENT NAME? ")) < 1)
|
||||
if (ask_user(YESORNO, _("Save file under "
|
||||
"DIFFERENT NAME? ")) != YES)
|
||||
continue;
|
||||
maychange = TRUE;
|
||||
}
|
||||
@@ -2270,12 +2250,12 @@ int write_it_out(bool exiting, bool withprompt)
|
||||
|
||||
sprintf(message, question, name);
|
||||
|
||||
choice = do_yesno_prompt(FALSE, message);
|
||||
choice = ask_user(YESORNO, message);
|
||||
|
||||
free(message);
|
||||
free(name);
|
||||
|
||||
if (choice < 1)
|
||||
if (choice != YES)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2291,7 +2271,7 @@ int write_it_out(bool exiting, bool withprompt)
|
||||
warn_and_briefly_pause(_("File on disk has changed"));
|
||||
|
||||
/* TRANSLATORS: Try to keep this at most 76 characters. */
|
||||
choice = do_yesno_prompt(FALSE, _("File was modified "
|
||||
choice = ask_user(YESORNO, _("File was modified "
|
||||
"since you opened it; continue saving? "));
|
||||
wipe_statusbar();
|
||||
|
||||
@@ -2299,14 +2279,16 @@ int write_it_out(bool exiting, bool withprompt)
|
||||
* overwrite the file right here when requested. */
|
||||
if (ISSET(SAVE_ON_EXIT) && withprompt) {
|
||||
free(given);
|
||||
if (choice == 1)
|
||||
if (choice == YES)
|
||||
return write_file(openfile->filename, NULL,
|
||||
NORMAL, OVERWRITE, NONOTES);
|
||||
else if (choice == 0)
|
||||
else if (choice == NO) /* Discard buffer */
|
||||
return 2;
|
||||
else
|
||||
return 0;
|
||||
} else if (choice != 1) {
|
||||
} else if (choice == CANCEL && exiting) {
|
||||
continue;
|
||||
} else if (choice != YES) {
|
||||
free(given);
|
||||
return 1;
|
||||
}
|
||||
@@ -2664,23 +2646,23 @@ char *input_tab(char *morsel, size_t *place, void (*refresh_func)(void), bool *l
|
||||
for (match = 0; match < num_matches; match++) {
|
||||
char *disp;
|
||||
|
||||
wmove(edit, row, (longest_name + 2) * (match % ncols));
|
||||
wmove(midwin, row, (longest_name + 2) * (match % ncols));
|
||||
|
||||
if (row == lastrow && (match + 1) % ncols == 0 &&
|
||||
match + 1 < num_matches) {
|
||||
waddstr(edit, _("(more)"));
|
||||
waddstr(midwin, _("(more)"));
|
||||
break;
|
||||
}
|
||||
|
||||
disp = display_string(matches[match], 0, longest_name, FALSE, FALSE);
|
||||
waddstr(edit, disp);
|
||||
waddstr(midwin, disp);
|
||||
free(disp);
|
||||
|
||||
if ((match + 1) % ncols == 0)
|
||||
row++;
|
||||
}
|
||||
|
||||
wnoutrefresh(edit);
|
||||
wnoutrefresh(midwin);
|
||||
*listed = TRUE;
|
||||
}
|
||||
|
||||
|
||||
36
src/global.c
36
src/global.c
@@ -1,8 +1,8 @@
|
||||
/**************************************************************************
|
||||
* global.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2020 Benno Schulenberg *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2021 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 *
|
||||
@@ -118,12 +118,12 @@ size_t wrap_at = 0;
|
||||
WINDOW *topwin = NULL;
|
||||
/* The top portion of the screen, showing the version number of nano,
|
||||
* the name of the file, and whether the buffer was modified. */
|
||||
WINDOW *edit = NULL;
|
||||
WINDOW *midwin = NULL;
|
||||
/* The middle portion of the screen: the edit window, showing the
|
||||
* contents of the current buffer, the file we are editing. */
|
||||
WINDOW *bottomwin = NULL;
|
||||
/* The bottom portion of the screen, where we display statusbar
|
||||
* messages, the status-bar prompt, and a list of shortcuts. */
|
||||
WINDOW *footwin = NULL;
|
||||
/* The bottom portion of the screen, where status-bar messages,
|
||||
* the status-bar prompt, and a list of shortcuts are shown. */
|
||||
int editwinrows = 0;
|
||||
/* How many rows does the edit window take up? */
|
||||
int editwincols = -1;
|
||||
@@ -201,6 +201,12 @@ char *syntaxstr = NULL;
|
||||
/* The color syntax name specified on the command line. */
|
||||
bool have_palette = FALSE;
|
||||
/* Whether the colors for the current syntax have been initialized. */
|
||||
bool rescind_colors = FALSE;
|
||||
/* Becomes TRUE when NO_COLOR is set in the environment. */
|
||||
bool perturbed = FALSE;
|
||||
/* Whether the multiline-coloring situation has changed. */
|
||||
bool recook = FALSE;
|
||||
/* Whether the multidata should be recalculated. */
|
||||
#endif
|
||||
|
||||
int currmenu = MMOST;
|
||||
@@ -602,7 +608,7 @@ void shortcut_init(void)
|
||||
const char *nextfile_gist = N_("Switch to the next file buffer");
|
||||
#endif
|
||||
const char *verbatim_gist = N_("Insert the next keystroke verbatim");
|
||||
const char *tab_gist = N_("Insert a tab at the cursor position");
|
||||
const char *tab_gist = N_("Insert a tab at the cursor position (or indent marked lines)");
|
||||
const char *enter_gist = N_("Insert a newline at the cursor position");
|
||||
const char *delete_gist = N_("Delete the character under the cursor");
|
||||
const char *backspace_gist =
|
||||
@@ -621,7 +627,7 @@ void shortcut_init(void)
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
const char *wordcount_gist =
|
||||
N_("Count the number of words, lines, and characters");
|
||||
N_("Count the number of lines, words, and characters");
|
||||
const char *suspend_gist = N_("Suspend the editor (return to the shell)");
|
||||
#endif
|
||||
const char *refresh_gist = N_("Refresh (redraw) the current screen");
|
||||
@@ -835,7 +841,7 @@ void shortcut_init(void)
|
||||
|
||||
#ifdef ENABLE_BROWSER
|
||||
add_to_funcs(goto_dir, MBROWSER,
|
||||
/* TRANSLATORS: Try to keep the next seven strings at most 10 characters. */
|
||||
/* TRANSLATORS: Try to keep the next four strings at most 10 characters. */
|
||||
N_("Go To Dir"), WITHORSANS(gotodir_gist), TOGETHER, VIEW);
|
||||
#ifdef ENABLE_HELP
|
||||
add_to_funcs(full_refresh, MBROWSER,
|
||||
@@ -1021,7 +1027,7 @@ void shortcut_init(void)
|
||||
N_("Down to anchor"), WITHORSANS(nextanchor_gist), BLANKAFTER, VIEW);
|
||||
|
||||
add_to_funcs(zap_text, MMAIN,
|
||||
/* TRANSLATORS: This *deletes* a line or marked region. */
|
||||
/* TRANSLATORS: This refers to deleting a line or marked region. */
|
||||
N_("Zap"), WITHORSANS(zap_gist), BLANKAFTER, NOVIEW);
|
||||
|
||||
if (!ISSET(RESTRICTED)) {
|
||||
@@ -1187,8 +1193,10 @@ void shortcut_init(void)
|
||||
add_to_sclist(MMAIN, "^\\", 0, do_replace, 0);
|
||||
add_to_sclist(MMAIN, "M-R", 0, do_replace, 0);
|
||||
add_to_sclist(MMOST, "^K", 0, cut_text, 0);
|
||||
#ifdef NANO_TINY
|
||||
add_to_sclist(MMAIN, "^U", 0, paste_text, 0);
|
||||
#else
|
||||
add_to_sclist(MMOST, "^U", 0, paste_text, 0);
|
||||
#ifndef NANO_TINY
|
||||
add_to_sclist(MMAIN, "^T", 0, do_execute, 0);
|
||||
#endif
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
@@ -1240,10 +1248,10 @@ void shortcut_init(void)
|
||||
add_to_sclist(MMAIN, "M-A", 0, do_mark, 0);
|
||||
add_to_sclist(MMAIN, "^6", 0, do_mark, 0);
|
||||
add_to_sclist(MMAIN, "^^", 0, do_mark, 0);
|
||||
add_to_sclist(MMAIN, "M-6", 0, copy_text, 0);
|
||||
add_to_sclist(MMAIN, "M-^", 0, copy_text, 0);
|
||||
add_to_sclist(MMOST, "M-6", 0, copy_text, 0);
|
||||
add_to_sclist(MMOST, "M-^", 0, copy_text, 0);
|
||||
add_to_sclist(MMAIN, "M-}", 0, do_indent, 0);
|
||||
add_to_sclist(MMAIN, "Tab", INDENT_KEY, do_indent, 0);
|
||||
add_to_sclist(MMAIN, "", INDENT_KEY, do_indent, 0);
|
||||
add_to_sclist(MMAIN, "M-{", 0, do_unindent, 0);
|
||||
add_to_sclist(MMAIN, "Sh-Tab", SHIFT_TAB, do_unindent, 0);
|
||||
add_to_sclist(MMAIN, "M-:", 0, record_macro, 0);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* help.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2000-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2000-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2017 Rishabh Dave *
|
||||
* Copyright (C) 2014-2019 Benno Schulenberg *
|
||||
* *
|
||||
@@ -463,7 +463,7 @@ void show_help(void)
|
||||
focusing = TRUE;
|
||||
|
||||
/* Show the cursor when we searched and found something. */
|
||||
kbinput = get_kbinput(edit, didfind == 1 || ISSET(SHOW_CURSOR));
|
||||
kbinput = get_kbinput(midwin, didfind == 1 || ISSET(SHOW_CURSOR));
|
||||
|
||||
didfind = 0;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* history.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2003-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2003-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
|
||||
11
src/move.c
11
src/move.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* move.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2018 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -44,6 +44,9 @@ void to_last_line(void)
|
||||
openfile->current_y = editwinrows - 1;
|
||||
|
||||
refresh_needed = TRUE;
|
||||
#ifdef ENABLE_COLOR
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
focusing = FALSE;
|
||||
}
|
||||
|
||||
@@ -222,6 +225,9 @@ void to_para_end(void)
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
|
||||
edit_redraw(was_current, CENTERING);
|
||||
#ifdef ENABLE_COLOR
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
}
|
||||
#endif /* ENABLE_JUSTIFY */
|
||||
|
||||
@@ -263,6 +269,9 @@ void to_next_block(void)
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current, CENTERING);
|
||||
#ifdef ENABLE_COLOR
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Move to the previous word. */
|
||||
|
||||
107
src/nano.c
107
src/nano.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* nano.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2021 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#if defined(__linux__) || !defined(NANO_TINY)
|
||||
#ifdef __linux__
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef ENABLE_UTF8
|
||||
@@ -243,14 +243,14 @@ void finish(void)
|
||||
/* Blank the status bar and (if applicable) the shortcut list. */
|
||||
blank_statusbar();
|
||||
blank_bottombars();
|
||||
wrefresh(bottomwin);
|
||||
wrefresh(footwin);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Deallocate the two or three subwindows. */
|
||||
if (topwin != NULL)
|
||||
delwin(topwin);
|
||||
delwin(edit);
|
||||
delwin(bottomwin);
|
||||
delwin(midwin);
|
||||
delwin(footwin);
|
||||
#endif
|
||||
/* Switch the cursor on, exit from curses, and restore terminal settings. */
|
||||
restore_terminal();
|
||||
@@ -304,20 +304,20 @@ void do_exit(void)
|
||||
/* When unmodified, simply close. Else, when doing automatic saving
|
||||
* and the file has a name, simply save. Otherwise, ask the user. */
|
||||
if (!openfile->modified)
|
||||
choice = 0;
|
||||
choice = NO;
|
||||
else if (ISSET(SAVE_ON_EXIT) && openfile->filename[0] != '\0')
|
||||
choice = 1;
|
||||
choice = YES;
|
||||
else {
|
||||
if (ISSET(SAVE_ON_EXIT))
|
||||
warn_and_briefly_pause(_("No file name"));
|
||||
|
||||
choice = do_yesno_prompt(FALSE, _("Save modified buffer? "));
|
||||
choice = ask_user(YESORNO, _("Save modified buffer? "));
|
||||
}
|
||||
|
||||
/* When not saving, or the save succeeds, close the buffer. */
|
||||
if (choice == 0 || (choice == 1 && write_it_out(TRUE, TRUE) > 0))
|
||||
if (choice == NO || (choice == YES && write_it_out(TRUE, TRUE) > 0))
|
||||
close_and_go();
|
||||
else if (choice != 1)
|
||||
else if (choice != YES)
|
||||
statusbar(_("Cancelled"));
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ void emergency_save(const char *filename)
|
||||
fprintf(stderr, _("\nToo many .save files\n"));
|
||||
else if (write_file(targetname, NULL, SPECIAL, OVERWRITE, NONOTES)) {
|
||||
fprintf(stderr, _("\nBuffer written to %s\n"), targetname);
|
||||
#ifndef NANO_TINY
|
||||
#if !defined(NANO_TINY) && defined(HAVE_CHMOD) && defined(HAVE_CHOWN)
|
||||
/* Try to chmod/chown the saved file to the values of the original file,
|
||||
* but ignore any failure as we are in a hurry to get out. */
|
||||
if (openfile->statinfo) {
|
||||
@@ -403,11 +403,11 @@ void die(const char *msg, ...)
|
||||
void window_init(void)
|
||||
{
|
||||
/* When resizing, first delete the existing windows. */
|
||||
if (edit != NULL) {
|
||||
if (midwin != NULL) {
|
||||
if (topwin != NULL)
|
||||
delwin(topwin);
|
||||
delwin(edit);
|
||||
delwin(bottomwin);
|
||||
delwin(midwin);
|
||||
delwin(footwin);
|
||||
}
|
||||
|
||||
topwin = NULL;
|
||||
@@ -417,8 +417,8 @@ void window_init(void)
|
||||
editwinrows = (ISSET(ZERO) ? LINES : 1);
|
||||
/* Set up two subwindows. If the terminal is just one line,
|
||||
* edit window and status-bar window will cover each other. */
|
||||
edit = newwin(editwinrows, COLS, 0, 0);
|
||||
bottomwin = newwin(1, COLS, LINES - 1, 0);
|
||||
midwin = newwin(editwinrows, COLS, 0, 0);
|
||||
footwin = newwin(1, COLS, LINES - 1, 0);
|
||||
} else {
|
||||
int toprows = ((ISSET(EMPTY_LINE) && LINES > 6) ? 2 : 1);
|
||||
int bottomrows = ((ISSET(NO_HELP) || LINES < 6) ? 1 : 3);
|
||||
@@ -432,17 +432,17 @@ void window_init(void)
|
||||
/* Set up the normal three subwindows. */
|
||||
if (toprows > 0)
|
||||
topwin = newwin(toprows, COLS, 0, 0);
|
||||
edit = newwin(editwinrows, COLS, toprows, 0);
|
||||
bottomwin = newwin(bottomrows, COLS, LINES - bottomrows, 0);
|
||||
midwin = newwin(editwinrows, COLS, toprows, 0);
|
||||
footwin = newwin(bottomrows, COLS, LINES - bottomrows, 0);
|
||||
}
|
||||
|
||||
/* In case the terminal shrunk, make sure the status line is clear. */
|
||||
wnoutrefresh(bottomwin);
|
||||
wnoutrefresh(footwin);
|
||||
|
||||
/* When not disabled, turn escape-sequence translation on. */
|
||||
if (!ISSET(RAW_SEQUENCES)) {
|
||||
keypad(edit, TRUE);
|
||||
keypad(bottomwin, TRUE);
|
||||
keypad(midwin, TRUE);
|
||||
keypad(footwin, TRUE);
|
||||
}
|
||||
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
@@ -670,8 +670,8 @@ void version(void)
|
||||
printf(_(" GNU nano, version %s\n"), VERSION);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
printf(" (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.\n");
|
||||
printf(_(" (C) 2014-%s the contributors to nano\n"), "2021");
|
||||
printf(" (C) 1999-2011, 2013-2022 Free Software Foundation, Inc.\n");
|
||||
printf(_(" (C) 2014-%s the contributors to nano\n"), "2022");
|
||||
#endif
|
||||
printf(_(" Compiled options:"));
|
||||
|
||||
@@ -894,10 +894,11 @@ void signal_init(void)
|
||||
sigaction(SIGTERM, &deed, NULL);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
#ifdef SIGWINCH
|
||||
/* Trap SIGWINCH because we want to handle window resizes. */
|
||||
deed.sa_handler = handle_sigwinch;
|
||||
sigaction(SIGWINCH, &deed, NULL);
|
||||
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
/* Prevent the suspend handler from getting interrupted. */
|
||||
sigfillset(&deed.sa_mask);
|
||||
@@ -998,11 +999,13 @@ void continue_nano(int signal)
|
||||
/* Block or unblock the SIGWINCH signal, depending on the blockit parameter. */
|
||||
void block_sigwinch(bool blockit)
|
||||
{
|
||||
#ifdef SIGWINCH
|
||||
sigset_t winch;
|
||||
|
||||
sigemptyset(&winch);
|
||||
sigaddset(&winch, SIGWINCH);
|
||||
sigprocmask(blockit ? SIG_BLOCK : SIG_UNBLOCK, &winch, NULL);
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (the_window_resized)
|
||||
@@ -1022,38 +1025,19 @@ void handle_sigwinch(int signal)
|
||||
/* Reinitialize and redraw the screen completely. */
|
||||
void regenerate_screen(void)
|
||||
{
|
||||
const char *tty = ttyname(0);
|
||||
int fd, result = 0;
|
||||
struct winsize win;
|
||||
|
||||
/* Reset the trigger. */
|
||||
the_window_resized = FALSE;
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
fd = open(tty, O_RDWR);
|
||||
if (fd == -1)
|
||||
return;
|
||||
result = ioctl(fd, TIOCGWINSZ, &win);
|
||||
close(fd);
|
||||
if (result == -1)
|
||||
return;
|
||||
/* Leave and immediately reenter curses mode, so that ncurses notices
|
||||
* the new screen dimensions and sets LINES and COLS accordingly. */
|
||||
endwin();
|
||||
refresh();
|
||||
|
||||
/* We could check whether COLS or LINES changed, and return otherwise,
|
||||
* but it seems curses does not always update these global variables. */
|
||||
#ifdef REDEFINING_MACROS_OK
|
||||
COLS = win.ws_col;
|
||||
LINES = win.ws_row;
|
||||
#endif
|
||||
thebar = (ISSET(INDICATOR) && LINES > 5 && COLS > 9) ? 1 : 0;
|
||||
bardata = nrealloc(bardata, LINES * sizeof(int));
|
||||
|
||||
editwincols = COLS - margin - thebar;
|
||||
|
||||
/* Do as the website suggests: leave and immediately reenter curses mode. */
|
||||
endwin();
|
||||
doupdate();
|
||||
|
||||
/* Put the terminal in the desired state again, and
|
||||
* recreate the subwindows with their (new) sizes. */
|
||||
terminal_init();
|
||||
@@ -1325,7 +1309,7 @@ int do_mouse(void)
|
||||
return retval;
|
||||
|
||||
/* If the click was in the edit window, put the cursor in that spot. */
|
||||
if (wmouse_trafo(edit, &click_row, &click_col, FALSE)) {
|
||||
if (wmouse_trafo(midwin, &click_row, &click_col, FALSE)) {
|
||||
linestruct *current_save = openfile->current;
|
||||
ssize_t row_count = click_row - openfile->current_y;
|
||||
size_t leftedge;
|
||||
@@ -1408,7 +1392,7 @@ void suck_up_input_and_paste_it(void)
|
||||
cutbuffer = line;
|
||||
|
||||
while (bracketed_paste) {
|
||||
int input = get_kbinput(edit, BLIND);
|
||||
int input = get_kbinput(midwin, BLIND);
|
||||
|
||||
if (input == '\r' || input == '\n') {
|
||||
line->next = make_new_node(line);
|
||||
@@ -1540,7 +1524,7 @@ void process_a_keystroke(void)
|
||||
const keystruct *shortcut;
|
||||
|
||||
/* Read in a keystroke, and show the cursor while waiting. */
|
||||
input = get_kbinput(edit, VISIBLE);
|
||||
input = get_kbinput(midwin, VISIBLE);
|
||||
|
||||
lastmessage = VACUUM;
|
||||
|
||||
@@ -1553,7 +1537,7 @@ void process_a_keystroke(void)
|
||||
/* If the user clicked on a shortcut, read in the key code that it was
|
||||
* converted into. Else the click has been handled or was invalid. */
|
||||
if (do_mouse() == 1)
|
||||
input = get_kbinput(edit, BLIND);
|
||||
input = get_kbinput(midwin, BLIND);
|
||||
else
|
||||
return;
|
||||
}
|
||||
@@ -1583,7 +1567,7 @@ void process_a_keystroke(void)
|
||||
|
||||
/* If we have a command, or if there aren't any other key codes waiting,
|
||||
* it's time to insert the gathered bytes into the edit buffer. */
|
||||
if ((shortcut || get_key_buffer_len() == 0) && puddle != NULL) {
|
||||
if ((shortcut || waiting_keycodes() == 0) && puddle != NULL) {
|
||||
puddle[depth] = '\0';
|
||||
|
||||
inject(puddle, depth);
|
||||
@@ -1805,10 +1789,12 @@ int main(int argc, char **argv)
|
||||
/* Back up the terminal settings so that they can be restored. */
|
||||
tcgetattr(STDIN_FILENO, &original_state);
|
||||
|
||||
#if defined(F_GETFL) && defined(F_SETFL)
|
||||
/* Get the state of standard input and ensure it uses blocking mode. */
|
||||
stdin_flags = fcntl(STDIN_FILENO, F_GETFL, 0);
|
||||
if (stdin_flags != -1)
|
||||
fcntl(STDIN_FILENO, F_SETFL, stdin_flags & ~O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* If setting the locale is successful and it uses UTF-8, we will
|
||||
@@ -2091,7 +2077,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Curses needs TERM; if it is unset, try falling back to a VT220. */
|
||||
if (getenv("TERM") == NULL)
|
||||
setenv("TERM", "vt220", 0);
|
||||
putenv("TERM=vt220");
|
||||
|
||||
/* Enter into curses mode. Abort if this fails. */
|
||||
if (initscr() == NULL)
|
||||
@@ -2101,6 +2087,9 @@ int main(int argc, char **argv)
|
||||
/* If the terminal can do colors, tell ncurses to switch them on. */
|
||||
if (has_colors())
|
||||
start_color();
|
||||
|
||||
/* When requested, suppress the default spotlight and error colors. */
|
||||
rescind_colors = (getenv("NO_COLOR") != NULL);
|
||||
#endif
|
||||
|
||||
/* Set up the function and shortcut lists. This needs to be done
|
||||
@@ -2545,7 +2534,7 @@ int main(int argc, char **argv)
|
||||
confirm_margin();
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
if (on_a_vt && get_key_buffer_len() == 0)
|
||||
if (on_a_vt && waiting_keycodes() == 0)
|
||||
mute_modifiers = FALSE;
|
||||
#endif
|
||||
if (currmenu != MMAIN)
|
||||
@@ -2559,7 +2548,7 @@ int main(int argc, char **argv)
|
||||
/* Update the displayed current cursor position only when there
|
||||
* is no message and no keys are waiting in the input buffer. */
|
||||
if (ISSET(CONSTANT_SHOW) && lastmessage == VACUUM && LINES > 1 &&
|
||||
!ISSET(ZERO) && get_key_buffer_len() == 0)
|
||||
!ISSET(ZERO) && waiting_keycodes() == 0)
|
||||
report_cursor_position();
|
||||
|
||||
as_an_at = TRUE;
|
||||
@@ -2575,13 +2564,13 @@ int main(int argc, char **argv)
|
||||
if (ISSET(ZERO) && lastmessage > HUSH) {
|
||||
if (openfile->current_y == editwinrows - 1 && LINES > 1) {
|
||||
edit_scroll(FORWARD);
|
||||
wnoutrefresh(edit);
|
||||
wnoutrefresh(midwin);
|
||||
}
|
||||
wredrawln(bottomwin, 0 ,1);
|
||||
wnoutrefresh(bottomwin);
|
||||
wredrawln(footwin, 0, 1);
|
||||
wnoutrefresh(footwin);
|
||||
place_the_cursor();
|
||||
} else if (ISSET(ZERO) && lastmessage > VACUUM)
|
||||
wredrawln(edit, editwinrows - 1, 1);
|
||||
wredrawln(midwin, editwinrows - 1, 1);
|
||||
#endif
|
||||
|
||||
errno = 0;
|
||||
|
||||
146
src/prompt.c
146
src/prompt.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* prompt.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016, 2018, 2020 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -157,15 +157,27 @@ void do_statusbar_backspace(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Zap some or all text from the answer. */
|
||||
void do_statusbar_cut_text(void)
|
||||
/* Zap the part of the answer after the cursor, or the whole answer. */
|
||||
void lop_the_answer(void)
|
||||
{
|
||||
if (!ISSET(CUT_FROM_CURSOR))
|
||||
if (answer[typing_x] == '\0')
|
||||
typing_x = 0;
|
||||
|
||||
answer[typing_x] = '\0';
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Copy the current answer (if any) into the cutbuffer. */
|
||||
void copy_the_answer(void)
|
||||
{
|
||||
if (*answer) {
|
||||
free_lines(cutbuffer);
|
||||
cutbuffer = make_new_node(NULL);
|
||||
cutbuffer->data = copy_of(answer);
|
||||
typing_x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Paste the first line of the cutbuffer into the current answer. */
|
||||
void paste_into_answer(void)
|
||||
{
|
||||
@@ -182,6 +194,7 @@ void paste_into_answer(void)
|
||||
answer = fusion;
|
||||
typing_x += pastelen;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MOUSE
|
||||
/* Handle a mouse click on the status-bar prompt or the shortcut list. */
|
||||
@@ -191,7 +204,7 @@ int do_statusbar_mouse(void)
|
||||
int retval = get_mouseinput(&click_row, &click_col, TRUE);
|
||||
|
||||
/* We can click on the status-bar window text to move the cursor. */
|
||||
if (retval == 0 && wmouse_trafo(bottomwin, &click_row, &click_col, FALSE)) {
|
||||
if (retval == 0 && wmouse_trafo(footwin, &click_row, &click_col, FALSE)) {
|
||||
size_t start_col = breadth(prompt) + 2;
|
||||
|
||||
/* Move to where the click occurred. */
|
||||
@@ -216,7 +229,7 @@ void inject_into_answer(char *burst, size_t count)
|
||||
answer = nrealloc(answer, strlen(answer) + count + 1);
|
||||
memmove(answer + typing_x + count, answer + typing_x,
|
||||
strlen(answer) - typing_x + 1);
|
||||
strncpy(answer + typing_x, burst , count);
|
||||
strncpy(answer + typing_x, burst, count);
|
||||
|
||||
typing_x += count;
|
||||
}
|
||||
@@ -227,7 +240,7 @@ void do_statusbar_verbatim_input(void)
|
||||
size_t count = 1;
|
||||
char *bytes;
|
||||
|
||||
bytes = get_verbatim_kbinput(bottomwin, &count);
|
||||
bytes = get_verbatim_kbinput(footwin, &count);
|
||||
|
||||
if (0 < count && count < 999)
|
||||
inject_into_answer(bytes, count);
|
||||
@@ -253,7 +266,7 @@ int do_statusbar_input(bool *finished)
|
||||
*finished = FALSE;
|
||||
|
||||
/* Read in a character. */
|
||||
input = get_kbinput(bottomwin, VISIBLE);
|
||||
input = get_kbinput(footwin, VISIBLE);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (input == KEY_WINCH)
|
||||
@@ -265,7 +278,7 @@ int do_statusbar_input(bool *finished)
|
||||
* shortcut character. */
|
||||
if (input == KEY_MOUSE) {
|
||||
if (do_statusbar_mouse() == 1)
|
||||
input = get_kbinput(bottomwin, BLIND);
|
||||
input = get_kbinput(footwin, BLIND);
|
||||
else
|
||||
return ERR;
|
||||
}
|
||||
@@ -290,7 +303,7 @@ int do_statusbar_input(bool *finished)
|
||||
/* If we got a shortcut, or if there aren't any other keystrokes waiting,
|
||||
* it's time to insert all characters in the input buffer (if not empty)
|
||||
* into the answer, and then clear the input buffer. */
|
||||
if ((shortcut || get_key_buffer_len() == 0) && puddle != NULL) {
|
||||
if ((shortcut || waiting_keycodes() == 0) && puddle != NULL) {
|
||||
puddle[depth] = '\0';
|
||||
|
||||
inject_into_answer(puddle, depth);
|
||||
@@ -327,10 +340,10 @@ int do_statusbar_input(bool *finished)
|
||||
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE &&
|
||||
openfile->filename[0] != '\0' &&
|
||||
(shortcut->func == do_verbatim_input ||
|
||||
shortcut->func == cut_text ||
|
||||
shortcut->func == paste_text ||
|
||||
shortcut->func == do_delete ||
|
||||
shortcut->func == do_backspace))
|
||||
shortcut->func == do_backspace ||
|
||||
shortcut->func == cut_text ||
|
||||
shortcut->func == paste_text))
|
||||
;
|
||||
#ifdef ENABLE_NANORC
|
||||
else if (shortcut->func == (functionptrtype)implant)
|
||||
@@ -338,16 +351,21 @@ int do_statusbar_input(bool *finished)
|
||||
#endif
|
||||
else if (shortcut->func == do_verbatim_input)
|
||||
do_statusbar_verbatim_input();
|
||||
else if (shortcut->func == cut_text)
|
||||
do_statusbar_cut_text();
|
||||
else if (shortcut->func == do_delete)
|
||||
do_statusbar_delete();
|
||||
else if (shortcut->func == do_backspace)
|
||||
do_statusbar_backspace();
|
||||
else if (shortcut->func == cut_text)
|
||||
lop_the_answer();
|
||||
#ifndef NANO_TINY
|
||||
else if (shortcut->func == copy_text)
|
||||
copy_the_answer();
|
||||
else if (shortcut->func == paste_text) {
|
||||
if (cutbuffer != NULL)
|
||||
paste_into_answer();
|
||||
} else {
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
/* Handle any other shortcut in the current menu, setting finished
|
||||
* to TRUE to indicate that we're done after running or trying to
|
||||
* run its associated function. */
|
||||
@@ -392,33 +410,33 @@ void draw_the_promptbar(void)
|
||||
end_page = get_statusbar_page_start(base, base + breadth(answer) - 1);
|
||||
|
||||
/* Color the prompt bar over its full width. */
|
||||
wattron(bottomwin, interface_color_pair[PROMPT_BAR]);
|
||||
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
|
||||
wattron(footwin, interface_color_pair[PROMPT_BAR]);
|
||||
mvwprintw(footwin, 0, 0, "%*s", COLS, " ");
|
||||
|
||||
mvwaddstr(bottomwin, 0, 0, prompt);
|
||||
waddch(bottomwin, ':');
|
||||
waddch(bottomwin, (the_page == 0) ? ' ' : '<');
|
||||
mvwaddstr(footwin, 0, 0, prompt);
|
||||
waddch(footwin, ':');
|
||||
waddch(footwin, (the_page == 0) ? ' ' : '<');
|
||||
|
||||
expanded = display_string(answer, the_page, COLS - base, FALSE, TRUE);
|
||||
waddstr(bottomwin, expanded);
|
||||
waddstr(footwin, expanded);
|
||||
free(expanded);
|
||||
|
||||
if (the_page < end_page && base + breadth(answer) - the_page > COLS)
|
||||
mvwaddch(bottomwin, 0, COLS - 1, '>');
|
||||
mvwaddch(footwin, 0, COLS - 1, '>');
|
||||
|
||||
wattroff(bottomwin, interface_color_pair[PROMPT_BAR]);
|
||||
wattroff(footwin, interface_color_pair[PROMPT_BAR]);
|
||||
|
||||
#if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH < 20210220)
|
||||
/* Work around a cursor-misplacement bug -- https://sv.gnu.org/bugs/?59808. */
|
||||
if (ISSET(NO_HELP)) {
|
||||
wmove(bottomwin, 0, 0);
|
||||
wrefresh(bottomwin);
|
||||
wmove(footwin, 0, 0);
|
||||
wrefresh(footwin);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Place the cursor at the right spot. */
|
||||
wmove(bottomwin, 0, column - the_page);
|
||||
wnoutrefresh(bottomwin);
|
||||
wmove(footwin, 0, column - the_page);
|
||||
wnoutrefresh(footwin);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -635,12 +653,14 @@ int do_prompt(int menu, const char *provided, linestruct **history_list,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Ask a simple Yes/No (and optionally All) question, specified in msg,
|
||||
* on the status bar. Return 1 for Yes, 0 for No, 2 for All (if all is
|
||||
* TRUE when passed in), and -1 for Cancel. */
|
||||
int do_yesno_prompt(bool all, const char *msg)
|
||||
#define UNDECIDED -2
|
||||
|
||||
/* Ask a simple Yes/No (and optionally All) question on the status bar
|
||||
* and return the choice -- either YES or NO or ALL or CANCEL. */
|
||||
int ask_user(bool withall, const char *question)
|
||||
{
|
||||
int choice = -2, width = 16;
|
||||
int choice = UNDECIDED;
|
||||
int width = 16;
|
||||
/* TRANSLATORS: For the next three strings, specify the starting letters
|
||||
* of the translations for "Yes"/"No"/"All". The first letter of each of
|
||||
* these strings MUST be a single-byte letter; others may be multi-byte. */
|
||||
@@ -648,7 +668,7 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
const char *nostr = _("Nn");
|
||||
const char *allstr = _("Aa");
|
||||
|
||||
while (choice == -2) {
|
||||
while (choice == UNDECIDED) {
|
||||
#ifdef ENABLE_NLS
|
||||
char letter[MAXCHARLEN + 1];
|
||||
int index = 0;
|
||||
@@ -669,34 +689,34 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
|
||||
/* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */
|
||||
sprintf(shortstr, " %c", yesstr[0]);
|
||||
wmove(bottomwin, 1, 0);
|
||||
wmove(footwin, 1, 0);
|
||||
post_one_key(shortstr, _("Yes"), width);
|
||||
|
||||
shortstr[1] = nostr[0];
|
||||
wmove(bottomwin, 2, 0);
|
||||
wmove(footwin, 2, 0);
|
||||
post_one_key(shortstr, _("No"), width);
|
||||
|
||||
if (all) {
|
||||
if (withall) {
|
||||
shortstr[1] = allstr[0];
|
||||
wmove(bottomwin, 1, width);
|
||||
wmove(footwin, 1, width);
|
||||
post_one_key(shortstr, _("All"), width);
|
||||
}
|
||||
|
||||
wmove(bottomwin, 2, width);
|
||||
wmove(footwin, 2, width);
|
||||
post_one_key(cancelshortcut->keystr, _("Cancel"), width);
|
||||
}
|
||||
|
||||
/* Color the prompt bar over its full width and display the question. */
|
||||
wattron(bottomwin, interface_color_pair[PROMPT_BAR]);
|
||||
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
|
||||
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
|
||||
wattroff(bottomwin, interface_color_pair[PROMPT_BAR]);
|
||||
wnoutrefresh(bottomwin);
|
||||
wattron(footwin, interface_color_pair[PROMPT_BAR]);
|
||||
mvwprintw(footwin, 0, 0, "%*s", COLS, " ");
|
||||
mvwaddnstr(footwin, 0, 0, question, actual_x(question, COLS - 1));
|
||||
wattroff(footwin, interface_color_pair[PROMPT_BAR]);
|
||||
wnoutrefresh(footwin);
|
||||
|
||||
currmenu = MYESNO;
|
||||
|
||||
/* When not replacing, show the cursor while waiting for a key. */
|
||||
kbinput = get_kbinput(bottomwin, !all);
|
||||
kbinput = get_kbinput(footwin, !withall);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH)
|
||||
@@ -704,7 +724,7 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
|
||||
/* Accept the first character of an external paste. */
|
||||
if (bracketed_paste && kbinput == BRACKETED_PASTE_MARKER)
|
||||
kbinput = get_kbinput(bottomwin, BLIND);
|
||||
kbinput = get_kbinput(footwin, BLIND);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
@@ -715,41 +735,41 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
if (using_utf8() && 0xC0 <= kbinput && kbinput <= 0xF7) {
|
||||
int extras = (kbinput / 16) % 4 + (kbinput <= 0xCF ? 1 : 0);
|
||||
|
||||
while (extras <= get_key_buffer_len() && extras-- > 0)
|
||||
letter[index++] = (unsigned char)get_kbinput(bottomwin, !all);
|
||||
while (extras <= waiting_keycodes() && extras-- > 0)
|
||||
letter[index++] = (unsigned char)get_kbinput(footwin, !withall);
|
||||
}
|
||||
#endif
|
||||
letter[index] = '\0';
|
||||
|
||||
/* See if the typed letter is in the Yes, No, or All strings. */
|
||||
if (strstr(yesstr, letter) != NULL)
|
||||
choice = 1;
|
||||
choice = YES;
|
||||
else if (strstr(nostr, letter) != NULL)
|
||||
choice = 0;
|
||||
else if (all && strstr(allstr, letter) != NULL)
|
||||
choice = 2;
|
||||
choice = NO;
|
||||
else if (withall && strstr(allstr, letter) != NULL)
|
||||
choice = ALL;
|
||||
else
|
||||
#endif /* ENABLE_NLS */
|
||||
if (strchr("Yy", kbinput) != NULL)
|
||||
choice = 1;
|
||||
choice = YES;
|
||||
else if (strchr("Nn", kbinput) != NULL)
|
||||
choice = 0;
|
||||
else if (all && strchr("Aa", kbinput) != NULL)
|
||||
choice = 2;
|
||||
choice = NO;
|
||||
else if (withall && strchr("Aa", kbinput) != NULL)
|
||||
choice = ALL;
|
||||
else if (func_from_key(&kbinput) == do_cancel)
|
||||
choice = -1;
|
||||
choice = CANCEL;
|
||||
/* Interpret ^N and ^Q as "No", to allow exiting in anger. */
|
||||
else if (kbinput == '\x0E' || kbinput == '\x11')
|
||||
choice = 0;
|
||||
choice = NO;
|
||||
/* And interpret ^Y as "Yes". */
|
||||
else if (kbinput == '\x19')
|
||||
choice = 1;
|
||||
choice = YES;
|
||||
#ifdef ENABLE_MOUSE
|
||||
else if (kbinput == KEY_MOUSE) {
|
||||
int mouse_x, mouse_y;
|
||||
/* We can click on the Yes/No/All shortcuts to select an answer. */
|
||||
if (get_mouseinput(&mouse_y, &mouse_x, FALSE) == 0 &&
|
||||
wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE) &&
|
||||
wmouse_trafo(footwin, &mouse_y, &mouse_x, FALSE) &&
|
||||
mouse_x < (width * 2) && mouse_y > 0) {
|
||||
int x = mouse_x / width;
|
||||
int y = mouse_y - 1;
|
||||
@@ -757,8 +777,8 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
/* x == 0 means Yes or No, y == 0 means Yes or All. */
|
||||
choice = -2 * x * y + x - y + 1;
|
||||
|
||||
if (choice == 2 && !all)
|
||||
choice = -2;
|
||||
if (choice == ALL && !withall)
|
||||
choice = UNDECIDED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -780,7 +800,7 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
#ifndef NANO_TINY
|
||||
/* Ignore the rest of an external paste. */
|
||||
while (bracketed_paste)
|
||||
kbinput = get_kbinput(bottomwin, BLIND);
|
||||
kbinput = get_kbinput(footwin, BLIND);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* prototypes.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -87,8 +87,8 @@ extern size_t wrap_at;
|
||||
#endif
|
||||
|
||||
extern WINDOW *topwin;
|
||||
extern WINDOW *edit;
|
||||
extern WINDOW *bottomwin;
|
||||
extern WINDOW *midwin;
|
||||
extern WINDOW *footwin;
|
||||
extern int editwinrows;
|
||||
extern int editwincols;
|
||||
extern int margin;
|
||||
@@ -141,6 +141,9 @@ extern char *alt_speller;
|
||||
extern syntaxtype *syntaxes;
|
||||
extern char *syntaxstr;
|
||||
extern bool have_palette;
|
||||
extern bool rescind_colors;
|
||||
extern bool perturbed;
|
||||
extern bool recook;
|
||||
#endif
|
||||
|
||||
extern bool refresh_needed;
|
||||
@@ -430,7 +433,7 @@ void put_cursor_at_end_of_answer(void);
|
||||
void add_or_remove_pipe_symbol_from_answer(void);
|
||||
int do_prompt(int menu, const char *provided, linestruct **history_list,
|
||||
void (*refresh_func)(void), const char *msg, ...);
|
||||
int do_yesno_prompt(bool all, const char *msg);
|
||||
int ask_user(bool withall, const char *question);
|
||||
|
||||
/* Most functions in rcfile.c. */
|
||||
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
|
||||
@@ -568,11 +571,11 @@ linestruct *line_from_number(ssize_t number);
|
||||
/* Most functions in winio.c. */
|
||||
void record_macro(void);
|
||||
void run_macro(void);
|
||||
size_t get_key_buffer_len(void);
|
||||
size_t waiting_keycodes(void);
|
||||
#ifdef ENABLE_NANORC
|
||||
void implant(const char *string);
|
||||
#endif
|
||||
int parse_kbinput(WINDOW *win);
|
||||
int get_input(WINDOW *win);
|
||||
int get_kbinput(WINDOW *win, bool showcursor);
|
||||
char *get_verbatim_kbinput(WINDOW *win, size_t *count);
|
||||
#ifdef ENABLE_MOUSE
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/**************************************************************************
|
||||
* rcfile.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2001-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014 Mike Frysinger *
|
||||
* Copyright (C) 2019 Brand Huntsman *
|
||||
* Copyright (C) 2014-2020 Benno Schulenberg *
|
||||
* Copyright (C) 2014-2021 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 *
|
||||
|
||||
58
src/search.c
58
src/search.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* search.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2015-2020 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -65,6 +65,9 @@ void tidy_up_after_search(void)
|
||||
if (openfile->mark)
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
#ifdef ENABLE_COLOR
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Prepare the prompt and ask the user what to search for. Keep looping
|
||||
@@ -186,7 +189,7 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
/* The time we last looked at the keyboard. */
|
||||
|
||||
/* Set non-blocking input so that we can just peek for a Cancel. */
|
||||
nodelay(edit, TRUE);
|
||||
nodelay(midwin, TRUE);
|
||||
|
||||
if (begin == NULL)
|
||||
came_full_circle = FALSE;
|
||||
@@ -226,14 +229,14 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
#ifndef NANO_TINY
|
||||
if (the_window_resized) {
|
||||
regenerate_screen();
|
||||
nodelay(edit, TRUE);
|
||||
nodelay(midwin, TRUE);
|
||||
statusbar(_("Searching..."));
|
||||
feedback = 1;
|
||||
}
|
||||
#endif
|
||||
/* If we're back at the beginning, then there is no needle. */
|
||||
if (came_full_circle) {
|
||||
nodelay(edit, FALSE);
|
||||
nodelay(midwin, FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -244,7 +247,7 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
* but stop when spell-checking or replacing in a region. */
|
||||
if (line == NULL) {
|
||||
if (whole_word_only || modus == INREGION) {
|
||||
nodelay(edit, FALSE);
|
||||
nodelay(midwin, FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -268,7 +271,7 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
|
||||
/* Glance at the keyboard once every second, to check for a Cancel. */
|
||||
if (time(NULL) - lastkbcheck > 0) {
|
||||
int input = wgetch(edit);
|
||||
int input = wgetch(midwin);
|
||||
|
||||
lastkbcheck = time(NULL);
|
||||
|
||||
@@ -276,7 +279,7 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
while (input != ERR) {
|
||||
if (input == ESC_CODE) {
|
||||
napms(20);
|
||||
input = wgetch(edit);
|
||||
input = wgetch(midwin);
|
||||
meta_key = TRUE;
|
||||
} else
|
||||
meta_key = FALSE;
|
||||
@@ -289,12 +292,12 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
statusbar(_("Cancelled"));
|
||||
/* Clear out the key buffer (in case a macro is running). */
|
||||
while (input != ERR)
|
||||
input = parse_kbinput(NULL);
|
||||
nodelay(edit, FALSE);
|
||||
input = get_input(NULL);
|
||||
nodelay(midwin, FALSE);
|
||||
return -2;
|
||||
}
|
||||
|
||||
input = wgetch(edit);
|
||||
input = wgetch(midwin);
|
||||
}
|
||||
|
||||
if (++feedback > 0)
|
||||
@@ -306,7 +309,7 @@ int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
|
||||
found_x = found - line->data;
|
||||
|
||||
nodelay(edit, FALSE);
|
||||
nodelay(midwin, FALSE);
|
||||
|
||||
/* Ensure that the found occurrence is not beyond the starting x. */
|
||||
if (came_full_circle && ((!ISSET(BACKWARDS_SEARCH) && (found_x > begin_x ||
|
||||
@@ -553,7 +556,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
came_full_circle = FALSE;
|
||||
|
||||
while (TRUE) {
|
||||
int choice = 0;
|
||||
int choice = NO;
|
||||
int result = findnextstr(needle, whole_word_only, modus,
|
||||
&match_len, skipone, real_current, *real_current_x);
|
||||
|
||||
@@ -589,21 +592,21 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
edit_refresh();
|
||||
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
choice = do_yesno_prompt(TRUE, _("Replace this instance?"));
|
||||
choice = ask_user(YESORALLORNO, _("Replace this instance?"));
|
||||
|
||||
spotlighted = FALSE;
|
||||
|
||||
if (choice == -1) /* The replacing was cancelled. */
|
||||
if (choice == CANCEL)
|
||||
break;
|
||||
else if (choice == 2)
|
||||
replaceall = TRUE;
|
||||
|
||||
replaceall = (choice == ALL);
|
||||
|
||||
/* When "No" or moving backwards, the search routine should
|
||||
* first move one character further before continuing. */
|
||||
skipone = (choice == 0 || ISSET(BACKWARDS_SEARCH));
|
||||
}
|
||||
|
||||
if (choice == 1 || replaceall) { /* Yes, replace it. */
|
||||
if (choice == YES || replaceall) {
|
||||
size_t length_change;
|
||||
char *altered;
|
||||
|
||||
@@ -657,6 +660,10 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
free(openfile->current->data);
|
||||
openfile->current->data = altered;
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
check_the_multis(openfile->current);
|
||||
refresh_needed = FALSE;
|
||||
#endif
|
||||
set_modified();
|
||||
as_an_at = TRUE;
|
||||
numreplaced++;
|
||||
@@ -732,6 +739,12 @@ void ask_for_and_do_replacements(void)
|
||||
/* Go to the specified line and x position. */
|
||||
void goto_line_posx(ssize_t line, size_t pos_x)
|
||||
{
|
||||
#ifdef ENABLE_COLOR
|
||||
if (line > openfile->edittop->lineno + editwinrows ||
|
||||
(ISSET(SOFTWRAP) && line > openfile->current->lineno))
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
|
||||
for (openfile->current = openfile->filetop; line > 1 &&
|
||||
openfile->current != openfile->filebot; line--)
|
||||
openfile->current = openfile->current->next;
|
||||
@@ -790,6 +803,12 @@ void goto_line_and_column(ssize_t line, ssize_t column, bool retain_answer,
|
||||
if (line < 1)
|
||||
line = 1;
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
if (line > openfile->edittop->lineno + editwinrows ||
|
||||
(ISSET(SOFTWRAP) && line > openfile->current->lineno))
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
|
||||
/* Iterate to the requested line. */
|
||||
for (openfile->current = openfile->filetop; line > 1 &&
|
||||
openfile->current != openfile->filebot; line--)
|
||||
@@ -992,6 +1011,11 @@ void go_to_and_confirm(linestruct *line)
|
||||
if (line != openfile->current) {
|
||||
openfile->current = line;
|
||||
openfile->current_x = 0;
|
||||
#ifdef ENABLE_COLOR
|
||||
if (line->lineno > openfile->edittop->lineno + editwinrows ||
|
||||
(ISSET(SOFTWRAP) && line->lineno > was_current->lineno))
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
edit_redraw(was_current, CENTERING);
|
||||
statusbar(_("Jumped to anchor"));
|
||||
} else if (openfile->current->has_anchor)
|
||||
|
||||
145
src/text.c
145
src/text.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* text.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2015 Mark Majeres *
|
||||
* Copyright (C) 2016 Mike Scalora *
|
||||
* Copyright (C) 2016 Sumedh Pendurkar *
|
||||
@@ -558,7 +558,8 @@ void do_undo(void)
|
||||
* and the nonewlines flag isn't set, do not re-add a newline that
|
||||
* wasn't actually deleted; just position the cursor. */
|
||||
if ((u->xflags & WAS_BACKSPACE_AT_EOF) && !ISSET(NO_NEWLINES)) {
|
||||
goto_line_posx(openfile->filebot->lineno, 0);
|
||||
openfile->current = openfile->filebot;
|
||||
openfile->current_x = 0;
|
||||
break;
|
||||
}
|
||||
line->data[u->tail_x] = '\0';
|
||||
@@ -665,6 +666,13 @@ void do_undo(void)
|
||||
|
||||
openfile->totsize = u->wassize;
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
if (u->type <= REPLACE)
|
||||
check_the_multis(openfile->current);
|
||||
else if (u->type == INSERT)
|
||||
perturbed = TRUE;
|
||||
#endif
|
||||
|
||||
/* When at the point where the buffer was last saved, unset "Modified". */
|
||||
if (openfile->current_undo == openfile->last_saved) {
|
||||
openfile->modified = FALSE;
|
||||
@@ -825,6 +833,13 @@ void do_redo(void)
|
||||
|
||||
openfile->totsize = u->newsize;
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
if (u->type <= REPLACE)
|
||||
check_the_multis(openfile->current);
|
||||
else if (u->type == INSERT)
|
||||
recook = TRUE;
|
||||
#endif
|
||||
|
||||
/* When at the point where the buffer was last saved, unset "Modified". */
|
||||
if (openfile->current_undo == openfile->last_saved) {
|
||||
openfile->modified = FALSE;
|
||||
@@ -1177,7 +1192,8 @@ void update_undo(undo_type action)
|
||||
else if (cutbuffer != NULL) {
|
||||
free_lines(u->cutbuffer);
|
||||
u->cutbuffer = copy_buffer(cutbuffer);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
if (!(u->xflags & MARK_WAS_SET)) {
|
||||
linestruct *bottomline = u->cutbuffer;
|
||||
size_t count = 0;
|
||||
@@ -1745,6 +1761,8 @@ void justify_text(bool whole_buffer)
|
||||
/* The leading part for lines after the first one. */
|
||||
size_t secondary_len = 0;
|
||||
/* The length of that later lead. */
|
||||
ssize_t was_the_linenumber = openfile->current->lineno;
|
||||
/* The line to return to after a full justification. */
|
||||
|
||||
/* TRANSLATORS: This one goes with Undid/Redid messages. */
|
||||
add_undo(COUPLE_BEGIN, N_("justification"));
|
||||
@@ -1961,7 +1979,8 @@ void justify_text(bool whole_buffer)
|
||||
openfile->current_x = openfile->mark_x;
|
||||
openfile->mark = bottom;
|
||||
openfile->mark_x = bottom_x;
|
||||
}
|
||||
} else if (whole_buffer && !openfile->mark)
|
||||
goto_line_posx(was_the_linenumber, 0);
|
||||
|
||||
add_undo(COUPLE_END, N_("justification"));
|
||||
|
||||
@@ -2031,11 +2050,19 @@ bool replace_buffer(const char *filename, undo_type action, const char *operatio
|
||||
if (descriptor < 0)
|
||||
return FALSE;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
add_undo(COUPLE_BEGIN, operation);
|
||||
#endif
|
||||
|
||||
/* When replacing the whole buffer, start cutting at the top. */
|
||||
if (action == CUT_TO_EOF) {
|
||||
openfile->current = openfile->filetop;
|
||||
openfile->current_x = 0;
|
||||
}
|
||||
|
||||
cutbuffer = NULL;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
add_undo(COUPLE_BEGIN, operation);
|
||||
|
||||
/* Cut either the marked region or the whole buffer. */
|
||||
add_undo(action, NULL);
|
||||
do_snip(openfile->mark != NULL, openfile->mark == NULL, FALSE);
|
||||
@@ -2060,6 +2087,7 @@ bool replace_buffer(const char *filename, undo_type action, const char *operatio
|
||||
/* Execute the given program, with the given temp file as last argument. */
|
||||
void treat(char *tempfile_name, char *theprogram, bool spelling)
|
||||
{
|
||||
#if defined(HAVE_FORK) && defined(HAVE_WAIT)
|
||||
ssize_t was_lineno = openfile->current->lineno;
|
||||
size_t was_pww = openfile->placewewant;
|
||||
size_t was_x = openfile->current_x;
|
||||
@@ -2154,14 +2182,9 @@ void treat(char *tempfile_name, char *theprogram, bool spelling)
|
||||
openfile->mark = line_from_number(was_mark_lineno);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
openfile->current = openfile->filetop;
|
||||
openfile->current_x = 0;
|
||||
|
||||
replaced = replace_buffer(tempfile_name, CUT_TO_EOF,
|
||||
/* TRANSLATORS: The next two go with Undid/Redid messages. */
|
||||
(spelling ? N_("spelling correction") : N_("formatting")));
|
||||
}
|
||||
|
||||
/* Go back to the old position. */
|
||||
goto_line_posx(was_lineno, was_x);
|
||||
@@ -2182,6 +2205,7 @@ void treat(char *tempfile_name, char *theprogram, bool spelling)
|
||||
statusline(REMARK, _("Finished checking spelling"));
|
||||
else
|
||||
statusline(REMARK, _("Buffer has been processed"));
|
||||
#endif
|
||||
}
|
||||
#endif /* ENABLE_SPELLER || ENABLE_COLOR */
|
||||
|
||||
@@ -2294,12 +2318,14 @@ bool fix_spello(const char *word)
|
||||
* correction. */
|
||||
void do_int_speller(const char *tempfile_name)
|
||||
{
|
||||
#if defined(HAVE_FORK) && defined(HAVE_WAITPID)
|
||||
char *misspellings, *pointer, *oneword;
|
||||
long pipesize;
|
||||
size_t buffersize, bytesread, totalread;
|
||||
int spell_fd[2], sort_fd[2], uniq_fd[2], tempfile_fd = -1;
|
||||
pid_t pid_spell, pid_sort, pid_uniq;
|
||||
int spell_status, sort_status, uniq_status;
|
||||
unsigned stash[sizeof(flags) / sizeof(flags[0])];
|
||||
|
||||
/* Create all three pipes up front. */
|
||||
if (pipe(spell_fd) == -1 || pipe(sort_fd) == -1 || pipe(uniq_fd) == -1) {
|
||||
@@ -2424,6 +2450,9 @@ void do_int_speller(const char *tempfile_name)
|
||||
terminal_init();
|
||||
doupdate();
|
||||
|
||||
/* Save the settings of the global flags. */
|
||||
memcpy(stash, flags, sizeof(flags));
|
||||
|
||||
/* Do any replacements case-sensitively, forward, and without regexes. */
|
||||
SET(CASE_SENSITIVE);
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
@@ -2454,6 +2483,9 @@ void do_int_speller(const char *tempfile_name)
|
||||
free(misspellings);
|
||||
refresh_needed = TRUE;
|
||||
|
||||
/* Restore the settings of the global flags. */
|
||||
memcpy(flags, stash, sizeof(flags));
|
||||
|
||||
/* Process the end of the three processes. */
|
||||
waitpid(pid_spell, &spell_status, 0);
|
||||
waitpid(pid_sort, &sort_status, 0);
|
||||
@@ -2467,6 +2499,7 @@ void do_int_speller(const char *tempfile_name)
|
||||
statusline(ALERT, _("Error invoking \"spell\""));
|
||||
else
|
||||
statusline(REMARK, _("Finished checking spelling"));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Spell check the current file. If an alternate spell checker is
|
||||
@@ -2475,7 +2508,6 @@ void do_spell(void)
|
||||
{
|
||||
FILE *stream;
|
||||
char *temp_name;
|
||||
unsigned stash[sizeof(flags) / sizeof(flags[0])];
|
||||
bool okay;
|
||||
|
||||
ran_a_tool = TRUE;
|
||||
@@ -2490,12 +2522,6 @@ void do_spell(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the settings of the global flags. */
|
||||
memcpy(stash, flags, sizeof(flags));
|
||||
|
||||
/* Don't add an extra newline when writing out the (selected) text. */
|
||||
SET(NO_NEWLINES);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark)
|
||||
okay = write_region_to_file(temp_name, stream, TEMPORARY, OVERWRITE);
|
||||
@@ -2505,6 +2531,7 @@ void do_spell(void)
|
||||
|
||||
if (!okay) {
|
||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||
unlink(temp_name);
|
||||
free(temp_name);
|
||||
return;
|
||||
}
|
||||
@@ -2519,9 +2546,6 @@ void do_spell(void)
|
||||
unlink(temp_name);
|
||||
free(temp_name);
|
||||
|
||||
/* Restore the settings of the global flags. */
|
||||
memcpy(flags, stash, sizeof(flags));
|
||||
|
||||
/* Ensure the help lines will be redrawn and a selection is retained. */
|
||||
currmenu = MMOST;
|
||||
shift_held = TRUE;
|
||||
@@ -2532,6 +2556,7 @@ void do_spell(void)
|
||||
/* Run a linting program on the current buffer. */
|
||||
void do_linter(void)
|
||||
{
|
||||
#if defined(HAVE_FORK) && defined(HAVE_WAITPID)
|
||||
char *lintings, *pointer, *onelint;
|
||||
long pipesize;
|
||||
size_t buffersize, bytesread, totalread;
|
||||
@@ -2558,12 +2583,12 @@ void do_linter(void)
|
||||
edit_refresh();
|
||||
|
||||
if (openfile->modified) {
|
||||
int choice = do_yesno_prompt(FALSE, _("Save modified buffer before linting?"));
|
||||
int choice = ask_user(YESORNO, _("Save modified buffer before linting?"));
|
||||
|
||||
if (choice == -1) {
|
||||
if (choice == CANCEL) {
|
||||
statusbar(_("Cancelled"));
|
||||
return;
|
||||
} else if (choice == 1 && (write_it_out(FALSE, FALSE) != 1))
|
||||
} else if (choice == YES && (write_it_out(FALSE, FALSE) != 1))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2647,36 +2672,31 @@ void do_linter(void)
|
||||
if ((*pointer == '\r') || (*pointer == '\n')) {
|
||||
*pointer = '\0';
|
||||
if (onelint != pointer) {
|
||||
char *filename = NULL, *linestr = NULL, *maybecol = NULL;
|
||||
char *message = copy_of(onelint);
|
||||
char *filename, *linestring, *colstring;
|
||||
char *complaint = copy_of(onelint);
|
||||
char *spacer = strstr(complaint, " ");
|
||||
|
||||
/* The recognized format is "filename:line:column: message",
|
||||
* where ":column" may be absent or be ",column" instead. */
|
||||
if (strstr(message, ": ") != NULL) {
|
||||
filename = strtok(onelint, ":");
|
||||
if ((linestr = strtok(NULL, ":")) != NULL) {
|
||||
if ((maybecol = strtok(NULL, ":")) != NULL) {
|
||||
ssize_t tmplineno = 0, tmpcolno = 0;
|
||||
char *tmplinecol;
|
||||
if ((filename = strtok(onelint, ":")) && spacer) {
|
||||
if ((linestring = strtok(NULL, ":"))) {
|
||||
if ((colstring = strtok(NULL, " "))) {
|
||||
ssize_t linenumber = strtol(linestring, NULL, 10);
|
||||
ssize_t colnumber = strtol(colstring, NULL, 10);
|
||||
|
||||
tmplineno = strtol(linestr, NULL, 10);
|
||||
if (tmplineno <= 0) {
|
||||
if (linenumber <= 0) {
|
||||
free(complaint);
|
||||
pointer++;
|
||||
free(message);
|
||||
continue;
|
||||
}
|
||||
|
||||
tmpcolno = strtol(maybecol, NULL, 10);
|
||||
/* Check if the middle field is in comma format. */
|
||||
if (tmpcolno <= 0) {
|
||||
strtok(linestr, ",");
|
||||
if ((tmplinecol = strtok(NULL, ",")) != NULL)
|
||||
tmpcolno = strtol(tmplinecol, NULL, 10);
|
||||
else
|
||||
tmpcolno = 1;
|
||||
if (colnumber <= 0) {
|
||||
colnumber = 1;
|
||||
strtok(linestring, ",");
|
||||
if ((colstring = strtok(NULL, ",")))
|
||||
colnumber = strtol(colstring, NULL, 10);
|
||||
}
|
||||
|
||||
/* Nice. We have a lint message we can use. */
|
||||
parsesuccess = TRUE;
|
||||
tmplint = curlint;
|
||||
curlint = nmalloc(sizeof(lintstruct));
|
||||
@@ -2684,17 +2704,17 @@ void do_linter(void)
|
||||
curlint->prev = tmplint;
|
||||
if (curlint->prev != NULL)
|
||||
curlint->prev->next = curlint;
|
||||
curlint->msg = copy_of(strstr(message, ": ") + 2);
|
||||
curlint->lineno = tmplineno;
|
||||
curlint->colno = tmpcolno;
|
||||
curlint->filename = copy_of(filename);
|
||||
curlint->lineno = linenumber;
|
||||
curlint->colno = colnumber;
|
||||
curlint->msg = copy_of(spacer + 1);
|
||||
|
||||
if (lints == NULL)
|
||||
lints = curlint;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(message);
|
||||
free(complaint);
|
||||
}
|
||||
onelint = pointer + 1;
|
||||
}
|
||||
@@ -2752,14 +2772,14 @@ void do_linter(void)
|
||||
|
||||
sprintf(msg, _("This message is for unopened file %s,"
|
||||
" open it in a new buffer?"), curlint->filename);
|
||||
choice = do_yesno_prompt(FALSE, msg);
|
||||
choice = ask_user(YESORNO, msg);
|
||||
currmenu = MLINTER;
|
||||
free(msg);
|
||||
|
||||
if (choice == -1) {
|
||||
if (choice == CANCEL) {
|
||||
statusbar(_("Cancelled"));
|
||||
break;
|
||||
} else if (choice == 1) {
|
||||
} else if (choice == YES) {
|
||||
open_buffer(curlint->filename, TRUE);
|
||||
} else {
|
||||
#endif
|
||||
@@ -2818,9 +2838,9 @@ void do_linter(void)
|
||||
|
||||
/* Place the cursor to indicate the affected line. */
|
||||
place_the_cursor();
|
||||
wnoutrefresh(edit);
|
||||
wnoutrefresh(midwin);
|
||||
|
||||
kbinput = get_kbinput(bottomwin, VISIBLE);
|
||||
kbinput = get_kbinput(footwin, VISIBLE);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH)
|
||||
@@ -2876,6 +2896,7 @@ void do_linter(void)
|
||||
lastmessage = VACUUM;
|
||||
currmenu = MMOST;
|
||||
titlebar(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Run a manipulation program on the contents of the buffer. */
|
||||
@@ -2904,13 +2925,10 @@ void do_formatter(void)
|
||||
if (temp_name != NULL)
|
||||
okay = write_file(temp_name, stream, TEMPORARY, OVERWRITE, NONOTES);
|
||||
|
||||
if (!okay) {
|
||||
if (!okay)
|
||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||
free(temp_name);
|
||||
return;
|
||||
}
|
||||
|
||||
treat(temp_name, openfile->syntax->formatter, FALSE);
|
||||
else
|
||||
treat(temp_name, openfile->syntax->formatter, FALSE);
|
||||
|
||||
unlink(temp_name);
|
||||
free(temp_name);
|
||||
@@ -2982,12 +3000,19 @@ void do_verbatim_input(void)
|
||||
size_t count = 1;
|
||||
char *bytes;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* When barless and with cursor on bottom row, make room for the feedback. */
|
||||
if (ISSET(ZERO) && openfile->current_y == editwinrows - 1 && LINES > 1) {
|
||||
edit_scroll(FORWARD);
|
||||
edit_refresh();
|
||||
}
|
||||
#endif
|
||||
/* TRANSLATORS: Shown when the next keystroke will be inserted verbatim. */
|
||||
statusline(INFO, _("Verbatim Input"));
|
||||
place_the_cursor();
|
||||
|
||||
/* Read in the first one or two bytes of the next keystroke. */
|
||||
bytes = get_verbatim_kbinput(edit, &count);
|
||||
bytes = get_verbatim_kbinput(midwin, &count);
|
||||
|
||||
/* When something valid was obtained, unsuppress cursor-position display,
|
||||
* insert the bytes into the edit buffer, and blank the status bar. */
|
||||
|
||||
28
src/utils.c
28
src/utils.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* utils.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2022 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -282,34 +282,26 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
return mbstrcasestr(start, needle);
|
||||
}
|
||||
|
||||
/* This is a wrapper for the malloc() function that properly handles
|
||||
* things when we run out of memory. */
|
||||
/* Allocate the given amount of memory and return a pointer to it. */
|
||||
void *nmalloc(size_t howmuch)
|
||||
{
|
||||
void *r = malloc(howmuch);
|
||||
void *section = malloc(howmuch);
|
||||
|
||||
if (howmuch == 0)
|
||||
die("Allocating zero bytes. Please report a bug.\n");
|
||||
|
||||
if (r == NULL)
|
||||
if (section == NULL)
|
||||
die(_("Nano is out of memory!\n"));
|
||||
|
||||
return r;
|
||||
return section;
|
||||
}
|
||||
|
||||
/* This is a wrapper for the realloc() function that properly handles
|
||||
* things when we run out of memory. */
|
||||
void *nrealloc(void *ptr, size_t howmuch)
|
||||
/* Reallocate the given section of memory to have the given size. */
|
||||
void *nrealloc(void *section, size_t howmuch)
|
||||
{
|
||||
void *r = realloc(ptr, howmuch);
|
||||
section = realloc(section, howmuch);
|
||||
|
||||
if (howmuch == 0)
|
||||
die("Allocating zero bytes. Please report a bug.\n");
|
||||
|
||||
if (r == NULL)
|
||||
if (section == NULL)
|
||||
die(_("Nano is out of memory!\n"));
|
||||
|
||||
return r;
|
||||
return section;
|
||||
}
|
||||
|
||||
/* Return an appropriately reallocated dest string holding a copy of src.
|
||||
|
||||
585
src/winio.c
585
src/winio.c
File diff suppressed because it is too large
Load Diff
@@ -26,10 +26,10 @@ color magenta "\<(break|continue|goto|return)\>"
|
||||
color brightmagenta "'([^'\]|\\(["'\abfnrtv]|x[[:xdigit:]]{1,2}|[0-3]?[0-7]{1,2}))'"
|
||||
|
||||
# GCC builtins.
|
||||
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
|
||||
# Strings and names of included files.
|
||||
color brightyellow ""([^"]|\\")*"" "#[[:blank:]]*include[[:blank:]]*<[^>]+>"
|
||||
color brightyellow ""([^"]|\\")*"|#[[:blank:]]*include[[:blank:]]*<[^>]+>"
|
||||
|
||||
# Preprocessor directives.
|
||||
color brightcyan start="^[[:blank:]]*#[[:blank:]]*(if(n?def)?|elif|warning|error|pragma)\>" end="(\`|[^\])$"
|
||||
|
||||
@@ -3,23 +3,23 @@
|
||||
syntax groff "\.(m[ems]|rof|tmac)$|/tmac\.[^/]+$"
|
||||
comment ".\""
|
||||
|
||||
# The argument of .ds or .nr
|
||||
# The setting of a string or register
|
||||
color cyan "^\.(ds|nr) [^[:space:]]*"
|
||||
# Single-character escapes
|
||||
color brightmagenta "\\."
|
||||
# The argument of \f or \s in the same color
|
||||
color brightmagenta "\\f(.|\(..)" "\\s(\+|\-)?[0-9]"
|
||||
# Newlines
|
||||
color brightmagenta "\\f(.|\(..)|\\s(\+|\-)?[0-9]"
|
||||
# References to registers
|
||||
color cyan "\\(\\)?n(.|\(..)"
|
||||
color cyan start="\\(\\)?n\[" end="]"
|
||||
# Requests
|
||||
color brightgreen "^\.[[:blank:]]*[^[:space:]]*"
|
||||
# Comments
|
||||
color yellow "^\.\\".*"
|
||||
# Strings
|
||||
# References to strings
|
||||
color green "\\(\\)?\*(.|\(..)"
|
||||
color green start="\\(\\)?\*\[" end="]"
|
||||
# Characters
|
||||
# Special characters
|
||||
color brightred "\\\(.."
|
||||
color brightred start="\\\[" end="]"
|
||||
# Macro arguments
|
||||
|
||||
@@ -22,9 +22,8 @@ color green "\<(true|false|null)\>"
|
||||
color brightblue ""[^"]+"[[:blank:]]*:"
|
||||
|
||||
# Brackets, braces, and separators.
|
||||
color brightblue "\[" "\]"
|
||||
color brightred "\{" "\}"
|
||||
color brightred "," ":"
|
||||
color brightblue "[][]"
|
||||
color brightred "[{},:]"
|
||||
|
||||
# Comments.
|
||||
color cyan "(^|[[:blank:]]+)(//|#).*"
|
||||
|
||||
@@ -6,10 +6,10 @@ comment ".\""
|
||||
|
||||
# Section headers, title line, and indented paragraphs.
|
||||
color green "^\.(SH|SS|TH) .*"
|
||||
color brightgreen "^\.(SH|SS|TH) " "^\.([HIT]P)"
|
||||
color brightgreen "^\.((SH|SS|TH) |[HIT]P)"
|
||||
# Type faces, and normal paragraphs.
|
||||
color brightred "^\.(B[IR]?|I[BR]?|R[BI]|S[BM]) .*"
|
||||
color brightblue "^\.(B[IR]?|I[BR]?|R[BI]|S[BM]) " "^\.([LP]?P)$"
|
||||
color brightblue "^\.((B[IR]?|I[BR]?|R[BI]|S[BM]) |[LP]?P$)"
|
||||
# Inline type faces.
|
||||
color magenta "\\f[BIPR]"
|
||||
# Relative margins, hyperlinks, and various other stuff.
|
||||
|
||||
@@ -15,7 +15,7 @@ color brightgreen "\<(goto|continue|break|return)\>"
|
||||
color brightgreen "@(encode|end|implementation|interface)|selector)\>"
|
||||
|
||||
# GCC builtins.
|
||||
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
|
||||
# Selector/method.
|
||||
color brightmagenta "(^|[[:blank:]])\[.*[[:blank:]].*\]"
|
||||
|
||||
@@ -23,11 +23,11 @@ color brightmagenta "(/([^/]|\\/)*/|%r\{([^}]|\\\})*\})[iomx]*"
|
||||
color brightblue "`[^`]*`|%x\{[^}]*\}"
|
||||
|
||||
# Strings, double-quoted.
|
||||
color green ""([^"]|\\")*"" "%[QW]?(\{[^}]*\}|\([^)]*\)|<[^>]*>|\[[^]]*\]|\$[^$]*\$|\^[^^]*\^|![^!]*!)"
|
||||
color green ""([^"]|\\")*"|%[QW]?(\{[^}]*\}|\([^)]*\)|<[^>]*>|\[[^]]*\]|\$[^$]*\$|\^[^^]*\^|![^!]*!)"
|
||||
# Expression substitution for inside double-quoted strings, "like #{this}".
|
||||
color brightgreen "#\{[^}]*\}"
|
||||
# Strings, single-quoted.
|
||||
color green "'([^']|\\')*'" "%[qw](\{[^}]*\}|\([^)]*\)|<[^>]*>|\[[^]]*\]|\$[^$]*\$|\^[^^]*\^|![^!]*!)"
|
||||
color green "'([^']|\\')*'|%[qw](\{[^}]*\}|\([^)]*\)|<[^>]*>|\[[^]]*\]|\$[^$]*\$|\^[^^]*\^|![^!]*!)"
|
||||
|
||||
# Comments.
|
||||
color cyan "#([^{#].*|$)"
|
||||
|
||||
@@ -25,7 +25,7 @@ color brightblue "\<(awk|cat|cd|ch(grp|mod|own)|cp|cut|echo|env|grep|head|instal
|
||||
color normal "[.-]tar\>"
|
||||
|
||||
# Basic variable names (no braces).
|
||||
color brightred "\$[-0-9@*#?$!]" "\$[[:alpha:]_][[:alnum:]_]*"
|
||||
color brightred "\$([-@*#?$!0-9]|[[:alpha:]_][[:alnum:]_]*)"
|
||||
# More complicated variable names; handles braces and replacements and arrays.
|
||||
color brightred "\$\{[#!]?([-@*#?$!]|[0-9]+|[[:alpha:]_][[:alnum:]_]*)(\[([[:blank:]]*[[:alnum:]_]+[[:blank:]]*|@)\])?(([#%/]|:?[-=?+])[^}]*\}|\[|\})"
|
||||
|
||||
|
||||
@@ -5,18 +5,22 @@ header "<\?xml.*version=.*\?>"
|
||||
magic "(XML|SGML) (sub)?document"
|
||||
comment "<!--|-->"
|
||||
|
||||
# The entire content of the tag:
|
||||
# First the entire content of the tag (for the attributes):
|
||||
color green start="<" end=">"
|
||||
|
||||
# The start and the end of the tag:
|
||||
color cyan "<[^> ]+" ">"
|
||||
# The angled brackets and the name of the tag:
|
||||
color cyan "<[^> ]+|/?>"
|
||||
|
||||
# The strings inside the tag:
|
||||
color magenta ""[^"]*""
|
||||
|
||||
# Prolog stuff:
|
||||
color #888 "<\?.+\?>|<!DOCTYPE[^>]+>|\]>"
|
||||
color #888 start="<!DOCTYPE[^>]*$" end="^[^<]*>"
|
||||
|
||||
# Comments:
|
||||
color yellow start="<!DOCTYPE" end="[/]?>"
|
||||
color yellow start="<!--" end="-->"
|
||||
|
||||
# Escapes:
|
||||
color red "&[^;]*;"
|
||||
# Entities (custom and predefined):
|
||||
color pink "&[^; ]+;"
|
||||
color red "&(amp|apos|gt|lt|quot);"
|
||||
|
||||
Reference in New Issue
Block a user