Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f92fb3ec4 | ||
|
|
293423bdda | ||
|
|
32719d64a1 | ||
|
|
f4321250ef | ||
|
|
908663e8fc | ||
|
|
1fb820386b | ||
|
|
9973366685 | ||
|
|
e72db0e350 | ||
|
|
87b2df6dea | ||
|
|
c24caf5fb8 | ||
|
|
8db21b68d5 | ||
|
|
cb31e45f6c | ||
|
|
588daf949e | ||
|
|
d21a9c8fc3 | ||
|
|
edbc1e5950 | ||
|
|
dc18746cbd | ||
|
|
c92b9be6cd | ||
|
|
eef7d1047a | ||
|
|
d49d4f7b56 | ||
|
|
2fbb71d555 | ||
|
|
66356ec7e2 | ||
|
|
4edc83c3c2 | ||
|
|
e6350aaba4 | ||
|
|
8bf8682b17 | ||
|
|
a9b5a0e029 | ||
|
|
026393a91a | ||
|
|
db897b574f | ||
|
|
2b1bc6866a | ||
|
|
90b959a677 | ||
|
|
116d9e6f01 | ||
|
|
6620acbff4 | ||
|
|
1cb6619d6a | ||
|
|
79a4bf81dc | ||
|
|
b77e6bd99d | ||
|
|
2bcc6d7f66 | ||
|
|
cd705a7c4c | ||
|
|
ecd18c1694 | ||
|
|
bc8a3a50a4 | ||
|
|
9b90ec877a | ||
|
|
8b483c10ba | ||
|
|
f915a28d30 | ||
|
|
cb3fc8892a | ||
|
|
06d9ee89e5 | ||
|
|
0b0b812206 | ||
|
|
eafae5d417 | ||
|
|
dfff78dffe | ||
|
|
40acb8714c | ||
|
|
d7af590c6b | ||
|
|
8c7e4f5108 | ||
|
|
1144d38316 | ||
|
|
0562d27b9c | ||
|
|
c5f49167ea | ||
|
|
9765c2faa0 | ||
|
|
85ebe971e2 | ||
|
|
fc101a6ded | ||
|
|
eb88ad980a | ||
|
|
9fa95a3680 | ||
|
|
d6cc2c40fe | ||
|
|
1df4115013 | ||
|
|
ea9f62fc0f | ||
|
|
a772194102 | ||
|
|
faf77fb1ec | ||
|
|
b0b24d9c3a | ||
|
|
c9f743f676 | ||
|
|
bd920b1f49 | ||
|
|
29e094cd21 | ||
|
|
7a8ae90dac | ||
|
|
13ec5d8ce9 | ||
|
|
30591c5e01 | ||
|
|
3f8e30efb1 | ||
|
|
e9fde7d7dc | ||
|
|
fd3423f79a | ||
|
|
a4044a7e5d | ||
|
|
2fa93ae999 | ||
|
|
c8c6340ce8 | ||
|
|
6263416355 | ||
|
|
84d6f1a5b6 | ||
|
|
ecccb8d027 | ||
|
|
173bbe11ef | ||
|
|
7531b71fa1 | ||
|
|
964c10db17 | ||
|
|
0e01080983 | ||
|
|
68a0314500 | ||
|
|
dca4ab5d8f | ||
|
|
86121cf3fc | ||
|
|
f03f5d5b51 | ||
|
|
379b1556ed | ||
|
|
bfcce57b69 | ||
|
|
4eac699df3 | ||
|
|
454f5cbdce | ||
|
|
248d7be8ef | ||
|
|
372bd0f7dd | ||
|
|
f920e0d30c | ||
|
|
0f3e303d1a | ||
|
|
c9680b8b64 | ||
|
|
656563beda | ||
|
|
8f95f9b1aa | ||
|
|
c6512a9717 | ||
|
|
07ce01c189 | ||
|
|
b5400ffe65 | ||
|
|
ac41587d4e | ||
|
|
e4b8d6fab5 | ||
|
|
72e8bcb027 | ||
|
|
7401670d58 | ||
|
|
87fbe24283 | ||
|
|
e4d452424b | ||
|
|
d48071b2b2 | ||
|
|
c1a484270b | ||
|
|
981a1d39bf | ||
|
|
925a001658 | ||
|
|
77023a749b | ||
|
|
1762920808 | ||
|
|
281a56fb74 | ||
|
|
592d0d6c9a | ||
|
|
3cc561e36e | ||
|
|
0333b87ad7 | ||
|
|
059c8efb44 | ||
|
|
eb68cd1c6b | ||
|
|
ecea413802 | ||
|
|
95253231e8 | ||
|
|
eb5968f845 | ||
|
|
f2c72bf759 | ||
|
|
e472b72565 | ||
|
|
e332d2df74 | ||
|
|
ed165827bc | ||
|
|
65bf36baa5 | ||
|
|
7598b77e75 | ||
|
|
a4132e2e64 | ||
|
|
8a66c820ab | ||
|
|
af0f81f71d |
3
AUTHORS
3
AUTHORS
@@ -53,6 +53,9 @@ Mike Scalora <mike@scalora.org>
|
||||
Faissal Bensefia <faissaloo@gmail.com>
|
||||
* Line numbers.
|
||||
|
||||
Sumedh Pendurkar <sumedh.pendurkar@gmail.com>
|
||||
* The word-completion feature.
|
||||
|
||||
Benno Schulenberg <bensberg@justemail.net>
|
||||
* An array of small bug fixes, the cut-word and block-jump
|
||||
routines, text selection by holding Shift, and some extra
|
||||
|
||||
@@ -2,7 +2,8 @@ Improvements in GNU nano
|
||||
========================
|
||||
|
||||
Since 2.7.0:
|
||||
- The ability to display line numbers in front of the text.
|
||||
- The keystroke ^] to complete a fragment to an existing full word.
|
||||
- The ability to display line numbers in front of the text (M-#).
|
||||
|
||||
Since 2.6.0:
|
||||
- Shift plus the cursor keys can be used for selecting text.
|
||||
|
||||
59
NEWS
59
NEWS
@@ -1,3 +1,28 @@
|
||||
2016.12.28 - GNU nano 2.7.3 "Ontbijtkoek" wipes away a handful of bugs:
|
||||
your editor is now able to handle filenames that contain
|
||||
newlines, avoids a brief flash of color when switching
|
||||
between buffers that are governed by different syntaxes,
|
||||
makes the Shift+Ctrl+Arrow keys select text again on a
|
||||
Linux console, is more resistant against malformations
|
||||
in the positionlog file, and does not crash when ^C is
|
||||
typed on systems where it produces the code KEY_CANCEL.
|
||||
Oh, and it no longer mistakenly warns about editing an
|
||||
unlocked file just after saving a new one. That's it.
|
||||
Tastes great with thick butter.
|
||||
|
||||
2016.12.12 - GNU nano 2.7.2 "Shemesh! Shemesh!" brings another feature:
|
||||
the ability to complete with one keystroke (^] by default)
|
||||
a fragment of a word to a full word existing elsewhere in
|
||||
the current buffer. Besides, this release fixes two bugs
|
||||
related to using line numbers in softwrap mode, allows to
|
||||
use the PageUp and PageDown keys together with Shift on
|
||||
VTE-based terminals, stops the help lines from flickering
|
||||
during interactive replacing, makes a "set fill" override
|
||||
an earlier "set nowrap", properly restores the selected
|
||||
region after an external spell check, and improves a few
|
||||
other tidbits. If you should find any more bugs, please
|
||||
run 'man nano | grep bugs' and report them there.
|
||||
|
||||
2016.10.29 - GNU nano 2.7.1 "Leuven" adds an often-asked-for feature: the
|
||||
ability to display line numbers beside the text. This can
|
||||
be activated with -l or --linenumbers on the command line,
|
||||
@@ -203,7 +228,7 @@
|
||||
linter support (see the nanorc man page for details). Also
|
||||
included are much improved syntax highlighting code, and
|
||||
configurations for JSON, texinfo, Go, and a default syntax
|
||||
for catch all highlighting. Finally, nano now has the
|
||||
for catch-all highlighting. Finally, nano now has the
|
||||
ability to set the color of the title bar, status bar, and
|
||||
shortcut keys (e.g. "^X") and their descriptions. Again
|
||||
see the nanorc page for details. There's much more, too
|
||||
@@ -1012,19 +1037,19 @@
|
||||
Also, the "show position" code now shows the starting
|
||||
column as 1 instead of 0. Have fun!
|
||||
|
||||
2002.03.05 - GNU nano 1.1.7 "lets change everything and see what breaks"
|
||||
is released. New features include new flags
|
||||
-N, --noconvert to stop any file format conversion and
|
||||
-Q, --quotestr for the new quoted text justification, a
|
||||
new tempnam() implementation to avoid silly warnings,
|
||||
2002.03.05 - GNU nano 1.1.7 "let's change everything and see what breaks"
|
||||
is released. New features include the new flags
|
||||
-N, --noconvert (to stop any file format conversion) and
|
||||
-Q, --quotestr (for the new quoted text justification),
|
||||
a new tempnam() implementation to avoid silly warnings,
|
||||
DOS and Mac file options in the Write File dialog,
|
||||
multiple save files (file.1) for abnormal exits, ^C now
|
||||
shows column as well as character position, and
|
||||
multibuffer allows duplicate files, even unnamed ones.
|
||||
Also, the static shortcut and toggle lengths are
|
||||
history, nano now reads SYSCONFDIR/nanorc if rc file
|
||||
support is enabled, and nano is now built with (and
|
||||
requires for rebuilding) autoconf 2.5.
|
||||
multiple save files (file.1) for abnormal exits,
|
||||
^C now showing column as well as character position, and
|
||||
multibuffer allowing duplicate files, even unnamed ones.
|
||||
Also, the static shortcut and toggle lengths are history,
|
||||
nano now reads SYSCONFDIR/nanorc if rc file support is
|
||||
enabled, and nano is now built with (and for rebuilding
|
||||
requires) autoconf 2.5.
|
||||
This release also includes fixes for some memory
|
||||
leaks, detecting DOS and Mac file format, justification,
|
||||
suspending keys, search & replace under various
|
||||
@@ -1300,7 +1325,7 @@
|
||||
New features include better (not yet perfect) binary
|
||||
display support and toggle support for most of the
|
||||
program flags (M-c, M-i, M-z, M-x, M-p, M-w, M-m, M-k
|
||||
and M-e for -c, -i, -x, -p, -w, -k, and -R).
|
||||
and M-e for -c, -i, -z, -x, -p, -w, -m, -k, and -R).
|
||||
|
||||
2000.08.09 - Nano 0.9.16, after some struggling, is released. This
|
||||
release should fix a few of the holes that 0.9.15 dug.
|
||||
@@ -1335,8 +1360,8 @@
|
||||
other major changes, this should be the feature set for
|
||||
nano 1.0, whenever it might be released =-)
|
||||
|
||||
2000.07.07 - Nano 0.9.12 (The "lucky day" release) is bursting with new
|
||||
features, bug fixes, and yummy fruit flavor. For
|
||||
2000.07.07 - Nano 0.9.12 (the "lucky day" release) is bursting with
|
||||
new features, bug fixes, and yummy fruit flavor. For
|
||||
changes, the alternate replace keystroke ^W^T is now
|
||||
^W^R to be compatible with later versions of Pico. ^W^T
|
||||
is now goto line, again for Pico compatibility. As for
|
||||
@@ -1433,7 +1458,7 @@
|
||||
path. The bug was in the new code for checking whether
|
||||
nano is invoked as 'pico'.
|
||||
|
||||
2000.04.14 - 0.9.1 has some more Pico compatibility built-in. The
|
||||
2000.04.14 - Nano 0.9.1 has some more Pico compatibility built-in. The
|
||||
option to switch to/from Search and Search/Replace (^T)
|
||||
is now available, and nano now displays the more
|
||||
Pico-like shortcut list when invoked as 'pico' (i.e. if
|
||||
|
||||
81
README
81
README
@@ -1,70 +1,67 @@
|
||||
|
||||
GNU nano - an enhanced clone of the Pico text editor.
|
||||
GNU nano -- an enhanced clone of the Pico text editor
|
||||
|
||||
Overview
|
||||
|
||||
The nano project was started because of a few "problems" with the
|
||||
wonderfully easy-to-use and friendly Pico text editor.
|
||||
The nano project was started because of a few "problems" with the
|
||||
wonderfully easy-to-use and friendly Pico text editor.
|
||||
|
||||
First and foremost was its license: the Pine suite does not use
|
||||
the GPL or a GPL-friendly license, and has unclear restrictions on
|
||||
redistribution. Because of this, Pine and Pico are not included
|
||||
with many GNU/Linux distributions. Also, other features (like
|
||||
go-to-line-number or search-and-replace) were unavailable until
|
||||
recently or require a command-line flag. Yuck.
|
||||
First and foremost was its license: the Pine suite does not use
|
||||
the GPL or a GPL-friendly license, and has unclear restrictions on
|
||||
redistribution. Because of this, Pine and Pico are not included
|
||||
with many GNU/Linux distributions. Also, other features (like
|
||||
go-to-line-number or search-and-replace) were unavailable until
|
||||
recently or require a command-line flag. Yuck.
|
||||
|
||||
nano aims to solve these problems by emulating the functionality of
|
||||
Pico as closely as possible while addressing the problems above and
|
||||
providing other extra functionality.
|
||||
nano aims to solve these problems by emulating the functionality of
|
||||
Pico as closely as possible while addressing the problems above and
|
||||
providing other extra functionality.
|
||||
|
||||
The nano editor is an official GNU package. For more information on
|
||||
GNU and the Free Software Foundation, please see http://www.gnu.org/.
|
||||
The nano editor is an official GNU package. For more information on
|
||||
GNU and the Free Software Foundation, please see http://www.gnu.org/.
|
||||
|
||||
How to compile and install nano
|
||||
|
||||
Download the nano source code, then:
|
||||
Download the nano source code, then:
|
||||
|
||||
tar zxvf nano-x.y.z.tar.gz
|
||||
cd nano-x.y.z
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
tar xvzf nano-x.y.z.tar.gz
|
||||
cd nano-x.y.z
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
It's that simple. Use --prefix with configure to override the
|
||||
default installation directory of /usr/local.
|
||||
It's that simple. Use --prefix with configure to override the
|
||||
default installation directory of /usr/local.
|
||||
|
||||
If you haven't configured with the "--disable-nanorc" option, after
|
||||
installation you may want to copy the doc/nanorc.sample to your
|
||||
home directory, rename it to ".nanorc", and then edit it according
|
||||
to your taste.
|
||||
If you haven't configured with the --disable-nanorc option, after
|
||||
installation you may want to copy the doc/nanorc.sample file to
|
||||
your home directory, rename it to ".nanorc", and then edit it
|
||||
according to your taste.
|
||||
|
||||
Web Page
|
||||
|
||||
https://nano-editor.org/
|
||||
|
||||
Mailing Lists and Bug Reports
|
||||
Mailing Lists
|
||||
|
||||
Savannah hosts all the nano-related mailing-lists.
|
||||
There are three nano-related mailing-lists.
|
||||
|
||||
+ info-nano@gnu.org is a very low traffic list used to announce
|
||||
new nano versions or other important information about the
|
||||
project.
|
||||
new nano versions or other important info about the project.
|
||||
+ help-nano@gnu.org is for those seeking to get help without
|
||||
wanting to hear about the technical details of its development.
|
||||
+ nano-devel@gnu.org is the list used by the people that make
|
||||
nano and a general development discussion list, with moderate
|
||||
traffic.
|
||||
+ nano-devel@gnu.org is the list used by the people that make nano
|
||||
and a general development discussion list, with moderate traffic.
|
||||
|
||||
To subscribe, send email to <name>-request@gnu.org with a
|
||||
subject of "subscribe", where <name> is the list you want to
|
||||
subscribe to.
|
||||
To subscribe, send email to <name>-request@gnu.org with a subject
|
||||
of "subscribe", where <name> is the list you want to subscribe to.
|
||||
|
||||
For general bug reports, please file a description of the problem
|
||||
on the Savannah bug tracker page for nano
|
||||
(https://savannah.gnu.org/bugs/?group=nano). The issue may have
|
||||
already been reported, and we are better able to track the state
|
||||
of the issue and whom to notify when fixed, the more the bug
|
||||
tracker is used.
|
||||
Bug Reports
|
||||
|
||||
To report a bug, please file a description of the problem on nano's
|
||||
bug tracker (https://savannah.gnu.org/bugs/?group=nano -- hover on
|
||||
"Bugs", then click "Submit new"). The issue may have already been
|
||||
reported, so please look first.
|
||||
|
||||
Current Status
|
||||
|
||||
|
||||
31
README.GIT
31
README.GIT
@@ -1,39 +1,42 @@
|
||||
INSTRUCTIONS TO COMPILE AND INSTALL NANO GIT VERSIONS
|
||||
=====================================================
|
||||
INSTRUCTIONS FOR COMPILING AND INSTALLING NANO FROM GIT
|
||||
=======================================================
|
||||
|
||||
The latest version of GNU nano is available via git, but building this needs
|
||||
a bit more care than the official stable and unstable tarballs.
|
||||
The latest changes and fixes for GNU nano are available via git, but
|
||||
building this needs a bit more care than the official tarballs.
|
||||
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
To successfully compile GNU nano from the git repo, you'll need the following
|
||||
To successfully compile GNU nano from git, you'll need the following
|
||||
packages:
|
||||
|
||||
- autoconf (version >= 2.61)
|
||||
- automake (version >= 1.7)
|
||||
- autopoint (version >= 0.11.5)
|
||||
- gettext (version >= 0.11.5)
|
||||
- git (version >= 2.7.4)
|
||||
- groff (version >= 1.12)
|
||||
- pkg-config (version >= 0.22)
|
||||
- texinfo (version >= 4.0)
|
||||
- glib 2.x (in case your system doesn't have vsnprintf(), which the
|
||||
configure script will check for)
|
||||
- make, gcc, and
|
||||
- the normal development libraries (curses or slang, etc.)
|
||||
- gcc (any version)
|
||||
- make (any version)
|
||||
|
||||
If you want UTF-8 support, you will also need libncursesw5-dev installed
|
||||
(version >= 5.7), or libslang2-dev (version >= 2.0) if you use --with-slang.
|
||||
If your system doesn't have 'snprintf' or 'vsnprintf' (which the configure
|
||||
script will check for), you will also need glib-2.x installed.
|
||||
|
||||
These should all be available in your distro's package manager or software
|
||||
center, or otherwise on any GNU mirror. Note that you'll need a version of
|
||||
curses or slang with wide character support if you want nano to use UTF-8.
|
||||
center, or otherwise on any GNU mirror.
|
||||
|
||||
|
||||
Download the source
|
||||
-------------------
|
||||
|
||||
To obtain the current nano development code (called 'master', or sometimes
|
||||
'trunk'), use the following command. It will create a copy of the files in
|
||||
a subdirectory of your current working directory called 'nano':
|
||||
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
|
||||
|
||||
|
||||
30
configure.ac
30
configure.ac
@@ -16,7 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
AC_INIT([GNU nano], [2.7.1], [nano-devel@gnu.org], [nano])
|
||||
AC_INIT([GNU nano], [2.7.3], [nano-devel@gnu.org], [nano])
|
||||
AC_CONFIG_SRCDIR([src/nano.c])
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE
|
||||
@@ -88,13 +88,12 @@ if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_comment" = xyes; then
|
||||
AC_MSG_ERROR([--enable-comment cannot work with --enable-tiny])
|
||||
else
|
||||
# Disabling nanorc silently disables comment support.
|
||||
enable_comment=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_comment" != xyes; then
|
||||
if test "x$enable_comment" != xno; then
|
||||
AC_DEFINE(ENABLE_COMMENT, 1, [Define this to disable the comment/uncomment functionality.])
|
||||
AC_DEFINE(ENABLE_COMMENT, 1, [Define this to enable the comment/uncomment function.])
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -173,7 +172,22 @@ fi
|
||||
AC_ARG_ENABLE(tabcomp,
|
||||
AS_HELP_STRING([--disable-tabcomp], [Disable tab completion functions]))
|
||||
if test "x$enable_tabcomp" = xno; then
|
||||
AC_DEFINE(DISABLE_TABCOMP, 1, [Define this to disable the tab completion functions for files and search strings.])
|
||||
AC_DEFINE(DISABLE_TABCOMP, 1, [Define this to disable the tab completion functions for filenames and search strings.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(wordcomp,
|
||||
AS_HELP_STRING([--disable-wordcomp], [Disable the word completion function]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_wordcomp" = xyes; then
|
||||
AC_MSG_ERROR([--enable-wordcomp cannot work with --enable-tiny])
|
||||
else
|
||||
enable_wordcomp=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_wordcomp" != xyes; then
|
||||
if test "x$enable_wordcomp" != xno; then
|
||||
AC_DEFINE(ENABLE_WORDCOMPLETION, 1, [Define this to enable the word completion function.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(wrapping,
|
||||
@@ -551,8 +565,12 @@ else
|
||||
AC_MSG_RESULT([Using $CURSES_LIB_NAME as the curses library])
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([$CURSES_LIB_NAME], use_default_colors, AC_DEFINE(HAVE_USE_DEFAULT_COLORS, 1, [Define this if your curses library has the use_default_colors() command.]))
|
||||
AC_CHECK_LIB([$CURSES_LIB_NAME], key_defined, AC_DEFINE(HAVE_KEY_DEFINED, 1, [Define this if your curses library has the key_defined() command.]))
|
||||
AC_CHECK_LIB([$CURSES_LIB_NAME], [use_default_colors],
|
||||
[AC_DEFINE(HAVE_USE_DEFAULT_COLORS, 1, [Define this if your curses library has the use_default_colors() command.])],
|
||||
[], [$CURSES_LIB])
|
||||
AC_CHECK_LIB([$CURSES_LIB_NAME], [key_defined],
|
||||
[AC_DEFINE(HAVE_KEY_DEFINED, 1, [Define this if your curses library has the key_defined() command.])],
|
||||
[], [$CURSES_LIB])
|
||||
|
||||
dnl Parse any configure options.
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANO 1 "version 2.7.1" "October 2016"
|
||||
.TH NANO 1 "version 2.7.3" "December 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
|
||||
.SH NAME
|
||||
@@ -294,7 +294,8 @@ that is not immediately undone, or after any reindentation, earlier edits
|
||||
cannot be undone any more. The workaround is, of course, to exit without
|
||||
saving.
|
||||
.sp
|
||||
Please report any other bugs that you encounter via
|
||||
Please report any other bugs that you encounter via:
|
||||
.br
|
||||
\fIhttps://savannah.gnu.org/bugs/?group=nano\fR.
|
||||
|
||||
.SH HOMEPAGE
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANORC 5 "version 2.7.1" "October 2016"
|
||||
.TH NANORC 5 "version 2.7.3" "December 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
|
||||
.SH NAME
|
||||
@@ -248,8 +248,9 @@ Save automatically on exit, don't prompt.
|
||||
.TP
|
||||
.B set titlecolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Specify the color combination to use for the titlebar.
|
||||
Valid color names for foreground and background are:
|
||||
.BR white , \ black , \ red , \ blue , \ green , \ yellow , \ magenta ", and " cyan .
|
||||
Valid names for the foreground and background colors are:
|
||||
.BR white ", " black ", " blue ", " green ", " red ", " cyan ", " yellow ", and " magenta .
|
||||
The name of the foreground color may be prefixed with \fBbright\fR.
|
||||
And either "\fIfgcolor\fR" or ",\fIbgcolor\fR" may be left out.
|
||||
.TP
|
||||
.B set unix
|
||||
@@ -488,6 +489,10 @@ Unindents (shifts to the left) the currently marked text.
|
||||
Comments or uncomments the current line or marked lines, using the comment
|
||||
style specified in the active syntax.
|
||||
.TP
|
||||
.B complete
|
||||
Completes the fragment before the cursor to a full word found elsewhere
|
||||
in the current buffer.
|
||||
.TP
|
||||
.B left
|
||||
Goes left one position (in the editor or browser).
|
||||
.TP
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 2.7.1" "October 2016"
|
||||
.TH RNANO 1 "version 2.7.3" "December 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
|
||||
.SH NAME
|
||||
|
||||
@@ -20,7 +20,7 @@ color red "\"[^"]*\"" "\'[^']*\'"
|
||||
color green "`[^`]*`"
|
||||
|
||||
# Error lines:
|
||||
color black "^\*\*\*.*"
|
||||
color brightred "^\*\*\*.*"
|
||||
|
||||
# Brackets:
|
||||
color magenta "\[|\]|\(|\)"
|
||||
|
||||
@@ -49,19 +49,19 @@ color ,green "[[:space:]]+$"
|
||||
syntax "/etc/portage" "\.(accept_keywords|env|keywords|mask|unmask|use)(/.+)?$"
|
||||
## Base text:
|
||||
color green "^.+$"
|
||||
## Use flags:
|
||||
color brightred "[[:space:]]+\+?[a-zA-Z0-9_-]+"
|
||||
color brightblue "[[:space:]]+-[a-zA-Z0-9_-]+"
|
||||
## Likely version and slot numbers:
|
||||
color magenta "-[[:digit:]].*([[:space:]]|$)"
|
||||
color magenta "-[[:digit:].]+(_(alpha|beta|pre|rc|p)[[:digit:]]*)*(-r[[:digit:]]+)?([:[:space:]]|$)"
|
||||
color magenta ":[^[:space:]]+([[:space:]]|$)"
|
||||
## Use flags (must come after version/slot):
|
||||
color brightred "[[:space:]]+\+?[A-Za-z0-9+_@-]+"
|
||||
color brightblue "[[:space:]]+-[A-Za-z0-9+_@-]+"
|
||||
## Accepted arches:
|
||||
color white "[~-]?\<(alpha|amd64|arm|hppa|ia64|mips|ppc|ppc64|s390|sh|sparc(-fbsd)?|x86(-fbsd)?)\>"
|
||||
color white "[~-]?\<(alpha|amd64|arm(64)?|hppa|ia64|m68k|mips|nios2|ppc(64)?|riscv|s390|sh|sparc|x86)(-(aix|(f|free|net|open)bsd|cygwin|hpux|interix|linux|macos|mint|solaris|winnt))?\>"
|
||||
color white "[[:space:]][*~-]?\*"
|
||||
## Categories:
|
||||
color cyan "^[[:space:]]*.*/"
|
||||
color cyan "^[[:space:]]*[^/]*/"
|
||||
## Masking regulators:
|
||||
color brightmagenta "^[[:space:]]*(=|~|<|<=|=<|>|>=|=>)"
|
||||
color brightmagenta "^[[:space:]]*(=|~|<|<=|>|>=)"
|
||||
## Comments:
|
||||
color yellow "#.*$"
|
||||
## Trailing space is bad!
|
||||
|
||||
@@ -7,8 +7,8 @@ comment "#"
|
||||
icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|comment|magic|linter|i?color|extendsyntax).*$"
|
||||
|
||||
# Keywords
|
||||
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cut|fill|historylog|justifytrim|locking|morespace|mouse|multibuffer|noconvert|nohelp|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize|tabstospaces|tempfile|unix|view|wordbounds)\>"
|
||||
icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>"
|
||||
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cut|fill[[:space:]]+[[:digit:]]+|historylog|justifytrim|locking|morespace|mouse|multibuffer|noconvert|nohelp|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[[:digit:]]+|tabstospaces|tempfile|unix|view|wordbounds)\>"
|
||||
icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>" "[[:space:]]+[[:digit:]]+$"
|
||||
icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+"
|
||||
icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
|
||||
icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
|
||||
@@ -20,10 +20,10 @@ icolor yellow "^[[:space:]]*i?color[[:space:]]*(bright)?(white|black|red|blue|gr
|
||||
icolor magenta "^[[:space:]]*i?color\>" "\<(start|end)="
|
||||
|
||||
# Strings
|
||||
icolor brightmagenta ""(\\.|[^"])*""
|
||||
color brightmagenta ""(\\.|[^"])*""
|
||||
# Comments
|
||||
icolor brightblue "(^|[[:space:]]+)#.*$"
|
||||
icolor cyan "^[[:space:]]*##.*$"
|
||||
color brightblue "(^|[[:space:]]+)#.*$"
|
||||
color cyan "^[[:space:]]*##.*$"
|
||||
|
||||
# Trailing whitespace
|
||||
color ,green "[[:space:]]+$"
|
||||
|
||||
@@ -10,7 +10,7 @@ color green "\<(define|include)\>"
|
||||
color red "\<(add|delete|flush|insert|remove|replace)\>"
|
||||
|
||||
# Families
|
||||
color yellow "\<(arp|bridge|inet|ip6?)\>"
|
||||
color yellow "\<(arp|bridge|inet|ingress|ip6?|netdev)\>"
|
||||
|
||||
# Terminal statements
|
||||
color red "\<(drop|reject)\>"
|
||||
@@ -27,4 +27,4 @@ color yellow ""(\\.|[^"])*"" "'(\\.|[^'])*'"
|
||||
color green "[{}():;|`$<>!=&\\]" "(\]|\[)"
|
||||
|
||||
# Basic variable names
|
||||
color brightred "\$[[:alpha:]_][[:alnum:]_.]*"
|
||||
color brightred "(\$|@)[[:alpha:]_-][[:alnum:]_.-]*"
|
||||
|
||||
@@ -14,10 +14,13 @@ color brightblue "^ .*"
|
||||
# Deleted lines.
|
||||
color brightred "^-.*"
|
||||
|
||||
# Header lines.
|
||||
color magenta "^(Index:|diff)[[:blank:]].*"
|
||||
# File names and dates.
|
||||
color red "^---.*"
|
||||
color green "^\+\+\+.*"
|
||||
# Line numbers.
|
||||
color brightyellow "^@@.*"
|
||||
# Header lines.
|
||||
color magenta "^diff.*"
|
||||
|
||||
# Statistics.
|
||||
color cyan start="^---$" end="^$"
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
@smallbook
|
||||
@set EDITION 0.4
|
||||
@set VERSION 2.7.1
|
||||
@set UPDATED October 2016
|
||||
@set VERSION 2.7.3
|
||||
@set UPDATED December 2016
|
||||
|
||||
@dircategory Editors
|
||||
@direntry
|
||||
@@ -21,7 +21,7 @@
|
||||
@titlepage
|
||||
@title GNU @code{nano}
|
||||
@subtitle a small and friendly text editor.
|
||||
@subtitle version 2.7.1
|
||||
@subtitle version 2.7.3
|
||||
|
||||
@author Chris Allegretta
|
||||
@page
|
||||
@@ -410,14 +410,19 @@ Characters not present on the keyboard can be entered in two ways:
|
||||
@item
|
||||
For characters with a single-byte code,
|
||||
pressing the Esc key twice and then typing a three-digit decimal number
|
||||
(from 000 to 255) will enter the character with the corresponding value.
|
||||
(from 000 to 255) will make @code{nano} behave as if you typed the key
|
||||
with that value.
|
||||
|
||||
@item
|
||||
For any possible character, pressing M-V (Alt+V) and then typing a
|
||||
six-digit hexadecimal number (starting with 0 or 1) will enter the
|
||||
character with the corresponding Unicode value.
|
||||
corresponding Unicode character into the buffer.
|
||||
@end itemize
|
||||
|
||||
For example, typing "Esc Esc 2 3 4" will enter the character "ê" ---
|
||||
useful when going to a French party. Typing "M-V 0 0 2 5 c 6" will
|
||||
enter the symbol "◆", a little black diamond.
|
||||
|
||||
@node Commands
|
||||
@section Commands
|
||||
|
||||
@@ -841,7 +846,8 @@ Save automatically on exit, don't prompt.
|
||||
@item set titlecolor @var{fgcolor},@var{bgcolor}
|
||||
Specify the color combination to use for the titlebar.
|
||||
Valid color names for foreground and background are:
|
||||
white, black, red, blue, green, yellow, magenta, and cyan.
|
||||
white, black, blue, green, red, cyan, yellow, and magenta.
|
||||
The name of the foreground color may be prefixed with 'bright'.
|
||||
And either @var{fgcolor} or @var{,bgcolor} may be left out.
|
||||
|
||||
@item set unix
|
||||
@@ -1090,6 +1096,10 @@ Unindents (shifts to the left) the currently marked text.
|
||||
Comments or uncomments the current line or marked lines, using the comment
|
||||
style specified in the active syntax.
|
||||
|
||||
@item complete
|
||||
Completes the fragment before the cursor to a full word found elsewhere
|
||||
in the current buffer.
|
||||
|
||||
@item left
|
||||
Goes left one position (in the editor or browser).
|
||||
|
||||
@@ -1500,18 +1510,21 @@ Disable use of the spell checker. This also eliminates the @code{-s}
|
||||
command-line option, which allows specifying an alternate spell checker.
|
||||
|
||||
@item --disable-tabcomp
|
||||
Disable the tab completion code when reading or writing files.
|
||||
Disable tab completion (when nano asks for a filename or a search string).
|
||||
|
||||
@item --disable-wordcomp
|
||||
Disable word completion.
|
||||
|
||||
@item --disable-wrapping
|
||||
Disable hard-wrapping of overlong lines. This also eliminates the @code{-w}
|
||||
command-line option, which enables long-line wrapping.
|
||||
Disable all hard-wrapping of overlong lines. This also eliminates the
|
||||
@code{-w} command-line option, which switches long-line wrapping off.
|
||||
|
||||
@item --enable-tiny
|
||||
This option disables all the above. It also disables some of the larger
|
||||
internals of the editor, like the marking code and the cut-to-end-of-line
|
||||
code. It also disables the function toggles. By using the enabling
|
||||
This option implies all of the above. It also disables some other
|
||||
internals of the editor, like the marking code, the cut-to-end-of-line
|
||||
code, and the function toggles. By using the enabling
|
||||
counterpart of the above options together with @code{--enable-tiny},
|
||||
specific features can be switched back on.
|
||||
specific features can be switched back on --- but a few cannot.
|
||||
|
||||
@item --enable-debug
|
||||
Enable support for runtime debug output. This can get pretty messy, so
|
||||
|
||||
1016
po/nano.pot
1016
po/nano.pot
File diff suppressed because it is too large
Load Diff
1043
po/pt_BR.po
1043
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1013
po/zh_CN.po
1013
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1025
po/zh_TW.po
1025
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,7 @@
|
||||
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
|
||||
CLEANFILES = revision.h
|
||||
|
||||
if BUILDING_FROM_GIT
|
||||
SOMETHING = "REVISION \"$(shell git describe --tags 2>/dev/null)\""
|
||||
else
|
||||
|
||||
@@ -69,7 +69,7 @@ char *do_browser(char *path)
|
||||
dir = opendir(path);
|
||||
|
||||
if (path == NULL || dir == NULL) {
|
||||
statusline(ALERT, "Cannot open directory: %s", strerror(errno));
|
||||
statusline(ALERT, _("Cannot open directory: %s"), strerror(errno));
|
||||
/* If we don't have a file list yet, there is nothing to show. */
|
||||
if (filelist == NULL) {
|
||||
napms(1200);
|
||||
@@ -147,7 +147,7 @@ char *do_browser(char *path)
|
||||
/* If we selected the same filename as last time, fake a
|
||||
* press of the Enter key so that the file is read in. */
|
||||
if (old_selected == selected)
|
||||
unget_kbinput(sc_seq_or(do_enter, 0), FALSE);
|
||||
unget_kbinput(KEY_ENTER, FALSE);
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -230,17 +230,11 @@ char *do_browser(char *path)
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
browser_refresh, _("Go To Directory"));
|
||||
|
||||
/* If the directory begins with a newline (i.e. an
|
||||
* encoded null), treat it as though it's blank. */
|
||||
if (i < 0 || *answer == '\n') {
|
||||
if (i < 0) {
|
||||
statusbar(_("Cancelled"));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Convert newlines to nulls in the directory name. */
|
||||
sunder(answer);
|
||||
align(&answer);
|
||||
|
||||
path = free_and_assign(path, real_dir_from_tilde(answer));
|
||||
|
||||
/* If the given path is relative, join it with the current path. */
|
||||
@@ -375,12 +369,11 @@ char *do_browse_from(const char *inpath)
|
||||
|
||||
if (path == NULL) {
|
||||
free(currentdir);
|
||||
statusline(MILD, "The working directory has disappeared");
|
||||
statusline(MILD, _("The working directory has disappeared"));
|
||||
beep();
|
||||
napms(1200);
|
||||
return NULL;
|
||||
} else
|
||||
align(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,7 +707,7 @@ void findnextfile(const char *needle)
|
||||
/* Save the settings of all flags. */
|
||||
memcpy(stash, flags, sizeof(flags));
|
||||
|
||||
/* Search forward, case insensitive and without regexes. */
|
||||
/* Search forward, case insensitive, and without regexes. */
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
UNSET(CASE_SENSITIVE);
|
||||
UNSET(USE_REGEXP);
|
||||
|
||||
167
src/chars.c
167
src/chars.c
@@ -88,11 +88,6 @@ void mbtowc_reset(void)
|
||||
IGNORE_CALL_RESULT(mbtowc(NULL, NULL, 0));
|
||||
}
|
||||
|
||||
void wctomb_reset(void)
|
||||
{
|
||||
IGNORE_CALL_RESULT(wctomb(NULL, 0));
|
||||
}
|
||||
|
||||
/* This function is equivalent to isalpha() for multibyte characters. */
|
||||
bool is_alpha_mbchar(const char *c)
|
||||
{
|
||||
@@ -172,8 +167,6 @@ bool is_cntrl_char(int c)
|
||||
* their high bits set. */
|
||||
bool is_cntrl_mbchar(const char *c)
|
||||
{
|
||||
assert(c != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
return ((c[0] & 0xE0) == 0 || c[0] == 127 ||
|
||||
@@ -208,8 +201,6 @@ bool is_punct_mbchar(const char *c)
|
||||
* punctuation when allow_punct is TRUE), and FALSE otherwise. */
|
||||
bool is_word_mbchar(const char *c, bool allow_punct)
|
||||
{
|
||||
assert(c != NULL);
|
||||
|
||||
if (*c == '\0')
|
||||
return FALSE;
|
||||
|
||||
@@ -217,15 +208,11 @@ bool is_word_mbchar(const char *c, bool allow_punct)
|
||||
return TRUE;
|
||||
|
||||
if (word_chars != NULL && *word_chars != '\0') {
|
||||
bool wordforming;
|
||||
char *symbol = charalloc(MB_CUR_MAX + 1);
|
||||
char symbol[mb_cur_max() + 1];
|
||||
int symlen = parse_mbchar(c, symbol, NULL);
|
||||
|
||||
symbol[symlen] = '\0';
|
||||
wordforming = (strstr(word_chars, symbol) != NULL);
|
||||
free(symbol);
|
||||
|
||||
return wordforming;
|
||||
return (strstr(word_chars, symbol) != NULL);
|
||||
}
|
||||
|
||||
return (allow_punct && is_punct_mbchar(c));
|
||||
@@ -234,12 +221,7 @@ bool is_word_mbchar(const char *c, bool allow_punct)
|
||||
/* Return the visible representation of control character c. */
|
||||
char control_rep(const signed char c)
|
||||
{
|
||||
assert(is_cntrl_char(c));
|
||||
|
||||
/* An embedded newline is an encoded null. */
|
||||
if (c == '\n')
|
||||
return '@';
|
||||
else if (c == DEL_CODE)
|
||||
if (c == DEL_CODE)
|
||||
return '?';
|
||||
else if (c == -97)
|
||||
return '=';
|
||||
@@ -250,9 +232,11 @@ char control_rep(const signed char c)
|
||||
}
|
||||
|
||||
/* Return the visible representation of multibyte control character c. */
|
||||
char control_mbrep(const char *c)
|
||||
char control_mbrep(const char *c, bool isdata)
|
||||
{
|
||||
assert(c != NULL);
|
||||
/* An embedded newline is an encoded NUL if it is data. */
|
||||
if (*c == '\n' && (isdata || as_an_at))
|
||||
return '@';
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
@@ -325,27 +309,25 @@ int mbwidth(const char *c)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return the maximum width in bytes of a multibyte character. */
|
||||
/* Return the maximum length (in bytes) of a character. */
|
||||
int mb_cur_max(void)
|
||||
{
|
||||
return
|
||||
#ifdef ENABLE_UTF8
|
||||
use_utf8 ? MB_CUR_MAX :
|
||||
if (use_utf8)
|
||||
return MB_CUR_MAX;
|
||||
else
|
||||
#endif
|
||||
1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Convert the Unicode value in chr to a multibyte character with the
|
||||
* same wide character value as chr, if possible. If the conversion
|
||||
* succeeds, return the (dynamically allocated) multibyte character and
|
||||
* its length. Otherwise, return an undefined (dynamically allocated)
|
||||
* multibyte character and a length of zero. */
|
||||
/* Convert the Unicode value in chr to a multibyte character, if possible.
|
||||
* If the conversion succeeds, return the (dynamically allocated) multibyte
|
||||
* character and its length. Otherwise, return an undefined (dynamically
|
||||
* allocated) multibyte character and a length of zero. */
|
||||
char *make_mbchar(long chr, int *chr_mb_len)
|
||||
{
|
||||
char *chr_mb;
|
||||
|
||||
assert(chr_mb_len != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
chr_mb = charalloc(MB_CUR_MAX);
|
||||
@@ -353,7 +335,7 @@ char *make_mbchar(long chr, int *chr_mb_len)
|
||||
|
||||
/* Reject invalid Unicode characters. */
|
||||
if (*chr_mb_len < 0 || !is_valid_unicode((wchar_t)chr)) {
|
||||
wctomb_reset();
|
||||
IGNORE_CALL_RESULT(wctomb(NULL, 0));
|
||||
*chr_mb_len = 0;
|
||||
}
|
||||
} else
|
||||
@@ -368,37 +350,35 @@ char *make_mbchar(long chr, int *chr_mb_len)
|
||||
|
||||
/* Parse a multibyte character from buf. Return the number of bytes
|
||||
* used. If chr isn't NULL, store the multibyte character in it. If
|
||||
* col isn't NULL, store the new display width in it. If *buf is '\t',
|
||||
* we expect col to have the current display width. */
|
||||
* col isn't NULL, add the character's width (in columns) to it. */
|
||||
int parse_mbchar(const char *buf, char *chr, size_t *col)
|
||||
{
|
||||
int buf_mb_len;
|
||||
int length;
|
||||
|
||||
assert(buf != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
/* Get the number of bytes in the multibyte character. */
|
||||
buf_mb_len = mblen(buf, MB_CUR_MAX);
|
||||
length = mblen(buf, MB_CUR_MAX);
|
||||
|
||||
/* When the multibyte sequence is invalid, only take the first byte. */
|
||||
if (buf_mb_len < 0) {
|
||||
if (length <= 0) {
|
||||
IGNORE_CALL_RESULT(mblen(NULL, 0));
|
||||
buf_mb_len = 1;
|
||||
} else if (buf_mb_len == 0)
|
||||
buf_mb_len++;
|
||||
length = 1;
|
||||
}
|
||||
|
||||
/* When requested, store the multibyte character in chr. */
|
||||
if (chr != NULL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < buf_mb_len; i++)
|
||||
for (i = 0; i < length; i++)
|
||||
chr[i] = buf[i];
|
||||
}
|
||||
|
||||
/* When requested, store the width of the wide character in col. */
|
||||
/* When requested, add the width of the character to col. */
|
||||
if (col != NULL) {
|
||||
/* If we have a tab, get its width in columns using the
|
||||
/* If we have a tab, compute its width in columns based on the
|
||||
* current value of col. */
|
||||
if (*buf == '\t')
|
||||
*col += tabsize - *col % tabsize;
|
||||
@@ -406,8 +386,7 @@ int parse_mbchar(const char *buf, char *chr, size_t *col)
|
||||
* column for the "^", and one for the visible character. */
|
||||
else if (is_cntrl_mbchar(buf)) {
|
||||
*col += 2;
|
||||
/* If we have a normal character, get its width in columns
|
||||
* normally. */
|
||||
/* If we have a normal character, get its width normally. */
|
||||
} else
|
||||
*col += mbwidth(buf);
|
||||
}
|
||||
@@ -415,15 +394,15 @@ int parse_mbchar(const char *buf, char *chr, size_t *col)
|
||||
#endif
|
||||
{
|
||||
/* A byte character is one byte long. */
|
||||
buf_mb_len = 1;
|
||||
length = 1;
|
||||
|
||||
/* When requested, store the byte character in chr. */
|
||||
if (chr != NULL)
|
||||
*chr = *buf;
|
||||
|
||||
/* When requested, store the width of the wide character in col. */
|
||||
/* When requested, add the width of the character to col. */
|
||||
if (col != NULL) {
|
||||
/* If we have a tab, get its width in columns using the
|
||||
/* If we have a tab, compute its width in columns using the
|
||||
* current value of col. */
|
||||
if (*buf == '\t')
|
||||
*col += tabsize - *col % tabsize;
|
||||
@@ -437,7 +416,7 @@ int parse_mbchar(const char *buf, char *chr, size_t *col)
|
||||
}
|
||||
}
|
||||
|
||||
return buf_mb_len;
|
||||
return length;
|
||||
}
|
||||
|
||||
/* Return the index in buf of the beginning of the multibyte character
|
||||
@@ -492,8 +471,6 @@ int nstrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
if (s1 == s2)
|
||||
return 0;
|
||||
|
||||
assert(s1 != NULL && s2 != NULL);
|
||||
|
||||
for (; *s1 != '\0' && *s2 != '\0' && n > 0; s1++, s2++, n--) {
|
||||
if (tolower(*s1) != tolower(*s2))
|
||||
break;
|
||||
@@ -510,8 +487,6 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
if (use_utf8) {
|
||||
wchar_t wc1, wc2;
|
||||
|
||||
assert(s1 != NULL && s2 != NULL);
|
||||
|
||||
while (*s1 != '\0' && *s2 != '\0' && n > 0) {
|
||||
bool bad1 = FALSE, bad2 = FALSE;
|
||||
|
||||
@@ -555,8 +530,6 @@ char *nstrcasestr(const char *haystack, const char *needle)
|
||||
{
|
||||
size_t needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)haystack;
|
||||
|
||||
@@ -580,8 +553,6 @@ char *mbstrcasestr(const char *haystack, const char *needle)
|
||||
if (use_utf8) {
|
||||
size_t needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)haystack;
|
||||
|
||||
@@ -602,27 +573,25 @@ char *mbstrcasestr(const char *haystack, const char *needle)
|
||||
|
||||
/* This function is equivalent to strstr(), except in that it scans the
|
||||
* string in reverse, starting at rev_start. */
|
||||
char *revstrstr(const char *haystack, const char *needle, const char
|
||||
*rev_start)
|
||||
char *revstrstr(const char *haystack, const char *needle,
|
||||
const char *pointer)
|
||||
{
|
||||
size_t rev_start_len, needle_len;
|
||||
size_t needle_len = strlen(needle);
|
||||
size_t tail_len = strlen(pointer);
|
||||
|
||||
assert(haystack != NULL && needle != NULL && rev_start != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)rev_start;
|
||||
|
||||
needle_len = strlen(needle);
|
||||
if (needle_len == 0)
|
||||
return (char *)pointer;
|
||||
|
||||
if (strlen(haystack) < needle_len)
|
||||
return NULL;
|
||||
|
||||
rev_start_len = strlen(rev_start);
|
||||
if (tail_len < needle_len)
|
||||
pointer += tail_len - needle_len;
|
||||
|
||||
for (; rev_start >= haystack; rev_start--, rev_start_len++) {
|
||||
if (rev_start_len >= needle_len && strncmp(rev_start, needle,
|
||||
needle_len) == 0)
|
||||
return (char *)rev_start;
|
||||
while (pointer >= haystack) {
|
||||
if (strncmp(pointer, needle, needle_len) == 0)
|
||||
return (char *)pointer;
|
||||
pointer--;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -635,8 +604,6 @@ char *revstrcasestr(const char *haystack, const char *needle, const char
|
||||
{
|
||||
size_t rev_start_len, needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL && rev_start != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)rev_start;
|
||||
|
||||
@@ -665,8 +632,6 @@ char *mbrevstrcasestr(const char *haystack, const char *needle, const
|
||||
if (use_utf8) {
|
||||
size_t rev_start_len, needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL && rev_start != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)rev_start;
|
||||
|
||||
@@ -706,8 +671,6 @@ size_t nstrnlen(const char *s, size_t maxlen)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
assert(s != NULL);
|
||||
|
||||
for (; *s != '\0' && maxlen > 0; s++, maxlen--, n++)
|
||||
;
|
||||
|
||||
@@ -718,8 +681,6 @@ size_t nstrnlen(const char *s, size_t maxlen)
|
||||
/* This function is equivalent to strnlen() for multibyte strings. */
|
||||
size_t mbstrnlen(const char *s, size_t maxlen)
|
||||
{
|
||||
assert(s != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
size_t n = 0;
|
||||
@@ -743,7 +704,7 @@ char *mbstrchr(const char *s, const char *c)
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool bad_s_mb = FALSE, bad_c_mb = FALSE;
|
||||
char *s_mb = charalloc(MB_CUR_MAX);
|
||||
char symbol[MB_CUR_MAX];
|
||||
const char *q = s;
|
||||
wchar_t ws, wc;
|
||||
|
||||
@@ -754,9 +715,9 @@ char *mbstrchr(const char *s, const char *c)
|
||||
}
|
||||
|
||||
while (*s != '\0') {
|
||||
int s_mb_len = parse_mbchar(s, s_mb, NULL);
|
||||
int sym_len = parse_mbchar(s, symbol, NULL);
|
||||
|
||||
if (mbtowc(&ws, s_mb, s_mb_len) < 0) {
|
||||
if (mbtowc(&ws, symbol, sym_len) < 0) {
|
||||
mbtowc_reset();
|
||||
ws = (unsigned char)*s;
|
||||
bad_s_mb = TRUE;
|
||||
@@ -765,12 +726,10 @@ char *mbstrchr(const char *s, const char *c)
|
||||
if (bad_s_mb == bad_c_mb && ws == wc)
|
||||
break;
|
||||
|
||||
s += s_mb_len;
|
||||
q += s_mb_len;
|
||||
s += sym_len;
|
||||
q += sym_len;
|
||||
}
|
||||
|
||||
free(s_mb);
|
||||
|
||||
if (*s == '\0')
|
||||
q = NULL;
|
||||
|
||||
@@ -785,8 +744,6 @@ char *mbstrchr(const char *s, const char *c)
|
||||
/* This function is equivalent to strpbrk() for multibyte strings. */
|
||||
char *mbstrpbrk(const char *s, const char *accept)
|
||||
{
|
||||
assert(s != NULL && accept != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
for (; *s != '\0'; s += move_mbright(s, 0)) {
|
||||
@@ -857,8 +814,6 @@ char *mbrevstrpbrk(const char *s, const char *accept, const char
|
||||
* and FALSE otherwise. */
|
||||
bool has_blank_chars(const char *s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
|
||||
for (; *s != '\0'; s++) {
|
||||
if (isblank(*s))
|
||||
return TRUE;
|
||||
@@ -871,25 +826,18 @@ bool has_blank_chars(const char *s)
|
||||
* multibyte characters, and FALSE otherwise. */
|
||||
bool has_blank_mbchars(const char *s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool retval = FALSE;
|
||||
char *chr_mb = charalloc(MB_CUR_MAX);
|
||||
char symbol[MB_CUR_MAX];
|
||||
|
||||
for (; *s != '\0'; s += move_mbright(s, 0)) {
|
||||
parse_mbchar(s, chr_mb, NULL);
|
||||
parse_mbchar(s, symbol, NULL);
|
||||
|
||||
if (is_blank_mbchar(chr_mb)) {
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
if (is_blank_mbchar(symbol))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
free(chr_mb);
|
||||
|
||||
return retval;
|
||||
return FALSE;
|
||||
} else
|
||||
#endif
|
||||
return has_blank_chars(s);
|
||||
@@ -912,12 +860,11 @@ bool is_valid_unicode(wchar_t wc)
|
||||
* is, and FALSE otherwise. */
|
||||
bool is_valid_mbstring(const char *s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
|
||||
return
|
||||
#ifdef ENABLE_UTF8
|
||||
use_utf8 ? (mbstowcs(NULL, s, 0) != (size_t)-1) :
|
||||
if (use_utf8)
|
||||
return (mbstowcs(NULL, s, 0) != (size_t)-1);
|
||||
else
|
||||
#endif
|
||||
TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* !DISABLE_NANORC */
|
||||
|
||||
280
src/files.c
280
src/files.c
@@ -148,8 +148,9 @@ void set_modified(void)
|
||||
|
||||
if (openfile->lock_filename == NULL) {
|
||||
/* TRANSLATORS: Keep the next ten messages at most 76 characters. */
|
||||
statusline(ALERT, _("Warning: Modifying a file which is not locked,"
|
||||
" check directory permission?"));
|
||||
// statusline(ALERT, _("Warning: Modifying a file which is not locked,"
|
||||
// " check directory permission?"));
|
||||
;
|
||||
} else {
|
||||
char *fullname = get_full_path(openfile->filename);
|
||||
write_lockfile(openfile->lock_filename, fullname, TRUE);
|
||||
@@ -179,8 +180,8 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi
|
||||
struct stat fileinfo;
|
||||
char *lockdata = charalloc(1024);
|
||||
char myhostname[32];
|
||||
ssize_t lockdatalen = 1024;
|
||||
ssize_t wroteamt;
|
||||
size_t lockdatalen = 1024;
|
||||
size_t wroteamt;
|
||||
|
||||
mypid = getpid();
|
||||
myuid = geteuid();
|
||||
@@ -320,8 +321,8 @@ int do_lockfile(const char *filename)
|
||||
fprintf(stderr, "lock file name is %s\n", lockfilename);
|
||||
#endif
|
||||
if (stat(lockfilename, &fileinfo) != -1) {
|
||||
ssize_t readtot = 0;
|
||||
ssize_t readamt = 0;
|
||||
size_t readtot = 0;
|
||||
size_t readamt = 0;
|
||||
char *lockbuf, *question, *pidstring, *postedname, *promptstr;
|
||||
int room, response;
|
||||
|
||||
@@ -422,12 +423,8 @@ void stat_with_alloc(const char *filename, struct stat **pstat)
|
||||
* or into a new buffer when MULTIBUFFER is set or there is no buffer yet. */
|
||||
bool open_buffer(const char *filename, bool undoable)
|
||||
{
|
||||
bool new_buffer = (openfile == NULL
|
||||
#ifndef DISABLE_MULTIBUFFER
|
||||
|| ISSET(MULTIBUFFER)
|
||||
#endif
|
||||
);
|
||||
/* Whether we load into this buffer or a new one. */
|
||||
bool new_buffer = (openfile == NULL || ISSET(MULTIBUFFER));
|
||||
/* Whether we load into the current buffer or a new one. */
|
||||
char *realname;
|
||||
/* The filename after tilde expansion. */
|
||||
FILE *f;
|
||||
@@ -437,6 +434,9 @@ bool open_buffer(const char *filename, bool undoable)
|
||||
|
||||
assert(filename != NULL);
|
||||
|
||||
/* Display newlines in filenames as ^J. */
|
||||
as_an_at = FALSE;
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
if (check_operating_dir(filename, FALSE)) {
|
||||
statusline(ALERT, _("Can't insert file from outside of %s"),
|
||||
@@ -567,7 +567,8 @@ void display_buffer(void)
|
||||
precalc_multicolorinfo();
|
||||
#endif
|
||||
|
||||
refresh_needed = TRUE;
|
||||
/* Update the content of the edit window straightaway. */
|
||||
edit_refresh();
|
||||
}
|
||||
|
||||
#ifndef DISABLE_MULTIBUFFER
|
||||
@@ -754,8 +755,6 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw
|
||||
/* 0 = *nix, 1 = DOS, 2 = Mac, 3 = both DOS and Mac. */
|
||||
#endif
|
||||
|
||||
assert(openfile->fileage != NULL && openfile->current != NULL);
|
||||
|
||||
buf = charalloc(bufx);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -912,7 +911,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
if (!writable)
|
||||
statusline(ALERT, "File '%s' is unwritable", filename);
|
||||
statusline(ALERT, _("File '%s' is unwritable"), filename);
|
||||
#ifndef NANO_TINY
|
||||
else if (format == 3) {
|
||||
/* TRANSLATORS: Keep the next four messages at most 78 characters. */
|
||||
@@ -947,13 +946,10 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Open the file (and decide if it exists). If newfie is TRUE, display
|
||||
* "New File" if the file is missing. Otherwise, say "[filename] not
|
||||
* found".
|
||||
*
|
||||
/* Open the file with the given name. If the file does not exist, display
|
||||
* "New File" if newfie is TRUE, and say "File not found" otherwise.
|
||||
* Return -2 if we say "New File", -1 if the file isn't opened, and the
|
||||
* fd opened otherwise. The file might still have an error while reading
|
||||
* with a 0 return value. *f is set to the opened file. */
|
||||
* obtained fd otherwise. *f is set to the opened file. */
|
||||
int open_file(const char *filename, bool newfie, bool quiet, FILE **f)
|
||||
{
|
||||
struct stat fileinfo, fileinfo2;
|
||||
@@ -972,39 +968,35 @@ int open_file(const char *filename, bool newfie, bool quiet, FILE **f)
|
||||
full_filename = mallocstrcpy(full_filename, filename);
|
||||
|
||||
if (stat(full_filename, &fileinfo) == -1) {
|
||||
/* All cases below return. */
|
||||
free(full_filename);
|
||||
|
||||
/* Well, maybe we can open the file even if the OS says it's
|
||||
* not there. */
|
||||
if ((fd = open(filename, O_RDONLY)) != -1) {
|
||||
if (!quiet)
|
||||
statusbar(_("Reading File"));
|
||||
return fd;
|
||||
}
|
||||
|
||||
if (newfie) {
|
||||
if (!quiet)
|
||||
statusbar(_("New File"));
|
||||
free(full_filename);
|
||||
return -2;
|
||||
}
|
||||
statusline(ALERT, _("File \"%s\" not found"), filename);
|
||||
return -1;
|
||||
} else if (S_ISDIR(fileinfo.st_mode) || S_ISCHR(fileinfo.st_mode) ||
|
||||
S_ISBLK(fileinfo.st_mode)) {
|
||||
free(full_filename);
|
||||
|
||||
/* Don't open directories, character files, or block files. */
|
||||
statusline(ALERT, S_ISDIR(fileinfo.st_mode) ?
|
||||
_("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), filename);
|
||||
return -1;
|
||||
} else if ((fd = open(full_filename, O_RDONLY)) == -1) {
|
||||
statusline(ALERT, _("File \"%s\" not found"), filename);
|
||||
free(full_filename);
|
||||
statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
/* The file is A-OK. Open it. */
|
||||
}
|
||||
|
||||
/* Don't open directories, character files, or block files. */
|
||||
if (S_ISDIR(fileinfo.st_mode) || S_ISCHR(fileinfo.st_mode) ||
|
||||
S_ISBLK(fileinfo.st_mode)) {
|
||||
statusline(ALERT, S_ISDIR(fileinfo.st_mode) ?
|
||||
_("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), filename);
|
||||
free(full_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try opening the file. */
|
||||
fd = open(full_filename, O_RDONLY);
|
||||
|
||||
if (fd == -1)
|
||||
statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno));
|
||||
else {
|
||||
/* The file is A-OK. Associate a stream with it. */
|
||||
*f = fdopen(fd, "rb");
|
||||
|
||||
if (*f == NULL) {
|
||||
@@ -1070,6 +1062,9 @@ void do_insertfile(void)
|
||||
bool execute = FALSE, right_side_up = FALSE, single_line = FALSE;
|
||||
#endif
|
||||
|
||||
/* Display newlines in filenames as ^J. */
|
||||
as_an_at = FALSE;
|
||||
|
||||
while (TRUE) {
|
||||
#ifndef NANO_TINY
|
||||
if (execute) {
|
||||
@@ -1111,10 +1106,8 @@ void do_insertfile(void)
|
||||
"./");
|
||||
|
||||
/* If we're in multibuffer mode and the filename or command is
|
||||
* blank, open a new buffer instead of canceling. If the
|
||||
* filename or command begins with a newline (i.e. an encoded
|
||||
* null), treat it as though it's blank. */
|
||||
if (i == -1 || (!ISSET(MULTIBUFFER) && (i == -2 || *answer == '\n'))) {
|
||||
* blank, open a new buffer instead of canceling. */
|
||||
if (i == -1 || (i == -2 && !ISSET(MULTIBUFFER))) {
|
||||
statusbar(_("Cancelled"));
|
||||
break;
|
||||
} else {
|
||||
@@ -1186,10 +1179,6 @@ void do_insertfile(void)
|
||||
current_was_at_top = (openfile->edittop == openfile->fileage);
|
||||
}
|
||||
|
||||
/* Convert newlines to nulls in the given filename. */
|
||||
sunder(answer);
|
||||
align(&answer);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (execute) {
|
||||
#ifndef DISABLE_MULTIBUFFER
|
||||
@@ -1229,7 +1218,7 @@ void do_insertfile(void)
|
||||
#ifndef NANO_TINY
|
||||
if (!execute)
|
||||
#endif
|
||||
if (check_poshistory(answer, &priorline, &priorcol))
|
||||
if (has_old_position(answer, &priorline, &priorcol))
|
||||
do_gotolinecolumn(priorline, priorcol, FALSE, FALSE);
|
||||
}
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
@@ -1357,8 +1346,6 @@ char *get_full_path(const char *origpath)
|
||||
|
||||
/* If we succeeded, canonicalize it in d_here. */
|
||||
if (d_here != NULL) {
|
||||
align(&d_here);
|
||||
|
||||
/* If the current directory isn't "/", tack a slash onto the end
|
||||
* of it. */
|
||||
if (strcmp(d_here, "/") != 0) {
|
||||
@@ -1420,8 +1407,6 @@ char *get_full_path(const char *origpath)
|
||||
|
||||
/* If we succeeded, canonicalize it in d_there. */
|
||||
if (d_there != NULL) {
|
||||
align(&d_there);
|
||||
|
||||
/* If the current directory isn't "/", tack a slash onto
|
||||
* the end of it. */
|
||||
if (strcmp(d_there, "/") != 0) {
|
||||
@@ -1544,6 +1529,8 @@ void init_operating_dir(void)
|
||||
/* If the operating directory is inaccessible, fail. */
|
||||
if (full_operating_dir == NULL || chdir(full_operating_dir) == -1)
|
||||
die("Invalid operating directory\n");
|
||||
|
||||
snuggly_fit(&full_operating_dir);
|
||||
}
|
||||
|
||||
/* Check to see if we're inside the operating directory. Return FALSE
|
||||
@@ -1634,6 +1621,7 @@ void init_backup_dir(void)
|
||||
} else {
|
||||
free(backup_dir);
|
||||
backup_dir = full_backup_dir;
|
||||
snuggly_fit(&backup_dir);
|
||||
}
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
@@ -1711,8 +1699,6 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
char *tempname = NULL;
|
||||
/* The name of the temporary file we write to on prepend. */
|
||||
|
||||
assert(name != NULL);
|
||||
|
||||
if (*name == '\0')
|
||||
return -1;
|
||||
|
||||
@@ -2005,10 +1991,6 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
}
|
||||
}
|
||||
|
||||
/* There might not be a magicline. There won't be when writing out
|
||||
* a selection. */
|
||||
assert(openfile->fileage != NULL && openfile->filebot != NULL);
|
||||
|
||||
while (fileptr != NULL) {
|
||||
size_t data_len = strlen(fileptr->data), size;
|
||||
|
||||
@@ -2156,8 +2138,6 @@ bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
filestruct *top, *bot;
|
||||
size_t top_x, bot_x;
|
||||
|
||||
assert(openfile->mark_set);
|
||||
|
||||
/* Partition the filestruct so that it contains only the marked text. */
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
@@ -2205,6 +2185,9 @@ int do_writeout(bool exiting)
|
||||
static bool did_credits = FALSE;
|
||||
#endif
|
||||
|
||||
/* Display newlines in filenames as ^J. */
|
||||
as_an_at = FALSE;
|
||||
|
||||
if (exiting && ISSET(TEMP_FILE) && openfile->filename[0] != '\0') {
|
||||
if (write_file(openfile->filename, NULL, FALSE, OVERWRITE, FALSE))
|
||||
return 1;
|
||||
@@ -2232,6 +2215,7 @@ int do_writeout(bool exiting)
|
||||
* it allows reading from or writing to files not specified on
|
||||
* the command line. */
|
||||
if (openfile->mark_set && !exiting && !ISSET(RESTRICTED))
|
||||
/* TRANSLATORS: The next six strings are prompts. */
|
||||
msg = (method == PREPEND) ? _("Prepend Selection to File") :
|
||||
(method == APPEND) ? _("Append Selection to File") :
|
||||
_("Write Selection to File");
|
||||
@@ -2245,8 +2229,7 @@ int do_writeout(bool exiting)
|
||||
|
||||
/* If we're using restricted mode, and the filename isn't blank,
|
||||
* disable tab completion. */
|
||||
i = do_prompt(!ISSET(RESTRICTED) ||
|
||||
openfile->filename[0] == '\0',
|
||||
i = do_prompt(!ISSET(RESTRICTED) || openfile->filename[0] == '\0',
|
||||
#ifndef DISABLE_TABCOMP
|
||||
TRUE,
|
||||
#endif
|
||||
@@ -2262,9 +2245,7 @@ int do_writeout(bool exiting)
|
||||
#endif
|
||||
);
|
||||
|
||||
/* If the filename or command begins with a newline (i.e. an
|
||||
* encoded null), treat it as though it's blank. */
|
||||
if (i < 0 || *answer == '\n') {
|
||||
if (i < 0) {
|
||||
statusbar(_("Cancelled"));
|
||||
break;
|
||||
} else {
|
||||
@@ -2343,15 +2324,10 @@ int do_writeout(bool exiting)
|
||||
#endif
|
||||
|
||||
if (method == OVERWRITE) {
|
||||
size_t answer_len = strlen(answer);
|
||||
bool name_exists, do_warning;
|
||||
char *full_answer, *full_filename;
|
||||
struct stat st;
|
||||
|
||||
/* Convert newlines to nulls, just before we get the
|
||||
* full path. */
|
||||
sunder(answer);
|
||||
|
||||
full_answer = get_full_path(answer);
|
||||
full_filename = get_full_path(openfile->filename);
|
||||
name_exists = (stat((full_answer == NULL) ?
|
||||
@@ -2363,22 +2339,19 @@ int do_writeout(bool exiting)
|
||||
answer : full_answer, (full_filename == NULL) ?
|
||||
openfile->filename : full_filename) != 0);
|
||||
|
||||
/* Convert nulls to newlines. answer_len is the
|
||||
* string's real length. */
|
||||
unsunder(answer, answer_len);
|
||||
|
||||
free(full_filename);
|
||||
free(full_answer);
|
||||
|
||||
if (do_warning) {
|
||||
/* If we're using restricted mode, we aren't allowed
|
||||
* to overwrite an existing file with the current
|
||||
* file. We also aren't allowed to change the name
|
||||
* of the current file if it has one, because that
|
||||
* would allow reading from or writing to files not
|
||||
* specified on the command line. */
|
||||
if (ISSET(RESTRICTED))
|
||||
/* When in restricted mode, we aren't allowed to overwrite
|
||||
* an existing file with the current buffer, nor to change
|
||||
* the name of the current file if it already has one. */
|
||||
if (ISSET(RESTRICTED)) {
|
||||
/* TRANSLATORS: Restricted mode forbids overwriting. */
|
||||
warn_and_shortly_pause(_("File exists -- "
|
||||
"cannot overwrite"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!maychange) {
|
||||
#ifndef NANO_TINY
|
||||
@@ -2421,10 +2394,6 @@ int do_writeout(bool exiting)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert newlines to nulls, just before we save the file. */
|
||||
sunder(answer);
|
||||
align(&answer);
|
||||
|
||||
/* Here's where we allow the selected text to be written to
|
||||
* a separate file. If we're using restricted mode, this
|
||||
* function is disabled, since it allows reading from or
|
||||
@@ -2470,8 +2439,6 @@ char *real_dir_from_tilde(const char *buf)
|
||||
{
|
||||
char *retval;
|
||||
|
||||
assert(buf != NULL);
|
||||
|
||||
if (*buf == '~') {
|
||||
size_t i = 1;
|
||||
char *tilde_dir;
|
||||
@@ -2554,8 +2521,6 @@ bool is_dir(const char *buf)
|
||||
struct stat fileinfo;
|
||||
bool retval;
|
||||
|
||||
assert(buf != NULL);
|
||||
|
||||
dirptr = real_dir_from_tilde(buf);
|
||||
|
||||
retval = (stat(dirptr, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode));
|
||||
@@ -2752,31 +2717,26 @@ char *input_tab(char *buf, bool allow_files, size_t *place,
|
||||
char *mzero, *glued;
|
||||
const char *lastslash = revstrstr(buf, "/", buf + *place);
|
||||
size_t lastslash_len = (lastslash == NULL) ? 0 : lastslash - buf + 1;
|
||||
char *match1 = charalloc(mb_cur_max());
|
||||
char *match2 = charalloc(mb_cur_max());
|
||||
int match1_len, match2_len;
|
||||
char char1[mb_cur_max()], char2[mb_cur_max()];
|
||||
int len1, len2;
|
||||
|
||||
/* Get the number of characters that all matches have in common. */
|
||||
while (TRUE) {
|
||||
match1_len = parse_mbchar(matches[0] + common_len, match1, NULL);
|
||||
len1 = parse_mbchar(matches[0] + common_len, char1, NULL);
|
||||
|
||||
for (match = 1; match < num_matches; match++) {
|
||||
match2_len = parse_mbchar(matches[match] + common_len,
|
||||
match2, NULL);
|
||||
if (match1_len != match2_len ||
|
||||
strncmp(match1, match2, match2_len) != 0)
|
||||
len2 = parse_mbchar(matches[match] + common_len, char2, NULL);
|
||||
|
||||
if (len1 != len2 || strncmp(char1, char2, len2) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (match < num_matches || matches[0][common_len] == '\0')
|
||||
break;
|
||||
|
||||
common_len += match1_len;
|
||||
common_len += len1;
|
||||
}
|
||||
|
||||
free(match1);
|
||||
free(match2);
|
||||
|
||||
mzero = charalloc(lastslash_len + common_len + 1);
|
||||
|
||||
strncpy(mzero, buf, lastslash_len);
|
||||
@@ -3004,12 +2964,10 @@ void load_history(void)
|
||||
size_t buf_len = 0;
|
||||
ssize_t read;
|
||||
|
||||
while ((read = getline(&line, &buf_len, hist)) >= 0) {
|
||||
if (read > 0 && line[read - 1] == '\n') {
|
||||
read--;
|
||||
line[read] = '\0';
|
||||
}
|
||||
while ((read = getline(&line, &buf_len, hist)) > 0) {
|
||||
line[--read] = '\0';
|
||||
if (read > 0) {
|
||||
/* Encode any embedded NUL as 0x0A. */
|
||||
unsunder(line, read);
|
||||
update_history(history, line);
|
||||
} else
|
||||
@@ -3024,22 +2982,23 @@ void load_history(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the lines of a history list, starting with the line at h, to
|
||||
/* Write the lines of a history list, starting with the line at head, to
|
||||
* the open file at hist. Return TRUE if the write succeeded, and FALSE
|
||||
* otherwise. */
|
||||
bool writehist(FILE *hist, filestruct *h)
|
||||
bool writehist(FILE *hist, const filestruct *head)
|
||||
{
|
||||
filestruct *p;
|
||||
const filestruct *item;
|
||||
|
||||
/* Write a history list from the oldest entry to the newest. Assume
|
||||
* the last history entry is a blank line. */
|
||||
for (p = h; p != NULL; p = p->next) {
|
||||
size_t p_len = strlen(p->data);
|
||||
/* Write a history list from the oldest entry to the newest. */
|
||||
for (item = head; item != NULL; item = item->next) {
|
||||
size_t length = strlen(item->data);
|
||||
|
||||
sunder(p->data);
|
||||
/* Decode 0x0A bytes as embedded NULs. */
|
||||
sunder(item->data);
|
||||
|
||||
if (fwrite(p->data, sizeof(char), p_len, hist) < p_len ||
|
||||
putc('\n', hist) == EOF)
|
||||
if (fwrite(item->data, sizeof(char), length, hist) < length)
|
||||
return FALSE;
|
||||
if (putc('\n', hist) == EOF)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -3084,7 +3043,6 @@ void save_history(void)
|
||||
void save_poshistory(void)
|
||||
{
|
||||
char *poshist = poshistfilename();
|
||||
char *statusstr = NULL;
|
||||
poshiststruct *posptr;
|
||||
FILE *hist;
|
||||
|
||||
@@ -3100,14 +3058,25 @@ void save_poshistory(void)
|
||||
chmod(poshist, S_IRUSR | S_IWUSR);
|
||||
|
||||
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
|
||||
char *path_and_place;
|
||||
size_t length;
|
||||
|
||||
/* Assume 20 decimal positions each for line and column number,
|
||||
* plus two spaces, plus the line feed, plus the null byte. */
|
||||
statusstr = charalloc(strlen(posptr->filename) + 44);
|
||||
sprintf(statusstr, "%s %ld %ld\n", posptr->filename, (long)posptr->lineno,
|
||||
(long)posptr->xno);
|
||||
if (fwrite(statusstr, sizeof(char), strlen(statusstr), hist) < strlen(statusstr))
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), poshist, strerror(errno));
|
||||
free(statusstr);
|
||||
path_and_place = charalloc(strlen(posptr->filename) + 44);
|
||||
sprintf(path_and_place, "%s %ld %ld\n", posptr->filename,
|
||||
(long)posptr->lineno, (long)posptr->xno);
|
||||
length = strlen(path_and_place);
|
||||
|
||||
/* Encode newlines in filenames as nulls. */
|
||||
sunder(path_and_place);
|
||||
/* Restore the terminating newline. */
|
||||
path_and_place[length - 1] = '\n';
|
||||
|
||||
if (fwrite(path_and_place, sizeof(char), length, hist) < length)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"),
|
||||
poshist, strerror(errno));
|
||||
free(path_and_place);
|
||||
}
|
||||
fclose(hist);
|
||||
}
|
||||
@@ -3176,27 +3145,28 @@ void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos)
|
||||
free(fullpath);
|
||||
}
|
||||
|
||||
/* Check the recorded last file positions to see if the given file
|
||||
* matches an existing entry. If so, return 1 and set line and column
|
||||
* to the retrieved values. Otherwise, return 0. */
|
||||
int check_poshistory(const char *file, ssize_t *line, ssize_t *column)
|
||||
/* Check whether the given file matches an existing entry in the recorded
|
||||
* last file positions. If not, return FALSE. If yes, return TRUE and
|
||||
* set line and column to the retrieved values. */
|
||||
bool has_old_position(const char *file, ssize_t *line, ssize_t *column)
|
||||
{
|
||||
poshiststruct *posptr;
|
||||
poshiststruct *posptr = position_history;
|
||||
char *fullpath = get_full_path(file);
|
||||
|
||||
if (fullpath == NULL)
|
||||
return 0;
|
||||
return FALSE;
|
||||
|
||||
while (posptr != NULL && strcmp(posptr->filename, fullpath) != 0)
|
||||
posptr = posptr->next;
|
||||
|
||||
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
|
||||
if (!strcmp(posptr->filename, fullpath)) {
|
||||
*line = posptr->lineno;
|
||||
*column = posptr->xno;
|
||||
free(fullpath);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
free(fullpath);
|
||||
return 0;
|
||||
|
||||
if (posptr == NULL)
|
||||
return FALSE;
|
||||
|
||||
*line = posptr->lineno;
|
||||
*column = posptr->xno;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Load the recorded file positions from ~/.nano/filepos_history. */
|
||||
@@ -3224,13 +3194,21 @@ void load_poshistory(void)
|
||||
poshiststruct *record_ptr = NULL, *newrecord;
|
||||
|
||||
/* Read and parse each line, and store the extracted data. */
|
||||
while ((read = getline(&line, &buf_len, hist)) > 2) {
|
||||
if (line[read - 1] == '\n')
|
||||
line[--read] = '\0';
|
||||
while ((read = getline(&line, &buf_len, hist)) > 5) {
|
||||
/* Decode nulls as embedded newlines. */
|
||||
unsunder(line, read);
|
||||
|
||||
lineptr = parse_next_word(line);
|
||||
xptr = parse_next_word(lineptr);
|
||||
/* Find where the x index and line number are in the line. */
|
||||
xptr = revstrstr(line, " ", line + read - 3);
|
||||
if (xptr == NULL)
|
||||
continue;
|
||||
lineptr = revstrstr(line, " ", xptr - 2);
|
||||
if (lineptr == NULL)
|
||||
continue;
|
||||
|
||||
/* Now separate the three elements of the line. */
|
||||
*(xptr++) = '\0';
|
||||
*(lineptr++) = '\0';
|
||||
|
||||
/* Create a new position record. */
|
||||
newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct));
|
||||
|
||||
54
src/global.c
54
src/global.c
@@ -29,8 +29,8 @@
|
||||
|
||||
/* Global variables. */
|
||||
#ifndef NANO_TINY
|
||||
volatile sig_atomic_t sigwinch_counter = 0;
|
||||
/* Is incremented by the handler whenever a SIGWINCH occurs. */
|
||||
volatile sig_atomic_t the_window_resized = FALSE;
|
||||
/* Set to TRUE by the handler whenever a SIGWINCH occurs. */
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -45,20 +45,20 @@ bool shift_held;
|
||||
bool focusing = TRUE;
|
||||
/* Whether an update of the edit window should center the cursor. */
|
||||
|
||||
bool as_an_at = TRUE;
|
||||
/* Whether a 0x0A byte should be shown as a ^@ instead of a ^J. */
|
||||
|
||||
int margin = 0;
|
||||
/* The amount of space reserved at the left for line numbers. */
|
||||
int editwincols = -1;
|
||||
/* The number of usable columns in the edit window: COLS - margin. */
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
int last_drawn_line = 0;
|
||||
/* The line number of the last drawn line. */
|
||||
int last_line_y;
|
||||
/* The y coordinate of the last drawn line. */
|
||||
#endif
|
||||
|
||||
message_type lastmessage = HUSH;
|
||||
/* Messages of type HUSH should not overwrite type MILD nor ALERT. */
|
||||
|
||||
filestruct *pletion_line = NULL;
|
||||
/* The line where the last completion was found, if any. */
|
||||
|
||||
int controlleft, controlright, controlup, controldown;
|
||||
#ifndef NANO_TINY
|
||||
int shiftcontrolleft, shiftcontrolright, shiftcontrolup, shiftcontroldown;
|
||||
@@ -388,18 +388,17 @@ const sc *first_sc_for(int menu, void (*func)(void))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the given menu's first shortcut sequence, or the default value
|
||||
* (2nd arg). Assumes currmenu for the menu to check. */
|
||||
int sc_seq_or(void (*func)(void), int defaultval)
|
||||
/* Return the first keycode that is bound to the given function in the
|
||||
* current menu, if any; otherwise, return the given default value. */
|
||||
int the_code_for(void (*func)(void), int defaultval)
|
||||
{
|
||||
const sc *s = first_sc_for(currmenu, func);
|
||||
|
||||
if (s) {
|
||||
meta_key = s->meta;
|
||||
return s->keycode;
|
||||
}
|
||||
/* else */
|
||||
return defaultval;
|
||||
if (s == NULL)
|
||||
return defaultval;
|
||||
|
||||
meta_key = s->meta;
|
||||
return s->keycode;
|
||||
}
|
||||
|
||||
/* Return a pointer to the function that is bound to the given key. */
|
||||
@@ -531,9 +530,6 @@ void shortcut_init(void)
|
||||
N_("Copy the current line and store it in the cutbuffer");
|
||||
const char *nano_indent_msg = N_("Indent the current line");
|
||||
const char *nano_unindent_msg = N_("Unindent the current line");
|
||||
#ifdef ENABLE_COMMENT
|
||||
const char *nano_comment_msg = N_("Comment/uncomment the current line or marked lines");
|
||||
#endif
|
||||
const char *nano_undo_msg = N_("Undo the last operation");
|
||||
const char *nano_redo_msg = N_("Redo the last undone operation");
|
||||
#endif
|
||||
@@ -591,6 +587,13 @@ void shortcut_init(void)
|
||||
N_("Refresh (redraw) the current screen");
|
||||
const char *nano_suspend_msg =
|
||||
N_("Suspend the editor (if suspension is enabled)");
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
const char *nano_completion_msg = N_("Try and complete the current word");
|
||||
#endif
|
||||
#ifdef ENABLE_COMMENT
|
||||
const char *nano_comment_msg =
|
||||
N_("Comment/uncomment the current line or marked lines");
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
const char *nano_savefile_msg = N_("Save file without prompting");
|
||||
const char *nano_findprev_msg = N_("Search next occurrence backward");
|
||||
@@ -925,6 +928,10 @@ void shortcut_init(void)
|
||||
add_to_funcs(do_suspend_void, MMAIN,
|
||||
N_("Suspend"), IFSCHELP(nano_suspend_msg), BLANKAFTER, VIEW);
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
add_to_funcs(complete_a_word, MMAIN,
|
||||
N_("Complete"), IFSCHELP(nano_completion_msg), TOGETHER, NOVIEW);
|
||||
#endif
|
||||
#ifdef ENABLE_COMMENT
|
||||
add_to_funcs(do_comment, MMAIN,
|
||||
N_("Comment Lines"), IFSCHELP(nano_comment_msg), BLANKAFTER, NOVIEW);
|
||||
@@ -1096,6 +1103,9 @@ void shortcut_init(void)
|
||||
add_to_sclist(MMAIN, "M-U", 0, do_undo, 0);
|
||||
add_to_sclist(MMAIN, "M-E", 0, do_redo, 0);
|
||||
#endif
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
add_to_sclist(MMAIN, "^]", 0, complete_a_word, 0);
|
||||
#endif
|
||||
#ifdef ENABLE_COMMENT
|
||||
add_to_sclist(MMAIN, "M-3", 0, do_comment, 0);
|
||||
#endif
|
||||
@@ -1443,6 +1453,10 @@ sc *strtosc(const char *input)
|
||||
else if (!strcasecmp(input, "comment"))
|
||||
s->scfunc = do_comment;
|
||||
#endif
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
else if (!strcasecmp(input, "complete"))
|
||||
s->scfunc = complete_a_word;
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
else if (!strcasecmp(input, "indent"))
|
||||
s->scfunc = do_indent_void;
|
||||
|
||||
35
src/move.c
35
src/move.c
@@ -56,10 +56,7 @@ void do_page_up(void)
|
||||
|
||||
/* If the cursor is less than a page away from the top of the file,
|
||||
* put it at the beginning of the first line. */
|
||||
if (openfile->current->lineno == 1 || (
|
||||
#ifndef NANO_TINY
|
||||
!ISSET(SOFTWRAP) &&
|
||||
#endif
|
||||
if (openfile->current->lineno == 1 || (!ISSET(SOFTWRAP) &&
|
||||
openfile->current->lineno <= editwinrows - 2)) {
|
||||
do_first_line();
|
||||
return;
|
||||
@@ -67,10 +64,7 @@ void do_page_up(void)
|
||||
|
||||
/* If we're not in smooth scrolling mode, put the cursor at the
|
||||
* beginning of the top line of the edit window, as Pico does. */
|
||||
#ifndef NANO_TINY
|
||||
if (!ISSET(SMOOTH_SCROLL))
|
||||
#endif
|
||||
{
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
openfile->current = openfile->edittop;
|
||||
openfile->placewewant = openfile->current_y = 0;
|
||||
}
|
||||
@@ -81,9 +75,9 @@ void do_page_up(void)
|
||||
openfile->current = openfile->current->prev;
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP) && openfile->current) {
|
||||
skipped += strlenpt(openfile->current->data) / COLS;
|
||||
skipped += strlenpt(openfile->current->data) / editwincols;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_page_up: i = %d, skipped = %d based on line %ld len %lu\n",
|
||||
fprintf(stderr, "paging up: i = %d, skipped = %d based on line %ld len %lu\n",
|
||||
i, skipped, (long)openfile->current->lineno, (unsigned long)strlenpt(openfile->current->data));
|
||||
#endif
|
||||
}
|
||||
@@ -93,11 +87,6 @@ void do_page_up(void)
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
openfile->placewewant);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_page_up: openfile->current->lineno = %lu, skipped = %d\n",
|
||||
(unsigned long)openfile->current->lineno, skipped);
|
||||
#endif
|
||||
|
||||
/* Scroll the edit window up a page. */
|
||||
adjust_viewport(STATIONARY);
|
||||
refresh_needed = TRUE;
|
||||
@@ -117,10 +106,7 @@ void do_page_down(void)
|
||||
|
||||
/* If we're not in smooth scrolling mode, put the cursor at the
|
||||
* beginning of the top line of the edit window, as Pico does. */
|
||||
#ifndef NANO_TINY
|
||||
if (!ISSET(SMOOTH_SCROLL))
|
||||
#endif
|
||||
{
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
openfile->current = openfile->edittop;
|
||||
openfile->placewewant = openfile->current_y = 0;
|
||||
}
|
||||
@@ -130,7 +116,7 @@ void do_page_down(void)
|
||||
for (i = mustmove; i > 0 && openfile->current != openfile->filebot; i--) {
|
||||
openfile->current = openfile->current->next;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_page_down: moving to line %lu\n", (unsigned long)openfile->current->lineno);
|
||||
fprintf(stderr, "paging down: moving to line %lu\n", (unsigned long)openfile->current->lineno);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -424,11 +410,8 @@ void do_up(bool scroll_only)
|
||||
|
||||
/* If we're at the top of the file, or if scroll_only is TRUE and
|
||||
* the top of the file is onscreen, get out. */
|
||||
if (openfile->current == openfile->fileage
|
||||
#ifndef NANO_TINY
|
||||
|| (scroll_only && openfile->edittop == openfile->fileage)
|
||||
#endif
|
||||
)
|
||||
if (openfile->current == openfile->fileage ||
|
||||
(scroll_only && openfile->edittop == openfile->fileage))
|
||||
return;
|
||||
|
||||
assert(ISSET(SOFTWRAP) || openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);
|
||||
@@ -593,7 +576,7 @@ void do_right(void)
|
||||
openfile->current_x = 0;
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP))
|
||||
openfile->current_y -= strlenpt(openfile->current->data) / COLS;
|
||||
openfile->current_y -= strlenpt(openfile->current->data) / editwincols;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
204
src/nano.c
204
src/nano.c
@@ -78,8 +78,6 @@ filestruct *copy_node(const filestruct *src)
|
||||
{
|
||||
filestruct *dst;
|
||||
|
||||
assert(src != NULL);
|
||||
|
||||
dst = (filestruct *)nmalloc(sizeof(filestruct));
|
||||
|
||||
dst->data = mallocstrcpy(NULL, src->data);
|
||||
@@ -96,8 +94,6 @@ filestruct *copy_node(const filestruct *src)
|
||||
/* Splice a new node into an existing linked list of filestructs. */
|
||||
void splice_node(filestruct *afterthis, filestruct *newnode)
|
||||
{
|
||||
assert(afterthis != NULL && newnode != NULL);
|
||||
|
||||
newnode->next = afterthis->next;
|
||||
newnode->prev = afterthis;
|
||||
if (afterthis->next != NULL)
|
||||
@@ -112,8 +108,6 @@ void splice_node(filestruct *afterthis, filestruct *newnode)
|
||||
/* Disconnect a node from a linked list of filestructs and delete it. */
|
||||
void unlink_node(filestruct *fileptr)
|
||||
{
|
||||
assert(fileptr != NULL);
|
||||
|
||||
if (fileptr->prev != NULL)
|
||||
fileptr->prev->next = fileptr->next;
|
||||
if (fileptr->next != NULL)
|
||||
@@ -129,8 +123,6 @@ void unlink_node(filestruct *fileptr)
|
||||
/* Free the data structures in the given node. */
|
||||
void delete_node(filestruct *fileptr)
|
||||
{
|
||||
assert(fileptr != NULL && fileptr->data != NULL);
|
||||
|
||||
free(fileptr->data);
|
||||
#ifndef DISABLE_COLOR
|
||||
free(fileptr->multidata);
|
||||
@@ -143,8 +135,6 @@ filestruct *copy_filestruct(const filestruct *src)
|
||||
{
|
||||
filestruct *head, *copy;
|
||||
|
||||
assert(src != NULL);
|
||||
|
||||
copy = copy_node(src);
|
||||
copy->prev = NULL;
|
||||
head = copy;
|
||||
@@ -237,7 +227,6 @@ partition *partition_filestruct(filestruct *top, size_t top_x,
|
||||
|
||||
/* Remove all text before top_x at the top of the partition. */
|
||||
charmove(top->data, top->data + top_x, strlen(top->data) - top_x + 1);
|
||||
align(&top->data);
|
||||
|
||||
/* Return the partition. */
|
||||
return p;
|
||||
@@ -513,8 +502,7 @@ openfilestruct *make_new_opennode(void)
|
||||
/* Unlink a node from the rest of the openfilestruct, and delete it. */
|
||||
void unlink_opennode(openfilestruct *fileptr)
|
||||
{
|
||||
assert(fileptr != NULL && fileptr->prev != NULL && fileptr->next != NULL &&
|
||||
fileptr != fileptr->prev && fileptr != fileptr->next);
|
||||
assert(fileptr != fileptr->prev && fileptr != fileptr->next);
|
||||
|
||||
fileptr->prev->next = fileptr->next;
|
||||
fileptr->next->prev = fileptr->prev;
|
||||
@@ -525,8 +513,6 @@ void unlink_opennode(openfilestruct *fileptr)
|
||||
/* Free all the memory in the given open-file node. */
|
||||
void delete_opennode(openfilestruct *fileptr)
|
||||
{
|
||||
assert(fileptr != NULL && fileptr->filename != NULL && fileptr->fileage != NULL);
|
||||
|
||||
free(fileptr->filename);
|
||||
free_filestruct(fileptr->fileage);
|
||||
#ifndef NANO_TINY
|
||||
@@ -1033,6 +1019,9 @@ void version(void)
|
||||
#ifdef DISABLE_TABCOMP
|
||||
printf(" --disable-tabcomp");
|
||||
#endif
|
||||
#ifndef ENABLE_WORDCOMPLETION
|
||||
printf(" --disable-wordcomp");
|
||||
#endif
|
||||
#ifdef DISABLE_WRAPPING
|
||||
printf(" --disable-wrapping");
|
||||
#endif
|
||||
@@ -1058,21 +1047,6 @@ void version(void)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Indicate that the current file has no name, in a way that gets the
|
||||
* user's attention. This is used when trying to save a file with no
|
||||
* name with the TEMP_FILE flag set, just before the filename prompt. */
|
||||
void no_current_file_name_warning(void)
|
||||
{
|
||||
/* Warn that the current file has no name. */
|
||||
statusbar(_("No file name"));
|
||||
beep();
|
||||
|
||||
/* Ensure that we see the warning. */
|
||||
napms(1800);
|
||||
|
||||
curs_set(1);
|
||||
}
|
||||
|
||||
/* If the current file buffer has been modified, and the TEMP_FILE flag
|
||||
* isn't set, ask whether or not to save the file buffer. If the
|
||||
* TEMP_FILE flag is set and the current file has a name, save it
|
||||
@@ -1096,7 +1070,7 @@ void do_exit(void)
|
||||
/* If the TEMP_FILE flag is set, and the current file doesn't
|
||||
* have a name, warn the user before prompting for a name. */
|
||||
if (ISSET(TEMP_FILE))
|
||||
no_current_file_name_warning();
|
||||
warn_and_shortly_pause(_("No file name"));
|
||||
|
||||
i = do_yesno_prompt(FALSE, _("Save modified buffer? "
|
||||
"(Answering \"No\" will DISCARD changes.) "));
|
||||
@@ -1304,12 +1278,8 @@ RETSIGTYPE do_continue(int signal)
|
||||
* and restore the terminal to its previous state in the process. */
|
||||
regenerate_screen();
|
||||
#else
|
||||
/* Restore the terminal to its previous state. */
|
||||
/* Restore the state of the terminal and redraw the whole screen. */
|
||||
terminal_init();
|
||||
|
||||
/* Wipe statusbar; redraw titlebar and edit window (and help lines). */
|
||||
blank_statusbar();
|
||||
wnoutrefresh(bottomwin);
|
||||
total_refresh();
|
||||
#endif
|
||||
}
|
||||
@@ -1319,7 +1289,7 @@ RETSIGTYPE do_continue(int signal)
|
||||
RETSIGTYPE handle_sigwinch(int signal)
|
||||
{
|
||||
/* Let the input routine know that a SIGWINCH has occurred. */
|
||||
sigwinch_counter++;
|
||||
the_window_resized = TRUE;
|
||||
}
|
||||
|
||||
/* Reinitialize and redraw the screen completely. */
|
||||
@@ -1329,6 +1299,9 @@ void regenerate_screen(void)
|
||||
int fd, result = 0;
|
||||
struct winsize win;
|
||||
|
||||
/* Reset the trigger. */
|
||||
the_window_resized = FALSE;
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
fd = open(tty, O_RDWR);
|
||||
@@ -1416,9 +1389,7 @@ void do_toggle(int flag)
|
||||
signal_init();
|
||||
break;
|
||||
case WHITESPACE_DISPLAY:
|
||||
titlebar(NULL);
|
||||
edit_refresh();
|
||||
break;
|
||||
titlebar(NULL); /* Fall through. */
|
||||
#ifndef DISABLE_COLOR
|
||||
case NO_COLOR_SYNTAX:
|
||||
#endif
|
||||
@@ -1432,14 +1403,7 @@ void do_toggle(int flag)
|
||||
|
||||
enabled = ISSET(flag);
|
||||
|
||||
if (flag == NO_HELP
|
||||
#ifndef DISABLE_WRAPPING
|
||||
|| flag == NO_WRAP
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
|| flag == NO_COLOR_SYNTAX
|
||||
#endif
|
||||
)
|
||||
if (flag == NO_HELP || flag == NO_WRAP || flag == NO_COLOR_SYNTAX)
|
||||
enabled = !enabled;
|
||||
|
||||
statusline(HUSH, "%s %s", _(flagtostr(flag)),
|
||||
@@ -1553,18 +1517,18 @@ void terminal_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_KEY_DEFINED
|
||||
/* Ask ncurses for a keycode, or assign a default one. */
|
||||
int get_keycode(const char *keyname, const int standard)
|
||||
{
|
||||
#ifdef HAVE_KEY_DEFINED
|
||||
const char *keyvalue = tigetstr(keyname);
|
||||
|
||||
if (keyvalue == 0 || keyvalue == (char *)-1)
|
||||
return standard;
|
||||
else
|
||||
if (keyvalue != 0 && keyvalue != (char *)-1)
|
||||
return key_defined(keyvalue);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return standard;
|
||||
}
|
||||
|
||||
/* Say that an unbound key was struck, and if possible which one. */
|
||||
void unbound_key(int code)
|
||||
@@ -1682,7 +1646,9 @@ int do_input(bool allow_funcs)
|
||||
}
|
||||
}
|
||||
|
||||
if (have_shortcut) {
|
||||
if (!have_shortcut)
|
||||
pletion_line = NULL;
|
||||
else {
|
||||
const subnfunc *f = sctofunc(s);
|
||||
|
||||
if (ISSET(VIEW_MODE) && f && !f->viewok) {
|
||||
@@ -1699,6 +1665,10 @@ int do_input(bool allow_funcs)
|
||||
)
|
||||
preserve = TRUE;
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
if (s->scfunc != complete_a_word)
|
||||
pletion_line = NULL;
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
if (s->scfunc == do_toggle_void) {
|
||||
do_toggle(s->toggle);
|
||||
@@ -1785,32 +1755,21 @@ int do_mouse(void)
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
size_t i = 0;
|
||||
for (openfile->current = openfile->edittop;
|
||||
openfile->current->next && i < mouse_y;
|
||||
openfile->current = openfile->current->next, i++) {
|
||||
|
||||
openfile->current = openfile->edittop;
|
||||
|
||||
while (openfile->current->next != NULL && i < mouse_y) {
|
||||
openfile->current_y = i;
|
||||
i += strlenpt(openfile->current->data) / COLS;
|
||||
i += strlenpt(openfile->current->data) / editwincols + 1;
|
||||
openfile->current = openfile->current->next;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_mouse(): moving to current_y = %ld, index i = %lu\n",
|
||||
(long)openfile->current_y, (unsigned long)i);
|
||||
fprintf(stderr, " openfile->current->data = \"%s\"\n", openfile->current->data);
|
||||
#endif
|
||||
|
||||
if (i > mouse_y) {
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->current_x = actual_x(openfile->current->data, mouse_x + (mouse_y - openfile->current_y) * COLS);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_mouse(): i > mouse_y, mouse_x = %d, current_x to = %lu\n",
|
||||
mouse_x, (unsigned long)openfile->current_x);
|
||||
#endif
|
||||
} else {
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
mouse_x + (mouse_y - openfile->current_y) * editwincols);
|
||||
} else
|
||||
openfile->current_x = actual_x(openfile->current->data, mouse_x);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_mouse(): i <= mouse_y, mouse_x = %d, setting current_x to = %lu\n",
|
||||
mouse_x, (unsigned long)openfile->current_x);
|
||||
#endif
|
||||
}
|
||||
} else
|
||||
#endif /* NANO_TINY */
|
||||
{
|
||||
@@ -1854,11 +1813,8 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
#ifndef NANO_TINY
|
||||
size_t orig_lenpt = 0;
|
||||
#endif
|
||||
|
||||
char *char_buf = charalloc(mb_cur_max());
|
||||
int char_buf_len;
|
||||
|
||||
assert(openfile->current != NULL && openfile->current->data != NULL);
|
||||
int char_len;
|
||||
|
||||
current_len = strlen(openfile->current->data);
|
||||
|
||||
@@ -1868,25 +1824,17 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
#endif
|
||||
|
||||
while (i < output_len) {
|
||||
/* If control codes are allowed, encode a verbatim null as a newline,
|
||||
* and let a verbatim ^J create a whole new line. */
|
||||
if (allow_cntrls) {
|
||||
if (output[i] == '\0')
|
||||
output[i] = '\n';
|
||||
else if (output[i] == '\n') {
|
||||
do_enter();
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Encode an embedded NUL byte as 0x0A. */
|
||||
if (output[i] == '\0')
|
||||
output[i] = '\n';
|
||||
|
||||
/* Get the next multibyte character. */
|
||||
char_buf_len = parse_mbchar(output + i, char_buf, NULL);
|
||||
char_len = parse_mbchar(output + i, char_buf, NULL);
|
||||
|
||||
i += char_buf_len;
|
||||
i += char_len;
|
||||
|
||||
/* If controls are not allowed, ignore an ASCII control character. */
|
||||
if (!allow_cntrls && is_ascii_cntrl_char(*(output + i - char_buf_len)))
|
||||
if (!allow_cntrls && is_ascii_cntrl_char(*(output + i - char_len)))
|
||||
continue;
|
||||
|
||||
/* If we're adding to the magicline, create a new magicline. */
|
||||
@@ -1900,13 +1848,13 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
|
||||
/* Make room for the new character and copy it into the line. */
|
||||
openfile->current->data = charealloc(openfile->current->data,
|
||||
current_len + char_buf_len + 1);
|
||||
charmove(openfile->current->data + openfile->current_x + char_buf_len,
|
||||
current_len + char_len + 1);
|
||||
charmove(openfile->current->data + openfile->current_x + char_len,
|
||||
openfile->current->data + openfile->current_x,
|
||||
current_len - openfile->current_x + 1);
|
||||
strncpy(openfile->current->data + openfile->current_x, char_buf,
|
||||
char_buf_len);
|
||||
current_len += char_buf_len;
|
||||
char_len);
|
||||
current_len += char_len;
|
||||
openfile->totsize++;
|
||||
set_modified();
|
||||
|
||||
@@ -1916,30 +1864,29 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
/* Note that current_x has not yet been incremented. */
|
||||
if (openfile->mark_set && openfile->current == openfile->mark_begin &&
|
||||
openfile->current_x < openfile->mark_begin_x)
|
||||
openfile->mark_begin_x += char_buf_len;
|
||||
openfile->mark_begin_x += char_len;
|
||||
#endif
|
||||
|
||||
openfile->current_x += char_buf_len;
|
||||
openfile->current_x += char_len;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
update_undo(ADD);
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPPING
|
||||
/* If we're wrapping text, we need to call edit_refresh(). */
|
||||
if (!ISSET(NO_WRAP))
|
||||
if (do_wrap(openfile->current))
|
||||
refresh_needed = TRUE;
|
||||
/* If text gets wrapped, the edit window needs a refresh. */
|
||||
if (!ISSET(NO_WRAP) && do_wrap(openfile->current))
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
ensure_line_is_visible();
|
||||
|
||||
/* Well, we might also need a full refresh if we've changed the
|
||||
* line length to be a new multiple of COLS. */
|
||||
/* If the number of screen rows that a softwrapped line occupies
|
||||
* has changed, we need a full refresh. */
|
||||
if (ISSET(SOFTWRAP) && refresh_needed == FALSE)
|
||||
if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS)
|
||||
if (strlenpt(openfile->current->data) / editwincols != orig_lenpt / editwincols)
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
|
||||
@@ -2081,6 +2028,10 @@ int main(int argc, char **argv)
|
||||
SET(NO_WRAP);
|
||||
#endif
|
||||
|
||||
/* If the executable's name starts with 'r', activate restricted mode. */
|
||||
if (*(tail(argv[0])) == 'r')
|
||||
SET(RESTRICTED);
|
||||
|
||||
while ((optchr =
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
getopt_long(argc, argv,
|
||||
@@ -2298,11 +2249,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* If the executable filename starts with 'r', enable restricted
|
||||
* mode. */
|
||||
if (*(tail(argv[0])) == 'r')
|
||||
SET(RESTRICTED);
|
||||
|
||||
/* If we're using restricted mode, disable suspending, backups,
|
||||
* rcfiles, and history files, since they all would allow reading
|
||||
* from or writing to files not specified on the command line. */
|
||||
@@ -2361,7 +2307,7 @@ int main(int argc, char **argv)
|
||||
alt_speller = NULL;
|
||||
#endif
|
||||
|
||||
do_rcfile();
|
||||
do_rcfiles();
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "After rebinding keys...\n");
|
||||
@@ -2580,14 +2526,12 @@ int main(int argc, char **argv)
|
||||
interface_color_pair[FUNCTION_TAG] = A_NORMAL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KEY_DEFINED
|
||||
/* Ask ncurses for the key codes for Control+Left/Right/Up/Down. */
|
||||
controlleft = get_keycode("kLFT5", CONTROL_LEFT);
|
||||
controlright = get_keycode("kRIT5", CONTROL_RIGHT);
|
||||
controlup = get_keycode("kUP5", CONTROL_UP);
|
||||
controldown = get_keycode("kDN5", CONTROL_DOWN);
|
||||
#endif
|
||||
#if !defined(NANO_TINY) && defined(HAVE_KEY_DEFINED)
|
||||
#ifndef NANO_TINY
|
||||
/* Ask for the codes for Shift+Control+Left/Right/Up/Down. */
|
||||
shiftcontrolleft = get_keycode("kLFT6", SHIFT_CONTROL_LEFT);
|
||||
shiftcontrolright = get_keycode("kRIT6", SHIFT_CONTROL_RIGHT);
|
||||
@@ -2654,7 +2598,7 @@ int main(int argc, char **argv)
|
||||
else if (ISSET(POS_HISTORY)) {
|
||||
ssize_t savedposline, savedposcol;
|
||||
/* If edited before, restore the last cursor position. */
|
||||
if (check_poshistory(argv[i], &savedposline, &savedposcol))
|
||||
if (has_old_position(argv[i], &savedposline, &savedposcol))
|
||||
do_gotolinecolumn(savedposline, savedposcol,
|
||||
FALSE, FALSE);
|
||||
}
|
||||
@@ -2688,7 +2632,7 @@ int main(int argc, char **argv)
|
||||
else if (ISSET(POS_HISTORY)) {
|
||||
ssize_t savedposline, savedposcol;
|
||||
/* If the file was edited before, restore the last cursor position. */
|
||||
if (check_poshistory(argv[optind], &savedposline, &savedposcol))
|
||||
if (has_old_position(argv[optind], &savedposline, &savedposcol))
|
||||
do_gotolinecolumn(savedposline, savedposcol, FALSE, FALSE);
|
||||
}
|
||||
#endif
|
||||
@@ -2721,27 +2665,29 @@ int main(int argc, char **argv)
|
||||
if (currmenu != MMAIN)
|
||||
display_main_list();
|
||||
|
||||
focusing = TRUE;
|
||||
lastmessage = HUSH;
|
||||
as_an_at = TRUE;
|
||||
|
||||
/* If constant cursor position display is on, and there are no
|
||||
* keys waiting in the input buffer, display the current cursor
|
||||
* position on the statusbar. */
|
||||
/* Update the displayed current cursor position only when there
|
||||
* are no keys waiting in the input buffer. */
|
||||
if (ISSET(CONST_UPDATE) && get_key_buffer_len() == 0)
|
||||
do_cursorpos(TRUE);
|
||||
|
||||
/* Refresh just the cursor position or the entire edit window. */
|
||||
if (!refresh_needed) {
|
||||
reset_cursor();
|
||||
wnoutrefresh(edit);
|
||||
} else
|
||||
edit_refresh();
|
||||
|
||||
/* Make sure the cursor is visible. */
|
||||
curs_set(1);
|
||||
|
||||
focusing = TRUE;
|
||||
|
||||
/* Forget any earlier statusbar x position. */
|
||||
reinit_statusbar_x();
|
||||
|
||||
/* Refresh either the entire edit window or just the cursor. */
|
||||
if (refresh_needed)
|
||||
edit_refresh();
|
||||
else {
|
||||
reset_cursor();
|
||||
curs_set(1);
|
||||
wnoutrefresh(edit);
|
||||
}
|
||||
|
||||
/* Read in and interpret keystrokes. */
|
||||
do_input(TRUE);
|
||||
}
|
||||
|
||||
@@ -484,6 +484,13 @@ typedef struct subnfunc {
|
||||
/* Next item in the list. */
|
||||
} subnfunc;
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
typedef struct completion_word {
|
||||
char *word;
|
||||
struct completion_word *next;
|
||||
} completion_word;
|
||||
#endif
|
||||
|
||||
/* The elements of the interface that can be colored differently. */
|
||||
enum
|
||||
{
|
||||
|
||||
118
src/prompt.c
118
src/prompt.c
@@ -34,10 +34,8 @@ static size_t statusbar_x = HIGHEST_POSITIVE;
|
||||
/* Read in a keystroke, interpret it if it is a shortcut or toggle, and
|
||||
* return it. Set ran_func to TRUE if we ran a function associated with
|
||||
* a shortcut key, and set finished to TRUE if we're done after running
|
||||
* or trying to run a function associated with a shortcut key.
|
||||
* refresh_func is the function we will call to refresh the edit window. */
|
||||
int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
void (*refresh_func)(void))
|
||||
* or trying to run a function associated with a shortcut key. */
|
||||
int do_statusbar_input(bool *ran_func, bool *finished)
|
||||
{
|
||||
int input;
|
||||
/* The character we read in. */
|
||||
@@ -106,7 +104,7 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
if ((have_shortcut || get_key_buffer_len() == 0) && kbinput != NULL) {
|
||||
/* Inject all characters in the input buffer at once, filtering out
|
||||
* control characters. */
|
||||
do_statusbar_output(kbinput, kbinput_len, TRUE, NULL);
|
||||
do_statusbar_output(kbinput, kbinput_len, TRUE);
|
||||
|
||||
/* Empty the input buffer. */
|
||||
kbinput_len = 0;
|
||||
@@ -117,10 +115,7 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
if (have_shortcut) {
|
||||
if (s->scfunc == do_tab || s->scfunc == do_enter)
|
||||
;
|
||||
else if (s->scfunc == total_refresh) {
|
||||
total_redraw();
|
||||
refresh_func();
|
||||
} else if (s->scfunc == do_left)
|
||||
else if (s->scfunc == do_left)
|
||||
do_statusbar_left();
|
||||
else if (s->scfunc == do_right)
|
||||
do_statusbar_right();
|
||||
@@ -144,18 +139,7 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
s->scfunc == do_backspace))
|
||||
;
|
||||
else if (s->scfunc == do_verbatim_input) {
|
||||
bool got_newline = FALSE;
|
||||
/* Whether we got a verbatim ^J. */
|
||||
|
||||
do_statusbar_verbatim_input(&got_newline);
|
||||
|
||||
/* If we got a verbatim ^J, remove it from the input buffer,
|
||||
* fake a press of Enter, and indicate that we're done. */
|
||||
if (got_newline) {
|
||||
get_input(NULL, 1);
|
||||
input = sc_seq_or(do_enter, 0);
|
||||
*finished = TRUE;
|
||||
}
|
||||
do_statusbar_verbatim_input();
|
||||
} else if (s->scfunc == do_cut_text_void)
|
||||
do_statusbar_cut_text();
|
||||
else if (s->scfunc == do_delete)
|
||||
@@ -207,11 +191,10 @@ int do_statusbar_mouse(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The user typed input_len multibyte characters. Add them to the
|
||||
* statusbar prompt, setting got_newline to TRUE if we got a verbatim ^J,
|
||||
* and filtering out ASCII control characters if filtering is TRUE. */
|
||||
/* The user typed input_len multibyte characters. Add them to the answer,
|
||||
* filtering out ASCII control characters if filtering is TRUE. */
|
||||
void do_statusbar_output(int *the_input, size_t input_len,
|
||||
bool filtering, bool *got_newline)
|
||||
bool filtering)
|
||||
{
|
||||
char *output = charalloc(input_len + 1);
|
||||
char *char_buf = charalloc(mb_cur_max());
|
||||
@@ -225,18 +208,9 @@ void do_statusbar_output(int *the_input, size_t input_len,
|
||||
i = 0;
|
||||
|
||||
while (i < input_len) {
|
||||
/* When not filtering, convert nulls and stop at a newline. */
|
||||
if (!filtering) {
|
||||
if (output[i] == '\0')
|
||||
output[i] = '\n';
|
||||
else if (output[i] == '\n') {
|
||||
/* Put back the rest of the characters for reparsing,
|
||||
* indicate that we got a ^J and get out. */
|
||||
unparse_kbinput(output + i, input_len - i);
|
||||
*got_newline = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Encode any NUL byte as 0x0A. */
|
||||
if (output[i] == '\0')
|
||||
output[i] = '\n';
|
||||
|
||||
/* Interpret the next multibyte character. */
|
||||
char_len = parse_mbchar(output + i, char_buf, NULL);
|
||||
@@ -311,7 +285,6 @@ void do_statusbar_delete(void)
|
||||
|
||||
charmove(answer + statusbar_x, answer + statusbar_x + char_len,
|
||||
strlen(answer) - statusbar_x - char_len + 1);
|
||||
align(&answer);
|
||||
|
||||
update_the_statusbar();
|
||||
}
|
||||
@@ -375,19 +348,15 @@ void do_statusbar_prev_word(void)
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Get verbatim input, setting got_newline to TRUE if we get a ^J as
|
||||
* part of the verbatim input. */
|
||||
void do_statusbar_verbatim_input(bool *got_newline)
|
||||
/* Get verbatim input and inject it into the answer, without filtering. */
|
||||
void do_statusbar_verbatim_input(void)
|
||||
{
|
||||
int *kbinput;
|
||||
size_t kbinput_len;
|
||||
|
||||
/* Read in all the verbatim characters. */
|
||||
kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
|
||||
|
||||
/* Display all the verbatim characters at once, not filtering out
|
||||
* control characters. */
|
||||
do_statusbar_output(kbinput, kbinput_len, FALSE, got_newline);
|
||||
do_statusbar_output(kbinput, kbinput_len, FALSE);
|
||||
}
|
||||
|
||||
/* Return the zero-based column position of the cursor in the answer. */
|
||||
@@ -511,7 +480,7 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
/* Ensure the cursor is shown when waiting for input. */
|
||||
curs_set(1);
|
||||
|
||||
kbinput = do_statusbar_input(&ran_func, &finished, refresh_func);
|
||||
kbinput = do_statusbar_input(&ran_func, &finished);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the window size changed, go reformat the prompt string. */
|
||||
@@ -537,7 +506,7 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
if (func == do_tab) {
|
||||
#ifndef DISABLE_HISTORIES
|
||||
if (history_list != NULL) {
|
||||
if (last_kbinput != sc_seq_or(do_tab, TAB_CODE))
|
||||
if (last_kbinput != the_code_for(do_tab, TAB_CODE))
|
||||
complete_len = strlen(answer);
|
||||
|
||||
if (complete_len > 0) {
|
||||
@@ -729,30 +698,22 @@ int do_prompt(bool allow_tabs,
|
||||
int do_yesno_prompt(bool all, const char *msg)
|
||||
{
|
||||
int response = -2, width = 16;
|
||||
const char *yesstr; /* String of Yes characters accepted. */
|
||||
const char *nostr; /* Same for No. */
|
||||
const char *allstr; /* And All, surprise! */
|
||||
int oldmenu = currmenu;
|
||||
char *message = display_string(msg, 0, COLS, FALSE);
|
||||
|
||||
assert(msg != NULL);
|
||||
|
||||
/* yesstr, nostr, and allstr are strings of any length. Each string
|
||||
* consists of all single-byte characters accepted as valid
|
||||
* characters for that value. The first value will be the one
|
||||
* displayed in the shortcuts. */
|
||||
/* TRANSLATORS: For the next three strings, if possible, specify
|
||||
* the single-byte shortcuts for both your language and English.
|
||||
* For example, in French: "OoYy" for "Oui". */
|
||||
yesstr = _("Yy");
|
||||
nostr = _("Nn");
|
||||
allstr = _("Aa");
|
||||
* For example, in French: "OoYy", for both "Oui" and "Yes". */
|
||||
const char *yesstr = _("Yy");
|
||||
const char *nostr = _("Nn");
|
||||
const char *allstr = _("Aa");
|
||||
|
||||
do {
|
||||
/* The above three variables consist of all the single-byte characters
|
||||
* that are accepted for the corresponding answer. Of each variable,
|
||||
* the first character is displayed in the help lines. */
|
||||
|
||||
while (response == -2) {
|
||||
int kbinput;
|
||||
functionptrtype func;
|
||||
#ifndef DISABLE_MOUSE
|
||||
int mouse_x, mouse_y;
|
||||
#endif
|
||||
|
||||
if (!ISSET(NO_HELP)) {
|
||||
char shortstr[3];
|
||||
@@ -783,31 +744,28 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
onekey("^C", _("Cancel"), width);
|
||||
}
|
||||
|
||||
/* Color the statusbar over its full width and display the question. */
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
blank_statusbar();
|
||||
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
|
||||
|
||||
mvwaddnstr(bottomwin, 0, 0, message, actual_x(message, COLS - 1));
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
/* Refresh edit window and statusbar before getting input. */
|
||||
wnoutrefresh(edit);
|
||||
wnoutrefresh(bottomwin);
|
||||
|
||||
/* When not replacing, show the cursor. */
|
||||
if (!all)
|
||||
curs_set(1);
|
||||
|
||||
currmenu = MYESNO;
|
||||
kbinput = get_kbinput(bottomwin);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
func = func_from_key(&kbinput);
|
||||
|
||||
if (func == do_cancel)
|
||||
response = -1;
|
||||
#ifndef DISABLE_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_x, &mouse_y, FALSE) == 0 &&
|
||||
wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE) &&
|
||||
@@ -828,10 +786,7 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
}
|
||||
}
|
||||
#endif /* !DISABLE_MOUSE */
|
||||
else if (func == total_refresh) {
|
||||
total_redraw();
|
||||
continue;
|
||||
} else {
|
||||
else {
|
||||
/* Look for the kbinput in the Yes, No (and All) strings. */
|
||||
if (strchr(yesstr, kbinput) != NULL)
|
||||
response = 1;
|
||||
@@ -840,10 +795,9 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
else if (all && strchr(allstr, kbinput) != NULL)
|
||||
response = 2;
|
||||
}
|
||||
} while (response == -2);
|
||||
}
|
||||
|
||||
/* Restore the previously active menu. */
|
||||
bottombars(oldmenu);
|
||||
free(message);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
73
src/proto.h
73
src/proto.h
@@ -26,7 +26,7 @@
|
||||
|
||||
/* All external variables. See global.c for their descriptions. */
|
||||
#ifndef NANO_TINY
|
||||
extern volatile sig_atomic_t sigwinch_counter;
|
||||
extern volatile sig_atomic_t the_window_resized;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -38,15 +38,15 @@ extern bool shift_held;
|
||||
|
||||
extern bool focusing;
|
||||
|
||||
extern bool as_an_at;
|
||||
|
||||
extern int margin;
|
||||
extern int editwincols;
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
extern int last_drawn_line;
|
||||
extern int last_line_y;
|
||||
#endif
|
||||
|
||||
extern message_type lastmessage;
|
||||
|
||||
extern filestruct *pletion_line;
|
||||
|
||||
extern int controlleft;
|
||||
extern int controlright;
|
||||
extern int controlup;
|
||||
@@ -209,7 +209,7 @@ bool is_cntrl_mbchar(const char *c);
|
||||
bool is_punct_mbchar(const char *c);
|
||||
bool is_word_mbchar(const char *c, bool allow_punct);
|
||||
char control_rep(const signed char c);
|
||||
char control_mbrep(const char *c);
|
||||
char control_mbrep(const char *c, bool isdata);
|
||||
int length_of_char(const char *c, int *width);
|
||||
int mbwidth(const char *c);
|
||||
int mb_cur_max(void);
|
||||
@@ -229,8 +229,8 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n);
|
||||
char *nstrcasestr(const char *haystack, const char *needle);
|
||||
#endif
|
||||
char *mbstrcasestr(const char *haystack, const char *needle);
|
||||
char *revstrstr(const char *haystack, const char *needle, const char
|
||||
*rev_start);
|
||||
char *revstrstr(const char *haystack, const char *needle,
|
||||
const char *pointer);
|
||||
char *revstrcasestr(const char *haystack, const char *needle, const char
|
||||
*rev_start);
|
||||
char *mbrevstrcasestr(const char *haystack, const char *needle, const
|
||||
@@ -348,19 +348,19 @@ const char *tail(const char *path);
|
||||
#ifndef DISABLE_HISTORIES
|
||||
char *histfilename(void);
|
||||
void load_history(void);
|
||||
bool writehist(FILE *hist, filestruct *histhead);
|
||||
bool writehist(FILE *hist, const filestruct *histhead);
|
||||
void save_history(void);
|
||||
int check_dotnano(void);
|
||||
void load_poshistory(void);
|
||||
void save_poshistory(void);
|
||||
void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos);
|
||||
int check_poshistory(const char *file, ssize_t *line, ssize_t *column);
|
||||
bool has_old_position(const char *file, ssize_t *line, ssize_t *column);
|
||||
#endif
|
||||
|
||||
/* Some functions in global.c. */
|
||||
size_t length_of_list(int menu);
|
||||
const sc *first_sc_for(int menu, void (*func)(void));
|
||||
int sc_seq_or(void (*func)(void), int defaultval);
|
||||
int the_code_for(void (*func)(void), int defaultval);
|
||||
functionptrtype func_from_key(int *kbinput);
|
||||
void assign_keyinfo(sc *s, const char *keystring, const int keycode);
|
||||
void print_sclist(void);
|
||||
@@ -456,7 +456,6 @@ void print_opt_full(const char *shortflag
|
||||
, const char *desc);
|
||||
void usage(void);
|
||||
void version(void);
|
||||
void no_current_file_name_warning(void);
|
||||
void do_exit(void);
|
||||
void close_and_go(void);
|
||||
void signal_init(void);
|
||||
@@ -481,14 +480,12 @@ int do_mouse(void);
|
||||
#endif
|
||||
void do_output(char *output, size_t output_len, bool allow_cntrls);
|
||||
|
||||
/* All functions in prompt.c. */
|
||||
int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
void (*refresh_func)(void));
|
||||
/* Most functions in prompt.c. */
|
||||
#ifndef DISABLE_MOUSE
|
||||
int do_statusbar_mouse(void);
|
||||
#endif
|
||||
void do_statusbar_output(int *the_input, size_t input_len,
|
||||
bool filtering, bool *got_newline);
|
||||
bool filtering);
|
||||
void do_statusbar_home(void);
|
||||
void do_statusbar_end(void);
|
||||
void do_statusbar_left(void);
|
||||
@@ -500,7 +497,7 @@ void do_statusbar_cut_text(void);
|
||||
void do_statusbar_prev_word(void);
|
||||
void do_statusbar_next_word(void);
|
||||
#endif
|
||||
void do_statusbar_verbatim_input(bool *got_newline);
|
||||
void do_statusbar_verbatim_input(void);
|
||||
size_t statusbar_xplustabs(void);
|
||||
size_t get_statusbar_page_start(size_t start_col, size_t column);
|
||||
void reinit_statusbar_x(void);
|
||||
@@ -522,22 +519,12 @@ int do_yesno_prompt(bool all, const char *msg);
|
||||
char *parse_next_word(char *ptr);
|
||||
#endif
|
||||
#ifndef DISABLE_NANORC
|
||||
void rcfile_error(const char *msg, ...);
|
||||
char *parse_argument(char *ptr);
|
||||
#ifndef DISABLE_COLOR
|
||||
char *parse_next_regex(char *ptr);
|
||||
void parse_syntax(char *ptr);
|
||||
void parse_includes(char *ptr);
|
||||
short color_to_short(const char *colorname, bool *bright);
|
||||
bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright);
|
||||
void grab_and_store(const char *kind, char *ptr, regexlisttype **storage);
|
||||
#endif
|
||||
void parse_rcfile(FILE *rcstream
|
||||
#ifndef DISABLE_COLOR
|
||||
, bool syntax_only
|
||||
#endif
|
||||
);
|
||||
void do_rcfile(void);
|
||||
void parse_rcfile(FILE *rcstream, bool syntax_only);
|
||||
void do_rcfiles(void);
|
||||
#endif /* !DISABLE_NANORC */
|
||||
|
||||
/* All functions in search.c. */
|
||||
@@ -603,18 +590,25 @@ void do_tab(void);
|
||||
void do_indent(ssize_t cols);
|
||||
void do_indent_void(void);
|
||||
void do_unindent(void);
|
||||
void do_undo(void);
|
||||
void do_redo(void);
|
||||
#endif
|
||||
bool white_string(const char *s);
|
||||
#ifdef ENABLE_COMMENT
|
||||
void do_comment(void);
|
||||
bool comment_line(undo_type action, filestruct *f, const char *comment_seq);
|
||||
#endif
|
||||
void do_undo(void);
|
||||
void do_redo(void);
|
||||
void do_enter(void);
|
||||
#ifndef NANO_TINY
|
||||
RETSIGTYPE cancel_command(int signal);
|
||||
bool execute_command(const char *command);
|
||||
void discard_until(const undo *thisitem, openfilestruct *thefile);
|
||||
void add_undo(undo_type action);
|
||||
#ifndef DISABLE_COMMENT
|
||||
void update_comment_undo(ssize_t lineno);
|
||||
#endif
|
||||
void update_undo(undo_type action);
|
||||
#endif /* !NANO_TINY */
|
||||
#ifndef DISABLE_WRAPPING
|
||||
void wrap_reset(void);
|
||||
bool do_wrap(filestruct *line);
|
||||
@@ -658,13 +652,16 @@ void do_formatter(void);
|
||||
void do_wordlinechar_count(void);
|
||||
#endif
|
||||
void do_verbatim_input(void);
|
||||
void complete_a_word(void);
|
||||
|
||||
/* All functions in utils.c. */
|
||||
void get_homedir(void);
|
||||
int digits(int n);
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
int digits(ssize_t n);
|
||||
#endif
|
||||
bool parse_num(const char *str, ssize_t *val);
|
||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column);
|
||||
void align(char **str);
|
||||
void snuggly_fit(char **str);
|
||||
void null_at(char **data, size_t index);
|
||||
void unsunder(char *str, size_t true_len);
|
||||
void sunder(char *str);
|
||||
@@ -700,16 +697,11 @@ void new_magicline(void);
|
||||
void remove_magicline(void);
|
||||
void mark_order(const filestruct **top, size_t *top_x, const filestruct
|
||||
**bot, size_t *bot_x, bool *right_side_up);
|
||||
void discard_until(const undo *thisitem, openfilestruct *thefile);
|
||||
void add_undo(undo_type action);
|
||||
void update_undo(undo_type action);
|
||||
#ifndef DISABLE_COMMENT
|
||||
void update_comment_undo(ssize_t lineno);
|
||||
bool comment_line(undo_type action, filestruct *f, const char *comment_seq);
|
||||
#endif
|
||||
#endif
|
||||
size_t get_totsize(const filestruct *begin, const filestruct *end);
|
||||
#ifndef NANO_TINY
|
||||
filestruct *fsfromline(ssize_t lineno);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
void dump_filestruct(const filestruct *inptr);
|
||||
void dump_filestruct_reverse(void);
|
||||
@@ -749,6 +741,7 @@ char *display_string(const char *buf, size_t start_col, size_t span,
|
||||
void titlebar(const char *path);
|
||||
extern void set_modified(void);
|
||||
void statusbar(const char *msg);
|
||||
void warn_and_shortly_pause(const char *msg);
|
||||
void statusline(message_type importance, const char *msg, ...);
|
||||
void bottombars(int menu);
|
||||
void onekey(const char *keystroke, const char *desc, int length);
|
||||
|
||||
148
src/rcfile.c
148
src/rcfile.c
@@ -33,6 +33,10 @@
|
||||
|
||||
#ifndef DISABLE_NANORC
|
||||
|
||||
#ifndef RCFILE_NAME
|
||||
#define RCFILE_NAME ".nanorc"
|
||||
#endif
|
||||
|
||||
static const rcoption rcopts[] = {
|
||||
{"boldtext", BOLD_TEXT},
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
@@ -526,35 +530,40 @@ void parse_binding(char *ptr, bool dobind)
|
||||
free(keycopy);
|
||||
}
|
||||
|
||||
/* Verify that the given file is not a folder nor a device. */
|
||||
bool is_good_file(char *file)
|
||||
{
|
||||
struct stat rcinfo;
|
||||
|
||||
/* If the thing exists, it may not be a directory nor a device. */
|
||||
if (stat(file, &rcinfo) != -1 && (S_ISDIR(rcinfo.st_mode) ||
|
||||
S_ISCHR(rcinfo.st_mode) || S_ISBLK(rcinfo.st_mode))) {
|
||||
rcfile_error(S_ISDIR(rcinfo.st_mode) ? _("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), file);
|
||||
return FALSE;
|
||||
} else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
/* Read and parse one included syntax file. */
|
||||
static void parse_one_include(char *file)
|
||||
{
|
||||
struct stat rcinfo;
|
||||
FILE *rcstream;
|
||||
|
||||
/* Can't get the specified file's full path because it may screw up
|
||||
* our cwd depending on the parent directories' permissions (see
|
||||
* Savannah bug #25297). */
|
||||
|
||||
/* Don't open directories, character files, or block files. */
|
||||
if (stat(file, &rcinfo) != -1) {
|
||||
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
|
||||
S_ISBLK(rcinfo.st_mode)) {
|
||||
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
|
||||
_("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), file);
|
||||
}
|
||||
}
|
||||
if (!is_good_file(file))
|
||||
return;
|
||||
|
||||
/* Open the new syntax file. */
|
||||
if ((rcstream = fopen(file, "rb")) == NULL) {
|
||||
rcfile_error(_("Error reading %s: %s"), file,
|
||||
strerror(errno));
|
||||
/* Open the included syntax file. */
|
||||
rcstream = fopen(file, "rb");
|
||||
|
||||
if (rcstream == NULL) {
|
||||
rcfile_error(_("Error reading %s: %s"), file, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Use the name and line number position of the new syntax file
|
||||
/* Use the name and line number position of the included syntax file
|
||||
* while parsing it, so we can know where any errors in it are. */
|
||||
nanorc = file;
|
||||
lineno = 0;
|
||||
@@ -585,8 +594,7 @@ void parse_includes(char *ptr)
|
||||
for (i = 0; i < files.gl_pathc; ++i)
|
||||
parse_one_include(files.gl_pathv[i]);
|
||||
} else
|
||||
rcfile_error(_("Error expanding %s: %s"), option,
|
||||
strerror(errno));
|
||||
rcfile_error(_("Error expanding %s: %s"), option, strerror(errno));
|
||||
|
||||
globfree(&files);
|
||||
free(expanded);
|
||||
@@ -904,8 +912,8 @@ void pick_up_name(const char *kind, char *ptr, char **storage)
|
||||
}
|
||||
#endif /* !DISABLE_COLOR */
|
||||
|
||||
/* Check whether the user has unmapped every shortcut for a
|
||||
* sequence we consider 'vital', like the exit function. */
|
||||
/* Verify that the user has not unmapped every shortcut for a
|
||||
* function that we consider 'vital' (such as "Exit"). */
|
||||
static void check_vitals_mapped(void)
|
||||
{
|
||||
subnfunc *f;
|
||||
@@ -932,13 +940,9 @@ static void check_vitals_mapped(void)
|
||||
}
|
||||
|
||||
/* Parse the rcfile, once it has been opened successfully at rcstream,
|
||||
* and close it afterwards. If syntax_only is TRUE, only allow the file
|
||||
* to contain color syntax commands. */
|
||||
void parse_rcfile(FILE *rcstream
|
||||
#ifndef DISABLE_COLOR
|
||||
, bool syntax_only
|
||||
#endif
|
||||
)
|
||||
* and close it afterwards. If syntax_only is TRUE, allow the file to
|
||||
* to contain only color syntax commands. */
|
||||
void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
{
|
||||
char *buf = NULL;
|
||||
ssize_t len;
|
||||
@@ -1115,7 +1119,7 @@ void parse_rcfile(FILE *rcstream
|
||||
#endif
|
||||
/* Make sure the option argument is a valid multibyte string. */
|
||||
if (!is_valid_mbstring(option)) {
|
||||
rcfile_error(N_("Option is not a valid multibyte string"));
|
||||
rcfile_error(N_("Argument is not a valid multibyte string"));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1143,8 +1147,10 @@ void parse_rcfile(FILE *rcstream
|
||||
rcfile_error(N_("Requested fill size \"%s\" is invalid"),
|
||||
option);
|
||||
wrap_at = -CHARS_FROM_EOL;
|
||||
} else
|
||||
} else {
|
||||
UNSET(NO_WRAP);
|
||||
free(option);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
@@ -1223,45 +1229,43 @@ void parse_rcfile(FILE *rcstream
|
||||
fclose(rcstream);
|
||||
lineno = 0;
|
||||
|
||||
check_vitals_mapped();
|
||||
return;
|
||||
}
|
||||
|
||||
/* The main rcfile function. It tries to open the system-wide rcfile,
|
||||
* followed by the current user's rcfile. */
|
||||
void do_rcfile(void)
|
||||
/* Read and interpret one of the two nanorc files. */
|
||||
void parse_one_nanorc(void)
|
||||
{
|
||||
struct stat rcinfo;
|
||||
FILE *rcstream;
|
||||
|
||||
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
|
||||
|
||||
/* Don't open directories, character files, or block files. */
|
||||
if (stat(nanorc, &rcinfo) != -1) {
|
||||
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
|
||||
S_ISBLK(rcinfo.st_mode))
|
||||
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
|
||||
_("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), nanorc);
|
||||
}
|
||||
/* Don't try to open directories nor devices. */
|
||||
if (!is_good_file(nanorc))
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Parsing file \"%s\"\n", nanorc);
|
||||
fprintf(stderr, "Going to parse file \"%s\"\n", nanorc);
|
||||
#endif
|
||||
|
||||
/* Try to open the system-wide nanorc. */
|
||||
rcstream = fopen(nanorc, "rb");
|
||||
if (rcstream != NULL)
|
||||
parse_rcfile(rcstream
|
||||
#ifndef DISABLE_COLOR
|
||||
, FALSE
|
||||
#endif
|
||||
);
|
||||
|
||||
/* If opening the file succeeded, parse it. Otherwise, only
|
||||
* complain if the file actually exists. */
|
||||
if (rcstream != NULL)
|
||||
parse_rcfile(rcstream, FALSE);
|
||||
else if (errno != ENOENT)
|
||||
rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno));
|
||||
}
|
||||
|
||||
/* First read the system-wide rcfile, then the user's rcfile. */
|
||||
void do_rcfiles(void)
|
||||
{
|
||||
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
|
||||
|
||||
/* Process the system-wide nanorc. */
|
||||
parse_one_nanorc();
|
||||
|
||||
/* When configured with --disable-wrapping-as-root, turn wrapping off
|
||||
* for root, so that only root's .nanorc or --fill can turn it on. */
|
||||
#ifdef DISABLE_ROOTWRAPPING
|
||||
/* We've already read SYSCONFDIR/nanorc, if it's there. If we're
|
||||
* root, and --disable-wrapping-as-root is used, turn wrapping off
|
||||
* now. */
|
||||
if (geteuid() == NANO_ROOT_UID)
|
||||
SET(NO_WRAP);
|
||||
#endif
|
||||
@@ -1271,38 +1275,16 @@ void do_rcfile(void)
|
||||
if (homedir == NULL)
|
||||
rcfile_error(N_("I can't find my home directory! Wah!"));
|
||||
else {
|
||||
#ifndef RCFILE_NAME
|
||||
#define RCFILE_NAME ".nanorc"
|
||||
#endif
|
||||
nanorc = charealloc(nanorc, strlen(homedir) + strlen(RCFILE_NAME) + 2);
|
||||
sprintf(nanorc, "%s/%s", homedir, RCFILE_NAME);
|
||||
|
||||
/* Don't open directories, character files, or block files. */
|
||||
if (stat(nanorc, &rcinfo) != -1) {
|
||||
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
|
||||
S_ISBLK(rcinfo.st_mode))
|
||||
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
|
||||
_("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), nanorc);
|
||||
}
|
||||
|
||||
/* Try to open the current user's nanorc. */
|
||||
rcstream = fopen(nanorc, "rb");
|
||||
if (rcstream == NULL) {
|
||||
/* Don't complain about the file's not existing. */
|
||||
if (errno != ENOENT)
|
||||
rcfile_error(N_("Error reading %s: %s"), nanorc,
|
||||
strerror(errno));
|
||||
} else
|
||||
parse_rcfile(rcstream
|
||||
#ifndef DISABLE_COLOR
|
||||
, FALSE
|
||||
#endif
|
||||
);
|
||||
/* Process the current user's nanorc. */
|
||||
parse_one_nanorc();
|
||||
}
|
||||
|
||||
check_vitals_mapped();
|
||||
|
||||
free(nanorc);
|
||||
nanorc = NULL;
|
||||
|
||||
if (errors && !ISSET(QUIET)) {
|
||||
errors = FALSE;
|
||||
|
||||
22
src/search.c
22
src/search.c
@@ -103,7 +103,7 @@ void search_replace_abort(void)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set)
|
||||
edit_refresh();
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
#ifdef HAVE_REGEX_H
|
||||
regexp_cleanup();
|
||||
@@ -664,18 +664,17 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
|
||||
if (i == -1) /* The replacing was cancelled. */
|
||||
break;
|
||||
else if (i == 2)
|
||||
replaceall = TRUE;
|
||||
}
|
||||
|
||||
if (i > 0 || replaceall) { /* Yes, replace it!!!! */
|
||||
if (i == 1 || replaceall) { /* Yes, replace it. */
|
||||
char *copy;
|
||||
size_t length_change;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
add_undo(REPLACE);
|
||||
#endif
|
||||
if (i == 2)
|
||||
replaceall = TRUE;
|
||||
|
||||
copy = replace_line(needle);
|
||||
|
||||
length_change = strlen(copy) - strlen(openfile->current->data);
|
||||
@@ -734,8 +733,8 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
|
||||
if (!replaceall) {
|
||||
#ifndef DISABLE_COLOR
|
||||
/* If color syntaxes are available and turned on, we
|
||||
* need to call edit_refresh(). */
|
||||
/* When doing syntax coloring, the replacement might require
|
||||
* a change of colors, so refresh the whole edit window. */
|
||||
if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX))
|
||||
edit_refresh();
|
||||
else
|
||||
@@ -744,6 +743,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
}
|
||||
|
||||
set_modified();
|
||||
as_an_at = TRUE;
|
||||
numreplaced++;
|
||||
}
|
||||
}
|
||||
@@ -774,7 +774,6 @@ void do_replace(void)
|
||||
|
||||
if (ISSET(VIEW_MODE)) {
|
||||
print_view_warning();
|
||||
search_replace_abort();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -826,8 +825,7 @@ void do_replace(void)
|
||||
openfile->edittop = edittop_save;
|
||||
openfile->current = begin;
|
||||
openfile->current_x = begin_x;
|
||||
|
||||
edit_refresh();
|
||||
refresh_needed = TRUE;
|
||||
|
||||
if (numreplaced >= 0)
|
||||
statusline(HUSH, P_("Replaced %lu occurrence",
|
||||
@@ -1205,10 +1203,10 @@ void update_history(filestruct **h, const char *s)
|
||||
/* If the history is full, delete the oldest item (the one at the
|
||||
* head of the list), to make room for a new item at the end. */
|
||||
if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
|
||||
filestruct *foo = *hage;
|
||||
filestruct *oldest = *hage;
|
||||
|
||||
*hage = (*hage)->next;
|
||||
unlink_node(foo);
|
||||
unlink_node(oldest);
|
||||
renumber(*hage);
|
||||
}
|
||||
|
||||
|
||||
330
src/text.c
330
src/text.c
@@ -6,6 +6,7 @@
|
||||
* Copyright (C) 2014, 2015 Mark Majeres *
|
||||
* Copyright (C) 2016 Mike Scalora *
|
||||
* Copyright (C) 2015, 2016 Benno Schulenberg *
|
||||
* Copyright (C) 2016 Sumedh Pendurkar *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -48,6 +49,13 @@ static filestruct *jusbottom = NULL;
|
||||
/* A pointer to the end of the buffer with unjustified text. */
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
static int pletion_x = 0;
|
||||
/* The x position in pletion_line of the last found completion. */
|
||||
static completion_word *list_of_completions;
|
||||
/* A linked list of the completions that have been attepmted. */
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Toggle the mark. */
|
||||
void do_mark(void)
|
||||
@@ -63,8 +71,8 @@ void do_mark(void)
|
||||
statusbar(_("Mark Unset"));
|
||||
openfile->mark_begin = NULL;
|
||||
openfile->mark_begin_x = 0;
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
edit_refresh();
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
@@ -94,7 +102,7 @@ void do_deletion(undo_type action)
|
||||
|
||||
if (openfile->current->data[openfile->current_x] != '\0') {
|
||||
/* We're in the middle of a line: delete the current character. */
|
||||
int char_buf_len = parse_mbchar(openfile->current->data +
|
||||
int char_len = parse_mbchar(openfile->current->data +
|
||||
openfile->current_x, NULL, NULL);
|
||||
size_t line_len = strlen(openfile->current->data +
|
||||
openfile->current_x);
|
||||
@@ -110,16 +118,16 @@ void do_deletion(undo_type action)
|
||||
|
||||
/* Move the remainder of the line "in", over the current character. */
|
||||
charmove(&openfile->current->data[openfile->current_x],
|
||||
&openfile->current->data[openfile->current_x + char_buf_len],
|
||||
line_len - char_buf_len + 1);
|
||||
&openfile->current->data[openfile->current_x + char_len],
|
||||
line_len - char_len + 1);
|
||||
null_at(&openfile->current->data, openfile->current_x +
|
||||
line_len - char_buf_len);
|
||||
line_len - char_len);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Adjust the mark if it is after the cursor on the current line. */
|
||||
if (openfile->mark_set && openfile->mark_begin == openfile->current &&
|
||||
openfile->mark_begin_x > openfile->current_x)
|
||||
openfile->mark_begin_x -= char_buf_len;
|
||||
openfile->mark_begin_x -= char_len;
|
||||
#endif
|
||||
/* Adjust the file size. */
|
||||
openfile->totsize--;
|
||||
@@ -173,8 +181,10 @@ void do_deletion(undo_type action)
|
||||
#ifndef NANO_TINY
|
||||
ensure_line_is_visible();
|
||||
|
||||
/* If the number of screen rows that a softwrapped line occupies
|
||||
* has changed, we need a full refresh. */
|
||||
if (ISSET(SOFTWRAP) && refresh_needed == FALSE)
|
||||
if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS)
|
||||
if (strlenpt(openfile->current->data) / editwincols != orig_lenpt / editwincols)
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
|
||||
@@ -414,7 +424,6 @@ void do_indent(ssize_t cols)
|
||||
/* Throw away the undo stack, to prevent making mistakes when
|
||||
* the user tries to undo something in the reindented text. */
|
||||
discard_until(NULL, openfile);
|
||||
openfile->current_undo = NULL;
|
||||
|
||||
/* Mark the file as modified. */
|
||||
set_modified();
|
||||
@@ -810,7 +819,7 @@ void do_undo(void)
|
||||
break;
|
||||
}
|
||||
|
||||
if (undidmsg)
|
||||
if (undidmsg && !pletion_line)
|
||||
statusline(HUSH, _("Undid action (%s)"), undidmsg);
|
||||
|
||||
renumber(f);
|
||||
@@ -970,8 +979,8 @@ void do_redo(void)
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Someone hits Enter *gasp!* */
|
||||
void do_enter()
|
||||
/* Break the current line at the cursor position. */
|
||||
void do_enter(void)
|
||||
{
|
||||
filestruct *newnode = make_new_node(openfile->current);
|
||||
size_t extra = 0;
|
||||
@@ -981,45 +990,48 @@ void do_enter()
|
||||
#ifndef NANO_TINY
|
||||
add_undo(ENTER);
|
||||
|
||||
/* Do auto-indenting, like the neolithic Turbo Pascal editor. */
|
||||
if (ISSET(AUTOINDENT)) {
|
||||
/* If we are breaking the line in the indentation, the new
|
||||
* indentation should have only current_x characters, and
|
||||
* current_x should not change. */
|
||||
extra = indent_length(openfile->current->data);
|
||||
|
||||
/* If we are breaking the line in the indentation, limit the new
|
||||
* indentation to the current x position. */
|
||||
if (extra > openfile->current_x)
|
||||
extra = openfile->current_x;
|
||||
}
|
||||
#endif
|
||||
newnode->data = charalloc(strlen(openfile->current->data +
|
||||
openfile->current_x) + extra + 1);
|
||||
openfile->current_x) + extra + 1);
|
||||
strcpy(&newnode->data[extra], openfile->current->data +
|
||||
openfile->current_x);
|
||||
openfile->current_x);
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(AUTOINDENT)) {
|
||||
/* Copy the whitespace from the current line to the new one. */
|
||||
strncpy(newnode->data, openfile->current->data, extra);
|
||||
openfile->totsize += extra;
|
||||
}
|
||||
#endif
|
||||
|
||||
null_at(&openfile->current->data, openfile->current_x);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Adjust the mark if it was on the current line after the cursor. */
|
||||
if (openfile->mark_set && openfile->current == openfile->mark_begin &&
|
||||
openfile->current_x < openfile->mark_begin_x) {
|
||||
openfile->mark_begin = newnode;
|
||||
openfile->mark_begin_x += extra - openfile->current_x;
|
||||
}
|
||||
#endif
|
||||
openfile->current_x = extra;
|
||||
|
||||
splice_node(openfile->current, newnode);
|
||||
openfile->current = newnode;
|
||||
renumber(newnode);
|
||||
|
||||
openfile->current = newnode;
|
||||
openfile->current_x = extra;
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
openfile->totsize++;
|
||||
set_modified();
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
update_undo(ENTER);
|
||||
#endif
|
||||
@@ -1142,6 +1154,9 @@ void discard_until(const undo *thisitem, openfilestruct *thefile)
|
||||
dropit = thefile->undotop;
|
||||
}
|
||||
|
||||
/* Adjust the pointer to the top of the undo stack. */
|
||||
thefile->current_undo = (undo *)thisitem;
|
||||
|
||||
/* Prevent a chain of editing actions from continuing. */
|
||||
thefile->last_action = OTHER;
|
||||
}
|
||||
@@ -1203,16 +1218,18 @@ void add_undo(undo_type action)
|
||||
case BACK:
|
||||
/* If the next line is the magic line, don't ever undo this
|
||||
* backspace, as it won't actually have deleted anything. */
|
||||
if (openfile->current->next == openfile->filebot && openfile->current->data[0] != '\0')
|
||||
if (openfile->current->next == openfile->filebot &&
|
||||
openfile->current->data[0] != '\0')
|
||||
u->xflags = WAS_FINAL_BACKSPACE;
|
||||
case DEL:
|
||||
if (u->begin != strlen(openfile->current->data)) {
|
||||
if (openfile->current->data[openfile->current_x] != '\0') {
|
||||
char *char_buf = charalloc(mb_cur_max() + 1);
|
||||
int char_buf_len = parse_mbchar(&openfile->current->data[u->begin], char_buf, NULL);
|
||||
null_at(&char_buf, char_buf_len);
|
||||
int char_len = parse_mbchar(&openfile->current->data[u->begin],
|
||||
char_buf, NULL);
|
||||
null_at(&char_buf, char_len);
|
||||
u->strdata = char_buf;
|
||||
if (u->type == BACK)
|
||||
u->mark_begin_x += char_buf_len;
|
||||
u->mark_begin_x += char_len;
|
||||
break;
|
||||
}
|
||||
/* Else purposely fall into the line-joining code. */
|
||||
@@ -1340,8 +1357,8 @@ fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openf
|
||||
openfile->current->data, (unsigned long)openfile->current_x, (unsigned long)u->begin);
|
||||
#endif
|
||||
char *char_buf = charalloc(mb_cur_max());
|
||||
size_t char_buf_len = parse_mbchar(&openfile->current->data[u->mark_begin_x], char_buf, NULL);
|
||||
u->strdata = addstrings(u->strdata, u->strdata ? strlen(u->strdata) : 0, char_buf, char_buf_len);
|
||||
int char_len = parse_mbchar(&openfile->current->data[u->mark_begin_x], char_buf, NULL);
|
||||
u->strdata = addstrings(u->strdata, u->strdata ? strlen(u->strdata) : 0, char_buf, char_len);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " >> current undo data is \"%s\"\n", u->strdata);
|
||||
#endif
|
||||
@@ -1351,21 +1368,15 @@ fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openf
|
||||
}
|
||||
case BACK:
|
||||
case DEL: {
|
||||
/* Add the removed character after or before earlier removed stuff. */
|
||||
char *char_buf = charalloc(mb_cur_max());
|
||||
size_t char_buf_len = parse_mbchar(&openfile->current->data[openfile->current_x], char_buf, NULL);
|
||||
if (openfile->current_x == u->begin) {
|
||||
/* They're deleting. */
|
||||
u->strdata = addstrings(u->strdata, strlen(u->strdata), char_buf, char_buf_len);
|
||||
int char_len = parse_mbchar(&openfile->current->data[openfile->current_x], char_buf, NULL);
|
||||
if (action == DEL) {
|
||||
u->strdata = addstrings(u->strdata, strlen(u->strdata), char_buf, char_len);
|
||||
u->mark_begin_x = openfile->current_x;
|
||||
} else if (openfile->current_x == u->begin - char_buf_len) {
|
||||
/* They're backspacing. */
|
||||
u->strdata = addstrings(char_buf, char_buf_len, u->strdata, strlen(u->strdata));
|
||||
u->begin = openfile->current_x;
|
||||
} else {
|
||||
/* They deleted something else on the line. */
|
||||
free(char_buf);
|
||||
add_undo(u->type);
|
||||
return;
|
||||
u->strdata = addstrings(char_buf, char_len, u->strdata, strlen(u->strdata));
|
||||
u->begin = openfile->current_x;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " >> current undo data is \"%s\"\nu->begin = %lu\n", u->strdata, (unsigned long)u->begin);
|
||||
@@ -1982,12 +1993,9 @@ bool begpar(const filestruct *const foo)
|
||||
|
||||
/* Case 2) or 5) or 4). */
|
||||
if (foo->prev->data[quote_len + temp_id_len] == '\0' ||
|
||||
(quote_len == 0 && indent_len > 0
|
||||
#ifndef NANO_TINY
|
||||
&& !ISSET(AUTOINDENT)
|
||||
#endif
|
||||
) || !indents_match(foo->prev->data + quote_len, temp_id_len,
|
||||
foo->data + quote_len, indent_len))
|
||||
(quote_len == 0 && indent_len > 0 && !ISSET(AUTOINDENT)) ||
|
||||
!indents_match(foo->prev->data + quote_len, temp_id_len,
|
||||
foo->data + quote_len, indent_len))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
@@ -2282,8 +2290,7 @@ void do_justify(bool full_justify)
|
||||
if (first_par_line == NULL) {
|
||||
backup_lines(openfile->current, full_justify ?
|
||||
openfile->filebot->lineno - openfile->current->lineno +
|
||||
((openfile->filebot->data[0] != '\0') ? 1 : 0) :
|
||||
par_len);
|
||||
((openfile->filebot->data[0] != '\0') ? 1 : 0) : par_len);
|
||||
first_par_line = openfile->current;
|
||||
}
|
||||
|
||||
@@ -2337,8 +2344,7 @@ void do_justify(bool full_justify)
|
||||
|
||||
/* We're just about to tack the next line onto this one. If
|
||||
* this line isn't empty, make sure it ends in a space. */
|
||||
if (line_len > 0 &&
|
||||
openfile->current->data[line_len - 1] != ' ') {
|
||||
if (line_len > 0 && openfile->current->data[line_len - 1] != ' ') {
|
||||
line_len++;
|
||||
openfile->current->data =
|
||||
charealloc(openfile->current->data, line_len + 1);
|
||||
@@ -2353,8 +2359,7 @@ void do_justify(bool full_justify)
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If needed, adjust the coordinates of the mark. */
|
||||
if (openfile->mark_set &&
|
||||
openfile->mark_begin == next_line) {
|
||||
if (openfile->mark_set && openfile->mark_begin == next_line) {
|
||||
openfile->mark_begin = openfile->current;
|
||||
openfile->mark_begin_x += line_len - indent_len;
|
||||
}
|
||||
@@ -2406,11 +2411,7 @@ void do_justify(bool full_justify)
|
||||
/* If this paragraph is non-quoted, and autoindent isn't
|
||||
* turned on, set the indentation length to zero so that the
|
||||
* indentation is treated as part of the line. */
|
||||
if (quote_len == 0
|
||||
#ifndef NANO_TINY
|
||||
&& !ISSET(AUTOINDENT)
|
||||
#endif
|
||||
)
|
||||
if (quote_len == 0 && !ISSET(AUTOINDENT))
|
||||
indent_len = 0;
|
||||
|
||||
/* Insert a new line after the current one. */
|
||||
@@ -2466,9 +2467,8 @@ void do_justify(bool full_justify)
|
||||
} else
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
|
||||
/* Renumber the lines of the now-justified current paragraph,
|
||||
* since both find_paragraph() and edit_refresh() need the line
|
||||
* numbers to be right. */
|
||||
/* Renumber the now-justified paragraph, since both refreshing the
|
||||
* edit window and finding a paragraph need correct line numbers. */
|
||||
renumber(curr_first_par_line);
|
||||
|
||||
/* We've just finished justifying the paragraph. If we're not
|
||||
@@ -2566,7 +2566,6 @@ void do_justify(bool full_justify)
|
||||
/* Throw away the entire undo stack, to prevent a crash when
|
||||
* the user tries to undo something in the justified text. */
|
||||
discard_until(NULL, openfile);
|
||||
openfile->current_undo = NULL;
|
||||
#endif
|
||||
/* Blow away the unjustified text. */
|
||||
free_filestruct(jusbuffer);
|
||||
@@ -2623,16 +2622,10 @@ bool do_int_spell_fix(const char *word)
|
||||
/* Save the settings of the global flags. */
|
||||
memcpy(stash, flags, sizeof(flags));
|
||||
|
||||
/* Make sure spell-check is case sensitive. */
|
||||
/* Do the spell checking case sensitive, forward, and without regexes. */
|
||||
SET(CASE_SENSITIVE);
|
||||
|
||||
/* Make sure spell-check goes forward only. */
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
/* Make sure spell-check doesn't use regular expressions. */
|
||||
UNSET(USE_REGEXP);
|
||||
#endif
|
||||
|
||||
/* Save the current search string, then set it to the misspelled word. */
|
||||
save_search = last_search;
|
||||
@@ -3043,6 +3036,11 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
#ifndef NANO_TINY
|
||||
if (old_mark_set) {
|
||||
filestruct *top_save = openfile->fileage;
|
||||
|
||||
/* If a magicline was added, remove it again. */
|
||||
if (added_magicline)
|
||||
remove_magicline();
|
||||
|
||||
/* Adjust the end point of the marked region for any change in
|
||||
* length of the region's last line. */
|
||||
if (right_side_up)
|
||||
@@ -3050,10 +3048,6 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
else
|
||||
openfile->mark_begin_x = strlen(openfile->filebot->data);
|
||||
|
||||
/* If a magicline was added, remove it again. */
|
||||
if (added_magicline)
|
||||
remove_magicline();
|
||||
|
||||
/* Unpartition the filestruct so that it contains all the text
|
||||
* again. Note that we've replaced the marked text originally
|
||||
* in the partition with the spell-checked marked text in the
|
||||
@@ -3074,6 +3068,8 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
|
||||
/* Go back to the old position. */
|
||||
goto_line_posx(lineno_save, current_x_save);
|
||||
if (openfile->current_x > strlen(openfile->current->data))
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
openfile->current_y = current_y_save;
|
||||
openfile->placewewant = pww_save;
|
||||
adjust_viewport(STATIONARY);
|
||||
@@ -3081,9 +3077,12 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
/* Stat the temporary file again, and mark the buffer as modified only
|
||||
* if this file was changed since it was written. */
|
||||
stat(tempfile_name, &spellfileinfo);
|
||||
if (spellfileinfo.st_mtime != timestamp)
|
||||
if (spellfileinfo.st_mtime != timestamp) {
|
||||
set_modified();
|
||||
|
||||
/* Flush the undo stack, to avoid making a mess when the user
|
||||
* tries to undo things in spell-corrected lines. */
|
||||
discard_until(NULL, openfile);
|
||||
}
|
||||
#ifndef NANO_TINY
|
||||
/* Unblock SIGWINCHes again. */
|
||||
allow_sigwinch(TRUE);
|
||||
@@ -3381,8 +3380,6 @@ void do_linter(void)
|
||||
sprintf(msg, _("This message is for unopened file %s,"
|
||||
" open it in a new buffer?"),
|
||||
curlint->filename);
|
||||
/* Show a cursor after the question. */
|
||||
curs_set(1);
|
||||
i = do_yesno_prompt(FALSE, msg);
|
||||
free(msg);
|
||||
if (i == -1) {
|
||||
@@ -3548,14 +3545,20 @@ void do_formatter(void)
|
||||
/* Replace the text of the current buffer with the formatted text. */
|
||||
replace_buffer(temp);
|
||||
|
||||
/* Restore the cursor position, and mark the file as modified. */
|
||||
/* Restore the cursor position. */
|
||||
goto_line_posx(lineno_save, current_x_save);
|
||||
if (openfile->current_x > strlen(openfile->current->data))
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
openfile->current_y = current_y_save;
|
||||
openfile->placewewant = pww_save;
|
||||
adjust_viewport(STATIONARY);
|
||||
|
||||
set_modified();
|
||||
|
||||
/* Flush the undo stack, to avoid a mess or crash when
|
||||
* the user tries to undo things in reformatted lines. */
|
||||
discard_until(NULL, openfile);
|
||||
|
||||
finalstatus = _("Finished formatting");
|
||||
}
|
||||
|
||||
@@ -3684,3 +3687,176 @@ void do_verbatim_input(void)
|
||||
|
||||
free(output);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
/* Copy the found completion candidate. */
|
||||
char *copy_completion(char *check_line, int start)
|
||||
{
|
||||
char *word;
|
||||
int position = start, len_of_word = 0, index = 0;
|
||||
|
||||
/* Find the length of the word by travelling to its end. */
|
||||
while (is_word_mbchar(&check_line[position], FALSE)) {
|
||||
int next = move_mbright(check_line, position);
|
||||
len_of_word += next - position;
|
||||
position = next;
|
||||
}
|
||||
|
||||
word = (char *)nmalloc((len_of_word + 1) * sizeof(char));
|
||||
|
||||
/* Simply copy the word. */
|
||||
while (index < len_of_word)
|
||||
word[index++] = check_line[start++];
|
||||
|
||||
word[index] = '\0';
|
||||
return word;
|
||||
}
|
||||
|
||||
/* Look at the fragment the user has typed, then search the current buffer for
|
||||
* the first word that starts with this fragment, and tentatively complete the
|
||||
* fragment. If the user types 'Complete' again, search and paste the next
|
||||
* possible completion. */
|
||||
void complete_a_word(void)
|
||||
{
|
||||
char *shard, *completion = NULL;
|
||||
int start_of_shard, shard_length = 0;
|
||||
int i = 0, j = 0;
|
||||
completion_word *some_word;
|
||||
bool was_set_wrapping = !ISSET(NO_WRAP);
|
||||
|
||||
/* If this is a fresh completion attempt... */
|
||||
if (pletion_line == NULL) {
|
||||
/* Clear the list of words of a previous completion run. */
|
||||
while (list_of_completions != NULL) {
|
||||
completion_word *dropit = list_of_completions;
|
||||
list_of_completions = list_of_completions->next;
|
||||
free(dropit->word);
|
||||
free(dropit);
|
||||
}
|
||||
|
||||
/* Prevent a completion from being merged with typed text. */
|
||||
openfile->last_action = OTHER;
|
||||
|
||||
/* Initialize the starting point for searching. */
|
||||
pletion_line = openfile->fileage;
|
||||
pletion_x = 0;
|
||||
|
||||
/* Wipe the "No further matches" message. */
|
||||
blank_statusbar();
|
||||
wnoutrefresh(bottomwin);
|
||||
} else {
|
||||
/* Remove the attempted completion from the buffer. */
|
||||
do_undo();
|
||||
}
|
||||
|
||||
/* Find the start of the fragment that the user typed. */
|
||||
start_of_shard = openfile->current_x;
|
||||
while (start_of_shard > 0) {
|
||||
int step_left = move_mbleft(openfile->current->data, start_of_shard);
|
||||
|
||||
if (!is_word_mbchar(&openfile->current->data[step_left], FALSE))
|
||||
break;
|
||||
start_of_shard = step_left;
|
||||
}
|
||||
|
||||
/* If there is no word fragment before the cursor, do nothing. */
|
||||
if (start_of_shard == openfile->current_x) {
|
||||
pletion_line = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
shard = (char *)nmalloc((openfile->current_x - start_of_shard + 1) * sizeof(char));
|
||||
|
||||
/* Copy the fragment that has to be searched for. */
|
||||
while (start_of_shard < openfile->current_x)
|
||||
shard[shard_length++] = openfile->current->data[start_of_shard++];
|
||||
shard[shard_length] = '\0';
|
||||
|
||||
/* Run through all of the lines in the buffer, looking for shard. */
|
||||
while (pletion_line != NULL) {
|
||||
int threshold = strlen(pletion_line->data) - shard_length - 1;
|
||||
/* The point where we can stop searching for shard. */
|
||||
|
||||
/* Traverse the whole line, looking for shard. */
|
||||
for (i = pletion_x; i < threshold; i++) {
|
||||
/* If the first byte doesn't match, run on. */
|
||||
if (pletion_line->data[i] != shard[0])
|
||||
continue;
|
||||
|
||||
/* Compare the rest of the bytes in shard. */
|
||||
for (j = 1; j < shard_length; j++)
|
||||
if (pletion_line->data[i + j] != shard[j])
|
||||
break;
|
||||
|
||||
/* If not all of the bytes matched, continue searching. */
|
||||
if (j < shard_length)
|
||||
continue;
|
||||
|
||||
/* If the found match is not /longer/ than shard, skip it. */
|
||||
if (!is_word_mbchar(&pletion_line->data[i + j], FALSE))
|
||||
continue;
|
||||
|
||||
/* If the match is not a separate word, skip it. */
|
||||
if (i > 0 && is_word_mbchar(&pletion_line->data[
|
||||
move_mbleft(pletion_line->data, i)], FALSE))
|
||||
continue;
|
||||
|
||||
/* If this match is the shard itself, ignore it. */
|
||||
if (pletion_line == openfile->current &&
|
||||
i == openfile->current_x - shard_length)
|
||||
continue;
|
||||
|
||||
completion = copy_completion(pletion_line->data, i);
|
||||
|
||||
/* Look among earlier attempted completions for a duplicate. */
|
||||
some_word = list_of_completions;
|
||||
while (some_word && strcmp(some_word->word, completion) != 0)
|
||||
some_word = some_word->next;
|
||||
|
||||
/* If we've already tried this word, skip it. */
|
||||
if (some_word != NULL) {
|
||||
free(completion);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add the found word to the list of completions. */
|
||||
some_word = (completion_word *)nmalloc(sizeof(completion_word));
|
||||
some_word->word = completion;
|
||||
some_word->next = list_of_completions;
|
||||
list_of_completions = some_word;
|
||||
|
||||
/* Temporarily disable wrapping so only one undo item is added. */
|
||||
SET(NO_WRAP);
|
||||
|
||||
/* Inject the completion into the buffer. */
|
||||
do_output(&completion[shard_length],
|
||||
strlen(completion) - shard_length, FALSE);
|
||||
|
||||
/* If needed, reenable wrapping and wrap the current line. */
|
||||
if (was_set_wrapping) {
|
||||
UNSET(NO_WRAP);
|
||||
do_wrap(openfile->current);
|
||||
}
|
||||
|
||||
/* Set the position for a possible next search attempt. */
|
||||
pletion_x = ++i;
|
||||
|
||||
free(shard);
|
||||
return;
|
||||
}
|
||||
|
||||
pletion_line = pletion_line->next;
|
||||
pletion_x = 0;
|
||||
}
|
||||
|
||||
/* The search has reached the end of the file. */
|
||||
if (list_of_completions != NULL) {
|
||||
statusline(ALERT, _("No further matches"));
|
||||
refresh_needed = TRUE;
|
||||
} else
|
||||
/* TRANSLATORS: Shown when there are zero possible completions. */
|
||||
statusline(ALERT, _("No matches"));
|
||||
|
||||
free(shard);
|
||||
}
|
||||
#endif /* ENABLE_WORDCOMPLETION */
|
||||
|
||||
103
src/utils.c
103
src/utils.c
@@ -54,7 +54,7 @@ void get_homedir(void)
|
||||
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
/* Return the number of digits that the given integer n takes up. */
|
||||
int digits(int n)
|
||||
int digits(ssize_t n)
|
||||
{
|
||||
if (n < 100000) {
|
||||
if (n < 1000) {
|
||||
@@ -93,8 +93,6 @@ bool parse_num(const char *str, ssize_t *val)
|
||||
char *first_error;
|
||||
ssize_t j;
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
/* The manual page for strtol() says this is required, and
|
||||
* it looks like it is! */
|
||||
errno = 0;
|
||||
@@ -126,26 +124,24 @@ bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
|
||||
if (comma == NULL)
|
||||
return parse_num(str, line);
|
||||
|
||||
if (!parse_num(comma + 1, column))
|
||||
return FALSE;
|
||||
retval = parse_num(comma + 1, column);
|
||||
|
||||
if (comma == str)
|
||||
return TRUE;
|
||||
return retval;
|
||||
|
||||
firstpart = mallocstrcpy(NULL, str);
|
||||
firstpart[comma - str] = '\0';
|
||||
|
||||
retval = parse_num(firstpart, line);
|
||||
|
||||
free(firstpart);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Fix the memory allocation for a string. */
|
||||
void align(char **str)
|
||||
/* Reduce the memory allocation of a string to what is needed. */
|
||||
void snuggly_fit(char **str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
if (*str != NULL)
|
||||
*str = charealloc(*str, strlen(*str) + 1);
|
||||
}
|
||||
@@ -153,8 +149,6 @@ void align(char **str)
|
||||
/* Null a string at a certain index and align it. */
|
||||
void null_at(char **data, size_t index)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
*data = charealloc(*data, index + 1);
|
||||
(*data)[index] = '\0';
|
||||
}
|
||||
@@ -163,8 +157,6 @@ void null_at(char **data, size_t index)
|
||||
* normally have newlines in it, so encode its nulls as newlines. */
|
||||
void unsunder(char *str, size_t true_len)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
for (; true_len > 0; true_len--, str++) {
|
||||
if (*str == '\0')
|
||||
*str = '\n';
|
||||
@@ -175,8 +167,6 @@ void unsunder(char *str, size_t true_len)
|
||||
* normally have newlines in it, so decode its newlines as nulls. */
|
||||
void sunder(char *str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
for (; *str != '\0'; str++) {
|
||||
if (*str == '\n')
|
||||
*str = '\0';
|
||||
@@ -313,11 +303,8 @@ const char *fixbounds(const char *r)
|
||||
* a separate word? That is: is it not part of a longer word?*/
|
||||
bool is_separate_word(size_t position, size_t length, const char *buf)
|
||||
{
|
||||
char *before = charalloc(mb_cur_max()), *after = charalloc(mb_cur_max());
|
||||
char before[mb_cur_max()], after[mb_cur_max()];
|
||||
size_t word_end = position + length;
|
||||
bool retval;
|
||||
|
||||
assert(buf != NULL && position < strlen(buf) && position + length <= strlen(buf));
|
||||
|
||||
/* Get the characters before and after the word, if any. */
|
||||
parse_mbchar(buf + move_mbleft(buf, position), before, NULL);
|
||||
@@ -326,13 +313,8 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
|
||||
/* If the word starts at the beginning of the line OR the character before
|
||||
* the word isn't a letter, and if the word ends at the end of the line OR
|
||||
* the character after the word isn't a letter, we have a whole word. */
|
||||
retval = (position == 0 || !is_alpha_mbchar(before)) &&
|
||||
(word_end == strlen(buf) || !is_alpha_mbchar(after));
|
||||
|
||||
free(before);
|
||||
free(after);
|
||||
|
||||
return retval;
|
||||
return ((position == 0 || !is_alpha_mbchar(before)) &&
|
||||
(buf[word_end] == '\0' || !is_alpha_mbchar(after)));
|
||||
}
|
||||
#endif /* !DISABLE_SPELLER */
|
||||
|
||||
@@ -350,8 +332,6 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
if ((start > haystack && *(start - 1) == '\0') || start < haystack)
|
||||
return NULL;
|
||||
|
||||
assert(haystack != NULL && needle != NULL && start != NULL);
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
if (ISSET(USE_REGEXP)) {
|
||||
if (ISSET(BACKWARDS_SEARCH)) {
|
||||
@@ -475,8 +455,6 @@ size_t get_page_start(size_t column)
|
||||
* column position of the cursor. */
|
||||
size_t xplustabs(void)
|
||||
{
|
||||
assert(openfile->current != NULL);
|
||||
|
||||
return strnlenpt(openfile->current->data, openfile->current_x);
|
||||
}
|
||||
|
||||
@@ -489,8 +467,6 @@ size_t actual_x(const char *text, size_t column)
|
||||
size_t width = 0;
|
||||
/* The screen display width to text[index], in columns. */
|
||||
|
||||
assert(text != NULL);
|
||||
|
||||
while (*text != '\0') {
|
||||
int charlen = parse_mbchar(text, NULL, &width);
|
||||
|
||||
@@ -514,8 +490,6 @@ size_t strnlenpt(const char *text, size_t maxlen)
|
||||
if (maxlen == 0)
|
||||
return 0;
|
||||
|
||||
assert(text != NULL);
|
||||
|
||||
while (*text != '\0') {
|
||||
int charlen = parse_mbchar(text, NULL, &width);
|
||||
|
||||
@@ -559,9 +533,6 @@ void remove_magicline(void)
|
||||
{
|
||||
if (openfile->filebot->data[0] == '\0' &&
|
||||
openfile->filebot != openfile->fileage) {
|
||||
assert(openfile->filebot != openfile->edittop &&
|
||||
openfile->filebot != openfile->current);
|
||||
|
||||
openfile->filebot = openfile->filebot->prev;
|
||||
free_filestruct(openfile->filebot->next);
|
||||
openfile->filebot->next = NULL;
|
||||
@@ -577,8 +548,6 @@ void remove_magicline(void)
|
||||
void mark_order(const filestruct **top, size_t *top_x, const filestruct
|
||||
**bot, size_t *bot_x, bool *right_side_up)
|
||||
{
|
||||
assert(top != NULL && top_x != NULL && bot != NULL && bot_x != NULL);
|
||||
|
||||
if ((openfile->current->lineno == openfile->mark_begin->lineno &&
|
||||
openfile->current_x > openfile->mark_begin_x) ||
|
||||
openfile->current->lineno > openfile->mark_begin->lineno) {
|
||||
@@ -597,37 +566,6 @@ void mark_order(const filestruct **top, size_t *top_x, const filestruct
|
||||
*right_side_up = FALSE;
|
||||
}
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Calculate the number of characters between begin and end, and return
|
||||
* it. */
|
||||
size_t get_totsize(const filestruct *begin, const filestruct *end)
|
||||
{
|
||||
size_t totsize = 0;
|
||||
const filestruct *f;
|
||||
|
||||
/* Go through the lines from begin to end->prev, if we can. */
|
||||
for (f = begin; f != end && f != NULL; f = f->next) {
|
||||
/* Count the number of characters on this line. */
|
||||
totsize += mbstrlen(f->data);
|
||||
|
||||
/* Count the newline if we have one. */
|
||||
if (f->next != NULL)
|
||||
totsize++;
|
||||
}
|
||||
|
||||
/* Go through the line at end, if we can. */
|
||||
if (f != NULL) {
|
||||
/* Count the number of characters on this line. */
|
||||
totsize += mbstrlen(f->data);
|
||||
|
||||
/* Count the newline if we have one. */
|
||||
if (f->next != NULL)
|
||||
totsize++;
|
||||
}
|
||||
|
||||
return totsize;
|
||||
}
|
||||
|
||||
/* Given a line number, return a pointer to the corresponding struct. */
|
||||
filestruct *fsfromline(ssize_t lineno)
|
||||
@@ -642,13 +580,32 @@ filestruct *fsfromline(ssize_t lineno)
|
||||
f = f->next;
|
||||
|
||||
if (f->lineno != lineno) {
|
||||
statusline(ALERT, _("Internal error: can't match line %d. "
|
||||
"Please save your work."), lineno);
|
||||
statusline(ALERT, _("Internal error: can't match line %ld. "
|
||||
"Please save your work."), (long)lineno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Count the number of characters from begin to end, and return it. */
|
||||
size_t get_totsize(const filestruct *begin, const filestruct *end)
|
||||
{
|
||||
const filestruct *line;
|
||||
size_t totsize = 0;
|
||||
|
||||
/* Sum the number of characters (plus a newline) in each line. */
|
||||
for (line = begin; line != end->next; line = line->next)
|
||||
totsize += mbstrlen(line->data) + 1;
|
||||
|
||||
/* The last line of a file doesn't have a newline -- otherwise it
|
||||
* wouldn't be the last line -- so subtract 1 when at EOF. */
|
||||
if (line == NULL)
|
||||
totsize--;
|
||||
|
||||
return totsize;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Dump the filestruct inptr to stderr. */
|
||||
|
||||
316
src/winio.c
316
src/winio.c
@@ -55,21 +55,6 @@ static bool seen_wide = FALSE;
|
||||
/* Whether we've seen a multicolumn character in the current line. */
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
static sig_atomic_t last_sigwinch_counter = 0;
|
||||
|
||||
/* Did we receive a SIGWINCH since we were last called? */
|
||||
bool the_window_resized(void)
|
||||
{
|
||||
if (sigwinch_counter == last_sigwinch_counter)
|
||||
return FALSE;
|
||||
|
||||
last_sigwinch_counter = sigwinch_counter;
|
||||
regenerate_screen();
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Control character compatibility:
|
||||
*
|
||||
* - Ctrl-H is Backspace under ASCII, ANSI, VT100, and VT220.
|
||||
@@ -144,8 +129,9 @@ void get_key_buffer(WINDOW *win)
|
||||
input = wgetch(win);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (the_window_resized()) {
|
||||
if (the_window_resized) {
|
||||
ungetch(input);
|
||||
regenerate_screen();
|
||||
input = KEY_WINCH;
|
||||
}
|
||||
#endif
|
||||
@@ -162,7 +148,8 @@ void get_key_buffer(WINDOW *win)
|
||||
handle_hupterm(0);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (the_window_resized()) {
|
||||
if (the_window_resized) {
|
||||
regenerate_screen();
|
||||
input = KEY_WINCH;
|
||||
break;
|
||||
}
|
||||
@@ -391,7 +378,8 @@ int parse_kbinput(WINDOW *win)
|
||||
break;
|
||||
case 2:
|
||||
if (double_esc) {
|
||||
/* An "ESC ESC [ X" sequence from Option+arrow. */
|
||||
/* An "ESC ESC [ X" sequence from Option+arrow, or
|
||||
* an "ESC ESC [ x" sequence from Shift+Alt+arrow. */
|
||||
switch (keycode) {
|
||||
case 'A':
|
||||
retval = KEY_HOME;
|
||||
@@ -400,11 +388,25 @@ int parse_kbinput(WINDOW *win)
|
||||
retval = KEY_END;
|
||||
break;
|
||||
case 'C':
|
||||
retval = controlright;
|
||||
retval = CONTROL_RIGHT;
|
||||
break;
|
||||
case 'D':
|
||||
retval = controlleft;
|
||||
retval = CONTROL_LEFT;
|
||||
break;
|
||||
#ifndef NANO_TINY
|
||||
case 'a':
|
||||
retval = shiftaltup;
|
||||
break;
|
||||
case 'b':
|
||||
retval = shiftaltdown;
|
||||
break;
|
||||
case 'c':
|
||||
retval = shiftaltright;
|
||||
break;
|
||||
case 'd':
|
||||
retval = shiftaltleft;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
double_esc = FALSE;
|
||||
escapes = 0;
|
||||
@@ -464,8 +466,9 @@ int parse_kbinput(WINDOW *win)
|
||||
escapes = 0;
|
||||
}
|
||||
} else if (keycode == '[' && key_buffer_len > 0 &&
|
||||
'A' <= *key_buffer && *key_buffer <= 'D') {
|
||||
/* This is an iTerm2 sequence: ^[ ^[ [ X. */
|
||||
(('A' <= *key_buffer && *key_buffer <= 'D') ||
|
||||
('a' <= *key_buffer && *key_buffer <= 'd'))) {
|
||||
/* An iTerm2/Eterm/rxvt sequence: ^[ ^[ [ X. */
|
||||
double_esc = TRUE;
|
||||
} else {
|
||||
/* Two escapes followed by a non-escape, and there are more
|
||||
@@ -505,28 +508,28 @@ int parse_kbinput(WINDOW *win)
|
||||
#ifndef NANO_TINY
|
||||
else if (retval == shiftcontrolleft) {
|
||||
shift_held = TRUE;
|
||||
return sc_seq_or(do_prev_word_void, shiftcontrolleft);
|
||||
return CONTROL_LEFT;
|
||||
} else if (retval == shiftcontrolright) {
|
||||
shift_held = TRUE;
|
||||
return sc_seq_or(do_next_word_void, shiftcontrolright);
|
||||
return CONTROL_RIGHT;
|
||||
} else if (retval == shiftcontrolup) {
|
||||
shift_held = TRUE;
|
||||
return sc_seq_or(do_prev_block, shiftcontrolup);
|
||||
return CONTROL_UP;
|
||||
} else if (retval == shiftcontroldown) {
|
||||
shift_held = TRUE;
|
||||
return sc_seq_or(do_next_block, shiftcontroldown);
|
||||
return CONTROL_DOWN;
|
||||
} else if (retval == shiftaltleft) {
|
||||
shift_held = TRUE;
|
||||
return sc_seq_or(do_home, shiftaltleft);
|
||||
return KEY_HOME;
|
||||
} else if (retval == shiftaltright) {
|
||||
shift_held = TRUE;
|
||||
return sc_seq_or(do_end, shiftaltright);
|
||||
return KEY_END;
|
||||
} else if (retval == shiftaltup) {
|
||||
shift_held = TRUE;
|
||||
return sc_seq_or(do_page_up, shiftaltup);
|
||||
return KEY_PPAGE;
|
||||
} else if (retval == shiftaltdown) {
|
||||
shift_held = TRUE;
|
||||
return sc_seq_or(do_page_down, shiftaltdown);
|
||||
return KEY_NPAGE;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -536,33 +539,33 @@ int parse_kbinput(WINDOW *win)
|
||||
unsigned char modifiers = 6;
|
||||
|
||||
if (console && ioctl(0, TIOCLINUX, &modifiers) >= 0) {
|
||||
/* Is Ctrl being held? */
|
||||
if (modifiers & 0x04) {
|
||||
if (retval == KEY_UP)
|
||||
return sc_seq_or(do_prev_block, controlup);
|
||||
else if (retval == KEY_DOWN)
|
||||
return sc_seq_or(do_next_block, controldown);
|
||||
else if (retval == KEY_LEFT)
|
||||
return sc_seq_or(do_prev_word_void, controlleft);
|
||||
else if (retval == KEY_RIGHT)
|
||||
return sc_seq_or(do_next_word_void, controlright);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Is Shift being held? */
|
||||
if (modifiers & 0x01)
|
||||
shift_held =TRUE;
|
||||
|
||||
shift_held = TRUE;
|
||||
#endif
|
||||
/* Is Ctrl being held? */
|
||||
if (modifiers & 0x04) {
|
||||
if (retval == KEY_UP)
|
||||
return CONTROL_UP;
|
||||
else if (retval == KEY_DOWN)
|
||||
return CONTROL_DOWN;
|
||||
else if (retval == KEY_LEFT)
|
||||
return CONTROL_LEFT;
|
||||
else if (retval == KEY_RIGHT)
|
||||
return CONTROL_RIGHT;
|
||||
}
|
||||
#ifndef NANO_TINY
|
||||
/* Are both Shift and Alt being held? */
|
||||
if ((modifiers & 0x09) == 0x09) {
|
||||
if (retval == KEY_UP)
|
||||
return sc_seq_or(do_page_up, shiftaltup);
|
||||
return KEY_PPAGE;
|
||||
else if (retval == KEY_DOWN)
|
||||
return sc_seq_or(do_page_down, shiftaltdown);
|
||||
return KEY_NPAGE;
|
||||
else if (retval == KEY_LEFT)
|
||||
return sc_seq_or(do_home, shiftaltleft);
|
||||
return KEY_HOME;
|
||||
else if (retval == KEY_RIGHT)
|
||||
return sc_seq_or(do_end, shiftaltright);
|
||||
return KEY_END;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -616,12 +619,18 @@ int parse_kbinput(WINDOW *win)
|
||||
case KEY_C1: /* End (1) on keypad with NumLock off. */
|
||||
return KEY_END;
|
||||
#ifndef NANO_TINY
|
||||
case SHIFT_PAGEUP: /* Fake key, from Shift+Alt+Up. */
|
||||
#ifdef KEY_SPREVIOUS
|
||||
case KEY_SPREVIOUS:
|
||||
#endif
|
||||
case SHIFT_PAGEUP: /* Fake key, from Shift+Alt+Up. */
|
||||
shift_held = TRUE;
|
||||
#endif
|
||||
case KEY_A3: /* PageUp (9) on keypad with NumLock off. */
|
||||
return KEY_PPAGE;
|
||||
#ifndef NANO_TINY
|
||||
#ifdef KEY_SNEXT
|
||||
case KEY_SNEXT:
|
||||
#endif
|
||||
case SHIFT_PAGEDOWN: /* Fake key, from Shift+Alt+Down. */
|
||||
shift_held = TRUE;
|
||||
#endif
|
||||
@@ -633,13 +642,13 @@ int parse_kbinput(WINDOW *win)
|
||||
#endif
|
||||
case DEL_CODE:
|
||||
if (ISSET(REBIND_DELETE))
|
||||
return sc_seq_or(do_delete, KEY_DC);
|
||||
return the_code_for(do_delete, KEY_DC);
|
||||
else
|
||||
return KEY_BACKSPACE;
|
||||
#ifdef KEY_SIC
|
||||
/* Slang doesn't support KEY_SIC. */
|
||||
case KEY_SIC:
|
||||
return sc_seq_or(do_insertfile_void, KEY_IC);
|
||||
return the_code_for(do_insertfile_void, KEY_IC);
|
||||
#endif
|
||||
#ifdef KEY_SBEG
|
||||
/* Slang doesn't support KEY_SBEG. */
|
||||
@@ -658,7 +667,7 @@ int parse_kbinput(WINDOW *win)
|
||||
#endif
|
||||
/* Slang doesn't support KEY_CANCEL. */
|
||||
case KEY_CANCEL:
|
||||
return first_sc_for(currmenu, do_cancel)->keycode;
|
||||
return the_code_for(do_cancel, 0x03);
|
||||
#endif
|
||||
#ifdef KEY_SUSPEND
|
||||
#ifdef KEY_SSUSPEND
|
||||
@@ -667,7 +676,7 @@ int parse_kbinput(WINDOW *win)
|
||||
#endif
|
||||
/* Slang doesn't support KEY_SUSPEND. */
|
||||
case KEY_SUSPEND:
|
||||
return sc_seq_or(do_suspend_void, KEY_SUSPEND);
|
||||
return the_code_for(do_suspend_void, KEY_SUSPEND);
|
||||
#endif
|
||||
#ifdef PDCURSES
|
||||
case KEY_SHIFT_L:
|
||||
@@ -1001,22 +1010,40 @@ int convert_sequence(const int *seq, size_t seq_len)
|
||||
break;
|
||||
case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
|
||||
* Linux console/xterm/Terminal. */
|
||||
return KEY_DC;
|
||||
if (seq_len > 2 && seq[2] == '~')
|
||||
return KEY_DC;
|
||||
break;
|
||||
case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
|
||||
* console/xterm. */
|
||||
return KEY_END;
|
||||
if (seq_len > 2 && seq[2] == '~')
|
||||
return KEY_END;
|
||||
break;
|
||||
case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
|
||||
* Linux console/xterm/Terminal;
|
||||
* Esc [ 5 ^ == PageUp on Eterm. */
|
||||
return KEY_PPAGE;
|
||||
if (seq_len > 2 && (seq[2] == '~' || seq[2] == '^'))
|
||||
return KEY_PPAGE;
|
||||
break;
|
||||
case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
|
||||
* Linux console/xterm/Terminal;
|
||||
* Esc [ 6 ^ == PageDown on Eterm. */
|
||||
return KEY_NPAGE;
|
||||
case '7': /* Esc [ 7 ~ == Home on rxvt. */
|
||||
return KEY_HOME;
|
||||
case '8': /* Esc [ 8 ~ == End on rxvt. */
|
||||
return KEY_END;
|
||||
if (seq_len > 2 && (seq[2] == '~' || seq[2] == '^'))
|
||||
return KEY_NPAGE;
|
||||
break;
|
||||
case '7': /* Esc [ 7 ~ == Home on Eterm/rxvt,
|
||||
* Esc [ 7 $ == Shift-Home on Eterm/rxvt. */
|
||||
if (seq_len > 2 && seq[2] == '~')
|
||||
return KEY_HOME;
|
||||
else if (seq_len > 2 && seq[2] == '$')
|
||||
return SHIFT_HOME;
|
||||
break;
|
||||
case '8': /* Esc [ 8 ~ == End on Eterm/rxvt.
|
||||
* Esc [ 8 $ == Shift-End on Eterm/rxvt. */
|
||||
if (seq_len > 2 && seq[2] == '~')
|
||||
return KEY_END;
|
||||
else if (seq_len > 2 && seq[2] == '$')
|
||||
return SHIFT_END;
|
||||
break;
|
||||
case '9': /* Esc [ 9 == Delete on Mach console. */
|
||||
return KEY_DC;
|
||||
case '@': /* Esc [ @ == Insert on Mach console. */
|
||||
@@ -1415,9 +1442,15 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
|
||||
if (!ISSET(REBIND_KEYPAD))
|
||||
keypad(win, FALSE);
|
||||
|
||||
/* Read in a stream of characters and interpret it if possible. */
|
||||
/* Read in one keycode, or one or two escapes. */
|
||||
retval = parse_verbatim_kbinput(win, kbinput_len);
|
||||
|
||||
/* If the code is invalid in the current mode, discard it. */
|
||||
if ((*retval == '\n' && as_an_at) || (*retval == '\0' && !as_an_at)) {
|
||||
*kbinput_len = 0;
|
||||
beep();
|
||||
}
|
||||
|
||||
/* Turn flow control characters back on if necessary and turn the
|
||||
* keypad back on if necessary now that we're done. */
|
||||
if (ISSET(PRESERVE))
|
||||
@@ -1432,10 +1465,10 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Read in one control character (or an iTerm double Escape), or convert a
|
||||
* series of six digits into a Unicode codepoint. Return in count either 1
|
||||
* (for a control character or the first byte of a multibyte sequence), or 2
|
||||
* (for an iTerm double Escape). */
|
||||
/* Read in one control character (or an iTerm/Eterm/rxvt double Escape),
|
||||
* or convert a series of six digits into a Unicode codepoint. Return
|
||||
* in count either 1 (for a control character or the first byte of a
|
||||
* multibyte sequence), or 2 (for an iTerm/Eterm/rxvt double Escape). */
|
||||
int *parse_verbatim_kbinput(WINDOW *win, size_t *count)
|
||||
{
|
||||
int *kbinput;
|
||||
@@ -1497,7 +1530,7 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *count)
|
||||
|
||||
*count = 1;
|
||||
|
||||
/* If this is an iTerm double escape, take both Escapes. */
|
||||
/* If this is an iTerm/Eterm/rxvt double escape, take both Escapes. */
|
||||
if (key_buffer_len > 3 && *key_buffer == ESC_CODE &&
|
||||
key_buffer[1] == ESC_CODE && key_buffer[2] == '[')
|
||||
*count = 2;
|
||||
@@ -1763,11 +1796,11 @@ void check_statusblank(void)
|
||||
* caller wants to display buf starting with column start_col, and
|
||||
* extending for at most span columns. start_col is zero-based. span
|
||||
* is one-based, so span == 0 means you get "" returned. The returned
|
||||
* string is dynamically allocated, and should be freed. If dollars is
|
||||
* string is dynamically allocated, and should be freed. If isdata is
|
||||
* TRUE, the caller might put "$" at the beginning or end of the line if
|
||||
* it's too long. */
|
||||
char *display_string(const char *buf, size_t start_col, size_t span,
|
||||
bool dollars)
|
||||
bool isdata)
|
||||
{
|
||||
size_t start_index;
|
||||
/* Index in buf of the first character shown. */
|
||||
@@ -1778,9 +1811,8 @@ char *display_string(const char *buf, size_t start_col, size_t span,
|
||||
size_t index;
|
||||
/* Current position in converted. */
|
||||
|
||||
/* If dollars is TRUE, make room for the "$" at the end of the
|
||||
* line. */
|
||||
if (dollars && span > 0 && strlenpt(buf) > start_col + span)
|
||||
/* If this is data, make room for the "$" at the end of the line. */
|
||||
if (isdata && !ISSET(SOFTWRAP) && strlenpt(buf) > start_col + span)
|
||||
span--;
|
||||
|
||||
if (span == 0)
|
||||
@@ -1801,12 +1833,12 @@ char *display_string(const char *buf, size_t start_col, size_t span,
|
||||
buf += start_index;
|
||||
|
||||
if (*buf != '\0' && *buf != '\t' &&
|
||||
(column < start_col || (dollars && column > 0))) {
|
||||
(column < start_col || (isdata && column > 0))) {
|
||||
/* We don't display the complete first character as it starts to
|
||||
* the left of the screen. */
|
||||
if (is_cntrl_mbchar(buf)) {
|
||||
if (column < start_col) {
|
||||
converted[index++] = control_mbrep(buf);
|
||||
converted[index++] = control_mbrep(buf, isdata);
|
||||
start_col++;
|
||||
buf += parse_mbchar(buf, NULL, NULL);
|
||||
}
|
||||
@@ -1869,7 +1901,7 @@ char *display_string(const char *buf, size_t start_col, size_t span,
|
||||
/* If buf contains a control character, represent it. */
|
||||
if (is_cntrl_mbchar(buf)) {
|
||||
converted[index++] = '^';
|
||||
converted[index++] = control_mbrep(buf);
|
||||
converted[index++] = control_mbrep(buf, isdata);
|
||||
start_col += 2;
|
||||
buf += charlength;
|
||||
continue;
|
||||
@@ -1929,8 +1961,8 @@ void titlebar(const char *path)
|
||||
/* What is shown before the path -- "File:", "DIR:", or "". */
|
||||
const char *state = "";
|
||||
/* The state of the current buffer -- "Modified", "View", or "". */
|
||||
char *fragment;
|
||||
/* The tail part of the pathname when dottified. */
|
||||
char *caption;
|
||||
/* The presentable form of the pathname. */
|
||||
|
||||
/* If the screen is too small, there is no titlebar. */
|
||||
if (topwin == NULL)
|
||||
@@ -1941,6 +1973,7 @@ void titlebar(const char *path)
|
||||
wattron(topwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
blank_titlebar();
|
||||
as_an_at = FALSE;
|
||||
|
||||
/* Do as Pico: if there is not enough width available for all items,
|
||||
* first sacrifice the version string, then eat up the side spaces,
|
||||
@@ -2009,14 +2042,16 @@ void titlebar(const char *path)
|
||||
wmove(topwin, 0, offset);
|
||||
|
||||
/* Print the full path if there's room; otherwise, dottify it. */
|
||||
if (pathlen + pluglen + statelen <= COLS)
|
||||
waddstr(topwin, path);
|
||||
else if (5 + statelen <= COLS) {
|
||||
if (pathlen + pluglen + statelen <= COLS) {
|
||||
caption = display_string(path, 0, pathlen, FALSE);
|
||||
waddstr(topwin, caption);
|
||||
free(caption);
|
||||
} else if (5 + statelen <= COLS) {
|
||||
waddstr(topwin, "...");
|
||||
fragment = display_string(path, 3 + pathlen - COLS + statelen,
|
||||
caption = display_string(path, 3 + pathlen - COLS + statelen,
|
||||
COLS - statelen, FALSE);
|
||||
waddstr(topwin, fragment);
|
||||
free(fragment);
|
||||
waddstr(topwin, caption);
|
||||
free(caption);
|
||||
}
|
||||
|
||||
/* Right-align the state if there's room; otherwise, trim it. */
|
||||
@@ -2038,6 +2073,15 @@ void statusbar(const char *msg)
|
||||
statusline(HUSH, msg);
|
||||
}
|
||||
|
||||
/* Warn the user on the statusbar and pause for a moment, so that the
|
||||
* message can be noticed and read. */
|
||||
void warn_and_shortly_pause(const char *msg)
|
||||
{
|
||||
statusbar(msg);
|
||||
beep();
|
||||
napms(1800);
|
||||
}
|
||||
|
||||
/* Display a message on the statusbar, and set suppress_cursorpos to
|
||||
* TRUE, so that the message won't be immediately overwritten if
|
||||
* constant cursor position display is on. */
|
||||
@@ -2273,10 +2317,12 @@ void edit_draw(filestruct *fileptr, const char *converted, int
|
||||
* the text -- but only for the parts that are not softwrapped. */
|
||||
if (margin > 0) {
|
||||
wattron(edit, interface_color_pair[LINE_NUMBER]);
|
||||
if (last_drawn_line != fileptr->lineno || last_line_y >= line)
|
||||
mvwprintw(edit, line, 0, "%*i", margin - 1, fileptr->lineno);
|
||||
else
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP) && startpos >= editwincols)
|
||||
mvwprintw(edit, line, 0, "%*s", margin - 1, " ");
|
||||
else
|
||||
#endif
|
||||
mvwprintw(edit, line, 0, "%*ld", margin - 1, (long)fileptr->lineno);
|
||||
wattroff(edit, interface_color_pair[LINE_NUMBER]);
|
||||
}
|
||||
#endif
|
||||
@@ -2644,10 +2690,6 @@ void edit_draw(filestruct *fileptr, const char *converted, int
|
||||
}
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
last_drawn_line = fileptr->lineno;
|
||||
last_line_y = line;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Just update one line in the edit buffer. This is basically a wrapper
|
||||
@@ -2694,15 +2736,11 @@ int update_line(filestruct *fileptr, size_t index)
|
||||
|
||||
/* Expand the line, replacing tabs with spaces, and control
|
||||
* characters with their displayed forms. */
|
||||
#ifdef NANO_TINY
|
||||
converted = display_string(fileptr->data, page_start, editwincols, TRUE);
|
||||
#else
|
||||
converted = display_string(fileptr->data, page_start, editwincols, !ISSET(SOFTWRAP));
|
||||
#ifdef DEBUG
|
||||
if (ISSET(SOFTWRAP) && strlen(converted) >= editwincols - 2)
|
||||
fprintf(stderr, "update_line(): converted(1) line = %s\n", converted);
|
||||
#endif
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Paint the line. */
|
||||
edit_draw(fileptr, converted, line, page_start);
|
||||
@@ -2727,7 +2765,7 @@ int update_line(filestruct *fileptr, size_t index)
|
||||
|
||||
/* Expand the line, replacing tabs with spaces, and control
|
||||
* characters with their displayed forms. */
|
||||
converted = display_string(fileptr->data, index, editwincols, !ISSET(SOFTWRAP));
|
||||
converted = display_string(fileptr->data, index, editwincols, TRUE);
|
||||
#ifdef DEBUG
|
||||
if (ISSET(SOFTWRAP) && strlen(converted) >= editwincols - 2)
|
||||
fprintf(stderr, "update_line(): converted(2) line = %s\n", converted);
|
||||
@@ -2755,31 +2793,32 @@ bool need_horizontal_scroll(const size_t old_column, const size_t new_column)
|
||||
return (get_page_start(old_column) != get_page_start(new_column));
|
||||
}
|
||||
|
||||
/* When edittop changes, try and figure out how many lines
|
||||
* we really have to work with (i.e. set maxrows). */
|
||||
/* When edittop changes, try and figure out how many lines we really
|
||||
* have to work with, accounting for softwrap mode. */
|
||||
void compute_maxrows(void)
|
||||
{
|
||||
int n;
|
||||
filestruct *foo = openfile->edittop;
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
int screenrow;
|
||||
filestruct *line = openfile->edittop;
|
||||
|
||||
if (!ISSET(SOFTWRAP)) {
|
||||
maxrows = editwinrows;
|
||||
return;
|
||||
}
|
||||
maxrows = 0;
|
||||
|
||||
maxrows = 0;
|
||||
for (n = 0; n < editwinrows && foo; n++) {
|
||||
maxrows++;
|
||||
n += strlenpt(foo->data) / editwincols;
|
||||
foo = foo->next;
|
||||
}
|
||||
for (screenrow = 0; screenrow < editwinrows && line != NULL; screenrow++) {
|
||||
screenrow += strlenpt(line->data) / editwincols;
|
||||
line = line->next;
|
||||
maxrows++;
|
||||
}
|
||||
|
||||
if (n < editwinrows)
|
||||
maxrows += editwinrows - n;
|
||||
if (screenrow < editwinrows)
|
||||
maxrows += editwinrows - screenrow;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "compute_maxrows(): maxrows = %d\n", maxrows);
|
||||
fprintf(stderr, "recomputed: maxrows = %d\n", maxrows);
|
||||
#endif
|
||||
} else
|
||||
#endif /* !NANO_TINY */
|
||||
maxrows = editwinrows;
|
||||
}
|
||||
|
||||
/* Scroll the edit window in the given direction and the given number
|
||||
@@ -2934,8 +2973,8 @@ void edit_redraw(filestruct *old_current)
|
||||
* if we've moved and changed text. */
|
||||
void edit_refresh(void)
|
||||
{
|
||||
filestruct *foo;
|
||||
int nlines;
|
||||
filestruct *line;
|
||||
int row = 0;
|
||||
|
||||
/* Figure out what maxrows should really be. */
|
||||
compute_maxrows();
|
||||
@@ -2944,29 +2983,30 @@ void edit_refresh(void)
|
||||
if (openfile->current->lineno < openfile->edittop->lineno ||
|
||||
openfile->current->lineno >= openfile->edittop->lineno + maxrows) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "edit_refresh(): line = %ld, edittop %ld + maxrows %d\n",
|
||||
fprintf(stderr, "edit-refresh: line = %ld, edittop = %ld and maxrows = %d\n",
|
||||
(long)openfile->current->lineno, (long)openfile->edittop->lineno, maxrows);
|
||||
#endif
|
||||
adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : STATIONARY);
|
||||
}
|
||||
|
||||
foo = openfile->edittop;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
|
||||
fprintf(stderr, "edit-refresh: now edittop = %ld\n", (long)openfile->edittop->lineno);
|
||||
#endif
|
||||
|
||||
for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
|
||||
nlines += update_line(foo, (foo == openfile->current) ?
|
||||
openfile->current_x : 0);
|
||||
foo = foo->next;
|
||||
line = openfile->edittop;
|
||||
|
||||
while (row < editwinrows && line != NULL) {
|
||||
if (line == openfile->current)
|
||||
row += update_line(line, openfile->current_x) + 1;
|
||||
else
|
||||
row += update_line(line, 0) + 1;
|
||||
line = line->next;
|
||||
}
|
||||
|
||||
for (; nlines < editwinrows; nlines++)
|
||||
blank_line(edit, nlines, 0, COLS);
|
||||
while (row < editwinrows)
|
||||
blank_line(edit, row++, 0, COLS);
|
||||
|
||||
reset_cursor();
|
||||
curs_set(1);
|
||||
wnoutrefresh(edit);
|
||||
|
||||
refresh_needed = FALSE;
|
||||
@@ -3070,25 +3110,24 @@ void display_main_list(void)
|
||||
* position always. In any case we reset suppress_cursorpos to FALSE. */
|
||||
void do_cursorpos(bool constant)
|
||||
{
|
||||
filestruct *f;
|
||||
char c;
|
||||
size_t i, cur_xpt = xplustabs() + 1;
|
||||
char saved_byte;
|
||||
size_t sum, cur_xpt = xplustabs() + 1;
|
||||
size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
|
||||
int linepct, colpct, charpct;
|
||||
|
||||
assert(openfile->fileage != NULL && openfile->current != NULL);
|
||||
|
||||
/* Determine the size of the file up to the cursor. */
|
||||
f = openfile->current->next;
|
||||
c = openfile->current->data[openfile->current_x];
|
||||
|
||||
openfile->current->next = NULL;
|
||||
saved_byte = openfile->current->data[openfile->current_x];
|
||||
openfile->current->data[openfile->current_x] = '\0';
|
||||
|
||||
i = get_totsize(openfile->fileage, openfile->current);
|
||||
sum = get_totsize(openfile->fileage, openfile->current);
|
||||
|
||||
openfile->current->data[openfile->current_x] = c;
|
||||
openfile->current->next = f;
|
||||
openfile->current->data[openfile->current_x] = saved_byte;
|
||||
|
||||
/* When not at EOF, subtract 1 for an overcounted newline. */
|
||||
if (openfile->current != openfile->filebot)
|
||||
sum--;
|
||||
|
||||
/* If the position needs to be suppressed, don't suppress it next time. */
|
||||
if (suppress_cursorpos && constant) {
|
||||
@@ -3099,14 +3138,14 @@ void do_cursorpos(bool constant)
|
||||
/* Display the current cursor position on the statusbar. */
|
||||
linepct = 100 * openfile->current->lineno / openfile->filebot->lineno;
|
||||
colpct = 100 * cur_xpt / cur_lenpt;
|
||||
charpct = (openfile->totsize == 0) ? 0 : 100 * i / openfile->totsize;
|
||||
charpct = (openfile->totsize == 0) ? 0 : 100 * sum / openfile->totsize;
|
||||
|
||||
statusline(HUSH,
|
||||
_("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
|
||||
(long)openfile->current->lineno,
|
||||
(long)openfile->filebot->lineno, linepct,
|
||||
(unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
|
||||
(unsigned long)i, (unsigned long)openfile->totsize, charpct);
|
||||
(unsigned long)sum, (unsigned long)openfile->totsize, charpct);
|
||||
|
||||
/* Displaying the cursor position should not suppress it next time. */
|
||||
suppress_cursorpos = FALSE;
|
||||
@@ -3145,7 +3184,6 @@ void spotlight(bool active, const char *word)
|
||||
room--;
|
||||
|
||||
reset_cursor();
|
||||
wnoutrefresh(edit);
|
||||
|
||||
if (active)
|
||||
wattron(edit, hilite_attribute);
|
||||
@@ -3161,6 +3199,8 @@ void spotlight(bool active, const char *word)
|
||||
|
||||
if (active)
|
||||
wattroff(edit, hilite_attribute);
|
||||
|
||||
wnoutrefresh(edit);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_EXTRA
|
||||
|
||||
Reference in New Issue
Block a user