Compare commits

..

87 Commits

Author SHA1 Message Date
Benno Schulenberg
2b5d29b8c6 po: update translations and regenerate POT file and PO files 2016-07-28 09:38:30 +02:00
Benno Schulenberg
b40520b574 bump version numbers and add a news item for 2.6.2 2016-07-28 09:21:27 +02:00
Benno Schulenberg
992533b91e moving: don't do an automatic smart home with Ctrl+Up and Ctrl+Down
It is nicer to have a predictable cursor position and not see it hop
left and right on differently indented lines.
2016-07-28 09:09:51 +02:00
Benno Schulenberg
f3e8991206 credits: don't bother blanking the second line nor the help lines
Those lines don't exist in that mode -- the relevant subwindows are
smaller, or have been made smaller just before.
2016-07-27 12:40:11 +02:00
Benno Schulenberg
df7353b312 tweaks: compute the sizes of the subwindows in a more direct manner 2016-07-27 12:27:04 +02:00
Benno Schulenberg
f311c0af87 tweaks: adjust a couple of comments 2016-07-27 09:23:49 +02:00
Benno Schulenberg
c88fae3310 search: match a beginning-of-line anchor just once per line
This fixes https://savannah.gnu.org/bugs/?48635.
2016-07-27 09:04:06 +02:00
Benno Schulenberg
68cfb08888 tweaks: fix compilation with --enable-tiny 2016-07-25 17:29:24 +02:00
Benno Schulenberg
4cff67fdde tweaks: adjust indentation after the previous change, and edit comments 2016-07-25 12:50:03 +02:00
Benno Schulenberg
aefe26d216 tweaks: factor out a common condition 2016-07-25 12:31:40 +02:00
Benno Schulenberg
8eb99e2a1d tweaks: put similar things together 2016-07-25 12:18:40 +02:00
Benno Schulenberg
19b6f906cc tweaks: rename another variable, for aptness 2016-07-25 10:57:33 +02:00
Benno Schulenberg
c38ffdc741 tweaks: rename two variables, to match others 2016-07-25 10:53:49 +02:00
Benno Schulenberg
a472f480a7 tweaks: trim some comments, and simplify a condition 2016-07-24 13:44:16 +02:00
Benno Schulenberg
4416d9c941 tweaks: shuffle the resetting of a counter to the tail of the routine 2016-07-24 13:15:45 +02:00
Benno Schulenberg
c073c5ae54 tweaks: don't bother resetting the Unicode code holder
It will be initialized when a new code is started.
2016-07-24 13:09:24 +02:00
David Lawrence Ramsey
fc0ddab349 input: provide feedback on the Unicode digits typed so far
This fulfills https://savannah.gnu.org/bugs/?48154.
2016-07-24 12:19:42 +02:00
Benno Schulenberg
c6dbcf91c3 new feature: functions to jump to previous or following block of text
And hard-bind the keys Ctrl+Up and Ctrl+Down to these functions.

Unlike the paragraph-jumping code, these new functions disregard
any indentation, treating only blank lines as separators.  They
also do an automatic smart home when that option is set.

This fulfills https://savannah.gnu.org/bugs/?48291.
2016-07-24 12:00:00 +02:00
Benno Schulenberg
8c7a38596d screen: include a workaround only when compiling against older ncurses
The bug with a leading wide character has been fixed since ncurses-5.9.

See https://savannah.gnu.org/bugs/?31743 for reference.
2016-07-24 10:38:31 +02:00
Benno Schulenberg
1c2d2a4027 tweaks: adjust a comment for removed definitions 2016-07-22 15:57:20 +02:00
Benno Schulenberg
1e5614b31b tweaks: avoid two compiler warnings 2016-07-22 15:48:06 +02:00
Benno Schulenberg
04b9b9c78b tweaks: avoid a runtime error when compiled with -fsanitize=undefined
This fixes https://savannah.gnu.org/bugs/?48540.
2016-07-22 15:39:45 +02:00
Benno Schulenberg
41ad376b70 chars: plug a gushing memory leak 2016-07-22 15:30:09 +02:00
Dirkjan Ochtman
1349c1d02c syntax: allow capital letters in Rust struct/trait names
Per https://doc.rust-lang.org/reference.html#fn2, non-ASCII characters are
currently not allowed in stable Rust, so keep it ASCII-only for now.

Signed-off-by: Dirkjan Ochtman <dirkjan@ochtman.nl>
2016-07-21 10:21:19 +02:00
Rishabh Dave
4c566c7903 tweaks: reduce the number of wattron/wattrof calls
Also, compose the coloring attributes during initialization
instead of every time when painting something.

Signed-off-by: Rishabh Dave <rishabhddave@gmail.com>
Signed-off-by: Benno Schulenberg <bensberg@justemail.net>
2016-07-21 10:10:59 +02:00
Benno Schulenberg
73a07215cc debug: remove duplicate information 2016-07-21 09:54:07 +02:00
Benno Schulenberg
bf091be778 chars: don't try to see a character in an empty line
This fixes https://savannah.gnu.org/bugs/?48578.
2016-07-21 09:46:47 +02:00
Benno Schulenberg
103dd06347 input: don't crash when the window is resized during verbatim input
Instead of referring to a window that might have been deleted by a
resize, just turn the keypad back on for the two windows from which
input might have been requested.

Also: don't insert KEY_WINCH as the verbatim keystroke.

