Compare commits
188 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 |
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.
|
||||
|
||||
10
IMPROVEMENTS
10
IMPROVEMENTS
@@ -1,7 +1,13 @@
|
||||
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
|
||||
|
||||
48
NEWS
48
NEWS
@@ -1,3 +1,33 @@
|
||||
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),
|
||||
@@ -22,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)
|
||||
@@ -148,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!
|
||||
@@ -184,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
|
||||
@@ -464,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
|
||||
@@ -486,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
|
||||
@@ -599,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
|
||||
@@ -937,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,
|
||||
@@ -1166,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!"
|
||||
|
||||
6
README
6
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
|
||||
|
||||
@@ -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.1], [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
|
||||
|
||||
16
doc/faq.html
16
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>
|
||||
@@ -88,7 +88,7 @@
|
||||
<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="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 web sites:</p>
|
||||
<ul>
|
||||
@@ -221,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>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANO 1 "version 2.6.1" "June 2016"
|
||||
.TH NANO 1 "version 2.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.
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANORC 5 "version 2.6.1" "June 2016"
|
||||
.TH NANORC 5 "version 2.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
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 2.6.1" "June 2016"
|
||||
.TH RNANO 1 "version 2.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.
|
||||
|
||||
@@ -20,7 +20,7 @@ color red "[a-z_]+!"
|
||||
color magenta "[A-Z][A-Z_0-9]+"
|
||||
|
||||
# Traits/Enums/Structs/Types/...
|
||||
color magenta "[A-Z][a-z0-9]+"
|
||||
color magenta "[A-Z][A-Za-z0-9]+"
|
||||
|
||||
# Strings
|
||||
color green "\".*\""
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
@smallbook
|
||||
@set EDITION 0.4
|
||||
@set VERSION 2.6.1
|
||||
@set UPDATED June 2016
|
||||
@set VERSION 2.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.1
|
||||
@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.
|
||||
|
||||
@@ -1473,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}
|
||||
|
||||
@@ -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
|
||||
|
||||
1030
po/nano.pot
1030
po/nano.pot
File diff suppressed because it is too large
Load Diff
999
po/pt_BR.po
999
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
983
po/zh_CN.po
983
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
990
po/zh_TW.po
990
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 \
|
||||
|
||||
179
src/browser.c
179
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;
|
||||
|
||||
free(newpath);
|
||||
newpath = NULL;
|
||||
present_path = mallocstrcpy(present_path, path);
|
||||
|
||||
titlebar(path);
|
||||
|
||||
while (TRUE) {
|
||||
struct stat st;
|
||||
int i;
|
||||
|
||||
/* Make sure that the cursor is off. */
|
||||
curs_set(0);
|
||||
lastmessage = HUSH;
|
||||
|
||||
bottombars(MBROWSER);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH) {
|
||||
/* Remember the selected file, to be able to reselect it. */
|
||||
present_name = strdup(filelist[selected]);
|
||||
|
||||
/* Reopen the current directory. */
|
||||
dir = opendir(path);
|
||||
if (dir != NULL)
|
||||
goto read_directory_contents;
|
||||
|
||||
statusline(ALERT, _("Error reading %s: %s"), path, strerror(errno));
|
||||
kbinput = ERR;
|
||||
}
|
||||
#endif
|
||||
/* Display (or redisplay) the file list if we don't have a key yet,
|
||||
* or the list has changed, or the selected file has changed. */
|
||||
if (kbinput == ERR || old_selected != selected)
|
||||
/* Display (or redisplay) the file list if the list itself or
|
||||
* the selected file has changed. */
|
||||
if (old_selected != selected)
|
||||
browser_refresh();
|
||||
|
||||
old_selected = selected;
|
||||
|
||||
kbinput = get_kbinput(edit);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_MOUSE
|
||||
if (kbinput == KEY_MOUSE) {
|
||||
int mouse_x, mouse_y;
|
||||
@@ -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
|
||||
@@ -245,6 +230,7 @@ char *do_browser(char *path)
|
||||
#endif
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
browser_refresh, _("Go To Directory"));
|
||||
|
||||
/* If the directory begins with a newline (i.e. an
|
||||
* encoded null), treat it as though it's blank. */
|
||||
if (i < 0 || *answer == '\n') {
|
||||
@@ -256,55 +242,41 @@ char *do_browser(char *path)
|
||||
sunder(answer);
|
||||
align(&answer);
|
||||
|
||||
newpath = real_dir_from_tilde(answer);
|
||||
path = free_and_assign(path, real_dir_from_tilde(answer));
|
||||
|
||||
if (newpath[0] != '/') {
|
||||
newpath = charealloc(newpath, strlen(path) +
|
||||
strlen(answer) + 1);
|
||||
sprintf(newpath, "%s%s", path, answer);
|
||||
/* If the given path is relative, join it with the current path. */
|
||||
if (*path != '/') {
|
||||
path = charealloc(path, strlen(present_path) +
|
||||
strlen(answer) + 1);
|
||||
sprintf(path, "%s%s", present_path, answer);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
if (check_operating_dir(newpath, FALSE)) {
|
||||
if (check_operating_dir(path, FALSE)) {
|
||||
/* TRANSLATORS: This refers to the confining effect of the
|
||||
* option --operatingdir, not of --restricted. */
|
||||
statusline(ALERT, _("Can't go outside of %s"),
|
||||
full_operating_dir);
|
||||
free(newpath);
|
||||
newpath = NULL;
|
||||
path = mallocstrcpy(path, present_path);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Snip any trailing slashes, so the name can be compared. */
|
||||
while (strlen(path) > 1 && path[strlen(path) - 1] == '/')
|
||||
path[strlen(path) - 1] = '\0';
|
||||
|
||||
/* In case the specified directory cannot be entered, select it
|
||||
* (if it is in the current list) so it will be highlighted. */
|
||||
for (i = 0; i < filelist_len; i++)
|
||||
if (strcmp(filelist[i], newpath) == 0)
|
||||
if (strcmp(filelist[i], path) == 0)
|
||||
selected = i;
|
||||
|
||||
/* Try opening and reading the specified directory. */
|
||||
goto read_directory_contents;
|
||||
} else if (func == do_up_void) {
|
||||
if (selected >= width)
|
||||
selected -= width;
|
||||
} else if (func == do_down_void) {
|
||||
if (selected + width <= filelist_len - 1)
|
||||
selected += width;
|
||||
#ifndef NANO_TINY
|
||||
} else if (func == do_prev_word_void) {
|
||||
selected -= (selected % width);
|
||||
} else if (func == do_next_word_void) {
|
||||
selected += width - 1 - (selected % width);
|
||||
if (selected >= filelist_len)
|
||||
selected = filelist_len - 1;
|
||||
#endif
|
||||
} else if (func == do_left) {
|
||||
if (selected > 0)
|
||||
selected--;
|
||||
} else if (func == do_right) {
|
||||
if (selected < filelist_len - 1)
|
||||
selected++;
|
||||
} else if (func == do_enter) {
|
||||
/* We can't move up from "/". */
|
||||
struct stat st;
|
||||
|
||||
/* It isn't possible to move up from the root directory. */
|
||||
if (strcmp(filelist[selected], "/..") == 0) {
|
||||
statusline(ALERT, _("Can't move up a directory"));
|
||||
continue;
|
||||
@@ -320,16 +292,15 @@ char *do_browser(char *path)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If for some reason the file is inaccessible, complain. */
|
||||
if (stat(filelist[selected], &st) == -1) {
|
||||
/* We can't open this file for some reason. Complain. */
|
||||
statusline(ALERT, _("Error reading %s: %s"),
|
||||
filelist[selected], strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If it isn't a directory, a file was selected -- we're done. */
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
/* We've successfully opened a file, so we're done. */
|
||||
retval = mallocstrcpy(NULL, filelist[selected]);
|
||||
break;
|
||||
}
|
||||
@@ -340,13 +311,27 @@ char *do_browser(char *path)
|
||||
present_name = striponedir(filelist[selected]);
|
||||
|
||||
/* Try opening and reading the selected directory. */
|
||||
newpath = strdup(filelist[selected]);
|
||||
path = mallocstrcpy(path, filelist[selected]);
|
||||
goto read_directory_contents;
|
||||
} else if (func == do_exit) {
|
||||
/* Exit from the file browser. */
|
||||
break;
|
||||
#ifndef NANO_TINY
|
||||
} else if (kbinput == KEY_WINCH) {
|
||||
;
|
||||
#endif
|
||||
} else
|
||||
unbound_key(kbinput);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the window resized, refresh the file list. */
|
||||
if (kbinput == KEY_WINCH) {
|
||||
/* Remember the selected file, to be able to reselect it. */
|
||||
present_name = mallocstrcpy(NULL, filelist[selected]);
|
||||
/* Reread the contents of the current directory. */
|
||||
goto read_directory_contents;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
titlebar(NULL);
|
||||
@@ -381,7 +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);
|
||||
@@ -695,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);
|
||||
|
||||
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/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
158
src/files.c
158
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);
|
||||
@@ -827,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)
|
||||
@@ -1076,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, "./");
|
||||
@@ -1108,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
|
||||
"./");
|
||||
|
||||
@@ -1226,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);
|
||||
@@ -1695,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
|
||||
@@ -1769,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;
|
||||
@@ -1948,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;
|
||||
|
||||
@@ -1965,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;
|
||||
}
|
||||
@@ -1987,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;
|
||||
@@ -1997,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);
|
||||
|
||||
@@ -2006,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;
|
||||
@@ -2040,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;
|
||||
@@ -2057,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;
|
||||
@@ -2067,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;
|
||||
@@ -2079,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;
|
||||
|
||||
@@ -2099,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);
|
||||
@@ -2125,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
|
||||
}
|
||||
|
||||
@@ -2166,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;
|
||||
@@ -2190,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)
|
||||
@@ -2216,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');
|
||||
@@ -2252,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, "./");
|
||||
@@ -2334,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;
|
||||
@@ -2362,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;
|
||||
@@ -2451,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;
|
||||
}
|
||||
|
||||
185
src/global.c
185
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? */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
402
src/nano.c
402
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>
|
||||
@@ -602,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;
|
||||
@@ -691,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)) {
|
||||
@@ -724,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
|
||||
@@ -859,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))
|
||||
@@ -918,9 +929,9 @@ 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");
|
||||
@@ -1040,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. */
|
||||
@@ -1297,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();
|
||||
@@ -1547,15 +1542,29 @@ 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
|
||||
@@ -1569,7 +1578,7 @@ int do_input(bool allow_funcs)
|
||||
{
|
||||
int input;
|
||||
/* The keystroke we read in: a character or a shortcut. */
|
||||
static int *puddle = NULL;
|
||||
static char *puddle = NULL;
|
||||
/* The input buffer for actual characters. */
|
||||
static size_t depth = 0;
|
||||
/* The length of the input buffer. */
|
||||
@@ -1587,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
|
||||
@@ -1609,103 +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 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 {
|
||||
depth++;
|
||||
puddle = (int *)nrealloc(puddle, depth * sizeof(int));
|
||||
puddle[depth - 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 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) {
|
||||
/* 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 (puddle != NULL) {
|
||||
/* Display all the characters in the input buffer at
|
||||
* once, filtering out control characters. */
|
||||
char *output = charalloc(depth + 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 < depth; i++)
|
||||
output[i] = (char)puddle[i];
|
||||
output[i] = '\0';
|
||||
/* Empty the input buffer. */
|
||||
free(puddle);
|
||||
puddle = NULL;
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
do_output(output, depth, FALSE);
|
||||
if (have_shortcut) {
|
||||
const subnfunc *f = sctofunc(s);
|
||||
|
||||
free(output);
|
||||
|
||||
/* Empty the input buffer. */
|
||||
free(puddle);
|
||||
puddle = NULL;
|
||||
depth = 0;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1841,8 +1863,8 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
#endif
|
||||
|
||||
while (i < output_len) {
|
||||
/* If control codes are allowed, encode a null as a newline, and
|
||||
* let a newline character create a whole new line. */
|
||||
/* If control codes are allowed, encode a verbatim null as a newline,
|
||||
* and let a verbatim ^J create a whole new line. */
|
||||
if (allow_cntrls) {
|
||||
if (output[i] == '\0')
|
||||
output[i] = '\n';
|
||||
@@ -2003,6 +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'},
|
||||
@@ -2048,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) {
|
||||
@@ -2154,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':
|
||||
@@ -2287,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;
|
||||
@@ -2305,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;
|
||||
@@ -2335,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) {
|
||||
@@ -2495,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
|
||||
@@ -2514,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
|
||||
@@ -2547,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();
|
||||
@@ -2623,7 +2669,7 @@ 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_buffer();
|
||||
|
||||
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 */
|
||||
|
||||
447
src/prompt.c
447
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);
|
||||
|
||||
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
|
||||
|
||||
95
src/search.c
95
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/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -155,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);
|
||||
@@ -494,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;
|
||||
|
||||
@@ -509,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();
|
||||
}
|
||||
@@ -600,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,
|
||||
@@ -626,8 +631,8 @@ ssize_t do_replace_loop(
|
||||
/* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
|
||||
* FALSE if (current, current_x) is. */
|
||||
|
||||
/* If the mark is on, frame the region, and turn the mark off. */
|
||||
if (old_mark_set) {
|
||||
/* If the mark is on, frame the region, and turn the mark off. */
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
openfile->mark_set = FALSE;
|
||||
@@ -745,15 +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
|
||||
@@ -831,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. */
|
||||
|
||||
51
src/text.c
51
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 */
|
||||
|
||||
@@ -2559,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();
|
||||
@@ -2666,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);
|
||||
@@ -2926,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;
|
||||
@@ -3074,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
|
||||
@@ -3107,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;
|
||||
}
|
||||
|
||||
@@ -3119,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;
|
||||
}
|
||||
|
||||
85
src/utils.c
85
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;
|
||||
|
||||
1516
src/winio.c
1516
src/winio.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user