Compare commits
141 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
|
||||
|
||||
@@ -2,6 +2,11 @@ Improvements in nano
|
||||
====================
|
||||
|
||||
Since 2.6.0:
|
||||
- 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
|
||||
|
||||
40
NEWS
40
NEWS
@@ -1,3 +1,25 @@
|
||||
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 +44,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 +170,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 +206,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 +486,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 +508,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 +621,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 +959,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 +1188,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!"
|
||||
|
||||
10
configure.ac
10
configure.ac
@@ -18,7 +18,7 @@
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
|
||||
# USA.
|
||||
|
||||
AC_INIT([nano], [2.6.1], [nano-devel@gnu.org], [nano])
|
||||
AC_INIT([nano], [2.6.3], [nano-devel@gnu.org], [nano])
|
||||
AC_CONFIG_SRCDIR([src/nano.c])
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE
|
||||
@@ -708,16 +708,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
|
||||
|
||||
@@ -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.6.3" "August 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
|
||||
@@ -148,9 +148,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,7 +17,7 @@
|
||||
.\" 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.6.3" "August 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.SH NAME
|
||||
@@ -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.6.3" "August 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.SH NAME
|
||||
|
||||
@@ -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.6.3
|
||||
@set UPDATED August 2016
|
||||
|
||||
@dircategory Editors
|
||||
@direntry
|
||||
@@ -21,7 +21,7 @@
|
||||
@titlepage
|
||||
@title @code{nano}
|
||||
@subtitle a small and friendly text editor.
|
||||
@subtitle version 2.6.1
|
||||
@subtitle version 2.6.3
|
||||
|
||||
@author Chris Allegretta
|
||||
@page
|
||||
@@ -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.
|
||||
|
||||
|
||||
888
po/nano.pot
888
po/nano.pot
File diff suppressed because it is too large
Load Diff
910
po/pt_BR.po
910
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
894
po/zh_CN.po
894
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
894
po/zh_TW.po
894
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 \
|
||||
|
||||
148
src/browser.c
148
src/browser.c
@@ -46,7 +46,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 +55,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 +105,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 +149,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 +160,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 +180,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 +221,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 +231,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 +243,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 +293,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 +312,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 +367,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);
|
||||
|
||||
287
src/chars.c
287
src/chars.c
@@ -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);
|
||||
|
||||
132
src/color.c
132
src/color.c
@@ -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 */
|
||||
|
||||
109
src/files.c
109
src/files.c
@@ -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;
|
||||
|
||||
@@ -232,8 +234,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 +249,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 +321,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) {
|
||||
@@ -341,18 +344,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 +373,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);
|
||||
@@ -1226,7 +1235,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 +1704,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 +1778,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 +1957,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 +1974,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 +1996,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 +2006,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 +2015,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 +2049,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 +2066,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 +2076,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 +2088,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 +2108,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 +2134,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 +2173,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 +2197,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 +2223,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 +2259,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 +2341,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 +2369,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 +2458,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;
|
||||
}
|
||||
|
||||
149
src/global.c
149
src/global.c
@@ -33,10 +33,10 @@ volatile sig_atomic_t sigwinch_counter = 0;
|
||||
/* Is incremented by the handler whenever a SIGWINCH occurs. */
|
||||
#endif
|
||||
|
||||
bool console;
|
||||
/* Whether we're running on a Linux VC (TRUE) or under X (FALSE). */
|
||||
bool meta_key;
|
||||
/* Whether the current keystroke is a Meta key. */
|
||||
bool func_key;
|
||||
/* Whether the current keystroke is an extended keypad value. */
|
||||
bool focusing = TRUE;
|
||||
/* Whether an update of the edit window should center the cursor. */
|
||||
|
||||
@@ -46,6 +46,8 @@ message_type lastmessage = HUSH;
|
||||
#ifndef NANO_TINY
|
||||
int controlleft = CONTROL_LEFT;
|
||||
int controlright = CONTROL_RIGHT;
|
||||
int controlup = CONTROL_UP;
|
||||
int controldown = CONTROL_DOWN;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
@@ -124,6 +126,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 +217,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;
|
||||
@@ -334,12 +339,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 +380,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 +398,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 +556,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 +859,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 +1127,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 +1361,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 +1452,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 +1675,7 @@ void thanks_for_all_the_fish(void)
|
||||
delwin(edit);
|
||||
delwin(bottomwin);
|
||||
|
||||
free(word_chars);
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
free(quotestr);
|
||||
#ifdef HAVE_REGEX_H
|
||||
|
||||
12
src/help.c
12
src/help.c
@@ -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) {
|
||||
|
||||
135
src/move.c
135
src/move.c
@@ -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);
|
||||
}
|
||||
|
||||
161
src/nano.c
161
src/nano.c
@@ -21,6 +21,7 @@
|
||||
**************************************************************************/
|
||||
|
||||
#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 (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;
|
||||
@@ -688,11 +686,14 @@ void die_save_file(const char *die_filename
|
||||
free(targetname);
|
||||
}
|
||||
|
||||
#define TOP_ROWS (ISSET(MORE_SPACE) ? 1 : 2)
|
||||
#define BOTTOM_ROWS (ISSET(NO_HELP) ? 1 : 3)
|
||||
|
||||
/* 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();
|
||||
editwinrows = LINES - TOP_ROWS - BOTTOM_ROWS;
|
||||
if (COLS < MIN_EDITOR_COLS || editwinrows < MIN_EDITOR_ROWS)
|
||||
die(_("Window size is too small for nano...\n"));
|
||||
|
||||
@@ -713,10 +714,9 @@ void window_init(void)
|
||||
delwin(bottomwin);
|
||||
|
||||
/* 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);
|
||||
topwin = newwin(TOP_ROWS, COLS, 0, 0);
|
||||
edit = newwin(editwinrows, COLS, TOP_ROWS, 0);
|
||||
bottomwin = newwin(BOTTOM_ROWS, COLS, TOP_ROWS + editwinrows, 0);
|
||||
|
||||
/* Turn the keypad on for the windows, if necessary. */
|
||||
if (!ISSET(REBIND_KEYPAD)) {
|
||||
@@ -859,6 +859,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,7 +920,7 @@ void usage(void)
|
||||
void version(void)
|
||||
{
|
||||
#ifdef REVISION
|
||||
printf(" nano from git, commit %s (after %s)\n", REVISION, VERSION);
|
||||
printf(" nano from git, %s\n", REVISION);
|
||||
#else
|
||||
printf(_(" nano, version %s\n"), VERSION);
|
||||
#endif
|
||||
@@ -1040,21 +1042,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 +1284,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();
|
||||
@@ -1550,12 +1536,13 @@ void terminal_init(void)
|
||||
/* 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 +1556,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 +1574,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,10 +1596,8 @@ 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;
|
||||
}
|
||||
}
|
||||
@@ -1625,9 +1610,9 @@ int do_input(bool allow_funcs)
|
||||
if (ISSET(VIEW_MODE))
|
||||
print_view_warning();
|
||||
else {
|
||||
depth++;
|
||||
puddle = (int *)nrealloc(puddle, depth * sizeof(int));
|
||||
puddle[depth - 1] = input;
|
||||
/* Store the byte, and leave room for a terminating zero. */
|
||||
puddle = charealloc(puddle, depth + 2);
|
||||
puddle[depth++] = (char)input;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1644,18 +1629,10 @@ int do_input(bool allow_funcs)
|
||||
#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;
|
||||
|
||||
for (i = 0; i < depth; i++)
|
||||
output[i] = (char)puddle[i];
|
||||
output[i] = '\0';
|
||||
|
||||
do_output(output, depth, FALSE);
|
||||
|
||||
free(output);
|
||||
/* 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);
|
||||
|
||||
/* Empty the input buffer. */
|
||||
free(puddle);
|
||||
@@ -1841,8 +1818,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 +1980,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 +2026,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 +2132,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 +2268,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 +2287,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 +2318,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 +2482,9 @@ int main(int argc, char **argv)
|
||||
/* Set up the terminal state. */
|
||||
terminal_init();
|
||||
|
||||
/* Check whether we're running on a Linux console. */
|
||||
console = (getenv("DISPLAY") == NULL);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Main: set up windows\n");
|
||||
#endif
|
||||
@@ -2514,25 +2504,32 @@ 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. */
|
||||
/* Ask ncurses for the key codes for Control+Left/Right/Up/Down. */
|
||||
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);
|
||||
keyvalue = tigetstr("kUP5");
|
||||
if (keyvalue != 0 && keyvalue != (char *)-1)
|
||||
controlup = key_defined(keyvalue);
|
||||
keyvalue = tigetstr("kDN5");
|
||||
if (keyvalue != 0 && keyvalue != (char *)-1)
|
||||
controldown = key_defined(keyvalue);
|
||||
#endif
|
||||
|
||||
#ifndef USE_SLANG
|
||||
/* Tell ncurses to pass the Esc key quickly. */
|
||||
set_escdelay(50);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
56
src/nano.h
56
src/nano.h
@@ -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,7 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
OVERWRITE, APPEND, PREPEND
|
||||
} append_type;
|
||||
} kind_of_writing_type;
|
||||
|
||||
typedef enum {
|
||||
UPWARD, DOWNWARD
|
||||
@@ -183,10 +187,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 +199,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 +210,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 +393,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. */
|
||||
@@ -408,8 +404,6 @@ typedef struct openfilestruct {
|
||||
/* The file's mark's x-coordinate position, if any. */
|
||||
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 +435,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 +550,16 @@ 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
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* An imaginary key for when we get a SIGWINCH (window resize). */
|
||||
@@ -604,10 +598,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 */
|
||||
|
||||
112
src/prompt.c
112
src/prompt.c
@@ -66,14 +66,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;
|
||||
else
|
||||
input = ERR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -87,23 +84,19 @@ 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;
|
||||
@@ -131,13 +124,6 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
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)
|
||||
@@ -152,40 +138,34 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
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) {
|
||||
/* 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. */
|
||||
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;
|
||||
}
|
||||
/* 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) {
|
||||
/* 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();
|
||||
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();
|
||||
do_statusbar_backspace();
|
||||
} else {
|
||||
/* Handle any other shortcut in the current menu, setting
|
||||
* ran_func to TRUE if we try to run their associated
|
||||
@@ -236,10 +216,10 @@ 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());
|
||||
@@ -261,9 +241,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;
|
||||
}
|
||||
}
|
||||
@@ -425,9 +405,9 @@ void do_statusbar_prev_word(void)
|
||||
}
|
||||
#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,7 +417,7 @@ 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
|
||||
@@ -491,9 +471,7 @@ void update_the_statusbar(void)
|
||||
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();
|
||||
|
||||
@@ -505,8 +483,7 @@ void update_the_statusbar(void)
|
||||
waddstr(bottomwin, expanded);
|
||||
free(expanded);
|
||||
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
reset_statusbar_cursor();
|
||||
@@ -607,7 +584,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) {
|
||||
@@ -855,15 +832,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);
|
||||
|
||||
81
src/proto.h
81
src/proto.h
@@ -30,8 +30,8 @@
|
||||
extern volatile sig_atomic_t sigwinch_counter;
|
||||
#endif
|
||||
|
||||
extern bool console;
|
||||
extern bool meta_key;
|
||||
extern bool func_key;
|
||||
extern bool focusing;
|
||||
|
||||
extern message_type lastmessage;
|
||||
@@ -39,6 +39,8 @@ extern message_type lastmessage;
|
||||
#ifndef NANO_TINY
|
||||
extern int controlleft;
|
||||
extern int controlright;
|
||||
extern int controlup;
|
||||
extern int controldown;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
@@ -91,7 +93,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 +147,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 +184,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 +320,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 +363,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 +399,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 +408,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 +444,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 +458,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 +496,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,7 +508,7 @@ void do_statusbar_cut_text(void);
|
||||
void do_statusbar_prev_word(void);
|
||||
void do_statusbar_next_word(void);
|
||||
#endif
|
||||
void do_statusbar_verbatim_input(bool *got_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);
|
||||
@@ -650,6 +631,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 +716,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 +746,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 +755,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 +783,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);
|
||||
|
||||
25
src/rcfile.c
25
src/rcfile.c
@@ -102,6 +102,7 @@ static const rcoption rcopts[] = {
|
||||
{"unix", MAKE_IT_UNIX},
|
||||
{"whitespace", 0},
|
||||
{"wordbounds", WORD_BOUNDS},
|
||||
{"wordchars", 0},
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
{"titlecolor", 0},
|
||||
@@ -469,20 +470,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 +656,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 +1066,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 +1098,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 +1176,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 +1194,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
|
||||
|
||||
31
src/search.c
31
src/search.c
@@ -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
|
||||
|
||||
19
src/text.c
19
src/text.c
@@ -2559,7 +2559,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 +2666,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);
|
||||
@@ -3107,7 +3108,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 +3120,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;
|
||||
}
|
||||
|
||||
61
src/utils.c
61
src/utils.c
@@ -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;
|
||||
|
||||
1269
src/winio.c
1269
src/winio.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user