This fixes https://savannah.gnu.org/bugs/?48532.
2016-07-17 12:18:12 +02:00
Benno Schulenberg
1d4c1e0bfc input: plug a memory leak
This fixes https://savannah.gnu.org/bugs/?48538.
2016-07-17 12:00:33 +02:00
Benno Schulenberg
b3fbb7c7ff input: report keystroke M-[ as being unbindable instead of just unbound 2016-07-16 14:05:33 +02:00
Benno Schulenberg
225203d40d tweaks: correct a comment 2016-07-16 13:29:50 +02:00
Benno Schulenberg
c2a0c78d9b tweaks: rename a variable and a type, to be less confusing 2016-07-16 13:29:50 +02:00
Benno Schulenberg
97f4fe26f0 build-sys: ignore the revision header file 2016-07-16 13:29:13 +02:00
Benno Schulenberg
ef071255e5 color: refresh the screen whenever the active syntax changes
This fixes https://savannah.gnu.org/bugs/?47296.
2016-07-14 17:51:33 +02:00
Benno Schulenberg
afb6a5b86d color: forget about aborting the precalculation for multiline regexes
This fixes https://savannah.gnu.org/bugs/?48389.
2016-07-14 14:31:14 +02:00
Benno Schulenberg
a37cd9f0ef tweaks: rename a variable, to clarify it refers to columns, not to bytes 2016-07-14 14:28:15 +02:00
Benno Schulenberg
6f12992cea new feature: add the option --wordchars, to set extra word characters
This allows the user to specify which other characters, besides the
default alphanumeric ones, should be considered as part of a word, so
that word operations like Ctrl+Left and Ctrl+Right will pass them by.

Using this option overrides the option --wordbounds.

This fulfills https://savannah.gnu.org/bugs/?47283.
2016-07-13 20:49:30 +02:00
Benno Schulenberg
d88423eaae tweaks: move a debug statement to its proper place, and improve aspect 2016-07-13 20:48:03 +02:00
Benno Schulenberg
8b28de1313 tweaks: don't call a thing malloc... when it doesn't call malloc() 2016-07-13 15:04:40 +02:00
Rishabh Dave
8fa72fb7e7 browser: elide a variable by fusing the uses of 'newpath' and 'path'
Signed-off-by: Rishabh Dave <rishabhddave@gmail.com>
2016-07-13 14:30:18 +02:00
Benno Schulenberg
b4babc2036 input: accept only the four iTerm sequences that actually get handled
This fixes https://savannah.gnu.org/bugs/?48455.
2016-07-13 13:01:46 +02:00
Benno Schulenberg
f2150d3f98 input: treat Ctrl+Alt+key different from Esc followed by Ctrl+key
When the user changes her mind after having pressed Esc, she cannot
unpress Esc, so do that for her by ignoring the escape code when
the subsequent keycode is outside of the normal printable range.

This restores the behavior from before nano-2.3.5 -- except that
Ctrl+Alt+key continues to report an unbound key.

This fixes https://savannah.gnu.org/bugs/?48459.
2016-07-13 10:01:07 +02:00
Benno Schulenberg
033376aec0 input: consider only O, o and [ as starters of multi-character sequences
This prevents many keycode sequences from being misconstrued when a
command key plus other keystrokes accumulate in the input buffer.

This fixes https://savannah.gnu.org/bugs/?48395.
2016-07-13 09:56:24 +02:00
Benno Schulenberg
e33a0b6dbe screen: avoid converting each character twice from multibyte to wide 2016-07-12 19:41:13 +02:00
Benno Schulenberg
0894587305 screen: elide another intermediate buffer for every visible character 2016-07-12 19:30:50 +02:00
Benno Schulenberg
960e848cc7 tweaks: elide a typedef, as it now has just one element 2016-07-12 09:35:48 +02:00
Benno Schulenberg
b4737072a6 tweaks: delete an element that is always FALSE and never used 2016-07-12 09:24:32 +02:00
Benno Schulenberg
8507dd4bd0 color: integrate the hilite attribute into the pair number
Color-pair numbers and attributes can be OR'd together -- do so,
to save an attron() call whenever the hilite is on.
2016-07-12 09:20:09 +02:00
Benno Schulenberg
62eeda3e9f tweaks: use mallocstrcpy() instead of strdup(), for a graceful death
To make nano save its modified buffers when it runs out of memory.
2016-07-11 20:45:26 +02:00
Benno Schulenberg
06c806215e tweaks: improve two comments 2016-07-11 20:11:29 +02:00
Benno Schulenberg
d2b25120f0 tweaks: fuse two handlings of a delete key, and fix a comment 2016-07-10 21:36:25 +02:00
Benno Schulenberg
0c319f8b4b tweaks: put the case labels (the keycodes) in a more sensible order 2016-07-10 20:49:52 +02:00
Benno Schulenberg
4fcc760158 tweaks: put some case labels closer to their statements
Also condense some comments, and group keys with the same result together.
2016-07-10 20:38:08 +02:00
Benno Schulenberg
0d5f918453 input: add some missing keycodes to the parsing routine
Add them so that <Esc> followed by <Home> will simply do "Home" instead of
reporting an unbound key.  The same for <End>, <PageUp> and <PageDown>.

This restores the behavior from before nano-2.3.5.
2016-07-10 20:21:11 +02:00
Rishabh Dave
9c7940b599 utils: accept mistypings and common separators between line and column
It is easy to type beside the comma key and hit instead "m" or ".", so
accept also these as a separator between line and column number.  And
when being generous anyway, also accept space, slash and semicolon.

This fulfills https://savannah.gnu.org/bugs/?48305.

Signed-off-by: Rishabh Dave <rishabhddave@gmail.com>
2016-07-04 22:04:24 +02:00
Benno Schulenberg
ccfb1eb0f1 tweaks: rearrange a function in my style, and rename a variable 2016-07-04 21:50:12 +02:00
Benno Schulenberg
7e3a9c3aa6 utils: don't bother to check line and column for NULL
When parsing a line and a column number, of course the found values
need to be passed back, otherwise it would be pointless to parse them.
2016-07-04 21:42:04 +02:00
Benno Schulenberg
a730b25ef9 browser: elide another call of opendir()
And in the bargain show an error message when doing ^R unreadabledir ^T.
2016-07-04 21:18:09 +02:00
Benno Schulenberg
500fef8314 tweaks: rename a variable -- to match others and to be more concise 2016-07-04 13:43:19 +02:00
Benno Schulenberg
29986e95a0 input: don't drop the first byte when user starts typing during loading
Precalculation of the multiline color data can be cut short when the
user is impatient and starts typing.  But this would drop the first
byte of whatever was typed -- not nice when it was just plain text,
but surprising and worse when the first keystroke was a command.

This fixes https://savannah.gnu.org/bugs/?48388.
2016-07-04 09:27:35 +02:00
Benno Schulenberg
4af1da7d95 color: push the resets further when start and end match are equal
When for a multiline syntax-coloring rule the starting regex matches at
the exact same spot as the ending regex, do a second round of resets, so
that reevaluation starts further back and gets a few more things right.

This mildly fixes https://savannah.gnu.org/bugs/?47420.
2016-07-03 16:23:54 +02:00
Benno Schulenberg
528b79b5f3 tweaks: rename a variable to be more accurate
When we get a ^J as verbatim input, it is not possible to include it
into the file buffer or the prompt answer, because this would mean
adding an encoded null to the buffer or answer, and that is not what
the user intended.  One option would have been to simply ignore a ^J
in verbatim input.  But the choice has been made to act the same way
as when the ^J (0x0A) is found in the file data: start a new line.

That is the same response as to the Enter key, yes -- but the code
for the Enter key is ^M (0x0D), not ^J.  So, to be more precise,
rename the relevant variable from 'got_enter' to 'got_newline'.
2016-07-03 16:19:27 +02:00
Benno Schulenberg
03a81aa9c5 browser: trim all trailing slashes (just in case there are more) 2016-07-03 16:18:26 +02:00
Rishabh Dave
4957c1121d browser: select an inaccessible directory also when tabbed
When the user tab-completed a name at the Go To Directory prompt, this
name will end in a slash.  Remove this slash, so the name can be found
in the file list (where directory names don't include the final slash).

This fixes http://savannah.gnu.org/bugs/?48353.

Signed-off-by: Rishabh Dave <rishabhddave@gmail.com>
2016-07-02 12:26:42 +02:00
Benno Schulenberg
d9d8eb2480 tweaks: straighten out the flow of a loop 2016-07-01 13:11:23 +02:00
Benno Schulenberg
d9aad9212f tweaks: elide a bit of code duplication 2016-07-01 13:11:00 +02:00
Benno Schulenberg
8b636de1d3 tweaks: put all the movement functions together
And order them from smallest stride to biggest stride.
2016-07-01 12:42:58 +02:00
Benno Schulenberg
aeab800490 tweaks: improve a few comments 2016-07-01 12:34:33 +02:00
Benno Schulenberg
f8c33e8630 tweaks: reduce the scope of two variables 2016-07-01 12:22:44 +02:00
Benno Schulenberg
b6efea266e chars: invalid sequences are not blank, nor text, nor punctuation
So, slightly speed up the functions that check for those.
2016-06-30 14:34:34 +02:00
Benno Schulenberg
8686cb3d3d chars: measure invalid sequences and unassigned codepoints more quickly
Invalid multibyte sequences get depicted with the Replacement Character,
and unassigned codepoints are shown as if they were a space.  Both have
a width of one.
2016-06-30 14:33:25 +02:00
Benno Schulenberg
91fff2a2c8 screen: avoid looking up the width of whitespace and control codes
Spaces and tabs and control codes never are multi-column glyphs, so
only look up the width for "normal", visible characters.
2016-06-30 14:32:10 +02:00
Benno Schulenberg
d6f43bd156 screen: elide the intermediate buffer for every single character 2016-06-30 14:29:14 +02:00
Benno Schulenberg
ebbe546033 screen: again, look at the bytes in their context
This avoids having to null-terminate every single-byte character.
2016-06-30 14:28:29 +02:00
Benno Schulenberg
cf0eed6c36 screen: don't check for every character whether there is still enough space
Just allocate ample space up front and thus discard the delaying 'if' for
each and every character.  In most cases this will allocate far too much,
but that hardly matters: it is freed again as soon as the line is printed.
2016-06-30 14:27:00 +02:00
Benno Schulenberg
feacacc46d chars: look at bytes in their context, so only valid sequences are accepted
This fixes https://savannah.gnu.org/bugs/?48125.

(The fix is slightly wasteful; speeding things up will follow later.)
2016-06-29 20:56:50 +02:00
Benno Schulenberg
af53c56ec8 chars: speed up the determination whether something is a control character
Use knowledge of UTF-8 instead of converting to wide characters first.
2016-06-29 20:56:50 +02:00
Benno Schulenberg
019d7b34ca chars: delete a now-unused function 2016-06-29 20:56:50 +02:00
Benno Schulenberg
622995fb12 chars: the representation of a control character is always two bytes
Any control character is represented by a ^ plus an ASCII character.
2016-06-29 20:56:50 +02:00
Benno Schulenberg
03586c60da chars: represent the high-bit controls more intelligibly
Instead of showing the upper control codes like this:

   ^À ^Á ^Â ^Ã ^Ä ^Å ^Æ ^Ç ^È ^É ^Ê ^Ë ^Ì ^Í ^Î ^Ï
   ^Ð ^Ñ ^Ò ^Ó ^Ô ^Õ ^Ö ^× ^Ø ^Ù ^Ú ^Û ^Ü ^Ý ^Þ ^ß

show them like this:

   ^` ^a ^b ^c ^d ^e ^f ^g ^h ^i ^j ^k ^l ^m ^n ^o
   ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^=

The lower control codes continue to be shown like this:

   ^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O
   ^P ^Q ^R ^S ^T ^U ^V ^W ^X ^Y ^Z ^[ ^\ ^] ^^ ^_

The representation of DEL (0x7F) continues as ^?.

Further, use knowledge of UTF-8 to avoid a roundtrip through
wide characters.
2016-06-29 20:56:50 +02:00
Benno Schulenberg
07a39e8e18 screen: don't simulate a sigwinch but directly reinitialize the screen
This fixes the second part of https://savannah.gnu.org/bugs/?48331.

Reported-by: Mike Frysinger <vapier@gentoo.org>
2016-06-29 15:55:38 +02:00
Benno Schulenberg
1d7c177606 input: don't drop a keystroke on the floor when the terminal resizes
This fixes the first part of https://savannah.gnu.org/bugs/?48331.

Reported-by: Mike Frysinger <vapier@gentoo.org>
2016-06-29 15:53:08 +02:00
Benno Schulenberg
2ae490cd8f build: refresh the git description whenever something is recompiled
This fixes https://savannah.gnu.org/bugs/?47962 reported by Cody Taylor.
2016-06-27 19:45:21 +02:00
Benno Schulenberg
6fda7a7057 chars: speed up two reverse-searching routines a bit
By removing from their main loops a condition that occurs just once.
2016-06-27 19:22:28 +02:00
Benno Schulenberg
1e2833e07b tweaks: elide two unneeded variables 2016-06-27 19:22:20 +02:00
Benno Schulenberg
067b0a3367 input: elide an extra buffer for inserting stuff into the text
Do the casting from integer to character rightaway in the first
intermediate buffer.
2016-06-27 19:18:40 +02:00
Benno Schulenberg
24b10179a1 files: beep whenever writing out a file fails
Just like when reading a file fails.  It needs the user's attention.
2016-06-27 19:17:53 +02:00
61 changed files with 15861 additions and 15014 deletions

1
.gitignore vendored
View File

@@ -36,3 +36,4 @@ core
/nano.spec
/src/nano
/src/revision.h

View File

@@ -2,6 +2,10 @@ Improvements in nano
====================
Since 2.6.0:
- 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

13
NEWS
View File

@@ -1,3 +1,16 @@
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),

View File

@@ -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.2], [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

View File

@@ -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.2" "July 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.

View File

@@ -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.2" "July 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

View File

@@ -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.2" "July 2016"
.\" Please adjust this date whenever revising the manpage.
.\"
.SH NAME

View File

@@ -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.

View File

@@ -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 "\".*\""

View File

@@ -6,8 +6,8 @@
@smallbook
@set EDITION 0.4
@set VERSION 2.6.1
@set UPDATED June 2016
@set VERSION 2.6.2
@set UPDATED July 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.2
@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.

833
po/bg.po

File diff suppressed because it is too large Load Diff

948
po/ca.po

File diff suppressed because it is too large Load Diff

834
po/cs.po

File diff suppressed because it is too large Load Diff

834
po/da.po

File diff suppressed because it is too large Load Diff

845
po/de.po

File diff suppressed because it is too large Load Diff

848
po/eo.po

File diff suppressed because it is too large Load Diff

847
po/es.po

File diff suppressed because it is too large Load Diff

833
po/eu.po

File diff suppressed because it is too large Load Diff

902
po/fi.po

File diff suppressed because it is too large Load Diff

917
po/fr.po

File diff suppressed because it is too large Load Diff

834
po/ga.po

File diff suppressed because it is too large Load Diff

834
po/gl.po

File diff suppressed because it is too large Load Diff

847
po/hr.po

File diff suppressed because it is too large Load Diff

835
po/hu.po

File diff suppressed because it is too large Load Diff

846
po/id.po

File diff suppressed because it is too large Load Diff

1023
po/it.po

File diff suppressed because it is too large Load Diff

834
po/ja.po

File diff suppressed because it is too large Load Diff

834
po/ms.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

847
po/nb.po

File diff suppressed because it is too large Load Diff

846
po/nl.po

File diff suppressed because it is too large Load Diff

863
po/nn.po

File diff suppressed because it is too large Load Diff

834
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

849
po/ro.po

File diff suppressed because it is too large Load Diff

834
po/ru.po

File diff suppressed because it is too large Load Diff

834
po/sl.po

File diff suppressed because it is too large Load Diff

834
po/sr.po

File diff suppressed because it is too large Load Diff

951
po/sv.po

File diff suppressed because it is too large Load Diff

846
po/tr.po

File diff suppressed because it is too large Load Diff

847
po/uk.po

File diff suppressed because it is too large Load Diff

847
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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 \

View File

@@ -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;
@@ -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);

View File

@@ -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)
@@ -110,7 +104,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 +124,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 +144,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 +156,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 +174,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 +183,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)
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 (0 <= c[0] && c[0] <= 127)
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 +291,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
@@ -667,7 +639,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 +653,19 @@ 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)
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 +785,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 +808,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);

View File

@@ -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 */

View File

@@ -1226,7 +1226,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 +1695,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 +1769,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 +1948,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 +1965,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 +1987,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 +1997,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 +2006,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 +2040,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 +2057,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 +2067,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 +2079,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 +2099,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 +2125,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 +2164,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 +2188,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 +2214,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 +2250,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 +2332,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 +2360,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 +2449,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;
}

View File

@@ -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;
@@ -570,6 +575,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 +878,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 +1146,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);
@@ -1450,6 +1470,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 +1693,7 @@ void thanks_for_all_the_fish(void)
delwin(edit);
delwin(bottomwin);
free(word_chars);
#ifndef DISABLE_JUSTIFY
free(quotestr);
#ifdef HAVE_REGEX_H

View File

@@ -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) {

View File

@@ -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. */

View File

@@ -21,6 +21,7 @@
**************************************************************************/
#include "proto.h"
#include "revision.h"
#include <stdio.h>
#include <stdarg.h>
@@ -688,11 +689,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 +717,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 +862,8 @@ void usage(void)
#ifndef NANO_TINY
print_opt("-W", "--wordbounds",
N_("Detect word boundaries more accurately"));
print_opt("-X", "--wordchars",
N_("Which other characters are word parts"));
#endif
#ifndef DISABLE_COLOR
if (!ISSET(RESTRICTED))
@@ -918,7 +923,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 +1045,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 +1287,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();
@@ -1553,9 +1542,10 @@ void unbound_key(int code)
if (func_key)
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 +1559,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. */
@@ -1625,9 +1615,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 +1634,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 +1823,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 +1985,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 +2031,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 +2137,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 +2273,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 +2292,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 +2323,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) {
@@ -2514,25 +2506,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

View File

@@ -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
@@ -199,14 +203,6 @@ typedef enum {
} undo_type;
/* Structure types. */
typedef struct color_pair {
int pairnum;
/* The color pair number used for this foreground color and
* background color. */
bool bright;
/* Is this color A_BOLD? */
} color_pair;
#ifndef DISABLE_COLOR
typedef struct colortype {
short fg;
@@ -218,6 +214,8 @@ typedef struct colortype {
int pairnum;
/* The color pair number used for this foreground color and
* background color. */
int attributes;
/* Pair number and brightness composed into ready-to-use attributes. */
int rex_flags;
/* The regex compilation flags (with or without REG_ICASE). */
char *start_regex;
@@ -566,6 +564,8 @@ enum
/* 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 +604,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 */

View File

@@ -131,13 +131,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 +145,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 +223,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 +248,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 +412,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 +424,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 +478,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 +490,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();
@@ -855,15 +839,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);

View File

@@ -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;
@@ -183,18 +188,12 @@ 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 +319,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);
@@ -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);
@@ -475,8 +476,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 +514,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 +526,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 +649,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 +734,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);
@@ -773,7 +773,7 @@ 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);
@@ -785,13 +785,12 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
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);

View File

@@ -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},
@@ -657,7 +658,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 +1068,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 +1100,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 +1178,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 +1196,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

View File

@@ -600,14 +600,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 +624,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 +743,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

View File

@@ -3107,7 +3107,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 +3119,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;
}

View File

@@ -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;
}
@@ -296,8 +294,8 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
* 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));
retval = (position == 0 || !is_alnum_mbchar(before)) &&
(word_end == strlen(buf) || !is_alnum_mbchar(after));
free(before);
free(after);
@@ -406,8 +404,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 +420,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;

View File

@@ -21,6 +21,7 @@
**************************************************************************/
#include "proto.h"
#include "revision.h"
#include <stdio.h>
#include <stdarg.h>
@@ -28,17 +29,27 @@
#include <unistd.h>
#include <ctype.h>
#ifdef REVISION
#define BRANDING REVISION
#else
#define BRANDING PACKAGE_STRING
#endif
static int *key_buffer = NULL;
/* The keystroke buffer, containing all the keystrokes we
* haven't handled yet at a given point. */
static size_t key_buffer_len = 0;
/* The length of the keystroke buffer. */
static bool solitary = FALSE;
/* Whether an Esc arrived by itself -- not as leader of a sequence. */
static int statusblank = 0;
/* The number of keystrokes left before we blank the statusbar. */
static bool suppress_cursorpos = FALSE;
/* Should we skip constant position display for one keystroke? */
#ifdef USING_OLD_NCURSES
static bool seen_wide = FALSE;
/* Whether we've seen a multicolumn character in the current line. */
#endif
#ifndef NANO_TINY
static sig_atomic_t last_sigwinch_counter = 0;
@@ -57,18 +68,13 @@ bool the_window_resized(void)
/* Control character compatibility:
*
* - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
* VT100, and VT220.
* - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
* VT220, and VT320.
* - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
* VT220, and VT320.
* - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
* VT220, and VT320.
* - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
* VT220, and VT320.
* - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
* ANSI, VT100, and VT220, and which is Backspace under VT320.
* - Ctrl-H is Backspace under ASCII, ANSI, VT100, and VT220.
* - Ctrl-I is Tab under ASCII, ANSI, VT100, VT220, and VT320.
* - Ctrl-M is Enter under ASCII, ANSI, VT100, VT220, and VT320.
* - Ctrl-Q is XON under ASCII, ANSI, VT100, VT220, and VT320.
* - Ctrl-S is XOFF under ASCII, ANSI, VT100, VT220, and VT320.
* - Ctrl-8 (Ctrl-?, NANO_CONTROL_8) is Delete under ASCII, ANSI,
* VT100, and VT220, but is Backspace under VT320.
*
* Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
* default, xterm assumes it's running on a VT320 and generates Ctrl-8
@@ -85,8 +91,8 @@ bool the_window_resized(void)
*
* We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
* console, the FreeBSD console, the Mach console, xterm, rxvt, Eterm,
* and Terminal. Among these, there are several conflicts and
* omissions, outlined as follows:
* and Terminal, and some for iTerm2. Among these, there are several
* conflicts and omissions, outlined as follows:
*
* - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
* (Ctrl-I is also Tab on ANSI, which we already support.)
@@ -134,8 +140,10 @@ void get_key_buffer(WINDOW *win)
input = wgetch(win);
#ifndef NANO_TINY
if (the_window_resized())
if (the_window_resized()) {
ungetch(input);
input = KEY_WINCH;
}
#endif
if (input == ERR && nodelay_mode)
@@ -353,6 +361,7 @@ int parse_kbinput(WINDOW *win)
/* If there are four consecutive escapes, discard three of them. */
if (escapes > 3)
escapes = 1;
solitary = (escapes == 1 && get_key_buffer_len() == 0);
/* Wait for more input. */
break;
default:
@@ -364,10 +373,12 @@ int parse_kbinput(WINDOW *win)
case 1:
/* Reset the escape counter. */
escapes = 0;
if (get_key_buffer_len() == 0 || key_buffer[0] == 0x1b) {
if ((*kbinput != 'O' && *kbinput != 'o' && *kbinput != '[') ||
get_key_buffer_len() == 0 || *key_buffer == 0x1B) {
/* One escape followed by a single non-escape:
* meta key sequence mode. */
meta_key = TRUE;
if (!solitary || (*kbinput >= 0x20 && *kbinput < 0x7F))
meta_key = TRUE;
retval = tolower(*kbinput);
} else
/* One escape followed by a non-escape, and there
@@ -392,9 +403,6 @@ int parse_kbinput(WINDOW *win)
retval = controlleft;
break;
#endif
default:
retval = ERR;
break;
}
double_esc = FALSE;
escapes = 0;
@@ -458,7 +466,8 @@ int parse_kbinput(WINDOW *win)
retval = *kbinput;
}
}
} else if (*kbinput=='[') {
} else if (*kbinput == '[' && key_buffer_len > 0 &&
'A' <= *key_buffer && *key_buffer <= 'D') {
/* This is an iTerm2 sequence: ^[ ^[ [ X. */
double_esc = TRUE;
} else {
@@ -490,118 +499,111 @@ int parse_kbinput(WINDOW *win)
if (retval != ERR) {
switch (retval) {
case NANO_CONTROL_8:
retval = ISSET(REBIND_DELETE) ? sc_seq_or(do_delete, 0) :
sc_seq_or(do_backspace, 0);
break;
case KEY_DOWN:
#ifdef KEY_SDOWN
/* ncurses and Slang don't support KEY_SDOWN. */
case KEY_SDOWN:
#endif
retval = sc_seq_or(do_down_void, *kbinput);
break;
case KEY_UP:
#ifdef KEY_SUP
/* ncurses and Slang don't support KEY_SUP. */
case KEY_SUP:
#endif
retval = sc_seq_or(do_up_void, *kbinput);
break;
case KEY_LEFT:
#ifdef KEY_SLEFT
/* Slang doesn't support KEY_SLEFT. */
case KEY_SLEFT:
#endif
case KEY_LEFT:
retval = sc_seq_or(do_left, *kbinput);
break;
case KEY_RIGHT:
#ifdef KEY_SRIGHT
/* Slang doesn't support KEY_SRIGHT. */
case KEY_SRIGHT:
#endif
case KEY_RIGHT:
retval = sc_seq_or(do_right, *kbinput);
break;
#ifdef KEY_SUP
/* ncurses and Slang don't support KEY_SUP. */
case KEY_SUP:
#endif
case KEY_UP:
retval = sc_seq_or(do_up_void, *kbinput);
break;
#ifdef KEY_SDOWN
/* ncurses and Slang don't support KEY_SDOWN. */
case KEY_SDOWN:
#endif
case KEY_DOWN:
retval = sc_seq_or(do_down_void, *kbinput);
break;
#ifdef KEY_SHOME
/* HP-UX 10-11 and Slang don't support KEY_SHOME. */
case KEY_SHOME:
#endif
case KEY_A1: /* Home (7) on numeric keypad with
* NumLock off. */
#ifdef KEY_HOME
case KEY_HOME:
#endif
case KEY_A1: /* Home (7) on keypad with NumLock off. */
retval = sc_seq_or(do_home, *kbinput);
break;
#ifdef KEY_SEND
/* HP-UX 10-11 and Slang don't support KEY_SEND. */
case KEY_SEND:
#endif
#ifdef KEY_END
case KEY_END:
#endif
case KEY_C1: /* End (1) on keypad with NumLock off. */
retval = sc_seq_or(do_end, *kbinput);
break;
case KEY_PPAGE:
case KEY_A3: /* PageUp (9) on keypad with NumLock off. */
retval = sc_seq_or(do_page_up, *kbinput);
break;
case KEY_NPAGE:
case KEY_C3: /* PageDown (3) on keypad with NumLock off. */
retval = sc_seq_or(do_page_down, *kbinput);
break;
case KEY_ENTER:
retval = sc_seq_or(do_enter, *kbinput);
break;
case KEY_BACKSPACE:
retval = sc_seq_or(do_backspace, *kbinput);
break;
#ifdef KEY_SDC
/* Slang doesn't support KEY_SDC. */
case KEY_SDC:
#endif
case NANO_CONTROL_8:
if (ISSET(REBIND_DELETE))
retval = sc_seq_or(do_delete, *kbinput);
else
retval = sc_seq_or(do_backspace, *kbinput);
break;
#endif
#ifdef KEY_SIC
/* Slang doesn't support KEY_SIC. */
case KEY_SIC:
retval = sc_seq_or(do_insertfile_void, *kbinput);
break;
#endif
case KEY_C3: /* PageDown (4) on numeric keypad with
* NumLock off. */
retval = sc_seq_or(do_page_down, *kbinput);
break;
case KEY_A3: /* PageUp (9) on numeric keypad with
* NumLock off. */
retval = sc_seq_or(do_page_up, *kbinput);
break;
case KEY_ENTER:
retval = sc_seq_or(do_enter, *kbinput);
break;
case KEY_B2: /* Center (5) on numeric keypad with
* NumLock off. */
retval = ERR;
break;
case KEY_C1: /* End (1) on numeric keypad with
* NumLock off. */
#ifdef KEY_SEND
/* HP-UX 10-11 and Slang don't support KEY_SEND. */
case KEY_SEND:
#ifdef KEY_SBEG
/* Slang doesn't support KEY_SBEG. */
case KEY_SBEG:
#endif
retval = sc_seq_or(do_end, *kbinput);
break;
#ifdef KEY_BEG
/* Slang doesn't support KEY_BEG. */
case KEY_BEG: /* Center (5) on numeric keypad with
* NumLock off. */
case KEY_BEG:
#endif
case KEY_B2: /* Center (5) on keypad with NumLock off. */
retval = ERR;
break;
#endif
#ifdef KEY_CANCEL
/* Slang doesn't support KEY_CANCEL. */
case KEY_CANCEL:
#ifdef KEY_SCANCEL
/* Slang doesn't support KEY_SCANCEL. */
case KEY_SCANCEL:
#endif
/* Slang doesn't support KEY_CANCEL. */
case KEY_CANCEL:
retval = first_sc_for(currmenu, do_cancel)->seq;
break;
#endif
#ifdef KEY_SBEG
/* Slang doesn't support KEY_SBEG. */
case KEY_SBEG: /* Center (5) on numeric keypad with
* NumLock off. */
retval = ERR;
break;
#endif
#ifdef KEY_SUSPEND
#ifdef KEY_SSUSPEND
/* Slang doesn't support KEY_SSUSPEND. */
case KEY_SSUSPEND:
retval = sc_seq_or(do_suspend_void, 0);
break;
#endif
#ifdef KEY_SUSPEND
/* Slang doesn't support KEY_SUSPEND. */
case KEY_SUSPEND:
retval = sc_seq_or(do_suspend_void, 0);
@@ -633,6 +635,10 @@ int parse_kbinput(WINDOW *win)
retval = sc_seq_or(do_prev_word_void, 0);
else if (retval == controlright)
retval = sc_seq_or(do_next_word_void, 0);
else if (retval == controlup)
retval = sc_seq_or(do_prev_block, 0);
else if (retval == controldown)
retval = sc_seq_or(do_next_block, 0);
#endif
/* If our result is an extended keypad value (i.e. a value
@@ -694,8 +700,9 @@ int convert_sequence(const int *seq, size_t seq_len)
if (seq_len >= 5) {
switch (seq[4]) {
case 'A': /* Esc O 1 ; 5 A == Ctrl-Up on Terminal. */
return CONTROL_UP;
case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on Terminal. */
return arrow_from_abcd(seq[4]);
return CONTROL_DOWN;
case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on Terminal. */
return CONTROL_RIGHT;
case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on Terminal. */
@@ -764,8 +771,9 @@ int convert_sequence(const int *seq, size_t seq_len)
case 'Y': /* Esc O Y == F10 on Mach console. */
return KEY_F(10);
case 'a': /* Esc O a == Ctrl-Up on rxvt. */
return CONTROL_UP;
case 'b': /* Esc O b == Ctrl-Down on rxvt. */
return arrow_from_abcd(seq[1]);
return CONTROL_DOWN;
case 'c': /* Esc O c == Ctrl-Right on rxvt. */
return CONTROL_RIGHT;
case 'd': /* Esc O d == Ctrl-Left on rxvt. */
@@ -839,8 +847,9 @@ int convert_sequence(const int *seq, size_t seq_len)
case 'o':
switch (seq[1]) {
case 'a': /* Esc o a == Ctrl-Up on Eterm. */
return CONTROL_UP;
case 'b': /* Esc o b == Ctrl-Down on Eterm. */
return arrow_from_abcd(seq[1]);
return CONTROL_DOWN;
case 'c': /* Esc o c == Ctrl-Right on Eterm. */
return CONTROL_RIGHT;
case 'd': /* Esc o d == Ctrl-Left on Eterm. */
@@ -893,8 +902,9 @@ int convert_sequence(const int *seq, size_t seq_len)
if (seq_len >= 5) {
switch (seq[4]) {
case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on xterm. */
return CONTROL_UP;
case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on xterm. */
return arrow_from_abcd(seq[4]);
return CONTROL_DOWN;
case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on xterm. */
return CONTROL_RIGHT;
case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on xterm. */
@@ -1220,7 +1230,7 @@ long add_unicode_digit(int kbinput, long factor, long *uni)
/* Translate a Unicode sequence: turn a six-digit hexadecimal number
* (from 000000 to 10FFFF, case-insensitive) into its corresponding
* multibyte value. */
long get_unicode_kbinput(int kbinput)
long get_unicode_kbinput(WINDOW *win, int kbinput)
{
static int uni_digits = 0;
static long uni = 0;
@@ -1231,66 +1241,63 @@ long get_unicode_kbinput(int kbinput)
switch (uni_digits) {
case 1:
/* First digit: This must be zero or one. Put it in the
* 0x100000's position of the Unicode sequence holder. */
if ('0' <= kbinput && kbinput <= '1')
/* The first digit must be zero or one. Put it in the
* 0x100000's position of the Unicode sequence holder.
* Otherwise, return the character itself as the result. */
if (kbinput == '0' || kbinput == '1')
uni = (kbinput - '0') * 0x100000;
else
/* This isn't the first digit of a Unicode sequence.
* Return this character as the result. */
retval = kbinput;
break;
case 2:
/* Second digit: This must be zero if the first was one, and
* may be any hexadecimal value if the first was zero. Put
* it in the 0x10000's position of the Unicode sequence
* holder. */
if (uni == 0 || '0' == kbinput)
/* The second digit must be zero if the first was one, but
* may be any hexadecimal value if the first was zero. */
if (kbinput == '0' || uni == 0)
retval = add_unicode_digit(kbinput, 0x10000, &uni);
else
/* This isn't the second digit of a Unicode sequence.
* Return this character as the result. */
retval = kbinput;
break;
case 3:
/* Third digit: This may be any hexadecimal value. Put it
* in the 0x1000's position of the Unicode sequence
* holder. */
/* Later digits may be any hexadecimal value. */
retval = add_unicode_digit(kbinput, 0x1000, &uni);
break;
case 4:
/* Fourth digit: This may be any hexadecimal value. Put it
* in the 0x100's position of the Unicode sequence
* holder. */
retval = add_unicode_digit(kbinput, 0x100, &uni);
break;
case 5:
/* Fifth digit: This may be any hexadecimal value. Put it
* in the 0x10's position of the Unicode sequence holder. */
retval = add_unicode_digit(kbinput, 0x10, &uni);
break;
case 6:
/* Sixth digit: This may be any hexadecimal value. Put it
* in the 0x1's position of the Unicode sequence holder. */
retval = add_unicode_digit(kbinput, 0x1, &uni);
/* If this character is a valid hexadecimal value, then the
* Unicode sequence is complete. */
/* If also the sixth digit was a valid hexadecimal value, then
* the Unicode sequence is complete, so return it. */
if (retval == ERR)
retval = uni;
break;
}
/* If we have a result, reset the Unicode digit counter and the
* Unicode sequence holder. */
if (retval != ERR) {
uni_digits = 0;
uni = 0;
/* Show feedback only when editing, not when at a prompt. */
if (retval == ERR && win == edit) {
char partial[7] = "......";
/* Construct the partial result, right-padding it with dots. */
snprintf(partial, uni_digits + 1, "%06lX", uni);
partial[uni_digits] = '.';
/* TRANSLATORS: This is shown while a six-digit hexadecimal
* Unicode character code (%s) is being typed in. */
statusline(HUSH, _("Unicode Input: %s"), partial);
}
#ifdef DEBUG
fprintf(stderr, "get_unicode_kbinput(): kbinput = %d, uni_digits = %d, uni = %ld, retval = %ld\n", kbinput, uni_digits, uni, retval);
fprintf(stderr, "get_unicode_kbinput(): kbinput = %d, uni_digits = %d, uni = %ld, retval = %ld\n",
kbinput, uni_digits, uni, retval);
#endif
/* If we have an end result, reset the Unicode digit counter. */
if (retval != ERR)
uni_digits = 0;
return retval;
}
#endif /* ENABLE_UTF8 */
@@ -1370,8 +1377,12 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
* keypad back on if necessary now that we're done. */
if (ISSET(PRESERVE))
enable_flow_control();
if (!ISSET(REBIND_KEYPAD))
keypad(win, TRUE);
/* Use the global window pointers, because a resize may have freed
* the data that the win parameter points to. */
if (!ISSET(REBIND_KEYPAD)) {
keypad(edit, TRUE);
keypad(bottomwin, TRUE);
}
return retval;
}
@@ -1388,11 +1399,20 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
while ((kbinput = get_input(win, 1)) == NULL)
;
#ifndef NANO_TINY
/* When the window was resized, abort and return nothing. */
if (*kbinput == KEY_WINCH) {
*kbinput_len = 0;
free(kbinput);
return NULL;
}
#endif
#ifdef ENABLE_UTF8
if (using_utf8()) {
/* Check whether the first keystroke is a valid hexadecimal
* digit. */
long uni = get_unicode_kbinput(*kbinput);
long uni = get_unicode_kbinput(win, *kbinput);
/* If the first keystroke isn't a valid hexadecimal digit, put
* back the first keystroke. */
@@ -1406,15 +1426,11 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
char *uni_mb;
int uni_mb_len, *seq, i;
if (win == edit)
/* TRANSLATORS: This is displayed during the input of a
* six-digit hexadecimal Unicode character code. */
statusbar(_("Unicode Input"));
while (uni == ERR) {
free(kbinput);
while ((kbinput = get_input(win, 1)) == NULL)
;
uni = get_unicode_kbinput(*kbinput);
uni = get_unicode_kbinput(win, *kbinput);
}
/* Put back the multibyte equivalent of the Unicode
@@ -1620,21 +1636,22 @@ const sc *get_shortcut(int *kbinput)
sc *s;
#ifdef DEBUG
fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s -- ", *kbinput, meta_key ? "TRUE" : "FALSE");
fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s -- ",
*kbinput, meta_key ? "TRUE" : "FALSE");
#endif
for (s = sclist; s != NULL; s = s->next) {
if ((s->menus & currmenu) && *kbinput == s->seq
&& meta_key == (s->type == META)) {
#ifdef DEBUG
fprintf (stderr, "matched seq \"%s\", and btw meta was %d (menu is %x from %x)\n",
s->keystr, meta_key, currmenu, s->menus);
fprintf (stderr, "matched seq '%s' (menu is %x from %x)\n",
s->keystr, currmenu, s->menus);
#endif
return s;
}
}
#ifdef DEBUG
fprintf (stderr, "matched nothing, btw meta was %d\n", meta_key);
fprintf (stderr, "matched nothing\n");
#endif
return NULL;
@@ -1656,14 +1673,6 @@ void blank_titlebar(void)
blank_line(topwin, 0, 0, COLS);
}
/* If the MORE_SPACE flag isn't set, blank the second line of the top
* portion of the window. */
void blank_topbar(void)
{
if (!ISSET(MORE_SPACE))
blank_line(topwin, 1, 0, COLS);
}
/* Blank all the lines of the middle portion of the window, i.e. the
* edit window. */
void blank_edit(void)
@@ -1714,86 +1723,58 @@ void check_statusblank(void)
/* Convert buf into a string that can be displayed on screen. The
* caller wants to display buf starting with column start_col, and
* extending for at most len columns. start_col is zero-based. len is
* one-based, so len == 0 means you get "" returned. The returned
* extending for at most span columns. start_col is zero-based. span
* is one-based, so span == 0 means you get "" returned. The returned
* string is dynamically allocated, and should be freed. If dollars is
* TRUE, the caller might put "$" at the beginning or end of the line if
* it's too long. */
char *display_string(const char *buf, size_t start_col, size_t len, bool
dollars)
char *display_string(const char *buf, size_t start_col, size_t span,
bool dollars)
{
size_t start_index;
/* Index in buf of the first character shown. */
size_t column;
/* Screen column that start_index corresponds to. */
size_t alloc_len;
/* The length of memory allocated for converted. */
char *converted;
/* The string we return. */
size_t index;
/* Current position in converted. */
char *buf_mb;
int buf_mb_len;
/* If dollars is TRUE, make room for the "$" at the end of the
* line. */
if (dollars && len > 0 && strlenpt(buf) > start_col + len)
len--;
if (dollars && span > 0 && strlenpt(buf) > start_col + span)
span--;
if (len == 0)
if (span == 0)
return mallocstrcpy(NULL, "");
buf_mb = charalloc(mb_cur_max());
start_index = actual_x(buf, start_col);
column = strnlenpt(buf, start_index);
assert(column <= start_col);
/* Make sure there's enough room for the initial character, whether
* it's a multibyte control character, a non-control multibyte
* character, a tab character, or a null terminator. Rationale:
*
* multibyte control character followed by a null terminator:
* 1 byte ('^') + mb_cur_max() bytes + 1 byte ('\0')
* multibyte non-control character followed by a null terminator:
* mb_cur_max() bytes + 1 byte ('\0')
* tab character followed by a null terminator:
* mb_cur_max() bytes + (tabsize - 1) bytes + 1 byte ('\0')
*
* Since tabsize has a minimum value of 1, it can substitute for 1
* byte above. */
alloc_len = (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
converted = charalloc(alloc_len);
/* Allocate enough space to hold the entire converted buffer. */
converted = charalloc(strlen(buf) * (mb_cur_max() + tabsize) + 1);
index = 0;
#ifdef USING_OLD_NCURSES
seen_wide = FALSE;
#endif
buf += start_index;
if (buf[start_index] != '\0' && buf[start_index] != '\t' &&
if (*buf != '\0' && *buf != '\t' &&
(column < start_col || (dollars && column > 0))) {
/* We don't display all of buf[start_index] since it starts to
/* We don't display the complete first character as it starts to
* the left of the screen. */
buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
if (is_cntrl_mbchar(buf_mb)) {
if (is_cntrl_mbchar(buf)) {
if (column < start_col) {
char *character = charalloc(mb_cur_max());
int charlen, i;
character = control_mbrep(buf_mb, character, &charlen);
for (i = 0; i < charlen; i++)
converted[index++] = character[i];
start_col += mbwidth(character);
free(character);
start_index += buf_mb_len;
converted[index++] = control_mbrep(buf);
start_col++;
buf += parse_mbchar(buf, NULL, NULL);
}
}
#ifdef ENABLE_UTF8
else if (using_utf8() && mbwidth(buf_mb) == 2) {
else if (using_utf8() && mbwidth(buf) == 2) {
if (column >= start_col) {
converted[index++] = ' ';
start_col++;
@@ -1802,26 +1783,15 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
converted[index++] = ' ';
start_col++;
start_index += buf_mb_len;
buf += parse_mbchar(buf, NULL, NULL);
}
#endif
}
while (buf[start_index] != '\0') {
buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
while (*buf != '\0') {
int charlength, charwidth = 1;
if (mbwidth(buf + start_index) > 1)
seen_wide = TRUE;
/* Make sure there's enough room for the next character, whether
* it's a multibyte control character, a non-control multibyte
* character, a tab character, or a null terminator. */
if (index + mb_cur_max() + tabsize + 1 >= alloc_len - 1) {
alloc_len += (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
converted = charealloc(converted, alloc_len);
}
if (*buf_mb == ' ') {
if (*buf == ' ') {
/* Show a space as a visible character, or as a space. */
#ifndef NANO_TINY
if (ISSET(WHITESPACE_DISPLAY)) {
@@ -1833,7 +1803,9 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
#endif
converted[index++] = ' ';
start_col++;
} else if (*buf_mb == '\t') {
buf++;
continue;
} else if (*buf == '\t') {
/* Show a tab as a visible character, or as as a space. */
#ifndef NANO_TINY
if (ISSET(WHITESPACE_DISPLAY)) {
@@ -1850,57 +1822,52 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
converted[index++] = ' ';
start_col++;
}
/* If buf contains a control character, interpret it. */
} else if (is_cntrl_mbchar(buf_mb)) {
char *character = charalloc(mb_cur_max());
int charlen, i;
converted[index++] = '^';
start_col++;
character = control_mbrep(buf_mb, character, &charlen);
for (i = 0; i < charlen; i++)
converted[index++] = character[i];
start_col += mbwidth(character);
free(character);
/* If buf contains a non-control character, interpret it. If buf
* contains an invalid multibyte sequence, display it as such. */
} else {
char *character = charalloc(mb_cur_max());
int charlen, i;
#ifdef ENABLE_UTF8
/* Make sure an invalid sequence-starter byte is properly
* terminated, so that it doesn't pick up lingering bytes
* of any previous content. */
if (using_utf8() && buf_mb_len == 1)
buf_mb[1] = '\0';
#endif
character = mbrep(buf_mb, character, &charlen);
for (i = 0; i < charlen; i++)
converted[index++] = character[i];
start_col += mbwidth(character);
free(character);
buf++;
continue;
}
start_index += buf_mb_len;
charlength = length_of_char(buf, &charwidth);
/* If buf contains a control character, represent it. */
if (is_cntrl_mbchar(buf)) {
converted[index++] = '^';
converted[index++] = control_mbrep(buf);
start_col += 2;
buf += charlength;
continue;
}
/* If buf contains a valid non-control character, simply copy it. */
if (charlength > 0) {
for (; charlength > 0; charlength--)
converted[index++] = *(buf++);
start_col += charwidth;
#ifdef USING_OLD_NCURSES
if (charwidth > 1)
seen_wide = TRUE;
#endif
continue;
}
/* Represent an invalid sequence with the Replacement Character. */
converted[index++] = '\xEF';
converted[index++] = '\xBF';
converted[index++] = '\xBD';
start_col += 1;
buf++;
/* For invalid codepoints, skip extra bytes. */
if (charlength < -1)
buf += charlength + 7;
}
free(buf_mb);
assert(alloc_len >= index + 1);
/* Null-terminate converted. */
converted[index] = '\0';
/* Make sure converted takes up no more than len columns. */
index = actual_x(converted, len);
/* Make sure converted takes up no more than span columns. */
index = actual_x(converted, span);
null_at(&converted, index);
return converted;
@@ -1929,9 +1896,7 @@ void titlebar(const char *path)
assert(path != NULL || openfile->filename != NULL);
if (interface_color_pair[TITLE_BAR].bright)
wattron(topwin, A_BOLD);
wattron(topwin, interface_color_pair[TITLE_BAR].pairnum);
wattron(topwin, interface_color_pair[TITLE_BAR]);
blank_titlebar();
@@ -2018,8 +1983,7 @@ void titlebar(const char *path)
else if (statelen > 0)
mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
wattroff(topwin, A_BOLD);
wattroff(topwin, interface_color_pair[TITLE_BAR].pairnum);
wattroff(topwin, interface_color_pair[TITLE_BAR]);
wnoutrefresh(topwin);
reset_cursor();
@@ -2088,15 +2052,12 @@ void statusline(message_type importance, const char *msg, ...)
start_x = (COLS - strlenpt(foo) - 4) / 2;
wmove(bottomwin, 0, start_x);
if (interface_color_pair[STATUS_BAR].bright)
wattron(bottomwin, A_BOLD);
wattron(bottomwin, interface_color_pair[STATUS_BAR].pairnum);
wattron(bottomwin, interface_color_pair[STATUS_BAR]);
waddstr(bottomwin, "[ ");
waddstr(bottomwin, foo);
free(foo);
waddstr(bottomwin, " ]");
wattroff(bottomwin, A_BOLD);
wattroff(bottomwin, interface_color_pair[STATUS_BAR].pairnum);
wattroff(bottomwin, interface_color_pair[STATUS_BAR]);
/* Push the message to the screen straightaway. */
wnoutrefresh(bottomwin);
@@ -2193,23 +2154,17 @@ void onekey(const char *keystroke, const char *desc, int length)
{
assert(keystroke != NULL && desc != NULL);
if (interface_color_pair[KEY_COMBO].bright)
wattron(bottomwin, A_BOLD);
wattron(bottomwin, interface_color_pair[KEY_COMBO].pairnum);
wattron(bottomwin, interface_color_pair[KEY_COMBO]);
waddnstr(bottomwin, keystroke, actual_x(keystroke, length));
wattroff(bottomwin, A_BOLD);
wattroff(bottomwin, interface_color_pair[KEY_COMBO].pairnum);
wattroff(bottomwin, interface_color_pair[KEY_COMBO]);
length -= strlenpt(keystroke) + 1;
if (length > 0) {
waddch(bottomwin, ' ');
if (interface_color_pair[FUNCTION_TAG].bright)
wattron(bottomwin, A_BOLD);
wattron(bottomwin, interface_color_pair[FUNCTION_TAG].pairnum);
wattron(bottomwin, interface_color_pair[FUNCTION_TAG]);
waddnstr(bottomwin, desc, actual_x(desc, length));
wattroff(bottomwin, A_BOLD);
wattroff(bottomwin, interface_color_pair[FUNCTION_TAG].pairnum);
wattroff(bottomwin, interface_color_pair[FUNCTION_TAG]);
}
}
@@ -2273,7 +2228,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int
* marking highlight on just the pieces that need it. */
mvwaddstr(edit, line, 0, converted);
#ifndef USE_SLANG
#ifdef USING_OLD_NCURSES
/* Tell ncurses to really redraw the line without trying to optimize
* for what it thinks is already there, because it gets it wrong in
* the case of a wide character in column zero. See bug #31743. */
@@ -2304,9 +2259,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int
regmatch_t endmatch;
/* Match position for end_regex. */
if (varnish->bright)
wattron(edit, A_BOLD);
wattron(edit, COLOR_PAIR(varnish->pairnum));
wattron(edit, varnish->attributes);
/* Two notes about regexec(). A return value of zero means
* that there is a match. Also, rm_eo is the first
* non-matching character after the match. */
@@ -2563,8 +2516,7 @@ void edit_draw(filestruct *fileptr, const char *converted, int
}
}
tail_of_loop:
wattroff(edit, A_BOLD);
wattroff(edit, COLOR_PAIR(varnish->pairnum));
wattroff(edit, varnish->attributes);
}
}
#endif /* !DISABLE_COLOR */
@@ -3233,10 +3185,8 @@ void do_credits(void)
nodelay(edit, TRUE);
blank_titlebar();
blank_topbar();
blank_edit();
blank_statusbar();
blank_bottombars();
wrefresh(topwin);
wrefresh(edit);