Compare commits
212 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
244de605a7 | ||
|
|
002652d263 | ||
|
|
08b770d425 | ||
|
|
2dffcf101f | ||
|
|
96fbdfbc7d | ||
|
|
272a953889 | ||
|
|
db310ac9b6 | ||
|
|
c11c688420 | ||
|
|
514cd9a099 | ||
|
|
406e5242a3 | ||
|
|
c26f58e783 | ||
|
|
5ad26f864a | ||
|
|
e7f39bc248 | ||
|
|
0242d84218 | ||
|
|
7275e11c4f | ||
|
|
77d140728d | ||
|
|
4d2ada60f5 | ||
|
|
382c9d792d | ||
|
|
aeb49a8013 | ||
|
|
c05c914eee | ||
|
|
c19f0c732e | ||
|
|
6ad3700a3d | ||
|
|
4f156aa6db | ||
|
|
6142ef87b5 | ||
|
|
da2fce90bd | ||
|
|
1e3cffbbd6 | ||
|
|
92c97c70d4 | ||
|
|
b77b1391c3 | ||
|
|
7e0c4e5726 | ||
|
|
50616148b0 | ||
|
|
3e40e5d4b5 | ||
|
|
2f9232a493 | ||
|
|
0d5fbfb91c | ||
|
|
56147434f3 | ||
|
|
21cb01e543 | ||
|
|
ea9aaee8c7 | ||
|
|
c22cd03f18 | ||
|
|
bd1c5d7c63 | ||
|
|
00b293bf70 | ||
|
|
76a960d73d | ||
|
|
97eb0e515f | ||
|
|
68010d931a | ||
|
|
c661506681 | ||
|
|
0dd2a55284 | ||
|
|
49fc528d88 | ||
|
|
928a24c204 | ||
|
|
d8031af030 | ||
|
|
f85648db68 | ||
|
|
b2e2c89b62 | ||
|
|
290d278f68 | ||
|
|
8edb096821 | ||
|
|
0a387d9d08 | ||
|
|
6c16744292 | ||
|
|
86a64b1bb5 | ||
|
|
1fd2354ad4 | ||
|
|
c8bc05b10e | ||
|
|
ee57cbfa66 | ||
|
|
bd1fcc5fe2 | ||
|
|
370406bb41 | ||
|
|
85844ee6ef | ||
|
|
e38e2c634b | ||
|
|
d80109dd5e | ||
|
|
b305911cba | ||
|
|
d60f95137e | ||
|
|
14ac47517b | ||
|
|
20058a1b63 | ||
|
|
f6dd0ad18a | ||
|
|
a7ae1766c0 | ||
|
|
faa46a3c71 | ||
|
|
03b168d0e3 | ||
|
|
2f6647687a | ||
|
|
c9e9964207 | ||
|
|
0a3a6441bc | ||
|
|
2eafe7bf58 | ||
|
|
08c51cfd45 | ||
|
|
b472f5a633 | ||
|
|
5806bf5249 | ||
|
|
90a90365a8 | ||
|
|
9cd30d4917 | ||
|
|
f33d8cae30 | ||
|
|
e471e2d462 | ||
|
|
fe38b78486 | ||
|
|
1af1f5c9f4 | ||
|
|
b9e83fe9f8 | ||
|
|
cb10b2b908 | ||
|
|
19dfd20a88 | ||
|
|
d12fdda15b | ||
|
|
3930a697e8 | ||
|
|
9322e1e6a4 | ||
|
|
b70fe38eab | ||
|
|
1c528db8da | ||
|
|
1c9ab8bf16 | ||
|
|
e295070193 | ||
|
|
91951ab22a | ||
|
|
5b0ab8be62 | ||
|
|
ecef093def | ||
|
|
6d6f5bd4a7 | ||
|
|
e3dbffc9f7 | ||
|
|
2225d54126 | ||
|
|
9115828e76 | ||
|
|
b43a72471a | ||
|
|
2b5d29b8c6 | ||
|
|
b40520b574 | ||
|
|
992533b91e | ||
|
|
f3e8991206 | ||
|
|
df7353b312 | ||
|
|
f311c0af87 | ||
|
|
c88fae3310 | ||
|
|
68cfb08888 | ||
|
|
4cff67fdde | ||
|
|
aefe26d216 | ||
|
|
8eb99e2a1d | ||
|
|
19b6f906cc | ||
|
|
c38ffdc741 | ||
|
|
a472f480a7 | ||
|
|
4416d9c941 | ||
|
|
c073c5ae54 | ||
|
|
fc0ddab349 | ||
|
|
c6dbcf91c3 | ||
|
|
8c7a38596d | ||
|
|
1c2d2a4027 | ||
|
|
1e5614b31b | ||
|
|
04b9b9c78b | ||
|
|
41ad376b70 | ||
|
|
1349c1d02c | ||
|
|
4c566c7903 | ||
|
|
73a07215cc | ||
|
|
bf091be778 | ||
|
|
103dd06347 | ||
|
|
1d4c1e0bfc | ||
|
|
b3fbb7c7ff | ||
|
|
225203d40d | ||
|
|
c2a0c78d9b | ||
|
|
97f4fe26f0 | ||
|
|
ef071255e5 | ||
|
|
afb6a5b86d | ||
|
|
a37cd9f0ef | ||
|
|
6f12992cea | ||
|
|
d88423eaae | ||
|
|
8b28de1313 | ||
|
|
8fa72fb7e7 | ||
|
|
b4babc2036 | ||
|
|
f2150d3f98 | ||
|
|
033376aec0 | ||
|
|
e33a0b6dbe | ||
|
|
0894587305 | ||
|
|
960e848cc7 | ||
|
|
b4737072a6 | ||
|
|
8507dd4bd0 | ||
|
|
62eeda3e9f | ||
|
|
06c806215e | ||
|
|
d2b25120f0 | ||
|
|
0c319f8b4b | ||
|
|
4fcc760158 | ||
|
|
0d5f918453 | ||
|
|
9c7940b599 | ||
|
|
ccfb1eb0f1 | ||
|
|
7e3a9c3aa6 | ||
|
|
a730b25ef9 | ||
|
|
500fef8314 | ||
|
|
29986e95a0 | ||
|
|
4af1da7d95 | ||
|
|
528b79b5f3 | ||
|
|
03a81aa9c5 | ||
|
|
4957c1121d | ||
|
|
d9d8eb2480 | ||
|
|
d9aad9212f | ||
|
|
8b636de1d3 | ||
|
|
aeab800490 | ||
|
|
f8c33e8630 | ||
|
|
b6efea266e | ||
|
|
8686cb3d3d | ||
|
|
91fff2a2c8 | ||
|
|
d6f43bd156 | ||
|
|
ebbe546033 | ||
|
|
cf0eed6c36 | ||
|
|
feacacc46d | ||
|
|
af53c56ec8 | ||
|
|
019d7b34ca | ||
|
|
622995fb12 | ||
|
|
03586c60da | ||
|
|
07a39e8e18 | ||
|
|
1d7c177606 | ||
|
|
2ae490cd8f | ||
|
|
6fda7a7057 | ||
|
|
1e2833e07b | ||
|
|
067b0a3367 | ||
|
|
24b10179a1 | ||
|
|
c14b581e0a | ||
|
|
bfcb4cd415 | ||
|
|
8fef94cd7d | ||
|
|
61d7ca4c41 | ||
|
|
559858a3dd | ||
|
|
ddd9c7a022 | ||
|
|
03c689c22c | ||
|
|
5270dd8b32 | ||
|
|
f33796bee1 | ||
|
|
e679c518b1 | ||
|
|
ba9214c689 | ||
|
|
68acc1dfc5 | ||
|
|
1a4ec6c2d3 | ||
|
|
6bb30978fb | ||
|
|
c0c30731c4 | ||
|
|
49eaa7c465 | ||
|
|
c2b199e926 | ||
|
|
80552aeab7 | ||
|
|
dfbabc0411 | ||
|
|
59b9b222c8 | ||
|
|
79e3eaf73c | ||
|
|
9106cc8ecc | ||
|
|
17fb6dfdc0 | ||
|
|
95f417fa9a |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -36,3 +36,4 @@ core
|
||||
|
||||
/nano.spec
|
||||
/src/nano
|
||||
/src/revision.h
|
||||
|
||||
13
AUTHORS
13
AUTHORS
@@ -1,9 +1,9 @@
|
||||
This file lists people who have made significant contributions to the
|
||||
nano editor. Please see the ChangeLog for specific changes by author.
|
||||
-------------------------------------------------------------------------
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Chris Allegretta <chrisa@asty.org>
|
||||
* Original program author, former and current maintainer.
|
||||
* Original program author and long-time maintainer.
|
||||
|
||||
David Lawrence Ramsey <pooka109@gmail.com>
|
||||
* Former stable series maintainer. Multiple buffer support,
|
||||
@@ -44,6 +44,13 @@ Mike Frysinger <vapier@gentoo.org>
|
||||
Mark Majeres <mark@engine12.com>
|
||||
* A functional undo/redo system, and coloring nano's interface.
|
||||
|
||||
Mahyar Abbaspour <mahyar.abaspour@gmail.com>
|
||||
* Improved handling of SIGWINCH.
|
||||
|
||||
Mike Scalora <mike@scalora.org>
|
||||
* The comment/uncomment feature.
|
||||
|
||||
Benno Schulenberg <bensberg@justemail.net>
|
||||
* A bunch of small bug fixes, the cutword routines, some extra
|
||||
* An array of small bug fixes, the cut-word and block-jump
|
||||
routines, text selection by holding Shift, and some extra
|
||||
key bindings. Current maintainer.
|
||||
|
||||
@@ -2966,7 +2966,7 @@ GNU nano 2.3.0 - 2011.02.26
|
||||
by Eitan Adler <lists@eitanadler.com>.
|
||||
|
||||
2011-02-23 Kamil Dudka <kdudka@redhat.com>
|
||||
* doc/man/nanorc.5: Fix small typo.
|
||||
* doc/man/nanorc.5: Fix small typo. Report and original patch by John Bradshaw.
|
||||
|
||||
2011-02-22 Chris Allegretta <chrisa@asty.org>
|
||||
* color.c (nfreeregex): Fix that we were trying to set the pointer passed by value
|
||||
@@ -3009,7 +3009,7 @@ GNU nano 2.2.6 - 2010.11.22
|
||||
|
||||
GNU nano 2.2.5 - 2010.08.05
|
||||
|
||||
2010-08-04 Lauri Kasanen <curaga@operamail.comcuraga@operamail.com>
|
||||
2010-08-04 Lauri Kasanen <curaga@operamail.com>
|
||||
* doc/syntax/mgp.nanorc: New Magicpoint syntax highlighting definition.
|
||||
|
||||
2010-08-04 Peter <exodus@savannah>
|
||||
@@ -3028,7 +3028,7 @@ GNU nano 2.2.5 - 2010.08.05
|
||||
|
||||
GNU nano 2.2.4 - 2010.04.15
|
||||
|
||||
2010-04-07 Chris Allegretta <chrisa@asty.org>
|
||||
2010-04-14 Chris Allegretta <chrisa@asty.org>
|
||||
* doc/man/nano.1,nanorc.5: Remove the backup file warnings now
|
||||
that a sufficient security fix exists for the backup file code.
|
||||
|
||||
|
||||
13
IMPROVEMENTS
13
IMPROVEMENTS
@@ -1,5 +1,14 @@
|
||||
Improvements in nano
|
||||
====================
|
||||
Improvements in GNU nano
|
||||
========================
|
||||
|
||||
Since 2.6.0:
|
||||
- Shift plus the cursor keys can be used for selecting text.
|
||||
- Ctrl+Arrow should now work also on a Linux virtual console.
|
||||
- Ctrl+Up and Ctrl+Down jump to previous or next block of text.
|
||||
- Feedback during Unicode Input (M-V followed by six digits).
|
||||
- The option 'wordchars' for specifying extra word characters.
|
||||
- Hi-bit control characters are shown in a more readable manner.
|
||||
- The ability to use negative numbers at the Go To Line prompt.
|
||||
|
||||
Noteworthy changes since 2.2
|
||||
----------------------------
|
||||
|
||||
55
NEWS
55
NEWS
@@ -1,3 +1,40 @@
|
||||
2016.09.01 - GNU nano 2.7.0 "Suni" adds a new feature: allowing text to be
|
||||
selected by holding Shift together with the cursor keys.
|
||||
Besides that, nano now works also when run in very tiny
|
||||
terminals (down to one line, one column), and improves
|
||||
the handling of the prompt in cramped spaces. Not much,
|
||||
but it's time to get it out there.
|
||||
|
||||
|
||||
2016.08.10 - nano 2.6.3 "Marika" makes the Ctrl+Arrow keys work also on
|
||||
a Linux virtual console, takes as verbatim only the very
|
||||
first keystroke after M-V, removes any lock files that it
|
||||
holds when dying, doesn't abort when a word contains digits
|
||||
(when using the default speller), fixes a small sorting bug
|
||||
in the file browser, makes searching case-insensitively in
|
||||
a UTF-8 locale a little faster, and doesn't enter invalid
|
||||
bytes when holding down both Alt keys. Santé!
|
||||
|
||||
2016.07.28 - nano 2.6.2 "Le vent nous portera" adds two new features: the
|
||||
keystrokes Ctrl+Up and Ctrl+Down for jumping between blocks
|
||||
of text, and the option 'wordchars' for specifying which
|
||||
characters (beside alphanumeric ones) should be considered
|
||||
word-forming. Further, it provides feedback during Unicode
|
||||
input (M-V followed by a six-digit hexadecimal number which
|
||||
must start with 0 or 10), avoids a crash when resizing the
|
||||
window during Verbatim input, doesn't drop a keystroke after
|
||||
having been suspended, and replaces the beginning-of-line
|
||||
anchor (^) just once per line. There are also several tiny
|
||||
improvements in screen rendering and key handling. Come get
|
||||
your hair tousled!
|
||||
|
||||
2016.06.27 - nano 2.6.1 "Stampede" is chiefly a translation update, but also
|
||||
adds one little feature (the ability to use negative numbers
|
||||
with Go To Line: -1 meaning the first line from the bottom),
|
||||
includes syntax highlighting for Rust, and fixes three tiny
|
||||
bugs (but in such far corners of the editor that they aren't
|
||||
even worth mentioning).
|
||||
|
||||
2016.06.17 - nano 2.6.0 "Rubicon" fixes more than fifty little bugs -- and
|
||||
some of them not so little. It improves moving about in
|
||||
the file browser, corrects failings of the internal spell
|
||||
@@ -15,7 +52,7 @@
|
||||
2016.02.25 - GNU nano 2.5.3 "Alphys" is released. This release
|
||||
contains fixes for bugs like: stray cursor positioning
|
||||
errors, many many memory leaks including file reading,
|
||||
using the file browser, searching for multi-byte characters,
|
||||
using the file browser, searching for multibyte characters,
|
||||
history completion, and many other places.
|
||||
New features include the ability to trim whitespace
|
||||
from the ends of lines when justifying text, see nanorc(5)
|
||||
@@ -141,7 +178,7 @@
|
||||
|
||||
2014.06.02 - GNU nano 2.3.4 won't leave you high, won't leave you dry. This
|
||||
release contains only a small number of fixes, but in
|
||||
particular allows nano to compile on non-UTF8 curses
|
||||
particular allows nano to compile on non-UTF-8 curses
|
||||
implementations (i.e. libncursesw). Other small fixes to
|
||||
the undo implementation and the default syntax config are
|
||||
also included. As always, Share and Enjoy!
|
||||
@@ -177,7 +214,7 @@
|
||||
release includes some fixes for the new libmagic code, as
|
||||
well as a fix for improper character counts when using
|
||||
auto-indent. Also included are new syntax highlighting
|
||||
definitions for RPM spec and lua files. Thanks for
|
||||
definitions for RPM spec and Lua files. Thanks for
|
||||
using nano and keep circulating the tapes.
|
||||
|
||||
2011.02.26 - GNU nano 2.3.0 "Septic surprise" is released. This first
|
||||
@@ -457,7 +494,7 @@
|
||||
thanks for sticking with us!
|
||||
|
||||
|
||||
2007.12.20- GNU nano 2.0.7 keeps its balance. This release fixes
|
||||
2007.12.20 - GNU nano 2.0.7 keeps its balance. This release fixes
|
||||
several bugs, among others: a segfault and several
|
||||
cursor positioning problems when uncutting text or
|
||||
inserting files into the current buffer; a problem where
|
||||
@@ -479,12 +516,12 @@
|
||||
under the GNU GPL version 3 or later and the GNU FDL
|
||||
version 1.2 or later. Have fun.
|
||||
|
||||
2007.04.26- GNU nano 2.0.6 "that was quick" is released. This release
|
||||
2007.04.26 - GNU nano 2.0.6 "that was quick" is released. This release
|
||||
fixes a potential segfault after justifying text marked
|
||||
from the bottom up. It also adds one more minor
|
||||
documentation update. Enjoy.
|
||||
|
||||
2007.04.22- GNU nano 2.0.5 braces for impact. Among other things, this
|
||||
2007.04.22 - GNU nano 2.0.5 braces for impact. Among other things, this
|
||||
release fixes various problems (including a segfault)
|
||||
when trying to open or save a file in a directory
|
||||
beginning with "~" that isn't a home directory; fixes a
|
||||
@@ -592,7 +629,7 @@
|
||||
properly at all times; lines of text containing tabs are
|
||||
now wrapped at the right place; double-column characters
|
||||
are now properly displayed when past the right edge of
|
||||
the screen; invalid multi-line color regexes are now
|
||||
the screen; invalid multiline color regexes are now
|
||||
ignored; and so on. Enjoy.
|
||||
|
||||
2006.03.30 - GNU nano 1.3.11 awakens from its fever dream. This release
|
||||
@@ -930,7 +967,7 @@
|
||||
0.11.2 of gettext, building with automake 1.6, some new
|
||||
code for displaying control characters, browser
|
||||
improvements, a new backup file option (-B, --backup), a
|
||||
new option to ignore rc files (-I,--ignorercfiles),
|
||||
new option to ignore rc files (-I, --ignorercfiles),
|
||||
compatibility with -pedantic, handling null characters
|
||||
before EOF, a slightly sportier nanorc.sample and more.
|
||||
Fixes are included for justification,
|
||||
@@ -1159,7 +1196,7 @@
|
||||
nasty segfault when trying to insert one's home
|
||||
directory (~), some checks for the NumLock key making
|
||||
the keypad go awry, window size sanity checks, many
|
||||
autoconf fixes, and support for the KDE konsole keypad
|
||||
autoconf fixes, and support for the KDE Konsole keypad
|
||||
layout. Have fun.
|
||||
|
||||
2001.01.07 - Nano 0.9.25 is the "Just one more feature I swear!"
|
||||
|
||||
8
README
8
README
@@ -1,5 +1,5 @@
|
||||
|
||||
nano - an enhanced clone of the Pico text editor
|
||||
GNU nano - an enhanced clone of the Pico text editor.
|
||||
|
||||
Overview
|
||||
|
||||
@@ -40,7 +40,7 @@ How to compile and install nano
|
||||
|
||||
Web Page
|
||||
|
||||
http://www.nano-editor.org/
|
||||
https://nano-editor.org/
|
||||
|
||||
Mailing Lists and Bug Reports
|
||||
|
||||
@@ -68,5 +68,5 @@ Mailing Lists and Bug Reports
|
||||
|
||||
Current Status
|
||||
|
||||
nano has reached its seventh milestone, 2.6.x. Since 2.5.0, it is
|
||||
a "rolling" release: bug fixing and development go hand in hand.
|
||||
GNU nano has reached its seventh milestone, 2.6.x. Since 2.5.0, it
|
||||
is a "rolling" release: bug fixing and development go hand in hand.
|
||||
|
||||
31
README.GIT
31
README.GIT
@@ -1,14 +1,14 @@
|
||||
INSTRUCTIONS TO COMPILE AND INSTALL NANO GIT VERSIONS
|
||||
=====================================================
|
||||
|
||||
The latest version of nano is available via git, but building this needs a
|
||||
bit more care than the official stable and unstable tarballs.
|
||||
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.
|
||||
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
To successfully compile nano from the git repo, you'll need the following
|
||||
To successfully compile GNU nano from the git repo, you'll need the following
|
||||
packages:
|
||||
|
||||
- autoconf (version >= 2.61)
|
||||
@@ -80,5 +80,26 @@ you'll need to run that "make install" command with root privileges.
|
||||
Problems?
|
||||
---------
|
||||
|
||||
Please submit any bugs in the git repository using the Savannah project's
|
||||
bug tracker (https://savannah.gnu.org/bugs/?group=nano).
|
||||
Please submit any bugs you find in the code in git via the bug tracker
|
||||
on Savannah (https://savannah.gnu.org/bugs/?group=nano).
|
||||
|
||||
|
||||
Contributing something
|
||||
----------------------
|
||||
|
||||
If you have a fix for a bug, or the code for a new or improved feature,
|
||||
first create a branch off of master:
|
||||
|
||||
$ git checkout -b somename
|
||||
|
||||
Then change the code so it does what you want, and commit it, with in the
|
||||
commit message (after the one-line summary) a rationale for the change:
|
||||
|
||||
$ git commit -as
|
||||
|
||||
Then create a patch (or patches):
|
||||
|
||||
$ git format-patch master
|
||||
|
||||
Send that patch (or patches) to <nano-devel@gnu.org>, as an attachment
|
||||
or with git send-email.
|
||||
|
||||
2
THANKS
2
THANKS
@@ -1,4 +1,4 @@
|
||||
The following people have helped nano in some way or other.
|
||||
The following people have helped GNU nano in some way or another.
|
||||
If we missed you here, let us know!
|
||||
|
||||
|
||||
|
||||
32
configure.ac
32
configure.ac
@@ -1,24 +1,22 @@
|
||||
# Configuration for nano - a small and user-friendly text editor
|
||||
# Configuration for GNU nano - a small and user-friendly text editor
|
||||
#
|
||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
# 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc.
|
||||
#
|
||||
# nano is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 3, or (at your option) any
|
||||
# later version.
|
||||
# GNU nano is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# nano is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
# GNU nano is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with nano; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
|
||||
# USA.
|
||||
# along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
AC_INIT([nano], [2.6.0], [nano-devel@gnu.org], [nano])
|
||||
AC_INIT([GNU nano], [2.7.0], [nano-devel@gnu.org], [nano])
|
||||
AC_CONFIG_SRCDIR([src/nano.c])
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE
|
||||
@@ -708,16 +706,16 @@ AM_CONDITIONAL(GROFF_HTML, test x$groff_html_support = xyes)
|
||||
AC_CHECK_PROG(haveit, makeinfo, yes, no)
|
||||
AM_CONDITIONAL(HAVE_MAKEINFO, test x$haveit = xyes)
|
||||
|
||||
# Check whether this is a git repository.
|
||||
AC_MSG_CHECKING([whether building from git])
|
||||
if test -d .git ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_PATH_PROG([GIT], [git])
|
||||
REVISION=`($GIT rev-parse --is-inside-work-tree >/dev/null 2>&1) && ($GIT rev-parse --short HEAD)`
|
||||
AC_SUBST(REVISION)
|
||||
AC_DEFINE_UNQUOTED([REVISION],"${REVISION}","Setting REVISION in config.h.")
|
||||
from_git=yes
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
from_git=no
|
||||
fi
|
||||
AM_CONDITIONAL(BUILDING_FROM_GIT, test x$from_git = xyes)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
|
||||
33
doc/faq.html
33
doc/faq.html
@@ -1,21 +1,21 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>The nano editor FAQ</title>
|
||||
<title>The GNU nano editor FAQ</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body text="#330000" bgcolor="#ffffff" link="#0000ef" vlink="#51188e" alink="#ff0000">
|
||||
<h1>The nano editor FAQ</h1>
|
||||
<h1>The GNU nano editor FAQ</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<h2><a href="#1">1. General</a></h2>
|
||||
<blockquote><p><a href="#1.1">1.1 About this FAQ</a><br>
|
||||
<a href="#1.2">1.2. How do I contribute to it?</a><br>
|
||||
<a href="#1.3">1.3. What is nano?</a><br>
|
||||
<a href="#1.3">1.3. What is GNU nano?</a><br>
|
||||
<a href="#1.4">1.4. What is the history behind nano?</a><br>
|
||||
<a href="#1.5">1.5. Why the name change from TIP?</a><br>
|
||||
<a href="#1.6">1.6. What is the current version of nano?</a><br>
|
||||
<a href="#1.7">1.7. I want to read the manpage without having to download the program!</a></p></blockquote>
|
||||
<h2><a href="#2">2. Where to get nano.</a></h2>
|
||||
<h2><a href="#2">2. Where to get GNU nano.</a></h2>
|
||||
<blockquote><p><a href="#2.1">2.1. FTP and WWW sites that carry nano.</a><br>
|
||||
<a href="#2.2">2.2. RedHat and derivatives (.rpm) packages.</a><br>
|
||||
<a href="#2.3">2.3. Debian (.deb) packages.</a><br>
|
||||
@@ -69,8 +69,8 @@
|
||||
<blockquote><p>This FAQ was originally written and maintained by Chris Allegretta <<a href="mailto:chrisa@asty.org">chrisa@asty.org</a>>, who also happens to be the creator of nano. It was then maintained by David Lawrence Ramsey <<a href="mailto:pooka109@gmail.com">pooka109@gmail.com</a>>. Maybe someone else will volunteer to maintain this FAQ someday, who knows...</p></blockquote>
|
||||
<h2><a name="1.2"></a>1.2. How do I contribute to it?</h2>
|
||||
<blockquote><p>Your best bet is to send it to the nano email address, <a href="mailto:nano@nano-editor.org">nano@nano-editor.org</a> and if it is useful enough it will be included in future versions.</p></blockquote>
|
||||
<h2><a name="1.3"></a>1.3. What is nano?</h2>
|
||||
<blockquote><p>nano is designed to be a free replacement for the Pico text editor, part of the Pine email suite from <a href="http://www.washington.edu/pine/">The University of Washington</a>. It aims to "emulate Pico as closely as possible and perhaps include extra functionality".</p></blockquote>
|
||||
<h2><a name="1.3"></a>1.3. What is GNU nano?</h2>
|
||||
<blockquote><p>GNU nano is designed to be a free replacement for the Pico text editor, part of the Pine email suite from <a href="http://www.washington.edu/pine/">The University of Washington</a>. It aims to "emulate Pico as closely as possible and perhaps include extra functionality".</p></blockquote>
|
||||
<h2><a name="1.4"></a>1.4. What is the history behind nano?</h2>
|
||||
<blockquote><p>Funny you should ask!</p>
|
||||
<p><b>In the beginning...</b></p>
|
||||
@@ -84,22 +84,21 @@
|
||||
<h2><a name="1.5"></a>1.5. Why the name change from TIP?</h2>
|
||||
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program "establishes a full duplex terminal connection to a remote host", and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
|
||||
<h2><a name="1.6"></a>1.6. What is the current version of nano?</h2>
|
||||
<blockquote><p>The current stable version of nano *should* be 2.4.2. Of course, you should always check the <a href="http://www.nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<blockquote><p>The current stable version of nano *should* be 2.4.2. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<h2><a name="1.7"></a>1.7. I want to read the man page without having to download the program!</h2>
|
||||
<blockquote><p>Jeez, demanding, aren't we? Okay, look <a href="http://www.nano-editor.org/dist/v2.4/nano.1.html">here</a>.</p></blockquote>
|
||||
<blockquote><p>Jeez, demanding, aren't we? Okay, look <a href="https://nano-editor.org/dist/v2.6/nano.1.html">here</a>.</p></blockquote>
|
||||
<hr width="100%">
|
||||
<h1><a name="2"></a>2. Where to get nano.</h1>
|
||||
<h1><a name="2"></a>2. Where to get GNU nano.</h1>
|
||||
<h2><a name="2.1"></a>2.1. FTP and WWW sites that carry nano.</h2>
|
||||
<blockquote><p>The nano distribution can be downloaded at the following fine web and ftp sites:</p>
|
||||
<blockquote><p>The nano distribution can be downloaded at the following web sites:</p>
|
||||
<ul>
|
||||
<li><a href="http://www.nano-editor.org/dist/">http://www.nano-editor.org/dist/</a></li>
|
||||
<li><a href="ftp://ftp.gnu.org/pub/gnu/nano/">ftp://ftp.gnu.org/pub/gnu/nano/</a></li>
|
||||
<li><a href="https://nano-editor.org/dist/">https://nano-editor.org/dist/</a></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h2><a name="2.2"></a>2.2. RedHat and derivatives (.rpm) packages.</h2>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><a href="http://www.nano-editor.org/dist/v2.2/RPMS/">http://www.nano-editor.org/dist/v2.2/RPMS/</a></li>
|
||||
<li><a href="https://nano-editor.org/dist/v2.5/RPMS/">https://nano-editor.org/dist/v2.5/RPMS/</a></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h2><a name="2.3"></a>2.3. Debian (.deb) packages.</h2>
|
||||
@@ -222,7 +221,7 @@
|
||||
<hr width="100%">
|
||||
<h1><a name="5"></a>5. Internationalization</h1>
|
||||
<h2><a name="5.1"></a>5.1. There's no translation for my language!</h2>
|
||||
<blockquote><p>In June 2001, nano entered the <a href="http://translationproject.org/html/welcome.html">Translation Project</a> and since then, translations should be managed from there.</p>
|
||||
<blockquote><p>In June 2001, GNU nano entered the <a href="http://translationproject.org/html/welcome.html">Translation Project</a> and since then, translations should be managed from there.</p>
|
||||
<p>If there isn't a translation for your language, you could ask <a href="http://translationproject.org/team/">your language team</a> to translate nano, or better still, join that team and do it yourself. Joining a team is easy. You just need to ask the team leader to add you, and then send a <a href="http://translationproject.org/disclaim.txt">translation disclaimer to the FSF</a> (this is necessary as nano is an official GNU package, but it does <b>not</b> mean that you transfer the rights of your work to the FSF, it's just so the FSF can legally manage them).</p>
|
||||
<p>In any case, translating nano is very easy. Just grab the latest <b>nano.pot</b> file listed on <a href="http://translationproject.org/domain/nano.html">nano's page</a> at the TP, and translate each <b>msgid</b> line into your native language on the <b>msgstr</b> line. When you're done, you should send it to the TP's central po repository.</p></blockquote>
|
||||
<h2><a name="5.2"></a>5.2. I don't like the translation for <x> in my language. How can I fix it?</h2>
|
||||
@@ -232,9 +231,9 @@
|
||||
<hr width="100%">
|
||||
<h1><a name="6"></a>6. Advocacy and Licensing</h1>
|
||||
<h2><a name="6.1"></a>6.1. Why should I use nano instead of Pico?</h2>
|
||||
<blockquote><p>There are many reasons to use nano instead of Pico. A more complete list can be found at the <a href="http://www.nano-editor.org/">nano homepage</a>.</p></blockquote>
|
||||
<blockquote><p>There are many reasons to use nano instead of Pico. A more complete list can be found at the <a href="https://nano-editor.org/">nano homepage</a>.</p></blockquote>
|
||||
<h2><a name="6.2"></a>6.2. Why should I use Pico instead of nano?</h2>
|
||||
<blockquote><p>Again, check out the <a href="http://www.nano-editor.org/">nano homepage</a> for a good summary of reasons. It really is a matter of personal preference as to which editor you should use. If you're the type of person who likes using the original version of a program, then Pico is the editor for you. If you don't mind sacrificing mailer integration with Pine, and are looking for a few more features, as well as a 'better' license in terms of adding your own changes, nano is the way to go.</p><p>Note that the last of these no longer applies to the new version of Pine, <a href="http://www.washington.edu/alpine/">Alpine</a>, which is under the Apache License, version 2.0.</p></blockquote>
|
||||
<blockquote><p>Again, check out the <a href="https://nano-editor.org/">nano homepage</a> for a good summary of reasons. It really is a matter of personal preference as to which editor you should use. If you're the type of person who likes using the original version of a program, then Pico is the editor for you. If you don't mind sacrificing mailer integration with Pine, and are looking for a few more features, as well as a 'better' license in terms of adding your own changes, nano is the way to go.</p><p>Note that the last of these no longer applies to the new version of Pine, <a href="http://www.washington.edu/alpine/">Alpine</a>, which is under the Apache License, version 2.0.</p></blockquote>
|
||||
<h2><a name="6.3"></a>6.3. What is so bad about the older Pine license?</h2>
|
||||
<blockquote><p>The U of W license for older versions of Pine and Pico is not considered truly Free Software according to both the Free Software Foundation and the <a href="http://www.debian.org/social_contract#guidelines">Debian Free Software Guidelines</a>. The main problem regards the limitations on distributing derived works: according to UW, you can distribute their software, and you can modify it, but you can not do both, i.e. distribute modified binaries.</p></blockquote>
|
||||
<h2><a name="6.4"></a>6.4. Okay, well, what mail program should I use then?</h2>
|
||||
@@ -248,7 +247,7 @@ Of course, due to the license change you can now use the <A HREF="http://www.was
|
||||
help-nano - <a href="http://mail.gnu.org/mailman/listinfo/help-nano/">http://mail.gnu.org/mailman/listinfo/help-nano/</a><br>
|
||||
nano-devel - <a href="http://mail.gnu.org/mailman/listinfo/nano-devel/">http://mail.gnu.org/mailman/listinfo/nano-devel/</a></p></blockquote>
|
||||
<h2><a name="7.2"></a>7.2. I want to send the development team a big load of cash (or just a thank you).</h2>
|
||||
<blockquote><p>That's fine. Send it <a href="mailto:nano-devel@gnu.org">our way</a>! Better yet, fix a <a href="https://savannah.gnu.org/bugs/?group=nano">bug</a> in the program or implement a <a href="http://www.nano-editor.org/dist/v2.3/TODO">cool feature</a> and send us that instead (though cash is fine too).</p></blockquote>
|
||||
<blockquote><p>That's fine. Send it <a href="mailto:nano-devel@gnu.org">our way</a>! Better yet, fix a <a href="https://savannah.gnu.org/bugs/?group=nano">bug</a> in the program or implement a <a href="https://nano-editor.org/dist/v2.6/TODO">cool feature</a> and send us that instead (though cash is fine too).</p></blockquote>
|
||||
<h2><a name="7.3"></a>7.3. How do I submit a bug report or patch?</h2>
|
||||
<blockquote>
|
||||
<p>The best place to submit bugs is to the <a href="https://savannah.gnu.org/bugs/?group=nano">Savannah bug tracker</a> as you can check whether the bug you are submitting has already been submitted.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANO 1 "version 2.6.0" "June 2016"
|
||||
.TH NANO 1 "version 2.7.0" "September 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
|
||||
@@ -48,9 +48,13 @@ contents of the cutbuffer at the current cursor position.
|
||||
When a more precise piece of text needs to be cut or copied, one can mark
|
||||
its start with \fB^6\fR, move the cursor to its end (the marked text will be
|
||||
highlighted), and then use \fB^K\fR to cut it, or \fBM-6\fR to copy it to the
|
||||
cutbuffer. One can also save the marked text to a file with \fB^O\fR, or
|
||||
cutbuffer. One can also save the marked text to a file with \fB^O\fR, or
|
||||
spell check it with \fB^T\fR.
|
||||
.PP
|
||||
Since nano-2.7.0, text can also be selected by holding Shift and moving the
|
||||
cursor with the arrow keys. Holding down the Alt key too will increase the
|
||||
stride.
|
||||
.PP
|
||||
The two lines at the bottom of the screen show the most important commands;
|
||||
the built-in help (\fB^G\fR) lists all the available ones.
|
||||
The default key bindings can be changed via the .nanorc file -- see
|
||||
@@ -148,9 +152,14 @@ keystroke instead of 25. Note that \fB\-c\fP overrides this.
|
||||
Show the current version number and exit.
|
||||
.TP
|
||||
.BR \-W ", " \-\-wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as part of a word.
|
||||
.TP
|
||||
.BR "\-X ""\fIcharacters\fB""" ", " "\-\-wordchars=""" \fIcharacters """
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as part of a word. This overrides option
|
||||
\fB\-W\fR (\fB\-\-wordbounds\fR).
|
||||
.TP
|
||||
.BR \-Y\ \fIname\fR ", " \-\-syntax= \fIname
|
||||
Specify the name of the syntax highlighting to use from among the ones
|
||||
defined in the \fInanorc\fP files.
|
||||
@@ -278,7 +287,7 @@ Please report any other bugs that you encounter via
|
||||
https://savannah.gnu.org/bugs/?group=nano.
|
||||
|
||||
.SH HOMEPAGE
|
||||
http://www.nano-editor.org/
|
||||
https://nano-editor.org/
|
||||
|
||||
.SH SEE ALSO
|
||||
.PD 0
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANORC 5 "version 2.6.0" "June 2016"
|
||||
.TH NANORC 5 "version 2.7.0" "September 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.SH NAME
|
||||
nanorc \- nano's rcfile
|
||||
nanorc \- GNU nano's rcfile
|
||||
.SH DESCRIPTION
|
||||
The \fInanorc\fP file contains the default settings for \fBnano\fP, a
|
||||
small and friendly editor. The file should be in Unix format, not in
|
||||
@@ -253,8 +253,13 @@ Set the two characters used to indicate the presence of tabs and
|
||||
spaces. They must be single-column characters.
|
||||
.TP
|
||||
.B set wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as parts of words.
|
||||
.TP
|
||||
.B set wordchars \fIstring\fP
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as parts of words. This overrides the option
|
||||
\fBwordbounds\fR.
|
||||
|
||||
.SH SYNTAX HIGHLIGHTING
|
||||
Coloring the different syntactic elements of a file
|
||||
@@ -505,6 +510,13 @@ Moves the cursor to the beginning of the current paragraph.
|
||||
.B endpara
|
||||
Moves the cursor to the end of the current paragraph.
|
||||
.TP
|
||||
.B prevblock
|
||||
Moves the cursor to the beginning of the current or preceding block of text.
|
||||
(Blocks are separated by one or more blank lines.)
|
||||
.TP
|
||||
.B nextblock
|
||||
Moves the cursor to the beginning of the next block of text.
|
||||
.TP
|
||||
.B prevpage
|
||||
Goes up one screenful.
|
||||
.TP
|
||||
@@ -518,7 +530,8 @@ Goes to the first line of the file.
|
||||
Goes to the last line of the file.
|
||||
.TP
|
||||
.B gotoline
|
||||
Goes to a specific line (and column if specified).
|
||||
Goes to a specific line (and column if specified). Negative numbers count
|
||||
from the end of the file (and end of the line).
|
||||
.TP
|
||||
.B gototext
|
||||
Switches from targeting a line number to searching for text.
|
||||
@@ -534,7 +547,7 @@ Switches to editing/viewing the previous buffer when multiple buffers are open.
|
||||
Switches to editing/viewing the next buffer when multiple buffers are open.
|
||||
.TP
|
||||
.B verbatim
|
||||
Inserts the next character verbatim into the file.
|
||||
Inserts the next keystroke verbatim into the file.
|
||||
.TP
|
||||
.B tab
|
||||
Inserts a tab at the current cursor location.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 2.6.0" "June 2016"
|
||||
.TH RNANO 1 "version 2.7.0" "September 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.SH NAME
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
## Sample initialization file for nano.
|
||||
## Sample initialization file for GNU nano.
|
||||
##
|
||||
## Please note that you must have configured nano with --enable-nanorc
|
||||
## for this file to be read! Also note that this file should not be in
|
||||
@@ -178,10 +178,15 @@
|
||||
## The default otherwise:
|
||||
# set whitespace ">."
|
||||
|
||||
## Detect word boundaries more accurately by treating punctuation
|
||||
## Detect word boundaries differently by treating punctuation
|
||||
## characters as parts of words.
|
||||
# set wordbounds
|
||||
|
||||
## The characters (besides alphanumeric ones) that should be considered
|
||||
## as parts of words. This option does not have a default value. When
|
||||
## set, it overrides option 'set wordbounds'.
|
||||
# set wordchars "<_>."
|
||||
|
||||
|
||||
## Paint the interface elements of nano.
|
||||
## This is an example; by default there are no colors.
|
||||
|
||||
@@ -34,6 +34,7 @@ pkgdata_DATA = asm.nanorc \
|
||||
pov.nanorc \
|
||||
python.nanorc \
|
||||
ruby.nanorc \
|
||||
rust.nanorc \
|
||||
sh.nanorc \
|
||||
spec.nanorc \
|
||||
tcl.nanorc \
|
||||
|
||||
39
doc/syntax/rust.nanorc
Normal file
39
doc/syntax/rust.nanorc
Normal file
@@ -0,0 +1,39 @@
|
||||
## Syntax highlighting for Rust.
|
||||
## Copyright 2015 Luke Francl.
|
||||
## Licensed under GPL version 3.
|
||||
|
||||
## NOTE: Rules are applied in order: later rules re-colorize matching text.
|
||||
|
||||
syntax "rust" "\.rs"
|
||||
comment "//"
|
||||
|
||||
# Function definitions
|
||||
color magenta "fn [a-z_0-9]+"
|
||||
|
||||
# Reserved words
|
||||
color yellow "\<(abstract|alignof|as|become|box|break|const|continue|crate|do|else|enum|extern|false|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|offsetof|override|priv|pub|pure|ref|return|sizeof|static|self|struct|super|true|trait|type|typeof|unsafe|unsized|use|virtual|where|while|yield)\>"
|
||||
|
||||
# Macros
|
||||
color red "[a-z_]+!"
|
||||
|
||||
# Constants
|
||||
color magenta "[A-Z][A-Z_0-9]+"
|
||||
|
||||
# Traits/Enums/Structs/Types/...
|
||||
color magenta "[A-Z][A-Za-z0-9]+"
|
||||
|
||||
# Strings
|
||||
color green "\".*\""
|
||||
color green start="\".*\\$" end=".*\""
|
||||
## NOTE: This isn't accurate, but matching "#{0,} for the end of the string is too liberal.
|
||||
color green start="r#+\"" end="\"#+"
|
||||
|
||||
# Comments
|
||||
color blue "//.*"
|
||||
color blue start="/\*" end="\*/"
|
||||
|
||||
# Attributes
|
||||
color magenta start="#!\[" end="\]"
|
||||
|
||||
# Some common markers
|
||||
color brightcyan "(XXX|TODO|FIXME|\?\?\?)"
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
@smallbook
|
||||
@set EDITION 0.4
|
||||
@set VERSION 2.6.0
|
||||
@set UPDATED June 2016
|
||||
@set VERSION 2.7.0
|
||||
@set UPDATED September 2016
|
||||
|
||||
@dircategory Editors
|
||||
@direntry
|
||||
@@ -19,16 +19,16 @@
|
||||
@c end tex
|
||||
|
||||
@titlepage
|
||||
@title @code{nano}
|
||||
@title GNU @code{nano}
|
||||
@subtitle a small and friendly text editor.
|
||||
@subtitle version 2.6.0
|
||||
@subtitle version 2.7.0
|
||||
|
||||
@author Chris Allegretta
|
||||
@page
|
||||
|
||||
This manual documents @code{nano}, a small and friendly text editor.
|
||||
This manual documents GNU @code{nano}, a small and friendly text editor.
|
||||
|
||||
This manual is part of the @code{nano} distribution.@*
|
||||
This manual is part of the GNU @code{nano} distribution.@*
|
||||
@sp 4
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
2009, 2014, 2015 Free Software Foundation, Inc.
|
||||
@@ -55,7 +55,7 @@ e-mail: @email{chrisa@@asty.org}@*
|
||||
@node Top
|
||||
@top
|
||||
|
||||
This manual documents @code{nano}, a small and friendly text editor.
|
||||
This manual documents GNU @code{nano}, a small and friendly text editor.
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
@@ -74,7 +74,7 @@ This manual documents @code{nano}, a small and friendly text editor.
|
||||
@node Introduction
|
||||
@chapter Introduction
|
||||
|
||||
@code{nano} is a small and friendly text editor. Besides basic text
|
||||
GNU @code{nano} is a small and friendly text editor. Besides basic text
|
||||
editing, @code{nano} offers many extra features, such as an interactive
|
||||
search-and-replace, undo/redo, syntax coloring, smooth scrolling,
|
||||
auto-indentation, go-to-line-and-column-number, feature toggles,
|
||||
@@ -231,9 +231,15 @@ Show the current version number and exit.
|
||||
|
||||
@item -W
|
||||
@itemx --wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as parts of words.
|
||||
|
||||
@item -X "@var{characters}"
|
||||
@itemx --wordchars="@var{characters}"
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as parts of words. This overrides option
|
||||
@option{-W} (@option{--wordbounds}).
|
||||
|
||||
@item -Y @var{name}
|
||||
@itemx --syntax=@var{name}
|
||||
Specify a specific syntax from the nanorc files to use for highlighting.
|
||||
@@ -831,9 +837,14 @@ spaces. They must be single-column characters. The default pair
|
||||
for a UTF-8 locale is @t{"»·"}, and for other locales @t{">."}.
|
||||
|
||||
@item set wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as part of a word.
|
||||
|
||||
@item set wordchars "@var{string}"
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as parts of words. This overrides the option
|
||||
@code{wordbounds}.
|
||||
|
||||
@end table
|
||||
|
||||
@node Syntax Highlighting
|
||||
@@ -1091,6 +1102,13 @@ Moves the cursor to the beginning of the current paragraph.
|
||||
@item endpara
|
||||
Moves the cursor to the end of the current paragraph.
|
||||
|
||||
@item prevblock
|
||||
Moves the cursor to the beginning of the current or preceding block of text.
|
||||
(Blocks are separated by one or more blank lines.)
|
||||
|
||||
@item nextblock
|
||||
Moves the cursor to the beginning of the next block of text.
|
||||
|
||||
@item prevpage
|
||||
Goes up one screenful.
|
||||
|
||||
@@ -1104,7 +1122,8 @@ Goes to the first line of the file.
|
||||
Goes to the last line of the file.
|
||||
|
||||
@item gotoline
|
||||
Goes to a specific line (and column if specified).
|
||||
Goes to a specific line (and column if specified). Negative numbers count
|
||||
from the end of the file (and end of the line).
|
||||
|
||||
@item gototext
|
||||
Switches from targeting a line number to searching for text.
|
||||
@@ -1120,7 +1139,7 @@ Switches to editing/viewing the previous buffer when multiple buffers are open.
|
||||
Switches to editing/viewing the next buffer when multiple buffers are open.
|
||||
|
||||
@item verbatim
|
||||
Inserts the next character verbatim into the file.
|
||||
Inserts the next keystroke verbatim into the file.
|
||||
|
||||
@item tab
|
||||
Inserts a tab at the current cursor location.
|
||||
@@ -1472,7 +1491,7 @@ chances are you only want this feature when you're working on the nano source.
|
||||
|
||||
@item --disable-nls
|
||||
Disables Native Language support. This will disable the use of any
|
||||
available @code{nano} translations.
|
||||
available GNU @code{nano} translations.
|
||||
|
||||
@item --disable-wrapping-as-root
|
||||
Disable hard-wrapping of overlong lines by default when @code{nano}
|
||||
|
||||
@@ -9,8 +9,8 @@ Summary : a user-friendly editor, a Pico clone with enhancements
|
||||
|
||||
License : GPLv3+
|
||||
Group : Applications/Editors
|
||||
URL : http://www.nano-editor.org/
|
||||
Source : http://www.nano-editor.org/dist/v2.4/%{name}-%{version}.tar.gz
|
||||
URL : https://nano-editor.org/
|
||||
Source : https://nano-editor.org/dist/v2.6/%{name}-%{version}.tar.gz
|
||||
|
||||
BuildRoot : %{_tmppath}/%{name}-%{version}-root
|
||||
BuildRequires : autoconf, automake, gettext-devel, ncurses-devel, texinfo
|
||||
@@ -18,7 +18,7 @@ Requires(post) : info
|
||||
Requires(preun) : info
|
||||
|
||||
%description
|
||||
nano is a small and friendly text editor. It aims to emulate the
|
||||
GNU nano is a small and friendly text editor. It aims to emulate the
|
||||
Pico text editor while also offering several enhancements.
|
||||
|
||||
%prep
|
||||
|
||||
1010
po/nano.pot
1010
po/nano.pot
File diff suppressed because it is too large
Load Diff
1166
po/pt_BR.po
1166
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Execute this is the po/ subdir.
|
||||
# Let this be executed in the po/ subdir.
|
||||
cd "$(dirname "$0")" || exit
|
||||
|
||||
echo "Updating translations via TP"
|
||||
@@ -15,10 +15,5 @@ if [ -n "${NEWSTUFF}" ]; then
|
||||
echo $(printf '%s\n' *.po | LC_ALL=C sort | sed 's/\.po//g') >>LINGUAS
|
||||
fi
|
||||
|
||||
echo "Remerging and recompiling the PO files..."
|
||||
make
|
||||
|
||||
#echo "Staging the files"
|
||||
#git add -v nano.pot
|
||||
#git add -v *.po
|
||||
#git add -v LINGUAS
|
||||
echo "Regenerating POT file and remerging and recompiling PO files..."
|
||||
make update-po
|
||||
|
||||
1021
po/zh_CN.po
1021
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1028
po/zh_TW.po
1028
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,21 @@
|
||||
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
|
||||
if BUILDING_FROM_GIT
|
||||
SOMETHING = "REVISION \"$(shell git describe --tags 2>/dev/null)\""
|
||||
else
|
||||
SOMETHING = "NOTHING \"from tarball\""
|
||||
endif
|
||||
|
||||
nano.o: revision.h
|
||||
winio.o: revision.h
|
||||
|
||||
revision.h: update_revision
|
||||
@[ -f $@ ] || touch $@
|
||||
@echo "#define $(SOMETHING)" | cmp -s $@ - || \
|
||||
echo "#define $(SOMETHING)" > $@
|
||||
|
||||
.PHONY: update_revision
|
||||
|
||||
bin_PROGRAMS = nano
|
||||
nano_SOURCES = browser.c \
|
||||
chars.c \
|
||||
|
||||
215
src/browser.c
215
src/browser.c
@@ -1,23 +1,22 @@
|
||||
/**************************************************************************
|
||||
* browser.c *
|
||||
* browser.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
|
||||
* 2010, 2011, 2013, 2014, 2015 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -46,7 +45,7 @@ static size_t selected = 0;
|
||||
* start browsing from. */
|
||||
char *do_browser(char *path)
|
||||
{
|
||||
char *retval = NULL, *newpath = NULL;
|
||||
char *retval = NULL;
|
||||
int kbinput;
|
||||
char *present_name = NULL;
|
||||
/* The name of the currently selected file, or of the directory we
|
||||
@@ -55,29 +54,19 @@ char *do_browser(char *path)
|
||||
/* The number of the selected file before the current selected file. */
|
||||
functionptrtype func;
|
||||
/* The function of the key the user typed in. */
|
||||
DIR *dir = opendir(path);
|
||||
|
||||
/* If we can't open the given directory, forget it. */
|
||||
if (dir == NULL) {
|
||||
beep();
|
||||
free(path);
|
||||
return NULL;
|
||||
}
|
||||
DIR *dir;
|
||||
/* The directory whose contents we are showing. */
|
||||
|
||||
/* Don't show a cursor in the file list. */
|
||||
curs_set(0);
|
||||
blank_statusbar();
|
||||
bottombars(MBROWSER);
|
||||
|
||||
read_directory_contents:
|
||||
/* We come here when we refresh or select a new directory. */
|
||||
|
||||
/* Start with no key pressed. */
|
||||
kbinput = ERR;
|
||||
path = free_and_assign(path, get_full_path(path));
|
||||
|
||||
path = mallocstrassn(path, get_full_path(newpath ? newpath : path));
|
||||
|
||||
if (path != NULL && newpath != NULL)
|
||||
if (path != NULL)
|
||||
dir = opendir(path);
|
||||
|
||||
if (path == NULL || dir == NULL) {
|
||||
@@ -115,50 +104,26 @@ char *do_browser(char *path)
|
||||
|
||||
old_selected = (size_t)-1;
|
||||
|
||||
newpath = NULL;
|
||||
present_path = mallocstrcpy(present_path, path);
|
||||
|
||||
titlebar(path);
|
||||
|
||||
while (TRUE) {
|
||||
struct stat st;
|
||||
int i;
|
||||
char *new_path;
|
||||
/* The path we switch to at the "Go to Directory"
|
||||
* prompt. */
|
||||
|
||||
/* Make sure that the cursor is off. */
|
||||
curs_set(0);
|
||||
lastmessage = HUSH;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH) {
|
||||
/* Remember the selected file, to be able to reselect it. */
|
||||
present_name = strdup(filelist[selected]);
|
||||
bottombars(MBROWSER);
|
||||
|
||||
/* Reopen the current directory. */
|
||||
dir = opendir(path);
|
||||
if (dir != NULL)
|
||||
goto read_directory_contents;
|
||||
|
||||
statusline(ALERT, _("Error reading %s: %s"), path, strerror(errno));
|
||||
kbinput = ERR;
|
||||
}
|
||||
#endif
|
||||
/* Display (or redisplay) the file list if we don't have a key yet,
|
||||
* or the list has changed, or the selected file has changed. */
|
||||
if (kbinput == ERR || old_selected != selected)
|
||||
/* Display (or redisplay) the file list if the list itself or
|
||||
* the selected file has changed. */
|
||||
if (old_selected != selected)
|
||||
browser_refresh();
|
||||
|
||||
old_selected = selected;
|
||||
|
||||
kbinput = get_kbinput(edit);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_MOUSE
|
||||
if (kbinput == KEY_MOUSE) {
|
||||
int mouse_x, mouse_y;
|
||||
@@ -183,7 +148,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, FALSE);
|
||||
unget_kbinput(sc_seq_or(do_enter, 0), FALSE);
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -194,15 +159,15 @@ char *do_browser(char *path)
|
||||
|
||||
if (func == total_refresh) {
|
||||
total_redraw();
|
||||
/* Simulate a window resize to force a directory reread. */
|
||||
#ifndef NANO_TINY
|
||||
/* Simulate a window resize to force a directory reread. */
|
||||
kbinput = KEY_WINCH;
|
||||
#endif
|
||||
} else if (func == do_help_void) {
|
||||
#ifndef DISABLE_HELP
|
||||
do_help_void();
|
||||
/* The window dimensions might have changed, so act as if. */
|
||||
#ifndef NANO_TINY
|
||||
/* The window dimensions might have changed, so act as if. */
|
||||
kbinput = KEY_WINCH;
|
||||
#endif
|
||||
#else
|
||||
@@ -214,6 +179,26 @@ char *do_browser(char *path)
|
||||
} else if (func == do_research) {
|
||||
/* Search for another filename. */
|
||||
do_fileresearch();
|
||||
} else if (func == do_left) {
|
||||
if (selected > 0)
|
||||
selected--;
|
||||
} else if (func == do_right) {
|
||||
if (selected < filelist_len - 1)
|
||||
selected++;
|
||||
#ifndef NANO_TINY
|
||||
} else if (func == do_prev_word_void) {
|
||||
selected -= (selected % width);
|
||||
} else if (func == do_next_word_void) {
|
||||
selected += width - 1 - (selected % width);
|
||||
if (selected >= filelist_len)
|
||||
selected = filelist_len - 1;
|
||||
#endif
|
||||
} else if (func == do_up_void) {
|
||||
if (selected >= width)
|
||||
selected -= width;
|
||||
} else if (func == do_down_void) {
|
||||
if (selected + width <= filelist_len - 1)
|
||||
selected += width;
|
||||
} else if (func == do_page_up) {
|
||||
if (selected < width)
|
||||
selected = 0;
|
||||
@@ -235,7 +220,7 @@ char *do_browser(char *path)
|
||||
selected = filelist_len - 1;
|
||||
} else if (func == goto_dir_void) {
|
||||
/* Ask for the directory to go to. */
|
||||
i = do_prompt(TRUE,
|
||||
int i = do_prompt(TRUE,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
FALSE,
|
||||
#endif
|
||||
@@ -246,8 +231,6 @@ char *do_browser(char *path)
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
browser_refresh, _("Go To Directory"));
|
||||
|
||||
bottombars(MBROWSER);
|
||||
|
||||
/* If the directory begins with a newline (i.e. an
|
||||
* encoded null), treat it as though it's blank. */
|
||||
if (i < 0 || *answer == '\n') {
|
||||
@@ -259,60 +242,41 @@ char *do_browser(char *path)
|
||||
sunder(answer);
|
||||
align(&answer);
|
||||
|
||||
new_path = real_dir_from_tilde(answer);
|
||||
path = free_and_assign(path, real_dir_from_tilde(answer));
|
||||
|
||||
if (new_path[0] != '/') {
|
||||
new_path = charealloc(new_path, strlen(path) +
|
||||
strlen(answer) + 1);
|
||||
sprintf(new_path, "%s%s", path, answer);
|
||||
/* If the given path is relative, join it with the current path. */
|
||||
if (*path != '/') {
|
||||
path = charealloc(path, strlen(present_path) +
|
||||
strlen(answer) + 1);
|
||||
sprintf(path, "%s%s", present_path, answer);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
if (check_operating_dir(new_path, FALSE)) {
|
||||
/* TRANSLATORS: This refers to the option --operatingdir,
|
||||
* not to --restricted. */
|
||||
statusline(ALERT, _("Can't go outside of %s "
|
||||
"in confined mode"), full_operating_dir);
|
||||
free(new_path);
|
||||
if (check_operating_dir(path, FALSE)) {
|
||||
/* TRANSLATORS: This refers to the confining effect of the
|
||||
* option --operatingdir, not of --restricted. */
|
||||
statusline(ALERT, _("Can't go outside of %s"),
|
||||
full_operating_dir);
|
||||
path = mallocstrcpy(path, present_path);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Snip any trailing slashes, so the name can be compared. */
|
||||
while (strlen(path) > 1 && path[strlen(path) - 1] == '/')
|
||||
path[strlen(path) - 1] = '\0';
|
||||
|
||||
dir = opendir(new_path);
|
||||
if (dir == NULL) {
|
||||
/* We can't open this directory for some reason. */
|
||||
statusline(ALERT, _("Error reading %s: %s"), answer,
|
||||
strerror(errno));
|
||||
free(new_path);
|
||||
continue;
|
||||
}
|
||||
/* In case the specified directory cannot be entered, select it
|
||||
* (if it is in the current list) so it will be highlighted. */
|
||||
for (i = 0; i < filelist_len; i++)
|
||||
if (strcmp(filelist[i], path) == 0)
|
||||
selected = i;
|
||||
|
||||
/* Start over again with the new path value. */
|
||||
free(path);
|
||||
path = new_path;
|
||||
/* Try opening and reading the specified directory. */
|
||||
goto read_directory_contents;
|
||||
} else if (func == do_up_void) {
|
||||
if (selected >= width)
|
||||
selected -= width;
|
||||
} else if (func == do_down_void) {
|
||||
if (selected + width <= filelist_len - 1)
|
||||
selected += width;
|
||||
#ifndef NANO_TINY
|
||||
} else if (func == do_prev_word_void) {
|
||||
selected -= (selected % width);
|
||||
} else if (func == do_next_word_void) {
|
||||
selected += width - 1 - (selected % width);
|
||||
if (selected >= filelist_len)
|
||||
selected = filelist_len - 1;
|
||||
#endif
|
||||
} else if (func == do_left) {
|
||||
if (selected > 0)
|
||||
selected--;
|
||||
} else if (func == do_right) {
|
||||
if (selected < filelist_len - 1)
|
||||
selected++;
|
||||
} else if (func == do_enter) {
|
||||
/* We can't move up from "/". */
|
||||
struct stat st;
|
||||
|
||||
/* It isn't possible to move up from the root directory. */
|
||||
if (strcmp(filelist[selected], "/..") == 0) {
|
||||
statusline(ALERT, _("Can't move up a directory"));
|
||||
continue;
|
||||
@@ -323,21 +287,20 @@ char *do_browser(char *path)
|
||||
* directory if it's ".." or if it's a symlink to a
|
||||
* directory outside the operating directory. */
|
||||
if (check_operating_dir(filelist[selected], FALSE)) {
|
||||
statusline(ALERT, _("Can't go outside of %s "
|
||||
"in confined mode"), full_operating_dir);
|
||||
statusline(ALERT, _("Can't go outside of %s"),
|
||||
full_operating_dir);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If for some reason the file is inaccessible, complain. */
|
||||
if (stat(filelist[selected], &st) == -1) {
|
||||
/* We can't open this file for some reason. Complain. */
|
||||
statusline(ALERT, _("Error reading %s: %s"),
|
||||
filelist[selected], strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If it isn't a directory, a file was selected -- we're done. */
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
/* We've successfully opened a file, so we're done. */
|
||||
retval = mallocstrcpy(NULL, filelist[selected]);
|
||||
break;
|
||||
}
|
||||
@@ -348,13 +311,27 @@ char *do_browser(char *path)
|
||||
present_name = striponedir(filelist[selected]);
|
||||
|
||||
/* Try opening and reading the selected directory. */
|
||||
newpath = filelist[selected];
|
||||
path = mallocstrcpy(path, filelist[selected]);
|
||||
goto read_directory_contents;
|
||||
} else if (func == do_exit) {
|
||||
/* Exit from the file browser. */
|
||||
break;
|
||||
#ifndef NANO_TINY
|
||||
} else if (kbinput == KEY_WINCH) {
|
||||
;
|
||||
#endif
|
||||
} else
|
||||
unbound_key(kbinput);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the window resized, refresh the file list. */
|
||||
if (kbinput == KEY_WINCH) {
|
||||
/* Remember the selected file, to be able to reselect it. */
|
||||
present_name = mallocstrcpy(NULL, filelist[selected]);
|
||||
/* Reread the contents of the current directory. */
|
||||
goto read_directory_contents;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
titlebar(NULL);
|
||||
@@ -389,7 +366,7 @@ char *do_browse_from(const char *inpath)
|
||||
* at all. If so, we'll just pass the current directory to
|
||||
* do_browser(). */
|
||||
if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
|
||||
path = mallocstrassn(path, striponedir(path));
|
||||
path = free_and_assign(path, striponedir(path));
|
||||
|
||||
if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
|
||||
char * currentdir = charalloc(PATH_MAX + 1);
|
||||
@@ -703,13 +680,13 @@ int filesearch_init(void)
|
||||
/* This is now one simple call. It just does a lot. */
|
||||
input = do_prompt(FALSE,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
TRUE,
|
||||
TRUE,
|
||||
#endif
|
||||
MWHEREISFILE, NULL,
|
||||
MWHEREISFILE, NULL,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
&search_history,
|
||||
&search_history,
|
||||
#endif
|
||||
browser_refresh, "%s%s", _("Search"), buf);
|
||||
browser_refresh, "%s%s", _("Search"), buf);
|
||||
|
||||
/* Release buf now that we don't need it anymore. */
|
||||
free(buf);
|
||||
@@ -782,11 +759,9 @@ void findnextfile(const char *needle)
|
||||
/* Search for a filename. */
|
||||
void do_filesearch(void)
|
||||
{
|
||||
if (filesearch_init() != 0) {
|
||||
/* Cancelled, or a blank search string, or done something. */
|
||||
bottombars(MBROWSER);
|
||||
/* If the user cancelled or jumped to first or last file, don't search. */
|
||||
if (filesearch_init() != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* If answer is now "", copy last_search into answer. */
|
||||
if (*answer == '\0')
|
||||
@@ -801,8 +776,6 @@ void do_filesearch(void)
|
||||
#endif
|
||||
|
||||
findnextfile(answer);
|
||||
|
||||
bottombars(MBROWSER);
|
||||
}
|
||||
|
||||
/* Search again for the last given filename, without prompting. */
|
||||
|
||||
311
src/chars.c
311
src/chars.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* chars.c *
|
||||
* chars.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
|
||||
* 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -35,12 +35,6 @@
|
||||
|
||||
static bool use_utf8 = FALSE;
|
||||
/* Whether we've enabled UTF-8 support. */
|
||||
static const wchar_t bad_wchar = 0xFFFD;
|
||||
/* If we get an invalid multibyte sequence, we treat it as
|
||||
* Unicode FFFD (Replacement Character), unless we're searching
|
||||
* for a match to it. */
|
||||
static const char *const bad_mbchar = "\xEF\xBF\xBD";
|
||||
static const int bad_mbchar_len = 3;
|
||||
|
||||
/* Enable UTF-8 support. */
|
||||
void utf8_init(void)
|
||||
@@ -99,6 +93,26 @@ 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)
|
||||
{
|
||||
assert(c != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswalpha(wc);
|
||||
} else
|
||||
#endif
|
||||
return isalpha((unsigned char)*c);
|
||||
}
|
||||
|
||||
/* This function is equivalent to isalnum() for multibyte characters. */
|
||||
bool is_alnum_mbchar(const char *c)
|
||||
{
|
||||
@@ -110,7 +124,7 @@ bool is_alnum_mbchar(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswalnum(wc);
|
||||
@@ -130,7 +144,7 @@ bool is_blank_mbchar(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswblank(wc);
|
||||
@@ -150,20 +164,9 @@ bool is_ascii_cntrl_char(int c)
|
||||
* handles high-bit control characters. */
|
||||
bool is_cntrl_char(int c)
|
||||
{
|
||||
return (-128 <= c && c < -96) || (0 <= c && c < 32) ||
|
||||
(127 <= c && c < 160);
|
||||
return ((c & 0x60) == 0 || c == 127);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* This function is equivalent to iscntrl() for wide characters, except
|
||||
* in that it also handles wide control characters with their high bits
|
||||
* set. */
|
||||
bool is_cntrl_wchar(wchar_t wc)
|
||||
{
|
||||
return (0 <= wc && wc < 32) || (127 <= wc && wc < 160);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function is equivalent to iscntrl() for multibyte characters,
|
||||
* except in that it also handles multibyte control characters with
|
||||
* their high bits set. */
|
||||
@@ -173,14 +176,8 @@ bool is_cntrl_mbchar(const char *c)
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
}
|
||||
|
||||
return is_cntrl_wchar(wc);
|
||||
return ((c[0] & 0xE0) == 0 || c[0] == 127 ||
|
||||
((signed char)c[0] == -62 && (signed char)c[1] < -96));
|
||||
} else
|
||||
#endif
|
||||
return is_cntrl_char((unsigned char)*c);
|
||||
@@ -197,7 +194,7 @@ bool is_punct_mbchar(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswpunct(wc);
|
||||
@@ -206,103 +203,100 @@ bool is_punct_mbchar(const char *c)
|
||||
return ispunct((unsigned char)*c);
|
||||
}
|
||||
|
||||
/* Return TRUE for a multibyte character found in a word (currently only
|
||||
* an alphanumeric or punctuation character, and only the latter if
|
||||
* allow_punct is TRUE) and FALSE otherwise. */
|
||||
/* Return TRUE when the given multibyte character c is a word-forming
|
||||
* character (that is: alphanumeric, or specified in wordchars, or
|
||||
* punctuation when allow_punct is TRUE), and FALSE otherwise. */
|
||||
bool is_word_mbchar(const char *c, bool allow_punct)
|
||||
{
|
||||
assert(c != NULL);
|
||||
|
||||
return is_alnum_mbchar(c) || (allow_punct ? is_punct_mbchar(c) :
|
||||
FALSE);
|
||||
if (*c == '\0')
|
||||
return FALSE;
|
||||
|
||||
if (is_alnum_mbchar(c))
|
||||
return TRUE;
|
||||
|
||||
if (word_chars != NULL && *word_chars != '\0') {
|
||||
bool wordforming;
|
||||
char *symbol = charalloc(MB_CUR_MAX + 1);
|
||||
int symlen = parse_mbchar(c, symbol, NULL);
|
||||
|
||||
symbol[symlen] = '\0';
|
||||
wordforming = (strstr(word_chars, symbol) != NULL);
|
||||
free(symbol);
|
||||
|
||||
return wordforming;
|
||||
}
|
||||
|
||||
return (allow_punct && is_punct_mbchar(c));
|
||||
}
|
||||
|
||||
/* c is a control character. It displays as ^@, ^?, or ^[ch], where ch
|
||||
* is (c + 64). We return that character. */
|
||||
char control_rep(char c)
|
||||
/* Return the visible representation of control character c. */
|
||||
char control_rep(const signed char c)
|
||||
{
|
||||
assert(is_cntrl_char(c));
|
||||
|
||||
/* Treat newlines embedded in a line as encoded nulls. */
|
||||
/* An embedded newline is an encoded null. */
|
||||
if (c == '\n')
|
||||
return '@';
|
||||
else if (c == NANO_CONTROL_8)
|
||||
else if (c == DEL_CODE)
|
||||
return '?';
|
||||
else if (c == -97)
|
||||
return '=';
|
||||
else if (c < 0)
|
||||
return c + 224;
|
||||
else
|
||||
return c + 64;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* c is a wide control character. It displays as ^@, ^?, or ^[ch],
|
||||
* where ch is (c + 64). We return that wide character. */
|
||||
wchar_t control_wrep(wchar_t wc)
|
||||
/* Return the visible representation of multibyte control character c. */
|
||||
char control_mbrep(const char *c)
|
||||
{
|
||||
assert(is_cntrl_wchar(wc));
|
||||
|
||||
/* Treat newlines embedded in a line as encoded nulls. */
|
||||
if (wc == '\n')
|
||||
return '@';
|
||||
else if (wc == NANO_CONTROL_8)
|
||||
return '?';
|
||||
else
|
||||
return wc + 64;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* c is a multibyte control character. It displays as ^@, ^?, or ^[ch],
|
||||
* where ch is (c + 64). We return that multibyte character. */
|
||||
char *control_mbrep(const char *c, char *crep, int *crep_len)
|
||||
{
|
||||
assert(c != NULL && crep != NULL && crep_len != NULL);
|
||||
assert(c != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
|
||||
IGNORE_CALL_RESULT(mbtowc(&wc, c, MB_CUR_MAX));
|
||||
*crep_len = wctomb(crep, control_wrep(wc));
|
||||
if ((unsigned char)c[0] < 128)
|
||||
return control_rep(c[0]);
|
||||
else
|
||||
return control_rep(c[1]);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
*crep_len = 1;
|
||||
*crep = control_rep(*c);
|
||||
}
|
||||
|
||||
return crep;
|
||||
return control_rep(*c);
|
||||
}
|
||||
|
||||
/* c is a multibyte non-control character. We return that multibyte
|
||||
* character. If crep is an invalid multibyte sequence, it will be
|
||||
* replaced with Unicode 0xFFFD (Replacement Character). */
|
||||
char *mbrep(const char *c, char *crep, int *crep_len)
|
||||
/* Assess how many bytes the given (multibyte) character occupies. Return -1
|
||||
* if the byte sequence is invalid, and return the number of bytes minus 8
|
||||
* when it encodes an invalid codepoint. Also, in the second parameter,
|
||||
* return the number of columns that the character occupies. */
|
||||
int length_of_char(const char *c, int *width)
|
||||
{
|
||||
assert(c != NULL && crep != NULL && crep_len != NULL);
|
||||
assert(c != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
int charlen = mbtowc(&wc, c, MB_CUR_MAX);
|
||||
|
||||
/* Reject invalid Unicode characters. */
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0 || !is_valid_unicode(wc)) {
|
||||
/* If the sequence is invalid... */
|
||||
if (charlen < 0) {
|
||||
mbtowc_reset();
|
||||
*crep_len = bad_mbchar_len;
|
||||
strncpy(crep, bad_mbchar, *crep_len);
|
||||
} else {
|
||||
*crep_len = wctomb(crep, wc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*crep_len < 0) {
|
||||
wctomb_reset();
|
||||
*crep_len = 0;
|
||||
}
|
||||
/* If the codepoint is invalid... */
|
||||
if (!is_valid_unicode(wc))
|
||||
return charlen - 8;
|
||||
else {
|
||||
*width = wcwidth(wc);
|
||||
/* If the codepoint is unassigned, assume a width of one. */
|
||||
if (*width < 0)
|
||||
*width = 1;
|
||||
return charlen;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
*crep_len = 1;
|
||||
*crep = *c;
|
||||
}
|
||||
|
||||
return crep;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function is equivalent to wcwidth() for multibyte characters. */
|
||||
@@ -317,15 +311,13 @@ int mbwidth(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 1;
|
||||
}
|
||||
|
||||
width = wcwidth(wc);
|
||||
|
||||
if (width == -1) {
|
||||
wc = bad_wchar;
|
||||
width = wcwidth(wc);
|
||||
}
|
||||
if (width == -1)
|
||||
return 1;
|
||||
|
||||
return width;
|
||||
} else
|
||||
@@ -518,32 +510,40 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
if (use_utf8) {
|
||||
wchar_t wc1, wc2;
|
||||
|
||||
if (s1 == s2)
|
||||
return 0;
|
||||
|
||||
assert(s1 != NULL && s2 != NULL);
|
||||
|
||||
for (; *s1 != '\0' && *s2 != '\0' && n > 0;
|
||||
s1 += move_mbright(s1, 0), s2 += move_mbright(s2, 0), n--) {
|
||||
while (*s1 != '\0' && *s2 != '\0' && n > 0) {
|
||||
bool bad1 = FALSE, bad2 = FALSE;
|
||||
|
||||
if (mbtowc(&wc1, s1, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc1 = (unsigned char)*s1;
|
||||
bad1 = TRUE;
|
||||
}
|
||||
|
||||
if (mbtowc(&wc2, s2, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc2 = (unsigned char)*s2;
|
||||
bad2 = TRUE;
|
||||
}
|
||||
|
||||
if (bad1 != bad2 || towlower(wc1) != towlower(wc2))
|
||||
break;
|
||||
if (bad1 || bad2) {
|
||||
if (*s1 != *s2)
|
||||
return (unsigned char)*s1 - (unsigned char)*s2;
|
||||
|
||||
if (bad1 != bad2)
|
||||
return (bad1 ? 1 : -1);
|
||||
} else {
|
||||
int difference = towlower(wc1) - towlower(wc2);
|
||||
|
||||
if (difference != 0)
|
||||
return difference;
|
||||
}
|
||||
|
||||
s1 += move_mbright(s1, 0);
|
||||
s2 += move_mbright(s2, 0);
|
||||
n--;
|
||||
}
|
||||
|
||||
return (n > 0) ? towlower(wc1) - towlower(wc2) : 0;
|
||||
return (n > 0) ? ((unsigned char)*s1 - (unsigned char)*s2) : 0;
|
||||
} else
|
||||
#endif
|
||||
return strncasecmp(s1, s2, n);
|
||||
@@ -553,20 +553,20 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
/* This function is equivalent to strcasestr(). */
|
||||
char *nstrcasestr(const char *haystack, const char *needle)
|
||||
{
|
||||
size_t haystack_len, needle_len;
|
||||
size_t needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)haystack;
|
||||
|
||||
haystack_len = strlen(haystack);
|
||||
needle_len = strlen(needle);
|
||||
|
||||
for (; *haystack != '\0' && haystack_len >= needle_len; haystack++,
|
||||
haystack_len--) {
|
||||
while (*haystack != '\0') {
|
||||
if (strncasecmp(haystack, needle, needle_len) == 0)
|
||||
return (char *)haystack;
|
||||
|
||||
haystack++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -578,21 +578,20 @@ char *mbstrcasestr(const char *haystack, const char *needle)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
size_t haystack_len, needle_len;
|
||||
size_t needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)haystack;
|
||||
|
||||
haystack_len = mbstrlen(haystack);
|
||||
needle_len = mbstrlen(needle);
|
||||
|
||||
for (; *haystack != '\0' && haystack_len >= needle_len;
|
||||
haystack += move_mbright(haystack, 0), haystack_len--) {
|
||||
if (mbstrncasecmp(haystack, needle, needle_len) == 0 &&
|
||||
mblen(haystack, MB_CUR_MAX) > 0)
|
||||
while (*haystack != '\0') {
|
||||
if (mbstrncasecmp(haystack, needle, needle_len) == 0)
|
||||
return (char *)haystack;
|
||||
|
||||
haystack += move_mbright(haystack, 0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -667,7 +666,6 @@ char *mbrevstrcasestr(const char *haystack, const char *needle, const
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool begin_line = FALSE;
|
||||
size_t rev_start_len, needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL && rev_start != NULL);
|
||||
@@ -682,22 +680,18 @@ char *mbrevstrcasestr(const char *haystack, const char *needle, const
|
||||
|
||||
rev_start_len = mbstrlen(rev_start);
|
||||
|
||||
while (!begin_line) {
|
||||
while (TRUE) {
|
||||
if (rev_start_len >= needle_len &&
|
||||
mbstrncasecmp(rev_start, needle, needle_len) == 0 &&
|
||||
mblen(rev_start, MB_CUR_MAX) > 0)
|
||||
mbstrncasecmp(rev_start, needle, needle_len) == 0)
|
||||
return (char *)rev_start;
|
||||
|
||||
/* If we've reached the head of the haystack, we found nothing. */
|
||||
if (rev_start == haystack)
|
||||
begin_line = TRUE;
|
||||
else {
|
||||
rev_start = haystack + move_mbleft(haystack, rev_start -
|
||||
haystack);
|
||||
rev_start_len++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
rev_start = haystack + move_mbleft(haystack, rev_start - haystack);
|
||||
rev_start_len++;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
return revstrcasestr(haystack, needle, rev_start);
|
||||
@@ -817,11 +811,14 @@ char *revstrpbrk(const char *s, const char *accept, const char
|
||||
{
|
||||
assert(s != NULL && accept != NULL && rev_start != NULL);
|
||||
|
||||
for (; rev_start >= s; rev_start--) {
|
||||
const char *q = (*rev_start == '\0') ? NULL : strchr(accept,
|
||||
*rev_start);
|
||||
if (*rev_start == '\0') {
|
||||
if (rev_start == s)
|
||||
return NULL;
|
||||
rev_start--;
|
||||
}
|
||||
|
||||
if (q != NULL)
|
||||
for (; rev_start >= s; rev_start--) {
|
||||
if (strchr(accept, *rev_start) != NULL)
|
||||
return (char *)rev_start;
|
||||
}
|
||||
|
||||
@@ -837,22 +834,22 @@ char *mbrevstrpbrk(const char *s, const char *accept, const char
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool begin_line = FALSE;
|
||||
|
||||
while (!begin_line) {
|
||||
const char *q = (*rev_start == '\0') ? NULL :
|
||||
mbstrchr(accept, rev_start);
|
||||
|
||||
if (q != NULL)
|
||||
return (char *)rev_start;
|
||||
|
||||
if (*rev_start == '\0') {
|
||||
if (rev_start == s)
|
||||
begin_line = TRUE;
|
||||
else
|
||||
rev_start = s + move_mbleft(s, rev_start - s);
|
||||
return NULL;
|
||||
rev_start = s + move_mbleft(s, rev_start - s);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
while (TRUE) {
|
||||
if (mbstrchr(accept, rev_start) != NULL)
|
||||
return (char *)rev_start;
|
||||
|
||||
/* If we've reached the head of the string, we found nothing. */
|
||||
if (rev_start == s)
|
||||
return NULL;
|
||||
|
||||
rev_start = s + move_mbleft(s, rev_start - s);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
return revstrpbrk(s, accept, rev_start);
|
||||
|
||||
156
src/color.c
156
src/color.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* color.c *
|
||||
* color.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
|
||||
* 2010, 2011, 2013, 2014, 2015 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
* for the colors in each syntax. */
|
||||
void set_colorpairs(void)
|
||||
{
|
||||
const syntaxtype *this_syntax = syntaxes;
|
||||
const syntaxtype *sint;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
size_t i;
|
||||
@@ -62,15 +62,14 @@ void set_colorpairs(void)
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
init_pair(i + 1, foreground, background);
|
||||
interface_color_pair[i].bright = bright;
|
||||
interface_color_pair[i].pairnum = COLOR_PAIR(i + 1);
|
||||
interface_color_pair[i] =
|
||||
COLOR_PAIR(i + 1) | (bright ? A_BOLD : A_NORMAL);
|
||||
}
|
||||
else {
|
||||
interface_color_pair[i].bright = FALSE;
|
||||
if (i != FUNCTION_TAG)
|
||||
interface_color_pair[i].pairnum = hilite_attribute;
|
||||
interface_color_pair[i] = hilite_attribute;
|
||||
else
|
||||
interface_color_pair[i].pairnum = A_NORMAL;
|
||||
interface_color_pair[i] = A_NORMAL;
|
||||
}
|
||||
|
||||
free(specified_color_combo[i]);
|
||||
@@ -79,25 +78,25 @@ void set_colorpairs(void)
|
||||
|
||||
/* For each syntax, go through its list of colors and assign each
|
||||
* its pair number, giving identical color pairs the same number. */
|
||||
for (; this_syntax != NULL; this_syntax = this_syntax->next) {
|
||||
colortype *this_color = this_syntax->color;
|
||||
int clr_pair = NUMBER_OF_ELEMENTS + 1;
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
colortype *ink;
|
||||
int new_number = NUMBER_OF_ELEMENTS + 1;
|
||||
|
||||
for (; this_color != NULL; this_color = this_color->next) {
|
||||
const colortype *beforenow = this_syntax->color;
|
||||
for (ink = sint->color; ink != NULL; ink = ink->next) {
|
||||
const colortype *beforenow = sint->color;
|
||||
|
||||
while (beforenow != this_color &&
|
||||
(beforenow->fg != this_color->fg ||
|
||||
beforenow->bg != this_color->bg ||
|
||||
beforenow->bright != this_color->bright))
|
||||
while (beforenow != ink && (beforenow->fg != ink->fg ||
|
||||
beforenow->bg != ink->bg ||
|
||||
beforenow->bright != ink->bright))
|
||||
beforenow = beforenow->next;
|
||||
|
||||
if (beforenow != this_color)
|
||||
this_color->pairnum = beforenow->pairnum;
|
||||
else {
|
||||
this_color->pairnum = clr_pair;
|
||||
clr_pair++;
|
||||
}
|
||||
if (beforenow != ink)
|
||||
ink->pairnum = beforenow->pairnum;
|
||||
else
|
||||
ink->pairnum = new_number++;
|
||||
|
||||
ink->attributes = COLOR_PAIR(ink->pairnum) |
|
||||
(ink->bright ? A_BOLD : A_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,7 +104,7 @@ void set_colorpairs(void)
|
||||
/* Initialize the color information. */
|
||||
void color_init(void)
|
||||
{
|
||||
colortype *tmpcolor = openfile->colorstrings;
|
||||
const colortype *ink;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
|
||||
@@ -121,9 +120,9 @@ void color_init(void)
|
||||
#endif
|
||||
|
||||
/* For each coloring expression, initialize the color pair. */
|
||||
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
||||
foreground = tmpcolor->fg;
|
||||
background = tmpcolor->bg;
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
foreground = ink->fg;
|
||||
background = ink->bg;
|
||||
|
||||
if (foreground == -1 && !using_defaults)
|
||||
foreground = COLOR_WHITE;
|
||||
@@ -131,7 +130,7 @@ void color_init(void)
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
|
||||
init_pair(tmpcolor->pairnum, foreground, background);
|
||||
init_pair(ink->pairnum, foreground, background);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "init_pair(): fg = %hd, bg = %hd\n", foreground, background);
|
||||
#endif
|
||||
@@ -340,42 +339,47 @@ void reset_multis_for_id(filestruct *fileptr, int index)
|
||||
* useful when we don't know how much screen state has changed. */
|
||||
void reset_multis(filestruct *fileptr, bool force)
|
||||
{
|
||||
int nobegin, noend;
|
||||
const colortype *ink;
|
||||
int nobegin = 0, noend = 0;
|
||||
regmatch_t startmatch, endmatch;
|
||||
const colortype *tmpcolor = openfile->colorstrings;
|
||||
|
||||
/* If there is no syntax or no multiline regex, there is nothing to do. */
|
||||
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
|
||||
return;
|
||||
|
||||
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If it's not a multi-line regex, amscray. */
|
||||
if (tmpcolor->end == NULL)
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
|
||||
alloc_multidata_if_needed(fileptr);
|
||||
|
||||
if (force == FALSE) {
|
||||
/* Check whether the multidata still matches the current situation. */
|
||||
nobegin = regexec(tmpcolor->start, fileptr->data, 1, &startmatch, 0);
|
||||
noend = regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
|
||||
if ((fileptr->multidata[tmpcolor->id] == CWHOLELINE ||
|
||||
fileptr->multidata[tmpcolor->id] == CNONE) &&
|
||||
nobegin = regexec(ink->start, fileptr->data, 1, &startmatch, 0);
|
||||
noend = regexec(ink->end, fileptr->data, 1, &endmatch, 0);
|
||||
if ((fileptr->multidata[ink->id] == CWHOLELINE ||
|
||||
fileptr->multidata[ink->id] == CNONE) &&
|
||||
nobegin && noend)
|
||||
continue;
|
||||
else if (fileptr->multidata[tmpcolor->id] == CSTARTENDHERE &&
|
||||
else if (fileptr->multidata[ink->id] == CSTARTENDHERE &&
|
||||
!nobegin && !noend && startmatch.rm_so < endmatch.rm_so)
|
||||
continue;
|
||||
else if (fileptr->multidata[tmpcolor->id] == CBEGINBEFORE &&
|
||||
else if (fileptr->multidata[ink->id] == CBEGINBEFORE &&
|
||||
nobegin && !noend)
|
||||
continue;
|
||||
else if (fileptr->multidata[tmpcolor->id] == CENDAFTER &&
|
||||
else if (fileptr->multidata[ink->id] == CENDAFTER &&
|
||||
!nobegin && noend)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we got here, things have changed. */
|
||||
reset_multis_for_id(fileptr, tmpcolor->id);
|
||||
reset_multis_for_id(fileptr, ink->id);
|
||||
|
||||
/* If start and end are the same, push the resets further. */
|
||||
if (force == FALSE && !nobegin && !noend &&
|
||||
startmatch.rm_so == endmatch.rm_so)
|
||||
reset_multis_for_id(fileptr, ink->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,23 +396,11 @@ void alloc_multidata_if_needed(filestruct *fileptr)
|
||||
}
|
||||
}
|
||||
|
||||
/* Poll the keyboard every second to see if the user starts typing. */
|
||||
bool key_was_pressed(void)
|
||||
{
|
||||
static time_t last_time = 0;
|
||||
|
||||
if (time(NULL) != last_time) {
|
||||
last_time = time(NULL);
|
||||
return (wgetch(edit) != ERR);
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Precalculate the multi-line start and end regex info so we can
|
||||
* speed up rendering (with any hope at all...). */
|
||||
void precalc_multicolorinfo(void)
|
||||
{
|
||||
const colortype *tmpcolor = openfile->colorstrings;
|
||||
const colortype *ink;
|
||||
regmatch_t startmatch, endmatch;
|
||||
filestruct *fileptr, *endptr;
|
||||
|
||||
@@ -418,32 +410,24 @@ void precalc_multicolorinfo(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Entering precalculation of multiline color info\n");
|
||||
#endif
|
||||
/* Let us get keypresses to see if the user is trying to start
|
||||
* editing. Later we may want to throw up a statusbar message
|
||||
* before starting this if it takes too long to do this routine.
|
||||
* For now silently abort if they hit a key. */
|
||||
nodelay(edit, TRUE);
|
||||
|
||||
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If this is not a multi-line regex, skip it. */
|
||||
if (tmpcolor->end == NULL)
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Starting work on color id %d\n", tmpcolor->id);
|
||||
fprintf(stderr, "Starting work on color id %d\n", ink->id);
|
||||
#endif
|
||||
|
||||
for (fileptr = openfile->fileage; fileptr != NULL; fileptr = fileptr->next) {
|
||||
int startx = 0, nostart = 0;
|
||||
|
||||
if (key_was_pressed())
|
||||
goto precalc_cleanup;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "working on lineno %ld... ", (long)fileptr->lineno);
|
||||
#endif
|
||||
alloc_multidata_if_needed(fileptr);
|
||||
|
||||
while ((nostart = regexec(tmpcolor->start, &fileptr->data[startx],
|
||||
1, &startmatch, (startx == 0) ? 0 : REG_NOTBOL)) == 0) {
|
||||
while ((nostart = regexec(ink->start, &fileptr->data[startx], 1,
|
||||
&startmatch, (startx == 0) ? 0 : REG_NOTBOL)) == 0) {
|
||||
/* Look for an end, and start marking how many lines are
|
||||
* encompassed, which should speed up rendering later. */
|
||||
startx += startmatch.rm_eo;
|
||||
@@ -451,14 +435,14 @@ void precalc_multicolorinfo(void)
|
||||
fprintf(stderr, "start found at pos %lu... ", (unsigned long)startx);
|
||||
#endif
|
||||
/* Look first on this line for an end. */
|
||||
if (regexec(tmpcolor->end, &fileptr->data[startx], 1,
|
||||
if (regexec(ink->end, &fileptr->data[startx], 1,
|
||||
&endmatch, (startx == 0) ? 0 : REG_NOTBOL) == 0) {
|
||||
startx += endmatch.rm_eo;
|
||||
/* Step ahead when both start and end are mere anchors. */
|
||||
if (startmatch.rm_so == startmatch.rm_eo &&
|
||||
endmatch.rm_so == endmatch.rm_eo)
|
||||
startx += 1;
|
||||
fileptr->multidata[tmpcolor->id] = CSTARTENDHERE;
|
||||
fileptr->multidata[ink->id] = CSTARTENDHERE;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "end found on this line\n");
|
||||
#endif
|
||||
@@ -470,11 +454,7 @@ void precalc_multicolorinfo(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\nadvancing to line %ld to find end... ", (long)endptr->lineno);
|
||||
#endif
|
||||
/* Check for interrupting keyboard input again. */
|
||||
if (key_was_pressed())
|
||||
goto precalc_cleanup;
|
||||
|
||||
if (regexec(tmpcolor->end, endptr->data, 1, &endmatch, 0) == 0)
|
||||
if (regexec(ink->end, endptr->data, 1, &endmatch, 0) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -489,20 +469,20 @@ void precalc_multicolorinfo(void)
|
||||
#endif
|
||||
/* We found it, we found it, la la la la la. Mark all
|
||||
* the lines in between and the end properly. */
|
||||
fileptr->multidata[tmpcolor->id] = CENDAFTER;
|
||||
fileptr->multidata[ink->id] = CENDAFTER;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "marking line %ld as CENDAFTER\n", (long)fileptr->lineno);
|
||||
#endif
|
||||
for (fileptr = fileptr->next; fileptr != endptr; fileptr = fileptr->next) {
|
||||
alloc_multidata_if_needed(fileptr);
|
||||
fileptr->multidata[tmpcolor->id] = CWHOLELINE;
|
||||
fileptr->multidata[ink->id] = CWHOLELINE;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "marking intermediary line %ld as CWHOLELINE\n", (long)fileptr->lineno);
|
||||
#endif
|
||||
}
|
||||
|
||||
alloc_multidata_if_needed(endptr);
|
||||
fileptr->multidata[tmpcolor->id] = CBEGINBEFORE;
|
||||
fileptr->multidata[ink->id] = CBEGINBEFORE;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "marking line %ld as CBEGINBEFORE\n", (long)fileptr->lineno);
|
||||
#endif
|
||||
@@ -517,13 +497,11 @@ void precalc_multicolorinfo(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "no match\n");
|
||||
#endif
|
||||
fileptr->multidata[tmpcolor->id] = CNONE;
|
||||
fileptr->multidata[ink->id] = CNONE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
precalc_cleanup:
|
||||
nodelay(edit, FALSE);
|
||||
}
|
||||
|
||||
#endif /* !DISABLE_COLOR */
|
||||
|
||||
25
src/cut.c
25
src/cut.c
@@ -1,22 +1,23 @@
|
||||
/**************************************************************************
|
||||
* cut.c *
|
||||
* cut.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014 Mark Majeres *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
166
src/files.c
166
src/files.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* files.c *
|
||||
* files.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -51,6 +51,8 @@ bool has_valid_path(const char *filename)
|
||||
statusline(ALERT, _("Path '%s' is not a directory"), parentdir);
|
||||
else if (access(parentdir, X_OK) == -1)
|
||||
statusline(ALERT, _("Path '%s' is not accessible"), parentdir);
|
||||
else if (ISSET(LOCKING) && access(parentdir, W_OK) == -1)
|
||||
statusline(MILD, _("Directory '%s' is not writable"), parentdir);
|
||||
else
|
||||
validity = TRUE;
|
||||
|
||||
@@ -98,6 +100,7 @@ void make_new_buffer(void)
|
||||
openfile->mark_set = FALSE;
|
||||
openfile->mark_begin = NULL;
|
||||
openfile->mark_begin_x = 0;
|
||||
openfile->kind_of_mark = SOFTMARK;
|
||||
|
||||
openfile->fmt = NIX_FILE;
|
||||
|
||||
@@ -232,8 +235,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi
|
||||
* byte 0 - 0x62
|
||||
* byte 1 - 0x30
|
||||
* bytes 2-12 - program name which created the lock
|
||||
* bytes 24,25 - little endian store of creator program's PID
|
||||
* (b24 = 256^0 column, b25 = 256^1 column)
|
||||
* bytes 24-27 - PID (little endian) of creator process
|
||||
* bytes 28-44 - username of who created the lock
|
||||
* bytes 68-100 - hostname of where the lock was created
|
||||
* bytes 108-876 - filename the lock is for
|
||||
@@ -248,7 +250,9 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi
|
||||
lockdata[0] = 0x62;
|
||||
lockdata[1] = 0x30;
|
||||
lockdata[24] = mypid % 256;
|
||||
lockdata[25] = mypid / 256;
|
||||
lockdata[25] = (mypid / 256) % 256;
|
||||
lockdata[26] = (mypid / (256 * 256)) % 256;
|
||||
lockdata[27] = mypid / (256 * 256 * 256);
|
||||
snprintf(&lockdata[2], 11, "nano %s", VERSION);
|
||||
strncpy(&lockdata[28], mypwuid->pw_name, 16);
|
||||
strncpy(&lockdata[68], myhostname, 31);
|
||||
@@ -318,7 +322,7 @@ int do_lockfile(const char *filename)
|
||||
if (stat(lockfilename, &fileinfo) != -1) {
|
||||
ssize_t readtot = 0;
|
||||
ssize_t readamt = 0;
|
||||
char *lockbuf, *question, *postedname, *promptstr;
|
||||
char *lockbuf, *question, *pidstring, *postedname, *promptstr;
|
||||
int room, response;
|
||||
|
||||
if ((lockfd = open(lockfilename, O_RDONLY)) < 0) {
|
||||
@@ -333,6 +337,8 @@ int do_lockfile(const char *filename)
|
||||
readtot += readamt;
|
||||
} while (readamt > 0 && readtot < LOCKBUFSIZE);
|
||||
|
||||
close(lockfd);
|
||||
|
||||
if (readtot < 48) {
|
||||
statusline(MILD, _("Error reading lock file %s: "
|
||||
"Not enough data read"), lockfilename);
|
||||
@@ -341,18 +347,23 @@ int do_lockfile(const char *filename)
|
||||
}
|
||||
|
||||
strncpy(lockprog, &lockbuf[2], 10);
|
||||
lockpid = (unsigned char)lockbuf[25] * 256 + (unsigned char)lockbuf[24];
|
||||
lockpid = (((unsigned char)lockbuf[27] * 256 + (unsigned char)lockbuf[26]) * 256 +
|
||||
(unsigned char)lockbuf[25]) * 256 + (unsigned char)lockbuf[24];
|
||||
strncpy(lockuser, &lockbuf[28], 16);
|
||||
free(lockbuf);
|
||||
|
||||
pidstring = charalloc(11);
|
||||
sprintf (pidstring, "%u", (unsigned int)lockpid);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "lockpid = %d\n", lockpid);
|
||||
fprintf(stderr, "program name which created this lock file should be %s\n", lockprog);
|
||||
fprintf(stderr, "user which created this lock file should be %s\n", lockuser);
|
||||
#endif
|
||||
/* TRANSLATORS: The second %s is the name of the user, the third that of the editor. */
|
||||
question = _("File %s is being edited (by %s with %s, PID %d); continue?");
|
||||
room = COLS - strlenpt(question) - strlenpt(lockuser) - strlenpt(lockprog) + 3;
|
||||
question = _("File %s is being edited (by %s with %s, PID %s); continue?");
|
||||
room = COLS - strlenpt(question) + 7 - strlenpt(lockuser) -
|
||||
strlenpt(lockprog) - strlenpt(pidstring);
|
||||
if (room < 4)
|
||||
postedname = mallocstrcpy(NULL, "_");
|
||||
else if (room < strlenpt(filename)) {
|
||||
@@ -365,11 +376,12 @@ int do_lockfile(const char *filename)
|
||||
} else
|
||||
postedname = mallocstrcpy(NULL, filename);
|
||||
|
||||
/* Allow extra space for username (14), program name (8), PID (3),
|
||||
/* Allow extra space for username (14), program name (8), PID (8),
|
||||
* and terminating \0 (1), minus the %s (2) for the file name. */
|
||||
promptstr = charalloc(strlen(question) + 24 + strlen(postedname));
|
||||
sprintf(promptstr, question, postedname, lockuser, lockprog, lockpid);
|
||||
promptstr = charalloc(strlen(question) + 29 + strlen(postedname));
|
||||
sprintf(promptstr, question, postedname, lockuser, lockprog, pidstring);
|
||||
free(postedname);
|
||||
free(pidstring);
|
||||
|
||||
response = do_yesno_prompt(FALSE, promptstr);
|
||||
free(promptstr);
|
||||
@@ -590,7 +602,6 @@ void switch_to_prevnext_buffer(bool to_next)
|
||||
#ifdef DEBUG
|
||||
dump_filestruct(openfile->current);
|
||||
#endif
|
||||
display_main_list();
|
||||
}
|
||||
|
||||
/* Switch to the previous entry in the openfile filebuffer. */
|
||||
@@ -828,7 +839,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw
|
||||
if (len > 0) {
|
||||
#ifndef NANO_TINY
|
||||
/* If file conversion isn't disabled and the last character in
|
||||
* this file is '\r', set format to Mac if we currently think
|
||||
* This file is '\r', set format to Mac if we currently think
|
||||
* the file is a *nix file, or to both DOS and Mac if we
|
||||
* currently think the file is a DOS file. */
|
||||
if (buf[len - 1] == '\r' && !ISSET(NO_CONVERT) && format < 2)
|
||||
@@ -1077,21 +1088,21 @@ void do_insertfile(
|
||||
while (TRUE) {
|
||||
#ifndef NANO_TINY
|
||||
if (execute) {
|
||||
msg =
|
||||
#ifndef DISABLE_MULTIBUFFER
|
||||
ISSET(MULTIBUFFER) ?
|
||||
_("Command to execute in new buffer [from %s] ") :
|
||||
if (ISSET(MULTIBUFFER))
|
||||
msg = _("Command to execute in new buffer [from %s] ");
|
||||
else
|
||||
#endif
|
||||
_("Command to execute [from %s] ");
|
||||
msg = _("Command to execute [from %s] ");
|
||||
} else
|
||||
#endif /* NANO_TINY */
|
||||
{
|
||||
msg =
|
||||
#ifndef DISABLE_MULTIBUFFER
|
||||
ISSET(MULTIBUFFER) ?
|
||||
_("File to insert into new buffer [from %s] ") :
|
||||
if (ISSET(MULTIBUFFER))
|
||||
msg = _("File to insert into new buffer [from %s] ");
|
||||
else
|
||||
#endif
|
||||
_("File to insert [from %s] ");
|
||||
msg = _("File to insert [from %s] ");
|
||||
}
|
||||
|
||||
present_path = mallocstrcpy(present_path, "./");
|
||||
@@ -1109,8 +1120,8 @@ void do_insertfile(
|
||||
#endif
|
||||
edit_refresh, msg,
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
operating_dir != NULL && strcmp(operating_dir,
|
||||
".") != 0 ? operating_dir :
|
||||
operating_dir != NULL && strcmp(operating_dir, ".") != 0 ?
|
||||
operating_dir :
|
||||
#endif
|
||||
"./");
|
||||
|
||||
@@ -1178,8 +1189,7 @@ void do_insertfile(
|
||||
size_t top_x, bot_x;
|
||||
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x,
|
||||
&right_side_up);
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
|
||||
single_line = (top == bot);
|
||||
}
|
||||
@@ -1228,7 +1238,7 @@ void do_insertfile(
|
||||
{
|
||||
/* Make sure the path to the file specified in answer is
|
||||
* tilde-expanded. */
|
||||
answer = mallocstrassn(answer, real_dir_from_tilde(answer));
|
||||
answer = free_and_assign(answer, real_dir_from_tilde(answer));
|
||||
|
||||
/* Save the file specified in answer in the current buffer. */
|
||||
open_buffer(answer, TRUE);
|
||||
@@ -1343,8 +1353,6 @@ void do_insertfile_void(void)
|
||||
FALSE
|
||||
#endif
|
||||
);
|
||||
|
||||
display_main_list();
|
||||
}
|
||||
|
||||
/* When passed "[relative path]" or "[relative path][filename]" in
|
||||
@@ -1699,15 +1707,15 @@ int copy_file(FILE *inn, FILE *out)
|
||||
*
|
||||
* tmp means we are writing a temporary file in a secure fashion. We
|
||||
* use it when spell checking or dumping the file on an error. If
|
||||
* append is APPEND, it means we are appending instead of overwriting.
|
||||
* If append is PREPEND, it means we are prepending instead of
|
||||
* method is APPEND, it means we are appending instead of overwriting.
|
||||
* If method is PREPEND, it means we are prepending instead of
|
||||
* overwriting. If nonamechange is TRUE, we don't change the current
|
||||
* filename. nonamechange is ignored if tmp is FALSE, we're appending,
|
||||
* or we're prepending.
|
||||
* filename. nonamechange is irrelevant when appending or prepending,
|
||||
* or when writing a temporary file.
|
||||
*
|
||||
* Return TRUE on success or FALSE on error. */
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
append, bool nonamechange)
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
kind_of_writing_type method, bool nonamechange)
|
||||
{
|
||||
bool retval = FALSE;
|
||||
/* Instead of returning in this function, you should always
|
||||
@@ -1773,7 +1781,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
* only if the file has not been modified by someone else since nano
|
||||
* opened it. */
|
||||
if (ISSET(BACKUP_FILE) && !tmp && realexists && openfile->current_stat &&
|
||||
(append != OVERWRITE || openfile->mark_set ||
|
||||
(method != OVERWRITE || openfile->mark_set ||
|
||||
openfile->current_stat->st_mtime == st.st_mtime)) {
|
||||
int backup_fd;
|
||||
FILE *backup_file;
|
||||
@@ -1952,7 +1960,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
}
|
||||
|
||||
/* If we're prepending, copy the file to a temp file. */
|
||||
if (append == PREPEND) {
|
||||
if (method == PREPEND) {
|
||||
int fd_source;
|
||||
FILE *f_source = NULL;
|
||||
|
||||
@@ -1969,7 +1977,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
tempname = safe_tempfile(&f);
|
||||
|
||||
if (tempname == NULL) {
|
||||
statusline(HUSH, _("Error writing temp file: %s"),
|
||||
statusline(ALERT, _("Error writing temp file: %s"),
|
||||
strerror(errno));
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
@@ -1991,7 +1999,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
}
|
||||
|
||||
if (f_source == NULL || copy_file(f_source, f) != 0) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), tempname,
|
||||
statusline(ALERT, _("Error writing temp file: %s"),
|
||||
strerror(errno));
|
||||
unlink(tempname);
|
||||
goto cleanup_and_exit;
|
||||
@@ -2001,7 +2009,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
if (f_open == NULL) {
|
||||
/* Now open the file in place. Use O_EXCL if tmp is TRUE. This
|
||||
* is copied from joe, because wiggy says so *shrug*. */
|
||||
fd = open(realname, O_WRONLY | O_CREAT | ((append == APPEND) ?
|
||||
fd = open(realname, O_WRONLY | O_CREAT | ((method == APPEND) ?
|
||||
O_APPEND : (tmp ? O_EXCL : O_TRUNC)), S_IRUSR |
|
||||
S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
|
||||
@@ -2010,17 +2018,17 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
|
||||
/* If we couldn't open the file, give up. */
|
||||
if (fd == -1) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
if (tempname != NULL)
|
||||
unlink(tempname);
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
|
||||
f = fdopen(fd, (append == APPEND) ? "ab" : "wb");
|
||||
f = fdopen(fd, (method == APPEND) ? "ab" : "wb");
|
||||
|
||||
if (f == NULL) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
goto cleanup_and_exit;
|
||||
@@ -2044,7 +2052,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
unsunder(fileptr->data, data_len);
|
||||
|
||||
if (size < data_len) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
fclose(f);
|
||||
goto cleanup_and_exit;
|
||||
@@ -2061,7 +2069,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->fmt == DOS_FILE || openfile->fmt == MAC_FILE) {
|
||||
if (putc('\r', f) == EOF) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
fclose(f);
|
||||
goto cleanup_and_exit;
|
||||
@@ -2071,7 +2079,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
if (openfile->fmt != MAC_FILE)
|
||||
#endif
|
||||
if (putc('\n', f) == EOF) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
fclose(f);
|
||||
goto cleanup_and_exit;
|
||||
@@ -2083,7 +2091,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
}
|
||||
|
||||
/* If we're prepending, open the temp file, and append it to f. */
|
||||
if (append == PREPEND) {
|
||||
if (method == PREPEND) {
|
||||
int fd_source;
|
||||
FILE *f_source = NULL;
|
||||
|
||||
@@ -2103,23 +2111,23 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
}
|
||||
|
||||
if (copy_file(f_source, f) == -1) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
|
||||
unlink(tempname);
|
||||
} else if (fclose(f) != 0) {
|
||||
statusline(HUSH, _("Error writing %s: %s"), realname,
|
||||
statusline(ALERT, _("Error writing %s: %s"), realname,
|
||||
strerror(errno));
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
|
||||
if (!tmp && append == OVERWRITE) {
|
||||
if (method == OVERWRITE && !tmp) {
|
||||
/* If we must set the filename, and it changed, adjust things. */
|
||||
if (!nonamechange && strcmp(openfile->filename, realname) != 0) {
|
||||
#ifndef DISABLE_COLOR
|
||||
char *syntaxname = openfile->syntax ? openfile->syntax->name : "";
|
||||
char *oldname = openfile->syntax ? openfile->syntax->name : "";
|
||||
filestruct *line = openfile->fileage;
|
||||
#endif
|
||||
openfile->filename = mallocstrcpy(openfile->filename, realname);
|
||||
@@ -2129,19 +2137,17 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
color_update();
|
||||
color_init();
|
||||
|
||||
char *newname = openfile->syntax ? openfile->syntax->name : "";
|
||||
|
||||
/* If the syntax changed, discard and recompute the multidata. */
|
||||
if (openfile->syntax &&
|
||||
strcmp(syntaxname, openfile->syntax->name) != 0) {
|
||||
if (strcmp(oldname, newname) != 0) {
|
||||
for (; line != NULL; line = line->next) {
|
||||
free(line->multidata);
|
||||
line->multidata = NULL;
|
||||
}
|
||||
precalc_multicolorinfo();
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
/* If color syntaxes are available and turned on, refresh. */
|
||||
if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX))
|
||||
edit_refresh();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2170,7 +2176,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
/* Write a marked selection from a file out to disk. Return TRUE on
|
||||
* success or FALSE on error. */
|
||||
bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
append_type append)
|
||||
kind_of_writing_type method)
|
||||
{
|
||||
bool retval;
|
||||
bool old_modified = openfile->modified;
|
||||
@@ -2194,7 +2200,7 @@ bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
added_magicline = TRUE;
|
||||
}
|
||||
|
||||
retval = write_file(name, f_open, tmp, append, TRUE);
|
||||
retval = write_file(name, f_open, tmp, method, TRUE);
|
||||
|
||||
/* If we added a magicline, remove it now. */
|
||||
if (added_magicline)
|
||||
@@ -2220,7 +2226,7 @@ int do_writeout(bool exiting)
|
||||
{
|
||||
int i;
|
||||
bool result = FALSE;
|
||||
append_type append = OVERWRITE;
|
||||
kind_of_writing_type method = OVERWRITE;
|
||||
char *given;
|
||||
/* The filename we offer, or what the user typed so far. */
|
||||
bool maychange = (openfile->filename[0] == '\0');
|
||||
@@ -2256,13 +2262,13 @@ int do_writeout(bool exiting)
|
||||
* it allows reading from or writing to files not specified on
|
||||
* the command line. */
|
||||
if (openfile->mark_set && !exiting && !ISSET(RESTRICTED))
|
||||
msg = (append == PREPEND) ? _("Prepend Selection to File") :
|
||||
(append == APPEND) ? _("Append Selection to File") :
|
||||
msg = (method == PREPEND) ? _("Prepend Selection to File") :
|
||||
(method == APPEND) ? _("Append Selection to File") :
|
||||
_("Write Selection to File");
|
||||
else
|
||||
#endif /* !NANO_TINY */
|
||||
msg = (append == PREPEND) ? _("File Name to Prepend to") :
|
||||
(append == APPEND) ? _("File Name to Append to") :
|
||||
msg = (method == PREPEND) ? _("File Name to Prepend to") :
|
||||
(method == APPEND) ? _("File Name to Append to") :
|
||||
_("File Name to Write");
|
||||
|
||||
present_path = mallocstrcpy(present_path, "./");
|
||||
@@ -2338,10 +2344,10 @@ int do_writeout(bool exiting)
|
||||
} else
|
||||
#endif /* !NANO_TINY */
|
||||
if (func == prepend_void) {
|
||||
append = (append == PREPEND) ? OVERWRITE : PREPEND;
|
||||
method = (method == PREPEND) ? OVERWRITE : PREPEND;
|
||||
continue;
|
||||
} else if (func == append_void) {
|
||||
append = (append == APPEND) ? OVERWRITE : APPEND;
|
||||
method = (method == APPEND) ? OVERWRITE : APPEND;
|
||||
continue;
|
||||
} else if (func == do_help_void) {
|
||||
continue;
|
||||
@@ -2366,7 +2372,7 @@ int do_writeout(bool exiting)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (append == OVERWRITE) {
|
||||
if (method == OVERWRITE) {
|
||||
size_t answer_len = strlen(answer);
|
||||
bool name_exists, do_warning;
|
||||
char *full_answer, *full_filename;
|
||||
@@ -2455,10 +2461,10 @@ int do_writeout(bool exiting)
|
||||
* writing to files not specified on the command line. */
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set && !exiting && !ISSET(RESTRICTED))
|
||||
result = write_marked_file(answer, NULL, FALSE, append);
|
||||
result = write_marked_file(answer, NULL, FALSE, method);
|
||||
else
|
||||
#endif
|
||||
result = write_file(answer, NULL, FALSE, append, FALSE);
|
||||
result = write_file(answer, NULL, FALSE, method, FALSE);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2475,8 +2481,6 @@ void do_writeout_void(void)
|
||||
/* If the user chose to discard the buffer, close it. */
|
||||
if (do_writeout(FALSE) == 2)
|
||||
close_and_go();
|
||||
|
||||
display_main_list();
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
|
||||
189
src/global.c
189
src/global.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* global.c *
|
||||
* global.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -33,10 +33,15 @@ volatile sig_atomic_t sigwinch_counter = 0;
|
||||
/* Is incremented by the handler whenever a SIGWINCH occurs. */
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && !defined(NANO_TINY)
|
||||
bool console;
|
||||
/* Whether we're running on a Linux VC (TRUE) or under X (FALSE). */
|
||||
#endif
|
||||
|
||||
bool meta_key;
|
||||
/* Whether the current keystroke is a Meta key. */
|
||||
bool func_key;
|
||||
/* Whether the current keystroke is an extended keypad value. */
|
||||
bool shift_held;
|
||||
/* Whether Shift was being held together with a movement key. */
|
||||
bool focusing = TRUE;
|
||||
/* Whether an update of the edit window should center the cursor. */
|
||||
|
||||
@@ -44,8 +49,9 @@ message_type lastmessage = HUSH;
|
||||
/* Messages of type HUSH should not overwrite type MILD nor ALERT. */
|
||||
|
||||
#ifndef NANO_TINY
|
||||
int controlleft = CONTROL_LEFT;
|
||||
int controlright = CONTROL_RIGHT;
|
||||
int controlleft, controlright, controlup, controldown;
|
||||
int shiftcontrolleft, shiftcontrolright, shiftcontrolup, shiftcontroldown;
|
||||
int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
@@ -124,6 +130,9 @@ size_t quotelen;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
char *word_chars = NULL;
|
||||
/* Nonalphanumeric characters that also form words. */
|
||||
|
||||
bool nodelay_mode = FALSE;
|
||||
/* Are we checking for a cancel wile doing something? */
|
||||
|
||||
@@ -167,8 +176,8 @@ bool refresh_needed = FALSE;
|
||||
/* Did a command mangle enough of the buffer that we should
|
||||
* repaint the screen? */
|
||||
|
||||
int currmenu;
|
||||
/* The currently loaded menu. */
|
||||
int currmenu = MMOST;
|
||||
/* The currently active menu, initialized to a dummy value. */
|
||||
sc *sclist = NULL;
|
||||
/* Pointer to the start of the shortcuts list. */
|
||||
subnfunc *allfuncs = NULL;
|
||||
@@ -212,7 +221,7 @@ int hilite_attribute = A_REVERSE;
|
||||
char* specified_color_combo[] = {};
|
||||
/* The color combinations as specified in the rcfile. */
|
||||
#endif
|
||||
color_pair interface_color_pair[] = {};
|
||||
int interface_color_pair[] = {};
|
||||
/* The processed color pairs for the interface elements. */
|
||||
|
||||
char *homedir = NULL;
|
||||
@@ -225,9 +234,9 @@ size_t length_of_list(int menu)
|
||||
size_t i = 0;
|
||||
|
||||
for (f = allfuncs; f != NULL; f = f->next)
|
||||
if ((f->menus & menu) != 0) {
|
||||
if ((f->menus & menu) && first_sc_for(menu, f->scfunc) != NULL)
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -334,12 +343,10 @@ void add_to_sclist(int menus, const char *scstring, void (*func)(void), int togg
|
||||
s->toggle = toggle;
|
||||
if (toggle)
|
||||
s->ordinal = ++counter;
|
||||
s->keystr = (char *) scstring;
|
||||
s->type = strtokeytype(scstring);
|
||||
assign_keyinfo(s);
|
||||
assign_keyinfo(s, scstring);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Setting sequence to %d for shortcut \"%s\" in menus %x\n", s->seq, scstring, s->menus);
|
||||
fprintf(stderr, "Setting keycode to %d for shortcut \"%s\" in menus %x\n", s->keycode, scstring, s->menus);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -377,8 +384,8 @@ int sc_seq_or(void (*func)(void), int defaultval)
|
||||
const sc *s = first_sc_for(currmenu, func);
|
||||
|
||||
if (s) {
|
||||
meta_key = (s->type == META);
|
||||
return s->seq;
|
||||
meta_key = s->meta;
|
||||
return s->keycode;
|
||||
}
|
||||
/* else */
|
||||
return defaultval;
|
||||
@@ -395,71 +402,54 @@ functionptrtype func_from_key(int *kbinput)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the type of command key based on the given string. */
|
||||
key_type strtokeytype(const char *str)
|
||||
/* Set the string and its corresponding keycode for the given shortcut s. */
|
||||
void assign_keyinfo(sc *s, const char *keystring)
|
||||
{
|
||||
if (str[0] == '^')
|
||||
return CONTROL;
|
||||
else if (str[0] == 'M')
|
||||
return META;
|
||||
else if (str[0] == 'F')
|
||||
return FKEY;
|
||||
else
|
||||
return RAWINPUT;
|
||||
}
|
||||
s->keystr = keystring;
|
||||
s->meta = (keystring[0] == 'M');
|
||||
|
||||
/* Assign the info to the shortcut struct.
|
||||
* Assumes keystr is already assigned, naturally. */
|
||||
void assign_keyinfo(sc *s)
|
||||
{
|
||||
if (s->type == CONTROL) {
|
||||
assert(strlen(s->keystr) > 1);
|
||||
s->seq = s->keystr[1] - 64;
|
||||
} else if (s->type == META) {
|
||||
assert(strlen(s->keystr) > 2);
|
||||
s->seq = tolower((int) s->keystr[2]);
|
||||
} else if (s->type == FKEY) {
|
||||
assert(strlen(s->keystr) > 1);
|
||||
s->seq = KEY_F0 + atoi(&s->keystr[1]);
|
||||
} else /* RAWINPUT */
|
||||
s->seq = (int) s->keystr[0];
|
||||
assert(strlen(keystring) > 1 && (!s->meta || strlen(keystring) > 2));
|
||||
|
||||
/* Override some keys which don't bind as easily as we'd like. */
|
||||
if (s->type == CONTROL && (!strcasecmp(&s->keystr[1], "space")))
|
||||
s->seq = 0;
|
||||
else if (s->type == META && (!strcasecmp(&s->keystr[2], "space")))
|
||||
s->seq = (int) ' ';
|
||||
else if (s->type == RAWINPUT) {
|
||||
if (!strcasecmp(s->keystr, "Up"))
|
||||
s->seq = KEY_UP;
|
||||
else if (!strcasecmp(s->keystr, "Down"))
|
||||
s->seq = KEY_DOWN;
|
||||
else if (!strcasecmp(s->keystr, "Left"))
|
||||
s->seq = KEY_LEFT;
|
||||
else if (!strcasecmp(s->keystr, "Right"))
|
||||
s->seq = KEY_RIGHT;
|
||||
else if (!strcasecmp(s->keystr, "Ins"))
|
||||
s->seq = KEY_IC;
|
||||
else if (!strcasecmp(s->keystr, "Del"))
|
||||
s->seq = KEY_DC;
|
||||
else if (!strcasecmp(s->keystr, "Bsp"))
|
||||
s->seq = KEY_BACKSPACE;
|
||||
/* The Tab and Enter keys don't actually produce special codes
|
||||
* but the exact integer values of ^I and ^M. Rebinding the
|
||||
* latter therefore also rebinds Tab and Enter. */
|
||||
else if (!strcasecmp(s->keystr, "Tab"))
|
||||
s->seq = NANO_CONTROL_I;
|
||||
else if (!strcasecmp(s->keystr, "Enter"))
|
||||
s->seq = KEY_ENTER;
|
||||
else if (!strcasecmp(s->keystr, "PgUp"))
|
||||
s->seq = KEY_PPAGE;
|
||||
else if (!strcasecmp(s->keystr, "PgDn"))
|
||||
s->seq = KEY_NPAGE;
|
||||
else if (!strcasecmp(s->keystr, "Home"))
|
||||
s->seq = KEY_HOME;
|
||||
else if (!strcasecmp(s->keystr, "End"))
|
||||
s->seq = KEY_END;
|
||||
}
|
||||
if (keystring[0] == '^') {
|
||||
s->keycode = keystring[1] - 64;
|
||||
if (strcasecmp(keystring, "^Space") == 0)
|
||||
s->keycode = 0;
|
||||
} else if (s->meta) {
|
||||
s->keycode = tolower((int)keystring[2]);
|
||||
if (strcasecmp(keystring, "M-Space") == 0)
|
||||
s->keycode = (int)' ';
|
||||
} else if (keystring[0] == 'F')
|
||||
s->keycode = KEY_F0 + atoi(&keystring[1]);
|
||||
/* Catch the strings that don't bind as easily as we'd like. */
|
||||
else if (!strcasecmp(keystring, "Up"))
|
||||
s->keycode = KEY_UP;
|
||||
else if (!strcasecmp(keystring, "Down"))
|
||||
s->keycode = KEY_DOWN;
|
||||
else if (!strcasecmp(keystring, "Left"))
|
||||
s->keycode = KEY_LEFT;
|
||||
else if (!strcasecmp(keystring, "Right"))
|
||||
s->keycode = KEY_RIGHT;
|
||||
else if (!strcasecmp(keystring, "Ins"))
|
||||
s->keycode = KEY_IC;
|
||||
else if (!strcasecmp(keystring, "Del"))
|
||||
s->keycode = KEY_DC;
|
||||
else if (!strcasecmp(keystring, "Bsp"))
|
||||
s->keycode = KEY_BACKSPACE;
|
||||
/* The Tab and Enter keys don't actually produce special codes
|
||||
* but the exact integer values of ^I and ^M. Rebinding the
|
||||
* latter therefore also rebinds Tab and Enter. */
|
||||
else if (!strcasecmp(keystring, "Tab"))
|
||||
s->keycode = TAB_CODE;
|
||||
else if (!strcasecmp(keystring, "Enter"))
|
||||
s->keycode = KEY_ENTER;
|
||||
else if (!strcasecmp(keystring, "PgUp"))
|
||||
s->keycode = KEY_PPAGE;
|
||||
else if (!strcasecmp(keystring, "PgDn"))
|
||||
s->keycode = KEY_NPAGE;
|
||||
else if (!strcasecmp(keystring, "Home"))
|
||||
s->keycode = KEY_HOME;
|
||||
else if (!strcasecmp(keystring, "End"))
|
||||
s->keycode = KEY_END;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -570,6 +560,10 @@ void shortcut_init(void)
|
||||
const char *nano_nextline_msg = N_("Go to next line");
|
||||
const char *nano_home_msg = N_("Go to beginning of current line");
|
||||
const char *nano_end_msg = N_("Go to end of current line");
|
||||
#ifndef NANO_TINY
|
||||
const char *nano_prevblock_msg = N_("Go to previous block of text");
|
||||
const char *nano_nextblock_msg = N_("Go to next block of text");
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
const char *nano_parabegin_msg =
|
||||
N_("Go to beginning of paragraph; then of previous paragraph");
|
||||
@@ -869,6 +863,13 @@ void shortcut_init(void)
|
||||
add_to_funcs(do_down_void, MMAIN|MBROWSER,
|
||||
next_line_tag, IFSCHELP(nano_nextline_msg), BLANKAFTER, VIEW);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
add_to_funcs(do_prev_block, MMAIN,
|
||||
N_("Prev Block"), IFSCHELP(nano_prevblock_msg), TOGETHER, VIEW);
|
||||
add_to_funcs(do_next_block, MMAIN,
|
||||
N_("Next Block"), IFSCHELP(nano_nextblock_msg), TOGETHER, VIEW);
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
add_to_funcs(do_para_begin_void, MMAIN|MWHEREIS,
|
||||
N_("Beg of Par"), IFSCHELP(nano_parabegin_msg), TOGETHER, VIEW);
|
||||
@@ -1130,6 +1131,10 @@ void shortcut_init(void)
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "Up", do_up_void, 0);
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "^N", do_down_void, 0);
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "Down", do_down_void, 0);
|
||||
#ifndef NANO_TINY
|
||||
add_to_sclist(MMAIN, "M-7", do_prev_block, 0);
|
||||
add_to_sclist(MMAIN, "M-8", do_next_block, 0);
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
add_to_sclist(MMAIN, "M-(", do_para_begin_void, 0);
|
||||
add_to_sclist(MMAIN, "M-9", do_para_begin_void, 0);
|
||||
@@ -1360,6 +1365,7 @@ sc *strtosc(const char *input)
|
||||
sc *s;
|
||||
|
||||
s = (sc *)nmalloc(sizeof(sc));
|
||||
s->toggle = 0;
|
||||
|
||||
#ifndef DISABLE_HELP
|
||||
if (!strcasecmp(input, "help"))
|
||||
@@ -1450,6 +1456,10 @@ sc *strtosc(const char *input)
|
||||
s->scfunc = do_cut_prev_word;
|
||||
else if (!strcasecmp(input, "cutwordright"))
|
||||
s->scfunc = do_cut_next_word;
|
||||
else if (!strcasecmp(input, "prevblock"))
|
||||
s->scfunc = do_prev_block;
|
||||
else if (!strcasecmp(input, "nextblock"))
|
||||
s->scfunc = do_next_block;
|
||||
else if (!strcasecmp(input, "findbracket"))
|
||||
s->scfunc = do_find_bracket;
|
||||
else if (!strcasecmp(input, "wordcount"))
|
||||
@@ -1669,6 +1679,7 @@ void thanks_for_all_the_fish(void)
|
||||
delwin(edit);
|
||||
delwin(bottomwin);
|
||||
|
||||
free(word_chars);
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
free(quotestr);
|
||||
#ifdef HAVE_REGEX_H
|
||||
|
||||
36
src/help.c
36
src/help.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* help.c *
|
||||
* help.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, *
|
||||
* 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -141,6 +141,12 @@ void do_help(void)
|
||||
|
||||
if (func == total_refresh) {
|
||||
total_redraw();
|
||||
} else if (func == do_up_void) {
|
||||
if (line > 0)
|
||||
line--;
|
||||
} else if (func == do_down_void) {
|
||||
if (line + (editwinrows - 1) < last_line)
|
||||
line++;
|
||||
} else if (func == do_page_up) {
|
||||
if (line > editwinrows - 2)
|
||||
line -= editwinrows - 2;
|
||||
@@ -149,12 +155,6 @@ void do_help(void)
|
||||
} else if (func == do_page_down) {
|
||||
if (line + (editwinrows - 1) < last_line)
|
||||
line += editwinrows - 2;
|
||||
} else if (func == do_up_void) {
|
||||
if (line > 0)
|
||||
line--;
|
||||
} else if (func == do_down_void) {
|
||||
if (line + (editwinrows - 1) < last_line)
|
||||
line++;
|
||||
} else if (func == do_first_line) {
|
||||
line = 0;
|
||||
} else if (func == do_last_line) {
|
||||
|
||||
189
src/move.c
189
src/move.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* move.c *
|
||||
* move.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -50,15 +50,15 @@ void do_last_line(void)
|
||||
/* Move up one page. */
|
||||
void do_page_up(void)
|
||||
{
|
||||
int i, skipped = 0;
|
||||
int i, mustmove, skipped = 0;
|
||||
|
||||
/* 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) &&
|
||||
!ISSET(SOFTWRAP) &&
|
||||
#endif
|
||||
openfile->current->lineno <= editwinrows - 2)) {
|
||||
openfile->current->lineno <= editwinrows - 2)) {
|
||||
do_first_line();
|
||||
return;
|
||||
}
|
||||
@@ -66,16 +66,16 @@ 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)) {
|
||||
if (!ISSET(SMOOTH_SCROLL))
|
||||
#endif
|
||||
{
|
||||
openfile->current = openfile->edittop;
|
||||
openfile->placewewant = openfile->current_y = 0;
|
||||
#ifndef NANO_TINY
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = editwinrows - 2; i - skipped > 0 && openfile->current !=
|
||||
openfile->fileage; i--) {
|
||||
mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
|
||||
|
||||
for (i = mustmove; i - skipped > 0 && openfile->current != openfile->fileage; i--) {
|
||||
openfile->current = openfile->current->prev;
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP) && openfile->current) {
|
||||
@@ -93,7 +93,7 @@ void do_page_up(void)
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_page_up: openfile->current->lineno = %lu, skipped = %d\n",
|
||||
(unsigned long)openfile->current->lineno, skipped);
|
||||
(unsigned long)openfile->current->lineno, skipped);
|
||||
#endif
|
||||
|
||||
/* Scroll the edit window up a page. */
|
||||
@@ -104,7 +104,7 @@ void do_page_up(void)
|
||||
/* Move down one page. */
|
||||
void do_page_down(void)
|
||||
{
|
||||
int i;
|
||||
int i, mustmove;
|
||||
|
||||
/* If the cursor is less than a page away from the bottom of the file,
|
||||
* put it at the end of the last line. */
|
||||
@@ -116,16 +116,16 @@ 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)) {
|
||||
if (!ISSET(SMOOTH_SCROLL))
|
||||
#endif
|
||||
{
|
||||
openfile->current = openfile->edittop;
|
||||
openfile->placewewant = openfile->current_y = 0;
|
||||
#ifndef NANO_TINY
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = maxrows - 2; i > 0 && openfile->current !=
|
||||
openfile->filebot; i--) {
|
||||
mustmove = (maxrows < 3) ? 1 : maxrows - 2;
|
||||
|
||||
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);
|
||||
@@ -210,6 +210,46 @@ void do_para_end_void(void)
|
||||
#endif /* !DISABLE_JUSTIFY */
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Move to the preceding block of text in the file. */
|
||||
void do_prev_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_text = FALSE, seen_text = FALSE;
|
||||
|
||||
/* Skip backward until first blank line after some nonblank line(s). */
|
||||
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
|
||||
openfile->current = openfile->current->prev;
|
||||
is_text = !white_string(openfile->current->data);
|
||||
seen_text = seen_text || is_text;
|
||||
}
|
||||
|
||||
/* Step forward one line again if this one is blank. */
|
||||
if (openfile->current->next != NULL &&
|
||||
white_string(openfile->current->data))
|
||||
openfile->current = openfile->current->next;
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Move to the next block of text in the file. */
|
||||
void do_next_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_white = white_string(openfile->current->data);
|
||||
bool seen_white = is_white;
|
||||
|
||||
/* Skip forward until first nonblank line after some blank line(s). */
|
||||
while (openfile->current->next != NULL && (!seen_white || is_white)) {
|
||||
openfile->current = openfile->current->next;
|
||||
is_white = white_string(openfile->current->data);
|
||||
seen_white = seen_white || is_white;
|
||||
}
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Move to the previous word in the file. If allow_punct is TRUE, treat
|
||||
* punctuation as part of a word. If allow_update is TRUE, update the
|
||||
* screen afterwards. */
|
||||
@@ -328,7 +368,7 @@ void do_next_word_void(void)
|
||||
* if we are. */
|
||||
void do_home(void)
|
||||
{
|
||||
size_t pww_save = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SMART_HOME)) {
|
||||
@@ -345,32 +385,28 @@ void do_home(void)
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
if (need_screen_update(pww_save))
|
||||
if (need_horizontal_scroll(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
|
||||
/* Move to the end of the current line. */
|
||||
void do_end(void)
|
||||
{
|
||||
size_t pww_save = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
if (need_screen_update(pww_save))
|
||||
if (need_horizontal_scroll(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
|
||||
/* If scroll_only is FALSE, move up one line. If scroll_only is TRUE,
|
||||
* scroll up one line without scrolling the cursor. */
|
||||
void do_up(
|
||||
#ifndef NANO_TINY
|
||||
bool scroll_only
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
)
|
||||
void do_up(bool scroll_only)
|
||||
{
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
/* 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
|
||||
@@ -403,47 +439,32 @@ void do_up(
|
||||
#endif
|
||||
editwinrows / 2 + 1);
|
||||
|
||||
/* If we're not on the first line of the edit window, and the target
|
||||
* column is beyond the screen or the mark is on, redraw the prior
|
||||
* and current lines. */
|
||||
if (openfile->current_y > 0 && need_screen_update(0)) {
|
||||
update_line(openfile->current->next, 0);
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
/* If the lines weren't already redrawn, see if they need to be. */
|
||||
if (openfile->current_y > 0) {
|
||||
/* Redraw the prior line if it was horizontally scrolled. */
|
||||
if (need_horizontal_scroll(was_column, 0))
|
||||
update_line(openfile->current->next, 0);
|
||||
/* Redraw the current line if it needs to be horizontally scrolled. */
|
||||
if (need_horizontal_scroll(0, xplustabs()))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move up one line. */
|
||||
void do_up_void(void)
|
||||
{
|
||||
do_up(
|
||||
#ifndef NANO_TINY
|
||||
FALSE
|
||||
#endif
|
||||
);
|
||||
do_up(FALSE);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Scroll up one line without scrolling the cursor. */
|
||||
void do_scroll_up(void)
|
||||
{
|
||||
do_up(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If scroll_only is FALSE, move down one line. If scroll_only is TRUE,
|
||||
* scroll down one line without scrolling the cursor. */
|
||||
void do_down(
|
||||
#ifndef NANO_TINY
|
||||
bool scroll_only
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
)
|
||||
void do_down(bool scroll_only)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
int amount = 0, enough;
|
||||
filestruct *topline;
|
||||
#endif
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
/* If we're at the bottom of the file, get out. */
|
||||
if (openfile->current == openfile->filebot)
|
||||
@@ -503,26 +524,30 @@ void do_down(
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're not on the last line of the edit window, and the target
|
||||
* column is beyond the screen or the mark is on, redraw the prior
|
||||
* and current lines. */
|
||||
if (openfile->current_y < editwinrows - 1 && need_screen_update(0)) {
|
||||
update_line(openfile->current->prev, 0);
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
/* If the lines weren't already redrawn, see if they need to be. */
|
||||
if (openfile->current_y < editwinrows - 1) {
|
||||
/* Redraw the prior line if it was horizontally scrolled. */
|
||||
if (need_horizontal_scroll(was_column, 0))
|
||||
update_line(openfile->current->prev, 0);
|
||||
/* Redraw the current line if it needs to be horizontally scrolled. */
|
||||
if (need_horizontal_scroll(0, xplustabs()))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move down one line. */
|
||||
void do_down_void(void)
|
||||
{
|
||||
do_down(
|
||||
#ifndef NANO_TINY
|
||||
FALSE
|
||||
#endif
|
||||
);
|
||||
do_down(FALSE);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Scroll up one line without scrolling the cursor. */
|
||||
void do_scroll_up(void)
|
||||
{
|
||||
do_up(TRUE);
|
||||
}
|
||||
|
||||
/* Scroll down one line without scrolling the cursor. */
|
||||
void do_scroll_down(void)
|
||||
{
|
||||
@@ -533,7 +558,7 @@ void do_scroll_down(void)
|
||||
/* Move left one character. */
|
||||
void do_left(void)
|
||||
{
|
||||
size_t pww_save = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
if (openfile->current_x > 0)
|
||||
openfile->current_x = move_mbleft(openfile->current->data,
|
||||
@@ -545,14 +570,14 @@ void do_left(void)
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
if (need_screen_update(pww_save))
|
||||
if (need_horizontal_scroll(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
|
||||
/* Move right one character. */
|
||||
void do_right(void)
|
||||
{
|
||||
size_t pww_save = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
assert(openfile->current_x <= strlen(openfile->current->data));
|
||||
|
||||
@@ -560,12 +585,16 @@ void do_right(void)
|
||||
openfile->current_x = move_mbright(openfile->current->data,
|
||||
openfile->current_x);
|
||||
else if (openfile->current != openfile->filebot) {
|
||||
do_down_void();
|
||||
openfile->current_x = 0;
|
||||
openfile->placewewant = 0;
|
||||
if (need_horizontal_scroll(was_column, 0))
|
||||
update_line(openfile->current, 0);
|
||||
do_down_void();
|
||||
return;
|
||||
}
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
if (need_screen_update(pww_save))
|
||||
if (need_horizontal_scroll(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
|
||||
532
src/nano.c
532
src/nano.c
@@ -1,26 +1,27 @@
|
||||
/**************************************************************************
|
||||
* nano.c *
|
||||
* nano.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "proto.h"
|
||||
#include "revision.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
@@ -218,17 +219,15 @@ partition *partition_filestruct(filestruct *top, size_t top_x,
|
||||
} else
|
||||
p->filebot = NULL;
|
||||
|
||||
/* Save the line above the top of the partition, detach the top of
|
||||
* the partition from it, and save the text before top_x in
|
||||
* top_data. */
|
||||
/* Remember which line is above the top of the partition, detach the
|
||||
* top of the partition from it, and save the text before top_x. */
|
||||
p->top_prev = top->prev;
|
||||
top->prev = NULL;
|
||||
p->top_data = mallocstrncpy(NULL, top->data, top_x + 1);
|
||||
p->top_data[top_x] = '\0';
|
||||
|
||||
/* Save the line below the bottom of the partition, detach the
|
||||
* bottom of the partition from it, and save the text after bot_x in
|
||||
* bot_data. */
|
||||
/* Remember which line is below the bottom of the partition, detach the
|
||||
* bottom of the partition from it, and save the text after bot_x. */
|
||||
p->bot_next = bot->next;
|
||||
bot->next = NULL;
|
||||
p->bot_data = mallocstrcpy(NULL, bot->data + bot_x);
|
||||
@@ -237,8 +236,7 @@ partition *partition_filestruct(filestruct *top, size_t top_x,
|
||||
null_at(&bot->data, bot_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);
|
||||
charmove(top->data, top->data + top_x, strlen(top->data) - top_x + 1);
|
||||
align(&top->data);
|
||||
|
||||
/* Return the partition. */
|
||||
@@ -249,23 +247,20 @@ partition *partition_filestruct(filestruct *top, size_t top_x,
|
||||
* at (filebot, strlen(filebot->data)) again. */
|
||||
void unpartition_filestruct(partition **p)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
assert(p != NULL && openfile->fileage != NULL && openfile->filebot != NULL);
|
||||
|
||||
/* Reattach the line above the top of the partition, and restore the
|
||||
* text before top_x from top_data. Free top_data when we're done
|
||||
* with it. */
|
||||
tmp = mallocstrcpy(NULL, openfile->fileage->data);
|
||||
openfile->fileage->prev = (*p)->top_prev;
|
||||
if (openfile->fileage->prev != NULL)
|
||||
openfile->fileage->prev->next = openfile->fileage;
|
||||
openfile->fileage->data = charealloc(openfile->fileage->data,
|
||||
strlen((*p)->top_data) + strlen(openfile->fileage->data) + 1);
|
||||
strcpy(openfile->fileage->data, (*p)->top_data);
|
||||
strlen((*p)->top_data) + strlen(openfile->fileage->data) + 1);
|
||||
charmove(openfile->fileage->data + strlen((*p)->top_data),
|
||||
openfile->fileage->data, strlen(openfile->fileage->data) + 1);
|
||||
strncpy(openfile->fileage->data, (*p)->top_data, strlen((*p)->top_data));
|
||||
free((*p)->top_data);
|
||||
strcat(openfile->fileage->data, tmp);
|
||||
free(tmp);
|
||||
|
||||
/* Reattach the line below the bottom of the partition, and restore
|
||||
* the text after bot_x from bot_data. Free bot_data when we're
|
||||
@@ -274,7 +269,7 @@ void unpartition_filestruct(partition **p)
|
||||
if (openfile->filebot->next != NULL)
|
||||
openfile->filebot->next->prev = openfile->filebot;
|
||||
openfile->filebot->data = charealloc(openfile->filebot->data,
|
||||
strlen(openfile->filebot->data) + strlen((*p)->bot_data) + 1);
|
||||
strlen(openfile->filebot->data) + strlen((*p)->bot_data) + 1);
|
||||
strcat(openfile->filebot->data, (*p)->bot_data);
|
||||
free((*p)->bot_data);
|
||||
|
||||
@@ -315,9 +310,8 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
|
||||
* the edit window is inside the partition, and keep track of
|
||||
* whether the mark begins inside the partition. */
|
||||
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
||||
edittop_inside = (openfile->edittop->lineno >=
|
||||
openfile->fileage->lineno && openfile->edittop->lineno <=
|
||||
openfile->filebot->lineno);
|
||||
edittop_inside = (openfile->edittop->lineno >= openfile->fileage->lineno &&
|
||||
openfile->edittop->lineno <= openfile->filebot->lineno);
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set) {
|
||||
mark_inside = (openfile->mark_begin->lineno >=
|
||||
@@ -332,8 +326,7 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the number of characters in the text, and subtract it from
|
||||
* totsize. */
|
||||
/* Subtract the number of characters in the text from the file size. */
|
||||
openfile->totsize -= get_totsize(top, bot);
|
||||
|
||||
if (*file_top == NULL) {
|
||||
@@ -343,7 +336,7 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
|
||||
*file_top = openfile->fileage;
|
||||
*file_bot = openfile->filebot;
|
||||
|
||||
/* Renumber starting with file_top. */
|
||||
/* Renumber, starting with file_top. */
|
||||
renumber(*file_top);
|
||||
} else {
|
||||
filestruct *file_bot_save = *file_bot;
|
||||
@@ -366,13 +359,11 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
|
||||
|
||||
delete_node(openfile->fileage);
|
||||
|
||||
/* Renumber starting with the line after the original
|
||||
* file_bot. */
|
||||
/* Renumber, starting with the line after the original file_bot. */
|
||||
renumber(file_bot_save->next);
|
||||
}
|
||||
|
||||
/* Since the text has now been saved, remove it from the
|
||||
* filestruct. */
|
||||
/* Since the text has now been saved, remove it from the filestruct. */
|
||||
openfile->fileage = (filestruct *)nmalloc(sizeof(filestruct));
|
||||
openfile->fileage->data = mallocstrcpy(NULL, "");
|
||||
openfile->filebot = openfile->fileage;
|
||||
@@ -408,12 +399,10 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
/* Renumber starting with the beginning line of the old
|
||||
* partition. */
|
||||
/* Renumber, starting with the beginning line of the old partition. */
|
||||
renumber(top_save);
|
||||
|
||||
/* If the NO_NEWLINES flag isn't set, and the text doesn't end with
|
||||
* a magicline, add a new magicline. */
|
||||
/* If the text doesn't end with a magicline, and it should, add one. */
|
||||
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
|
||||
new_magicline();
|
||||
}
|
||||
@@ -439,22 +428,21 @@ void copy_from_filestruct(filestruct *somebuffer)
|
||||
size_t top_x, bot_x;
|
||||
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
|
||||
single_line = (top == bot);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Partition the filestruct so that it contains no text, and keep
|
||||
* track of whether the top of the edit window is inside the
|
||||
* partition. */
|
||||
filepart = partition_filestruct(openfile->current,
|
||||
openfile->current_x, openfile->current, openfile->current_x);
|
||||
/* Partition the filestruct so that it contains no text, and remember
|
||||
* whether the current line is at the top of the edit window. */
|
||||
filepart = partition_filestruct(openfile->current, openfile->current_x,
|
||||
openfile->current, openfile->current_x);
|
||||
edittop_inside = (openfile->edittop == openfile->fileage);
|
||||
free_filestruct(openfile->fileage);
|
||||
|
||||
/* Put the top and bottom of the current filestruct at the top and
|
||||
* bottom of a copy of the passed buffer. */
|
||||
free_filestruct(openfile->fileage);
|
||||
openfile->fileage = copy_filestruct(somebuffer);
|
||||
openfile->filebot = openfile->fileage;
|
||||
while (openfile->filebot->next != NULL)
|
||||
@@ -489,33 +477,29 @@ void copy_from_filestruct(filestruct *somebuffer)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the number of characters in the copied text, and add it to
|
||||
* totsize. */
|
||||
openfile->totsize += get_totsize(openfile->fileage,
|
||||
openfile->filebot);
|
||||
/* Add the number of characters in the copied text to the file size. */
|
||||
openfile->totsize += get_totsize(openfile->fileage, openfile->filebot);
|
||||
|
||||
/* Update the current y-coordinate to account for the number of
|
||||
* lines the copied text has, less one since the first line will be
|
||||
* tacked onto the current line. */
|
||||
openfile->current_y += openfile->filebot->lineno - 1;
|
||||
|
||||
top_save = openfile->fileage;
|
||||
|
||||
/* If the top of the edit window is inside the partition, set it to
|
||||
* where the copied text now starts. */
|
||||
/* If we pasted onto the first line of the edit window, the corresponding
|
||||
* struct has been freed, so... point at the start of the copied text. */
|
||||
if (edittop_inside)
|
||||
openfile->edittop = openfile->fileage;
|
||||
|
||||
top_save = openfile->fileage;
|
||||
|
||||
/* Unpartition the filestruct so that it contains all the text
|
||||
* again, plus the copied text. */
|
||||
unpartition_filestruct(&filepart);
|
||||
|
||||
/* Renumber starting with the beginning line of the old
|
||||
* partition. */
|
||||
/* Renumber, starting with the beginning line of the old partition. */
|
||||
renumber(top_save);
|
||||
|
||||
/* If the NO_NEWLINES flag isn't set, and the text doesn't end with
|
||||
* a magicline, add a new magicline. */
|
||||
/* If the text doesn't end with a magicline, and it should, add one. */
|
||||
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
|
||||
new_magicline();
|
||||
}
|
||||
@@ -619,49 +603,46 @@ void die(const char *msg, ...)
|
||||
vfprintf(stderr, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Save the current file buffer if it's been modified. */
|
||||
#ifndef NANO_TINY
|
||||
/* If the current buffer has a lockfile, remove it. */
|
||||
if (openfile && ISSET(LOCKING) && openfile->lock_filename)
|
||||
delete_lockfile(openfile->lock_filename);
|
||||
#endif
|
||||
|
||||
/* If the current file buffer was modified, save it. */
|
||||
if (openfile && openfile->modified) {
|
||||
/* If we've partitioned the filestruct, unpartition it now. */
|
||||
/* If the filestruct is partitioned, unpartition it first. */
|
||||
if (filepart != NULL)
|
||||
unpartition_filestruct(&filepart);
|
||||
|
||||
die_save_file(openfile->filename
|
||||
#ifndef NANO_TINY
|
||||
, openfile->current_stat
|
||||
#endif
|
||||
);
|
||||
die_save_file(openfile->filename, openfile->current_stat);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_MULTIBUFFER
|
||||
/* Save all of the other modified file buffers, if any. */
|
||||
if (openfile != NULL) {
|
||||
openfilestruct *tmp = openfile;
|
||||
openfilestruct *firstone = openfile;
|
||||
|
||||
while (tmp != openfile->next) {
|
||||
while (openfile->next != firstone) {
|
||||
openfile = openfile->next;
|
||||
|
||||
/* Save the current file buffer if it's been modified. */
|
||||
if (openfile->modified)
|
||||
die_save_file(openfile->filename
|
||||
#ifndef NANO_TINY
|
||||
, openfile->current_stat
|
||||
if (ISSET(LOCKING) && openfile->lock_filename)
|
||||
delete_lockfile(openfile->lock_filename);
|
||||
#endif
|
||||
);
|
||||
if (openfile->modified)
|
||||
die_save_file(openfile->filename, openfile->current_stat);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get out. */
|
||||
/* Abandon the building. */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Save the current file under the name specified in die_filename, which
|
||||
* is modified to be unique if necessary. */
|
||||
void die_save_file(const char *die_filename
|
||||
#ifndef NANO_TINY
|
||||
, struct stat *die_stat
|
||||
#endif
|
||||
)
|
||||
void die_save_file(const char *die_filename, struct stat *die_stat)
|
||||
{
|
||||
char *targetname;
|
||||
bool failed = TRUE;
|
||||
@@ -708,32 +689,34 @@ void die_save_file(const char *die_filename
|
||||
/* Initialize the three window portions nano uses. */
|
||||
void window_init(void)
|
||||
{
|
||||
/* If the screen height is too small, get out. */
|
||||
editwinrows = LINES - 5 + more_space() + no_help();
|
||||
if (COLS < MIN_EDITOR_COLS || editwinrows < MIN_EDITOR_ROWS)
|
||||
die(_("Window size is too small for nano...\n"));
|
||||
/* First delete existing windows, in case of resizing. */
|
||||
delwin(topwin);
|
||||
topwin = NULL;
|
||||
delwin(edit);
|
||||
delwin(bottomwin);
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
/* Set up fill, based on the screen width. */
|
||||
fill = wrap_at;
|
||||
if (fill <= 0)
|
||||
fill += COLS;
|
||||
if (fill < 0)
|
||||
fill = 0;
|
||||
#endif
|
||||
/* If the terminal is very flat, don't set up a titlebar. */
|
||||
if (LINES < 3) {
|
||||
editwinrows = 1;
|
||||
/* Set up two subwindows. If the terminal is just one line,
|
||||
* edit window and statusbar window will cover each other. */
|
||||
edit = newwin(1, COLS, 0, 0);
|
||||
bottomwin = newwin(1, COLS, LINES - 1, 0);
|
||||
} else {
|
||||
int toprows = (ISSET(MORE_SPACE) ? 1 : (LINES < 6) ? 1 : 2);
|
||||
int bottomrows = (ISSET(NO_HELP) ? 1 : (LINES < 5) ? 1 : 3);
|
||||
|
||||
if (topwin != NULL)
|
||||
delwin(topwin);
|
||||
if (edit != NULL)
|
||||
delwin(edit);
|
||||
if (bottomwin != NULL)
|
||||
delwin(bottomwin);
|
||||
editwinrows = LINES - toprows - bottomrows;
|
||||
|
||||
/* Set up the windows. */
|
||||
topwin = newwin(2 - more_space(), COLS, 0, 0);
|
||||
edit = newwin(editwinrows, COLS, 2 - more_space(), 0);
|
||||
bottomwin = newwin(3 - no_help(), COLS, editwinrows + (2 -
|
||||
more_space()), 0);
|
||||
/* Set up the normal three subwindows. */
|
||||
topwin = newwin(toprows, COLS, 0, 0);
|
||||
edit = newwin(editwinrows, COLS, toprows, 0);
|
||||
bottomwin = newwin(bottomrows, COLS, toprows + editwinrows, 0);
|
||||
}
|
||||
|
||||
/* In case the terminal shrunk, make sure the status line is clear. */
|
||||
blank_statusbar();
|
||||
wnoutrefresh(bottomwin);
|
||||
|
||||
/* Turn the keypad on for the windows, if necessary. */
|
||||
if (!ISSET(REBIND_KEYPAD)) {
|
||||
@@ -741,6 +724,15 @@ void window_init(void)
|
||||
keypad(edit, TRUE);
|
||||
keypad(bottomwin, TRUE);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
/* Set up the wrapping point, accounting for screen width when negative. */
|
||||
fill = wrap_at;
|
||||
if (fill <= 0)
|
||||
fill += COLS;
|
||||
if (fill < 0)
|
||||
fill = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef DISABLE_MOUSE
|
||||
@@ -876,6 +868,8 @@ void usage(void)
|
||||
#ifndef NANO_TINY
|
||||
print_opt("-W", "--wordbounds",
|
||||
N_("Detect word boundaries more accurately"));
|
||||
print_opt(_("-X <str>"), _("--wordchars=<str>"),
|
||||
N_("Which other characters are word parts"));
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
if (!ISSET(RESTRICTED))
|
||||
@@ -935,14 +929,14 @@ void usage(void)
|
||||
void version(void)
|
||||
{
|
||||
#ifdef REVISION
|
||||
printf(" nano from git, commit %s (after %s)\n", REVISION, VERSION);
|
||||
printf(" GNU nano from git, %s\n", REVISION);
|
||||
#else
|
||||
printf(_(" nano, version %s\n"), VERSION);
|
||||
printf(_(" GNU nano, version %s\n"), VERSION);
|
||||
#endif
|
||||
printf(" (C) 1999..2016 Free Software Foundation, Inc.\n");
|
||||
printf(_(" (C) 2014..%s the contributors to nano\n"), "2016");
|
||||
printf(
|
||||
_(" Email: nano@nano-editor.org Web: http://www.nano-editor.org/"));
|
||||
_(" Email: nano@nano-editor.org Web: https://nano-editor.org/"));
|
||||
printf(_("\n Compiled options:"));
|
||||
|
||||
#ifdef NANO_TINY
|
||||
@@ -1057,21 +1051,6 @@ void version(void)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Return 1 if the MORE_SPACE flag is set, and 0 otherwise. This is
|
||||
* used to calculate the sizes and Y coordinates of the subwindows. */
|
||||
int more_space(void)
|
||||
{
|
||||
return ISSET(MORE_SPACE) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Return 2 if the NO_HELP flag is set, and 0 otherwise. This is used
|
||||
* to calculate the sizes and Y coordinates of the subwindows, because
|
||||
* having NO_HELP adds two lines to the edit window. */
|
||||
int no_help(void)
|
||||
{
|
||||
return ISSET(NO_HELP) ? 2 : 0;
|
||||
}
|
||||
|
||||
/* Indicate that the current file has no name, in a way that gets the
|
||||
* user's attention. This is used when trying to save a file with no
|
||||
* name with the TEMP_FILE flag set, just before the filename prompt. */
|
||||
@@ -1126,8 +1105,6 @@ void do_exit(void)
|
||||
close_and_go();
|
||||
else if (i != 1)
|
||||
statusbar(_("Cancelled"));
|
||||
|
||||
display_main_list();
|
||||
}
|
||||
|
||||
/* Close the current buffer, and terminate nano if it was the last. */
|
||||
@@ -1316,10 +1293,9 @@ RETSIGTYPE do_continue(int signal)
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Perhaps the user resized the window while we slept. Handle it,
|
||||
* and restore the terminal to its previous state and update the
|
||||
* screen in the process. */
|
||||
handle_sigwinch(0);
|
||||
/* Perhaps the user resized the window while we slept. So act as if,
|
||||
* and restore the terminal to its previous state in the process. */
|
||||
regenerate_screen();
|
||||
#else
|
||||
/* Restore the terminal to its previous state. */
|
||||
terminal_init();
|
||||
@@ -1566,39 +1542,52 @@ void terminal_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(NANO_TINY) && defined(HAVE_KEY_DEFINED)
|
||||
/* Ask ncurses for a keycode, or assign a default one. */
|
||||
int get_keycode(const char *keyname, const int standard)
|
||||
{
|
||||
const char *keyvalue = tigetstr(keyname);
|
||||
|
||||
if (keyvalue == 0 || keyvalue == (char *)-1)
|
||||
return standard;
|
||||
else
|
||||
return key_defined(keyvalue);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Say that an unbound key was struck, and if possible which one. */
|
||||
void unbound_key(int code)
|
||||
{
|
||||
if (func_key)
|
||||
if (!is_byte(code))
|
||||
statusline(ALERT, _("Unbound key"));
|
||||
else if (meta_key) {
|
||||
if (0x60 < code && code < 0x7B)
|
||||
code -= 0x20;
|
||||
statusline(ALERT, _("Unbound key: M-%c"), code);
|
||||
if (code == '[')
|
||||
statusline(ALERT, _("Unbindable key: M-["));
|
||||
else
|
||||
statusline(ALERT, _("Unbound key: M-%c"), toupper(code));
|
||||
} else if (code < 0x20)
|
||||
statusline(ALERT, _("Unbound key: ^%c"), code + 0x40);
|
||||
else
|
||||
statusline(ALERT, _("Unbound key: %c"), code);
|
||||
}
|
||||
|
||||
/* Read in a character, interpret it as a shortcut or toggle if
|
||||
* necessary, and return it.
|
||||
* If allow_funcs is FALSE, don't actually run any functions associated
|
||||
* with shortcut keys. */
|
||||
/* Read in a keystroke. Act on the keystroke if it is a shortcut or a toggle;
|
||||
* otherwise, insert it into the edit buffer. If allow_funcs is FALSE, don't
|
||||
* do anything with the keystroke -- just return it. */
|
||||
int do_input(bool allow_funcs)
|
||||
{
|
||||
int input;
|
||||
/* The character we read in. */
|
||||
static int *kbinput = NULL;
|
||||
/* The input buffer. */
|
||||
static size_t kbinput_len = 0;
|
||||
/* The keystroke we read in: a character or a shortcut. */
|
||||
static char *puddle = NULL;
|
||||
/* The input buffer for actual characters. */
|
||||
static size_t depth = 0;
|
||||
/* The length of the input buffer. */
|
||||
bool preserve = FALSE;
|
||||
/* Preserve the contents of the cutbuffer? */
|
||||
/* Whether to preserve the contents of the cutbuffer. */
|
||||
const sc *s;
|
||||
bool have_shortcut;
|
||||
|
||||
/* Read in a character. */
|
||||
/* Read in a keystroke. */
|
||||
input = get_kbinput(edit);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -1607,7 +1596,7 @@ int do_input(bool allow_funcs)
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_MOUSE
|
||||
if (func_key && input == KEY_MOUSE) {
|
||||
if (input == KEY_MOUSE) {
|
||||
/* We received a mouse click. */
|
||||
if (do_mouse() == 1)
|
||||
/* The click was on a shortcut -- read in the character
|
||||
@@ -1629,106 +1618,116 @@ int do_input(bool allow_funcs)
|
||||
/* If we got a non-high-bit control key, a meta key sequence, or a
|
||||
* function key, and it's not a shortcut or toggle, throw it out. */
|
||||
if (!have_shortcut) {
|
||||
if (is_ascii_cntrl_char(input) || meta_key || func_key) {
|
||||
if (is_ascii_cntrl_char(input) || meta_key || !is_byte(input)) {
|
||||
unbound_key(input);
|
||||
meta_key = FALSE;
|
||||
func_key = FALSE;
|
||||
input = ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (allow_funcs) {
|
||||
/* If we got a character, and it isn't a shortcut or toggle,
|
||||
* it's a normal text character. Display the warning if we're
|
||||
* in view mode, or add the character to the input buffer if
|
||||
* we're not. */
|
||||
if (input != ERR && !have_shortcut) {
|
||||
if (ISSET(VIEW_MODE))
|
||||
print_view_warning();
|
||||
else {
|
||||
kbinput_len++;
|
||||
kbinput = (int *)nrealloc(kbinput, kbinput_len *
|
||||
sizeof(int));
|
||||
kbinput[kbinput_len - 1] = input;
|
||||
}
|
||||
}
|
||||
if (!allow_funcs)
|
||||
return input;
|
||||
|
||||
/* If we got a shortcut or toggle, or if there aren't any other
|
||||
* characters waiting after the one we read in, we need to
|
||||
* output all the characters in the input buffer if it isn't
|
||||
* empty. Note that it should be empty if we're in view
|
||||
* mode. */
|
||||
if (have_shortcut || get_key_buffer_len() == 0) {
|
||||
/* If the keystroke isn't a shortcut nor a toggle, it's a normal text
|
||||
* character: add the character to the input buffer -- or display a
|
||||
* warning when we're in view mode. */
|
||||
if (input != ERR && !have_shortcut) {
|
||||
if (ISSET(VIEW_MODE))
|
||||
print_view_warning();
|
||||
else {
|
||||
/* Store the byte, and leave room for a terminating zero. */
|
||||
puddle = charealloc(puddle, depth + 2);
|
||||
puddle[depth++] = (char)input;
|
||||
}
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set && openfile->kind_of_mark == SOFTMARK) {
|
||||
openfile->mark_set = FALSE;
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If we got a shortcut or toggle, or if there aren't any other
|
||||
* characters waiting after the one we read in, we need to output
|
||||
* all available characters in the input puddle. Note that this
|
||||
* puddle will be empty if we're in view mode. */
|
||||
if (have_shortcut || get_key_buffer_len() == 0) {
|
||||
#ifndef DISABLE_WRAPPING
|
||||
/* If we got a shortcut or toggle, and it's not the shortcut
|
||||
* for verbatim input, turn off prepending of wrapped text. */
|
||||
if (have_shortcut && s->scfunc != do_verbatim_input)
|
||||
wrap_reset();
|
||||
/* If we got a shortcut or toggle, and it's not the shortcut
|
||||
* for verbatim input, turn off prepending of wrapped text. */
|
||||
if (have_shortcut && s->scfunc != do_verbatim_input)
|
||||
wrap_reset();
|
||||
#endif
|
||||
|
||||
if (kbinput != NULL) {
|
||||
/* Display all the characters in the input buffer at
|
||||
* once, filtering out control characters. */
|
||||
char *output = charalloc(kbinput_len + 1);
|
||||
size_t i;
|
||||
if (puddle != NULL) {
|
||||
/* Insert all bytes in the input buffer into the edit buffer
|
||||
* at once, filtering out any low control codes. */
|
||||
puddle[depth] = '\0';
|
||||
do_output(puddle, depth, FALSE);
|
||||
|
||||
for (i = 0; i < kbinput_len; i++)
|
||||
output[i] = (char)kbinput[i];
|
||||
output[i] = '\0';
|
||||
/* Empty the input buffer. */
|
||||
free(puddle);
|
||||
puddle = NULL;
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
do_output(output, kbinput_len, FALSE);
|
||||
if (have_shortcut) {
|
||||
const subnfunc *f = sctofunc(s);
|
||||
|
||||
free(output);
|
||||
|
||||
/* Empty the input buffer. */
|
||||
kbinput_len = 0;
|
||||
free(kbinput);
|
||||
kbinput = NULL;
|
||||
}
|
||||
if (ISSET(VIEW_MODE) && f && !f->viewok) {
|
||||
print_view_warning();
|
||||
return ERR;
|
||||
}
|
||||
|
||||
if (have_shortcut) {
|
||||
const subnfunc *f = sctofunc(s);
|
||||
/* If the function associated with this shortcut is
|
||||
* cutting or copying text, remember this. */
|
||||
if (s->scfunc == do_cut_text_void
|
||||
/* If the function associated with this shortcut is
|
||||
* cutting or copying text, remember this. */
|
||||
if (s->scfunc == do_cut_text_void
|
||||
#ifndef NANO_TINY
|
||||
|| s->scfunc == do_copy_text || s->scfunc == do_cut_till_eof
|
||||
#endif
|
||||
)
|
||||
preserve = TRUE;
|
||||
preserve = TRUE;
|
||||
|
||||
if (s->scfunc == NULL) {
|
||||
statusbar("Internal error: shortcut without function!");
|
||||
return ERR;
|
||||
}
|
||||
if (ISSET(VIEW_MODE) && f && !f->viewok)
|
||||
print_view_warning();
|
||||
else {
|
||||
#ifndef NANO_TINY
|
||||
if (s->scfunc == do_toggle_void) {
|
||||
do_toggle(s->toggle);
|
||||
if (s->toggle != CUT_TO_END)
|
||||
preserve = TRUE;
|
||||
} else
|
||||
if (s->scfunc == do_toggle_void) {
|
||||
do_toggle(s->toggle);
|
||||
if (s->toggle != CUT_TO_END)
|
||||
preserve = TRUE;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Execute the function of the shortcut. */
|
||||
s->scfunc();
|
||||
#ifndef DISABLE_COLOR
|
||||
if (f && !f->viewok)
|
||||
reset_multis(openfile->current, FALSE);
|
||||
#endif
|
||||
if (refresh_needed) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "running edit_refresh() as refresh_needed is true\n");
|
||||
#endif
|
||||
edit_refresh();
|
||||
refresh_needed = FALSE;
|
||||
} else if (s->scfunc == do_delete || s->scfunc == do_backspace)
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
/* If Shifted movement occurs, set the mark. */
|
||||
if (shift_held && !openfile->mark_set) {
|
||||
openfile->mark_set = TRUE;
|
||||
openfile->mark_begin = openfile->current;
|
||||
openfile->mark_begin_x = openfile->current_x;
|
||||
openfile->kind_of_mark = SOFTMARK;
|
||||
}
|
||||
#endif
|
||||
/* Execute the function of the shortcut. */
|
||||
s->scfunc();
|
||||
#ifndef NANO_TINY
|
||||
/* If Shiftless movement occurred, discard a soft mark. */
|
||||
if (openfile->mark_set && !shift_held &&
|
||||
openfile->kind_of_mark == SOFTMARK) {
|
||||
openfile->mark_set = FALSE;
|
||||
openfile->mark_begin = NULL;
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
if (f && !f->viewok)
|
||||
reset_multis(openfile->current, FALSE);
|
||||
#endif
|
||||
if (refresh_needed) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "running edit_refresh() as refresh_needed is true\n");
|
||||
#endif
|
||||
edit_refresh();
|
||||
refresh_needed = FALSE;
|
||||
} else if (s->scfunc == do_delete || s->scfunc == do_backspace)
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1864,12 +1863,11 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
#endif
|
||||
|
||||
while (i < output_len) {
|
||||
/* If allow_cntrls is TRUE, convert nulls and newlines properly. */
|
||||
/* 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) {
|
||||
/* Null to newline, if needed. */
|
||||
if (output[i] == '\0')
|
||||
output[i] = '\n';
|
||||
/* Newline to Enter, if needed. */
|
||||
else if (output[i] == '\n') {
|
||||
do_enter();
|
||||
i++;
|
||||
@@ -1877,31 +1875,29 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
}
|
||||
}
|
||||
|
||||
/* Interpret the next multibyte character. */
|
||||
/* Get the next multibyte character. */
|
||||
char_buf_len = parse_mbchar(output + i, char_buf, NULL);
|
||||
|
||||
i += char_buf_len;
|
||||
|
||||
/* If allow_cntrls is FALSE, filter out an ASCII control character. */
|
||||
/* If controls are not allowed, ignore an ASCII control character. */
|
||||
if (!allow_cntrls && is_ascii_cntrl_char(*(output + i - char_buf_len)))
|
||||
continue;
|
||||
|
||||
/* If the NO_NEWLINES flag isn't set, when a character is
|
||||
* added to the magicline, it means we need a new magicline. */
|
||||
/* If we're adding to the magicline, create a new magicline. */
|
||||
if (!ISSET(NO_NEWLINES) && openfile->filebot == openfile->current)
|
||||
new_magicline();
|
||||
|
||||
/* More dangerousness fun =) */
|
||||
openfile->current->data = charealloc(openfile->current->data,
|
||||
current_len + char_buf_len + 1);
|
||||
|
||||
assert(openfile->current_x <= current_len);
|
||||
|
||||
/* 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,
|
||||
openfile->current->data + openfile->current_x,
|
||||
current_len - openfile->current_x + 1);
|
||||
strncpy(openfile->current->data + openfile->current_x, char_buf,
|
||||
char_buf_len);
|
||||
char_buf_len);
|
||||
current_len += char_buf_len;
|
||||
openfile->totsize++;
|
||||
set_modified();
|
||||
@@ -2029,6 +2025,7 @@ int main(int argc, char **argv)
|
||||
{"smooth", 0, NULL, 'S'},
|
||||
{"quickblank", 0, NULL, 'U'},
|
||||
{"wordbounds", 0, NULL, 'W'},
|
||||
{"wordchars", 1, NULL, 'X'},
|
||||
{"autoindent", 0, NULL, 'i'},
|
||||
{"cut", 0, NULL, 'k'},
|
||||
{"unix", 0, NULL, 'u'},
|
||||
@@ -2074,11 +2071,11 @@ int main(int argc, char **argv)
|
||||
while ((optchr =
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
getopt_long(argc, argv,
|
||||
"ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tuvwxz$",
|
||||
"ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$",
|
||||
long_options, NULL)
|
||||
#else
|
||||
getopt(argc, argv,
|
||||
"ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tuvwxz$")
|
||||
"ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$")
|
||||
#endif
|
||||
) != -1) {
|
||||
switch (optchr) {
|
||||
@@ -2180,6 +2177,9 @@ int main(int argc, char **argv)
|
||||
case 'W':
|
||||
SET(WORD_BOUNDS);
|
||||
break;
|
||||
case 'X':
|
||||
word_chars = mallocstrcpy(word_chars, optarg);
|
||||
break;
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
case 'Y':
|
||||
@@ -2313,6 +2313,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
char *backup_dir_cpy = backup_dir;
|
||||
char *word_chars_cpy = word_chars;
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
char *quotestr_cpy = quotestr;
|
||||
@@ -2331,6 +2332,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
backup_dir = NULL;
|
||||
word_chars = NULL;
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
quotestr = NULL;
|
||||
@@ -2361,6 +2363,10 @@ int main(int argc, char **argv)
|
||||
free(backup_dir);
|
||||
backup_dir = backup_dir_cpy;
|
||||
}
|
||||
if (word_chars_cpy != NULL) {
|
||||
free(word_chars);
|
||||
word_chars = word_chars_cpy;
|
||||
}
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
if (quotestr_cpy != NULL) {
|
||||
@@ -2521,6 +2527,11 @@ int main(int argc, char **argv)
|
||||
/* Set up the terminal state. */
|
||||
terminal_init();
|
||||
|
||||
#if defined(__linux__) && !defined(NANO_TINY)
|
||||
/* Check whether we're running on a Linux console. */
|
||||
console = (getenv("DISPLAY") == NULL);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Main: set up windows\n");
|
||||
#endif
|
||||
@@ -2540,25 +2551,33 @@ int main(int argc, char **argv)
|
||||
#ifndef DISABLE_COLOR
|
||||
set_colorpairs();
|
||||
#else
|
||||
interface_color_pair[TITLE_BAR].pairnum = hilite_attribute;
|
||||
interface_color_pair[STATUS_BAR].pairnum = hilite_attribute;
|
||||
interface_color_pair[KEY_COMBO].pairnum = hilite_attribute;
|
||||
interface_color_pair[FUNCTION_TAG].pairnum = A_NORMAL;
|
||||
interface_color_pair[TITLE_BAR].bright = FALSE;
|
||||
interface_color_pair[STATUS_BAR].bright = FALSE;
|
||||
interface_color_pair[KEY_COMBO].bright = FALSE;
|
||||
interface_color_pair[FUNCTION_TAG].bright = FALSE;
|
||||
interface_color_pair[TITLE_BAR] = hilite_attribute;
|
||||
interface_color_pair[STATUS_BAR] = hilite_attribute;
|
||||
interface_color_pair[KEY_COMBO] = hilite_attribute;
|
||||
interface_color_pair[FUNCTION_TAG] = A_NORMAL;
|
||||
#endif
|
||||
|
||||
#if !defined(NANO_TINY) && defined(HAVE_KEY_DEFINED)
|
||||
const char *keyvalue;
|
||||
/* Ask ncurses for the key codes for Control+Left and Control+Right. */
|
||||
keyvalue = tigetstr("kLFT5");
|
||||
if (keyvalue != 0 && keyvalue != (char *)-1)
|
||||
controlleft = key_defined(keyvalue);
|
||||
keyvalue = tigetstr("kRIT5");
|
||||
if (keyvalue != 0 && keyvalue != (char *)-1)
|
||||
controlright = key_defined(keyvalue);
|
||||
/* 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);
|
||||
/* 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);
|
||||
shiftcontrolup = get_keycode("kUP6", SHIFT_CONTROL_UP);
|
||||
shiftcontroldown = get_keycode("kDN6", SHIFT_CONTROL_DOWN);
|
||||
/* Ask for the codes for Shift+Alt+Left/Right/Up/Down. */
|
||||
shiftaltleft = get_keycode("kLFT4", SHIFT_ALT_LEFT);
|
||||
shiftaltright = get_keycode("kRIT4", SHIFT_ALT_RIGHT);
|
||||
shiftaltup = get_keycode("kUP4", SHIFT_ALT_UP);
|
||||
shiftaltdown = get_keycode("kDN4", SHIFT_ALT_DOWN);
|
||||
#endif
|
||||
|
||||
#ifndef USE_SLANG
|
||||
/* Tell ncurses to pass the Esc key quickly. */
|
||||
set_escdelay(50);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -2573,6 +2592,7 @@ int main(int argc, char **argv)
|
||||
optind++;
|
||||
}
|
||||
|
||||
/* If one of the arguments is a dash, read text from standard input. */
|
||||
if (optind < argc && !strcmp(argv[optind], "-")) {
|
||||
stdin_pager();
|
||||
set_modified();
|
||||
@@ -2649,15 +2669,15 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Main: bottom win, top win and edit win\n");
|
||||
fprintf(stderr, "Main: show buffer contents, and enter main loop\n");
|
||||
#endif
|
||||
|
||||
display_main_list();
|
||||
|
||||
display_buffer();
|
||||
|
||||
while (TRUE) {
|
||||
currmenu = MMAIN;
|
||||
if (currmenu != MMAIN)
|
||||
display_main_list();
|
||||
|
||||
focusing = TRUE;
|
||||
lastmessage = HUSH;
|
||||
|
||||
@@ -2675,7 +2695,7 @@ int main(int argc, char **argv)
|
||||
curs_set(1);
|
||||
wnoutrefresh(edit);
|
||||
|
||||
/* Read in and interpret characters. */
|
||||
/* Read in and interpret keystrokes. */
|
||||
do_input(TRUE);
|
||||
}
|
||||
|
||||
|
||||
103
src/nano.h
103
src/nano.h
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* nano.h *
|
||||
* nano.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
*
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
/* Macros for flags, indexing each bit in a small array. */
|
||||
#define FLAGS(flag) flags[((flag) / (sizeof(unsigned) * 8))]
|
||||
#define FLAGMASK(flag) (1 << ((flag) % (sizeof(unsigned) * 8)))
|
||||
#define FLAGMASK(flag) ((unsigned)1 << ((flag) % (sizeof(unsigned) * 8)))
|
||||
#define SET(flag) FLAGS(flag) |= FLAGMASK(flag)
|
||||
#define UNSET(flag) FLAGS(flag) &= ~FLAGMASK(flag)
|
||||
#define ISSET(flag) ((FLAGS(flag) & FLAGMASK(flag)) != 0)
|
||||
@@ -92,6 +92,10 @@
|
||||
#include <curses.h>
|
||||
#endif /* CURSES_H */
|
||||
|
||||
#if defined(NCURSES_VERSION_MAJOR) && (NCURSES_VERSION_MAJOR < 6)
|
||||
#define USING_OLD_NCURSES yes
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
/* Native language support. */
|
||||
#ifdef HAVE_LIBINTL_H
|
||||
@@ -173,7 +177,11 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
OVERWRITE, APPEND, PREPEND
|
||||
} append_type;
|
||||
} kind_of_writing_type;
|
||||
|
||||
typedef enum {
|
||||
SOFTMARK, HARDMARK
|
||||
} mark_type;
|
||||
|
||||
typedef enum {
|
||||
UPWARD, DOWNWARD
|
||||
@@ -183,10 +191,6 @@ typedef enum {
|
||||
CENTERING, FLOWING, STATIONARY
|
||||
} update_type;
|
||||
|
||||
typedef enum {
|
||||
CONTROL, META, FKEY, RAWINPUT
|
||||
} key_type;
|
||||
|
||||
typedef enum {
|
||||
ADD, DEL, BACK, CUT, CUT_EOF, REPLACE,
|
||||
#ifndef DISABLE_WRAPPING
|
||||
@@ -199,14 +203,6 @@ typedef enum {
|
||||
} undo_type;
|
||||
|
||||
/* Structure types. */
|
||||
typedef struct color_pair {
|
||||
int pairnum;
|
||||
/* The color pair number used for this foreground color and
|
||||
* background color. */
|
||||
bool bright;
|
||||
/* Is this color A_BOLD? */
|
||||
} color_pair;
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
typedef struct colortype {
|
||||
short fg;
|
||||
@@ -218,6 +214,8 @@ typedef struct colortype {
|
||||
int pairnum;
|
||||
/* The color pair number used for this foreground color and
|
||||
* background color. */
|
||||
int attributes;
|
||||
/* Pair number and brightness composed into ready-to-use attributes. */
|
||||
int rex_flags;
|
||||
/* The regex compilation flags (with or without REG_ICASE). */
|
||||
char *start_regex;
|
||||
@@ -399,6 +397,8 @@ typedef struct openfilestruct {
|
||||
/* The file's y-coordinate position. */
|
||||
bool modified;
|
||||
/* Whether the file has been modified. */
|
||||
struct stat *current_stat;
|
||||
/* The file's current stat information. */
|
||||
#ifndef NANO_TINY
|
||||
bool mark_set;
|
||||
/* Whether the mark is on in this file. */
|
||||
@@ -406,10 +406,10 @@ typedef struct openfilestruct {
|
||||
/* The file's line where the mark is, if any. */
|
||||
size_t mark_begin_x;
|
||||
/* The file's mark's x-coordinate position, if any. */
|
||||
mark_type kind_of_mark;
|
||||
/* Whether this is a soft or a hard mark. */
|
||||
file_format fmt;
|
||||
/* The file's format. */
|
||||
struct stat *current_stat;
|
||||
/* The file's current stat information. */
|
||||
undo *undotop;
|
||||
/* The top of the undo list. */
|
||||
undo *current_undo;
|
||||
@@ -441,12 +441,12 @@ typedef struct rcoption {
|
||||
#endif
|
||||
|
||||
typedef struct sc {
|
||||
char *keystr;
|
||||
/* The shortcut key for a function, ASCII version. */
|
||||
key_type type;
|
||||
/* What kind of command key it is, for convenience later. */
|
||||
int seq;
|
||||
/* The actual sequence to check once the type is determined. */
|
||||
const char *keystr;
|
||||
/* The string that describes a keystroke, like "^C" or "M-R". */
|
||||
bool meta;
|
||||
/* Whether this is a Meta keystroke. */
|
||||
int keycode;
|
||||
/* The integer that, together with meta, identifies the keystroke. */
|
||||
int menus;
|
||||
/* Which menus this applies to. */
|
||||
void (*scfunc)(void);
|
||||
@@ -556,16 +556,28 @@ enum
|
||||
#define MMOST (MMAIN|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MWRITEFILE|MINSERTFILE|\
|
||||
MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MSPELL|MLINTER)
|
||||
|
||||
/* Control key sequences. Changing these would be very, very bad. */
|
||||
#define NANO_CONTROL_SPACE 0
|
||||
#define NANO_CONTROL_I 9
|
||||
#define NANO_CONTROL_3 27
|
||||
#define NANO_CONTROL_7 31
|
||||
#define NANO_CONTROL_8 127
|
||||
/* Basic control codes. */
|
||||
#define TAB_CODE 0x09
|
||||
#define ESC_CODE 0x1B
|
||||
#define DEL_CODE 0x7F
|
||||
|
||||
/* Codes for "modified" Arrow keys, beyond KEY_MAX of ncurses. */
|
||||
#define CONTROL_LEFT 0x401
|
||||
#define CONTROL_RIGHT 0x402
|
||||
#define CONTROL_UP 0x403
|
||||
#define CONTROL_DOWN 0x404
|
||||
#define SHIFT_CONTROL_LEFT 0x405
|
||||
#define SHIFT_CONTROL_RIGHT 0x406
|
||||
#define SHIFT_CONTROL_UP 0x407
|
||||
#define SHIFT_CONTROL_DOWN 0x408
|
||||
#define SHIFT_ALT_LEFT 0x409
|
||||
#define SHIFT_ALT_RIGHT 0x40a
|
||||
#define SHIFT_ALT_UP 0x40b
|
||||
#define SHIFT_ALT_DOWN 0x40c
|
||||
#define SHIFT_PAGEUP 0x40d
|
||||
#define SHIFT_PAGEDOWN 0x40e
|
||||
#define SHIFT_HOME 0x40f
|
||||
#define SHIFT_END 0x410
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* An imaginary key for when we get a SIGWINCH (window resize). */
|
||||
@@ -582,11 +594,6 @@ enum
|
||||
/* The maximum number of entries displayed in the main shortcut list. */
|
||||
#define MAIN_VISIBLE (((COLS + 40) / 20) * 2)
|
||||
|
||||
/* The minimum editor window columns and rows required for nano to work
|
||||
* correctly. Don't make these smaller than 4 and 1. */
|
||||
#define MIN_EDITOR_COLS 4
|
||||
#define MIN_EDITOR_ROWS 1
|
||||
|
||||
/* The default number of characters from the end of the line where
|
||||
* wrapping occurs. */
|
||||
#define CHARS_FROM_EOL 8
|
||||
@@ -604,10 +611,4 @@ enum
|
||||
/* The largest size_t number that doesn't have the high bit set. */
|
||||
#define HIGHEST_POSITIVE ((~(size_t)0) >> 1)
|
||||
|
||||
#ifdef REVISION
|
||||
#define BRANDING PACKAGE_VERSION"-git "REVISION
|
||||
#else
|
||||
#define BRANDING PACKAGE_STRING
|
||||
#endif
|
||||
|
||||
#endif /* !NANO_H */
|
||||
|
||||
451
src/prompt.c
451
src/prompt.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* prompt.c *
|
||||
* prompt.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -28,15 +28,12 @@
|
||||
|
||||
static char *prompt = NULL;
|
||||
/* The prompt string used for statusbar questions. */
|
||||
static size_t statusbar_x = (size_t)-1;
|
||||
static size_t statusbar_x = HIGHEST_POSITIVE;
|
||||
/* The cursor position in answer. */
|
||||
static size_t statusbar_pww = (size_t)-1;
|
||||
/* The place we want in answer. */
|
||||
|
||||
/* Read in a character, interpret it as a shortcut or toggle if
|
||||
* necessary, 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
|
||||
/* 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,
|
||||
@@ -66,14 +63,11 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
#ifndef DISABLE_MOUSE
|
||||
/* If we got a mouse click and it was on a shortcut, read in the
|
||||
* shortcut character. */
|
||||
if (func_key && input == KEY_MOUSE) {
|
||||
if (input == KEY_MOUSE) {
|
||||
if (do_statusbar_mouse() == 1)
|
||||
input = get_kbinput(bottomwin);
|
||||
else {
|
||||
meta_key = FALSE;
|
||||
func_key = FALSE;
|
||||
input = ERR;
|
||||
}
|
||||
else
|
||||
return ERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -87,120 +81,100 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
/* If we got a non-high-bit control key, a meta key sequence, or a
|
||||
* function key, and it's not a shortcut or toggle, throw it out. */
|
||||
if (!have_shortcut) {
|
||||
if (is_ascii_cntrl_char(input) || meta_key || func_key) {
|
||||
if (is_ascii_cntrl_char(input) || meta_key || !is_byte(input)) {
|
||||
beep();
|
||||
meta_key = FALSE;
|
||||
func_key = FALSE;
|
||||
input = ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got a character, and it isn't a shortcut or toggle,
|
||||
* it's a normal text character. Display the warning if we're
|
||||
* in view mode, or add the character to the input buffer if
|
||||
* we're not. */
|
||||
/* If the keystroke isn't a shortcut nor a toggle, it's a normal text
|
||||
* character: add the it to the input buffer, when allowed. */
|
||||
if (input != ERR && !have_shortcut) {
|
||||
/* If we're using restricted mode, the filename isn't blank,
|
||||
* and we're at the "Write File" prompt, disable text input. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE) {
|
||||
/* Only accept input when not in restricted mode, or when not at
|
||||
* the "Write File" prompt, or when there is no filename yet. */
|
||||
if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
|
||||
openfile->filename[0] == '\0') {
|
||||
kbinput_len++;
|
||||
kbinput = (int *)nrealloc(kbinput, kbinput_len * sizeof(int));
|
||||
kbinput[kbinput_len - 1] = input;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got a shortcut, or if there aren't any other characters
|
||||
* waiting after the one we read in, we need to display all the
|
||||
* characters in the input buffer if it isn't empty. */
|
||||
if (have_shortcut || get_key_buffer_len() == 0) {
|
||||
if (kbinput != NULL) {
|
||||
/* Display all the characters in the input buffer at
|
||||
* once, filtering out control characters. */
|
||||
do_statusbar_output(kbinput, kbinput_len, TRUE, NULL);
|
||||
/* If we got a shortcut, or if there aren't any other keystrokes waiting
|
||||
* after the one we read in, we need to insert all the characters in the
|
||||
* input buffer (if not empty) into the answer. */
|
||||
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);
|
||||
|
||||
/* Empty the input buffer. */
|
||||
kbinput_len = 0;
|
||||
free(kbinput);
|
||||
kbinput = NULL;
|
||||
}
|
||||
/* Empty the input buffer. */
|
||||
kbinput_len = 0;
|
||||
free(kbinput);
|
||||
kbinput = NULL;
|
||||
}
|
||||
|
||||
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_cut_text_void) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable Cut. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE)
|
||||
do_statusbar_cut_text();
|
||||
} else if (s->scfunc == do_left)
|
||||
do_statusbar_left();
|
||||
else if (s->scfunc == do_right)
|
||||
do_statusbar_right();
|
||||
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)
|
||||
do_statusbar_left();
|
||||
else if (s->scfunc == do_right)
|
||||
do_statusbar_right();
|
||||
#ifndef NANO_TINY
|
||||
else if (s->scfunc == do_prev_word_void)
|
||||
do_statusbar_prev_word();
|
||||
else if (s->scfunc == do_next_word_void)
|
||||
do_statusbar_next_word();
|
||||
else if (s->scfunc == do_prev_word_void)
|
||||
do_statusbar_prev_word();
|
||||
else if (s->scfunc == do_next_word_void)
|
||||
do_statusbar_next_word();
|
||||
#endif
|
||||
else if (s->scfunc == do_home)
|
||||
do_statusbar_home();
|
||||
else if (s->scfunc == do_end)
|
||||
do_statusbar_end();
|
||||
else if (s->scfunc == do_verbatim_input) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable verbatim input. */
|
||||
if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
|
||||
openfile->filename[0] == '\0') {
|
||||
bool got_enter = FALSE;
|
||||
/* Whether we got the Enter key. */
|
||||
else if (s->scfunc == do_home)
|
||||
do_statusbar_home();
|
||||
else if (s->scfunc == do_end)
|
||||
do_statusbar_end();
|
||||
/* When in restricted mode at the "Write File" prompt and the
|
||||
* filename isn't blank, disallow any input and deletion. */
|
||||
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE &&
|
||||
openfile->filename[0] != '\0' &&
|
||||
(s->scfunc == do_verbatim_input ||
|
||||
s->scfunc == do_cut_text_void ||
|
||||
s->scfunc == do_delete ||
|
||||
s->scfunc == do_backspace))
|
||||
;
|
||||
else if (s->scfunc == do_verbatim_input) {
|
||||
bool got_newline = FALSE;
|
||||
/* Whether we got a verbatim ^J. */
|
||||
|
||||
do_statusbar_verbatim_input(&got_enter);
|
||||
do_statusbar_verbatim_input(&got_newline);
|
||||
|
||||
/* If we got the Enter key, remove it from the input
|
||||
* buffer, set input to the key value for Enter, and
|
||||
* set finished to TRUE to indicate that we're done. */
|
||||
if (got_enter) {
|
||||
get_input(NULL, 1);
|
||||
input = sc_seq_or(do_enter, 0);
|
||||
*finished = TRUE;
|
||||
}
|
||||
}
|
||||
} else if (s->scfunc == do_delete) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable Delete. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE)
|
||||
do_statusbar_delete();
|
||||
} else if (s->scfunc == do_backspace) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable Backspace. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE)
|
||||
do_statusbar_backspace();
|
||||
} else {
|
||||
/* Handle any other shortcut in the current menu, setting
|
||||
* ran_func to TRUE if we try to run their associated
|
||||
* functions and setting finished to TRUE to indicate
|
||||
* that we're done after running or trying to run their
|
||||
* associated functions. */
|
||||
f = sctofunc(s);
|
||||
if (s->scfunc != NULL) {
|
||||
*ran_func = TRUE;
|
||||
if (f && (!ISSET(VIEW_MODE) || f->viewok) &&
|
||||
f->scfunc != do_gotolinecolumn_void)
|
||||
f->scfunc();
|
||||
}
|
||||
/* If we got a verbatim ^J, remove it from the input buffer,
|
||||
* fake a press of Enter, and indicate that we're done. */
|
||||
if (got_newline) {
|
||||
get_input(NULL, 1);
|
||||
input = sc_seq_or(do_enter, 0);
|
||||
*finished = TRUE;
|
||||
}
|
||||
} else if (s->scfunc == do_cut_text_void)
|
||||
do_statusbar_cut_text();
|
||||
else if (s->scfunc == do_delete)
|
||||
do_statusbar_delete();
|
||||
else if (s->scfunc == do_backspace)
|
||||
do_statusbar_backspace();
|
||||
else {
|
||||
/* Handle any other shortcut in the current menu, setting
|
||||
* ran_func to TRUE if we try to run their associated functions,
|
||||
* and setting finished to TRUE to indicatethat we're done after
|
||||
* running or trying to run their associated functions. */
|
||||
f = sctofunc(s);
|
||||
if (s->scfunc != NULL) {
|
||||
*ran_func = TRUE;
|
||||
if (f && (!ISSET(VIEW_MODE) || f->viewok) &&
|
||||
f->scfunc != do_gotolinecolumn_void)
|
||||
f->scfunc();
|
||||
}
|
||||
*finished = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,8 +192,6 @@ int do_statusbar_mouse(void)
|
||||
if (retval == 0 && wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE)) {
|
||||
size_t start_col;
|
||||
|
||||
assert(prompt != NULL);
|
||||
|
||||
start_col = strlenpt(prompt) + 2;
|
||||
|
||||
/* Move to where the click occurred. */
|
||||
@@ -227,7 +199,7 @@ int do_statusbar_mouse(void)
|
||||
statusbar_x = actual_x(answer,
|
||||
get_statusbar_page_start(start_col, start_col +
|
||||
statusbar_xplustabs()) + mouse_x - start_col);
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,17 +208,15 @@ int do_statusbar_mouse(void)
|
||||
#endif
|
||||
|
||||
/* The user typed input_len multibyte characters. Add them to the
|
||||
* statusbar prompt, setting got_enter to TRUE if we get a newline,
|
||||
* statusbar prompt, setting got_newline to TRUE if we got a verbatim ^J,
|
||||
* and filtering out ASCII control characters if filtering is TRUE. */
|
||||
void do_statusbar_output(int *the_input, size_t input_len,
|
||||
bool filtering, bool *got_enter)
|
||||
bool filtering, bool *got_newline)
|
||||
{
|
||||
char *output = charalloc(input_len + 1);
|
||||
char *char_buf = charalloc(mb_cur_max());
|
||||
int i, char_len;
|
||||
|
||||
assert(answer != NULL);
|
||||
|
||||
/* Copy the typed stuff so it can be treated. */
|
||||
for (i = 0; i < input_len; i++)
|
||||
output[i] = (char)the_input[i];
|
||||
@@ -261,9 +231,9 @@ void do_statusbar_output(int *the_input, size_t input_len,
|
||||
output[i] = '\n';
|
||||
else if (output[i] == '\n') {
|
||||
/* Put back the rest of the characters for reparsing,
|
||||
* indicate that we got the Enter key and get out. */
|
||||
* indicate that we got a ^J and get out. */
|
||||
unparse_kbinput(output + i, input_len - i);
|
||||
*got_enter = TRUE;
|
||||
*got_newline = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -277,8 +247,6 @@ void do_statusbar_output(int *the_input, size_t input_len,
|
||||
if (filtering && is_ascii_cntrl_char(*(output + i - char_len)))
|
||||
continue;
|
||||
|
||||
assert(statusbar_x <= strlen(answer));
|
||||
|
||||
/* Insert the typed character into the existing answer string. */
|
||||
answer = charealloc(answer, strlen(answer) + char_len + 1);
|
||||
charmove(answer + statusbar_x + char_len, answer + statusbar_x,
|
||||
@@ -291,23 +259,21 @@ void do_statusbar_output(int *the_input, size_t input_len,
|
||||
free(char_buf);
|
||||
free(output);
|
||||
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Move to the beginning of the prompt text. */
|
||||
/* Move to the beginning of the answer. */
|
||||
void do_statusbar_home(void)
|
||||
{
|
||||
statusbar_x = 0;
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Move to the end of the prompt text. */
|
||||
/* Move to the end of the answer. */
|
||||
void do_statusbar_end(void)
|
||||
{
|
||||
statusbar_x = strlen(answer);
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Move left one character. */
|
||||
@@ -315,16 +281,16 @@ void do_statusbar_left(void)
|
||||
{
|
||||
if (statusbar_x > 0) {
|
||||
statusbar_x = move_mbleft(answer, statusbar_x);
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
}
|
||||
|
||||
/* Move right one character. */
|
||||
void do_statusbar_right(void)
|
||||
{
|
||||
if (statusbar_x < strlen(answer)) {
|
||||
if (answer[statusbar_x] != '\0') {
|
||||
statusbar_x = move_mbright(answer, statusbar_x);
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,13 +306,9 @@ void do_statusbar_backspace(void)
|
||||
/* Delete one character. */
|
||||
void do_statusbar_delete(void)
|
||||
{
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
|
||||
if (answer[statusbar_x] != '\0') {
|
||||
int char_len = parse_mbchar(answer + statusbar_x, NULL, NULL);
|
||||
|
||||
assert(statusbar_x < strlen(answer));
|
||||
|
||||
charmove(answer + statusbar_x, answer + statusbar_x + char_len,
|
||||
strlen(answer) - statusbar_x - char_len + 1);
|
||||
align(&answer);
|
||||
@@ -355,33 +317,23 @@ void do_statusbar_delete(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Move text from the prompt into oblivion. */
|
||||
/* Zap some or all text from the answer. */
|
||||
void do_statusbar_cut_text(void)
|
||||
{
|
||||
assert(answer != NULL);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(CUT_TO_END))
|
||||
null_at(&answer, statusbar_x);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
null_at(&answer, 0);
|
||||
if (!ISSET(CUT_TO_END))
|
||||
statusbar_x = 0;
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
}
|
||||
|
||||
null_at(&answer, statusbar_x);
|
||||
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Move to the next word in the prompt text. */
|
||||
/* Move to the next word in the answer. */
|
||||
void do_statusbar_next_word(void)
|
||||
{
|
||||
bool seen_space = !is_word_mbchar(answer + statusbar_x, FALSE);
|
||||
|
||||
assert(answer != NULL);
|
||||
|
||||
/* Move forward until we reach the start of a word. */
|
||||
while (answer[statusbar_x] != '\0') {
|
||||
statusbar_x = move_mbright(answer, statusbar_x);
|
||||
@@ -394,16 +346,14 @@ void do_statusbar_next_word(void)
|
||||
break;
|
||||
}
|
||||
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Move to the previous word in the prompt text. */
|
||||
/* Move to the previous word in the answer. */
|
||||
void do_statusbar_prev_word(void)
|
||||
{
|
||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||
|
||||
assert(answer != NULL);
|
||||
|
||||
/* Move backward until we pass over the start of a word. */
|
||||
while (statusbar_x != 0) {
|
||||
statusbar_x = move_mbleft(answer, statusbar_x);
|
||||
@@ -421,13 +371,13 @@ void do_statusbar_prev_word(void)
|
||||
/* Move one character forward again to sit on the start of the word. */
|
||||
statusbar_x = move_mbright(answer, statusbar_x);
|
||||
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Get verbatim input. Set got_enter to TRUE if we got the Enter key as
|
||||
/* Get verbatim input, setting got_newline to TRUE if we get a ^J as
|
||||
* part of the verbatim input. */
|
||||
void do_statusbar_verbatim_input(bool *got_enter)
|
||||
void do_statusbar_verbatim_input(bool *got_newline)
|
||||
{
|
||||
int *kbinput;
|
||||
size_t kbinput_len;
|
||||
@@ -437,101 +387,86 @@ void do_statusbar_verbatim_input(bool *got_enter)
|
||||
|
||||
/* Display all the verbatim characters at once, not filtering out
|
||||
* control characters. */
|
||||
do_statusbar_output(kbinput, kbinput_len, FALSE, got_enter);
|
||||
do_statusbar_output(kbinput, kbinput_len, FALSE, got_newline);
|
||||
}
|
||||
|
||||
/* Return the placewewant associated with statusbar_x, i.e. the
|
||||
* zero-based column position of the cursor. The value will be no
|
||||
* smaller than statusbar_x. */
|
||||
/* Return the zero-based column position of the cursor in the answer. */
|
||||
size_t statusbar_xplustabs(void)
|
||||
{
|
||||
return strnlenpt(answer, statusbar_x);
|
||||
}
|
||||
|
||||
/* nano scrolls horizontally within a line in chunks. This function
|
||||
* returns the column number of the first character displayed in the
|
||||
* statusbar prompt when the cursor is at the given column with the
|
||||
* prompt ending at start_col. Note that (0 <= column -
|
||||
* get_statusbar_page_start(column) < COLS). */
|
||||
size_t get_statusbar_page_start(size_t start_col, size_t column)
|
||||
/* Return the column number of the first character of the answer that is
|
||||
* displayed in the statusbar when the cursor is at the given column,
|
||||
* with the available room for the answer starting at base. Note that
|
||||
* (0 <= column - get_statusbar_page_start(column) < COLS). */
|
||||
size_t get_statusbar_page_start(size_t base, size_t column)
|
||||
{
|
||||
if (column == start_col || column < COLS - 1 || COLS == start_col + 1)
|
||||
if (column == base || column < COLS - 1)
|
||||
return 0;
|
||||
else if (COLS > base + 2)
|
||||
return column - base - 1 - (column - base - 1) % (COLS - base - 2);
|
||||
else
|
||||
return column - start_col - (column - start_col) % (COLS -
|
||||
start_col - 1);
|
||||
return column - 2;
|
||||
}
|
||||
|
||||
/* Reinitialize the cursor position in the status bar prompt. */
|
||||
/* Reinitialize the cursor position in the answer. */
|
||||
void reinit_statusbar_x(void)
|
||||
{
|
||||
statusbar_x = (size_t)-1;
|
||||
statusbar_pww = (size_t)-1;
|
||||
statusbar_x = HIGHEST_POSITIVE;
|
||||
}
|
||||
|
||||
/* Put the cursor in the statusbar prompt at statusbar_x. */
|
||||
/* Put the cursor in the answer at statusbar_x. */
|
||||
void reset_statusbar_cursor(void)
|
||||
{
|
||||
size_t start_col = strlenpt(prompt) + 2;
|
||||
size_t xpt = statusbar_xplustabs();
|
||||
|
||||
/* Work around a cursor-misplacement bug in VTEs. */
|
||||
wmove(bottomwin, 0, 0);
|
||||
wnoutrefresh(bottomwin);
|
||||
doupdate();
|
||||
|
||||
wmove(bottomwin, 0, start_col + xpt -
|
||||
get_statusbar_page_start(start_col, start_col + xpt));
|
||||
get_statusbar_page_start(start_col, start_col + xpt));
|
||||
|
||||
wnoutrefresh(bottomwin);
|
||||
}
|
||||
|
||||
/* Repaint the statusbar. */
|
||||
void update_the_statusbar(void)
|
||||
{
|
||||
size_t start_col, index, page_start;
|
||||
size_t base, the_page, end_page;
|
||||
char *expanded;
|
||||
|
||||
assert(prompt != NULL && statusbar_x <= strlen(answer));
|
||||
base = strlenpt(prompt) + 2;
|
||||
the_page = get_statusbar_page_start(base, base + strnlenpt(answer, statusbar_x));
|
||||
end_page = get_statusbar_page_start(base, base + strlenpt(answer) - 1);
|
||||
|
||||
start_col = strlenpt(prompt) + 2;
|
||||
index = strnlenpt(answer, statusbar_x);
|
||||
page_start = get_statusbar_page_start(start_col, start_col + index);
|
||||
|
||||
if (interface_color_pair[TITLE_BAR].bright)
|
||||
wattron(bottomwin, A_BOLD);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
blank_statusbar();
|
||||
|
||||
mvwaddnstr(bottomwin, 0, 0, prompt, actual_x(prompt, COLS - 2));
|
||||
mvwaddstr(bottomwin, 0, 0, prompt);
|
||||
waddch(bottomwin, ':');
|
||||
waddch(bottomwin, (page_start == 0) ? ' ' : '$');
|
||||
waddch(bottomwin, (the_page == 0) ? ' ' : '<');
|
||||
|
||||
expanded = display_string(answer, page_start, COLS - start_col - 1, FALSE);
|
||||
expanded = display_string(answer, the_page, COLS - base - 1, FALSE);
|
||||
waddstr(bottomwin, expanded);
|
||||
free(expanded);
|
||||
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
waddch(bottomwin, (the_page >= end_page) ? ' ' : '>');
|
||||
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
reset_statusbar_cursor();
|
||||
wnoutrefresh(bottomwin);
|
||||
}
|
||||
|
||||
/* Update the statusbar line /if/ the placewewant changes page. */
|
||||
void update_bar_if_needed(void)
|
||||
{
|
||||
size_t start_col = strlenpt(prompt) + 2;
|
||||
size_t was_pww = statusbar_pww;
|
||||
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
|
||||
if (get_statusbar_page_start(start_col, start_col + statusbar_pww) !=
|
||||
get_statusbar_page_start(start_col, start_col + was_pww))
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Get a string of input at the statusbar prompt. */
|
||||
functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
bool allow_files, bool *listed,
|
||||
#endif
|
||||
const char *curranswer,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
filestruct **history_list,
|
||||
#endif
|
||||
@@ -559,15 +494,11 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
#endif
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
|
||||
answer = mallocstrcpy(answer, curranswer);
|
||||
|
||||
if (statusbar_x > strlen(answer)) {
|
||||
if (statusbar_x > strlen(answer))
|
||||
statusbar_x = strlen(answer);
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answer, (unsigned long) statusbar_x);
|
||||
fprintf(stderr, "acquiring: answer = \"%s\", statusbar_x = %lu\n", answer, (unsigned long) statusbar_x);
|
||||
#endif
|
||||
|
||||
update_the_statusbar();
|
||||
@@ -576,25 +507,24 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
wnoutrefresh(edit);
|
||||
wnoutrefresh(bottomwin);
|
||||
|
||||
/* If we're using restricted mode, we aren't allowed to change the
|
||||
* name of the current file once it has one, because that would
|
||||
* allow writing to files not specified on the command line. In
|
||||
* this case, disable all keys that would change the text if the
|
||||
* filename isn't blank and we're at the "Write File" prompt. */
|
||||
while (TRUE) {
|
||||
/* Ensure the cursor is on when waiting for input. */
|
||||
/* Ensure the cursor is shown when waiting for input. */
|
||||
curs_set(1);
|
||||
|
||||
kbinput = do_statusbar_input(&ran_func, &finished, refresh_func);
|
||||
assert(statusbar_x <= strlen(answer));
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the window size changed, go reformat the prompt string. */
|
||||
if (kbinput == KEY_WINCH) {
|
||||
refresh_func();
|
||||
update_the_statusbar();
|
||||
continue;
|
||||
}
|
||||
*actual = KEY_WINCH;
|
||||
#ifndef DISABLE_HISTORIES
|
||||
free(magichistory);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
func = func_from_key(&kbinput);
|
||||
|
||||
if (func == do_cancel || func == do_enter)
|
||||
@@ -607,7 +537,7 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
if (func == do_tab) {
|
||||
#ifndef DISABLE_HISTORIES
|
||||
if (history_list != NULL) {
|
||||
if (last_kbinput != sc_seq_or(do_tab, NANO_CONTROL_I))
|
||||
if (last_kbinput != sc_seq_or(do_tab, TAB_CODE))
|
||||
complete_len = strlen(answer);
|
||||
|
||||
if (complete_len > 0) {
|
||||
@@ -620,8 +550,6 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
if (allow_tabs)
|
||||
answer = input_tab(answer, allow_files, &statusbar_x,
|
||||
&tabbed, refresh_func, listed);
|
||||
|
||||
update_the_statusbar();
|
||||
} else
|
||||
#endif /* !DISABLE_TABCOMP */
|
||||
#ifndef DISABLE_HISTORIES
|
||||
@@ -639,8 +567,6 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
statusbar_x = strlen(answer);
|
||||
}
|
||||
|
||||
update_the_statusbar();
|
||||
|
||||
/* This key has a shortcut-list entry when it's used to
|
||||
* move to an older search, which means that finished has
|
||||
* been set to TRUE. Set it back to FALSE here, so that
|
||||
@@ -665,8 +591,6 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
statusbar_x = strlen(answer);
|
||||
}
|
||||
|
||||
update_the_statusbar();
|
||||
|
||||
/* This key has a shortcut-list entry when it's used to
|
||||
* move to a newer search, which means that finished has
|
||||
* been set to TRUE. Set it back to FALSE here, so that
|
||||
@@ -676,8 +600,6 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
} else
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
if (func == do_help_void) {
|
||||
update_the_statusbar();
|
||||
|
||||
/* This key has a shortcut-list entry when it's used to go to
|
||||
* the help browser or display a message indicating that help
|
||||
* is disabled, which means that finished has been set to TRUE.
|
||||
@@ -691,11 +613,11 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
if (finished)
|
||||
break;
|
||||
|
||||
update_the_statusbar();
|
||||
|
||||
#if !defined(DISABLE_HISTORIES) && !defined(DISABLE_TABCOMP)
|
||||
last_kbinput = kbinput;
|
||||
#endif
|
||||
reset_statusbar_cursor();
|
||||
wnoutrefresh(bottomwin);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
@@ -734,42 +656,48 @@ int do_prompt(bool allow_tabs,
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
functionptrtype func;
|
||||
functionptrtype func = NULL;
|
||||
#ifndef DISABLE_TABCOMP
|
||||
bool listed = FALSE;
|
||||
#endif
|
||||
/* Save a possible current statusbar x position. */
|
||||
size_t was_statusbar_x = statusbar_x;
|
||||
size_t was_pww = statusbar_pww;
|
||||
|
||||
prompt = charalloc(((COLS - 4) * mb_cur_max()) + 1);
|
||||
|
||||
bottombars(menu);
|
||||
|
||||
va_start(ap, msg);
|
||||
vsnprintf(prompt, (COLS - 4) * mb_cur_max(), msg, ap);
|
||||
va_end(ap);
|
||||
null_at(&prompt, actual_x(prompt, COLS - 4));
|
||||
answer = mallocstrcpy(answer, curranswer);
|
||||
|
||||
func = get_prompt_string(&retval, allow_tabs,
|
||||
#ifndef NANO_TINY
|
||||
redo_theprompt:
|
||||
#endif
|
||||
prompt = charalloc((COLS * mb_cur_max()) + 1);
|
||||
va_start(ap, msg);
|
||||
vsnprintf(prompt, COLS * mb_cur_max(), msg, ap);
|
||||
va_end(ap);
|
||||
/* Reserve five columns for colon plus angles plus answer, ":<aa>". */
|
||||
null_at(&prompt, actual_x(prompt, (COLS < 5) ? 0 : COLS - 5));
|
||||
|
||||
func = acquire_an_answer(&retval, allow_tabs,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
allow_files, &listed,
|
||||
#endif
|
||||
curranswer,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
history_list,
|
||||
history_list,
|
||||
#endif
|
||||
refresh_func);
|
||||
refresh_func);
|
||||
|
||||
free(prompt);
|
||||
prompt = NULL;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (retval == KEY_WINCH)
|
||||
goto redo_theprompt;
|
||||
#endif
|
||||
|
||||
/* If we're done with this prompt, restore the x position to what
|
||||
* it was at a possible previous prompt. */
|
||||
if (func == do_cancel || func == do_enter) {
|
||||
if (func == do_cancel || func == do_enter)
|
||||
statusbar_x = was_statusbar_x;
|
||||
statusbar_pww = was_pww;
|
||||
}
|
||||
|
||||
/* If we left the prompt via Cancel or Enter, set the return value
|
||||
* properly. */
|
||||
@@ -855,15 +783,12 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
onekey("^C", _("Cancel"), width);
|
||||
}
|
||||
|
||||
if (interface_color_pair[TITLE_BAR].bright)
|
||||
wattron(bottomwin, A_BOLD);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
blank_statusbar();
|
||||
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
|
||||
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
/* Refresh edit window and statusbar before getting input. */
|
||||
wnoutrefresh(edit);
|
||||
@@ -917,6 +842,8 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
}
|
||||
} while (response == -2);
|
||||
|
||||
currmenu = oldmenu;
|
||||
/* Restore the previously active menu. */
|
||||
bottombars(oldmenu);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
127
src/proto.h
127
src/proto.h
@@ -1,22 +1,21 @@
|
||||
/**************************************************************************
|
||||
* proto.h *
|
||||
* proto.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -30,8 +29,13 @@
|
||||
extern volatile sig_atomic_t sigwinch_counter;
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && !defined(NANO_TINY)
|
||||
extern bool console;
|
||||
#endif
|
||||
|
||||
extern bool meta_key;
|
||||
extern bool func_key;
|
||||
extern bool shift_held;
|
||||
|
||||
extern bool focusing;
|
||||
|
||||
extern message_type lastmessage;
|
||||
@@ -39,6 +43,16 @@ extern message_type lastmessage;
|
||||
#ifndef NANO_TINY
|
||||
extern int controlleft;
|
||||
extern int controlright;
|
||||
extern int controlup;
|
||||
extern int controldown;
|
||||
extern int shiftcontrolleft;
|
||||
extern int shiftcontrolright;
|
||||
extern int shiftcontrolup;
|
||||
extern int shiftcontroldown;
|
||||
extern int shiftaltleft;
|
||||
extern int shiftaltright;
|
||||
extern int shiftaltup;
|
||||
extern int shiftaltdown;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
@@ -91,7 +105,10 @@ extern size_t quotelen;
|
||||
#endif
|
||||
#endif /* !DISABLE_JUSTIFY */
|
||||
|
||||
extern char *word_chars;
|
||||
|
||||
extern bool nodelay_mode;
|
||||
|
||||
extern char *answer;
|
||||
|
||||
extern ssize_t tabsize;
|
||||
@@ -142,7 +159,7 @@ extern int hilite_attribute;
|
||||
#ifndef DISABLE_COLOR
|
||||
extern char* specified_color_combo[NUMBER_OF_ELEMENTS];
|
||||
#endif
|
||||
extern color_pair interface_color_pair[NUMBER_OF_ELEMENTS];
|
||||
extern int interface_color_pair[NUMBER_OF_ELEMENTS];
|
||||
|
||||
extern char *homedir;
|
||||
|
||||
@@ -179,22 +196,17 @@ bool nisblank(int c);
|
||||
bool niswblank(wchar_t wc);
|
||||
#endif
|
||||
bool is_byte(int c);
|
||||
bool is_alpha_mbchar(const char *c);
|
||||
bool is_alnum_mbchar(const char *c);
|
||||
bool is_blank_mbchar(const char *c);
|
||||
bool is_ascii_cntrl_char(int c);
|
||||
bool is_cntrl_char(int c);
|
||||
#ifdef ENABLE_UTF8
|
||||
bool is_cntrl_wchar(wchar_t wc);
|
||||
#endif
|
||||
bool is_cntrl_mbchar(const char *c);
|
||||
bool is_punct_mbchar(const char *c);
|
||||
bool is_word_mbchar(const char *c, bool allow_punct);
|
||||
char control_rep(char c);
|
||||
#ifdef ENABLE_UTF8
|
||||
wchar_t control_wrep(wchar_t wc);
|
||||
#endif
|
||||
char *control_mbrep(const char *c, char *crep, int *crep_len);
|
||||
char *mbrep(const char *c, char *crep, int *crep_len);
|
||||
char control_rep(const signed char c);
|
||||
char control_mbrep(const char *c);
|
||||
int length_of_char(const char *c, int *width);
|
||||
int mbwidth(const char *c);
|
||||
int mb_cur_max(void);
|
||||
char *make_mbchar(long chr, int *chr_mb_len);
|
||||
@@ -320,11 +332,11 @@ int delete_lockfile(const char *lockfilename);
|
||||
int write_lockfile(const char *lockfilename, const char *origfilename, bool modified);
|
||||
#endif
|
||||
int copy_file(FILE *inn, FILE *out);
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
append, bool nonamechange);
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
kind_of_writing_type method, bool nonamechange);
|
||||
#ifndef NANO_TINY
|
||||
bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
append_type append);
|
||||
kind_of_writing_type method);
|
||||
#endif
|
||||
int do_writeout(bool exiting);
|
||||
void do_writeout_void(void);
|
||||
@@ -363,8 +375,7 @@ 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);
|
||||
functionptrtype func_from_key(int *kbinput);
|
||||
key_type strtokeytype(const char *str);
|
||||
void assign_keyinfo(sc *s);
|
||||
void assign_keyinfo(sc *s, const char *keystring);
|
||||
void print_sclist(void);
|
||||
void shortcut_init(void);
|
||||
#ifndef DISABLE_COLOR
|
||||
@@ -400,6 +411,8 @@ void do_para_end(bool allow_update);
|
||||
void do_para_end_void(void);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
void do_prev_block(void);
|
||||
void do_next_block(void);
|
||||
void do_prev_word(bool allow_punct, bool allow_update);
|
||||
void do_prev_word_void(void);
|
||||
bool do_next_word(bool allow_punct, bool allow_update);
|
||||
@@ -407,26 +420,12 @@ void do_next_word_void(void);
|
||||
#endif
|
||||
void do_home(void);
|
||||
void do_end(void);
|
||||
void do_up(
|
||||
#ifndef NANO_TINY
|
||||
bool scroll_only
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
);
|
||||
void do_up(bool scroll_only);
|
||||
void do_up_void(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_scroll_up(void);
|
||||
#endif
|
||||
void do_down(
|
||||
#ifndef NANO_TINY
|
||||
bool scroll_only
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
);
|
||||
void do_down(bool scroll_only);
|
||||
void do_down_void(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_scroll_up(void);
|
||||
void do_scroll_down(void);
|
||||
#endif
|
||||
void do_left(void);
|
||||
@@ -457,11 +456,7 @@ void say_there_is_no_help(void);
|
||||
#endif
|
||||
void finish(void);
|
||||
void die(const char *msg, ...);
|
||||
void die_save_file(const char *die_filename
|
||||
#ifndef NANO_TINY
|
||||
, struct stat *die_stat
|
||||
#endif
|
||||
);
|
||||
void die_save_file(const char *die_filename, struct stat *die_stat);
|
||||
void window_init(void);
|
||||
#ifndef DISABLE_MOUSE
|
||||
void disable_mouse_support(void);
|
||||
@@ -475,8 +470,6 @@ void print_opt_full(const char *shortflag
|
||||
, const char *desc);
|
||||
void usage(void);
|
||||
void version(void);
|
||||
int more_space(void);
|
||||
int no_help(void);
|
||||
void no_current_file_name_warning(void);
|
||||
void do_exit(void);
|
||||
void close_and_go(void);
|
||||
@@ -515,7 +508,7 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
int do_statusbar_mouse(void);
|
||||
#endif
|
||||
void do_statusbar_output(int *the_input, size_t input_len,
|
||||
bool filtering, bool *got_enter);
|
||||
bool filtering, bool *got_newline);
|
||||
void do_statusbar_home(void);
|
||||
void do_statusbar_end(void);
|
||||
void do_statusbar_left(void);
|
||||
@@ -527,22 +520,12 @@ void do_statusbar_cut_text(void);
|
||||
void do_statusbar_prev_word(void);
|
||||
void do_statusbar_next_word(void);
|
||||
#endif
|
||||
void do_statusbar_verbatim_input(bool *got_enter);
|
||||
void do_statusbar_verbatim_input(bool *got_newline);
|
||||
size_t statusbar_xplustabs(void);
|
||||
size_t get_statusbar_page_start(size_t start_col, size_t column);
|
||||
void reinit_statusbar_x(void);
|
||||
void reset_statusbar_cursor(void);
|
||||
void update_the_statusbar(void);
|
||||
void update_bar_if_needed(void);
|
||||
functionptrtype get_prompt_string(int *value, bool allow_tabs,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
bool allow_files, bool *listed,
|
||||
#endif
|
||||
const char *curranswer,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
filestruct **history_list,
|
||||
#endif
|
||||
void (*refresh_func)(void));
|
||||
int do_prompt(bool allow_tabs,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
bool allow_files,
|
||||
@@ -650,6 +633,7 @@ void do_tab(void);
|
||||
void do_indent(ssize_t cols);
|
||||
void do_indent_void(void);
|
||||
void do_unindent(void);
|
||||
bool white_string(const char *s);
|
||||
void do_undo(void);
|
||||
void do_redo(void);
|
||||
#endif
|
||||
@@ -734,7 +718,7 @@ void *nmalloc(size_t howmuch);
|
||||
void *nrealloc(void *ptr, size_t howmuch);
|
||||
char *mallocstrncpy(char *dest, const char *src, size_t n);
|
||||
char *mallocstrcpy(char *dest, const char *src);
|
||||
char *mallocstrassn(char *dest, char *src);
|
||||
char *free_and_assign(char *dest, char *src);
|
||||
size_t get_page_start(size_t column);
|
||||
size_t xplustabs(void);
|
||||
size_t actual_x(const char *s, size_t column);
|
||||
@@ -764,7 +748,7 @@ void dump_filestruct_reverse(void);
|
||||
void get_key_buffer(WINDOW *win);
|
||||
size_t get_key_buffer_len(void);
|
||||
void unget_input(int *input, size_t input_len);
|
||||
void unget_kbinput(int kbinput, bool metakey, bool funckey);
|
||||
void unget_kbinput(int kbinput, bool metakey);
|
||||
int *get_input(WINDOW *win, size_t input_len);
|
||||
int get_kbinput(WINDOW *win);
|
||||
int parse_kbinput(WINDOW *win);
|
||||
@@ -773,25 +757,24 @@ int parse_escape_sequence(WINDOW *win, int kbinput);
|
||||
int get_byte_kbinput(int kbinput);
|
||||
#ifdef ENABLE_UTF8
|
||||
long add_unicode_digit(int kbinput, long factor, long *uni);
|
||||
long get_unicode_kbinput(int kbinput);
|
||||
long get_unicode_kbinput(WINDOW *win, int kbinput);
|
||||
#endif
|
||||
int get_control_kbinput(int kbinput);
|
||||
void unparse_kbinput(char *output, size_t output_len);
|
||||
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
|
||||
int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
|
||||
int *parse_verbatim_kbinput(WINDOW *win, size_t *count);
|
||||
#ifndef DISABLE_MOUSE
|
||||
int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
|
||||
#endif
|
||||
const sc *get_shortcut(int *kbinput);
|
||||
void blank_line(WINDOW *win, int y, int x, int n);
|
||||
void blank_titlebar(void);
|
||||
void blank_topbar(void);
|
||||
void blank_edit(void);
|
||||
void blank_statusbar(void);
|
||||
void blank_bottombars(void);
|
||||
void check_statusblank(void);
|
||||
char *display_string(const char *buf, size_t start_col, size_t len, bool
|
||||
dollars);
|
||||
char *display_string(const char *buf, size_t start_col, size_t span,
|
||||
bool dollars);
|
||||
void titlebar(const char *path);
|
||||
extern void set_modified(void);
|
||||
void statusbar(const char *msg);
|
||||
@@ -802,7 +785,7 @@ void reset_cursor(void);
|
||||
void edit_draw(filestruct *fileptr, const char *converted, int
|
||||
line, size_t start);
|
||||
int update_line(filestruct *fileptr, size_t index);
|
||||
bool need_screen_update(size_t pww_save);
|
||||
bool need_horizontal_scroll(const size_t old_column, const size_t new_column);
|
||||
void edit_scroll(scroll_dir direction, ssize_t nlines);
|
||||
void edit_redraw(filestruct *old_current);
|
||||
void edit_refresh(void);
|
||||
|
||||
50
src/rcfile.c
50
src/rcfile.c
@@ -1,22 +1,23 @@
|
||||
/**************************************************************************
|
||||
* rcfile.c *
|
||||
* rcfile.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
|
||||
* 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014 Mike Frysinger *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -102,6 +103,7 @@ static const rcoption rcopts[] = {
|
||||
{"unix", MAKE_IT_UNIX},
|
||||
{"whitespace", 0},
|
||||
{"wordbounds", WORD_BOUNDS},
|
||||
{"wordchars", 0},
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
{"titlecolor", 0},
|
||||
@@ -469,20 +471,18 @@ void parse_binding(char *ptr, bool dobind)
|
||||
goto free_copy;
|
||||
}
|
||||
|
||||
newsc->keystr = keycopy;
|
||||
newsc->menus = menu;
|
||||
newsc->type = strtokeytype(newsc->keystr);
|
||||
assign_keyinfo(newsc);
|
||||
assign_keyinfo(newsc, keycopy);
|
||||
|
||||
/* Do not allow rebinding the equivalent of the Escape key. */
|
||||
if (newsc->type == META && newsc->seq == 91) {
|
||||
/* Do not allow rebinding a frequent escape-sequence starter: Esc [. */
|
||||
if (newsc->meta && newsc->keycode == 91) {
|
||||
rcfile_error(N_("Sorry, keystroke \"%s\" may not be rebound"), newsc->keystr);
|
||||
free(newsc);
|
||||
goto free_copy;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "s->keystr = \"%s\"\n", newsc->keystr);
|
||||
fprintf(stderr, "s->seq = \"%d\"\n", newsc->seq);
|
||||
fprintf(stderr, "s->keycode = \"%d\"\n", newsc->keycode);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -657,7 +657,7 @@ void parse_colors(char *ptr, int rex_flags)
|
||||
/* Now for the fun part. Start adding regexes to individual strings
|
||||
* in the colorstrings array, woo! */
|
||||
while (ptr != NULL && *ptr != '\0') {
|
||||
colortype *newcolor;
|
||||
colortype *newcolor = NULL;
|
||||
/* The container for a color plus its regexes. */
|
||||
bool goodstart;
|
||||
/* Whether the start expression was valid. */
|
||||
@@ -1067,7 +1067,8 @@ void parse_rcfile(FILE *rcstream
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "parse_rcfile(): option name = \"%s\"\n", rcopts[i].name);
|
||||
fprintf(stderr, " Option name = \"%s\"\n", rcopts[i].name);
|
||||
fprintf(stderr, " Flag = %ld\n", rcopts[i].flag);
|
||||
#endif
|
||||
/* First handle unsetting. */
|
||||
if (set == -1) {
|
||||
@@ -1098,7 +1099,7 @@ void parse_rcfile(FILE *rcstream
|
||||
|
||||
option = mallocstrcpy(NULL, option);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "option argument = \"%s\"\n", option);
|
||||
fprintf(stderr, " Option argument = \"%s\"\n", option);
|
||||
#endif
|
||||
/* Make sure the option argument is a valid multibyte string. */
|
||||
if (!is_valid_mbstring(option)) {
|
||||
@@ -1176,6 +1177,9 @@ void parse_rcfile(FILE *rcstream
|
||||
if (strcasecmp(rcopts[i].name, "backupdir") == 0)
|
||||
backup_dir = option;
|
||||
else
|
||||
if (strcasecmp(rcopts[i].name, "wordchars") == 0)
|
||||
word_chars = option;
|
||||
else
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
if (strcasecmp(rcopts[i].name, "speller") == 0)
|
||||
@@ -1191,10 +1195,6 @@ void parse_rcfile(FILE *rcstream
|
||||
free(option);
|
||||
} else
|
||||
assert(FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "flag = %ld\n", rcopts[i].flag);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
|
||||
137
src/search.c
137
src/search.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* search.c *
|
||||
* search.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -104,7 +104,6 @@ void not_found_msg(const char *str)
|
||||
* search, if any. */
|
||||
void search_replace_abort(void)
|
||||
{
|
||||
display_main_list();
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set)
|
||||
edit_refresh();
|
||||
@@ -156,32 +155,32 @@ int search_init(bool replacing, bool use_answer)
|
||||
/* This is now one simple call. It just does a lot. */
|
||||
i = do_prompt(FALSE,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
TRUE,
|
||||
TRUE,
|
||||
#endif
|
||||
replacing ? MREPLACE : MWHEREIS, backupstring,
|
||||
replacing ? MREPLACE : MWHEREIS, backupstring,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
&search_history,
|
||||
&search_history,
|
||||
#endif
|
||||
/* TRANSLATORS: This is the main search prompt. */
|
||||
edit_refresh, "%s%s%s%s%s%s", _("Search"),
|
||||
/* TRANSLATORS: This is the main search prompt. */
|
||||
edit_refresh, "%s%s%s%s%s%s", _("Search"),
|
||||
#ifndef NANO_TINY
|
||||
/* TRANSLATORS: The next three strings are modifiers of the search prompt. */
|
||||
ISSET(CASE_SENSITIVE) ? _(" [Case Sensitive]") :
|
||||
/* TRANSLATORS: The next three modify the search prompt. */
|
||||
ISSET(CASE_SENSITIVE) ? _(" [Case Sensitive]") :
|
||||
#endif
|
||||
"",
|
||||
"",
|
||||
#ifdef HAVE_REGEX_H
|
||||
ISSET(USE_REGEXP) ? _(" [Regexp]") :
|
||||
ISSET(USE_REGEXP) ? _(" [Regexp]") :
|
||||
#endif
|
||||
"",
|
||||
"",
|
||||
#ifndef NANO_TINY
|
||||
ISSET(BACKWARDS_SEARCH) ? _(" [Backwards]") :
|
||||
ISSET(BACKWARDS_SEARCH) ? _(" [Backwards]") :
|
||||
#endif
|
||||
"", replacing ?
|
||||
"", replacing ?
|
||||
#ifndef NANO_TINY
|
||||
/* TRANSLATORS: The next two strings are modifiers of the search prompt. */
|
||||
openfile->mark_set ? _(" (to replace) in selection") :
|
||||
/* TRANSLATORS: The next two modify the search prompt. */
|
||||
openfile->mark_set ? _(" (to replace) in selection") :
|
||||
#endif
|
||||
_(" (to replace)") : "", buf);
|
||||
_(" (to replace)") : "", buf);
|
||||
|
||||
/* Release buf now that we don't need it anymore. */
|
||||
free(buf);
|
||||
@@ -302,6 +301,8 @@ int findnextstr(
|
||||
}
|
||||
|
||||
if (++feedback > 0)
|
||||
/* TRANSLATORS: This is shown when searching takes
|
||||
* more than half a second. */
|
||||
statusbar(_("Searching..."));
|
||||
}
|
||||
|
||||
@@ -493,6 +494,9 @@ void go_looking(void)
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_current_x = openfile->current_x;
|
||||
int didfind;
|
||||
#ifdef DEBUG
|
||||
clock_t start = clock();
|
||||
#endif
|
||||
|
||||
came_full_circle = FALSE;
|
||||
|
||||
@@ -508,6 +512,10 @@ void go_looking(void)
|
||||
openfile->current_x == was_current_x)
|
||||
statusbar(_("This is the only occurrence"));
|
||||
|
||||
#ifdef DEBUG
|
||||
statusline(HUSH, "Took: %.2f", (double)(clock() - start) / CLOCKS_PER_SEC);
|
||||
#endif
|
||||
|
||||
edit_redraw(was_current);
|
||||
search_replace_abort();
|
||||
}
|
||||
@@ -599,14 +607,12 @@ char *replace_line(const char *needle)
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* Step through each replace word and prompt user before replacing.
|
||||
* Parameters real_current and real_current_x are needed in order to
|
||||
/* Step through each occurrence of the search string and prompt the user
|
||||
* before replacing it. We seek for needle, and replace it with answer.
|
||||
* The parameters real_current and real_current_x are needed in order to
|
||||
* allow the cursor position to be updated when a word before the cursor
|
||||
* is replaced by a shorter word.
|
||||
*
|
||||
* needle is the string to seek. We replace it with answer. Return -1
|
||||
* if needle isn't found, else the number of replacements performed. If
|
||||
* canceled isn't NULL, set it to TRUE if we canceled. */
|
||||
* is replaced by a shorter word. Return -1 if needle isn't found, -2 if
|
||||
* the seeking is aborted, else the number of replacements performed. */
|
||||
ssize_t do_replace_loop(
|
||||
#ifndef DISABLE_SPELLER
|
||||
bool whole_word_only,
|
||||
@@ -625,10 +631,10 @@ ssize_t do_replace_loop(
|
||||
/* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
|
||||
* FALSE if (current, current_x) is. */
|
||||
|
||||
/* If the mark is on, frame the region, and turn the mark off. */
|
||||
if (old_mark_set) {
|
||||
/* If the mark is on, frame the region, and turn the mark off. */
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
openfile->mark_set = FALSE;
|
||||
|
||||
/* Start either at the top or the bottom of the marked region. */
|
||||
@@ -744,15 +750,13 @@ ssize_t do_replace_loop(
|
||||
}
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
/* Don't find the same zero-length match again. */
|
||||
if (match_len == 0)
|
||||
/* Don't find the same zero-length or BOL match again. */
|
||||
if (match_len == 0 || (*needle == '^' && ISSET(USE_REGEXP)))
|
||||
match_len++;
|
||||
#endif
|
||||
|
||||
/* Set the cursor at the last character of the replacement
|
||||
* text, so searching will resume after the replacement
|
||||
* text. Note that current_x might be set to (size_t)-1
|
||||
* here. */
|
||||
* text, so that searching will continue /after/ it. Note
|
||||
* that current_x might be set to (size_t)-1 here. */
|
||||
#ifndef NANO_TINY
|
||||
if (!ISSET(BACKWARDS_SEARCH))
|
||||
#endif
|
||||
@@ -830,14 +834,14 @@ void do_replace(void)
|
||||
|
||||
i = do_prompt(FALSE,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
TRUE,
|
||||
TRUE,
|
||||
#endif
|
||||
MREPLACEWITH, NULL,
|
||||
MREPLACEWITH, NULL,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
&replace_history,
|
||||
&replace_history,
|
||||
#endif
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
edit_refresh, _("Replace with"));
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
edit_refresh, _("Replace with"));
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
/* If the replace string is not "", add it to the replace history list. */
|
||||
@@ -913,31 +917,27 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
edit_refresh, _("Enter line number, column number"));
|
||||
|
||||
/* Cancel, or Enter with blank string. */
|
||||
/* If the user cancelled or gave a blank answer, get out. */
|
||||
if (i < 0) {
|
||||
statusbar(_("Cancelled"));
|
||||
display_main_list();
|
||||
return;
|
||||
}
|
||||
|
||||
func = func_from_key(&i);
|
||||
|
||||
if (func == gototext_void) {
|
||||
/* Keep answer up on the statusbar. */
|
||||
/* Retain what the user typed so far and switch to searching. */
|
||||
search_init(TRUE, TRUE);
|
||||
|
||||
do_search();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do a bounds check. Display a warning on an out-of-bounds
|
||||
* line or column number only if we hit Enter at the statusbar
|
||||
* prompt. */
|
||||
if (!parse_line_column(answer, &line, &column) ||
|
||||
line < 1 || column < 1) {
|
||||
if (i == 0)
|
||||
statusbar(_("Invalid line or column number"));
|
||||
display_main_list();
|
||||
/* If a function was executed, we're done here. */
|
||||
if (i > 0)
|
||||
return;
|
||||
|
||||
/* Try to extract one or two numbers from the user's response. */
|
||||
if (!parse_line_column(answer, &line, &column)) {
|
||||
statusbar(_("Invalid line or column number"));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -948,10 +948,24 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
column = openfile->placewewant + 1;
|
||||
}
|
||||
|
||||
/* Take a negative line number to mean: from the end of the file. */
|
||||
if (line < 0)
|
||||
line = openfile->filebot->lineno + line + 1;
|
||||
if (line < 1)
|
||||
line = 1;
|
||||
|
||||
/* Iterate to the requested line. */
|
||||
for (openfile->current = openfile->fileage; line > 1 &&
|
||||
openfile->current != openfile->filebot; line--)
|
||||
openfile->current = openfile->current->next;
|
||||
|
||||
/* Take a negative column number to mean: from the end of the line. */
|
||||
if (column < 0)
|
||||
column = strlenpt(openfile->current->data) + column + 2;
|
||||
if (column < 1)
|
||||
column = 1;
|
||||
|
||||
/* Set the x position that corresponds to the requested column. */
|
||||
openfile->current_x = actual_x(openfile->current->data, column - 1);
|
||||
openfile->placewewant = column - 1;
|
||||
|
||||
@@ -959,7 +973,6 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
if (interactive) {
|
||||
edit_update(CENTERING);
|
||||
edit_refresh();
|
||||
display_main_list();
|
||||
} else {
|
||||
/* If the target line is close to the tail of the file, put the last
|
||||
* line of the file on the bottom line of the screen; otherwise, just
|
||||
|
||||
114
src/text.c
114
src/text.c
@@ -1,22 +1,24 @@
|
||||
/**************************************************************************
|
||||
* text.c *
|
||||
* text.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015 Mark Majeres *
|
||||
* Copyright (C) 2016 Mike Scalora *
|
||||
* Copyright (C) 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -49,16 +51,18 @@ static filestruct *jusbottom = NULL;
|
||||
void do_mark(void)
|
||||
{
|
||||
openfile->mark_set = !openfile->mark_set;
|
||||
|
||||
if (openfile->mark_set) {
|
||||
statusbar(_("Mark Set"));
|
||||
openfile->mark_begin = openfile->current;
|
||||
openfile->mark_begin_x = openfile->current_x;
|
||||
openfile->kind_of_mark = HARDMARK;
|
||||
} else {
|
||||
statusbar(_("Mark Unset"));
|
||||
openfile->mark_begin = NULL;
|
||||
openfile->mark_begin_x = 0;
|
||||
edit_refresh();
|
||||
}
|
||||
edit_refresh();
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
@@ -247,25 +251,18 @@ void do_tab(void)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(TABS_TO_SPACES)) {
|
||||
char *output;
|
||||
size_t output_len = 0, new_pww = xplustabs();
|
||||
char *spaces = charalloc(tabsize + 1);
|
||||
size_t length = tabsize - (xplustabs() % tabsize);
|
||||
|
||||
do {
|
||||
new_pww++;
|
||||
output_len++;
|
||||
} while (new_pww % tabsize != 0);
|
||||
charset(spaces, ' ', length);
|
||||
spaces[length] = '\0';
|
||||
|
||||
output = charalloc(output_len + 1);
|
||||
do_output(spaces, length, TRUE);
|
||||
|
||||
charset(output, ' ', output_len);
|
||||
output[output_len] = '\0';
|
||||
|
||||
do_output(output, output_len, TRUE);
|
||||
|
||||
free(output);
|
||||
free(spaces);
|
||||
} else
|
||||
#endif
|
||||
do_output((char *) "\t", 1, TRUE);
|
||||
do_output((char *)"\t", 1, TRUE);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -306,7 +303,7 @@ void do_indent(ssize_t cols)
|
||||
/* If the mark is on, use all lines covered by the mark. */
|
||||
if (openfile->mark_set)
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
/* Otherwise, use the current line. */
|
||||
else {
|
||||
top = openfile->current;
|
||||
@@ -472,8 +469,8 @@ void do_comment()
|
||||
|
||||
/* Determine which lines to work on. */
|
||||
if (openfile->mark_set)
|
||||
mark_order((const filestruct **) &top, &top_x,
|
||||
(const filestruct **) &bot, &bot_x, NULL);
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
else {
|
||||
top = openfile->current;
|
||||
bot = top;
|
||||
@@ -2037,7 +2034,7 @@ void backup_lines(filestruct *first_line, size_t par_len)
|
||||
* current and filebot if filebot is the last line in the
|
||||
* paragraph. */
|
||||
assert(par_len > 0 && openfile->current->lineno + par_len <=
|
||||
openfile->filebot->lineno + 1);
|
||||
openfile->filebot->lineno + 1);
|
||||
|
||||
/* Move bot down par_len lines to the line after the last line of
|
||||
* the paragraph, if there is one. */
|
||||
@@ -2047,7 +2044,7 @@ void backup_lines(filestruct *first_line, size_t par_len)
|
||||
/* Move the paragraph from the current buffer's filestruct to the
|
||||
* justify buffer. */
|
||||
move_to_filestruct(&jusbuffer, &jusbottom, top, 0, bot,
|
||||
(i == 1 && bot == openfile->filebot) ? strlen(bot->data) : 0);
|
||||
(i == 1 && bot == openfile->filebot) ? strlen(bot->data) : 0);
|
||||
|
||||
/* Copy the paragraph back to the current buffer's filestruct from
|
||||
* the justify buffer. */
|
||||
@@ -2524,8 +2521,8 @@ void do_justify(bool full_justify)
|
||||
/* Partition the filestruct so that it contains only the
|
||||
* text of the justified paragraph. */
|
||||
filepart = partition_filestruct(first_par_line, 0,
|
||||
last_par_line, filebot_inpar ?
|
||||
strlen(last_par_line->data) : 0);
|
||||
last_par_line, filebot_inpar ?
|
||||
strlen(last_par_line->data) : 0);
|
||||
|
||||
/* Remove the text of the justified paragraph, and
|
||||
* replace it with the text in the justify buffer. */
|
||||
@@ -2566,7 +2563,7 @@ void do_justify(bool full_justify)
|
||||
}
|
||||
} else {
|
||||
/* Put the keystroke back into the queue. */
|
||||
unget_kbinput(kbinput, meta_key, func_key);
|
||||
unget_kbinput(kbinput, meta_key);
|
||||
|
||||
/* Set the desired screen column (always zero, except at EOF). */
|
||||
openfile->placewewant = xplustabs();
|
||||
@@ -2650,7 +2647,7 @@ bool do_int_spell_fix(const char *word)
|
||||
/* If the mark is on, start at the beginning of the marked region. */
|
||||
if (old_mark_set) {
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
/* If the region is marked normally, swap the end points, so that
|
||||
* (current, current_x) (where searching starts) is at the top. */
|
||||
if (right_side_up) {
|
||||
@@ -2673,14 +2670,15 @@ bool do_int_spell_fix(const char *word)
|
||||
/* Find the first whole occurrence of word. */
|
||||
result = findnextstr(TRUE, NULL, 0, word, NULL);
|
||||
|
||||
/* The word must exist; if not, something is wrong. */
|
||||
if (result == 0)
|
||||
statusline(ALERT, "Internal error: "
|
||||
"speller listed unfindable word: %s", word);
|
||||
else if (result == 1) {
|
||||
/* If the word isn't found, alert the user; if it is, allow correction. */
|
||||
if (result == 0) {
|
||||
statusline(ALERT, _("Unfindable word: %s"), word);
|
||||
lastmessage = HUSH;
|
||||
proceed = TRUE;
|
||||
napms(2800);
|
||||
} else if (result == 1) {
|
||||
exp_word = display_string(openfile->current->data, xplustabs(),
|
||||
strlenpt(word), FALSE);
|
||||
|
||||
edit_refresh();
|
||||
|
||||
spotlight(TRUE, exp_word);
|
||||
@@ -2933,6 +2931,7 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
{
|
||||
int alt_spell_status;
|
||||
size_t current_x_save = openfile->current_x;
|
||||
size_t pww_save = openfile->placewewant;
|
||||
ssize_t current_y_save = openfile->current_y;
|
||||
ssize_t lineno_save = openfile->current->lineno;
|
||||
struct stat spellfileinfo;
|
||||
@@ -3030,7 +3029,7 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
if (old_mark_set) {
|
||||
/* Trim the filestruct so that it contains only the marked text. */
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
||||
|
||||
/* Foresay whether a magicline will be added when the
|
||||
@@ -3081,6 +3080,7 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
/* Go back to the old position. */
|
||||
goto_line_posx(lineno_save, current_x_save);
|
||||
openfile->current_y = current_y_save;
|
||||
openfile->placewewant = pww_save;
|
||||
edit_update(STATIONARY);
|
||||
|
||||
/* Stat the temporary file again, and mark the buffer as modified only
|
||||
@@ -3114,7 +3114,7 @@ void do_spell(void)
|
||||
temp = safe_tempfile(&temp_file);
|
||||
|
||||
if (temp == NULL) {
|
||||
statusline(HUSH, _("Error writing temp file: %s"), strerror(errno));
|
||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3126,7 +3126,7 @@ void do_spell(void)
|
||||
status = write_file(temp, temp_file, TRUE, OVERWRITE, FALSE);
|
||||
|
||||
if (!status) {
|
||||
statusline(HUSH, _("Error writing temp file: %s"), strerror(errno));
|
||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||
free(temp);
|
||||
return;
|
||||
}
|
||||
@@ -3139,8 +3139,6 @@ void do_spell(void)
|
||||
unlink(temp);
|
||||
free(temp);
|
||||
|
||||
currmenu = MMAIN;
|
||||
|
||||
/* If the spell-checker printed any error messages onscreen, make
|
||||
* sure that they're cleared off. */
|
||||
total_refresh();
|
||||
@@ -3187,16 +3185,16 @@ void do_linter(void)
|
||||
|
||||
if (i == -1) {
|
||||
statusbar(_("Cancelled"));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
} else if (i == 1 && (do_writeout(FALSE) != TRUE))
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
lintcopy = mallocstrcpy(NULL, openfile->syntax->linter);
|
||||
/* Create a pipe up front. */
|
||||
if (pipe(lint_fd) == -1) {
|
||||
statusbar(_("Could not create pipe"));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
blank_bottombars();
|
||||
@@ -3244,14 +3242,14 @@ void do_linter(void)
|
||||
if (pid_lint < 0) {
|
||||
close(lint_fd[0]);
|
||||
statusbar(_("Could not fork"));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the system pipe buffer size. */
|
||||
if ((pipe_buff_size = fpathconf(lint_fd[0], _PC_PIPE_BUF)) < 1) {
|
||||
close(lint_fd[0]);
|
||||
statusbar(_("Could not get size of pipe buffer"));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read in the returned syntax errors. */
|
||||
@@ -3349,7 +3347,7 @@ void do_linter(void)
|
||||
|
||||
if (!WIFEXITED(lint_status) || WEXITSTATUS(lint_status) > 2) {
|
||||
statusbar(invocation_error(openfile->syntax->linter));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
free(read_buff);
|
||||
@@ -3357,7 +3355,7 @@ void do_linter(void)
|
||||
if (parsesuccess == 0) {
|
||||
statusline(HUSH, _("Got 0 parsable lines from command: %s"),
|
||||
openfile->syntax->linter);
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
bottombars(MLINTER);
|
||||
@@ -3421,8 +3419,9 @@ void do_linter(void)
|
||||
bottombars(MLINTER);
|
||||
}
|
||||
|
||||
/* Show the cursor to indicate the affected line. */
|
||||
/* Place and show the cursor to indicate the affected line. */
|
||||
reset_cursor();
|
||||
wnoutrefresh(edit);
|
||||
curs_set(1);
|
||||
|
||||
kbinput = get_kbinput(bottomwin);
|
||||
@@ -3464,9 +3463,6 @@ void do_linter(void)
|
||||
free(tmplint->filename);
|
||||
free(tmplint);
|
||||
}
|
||||
|
||||
exit_from_lint:
|
||||
display_main_list();
|
||||
}
|
||||
|
||||
#ifndef DISABLE_SPELLER
|
||||
@@ -3606,7 +3602,7 @@ void do_wordlinechar_count(void)
|
||||
* contains only the marked text, and turn the mark off. */
|
||||
if (old_mark_set) {
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
||||
openfile->mark_set = FALSE;
|
||||
}
|
||||
|
||||
94
src/utils.c
94
src/utils.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* utils.c *
|
||||
* utils.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -77,35 +77,33 @@ bool parse_num(const char *str, ssize_t *val)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read two ssize_t's, separated by a comma, from str, and store them in
|
||||
* *line and *column (if they're not both NULL). Return FALSE on error,
|
||||
* or TRUE otherwise. */
|
||||
/* Read two numbers, separated by a comma, from str, and store them in
|
||||
* *line and *column. Return FALSE on error, and TRUE otherwise. */
|
||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
|
||||
{
|
||||
bool retval = TRUE;
|
||||
bool retval;
|
||||
char *firstpart;
|
||||
const char *comma;
|
||||
|
||||
assert(str != NULL);
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
|
||||
comma = strchr(str, ',');
|
||||
comma = strpbrk(str, "m,. /;");
|
||||
|
||||
if (comma != NULL && column != NULL) {
|
||||
if (!parse_num(comma + 1, column))
|
||||
retval = FALSE;
|
||||
}
|
||||
if (comma == NULL)
|
||||
return parse_num(str, line);
|
||||
|
||||
if (line != NULL) {
|
||||
if (comma != NULL) {
|
||||
char *str_line = mallocstrncpy(NULL, str, comma - str + 1);
|
||||
str_line[comma - str] = '\0';
|
||||
if (!parse_num(comma + 1, column))
|
||||
return FALSE;
|
||||
|
||||
if (str_line[0] != '\0' && !parse_num(str_line, line))
|
||||
retval = FALSE;
|
||||
if (comma == str)
|
||||
return TRUE;
|
||||
|
||||
free(str_line);
|
||||
} else if (!parse_num(str, line))
|
||||
retval = FALSE;
|
||||
}
|
||||
firstpart = mallocstrcpy(NULL, str);
|
||||
firstpart[comma - str] = '\0';
|
||||
|
||||
retval = parse_num(firstpart, line);
|
||||
free(firstpart);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -292,12 +290,11 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
|
||||
parse_mbchar(buf + move_mbleft(buf, position), before, NULL);
|
||||
parse_mbchar(buf + word_end, after, NULL);
|
||||
|
||||
/* If we're at the beginning of the line or the character before the
|
||||
* word isn't a non-punctuation "word" character, and if we're at
|
||||
* the end of the line or the character after the word isn't a
|
||||
* non-punctuation "word" character, we have a whole word. */
|
||||
retval = (position == 0 || !is_word_mbchar(before, FALSE)) &&
|
||||
(word_end == strlen(buf) || !is_word_mbchar(after, FALSE));
|
||||
/* 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);
|
||||
@@ -406,8 +403,8 @@ void *nrealloc(void *ptr, size_t howmuch)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Copy the first n characters of one malloc()ed string to another
|
||||
* pointer. Should be used as: "dest = mallocstrncpy(dest, src, n);". */
|
||||
/* Allocate and copy the first n characters of the given src string, after
|
||||
* freeing the destination. Usage: "dest = mallocstrncpy(dest, src, n);". */
|
||||
char *mallocstrncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
if (src == NULL)
|
||||
@@ -422,17 +419,15 @@ char *mallocstrncpy(char *dest, const char *src, size_t n)
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Copy one malloc()ed string to another pointer. Should be used as:
|
||||
/* Free the dest string and return a malloc'ed copy of src. Should be used as:
|
||||
* "dest = mallocstrcpy(dest, src);". */
|
||||
char *mallocstrcpy(char *dest, const char *src)
|
||||
{
|
||||
return mallocstrncpy(dest, src, (src == NULL) ? 1 : strlen(src) + 1);
|
||||
}
|
||||
|
||||
/* Free the malloc()ed string at dest and return the malloc()ed string
|
||||
* at src. Should be used as: "answer = mallocstrassn(answer,
|
||||
* real_dir_from_tilde(answer));". */
|
||||
char *mallocstrassn(char *dest, char *src)
|
||||
/* Free the string at dest and return the string at src. */
|
||||
char *free_and_assign(char *dest, char *src)
|
||||
{
|
||||
free(dest);
|
||||
return src;
|
||||
@@ -539,8 +534,9 @@ void new_magicline(void)
|
||||
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->fileage) {
|
||||
assert(openfile->filebot != openfile->edittop &&
|
||||
openfile->filebot != openfile->current);
|
||||
|
||||
openfile->filebot = openfile->filebot->prev;
|
||||
free_filestruct(openfile->filebot->next);
|
||||
@@ -560,8 +556,8 @@ void mark_order(const filestruct **top, size_t *top_x, const filestruct
|
||||
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) {
|
||||
openfile->current_x > openfile->mark_begin_x) ||
|
||||
openfile->current->lineno > openfile->mark_begin->lineno) {
|
||||
*top = openfile->mark_begin;
|
||||
*top_x = openfile->mark_begin_x;
|
||||
*bot = openfile->current;
|
||||
|
||||
1598
src/winio.c
1598
src/winio.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user