Compare commits

...

85 Commits

Author SHA1 Message Date
Benno Schulenberg
4474bc0970 po: update translations and regenerate POT file and PO files 2017-02-23 11:46:40 +01:00
Benno Schulenberg
926fe5f789 bump version numbers and add a news item for the 2.7.5 release 2017-02-23 11:33:45 +01:00
Mike Frysinger
d0c64e8086 syntax: gentoo: match .eblit files too 2017-02-22 13:35:36 -05:00
Benno Schulenberg
de3260cdb1 justify: reduce the character count when trimming trailing spaces
This fixes https://savannah.gnu.org/bugs/?50379.
2017-02-22 17:29:39 +01:00
Benno Schulenberg
23c3fd9bcd statusbar: display at most three consecutive alert messages
Cap the number of pauses when displaying ALERT messages, to avoid
making the user wait for ages when tens or hundreds of files were
specified on the command line.

This fixes https://savannah.gnu.org/bugs/?50362.
Reported-by: Mike Frysinger <vapier@gentoo.org>
2017-02-22 10:48:26 +01:00
Benno Schulenberg
c118397a14 tweaks: update some copyright years
Reflect the significant changes in painting and regex searching
in the copyright notices.
2017-02-21 20:27:49 +01:00
Mike Frysinger
cd5d7faa4e syntax: gentoo: flag mixed whitespace 2017-02-21 17:46:13 +01:00
Mike Frysinger
3ca6c9241f syntax: c++: add override keyword 2017-02-21 17:46:07 +01:00
David Lawrence Ramsey
a847d37b24 tweaks: split the grafting code off from copy_from_buffer()
Later on we're going to need the ability to graft a buffer into the
current file buffer without making a copy of it first.
2017-02-17 21:00:34 +01:00
David Lawrence Ramsey
1cb945fe8e tweaks: rename the functions for moving to and copying from a buffer
The name "filestruct" was a mistake.  What was meant was:
buffer -- a linked list of structs that each describe a line.
2017-02-17 20:06:32 +01:00
Benno Schulenberg
330741b650 tweaks: adjust two comments, to be more accurate 2017-02-17 19:59:34 +01:00
David Lawrence Ramsey
f773d715e8 tweaks: rewrap two lines and fix two typos 2017-02-17 19:55:54 +01:00
Benno Schulenberg
407f2d5bcf tweaks: move a comment and rewrap a line 2017-02-17 12:01:25 +01:00
David Lawrence Ramsey
61e8b3d542 screen: don't hide two-column characters at left edge in softwrap mode
When in softwrap mode, no "$" continuation characters are displayed,
so the code that reserves space for them should be skipped then.

This fixes https://savannah.gnu.org/bugs/?50335.
2017-02-17 11:39:37 +01:00
Benno Schulenberg
de36e1c120 tweaks: rename a variable, to be more general 2017-02-16 13:27:09 +01:00
Benno Schulenberg
a8c1dc1402 rcfile: don't accept empty regexes for syntax coloring
As a small service to the user, reject empty regex strings,
because an entirely empty regex simply doesn't make sense.

Inspired-by: Elia Geretto <elia.f.geretto@gmail.com>
2017-02-16 13:25:38 +01:00
Benno Schulenberg
d60e7d374c spelling: correctly adjust the length of a single-line region
When the marked region covers only a single line (or a part of it),
its new endpoint is not simply the length of the last line of the
spell-checked text, but instead the old endpoint plus the /change/
in length.

This fixes https://savannah.gnu.org/bugs/?50316.
Reported-by: David Lawrence Ramsey <pooka109@gmail.com>
2017-02-16 11:52:24 +01:00
Benno Schulenberg
2358badc65 painting: properly detect a change in start/end matches
The inversion of the logic in commit a6605dce was incomplete -- oops.

This fixes https://savannah.gnu.org/bugs/?50306.
2017-02-14 16:56:43 +01:00
David Lawrence Ramsey
efdb543f8c tweaks: fix compilation when configured with --enable-tiny 2017-02-13 20:41:48 +01:00
David Lawrence Ramsey
c24545fe9a tweaks: always directly do a refresh when the margin changes
The previous code only directly refreshed the screen when the margin
changed due to toggling line numbering on.  When the margin changed
due to toggling it off, it would indirectly refresh via do_toggle().
2017-02-13 20:25:38 +01:00
Benno Schulenberg
8fbadecf0a tweaks: adjust whitespace after preceding changes 2017-02-13 19:47:24 +01:00
Benno Schulenberg
a6605dce00 tweaks: rename two variables, to avoid double negatives 2017-02-13 19:47:20 +01:00
Benno Schulenberg
9ec546d293 tweaks: rename a function, and drop an unneeded parameter
When replacements are made, nothing needs to be reset any more
(it was done insufficiently anyway).  Just make sure the screen
is refreshed when all is done -- this may be superfluous when
doing interactive replacements, but not when replacing all.
2017-02-13 19:47:03 +01:00
Benno Schulenberg
fccfcccd37 tweaks: reshuffle an assignment and trim some comments 2017-02-13 19:46:51 +01:00
Benno Schulenberg
03148804e6 tweaks: scrap some debugging stuff 2017-02-13 19:46:41 +01:00
Benno Schulenberg
3b86c7a190 tweaks: discard the now unused multidata-resetting routine 2017-02-13 12:14:58 +01:00
Benno Schulenberg
7ef5c53263 painting: mark an unpaired start match as CWOULDBE
The lines that come after an unpaired start have to know about this.

This fixes https://savannah.gnu.org/bugs/?50293.
2017-02-13 11:18:54 +01:00
Benno Schulenberg
6bd94040df painting: don't look at the current multidata when coloring a line
When coloring a line, look only at the multidata of the preceding
line, and based on that determine what to seek in the current line.

This fixes https://savannah.gnu.org/bugs/?50292.
2017-02-13 10:03:07 +01:00
Benno Schulenberg
b3bcc8eeac painting: make use of the multidata of the preceding line
When painting a line, the multidata of the line /before/ it is valid
in most cases: it was determined just a moment ago.  And it tells us
all we need to know: whether there is an unpaired start match before
the current line or not.

The only exception is when painting the first line of the screen:
the multidata of the line before it might be stale.  So for the
first screen line we will always have to do some backtracking.
But that is left for later.

This fixes https://savannah.gnu.org/bugs/?50121.
2017-02-12 18:24:49 +01:00
Benno Schulenberg
fb8fdcaa0a tweaks: fiddle with some wordings in the texinfo document
Also, add two cross references: one in words, and one with a link.
2017-02-12 12:06:44 +01:00
David Lawrence Ramsey
7fac9ec51c docs: mention the ability to read from stdin
Also, remove the special "+line,column" argument from among the options,
since it isn't an option -- put it in a separate paragraph instead.
2017-02-12 11:39:51 +01:00
David Lawrence Ramsey
17f5c056ca tweaks: reduce duplicate code in new_magicline() and move_to_filestruct()
These two functions unnecessarily copy make_new_node(); use that instead.
2017-02-12 10:46:50 +01:00
Benno Schulenberg
914af36546 spelling: don't unnecessarily fiddle with the viewport
If we're somewhere deep into the file and do a spell check, and the
first misspelled word happens to be right there, onscreen already,
then this word does not need to be centered -- it /should/ not be
centered.  We should scroll only when necessary.
2017-02-10 22:09:03 +01:00
Benno Schulenberg
5c3d529761 tweaks: rename a variable and condense an if 2017-02-10 14:07:42 +01:00
Benno Schulenberg
8f10e364bb replacing: stop searching in a region when edge of buffer is reached
Just like when spell-checking, there is no need to wrap around when
doing replacements in a region, because a region cannot straddle the
buffer's edges.

This is the proper fix for https://savannah.gnu.org/bugs/?50158,
and fixes https://savannah.gnu.org/bugs/?50273.
2017-02-10 13:51:51 +01:00
David Lawrence Ramsey
b1b9770c57 tweaks: rename a variable and adjust some types in edit_scroll()
Scrolling works on rows, not on lines.  Accordingly, rename the nlines
variable to nrows.  And rows should be of the type int, not ssize_t.
2017-02-05 20:04:31 +01:00
David Lawrence Ramsey
78037831f8 tweaks: rename a variable in edit_scroll(), to make sense 2017-02-05 19:44:42 +01:00
David Lawrence Ramsey
83ff644b6a tweaks: do a comparison a bit differently in do_output() and do_deletion()
Make it clearer we're comparing the number of rows, not string lengths.
2017-02-05 12:30:09 +01:00
David Lawrence Ramsey
3e22240fd5 tweaks: rename mouse_x & mouse_y to mouse_col & mouse_row in do_mouse() 2017-02-05 12:30:09 +01:00
David Lawrence Ramsey
34e086f038 tweaks: rename a variable in edit_redraw(), to make sense 2017-02-05 12:30:09 +01:00
David Lawrence Ramsey
f2ac20114e tweaks: adjust and correct some comments 2017-02-05 12:29:43 +01:00
Benno Schulenberg
da5643853f replacing: start at the region's edge instead of one step before it
After the changes to the search routine, it is no longer necessary to
take one step back before starting a replacement session.

This fixes https://savannah.gnu.org/bugs/?50147.
2017-01-26 21:36:13 +01:00
Benno Schulenberg
437cb410e9 replacing: detect when the whole region has already been covered
Even when a match falls within the marked region, this does not mean
that it is a true match when already the whole file has been searched,
because then this is the second time we find this match.

This fixes https://savannah.gnu.org/bugs/?50158.
2017-01-26 21:25:15 +01:00
Benno Schulenberg
94e563232e general: stop the spell checker from crashing after the changes in search
The spell fixer does not provide a beginning line, so the search routine
should then not try to refer to any data of this line.  Also, since the
changes to the search routine there is no need any more to retreat one
step before starting to search for a misspelled word.

This fixes https://savannah.gnu.org/bugs/?50159.
2017-01-26 20:21:41 +01:00
Benno Schulenberg
ef7a7c5360 replacing: ignore the first match when the user said no
When the user answered No to a replacement prompt, skip the match
at the current position, so we don't stay stuck there.

Also, when replacing in the backward direction, or the match is
of length zero, skip the match at the current position, to not
get stuck.

This fixes https://savannah.gnu.org/bugs/?50126.
Reported-by: David Lawrence Ramsey <pooka109@gmail.com>

This also fixes https://savannah.gnu.org/bugs/?50137,
and refixes https://savannah.gnu.org/bugs/?48635,
and fixes https://savannah.gnu.org/bugs/?50144.
2017-01-26 17:41:49 +01:00
Benno Schulenberg
64aa8757a8 search: make the \b and \B anchors work correctly in both directions
That is: remove the special treatment of BOW anchors, and instead make
regexes match against the whole line instead of against an artificially
shortened one, because the latter method creates ghost matches: matches
at the starting point of the search that aren't really matches when seen
in the context of the whole line.

This fixes https://savannah.gnu.org/bugs/?50030.
2017-01-26 16:24:18 +01:00
Benno Schulenberg
4ed3591703 replacing: don't go outside of the selected region
When the tail of a match falls outside of the marked region,
it is in fact not a match and should not be replaced.

This fixes https://savannah.gnu.org/bugs/?50136.
2017-01-25 11:59:50 +01:00
Benno Schulenberg
3534d8ff25 replacing: compensate cursor position only for replacements /before/ it
When a replacement happens right at where the cursor sits, the position
of the cursor should not be adjusted, because the real cursor position
is between the current character and the preceding one: the place where
the cursor is shown is in fact right /after/ the insertion point.

This fixes https://savannah.gnu.org/bugs/?50134,
and fixes https://savannah.gnu.org/bugs/?50135.
2017-01-24 19:32:27 +01:00
Benno Schulenberg
a8a70f0f29 tweaks: slightly speed up the change detection for multiline matches 2017-01-22 10:17:24 +01:00
Benno Schulenberg
1d10d79860 painting: account for index maybe being zero after the preceding change 2017-01-22 10:12:27 +01:00
Benno Schulenberg
8441887ec0 painting: advance only when both start /and/ end match are zero-length 2017-01-22 10:07:48 +01:00
Benno Schulenberg
775f007348 tweaks: use a cheaper way to detect an end-of-line
There is no need to compute the line length: just avoid overstepping
the terminating NUL byte when being forced to advance the index.
2017-01-21 19:44:48 +01:00
Benno Schulenberg
414a1ecc8d tweaks: and rename another variable, to keep in style 2017-01-21 19:26:43 +01:00
Benno Schulenberg
e0bdf671b8 tweaks: rename another variable, to be shorter 2017-01-21 17:53:00 +01:00
Benno Schulenberg
13fbf13b85 tweaks: rename a variable, to be more general and match one elsewhere 2017-01-21 17:38:21 +01:00
Benno Schulenberg
96f50b8d55 tweaks: adjust some comments, reshuffle a line, and use a while loop 2017-01-21 17:36:52 +01:00
Benno Schulenberg
76d83070c4 tweaks: elide a variable plus its corresponding dark logic
Just assign the 'CNONE' value upfront, instead of figuring out
at the end of the line whether anything has been assigned yet.

Also, the old logic would leave unmarked a line that contains a
start match without any terminating end match.  Not serious, but
not right.
2017-01-21 16:56:50 +01:00
Benno Schulenberg
1194a41cdb tweaks: scrap a bunch of debugging lines -- they obscure the logic 2017-01-21 16:17:43 +01:00
Benno Schulenberg
eba470a869 tweaks: normalize some paragraph formatting in the FAQ 2017-01-21 12:31:01 +01:00
Benno Schulenberg
9a4a5454f2 painting: properly look for a new start match only after the end match 2017-01-21 12:30:56 +01:00
Benno Schulenberg
af7201f9a0 tweaks: reshuffle three variables 2017-01-21 12:30:51 +01:00
Benno Schulenberg
2f80193d96 tweaks: reshuffle a test to a better place 2017-01-21 12:30:44 +01:00
Benno Schulenberg
23595c8376 tweaks: differentiate single-regex matches from paired-regex matches
Don't use the 'startmatch' variable when the corresponding match is
not the start of anything but is the entire match by itself.
2017-01-21 12:30:38 +01:00
Benno Schulenberg
669453506c painting: when skipping a zero-length match, skip a character, not a byte 2017-01-21 12:29:27 +01:00
Benno Schulenberg
9de376deed painting: stay within the line when skipping zero-length matches
Don't blithely overshoot the end of a line when both start regex and
end regex match an empty string.  Overshooting would let the matching
run on into uncharted country and thus ultimately cause a segfault.

This fixes https://savannah.gnu.org/bugs/?50056.
Reported-by: Elia Geretto <elia.f.geretto@gmail.com>
2017-01-20 17:03:10 +01:00
Benno Schulenberg
94907aa534 painting: do not bluntly ignore zero-length start matches -- handle them
The segmentation fault that this causes when both start and end match are
zero-length will be tackled later (https://savannah.gnu.org/bugs/?50056).

This fixes https://savannah.gnu.org/bugs/?50078.
Inspired-by: Elia Geretto <elia.f.geretto@gmail.com>
2017-01-20 14:00:14 +01:00
Benno Schulenberg
7e5524bb66 painting: do not let a match for 'end' overlap a match for 'start'
During precalculation and in step_two, we begin looking for an end
match only after the full start match, not merely one byte beyond
its starting point.  So do that too when searching backward for an
unpaired start match.

Also, index can never be zero here, because if the match was of length
zero, this piece of code will have been skipped by the preceding goto.
So we can always use REG_NOTBOL here.

(That goto is wrong, by the way: https://savannah.gnu.org/bugs/?50078,
but that will follow later.)
2017-01-20 13:17:10 +01:00
Benno Schulenberg
e8c7cf2071 startup: report an error when the given line or column number is invalid
This fixes https://savannah.gnu.org/bugs/?50028.
2017-01-19 10:33:42 +01:00
Benno Schulenberg
605f031833 files: leave out the confusing "[from ./]" when prompting for a command
This fixes https://savannah.gnu.org/bugs/?49892.
2017-01-19 10:31:55 +01:00
Benno Schulenberg
c88d7ce530 search: begin from where we are, to be able to find the first \B
A search should start at the place of the cursor, not one step beyond,
so that the non-word boundary between the current character and the next
will be found.  Starting one step beyond the current character, as was
done until now, would find the non-word boundary between the next and
the overnext character as the first one.
2017-01-17 11:33:57 +01:00
Benno Schulenberg
9f884810b6 tweaks: use a subtraction instead of a counter
And return a better value, so that less calculation is needed.
2017-01-13 19:33:32 +01:00
Benno Schulenberg
5d5666fba6 tweaks: swap two blocks of code to reduce the number of #ifdefs 2017-01-13 19:29:39 +01:00
Benno Schulenberg
980e334e37 tweaks: rearrange some code to separate softwrap and normal mode more
(Ignore the indentation for the moment.)
2017-01-13 19:17:59 +01:00
Benno Schulenberg
9bb64fccef tweaks: chuck some obscuring debugging stuff 2017-01-13 17:47:55 +01:00
David Lawrence Ramsey
6e3adf31b8 tweaks: let update_line() return the correct value on error
If the given line is out of range of editwinrows, we don't display it
at all, so we obviously don't display more than one line of it.  Thus,
the return value in this case should be zero, not one.
2017-01-13 17:41:26 +01:00
David Lawrence Ramsey
c67c431239 tweaks: improve comments and formatting in update_line() 2017-01-13 17:36:02 +01:00
Benno Schulenberg
bf0268d41d tweaks: condense a comment, rename a variable, and use a while loop 2017-01-12 21:31:08 +01:00
Benno Schulenberg
b7c2513f7d tweaks: rename some variables, to better distinguish rows from lines
And columns from indexes -- columns are places on the screen, while
indexes point to characters in a line in the current buffer.
2017-01-12 19:32:21 +01:00
Benno Schulenberg
892762d99c tweaks: rename some variables, to show they refer to screen rows 2017-01-12 18:03:36 +01:00
Benno Schulenberg
f7d320d932 tweaks: rename a function, to show it refers to screen rows 2017-01-12 17:48:33 +01:00
Benno Schulenberg
0208ae7149 tweaks: rename a variable -- lines refers to buffer, rows to screen 2017-01-12 17:33:46 +01:00
Benno Schulenberg
26fb907aa6 screen: ehm... no, that was wrong: page_start /is/ a column position
(The mistake becomes visible when you go to the end of a very long line
of double-width characters: the $ will be shown on the right edge, even
though you're already at line's end.)

This reverts commit 16a7fd4b from yesterday.
2017-01-12 10:29:20 +01:00
Benno Schulenberg
ea40765904 tweaks: rename two variables, and always pass a valid result back
What is the point of parsing a number when you're not interested in
the result?  All callers of parse_num() pass a container for it.
2017-01-11 19:24:35 +01:00
Benno Schulenberg
16a7fd4bfc screen: don't compare a character index with a column position
This addresses part of https://savannah.gnu.org/patch/?9216.
Reported-by: David Lawrence Ramsey <pooka109@gmail.com>
2017-01-11 17:22:46 +01:00
Benno Schulenberg
eca6faee5b tweaks: free an option string also when it was invalid 2017-01-11 09:49:24 +01:00
58 changed files with 9434 additions and 9537 deletions

View File

@@ -1,3 +1,97 @@
Changes between v2.7.4 and v2.7.5:
----------------------------------
Benno Schulenberg (65):
bump version numbers and add a news item for the 2.7.5 release
files: leave out the confusing "[from ./]" when prompting for a command
general: stop the spell checker from crashing after the changes in search
justify: reduce the character count when trimming trailing spaces
painting: account for index maybe being zero after the preceding change
painting: advance only when both start /and/ end match are zero-length
painting: do not bluntly ignore zero-length start matches -- handle them
painting: do not let a match for 'end' overlap a match for 'start'
painting: don't look at the current multidata when coloring a line
painting: make use of the multidata of the preceding line
painting: mark an unpaired start match as CWOULDBE
painting: properly detect a change in start/end matches
painting: properly look for a new start match only after the end match
painting: stay within the line when skipping zero-length matches
painting: when skipping a zero-length match, skip a character, not a byte
rcfile: don't accept empty regexes for syntax coloring
replacing: compensate cursor position only for replacements /before/ it
replacing: detect when the whole region has already been covered
replacing: don't go outside of the selected region
replacing: ignore the first match when the user said no
replacing: start at the region's edge instead of one step before it
replacing: stop searching in a region when edge of buffer is reached
screen: don't compare a character index with a column position
screen: ehm... no, that was wrong: page_start /is/ a column position
search: begin from where we are, to be able to find the first \B
search: make the \b and \B anchors work correctly in both directions
spelling: correctly adjust the length of a single-line region
spelling: don't unnecessarily fiddle with the viewport
startup: report an error when the given line or column number is invalid
statusbar: display at most three consecutive alert messages
tweaks: adjust some comments, reshuffle a line, and use a while loop
tweaks: adjust two comments, to be more accurate
tweaks: adjust whitespace after preceding changes
tweaks: and rename another variable, to keep in style
tweaks: chuck some obscuring debugging stuff
tweaks: condense a comment, rename a variable, and use a while loop
tweaks: differentiate single-regex matches from paired-regex matches
tweaks: discard the now unused multidata-resetting routine
tweaks: elide a variable plus its corresponding dark logic
tweaks: fiddle with some wordings in the texinfo document
tweaks: free an option string also when it was invalid
tweaks: move a comment and rewrap a line
tweaks: normalize some paragraph formatting in the FAQ
tweaks: rearrange some code to separate softwrap and normal mode more
tweaks: rename a function, and drop an unneeded parameter
tweaks: rename a function, to show it refers to screen rows
tweaks: rename another variable, to be shorter
tweaks: rename a variable and condense an if
tweaks: rename a variable -- lines refers to buffer, rows to screen
tweaks: rename a variable, to be more general
tweaks: rename a variable, to be more general and match one elsewhere
tweaks: rename some variables, to better distinguish rows from lines
tweaks: rename some variables, to show they refer to screen rows
tweaks: rename two variables, and always pass a valid result back
tweaks: rename two variables, to avoid double negatives
tweaks: reshuffle an assignment and trim some comments
tweaks: reshuffle a test to a better place
tweaks: reshuffle three variables
tweaks: scrap a bunch of debugging lines -- they obscure the logic
tweaks: scrap some debugging stuff
tweaks: slightly speed up the change detection for multiline matches
tweaks: swap two blocks of code to reduce the number of #ifdefs
tweaks: update some copyright years
tweaks: use a cheaper way to detect an end-of-line
tweaks: use a subtraction instead of a counter
David Lawrence Ramsey (16):
docs: mention the ability to read from stdin
screen: don't hide two-column characters at left edge in softwrap mode
tweaks: adjust and correct some comments
tweaks: always directly do a refresh when the margin changes
tweaks: do a comparison a bit differently in do_output() and do_deletion()
tweaks: fix compilation when configured with --enable-tiny
tweaks: improve comments and formatting in update_line()
tweaks: let update_line() return the correct value on error
tweaks: reduce duplicate code in new_magicline() and move_to_filestruct()
tweaks: rename a variable and adjust some types in edit_scroll()
tweaks: rename a variable in edit_redraw(), to make sense
tweaks: rename a variable in edit_scroll(), to make sense
tweaks: rename mouse_x & mouse_y to mouse_col & mouse_row in do_mouse()
tweaks: rename the functions for moving to and copying from a buffer
tweaks: rewrap two lines and fix two typos
tweaks: split the grafting code off from copy_from_buffer()
Mike Frysinger (3):
syntax: c++: add override keyword
syntax: gentoo: flag mixed whitespace
syntax: gentoo: match .eblit files too
Changes between v2.7.3 and v2.7.4:
----------------------------------

10
NEWS
View File

@@ -1,3 +1,13 @@
2017.02.23 - GNU nano 2.7.5 "Nijntje" can properly search and replace
the \B and \b regex anchors, correctly repaints things
when multiline regexes with identical start and end are
involved, fixes a crash with zero-length regex matches,
does replacements at the edges of a marked region right,
no longer hides double-width characters at the head of
softwrapped rows, displays at most three warnings at
startup, and documents the ability to read a file from
standard input. Come tickle my ears.
2017.01.10 - GNU nano 2.7.4 "Red dress" undoes deletions in an orderly
manner again (bug was introduced in previous version),
sets the preferred x position for vertical movements

View File

@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/.
AC_INIT([GNU nano], [2.7.4], [nano-devel@gnu.org], [nano])
AC_INIT([GNU nano], [2.7.5], [nano-devel@gnu.org], [nano])
AC_CONFIG_SRCDIR([src/nano.c])
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE

View File

@@ -82,7 +82,7 @@
<h2><a name="1.5"></a>1.5. Why the name change from TIP?</h2>
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program &quot;establishes a full duplex terminal connection to a remote host&quot;, and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
<h2><a name="1.6"></a>1.6. What is the current version of nano?</h2>
<blockquote><p>The current version of nano <i>should</i> be <b>2.7.4</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
<blockquote><p>The current version of nano <i>should</i> be <b>2.7.5</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
<h2><a name="1.7"></a>1.7. I want to read the man page without having to download the program!</h2>
<blockquote><p>Jeez, demanding, aren't we? Okay, look <a href="https://nano-editor.org/dist/latest/nano.1.html">here</a>.</p></blockquote>
<hr width="100%">
@@ -164,8 +164,8 @@
<blockquote><p>It's not hard at all! But, your nano must <b>not</b> have been compiled with <b>--disable-nanorc</b>. Then simply copy the <b>sample.nanorc</b> that came with the nano source or your nano package (most likely in /usr/doc/nano) to .nanorc in your home directory. If you didn't get one, the syntax of the file is simple. Flags are turned on and off by using the words <b>set</b> and <b>unset</b> plus the long option name for the feature. For example, &quot;set nowrap&quot; or &quot;set smarthome&quot;.</p></blockquote>
<h2><a name="3.9b"></a>3.9b. How about in Win32?</h2>
<blockquote><p>If you're using the official nano .zip file and have extracted all the files, you should take the file nano.rc and place it somewhere on your Win32 system (for example, if you have write permission to do so, at the top of C:\). Then you must create an Environment variable called HOME which points to the directory where you put nano.rc. In Windows XP, you can get to Environment variables by right-clicking "My Computer" either on the desktop or in the Start Menu, and selecting Properties. This should bring up the System Properties panel. Then click the Advanced Tab, and there should be a button called Environment Variables. Click that to bring up the Environment Variables section. Now, under User Variables you should be able to click the New button, and make a new Variables Name called HOME, with the Variable Value of whatever path you copied nano.rc into (just the directory name; don't add nano.rc onto the end).</p>
<p>We're still working on documentation for enabling syntax highlighting on Win32; please bear with us.</p>
<p>Note that the nano.rc file must remain Unix-formatted in order for nano to understand it. In other words, you should probably use only nano to edit its config file. Other programs like Wordpad and Notepad will convert the file to DOS format when saving, and the latter does not even properly read Unix-formatted files to begin with.</p></blockquote>
<p>We're still working on documentation for enabling syntax highlighting on Win32; please bear with us.</p>
<p>Note that the nano.rc file must remain Unix-formatted in order for nano to understand it. In other words, you should probably use only nano to edit its config file. Other programs like Wordpad and Notepad will convert the file to DOS format when saving, and the latter does not even properly read Unix-formatted files to begin with.</p></blockquote>
<hr width="100%">
<h1><a name="4"></a>4. Running</h1>
@@ -210,9 +210,9 @@
<h2><a name="4.11"></a>4.11. How do I select text for or paste text from the clipboard in an X terminal when I'm running nano in one and nano's mouse support is turned on?</h2>
<blockquote><p>Try holding down the Shift key and selecting or pasting the text as you normally would.</p></blockquote>
<h2><a name="4.12"></a>4.12. On startup I get a message that says "Detected a legacy nano history file". Now older nano versions can't find my search history!</h2>
<blockquote><p>In nano 2.3.0, cursor-position history was introduced, and both history files now reside in a .nano subdirectory in your home directory. A newer nano will move an existing search-history file to this new location so it can continue to be used. This means that if you then try and use an earlier version of nano, it will be unable to see your current search history. To fix this, run the following command:<br>
<blockquote><p>In nano 2.3.0, cursor-position history was introduced, and both history files now reside in a .nano subdirectory in your home directory. A newer nano will move an existing search-history file to this new location so it can continue to be used. This means that if you then try and use an earlier version of nano, it will be unable to see your current search history. To fix this, run the following command:</p>
<p><b>ln -sf ~/.nano/search_history ~/.nano_history</b></p>
</p><p>The "migration service" (moving the search-history file to its new location) will be deleted from nano in early 2018.</p></blockquote>
<p>The "migration service" (moving the search-history file to its new location) will be deleted from nano in early 2018.</p></blockquote>
<hr width="100%">
<h1><a name="5"></a>5. Internationalization</h1>
@@ -248,8 +248,8 @@ Of course, due to the license change you can now use the <A HREF="http://www.was
<blockquote><p>That's fine. Send it <a href="mailto:nano-devel@gnu.org">our way</a>! Better yet, fix a <a href="https://savannah.gnu.org/bugs/?group=nano">bug</a> in the program or implement a <a href="https://nano-editor.org/dist/latest/TODO">cool feature</a> and send us that instead (though cash is fine too).</p></blockquote>
<h2><a name="7.3"></a>7.3. How do I submit a bug report or patch?</h2>
<blockquote>
<p>The best place to submit bugs is to the <a href="https://savannah.gnu.org/bugs/?group=nano">Savannah bug tracker</a> as you can check whether the bug you are submitting has already been submitted.
<p>Please submit patches for nano via the <a href="https://savannah.gnu.org/patch/?group=nano">Savannah project's patch manager</a> for the nano project.</p></blockquote>
<p>The best place to submit bugs is to the <a href="https://savannah.gnu.org/bugs/?group=nano">Savannah bug tracker</a> as you can check whether the bug you are submitting has already been submitted.
<p>Please submit patches for nano via the <a href="https://savannah.gnu.org/patch/?group=nano">Savannah project's patch manager</a> for the nano project.</p></blockquote>
<h2><a name="7.4"></a>7.4. How do I join the development team?</h2>
<blockquote><p>The easiest way is to consistently send in good patches that add some needed functionality, fix a bug or two, and/or make the program more optimized/efficient. Then ask nicely and you will probably be added to the Savannah development list and be given write access after a while. There is a lot of responsibility that goes along with being a team member, so don't think it's just something to add to your resume.</p></blockquote>
<h2><a name="7.5"></a>7.5. Can I have write access to the git tree?</h2>

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.7.4" "January 2017"
.TH NANO 1 "version 2.7.5" "February 2017"
.\" Please adjust this date whenever revising the manpage.
.SH NAME
@@ -34,6 +34,13 @@ top of copying Pico's look and feel, \fBnano\fP also implements some
missing (or disabled by default) features in Pico, such as "search and
replace" and "go to line and column number".
When opening a file, the cursor can be put on a specific line by adding
the line number with a plus sign (\fB+\fR) before the filename, and even
in a specific column by adding it with a comma.
If the first file specified is a dash (\fB\-\fR), \fBnano\fR will read
data from standard input.
.SH EDITING
Entering text and moving around in a file is straightforward: typing the
letters and using the normal cursor movement keys. Commands are entered
@@ -61,11 +68,6 @@ The default key bindings can be changed via the .nanorc file -- see
.SH OPTIONS
.TP
.B +\fIline\fP,\fIcolumn\fP
Places the cursor on line number \fIline\fP and at column number \fIcolumn\fP
(at least one of which must be specified) on startup, instead of the
default line 1, column 1.
.TP
.BR \-A ", " \-\-smarthome
Make the Home key smarter. When Home is pressed anywhere but at the
very beginning of non-whitespace characters on a line, the cursor will

View File

@@ -6,8 +6,8 @@
@smallbook
@set EDITION 0.4
@set VERSION 2.7.4
@set UPDATED January 2017
@set VERSION 2.7.5
@set UPDATED February 2017
@dircategory Editors
@direntry
@@ -21,7 +21,7 @@
@titlepage
@title GNU @code{nano}
@subtitle a small and friendly text editor.
@subtitle version 2.7.4
@subtitle version 2.7.5
@author Chris Allegretta
@page
@@ -97,21 +97,24 @@ The usual way to invoke @code{nano} is:
@code{nano [FILE]}
@end quotation
But it is also possible to specify one or more options, and to edit
several files in a row. Additionally, the cursor can be put on a
specific line of a file by adding the line number
But it is also possible to specify one or more options (see the next
section), and to edit several files in a row. Additionally, the cursor
can be put on a specific line of a file by adding the line number
with a plus sign before the filename, and even in a specific column by
adding it with a comma. So the complete command synopsis is:
adding it with a comma. So a more complete command synopsis is:
@quotation
@code{nano [OPTION]@dots{} [[+LINE[,COLUMN]|+,COLUMN] FILE]@dots{}}
@end quotation
But normallly you would set your preferred options in your
@file{.nanorc} file. And when the @code{positionlog} option is set
Normally, however, you set your preferred options in a @file{.nanorc}
file (see @xref{Nanorc Files}). And when using @code{set positionlog}
(making @code{nano} remember the cursor position when you close a file),
you will rarely need to specify a line number.
As a special case: when the first file specified is a dash, @code{nano}
will read data from standard input. Which means you can pipe the output
of a command straight into a buffer.
@node Command-line Options
@chapter Command-line Options
@@ -120,10 +123,6 @@ you will rarely need to specify a line number.
@table @option
@item +@var{line},@var{column}
Start at line number @var{line} and column number @var{column} (at least one of
which must be specified) instead of the default of line 1, column 1.
@item -A
@itemx --smarthome
Make the Home key smarter. When Home is pressed anywhere but at the

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.7.4" "January 2017"
.TH NANORC 5 "version 2.7.5" "February 2017"
.\" Please adjust this date whenever revising the manpage.
.SH NAME

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.7.4" "January 2017"
.TH RNANO 1 "version 2.7.5" "February 2017"
.\" Please adjust this date whenever revising the manpage.
.SH NAME

486
po/bg.po

File diff suppressed because it is too large Load Diff

487
po/ca.po

File diff suppressed because it is too large Load Diff

487
po/cs.po

File diff suppressed because it is too large Load Diff

487
po/da.po

File diff suppressed because it is too large Load Diff

494
po/de.po

File diff suppressed because it is too large Load Diff

515
po/eo.po

File diff suppressed because it is too large Load Diff

496
po/es.po

File diff suppressed because it is too large Load Diff

486
po/eu.po

File diff suppressed because it is too large Load Diff

487
po/fi.po

File diff suppressed because it is too large Load Diff

685
po/fr.po

File diff suppressed because it is too large Load Diff

1048
po/ga.po

File diff suppressed because it is too large Load Diff

483
po/gl.po

File diff suppressed because it is too large Load Diff

497
po/hr.po

File diff suppressed because it is too large Load Diff

487
po/hu.po

File diff suppressed because it is too large Load Diff

486
po/id.po

File diff suppressed because it is too large Load Diff

483
po/it.po

File diff suppressed because it is too large Load Diff

483
po/ja.po

File diff suppressed because it is too large Load Diff

487
po/ms.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

494
po/nb.po

File diff suppressed because it is too large Load Diff

520
po/nl.po

File diff suppressed because it is too large Load Diff

495
po/nn.po

File diff suppressed because it is too large Load Diff

483
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

483
po/ro.po

File diff suppressed because it is too large Load Diff

487
po/ru.po

File diff suppressed because it is too large Load Diff

484
po/sl.po

File diff suppressed because it is too large Load Diff

530
po/sr.po

File diff suppressed because it is too large Load Diff

544
po/sv.po

File diff suppressed because it is too large Load Diff

486
po/tr.po

File diff suppressed because it is too large Load Diff

512
po/uk.po

File diff suppressed because it is too large Load Diff

494
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

@@ -35,7 +35,7 @@ static char **filelist = NULL;
static size_t filelist_len = 0;
/* The number of files in the list. */
static int width = 0;
/* The number of files that we can display per line. */
/* The number of files that we can display per screen row. */
static int longest = 0;
/* The number of columns in the longest filename in the list. */
static size_t selected = 0;
@@ -385,7 +385,7 @@ char *do_browse_from(const char *inpath)
* set filelist_len to the number of files in that list, set longest to
* the width in columns of the longest filename in that list (between 15
* and COLS), and set width to the number of files that we can display
* per line. And sort the list too. */
* per screen row. And sort the list too. */
void read_the_list(const char *path, DIR *dir)
{
const struct dirent *nextdir;
@@ -482,15 +482,15 @@ functionptrtype parse_browser_input(int *kbinput)
return func_from_key(kbinput);
}
/* Set width to the number of files that we can display per line, if
* necessary, and display the list of files. */
/* Set width to the number of files that we can display per screen row,
* if necessary, and display the list of files. */
void browser_refresh(void)
{
size_t i;
int line = 0, col = 0;
/* The current line and column while the list is getting displayed. */
int the_line = 0, the_column = 0;
/* The line and column of the selected item. */
int row = 0, col = 0;
/* The current row and column while the list is getting displayed. */
int the_row = 0, the_column = 0;
/* The row and column of the selected item. */
char *info;
/* The additional information that we'll display about a file. */
@@ -501,7 +501,7 @@ void browser_refresh(void)
i = selected - selected % (editwinrows * width);
for (; i < filelist_len && line < editwinrows; i++) {
for (; i < filelist_len && row < editwinrows; i++) {
struct stat st;
const char *thename = tail(filelist[i]);
/* The filename we display, minus the path. */
@@ -524,16 +524,16 @@ void browser_refresh(void)
* remember its location to be able to place the cursor on it. */
if (i == selected) {
wattron(edit, hilite_attribute);
the_line = line;
the_row = row;
the_column = col;
}
blank_line(edit, line, col, longest);
blank_row(edit, row, col, longest);
/* If the name is too long, we display something like "...ename". */
if (dots)
mvwaddstr(edit, line, col, "...");
mvwaddstr(edit, line, dots ? col + 3 : col, disp);
mvwaddstr(edit, row, col, "...");
mvwaddstr(edit, row, dots ? col + 3 : col, disp);
free(disp);
@@ -591,7 +591,7 @@ void browser_refresh(void)
infolen = infomaxlen;
}
mvwaddstr(edit, line, col - infolen, info);
mvwaddstr(edit, row, col - infolen, info);
/* If this is the selected item, finish its highlighting. */
if (i == selected)
@@ -602,17 +602,17 @@ void browser_refresh(void)
/* Add some space between the columns. */
col += 2;
/* If the next entry isn't going to fit on the current line,
* move to the next line. */
/* If the next entry isn't going to fit on the current row,
* move to the next row. */
if (col > COLS - longest) {
line++;
row++;
col = 0;
}
}
/* If requested, put the cursor on the selected item and switch it on. */
if (ISSET(SHOW_CURSOR)) {
wmove(edit, the_line, the_column);
wmove(edit, the_row, the_column);
curs_set(1);
}

View File

@@ -3,7 +3,7 @@
* *
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
* 2010, 2011, 2013, 2014, 2015 Free Software Foundation, Inc. *
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
* Copyright (C) 2014, 2015, 2016, 2017 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -290,53 +290,12 @@ void color_update(void)
}
}
/* Reset the multiline coloring cache for one specific regex (given by
* index) for lines that need reevaluation. */
void reset_multis_for_id(filestruct *fileptr, int index)
{
filestruct *row;
/* Reset the cache of earlier lines, as far back as needed. */
for (row = fileptr->prev; row != NULL; row = row->prev) {
alloc_multidata_if_needed(row);
if (row->multidata[index] == CNONE)
break;
row->multidata[index] = -1;
}
for (; row != NULL; row = row->prev) {
alloc_multidata_if_needed(row);
if (row->multidata[index] != CNONE)
break;
row->multidata[index] = -1;
}
/* Reset the cache of the current line. */
fileptr->multidata[index] = -1;
/* Reset the cache of later lines, as far ahead as needed. */
for (row = fileptr->next; row != NULL; row = row->next) {
alloc_multidata_if_needed(row);
if (row->multidata[index] == CNONE)
break;
row->multidata[index] = -1;
}
for (; row != NULL; row = row->next) {
alloc_multidata_if_needed(row);
if (row->multidata[index] != CNONE)
break;
row->multidata[index] = -1;
}
refresh_needed = TRUE;
}
/* Reset multi-line strings around the filestruct fileptr, trying to be
* smart about stopping. Bool force means: reset everything regardless,
* useful when we don't know how much screen state has changed. */
void reset_multis(filestruct *fileptr, bool force)
/* Determine whether the matches of multiline regexes are still the same,
* and if not, schedule a screen refresh, so things will be repainted. */
void check_the_multis(filestruct *line)
{
const colortype *ink;
int nobegin = 0, noend = 0;
bool astart, anend;
regmatch_t startmatch, endmatch;
/* If there is no syntax or no multiline regex, there is nothing to do. */
@@ -344,38 +303,34 @@ void reset_multis(filestruct *fileptr, bool force)
return;
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
/* If it's not a multi-line regex, amscray. */
/* If it's not a multiline regex, skip. */
if (ink->end == NULL)
continue;
alloc_multidata_if_needed(fileptr);
alloc_multidata_if_needed(line);
if (force == FALSE) {
/* Check whether the multidata still matches the current situation. */
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)
astart = (regexec(ink->start, line->data, 1, &startmatch, 0) == 0);
anend = (regexec(ink->end, line->data, 1, &endmatch, 0) == 0);
/* Check whether the multidata still matches the current situation. */
if (line->multidata[ink->id] == CNONE ||
line->multidata[ink->id] == CWHOLELINE) {
if (!astart && !anend)
continue;
else if (fileptr->multidata[ink->id] == CSTARTENDHERE &&
!nobegin && !noend && startmatch.rm_so < endmatch.rm_so)
} else if (line->multidata[ink->id] == CSTARTENDHERE) {
if (astart && anend && startmatch.rm_so < endmatch.rm_so)
continue;
else if (fileptr->multidata[ink->id] == CBEGINBEFORE &&
nobegin && !noend)
} else if (line->multidata[ink->id] == CBEGINBEFORE) {
if (!astart && anend)
continue;
else if (fileptr->multidata[ink->id] == CENDAFTER &&
!nobegin && noend)
} else if (line->multidata[ink->id] == CENDAFTER) {
if (astart && !anend)
continue;
}
/* If we got here, things have changed. */
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);
/* There is a mismatch, so something changed: repaint. */
refresh_needed = TRUE;
return;
}
}
@@ -398,103 +353,85 @@ void precalc_multicolorinfo(void)
{
const colortype *ink;
regmatch_t startmatch, endmatch;
filestruct *fileptr, *endptr;
filestruct *line, *tailline;
if (openfile->colorstrings == NULL || ISSET(NO_COLOR_SYNTAX))
return;
#ifdef DEBUG
fprintf(stderr, "Entering precalculation of multiline color info\n");
fprintf(stderr, "Precalculating the multiline color info...\n");
#endif
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
/* If this is not a multi-line regex, skip it. */
if (ink->end == NULL)
continue;
#ifdef DEBUG
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;
#ifdef DEBUG
fprintf(stderr, "working on lineno %ld... ", (long)fileptr->lineno);
#endif
alloc_multidata_if_needed(fileptr);
for (line = openfile->fileage; line != NULL; line = line->next) {
int index = 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;
#ifdef DEBUG
fprintf(stderr, "start found at pos %lu... ", (unsigned long)startx);
#endif
/* Look first on this line for an end. */
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. */
alloc_multidata_if_needed(line);
/* Assume nothing applies until proven otherwise below. */
line->multidata[ink->id] = CNONE;
/* For an unpaired start match, mark all remaining lines. */
if (line->prev && line->prev->multidata[ink->id] == CWOULDBE) {
line->multidata[ink->id] = CWOULDBE;
continue;
}
/* When the line contains a start match, look for an end, and if
* found, mark all the lines that are affected. */
while (regexec(ink->start, line->data + index, 1,
&startmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) {
/* Begin looking for an end match after the start match. */
index += startmatch.rm_eo;
/* If there is an end match on this line, mark the line, but
* continue looking for other starts after it. */
if (regexec(ink->end, line->data + index, 1,
&endmatch, (index == 0) ? 0 : REG_NOTBOL) == 0) {
line->multidata[ink->id] = CSTARTENDHERE;
index += endmatch.rm_eo;
/* If both start and end are mere anchors, step ahead. */
if (startmatch.rm_so == startmatch.rm_eo &&
endmatch.rm_so == endmatch.rm_eo)
startx += 1;
fileptr->multidata[ink->id] = CSTARTENDHERE;
#ifdef DEBUG
fprintf(stderr, "end found on this line\n");
#endif
endmatch.rm_so == endmatch.rm_eo) {
/* When at end-of-line, we're done. */
if (line->data[index] == '\0')
break;
index = move_mbright(line->data, index);
}
continue;
}
/* Nice, we didn't find the end regex on this line. Let's start looking for it. */
for (endptr = fileptr->next; endptr != NULL; endptr = endptr->next) {
#ifdef DEBUG
fprintf(stderr, "\nadvancing to line %ld to find end... ", (long)endptr->lineno);
#endif
if (regexec(ink->end, endptr->data, 1, &endmatch, 0) == 0)
/* Look for an end match on later lines. */
tailline = line->next;
while (tailline != NULL) {
if (regexec(ink->end, tailline->data, 1, &endmatch, 0) == 0)
break;
tailline = tailline->next;
}
if (endptr == NULL) {
#ifdef DEBUG
fprintf(stderr, "no end found, breaking out\n");
#endif
if (tailline == NULL) {
line->multidata[ink->id] = CWOULDBE;
break;
}
#ifdef DEBUG
fprintf(stderr, "end found\n");
#endif
/* We found it, we found it, la la la la la. Mark all
* the lines in between and the end properly. */
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[ink->id] = CWHOLELINE;
#ifdef DEBUG
fprintf(stderr, "marking intermediary line %ld as CWHOLELINE\n", (long)fileptr->lineno);
#endif
line->multidata[ink->id] = CENDAFTER;
for (line = line->next; line != tailline; line = line->next) {
alloc_multidata_if_needed(line);
line->multidata[ink->id] = CWHOLELINE;
}
alloc_multidata_if_needed(endptr);
fileptr->multidata[ink->id] = CBEGINBEFORE;
#ifdef DEBUG
fprintf(stderr, "marking line %ld as CBEGINBEFORE\n", (long)fileptr->lineno);
#endif
/* Skip to the end point of the match. */
startx = endmatch.rm_eo;
#ifdef DEBUG
fprintf(stderr, "jumping to line %ld pos %lu to continue\n", (long)fileptr->lineno, (unsigned long)startx);
#endif
}
alloc_multidata_if_needed(tailline);
tailline->multidata[ink->id] = CBEGINBEFORE;
if (nostart && startx == 0) {
#ifdef DEBUG
fprintf(stderr, "no match\n");
#endif
fileptr->multidata[ink->id] = CNONE;
continue;
/* Begin looking for a new start after the end match. */
index = endmatch.rm_eo;
}
}
}

View File

@@ -49,10 +49,10 @@ inline bool keeping_cutbuffer(void)
void cut_line(void)
{
if (openfile->current != openfile->filebot)
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 0,
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
openfile->current->next, 0);
else
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current, 0,
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
openfile->current, strlen(openfile->current->data));
openfile->placewewant = 0;
}
@@ -68,7 +68,7 @@ void cut_marked(bool *right_side_up)
mark_order((const filestruct **)&top, &top_x,
(const filestruct **)&bot, &bot_x, right_side_up);
move_to_filestruct(&cutbuffer, &cutbottom, top, top_x, bot, bot_x);
extract_buffer(&cutbuffer, &cutbottom, top, top_x, bot, bot_x);
openfile->placewewant = xplustabs();
}
@@ -86,14 +86,14 @@ void cut_to_eol(void)
/* If we're not at the end of the line, move all the text from
* the current position up to it, not counting the newline at
* the end, into the cutbuffer. */
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
extract_buffer(&cutbuffer, &cutbottom, openfile->current,
openfile->current_x, openfile->current, data_len);
else if (openfile->current != openfile->filebot) {
/* If we're at the end of the line, and it isn't the last line
* of the file, move all the text from the current position up
* to the beginning of the next line, i.e. the newline at the
* end, into the cutbuffer. */
move_to_filestruct(&cutbuffer, &cutbottom, openfile->current,
extract_buffer(&cutbuffer, &cutbottom, openfile->current,
openfile->current_x, openfile->current->next, 0);
openfile->placewewant = xplustabs();
}
@@ -103,7 +103,7 @@ void cut_to_eol(void)
* file into the cutbuffer. */
void cut_to_eof(void)
{
move_to_filestruct(&cutbuffer, &cutbottom,
extract_buffer(&cutbuffer, &cutbottom,
openfile->current, openfile->current_x,
openfile->filebot, strlen(openfile->filebot->data));
}
@@ -172,10 +172,10 @@ void do_cut_text(bool copy_text, bool cut_till_eof)
if (cutbuffer != NULL) {
if (cb_save != NULL) {
cb_save->data += cb_save_len;
copy_from_filestruct(cb_save);
copy_from_buffer(cb_save);
cb_save->data -= cb_save_len;
} else
copy_from_filestruct(cutbuffer);
copy_from_buffer(cutbuffer);
/* If the copied region was marked forward, put the new desired
* x position at its end; otherwise, leave it at its beginning. */
@@ -194,7 +194,7 @@ void do_cut_text(bool copy_text, bool cut_till_eof)
refresh_needed = TRUE;
#ifndef DISABLE_COLOR
reset_multis(openfile->current, FALSE);
check_the_multis(openfile->current);
#endif
#ifdef DEBUG
@@ -223,7 +223,7 @@ void do_copy_text(void)
static struct filestruct *next_contiguous_line = NULL;
bool mark_set = openfile->mark_set;
/* Remember the current view port and cursor position. */
/* Remember the current viewport and cursor position. */
ssize_t is_edittop_lineno = openfile->edittop->lineno;
ssize_t is_current_lineno = openfile->current->lineno;
size_t is_current_x = openfile->current_x;
@@ -237,7 +237,7 @@ void do_copy_text(void)
next_contiguous_line = (mark_set ? NULL : openfile->current);
if (mark_set) {
/* Restore the view port and cursor position. */
/* Restore the viewport and cursor position. */
openfile->edittop = fsfromline(is_edittop_lineno);
openfile->current = fsfromline(is_current_lineno);
openfile->current_x = is_current_x;
@@ -268,7 +268,7 @@ void do_uncut_text(void)
/* Add a copy of the text in the cutbuffer to the current filestruct
* at the current cursor position. */
copy_from_filestruct(cutbuffer);
copy_from_buffer(cutbuffer);
#ifndef NANO_TINY
update_undo(PASTE);
@@ -291,7 +291,7 @@ void do_uncut_text(void)
refresh_needed = TRUE;
#ifndef DISABLE_COLOR
reset_multis(openfile->current, FALSE);
check_the_multis(openfile->current);
#endif
#ifdef DEBUG

View File

@@ -731,25 +731,26 @@ filestruct *read_line(char *buf, size_t buf_len, filestruct *prevnode)
* undoable means do we want to create undo records to try and undo
* this. Will also attempt to check file writability if fd > 0 and
* checkwritable == TRUE. */
void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkwritable)
void read_file(FILE *f, int fd, const char *filename, bool undoable,
bool checkwritable)
{
size_t num_lines = 0;
/* The number of lines in the file. */
size_t len = 0;
/* The length of the current line of the file. */
size_t bufx = MAX_BUF_SIZE;
/* The size of each chunk of the file that we read. */
char input = '\0';
/* The current input character. */
char *buf;
/* The buffer where we store chunks of the file. */
/* The buffer in which we assemble each line of the file. */
size_t bufx = MAX_BUF_SIZE;
/* The allocated size of the line buffer; increased as needed. */
filestruct *fileptr = openfile->current->prev;
/* The line after which to start inserting. */
int input_int;
/* The current value we read from the file, whether an input
* character or EOF. */
bool writable = TRUE;
/* Is the file writable (if we care) */
/* Whether the file is writable (in case we care). */
#ifndef NANO_TINY
int format = 0;
/* 0 = *nix, 1 = DOS, 2 = Mac, 3 = both DOS and Mac. */
@@ -837,7 +838,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw
if (len > 0) {
#ifndef NANO_TINY
/* If file conversion isn't disabled and the last character in
* This file is '\r', set format to Mac if we currently think
* this file is '\r', set format to Mac if we currently think
* the file is a *nix file, or to both DOS and Mac if we
* currently think the file is a DOS file. */
if (buf[len - 1] == '\r' && !ISSET(NO_CONVERT) && format < 2)
@@ -1069,10 +1070,11 @@ void do_insertfile(void)
if (execute) {
#ifndef DISABLE_MULTIBUFFER
if (ISSET(MULTIBUFFER))
msg = _("Command to execute in new buffer [from %s] ");
/* TRANSLATORS: The next four messages are prompts. */
msg = _("Command to execute in new buffer");
else
#endif
msg = _("Command to execute [from %s] ");
msg = _("Command to execute");
} else
#endif /* NANO_TINY */
{

View File

@@ -94,8 +94,8 @@ WINDOW *bottomwin;
* messages, the statusbar prompt, and a list of shortcuts. */
int editwinrows = 0;
/* How many rows does the edit window take up? */
int maxrows = 0;
/* How many usable lines there are (due to soft wrapping). */
int maxlines = 0;
/* How many file lines can be shown (due to soft wrapping). */
filestruct *cutbuffer = NULL;
/* The buffer where we store cut text. */

View File

@@ -100,7 +100,7 @@ void do_page_down(void)
/* If the cursor is less than a page away from the bottom of the file,
* put it at the end of the last line. */
if (openfile->current->lineno + maxrows - 2 >= openfile->filebot->lineno) {
if (openfile->current->lineno + maxlines - 2 >= openfile->filebot->lineno) {
do_last_line();
return;
}
@@ -112,7 +112,7 @@ void do_page_down(void)
openfile->placewewant = openfile->current_y = 0;
}
mustmove = (maxrows < 3) ? 1 : maxrows - 2;
mustmove = (maxlines < 3) ? 1 : maxlines - 2;
for (i = mustmove; i > 0 && openfile->current != openfile->filebot; i--) {
openfile->current = openfile->current->next;
@@ -488,11 +488,9 @@ void do_down(bool scroll_only)
openfile->current_x = actual_x(openfile->current->data,
openfile->placewewant);
/* If scroll_only is FALSE and if we're on the last line of the
* edit window, scroll the edit window down one line if we're in
* smooth scrolling mode, or down half a page if we're not. If
* scroll_only is TRUE, scroll the edit window down one line
* unconditionally. */
/* When the cursor was on the last line of the edit window (or when just
* scrolling without moving the cursor), scroll the edit window down -- one
* line if we're in smooth scrolling mode, and half a page otherwise. */
#ifndef NANO_TINY
if (openfile->current_y == editwinrows - 1 || amount > 0 || scroll_only) {
if (amount < 1 || scroll_only)

View File

@@ -278,7 +278,7 @@ void unpartition_filestruct(partition **p)
* current filestruct to a filestruct beginning with file_top and ending
* with file_bot. If no text is between (top, top_x) and (bot, bot_x),
* don't do anything. */
void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
void extract_buffer(filestruct **file_top, filestruct **file_bot,
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x)
{
filestruct *top_save;
@@ -353,14 +353,10 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
}
/* Since the text has now been saved, remove it from the filestruct. */
openfile->fileage = (filestruct *)nmalloc(sizeof(filestruct));
openfile->fileage = make_new_node(NULL);
openfile->fileage->data = mallocstrcpy(NULL, "");
openfile->filebot = openfile->fileage;
#ifndef DISABLE_COLOR
openfile->fileage->multidata = NULL;
#endif
/* Restore the current line and cursor position. If the mark begins
* inside the partition, set the beginning of the mark to where the
* saved text used to start. */
@@ -396,9 +392,9 @@ void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
new_magicline();
}
/* Copy all text from the given filestruct to the current filestruct
/* Meld the given buffer into the current file buffer
* at the current cursor position. */
void copy_from_filestruct(filestruct *somebuffer)
void ingraft_buffer(filestruct *somebuffer)
{
filestruct *top_save;
size_t current_x_save = openfile->current_x;
@@ -431,8 +427,8 @@ void copy_from_filestruct(filestruct *somebuffer)
free_filestruct(openfile->fileage);
/* Put the top and bottom of the current filestruct at the top and
* bottom of a copy of the passed buffer. */
openfile->fileage = copy_filestruct(somebuffer);
* bottom of the passed buffer. */
openfile->fileage = somebuffer;
openfile->filebot = openfile->fileage;
while (openfile->filebot->next != NULL)
openfile->filebot = openfile->filebot->next;
@@ -488,6 +484,14 @@ void copy_from_filestruct(filestruct *somebuffer)
new_magicline();
}
/* Meld a copy of the given buffer into the current file buffer. */
void copy_from_buffer(filestruct *somebuffer)
{
filestruct *the_copy = copy_filestruct(somebuffer);
ingraft_buffer(the_copy);
}
/* Create a new openfilestruct node. */
openfilestruct *make_new_opennode(void)
{
@@ -916,7 +920,7 @@ void version(void)
printf(_(" GNU nano, version %s\n"), VERSION);
#endif
printf(" (C) 1999..2016 Free Software Foundation, Inc.\n");
printf(_(" (C) 2014..%s the contributors to nano\n"), "2016");
printf(_(" (C) 2014..%s the contributors to nano\n"), "2017");
printf(
_(" Email: nano@nano-editor.org Web: https://nano-editor.org/"));
printf(_("\n Compiled options:"));
@@ -1387,9 +1391,6 @@ void do_toggle(int flag)
titlebar(NULL); /* Fall through. */
#ifndef DISABLE_COLOR
case NO_COLOR_SYNTAX:
#endif
#ifdef ENABLE_LINENUMBERS
case LINE_NUMBERS:
#endif
case SOFTWRAP:
refresh_needed = TRUE;
@@ -1694,7 +1695,7 @@ int do_input(bool allow_funcs)
#endif
#ifndef DISABLE_COLOR
if (f && !f->viewok)
reset_multis(openfile->current, FALSE);
check_the_multis(openfile->current);
#endif
if (!refresh_needed && (s->scfunc == do_delete || s->scfunc == do_backspace))
update_line(openfile->current, openfile->current_x);
@@ -1724,24 +1725,24 @@ void xoff_complaint(void)
/* Handle a mouse click on the edit window or the shortcut list. */
int do_mouse(void)
{
int mouse_x, mouse_y;
int retval = get_mouseinput(&mouse_x, &mouse_y, TRUE);
int mouse_col, mouse_row;
int retval = get_mouseinput(&mouse_col, &mouse_row, TRUE);
/* If the click is wrong or already handled, we're done. */
if (retval != 0)
return retval;
/* If the click was in the edit window, put the cursor in that spot. */
if (wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
bool sameline = (mouse_y == openfile->current_y);
/* Whether the click was on the line where the cursor is. */
if (wmouse_trafo(edit, &mouse_row, &mouse_col, FALSE)) {
bool sameline = (mouse_row == openfile->current_y);
/* Whether the click was on the row where the cursor is. */
filestruct *current_save = openfile->current;
#ifndef NANO_TINY
size_t current_x_save = openfile->current_x;
#endif
#ifdef DEBUG
fprintf(stderr, "mouse_y = %d, current_y = %ld\n", mouse_y, (long)openfile->current_y);
fprintf(stderr, "mouse_row = %d, current_y = %ld\n", mouse_row, (long)openfile->current_y);
#endif
#ifndef NANO_TINY
@@ -1750,18 +1751,18 @@ int do_mouse(void)
openfile->current = openfile->edittop;
while (openfile->current->next != NULL && current_row < mouse_y) {
while (openfile->current->next != NULL && current_row < mouse_row) {
current_row += strlenpt(openfile->current->data) / editwincols + 1;
openfile->current = openfile->current->next;
}
if (current_row > mouse_y) {
if (current_row > mouse_row) {
openfile->current = openfile->current->prev;
current_row -= strlenpt(openfile->current->data) / editwincols + 1;
openfile->current_x = actual_x(openfile->current->data,
((mouse_y - current_row) * editwincols) + mouse_x);
((mouse_row - current_row) * editwincols) + mouse_col);
} else
openfile->current_x = actual_x(openfile->current->data, mouse_x);
openfile->current_x = actual_x(openfile->current->data, mouse_col);
openfile->current_y = current_row;
ensure_line_is_visible();
@@ -1772,17 +1773,17 @@ int do_mouse(void)
ssize_t current_row = openfile->current_y;
/* Move to where the click occurred. */
while (current_row < mouse_y && openfile->current->next != NULL) {
while (current_row < mouse_row && openfile->current->next != NULL) {
openfile->current = openfile->current->next;
current_row++;
}
while (current_row > mouse_y && openfile->current->prev != NULL) {
while (current_row > mouse_row && openfile->current->prev != NULL) {
openfile->current = openfile->current->prev;
current_row--;
}
openfile->current_x = actual_x(openfile->current->data,
get_page_start(xplustabs()) + mouse_x);
get_page_start(xplustabs()) + mouse_col);
}
#ifndef NANO_TINY
@@ -1811,7 +1812,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
{
size_t current_len, i = 0;
#ifndef NANO_TINY
size_t orig_lenpt = 0;
size_t orig_rows = 0;
#endif
char *char_buf = charalloc(mb_cur_max());
int char_len;
@@ -1820,7 +1821,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
#ifndef NANO_TINY
if (ISSET(SOFTWRAP))
orig_lenpt = strlenpt(openfile->current->data);
orig_rows = strlenpt(openfile->current->data) / editwincols;
#endif
while (i < output_len) {
@@ -1886,7 +1887,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
/* If the number of screen rows that a softwrapped line occupies
* has changed, we need a full refresh. */
if (ISSET(SOFTWRAP) && refresh_needed == FALSE)
if (strlenpt(openfile->current->data) / editwincols != orig_lenpt / editwincols)
if ((strlenpt(openfile->current->data) / editwincols) != orig_rows)
refresh_needed = TRUE;
#endif
@@ -1895,7 +1896,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
openfile->placewewant = xplustabs();
#ifndef DISABLE_COLOR
reset_multis(openfile->current, FALSE);
check_the_multis(openfile->current);
#endif
if (!refresh_needed)
@@ -2557,7 +2558,8 @@ int main(int argc, char **argv)
* non-option argument, and it is followed by at least one other
* argument, the filename it applies to. */
if (0 < optind && optind < argc - 1 && argv[optind][0] == '+') {
parse_line_column(&argv[optind][1], &startline, &startcol);
if (!parse_line_column(&argv[optind][1], &startline, &startcol))
statusline(ALERT, _("Invalid line or column number"));
optind++;
}
@@ -2581,9 +2583,10 @@ int main(int argc, char **argv)
for (; i < argc; i++) {
/* If there's a +LINE or +LINE,COLUMN flag here, it is followed
* by at least one other argument: the filename it applies to. */
if (i < argc - 1 && argv[i][0] == '+')
parse_line_column(&argv[i][1], &iline, &icol);
else {
if (i < argc - 1 && argv[i][0] == '+') {
if (!parse_line_column(&argv[i][1], &iline, &icol))
statusline(ALERT, _("Invalid line or column number"));
} else {
/* If opening fails, don't try to position the cursor. */
if (!open_buffer(argv[i], FALSE))
continue;
@@ -2648,19 +2651,16 @@ int main(int argc, char **argv)
int needed_margin = digits(openfile->filebot->lineno) + 1;
/* Only enable line numbers when there is enough room for them. */
if (ISSET(LINE_NUMBERS) && needed_margin < COLS - 3) {
if (needed_margin != margin) {
margin = needed_margin;
editwincols = COLS - margin;
/* The margin has changed -- schedule a full refresh. */
refresh_needed = TRUE;
}
} else
#endif
{
margin = 0;
editwincols = COLS;
if (!ISSET(LINE_NUMBERS) || needed_margin > COLS - 4)
needed_margin = 0;
if (needed_margin != margin) {
margin = needed_margin;
editwincols = COLS - margin;
/* The margin has changed -- schedule a full refresh. */
refresh_needed = TRUE;
}
#endif
if (currmenu != MMAIN)
display_main_list();

View File

@@ -288,6 +288,8 @@ typedef struct lintstruct {
/* Whole line engulfed by the regex, start < me, end > me. */
#define CSTARTENDHERE (1<<5)
/* Regex starts and ends within this line. */
#define CWOULDBE (1<<6)
/* An unpaired start match on or before this line. */
#endif /* !DISABLE_COLOR */
/* More structure types. */

View File

@@ -76,7 +76,7 @@ extern WINDOW *topwin;
extern WINDOW *edit;
extern WINDOW *bottomwin;
extern int editwinrows;
extern int maxrows;
extern int maxlines;
extern filestruct *cutbuffer;
extern filestruct *cutbottom;
@@ -266,7 +266,7 @@ bool is_valid_mbstring(const char *s);
void set_colorpairs(void);
void color_init(void);
void color_update(void);
void reset_multis(filestruct *fileptr, bool force);
void check_the_multis(filestruct *line);
void alloc_multidata_if_needed(filestruct *fileptr);
void precalc_multicolorinfo(void);
#endif
@@ -302,7 +302,8 @@ void switch_to_next_buffer_void(void);
bool close_buffer(void);
#endif
filestruct *read_line(char *buf, size_t buf_len, filestruct *prevnode);
void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkwritable);
void read_file(FILE *f, int fd, const char *filename, bool undoable,
bool checkwritable);
int open_file(const char *filename, bool newfie, bool quiet, FILE **f);
char *get_next_filename(const char *name, const char *suffix);
void do_insertfile_void(void);
@@ -429,9 +430,10 @@ void renumber(filestruct *fileptr);
partition *partition_filestruct(filestruct *top, size_t top_x,
filestruct *bot, size_t bot_x);
void unpartition_filestruct(partition **p);
void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
void extract_buffer(filestruct **file_top, filestruct **file_bot,
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x);
void copy_from_filestruct(filestruct *somebuffer);
void ingraft_buffer(filestruct *somebuffer);
void copy_from_buffer(filestruct *somebuffer);
openfilestruct *make_new_opennode(void);
void unlink_opennode(openfilestruct *fileptr);
void delete_opennode(openfilestruct *fileptr);
@@ -532,8 +534,8 @@ void regexp_cleanup(void);
void not_found_msg(const char *str);
void search_replace_abort(void);
int search_init(bool replacing, bool use_answer);
int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
const filestruct *begin, size_t begin_x);
int findnextstr(const char *needle, bool whole_word_only, bool have_region,
size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x);
void do_search(void);
#ifndef NANO_TINY
void do_findprevious(void);
@@ -727,7 +729,7 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *count);
int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
#endif
const sc *get_shortcut(int *kbinput);
void blank_line(WINDOW *win, int y, int x, int n);
void blank_row(WINDOW *win, int y, int x, int n);
void blank_titlebar(void);
void blank_edit(void);
void blank_statusbar(void);
@@ -747,7 +749,7 @@ void edit_draw(filestruct *fileptr, const char *converted,
int line, size_t from_col);
int update_line(filestruct *fileptr, size_t index);
bool need_horizontal_scroll(const size_t old_column, const size_t new_column);
void edit_scroll(scroll_dir direction, ssize_t nlines);
void edit_scroll(scroll_dir direction, int nrows);
void edit_redraw(filestruct *old_current);
void edit_refresh(void);
void adjust_viewport(update_type location);

View File

@@ -648,7 +648,7 @@ void parse_colors(char *ptr, int rex_flags)
{
short fg, bg;
bool bright = FALSE;
char *fgstr;
char *item;
assert(ptr != NULL);
@@ -664,9 +664,9 @@ void parse_colors(char *ptr, int rex_flags)
return;
}
fgstr = ptr;
item = ptr;
ptr = parse_next_word(ptr);
if (!parse_color_names(fgstr, &fg, &bg, &bright))
if (!parse_color_names(item, &fg, &bg, &bright))
return;
if (*ptr == '\0') {
@@ -696,12 +696,16 @@ void parse_colors(char *ptr, int rex_flags)
continue;
}
fgstr = ++ptr;
item = ++ptr;
ptr = parse_next_regex(ptr);
if (ptr == NULL)
break;
goodstart = nregcomp(fgstr, rex_flags);
if (*item == '\0') {
rcfile_error(N_("Empty regex string"));
goodstart = FALSE;
} else
goodstart = nregcomp(item, rex_flags);
/* If the starting regex is valid, initialize a new color struct,
* and hook it in at the tail of the linked list. */
@@ -713,7 +717,7 @@ void parse_colors(char *ptr, int rex_flags)
newcolor->bright = bright;
newcolor->rex_flags = rex_flags;
newcolor->start_regex = mallocstrcpy(NULL, fgstr);
newcolor->start_regex = mallocstrcpy(NULL, item);
newcolor->start = NULL;
newcolor->end_regex = NULL;
@@ -746,19 +750,24 @@ void parse_colors(char *ptr, int rex_flags)
continue;
}
fgstr = ++ptr;
item = ++ptr;
ptr = parse_next_regex(ptr);
if (ptr == NULL)
break;
if (*item == '\0') {
rcfile_error(N_("Empty regex string"));
continue;
}
/* If the start regex was invalid, skip past the end regex
* to stay in sync. */
if (!goodstart)
continue;
/* If it's valid, save the ending regex string. */
if (nregcomp(fgstr, rex_flags))
newcolor->end_regex = mallocstrcpy(NULL, fgstr);
if (nregcomp(item, rex_flags))
newcolor->end_regex = mallocstrcpy(NULL, item);
/* Lame way to skip another static counter. */
newcolor->id = live_syntax->nmultis;
@@ -1147,10 +1156,9 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
rcfile_error(N_("Requested fill size \"%s\" is invalid"),
option);
wrap_at = -CHARS_FROM_EOL;
} else {
} else
UNSET(NO_WRAP);
free(option);
}
free(option);
} else
#endif
#ifndef NANO_TINY
@@ -1211,8 +1219,8 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
rcfile_error(N_("Requested tab size \"%s\" is invalid"),
option);
tabsize = -1;
} else
free(option);
}
free(option);
} else
assert(FALSE);
}

View File

@@ -3,7 +3,7 @@
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* Copyright (C) 2015, 2016 Benno Schulenberg *
* Copyright (C) 2015, 2016, 2017 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -38,8 +38,6 @@ static bool history_changed = FALSE;
#ifdef HAVE_REGEX_H
static bool regexp_compiled = FALSE;
/* Have we compiled any regular expressions? */
static bool bow_anchored = FALSE;
/* Whether a regex starts with a beginning-of-word anchor. */
/* Compile the given regular expression and store it in search_regexp.
* Return TRUE if the expression is valid, and FALSE otherwise. */
@@ -62,10 +60,6 @@ bool regexp_init(const char *regexp)
regexp_compiled = TRUE;
/* Remember whether the regex starts with a beginning-of-word anchor. */
bow_anchored = (strncmp(regexp, "\\<", 2) == 0 ||
strncmp(regexp, "\\b", 2) == 0);
return TRUE;
}
@@ -237,32 +231,23 @@ int search_init(bool replacing, bool use_answer)
* where we first started searching, at column begin_x. Return 1 when we
* found something, 0 when nothing, and -2 on cancel. When match_len is
* not NULL, set it to the length of the found string, if any. */
int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
const filestruct *begin, size_t begin_x)
int findnextstr(const char *needle, bool whole_word_only, bool have_region,
size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x)
{
size_t found_len = strlen(needle);
/* The length of a match -- will be recomputed for a regex. */
int feedback = 0;
/* When bigger than zero, show and wipe the "Searching..." message. */
filestruct *line = openfile->current;
const char *from = line->data, *found = NULL;
/* The line that we will search through now. */
const char *from = line->data + openfile->current_x;
/* The point in the line from where we start searching. */
const char *found = NULL;
/* A pointer to the location of the match, if any. */
size_t found_x;
/* The x coordinate of a found occurrence. */
time_t lastkbcheck = time(NULL);
/* 'from' might end up 1 character before the start or after the end
* of the line. This is fine because in that case strstrwrapper()
* will return immediately and say that no match was found, and
* 'from' will be properly set when the search continues on the
* previous or next line. */
if (ISSET(BACKWARDS_SEARCH)) {
if (openfile->current_x == 0)
from += -1;
else
from += move_mbleft(line->data, openfile->current_x);
} else
from += move_mbright(line->data, openfile->current_x);
enable_nodelay();
if (begin == NULL)
@@ -293,29 +278,29 @@ int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
}
/* Search for the needle in the current line. */
found = strstrwrapper(line->data, needle, from);
if (!skipone)
found = strstrwrapper(line->data, needle, from);
/* Ignore the initial match at the starting position: continue
* searching from the next character, or invalidate the match. */
if (skipone || (!whole_word_only && !came_full_circle &&
found == begin->data + begin_x)) {
skipone = FALSE;
if (ISSET(BACKWARDS_SEARCH) && from != line->data) {
from = line->data + move_mbleft(line->data, from - line->data);
continue;
} else if (!ISSET(BACKWARDS_SEARCH) && *from != '\0') {
from += move_mbright(from, 0);
continue;
}
found = NULL;
}
if (found != NULL) {
#ifdef HAVE_REGEX_H
/* When doing a regex search, compute the length of the match. */
if (ISSET(USE_REGEXP)) {
if (ISSET(USE_REGEXP))
found_len = regmatches[0].rm_eo - regmatches[0].rm_so;
/* If the regex starts with a BOW anchor, check that the found
* match actually is the start of a word. If not, continue. */
if (bow_anchored && found != line->data) {
size_t before = move_mbleft(line->data, found - line->data);
/* If a word char is before the match, skip this match. */
if (is_word_mbchar(line->data + before, FALSE)) {
if (ISSET(BACKWARDS_SEARCH))
from = line->data + before;
else
from = found + move_mbright(found, 0);
continue;
}
}
}
#endif
#ifndef DISABLE_SPELLER
/* When we're spell checking, a match should be a separate word;
@@ -343,15 +328,14 @@ int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
else
line = line->next;
/* If we've reached the start or end of the buffer, wrap around. */
/* If we've reached the start or end of the buffer, wrap around;
* but stop when spell-checking or replacing in a region. */
if (line == NULL) {
#ifndef DISABLE_SPELLER
/* When we're spell-checking, end-of-buffer means we're done. */
if (whole_word_only) {
if (whole_word_only || have_region) {
disable_nodelay();
return 0;
}
#endif
if (ISSET(BACKWARDS_SEARCH))
line = openfile->filebot;
else
@@ -478,7 +462,7 @@ void go_looking(void)
came_full_circle = FALSE;
didfind = findnextstr(last_search, FALSE, NULL,
didfind = findnextstr(last_search, FALSE, FALSE, NULL, FALSE,
openfile->current, openfile->current_x);
/* If we found something, and we're back at the exact same spot
@@ -527,7 +511,7 @@ int replace_regexp(char *string, bool create)
* subexpression match to the new line. */
if (create) {
strncpy(string, openfile->current->data +
openfile->current_x + regmatches[num].rm_so, i);
regmatches[num].rm_so, i);
string += i;
}
}
@@ -594,16 +578,19 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
ssize_t numreplaced = -1;
size_t match_len;
bool replaceall = FALSE;
bool skipone = FALSE;
bool mark_was_set = FALSE;
#ifndef NANO_TINY
bool old_mark_set = openfile->mark_set;
filestruct *top, *bot;
size_t top_x, bot_x;
bool right_side_up = FALSE;
/* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
* FALSE if (current, current_x) is. */
mark_was_set = openfile->mark_set;
/* If the mark is on, frame the region, and turn the mark off. */
if (old_mark_set) {
if (mark_was_set) {
mark_order((const filestruct **)&top, &top_x,
(const filestruct **)&bot, &bot_x, &right_side_up);
openfile->mark_set = FALSE;
@@ -611,7 +598,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
/* Start either at the top or the bottom of the marked region. */
if (!ISSET(BACKWARDS_SEARCH)) {
openfile->current = top;
openfile->current_x = (top_x == 0 ? 0 : top_x - 1);
openfile->current_x = top_x;
} else {
openfile->current = bot;
openfile->current_x = bot_x;
@@ -623,8 +610,8 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
while (TRUE) {
int i = 0;
int result = findnextstr(needle, whole_word_only, &match_len,
real_current, *real_current_x);
int result = findnextstr(needle, whole_word_only, mark_was_set,
&match_len, skipone, real_current, *real_current_x);
/* If nothing more was found, or the user aborted, stop looping. */
if (result < 1) {
@@ -634,15 +621,14 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
}
#ifndef NANO_TINY
if (old_mark_set) {
/* When we've found an occurrence outside of the marked region,
* stop the fanfare. */
if (openfile->current->lineno > bot->lineno ||
openfile->current->lineno < top->lineno ||
(openfile->current == bot && openfile->current_x > bot_x) ||
(openfile->current == top && openfile->current_x < top_x))
break;
}
/* An occurrence outside of the marked region means we're done. */
if (mark_was_set && (openfile->current->lineno > bot->lineno ||
openfile->current->lineno < top->lineno ||
(openfile->current == bot &&
openfile->current_x + match_len > bot_x) ||
(openfile->current == top &&
openfile->current_x < top_x)))
break;
#endif
/* Indicate that we found the search string. */
@@ -674,6 +660,10 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
break;
else if (i == 2)
replaceall = TRUE;
/* When "No" or moving backwards, the search routine should
* first move one character further before continuing. */
skipone = (i == 0 || ISSET(BACKWARDS_SEARCH));
}
if (i == 1 || replaceall) { /* Yes, replace it. */
@@ -690,7 +680,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
#ifndef NANO_TINY
/* If the mark was on and it was located after the cursor,
* then adjust its x position for any text length changes. */
if (old_mark_set && !right_side_up) {
if (mark_was_set && !right_side_up) {
if (openfile->current == openfile->mark_begin &&
openfile->mark_begin_x > openfile->current_x) {
if (openfile->mark_begin_x < openfile->current_x + match_len)
@@ -703,10 +693,10 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
/* If the mark was not on or it was before the cursor, then
* adjust the cursor's x position for any text length changes. */
if (!old_mark_set || right_side_up) {
if (!mark_was_set || right_side_up) {
#endif
if (openfile->current == real_current &&
openfile->current_x <= *real_current_x) {
openfile->current_x < *real_current_x) {
if (*real_current_x < openfile->current_x + match_len)
*real_current_x = openfile->current_x + match_len;
*real_current_x += length_change;
@@ -719,26 +709,18 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
#ifdef HAVE_REGEX_H
/* Don't find the same zero-length or BOL match again. */
if (match_len == 0 || (*needle == '^' && ISSET(USE_REGEXP)))
match_len++;
skipone = TRUE;
#endif
/* Set the cursor at the last character of the replacement
* text, so that searching will continue /after/ it. Note
* that current_x might be set to (size_t)-1 here. */
/* When moving forward, put the cursor just after the replacement
* text, so that searching will continue there. */
if (!ISSET(BACKWARDS_SEARCH))
openfile->current_x += match_len + length_change - 1;
openfile->current_x += match_len + length_change;
/* Update the file size, and put the changed line into place. */
openfile->totsize += mbstrlen(copy) - mbstrlen(openfile->current->data);
free(openfile->current->data);
openfile->current->data = copy;
#ifndef DISABLE_COLOR
/* Reset the precalculated multiline-regex hints only when
* the first replacement has been made. */
if (numreplaced == 0)
reset_multis(openfile->current, TRUE);
#endif
if (!replaceall) {
#ifndef DISABLE_COLOR
/* When doing syntax coloring, the replacement might require
@@ -758,9 +740,13 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
if (numreplaced == -1)
not_found_msg(needle);
#ifndef DISABLE_COLOR
else if (numreplaced > 0)
refresh_needed = TRUE;
#endif
#ifndef NANO_TINY
if (old_mark_set)
if (mark_was_set)
openfile->mark_set = TRUE;
#endif
@@ -890,7 +876,7 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
/* Try to extract one or two numbers from the user's response. */
if (!parse_line_column(answer, &line, &column)) {
statusbar(_("Invalid line or column number"));
statusline(ALERT, _("Invalid line or column number"));
return;
}
} else {

View File

@@ -92,7 +92,7 @@ char *invocation_error(const char *name)
void do_deletion(undo_type action)
{
#ifndef NANO_TINY
size_t orig_lenpt = 0;
size_t orig_rows = 0;
#endif
assert(openfile->current != NULL && openfile->current->data != NULL &&
@@ -113,7 +113,7 @@ void do_deletion(undo_type action)
update_undo(action);
if (ISSET(SOFTWRAP))
orig_lenpt = strlenpt(openfile->current->data);
orig_rows = strlenpt(openfile->current->data) / editwincols;
#endif
/* Move the remainder of the line "in", over the current character. */
@@ -184,7 +184,7 @@ void do_deletion(undo_type action)
/* If the number of screen rows that a softwrapped line occupies
* has changed, we need a full refresh. */
if (ISSET(SOFTWRAP) && refresh_needed == FALSE)
if (strlenpt(openfile->current->data) / editwincols != orig_lenpt / editwincols)
if ((strlenpt(openfile->current->data) / editwincols) != orig_rows)
refresh_needed = TRUE;
#endif
@@ -647,7 +647,7 @@ void undo_cut(undo *u)
else
goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
copy_from_filestruct(u->cutbuffer);
copy_from_buffer(u->cutbuffer);
if (u->xflags != WAS_MARKED_FORWARD && u->type != PASTE)
goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
@@ -949,7 +949,7 @@ void do_redo(void)
case INSERT:
redidmsg = _("text insert");
goto_line_posx(u->lineno, u->begin);
copy_from_filestruct(u->cutbuffer);
copy_from_buffer(u->cutbuffer);
free_filestruct(u->cutbuffer);
u->cutbuffer = NULL;
break;
@@ -2064,12 +2064,12 @@ void backup_lines(filestruct *first_line, size_t par_len)
/* Move the paragraph from the current buffer's filestruct to the
* justify buffer. */
move_to_filestruct(&jusbuffer, &jusbottom, top, 0, bot,
extract_buffer(&jusbuffer, &jusbottom, top, 0, bot,
(i == 1 && bot == openfile->filebot) ? strlen(bot->data) : 0);
/* Copy the paragraph back to the current buffer's filestruct from
* the justify buffer. */
copy_from_filestruct(jusbuffer);
copy_from_buffer(jusbuffer);
/* Move upward from the last line of the paragraph to the first
* line, putting first_line, edittop, current, and mark_begin at the
@@ -2445,10 +2445,11 @@ void do_justify(bool full_justify)
#endif
/* Break the current line. */
if (ISSET(JUSTIFY_TRIM)) {
if (ISSET(JUSTIFY_TRIM)) {
while (break_pos > 0 &&
is_blank_mbchar(&openfile->current->data[break_pos - 1])) {
break_pos--;
openfile->totsize--;
}
}
null_at(&openfile->current->data, break_pos);
@@ -2641,23 +2642,21 @@ bool do_int_spell_fix(const char *word)
* (current, current_x) (where searching starts) is at the top. */
if (right_side_up) {
openfile->current = top;
openfile->current_x = (size_t)(top_x - 1);
openfile->current_x = top_x;
openfile->mark_begin = bot;
openfile->mark_begin_x = bot_x;
} else
openfile->current_x = (size_t)(openfile->current_x - 1);
}
openfile->mark_set = FALSE;
} else
#endif
/* Otherwise, start from the top of the file. */
{
openfile->edittop = openfile->fileage;
openfile->current = openfile->fileage;
openfile->current_x = (size_t)-1;
openfile->current_x = 0;
}
/* Find the first whole occurrence of word. */
result = findnextstr(word, TRUE, NULL, NULL, 0);
result = findnextstr(word, TRUE, TRUE, NULL, FALSE, NULL, 0);
/* If the word isn't found, alert the user; if it is, allow correction. */
if (result == 0) {
@@ -2685,7 +2684,6 @@ bool do_int_spell_fix(const char *word)
/* If a replacement was given, go through all occurrences. */
if (proceed && strcmp(word, answer) != 0) {
openfile->current_x--;
#ifndef NANO_TINY
/* Replacements should happen only in the marked region. */
openfile->mark_set = old_mark_set;
@@ -2929,7 +2927,7 @@ const char *do_alt_speller(char *tempfile_name)
bool added_magicline = FALSE;
/* Whether we added a magicline after filebot. */
filestruct *top, *bot;
size_t top_x, bot_x;
size_t top_x, bot_x, was_x, new_x;
bool right_side_up = FALSE;
ssize_t mb_lineno_save = 0;
/* We're going to close the current file, and open the output of
@@ -3040,9 +3038,17 @@ const char *do_alt_speller(char *tempfile_name)
/* Adjust the end point of the marked region for any change in
* length of the region's last line. */
if (right_side_up)
current_x_save = strlen(openfile->filebot->data);
was_x = current_x_save;
else
openfile->mark_begin_x = strlen(openfile->filebot->data);
was_x = openfile->mark_begin_x;
if (top == bot)
new_x = was_x - bot_x + top_x + strlen(openfile->filebot->data);
else
new_x = strlen(openfile->filebot->data);
if (right_side_up)
current_x_save = new_x;
else
openfile->mark_begin_x = new_x;
/* Unpartition the filestruct so that it contains all the text
* again. Note that we've replaced the marked text originally

View File

@@ -85,25 +85,22 @@ int digits(ssize_t n)
}
#endif
/* Read a ssize_t from str, and store it in *val (if val is not NULL).
* On error, we return FALSE and don't change *val. Otherwise, we
* return TRUE. */
bool parse_num(const char *str, ssize_t *val)
/* Read an integer from str. If it parses okay, store it in *result
* and return TRUE; otherwise, return FALSE. */
bool parse_num(const char *str, ssize_t *result)
{
char *first_error;
ssize_t j;
ssize_t value;
/* The manual page for strtol() says this is required, and
* it looks like it is! */
/* The manual page for strtol() says this is required. */
errno = 0;
j = (ssize_t)strtol(str, &first_error, 10);
value = (ssize_t)strtol(str, &first_error, 10);
if (errno == ERANGE || *str == '\0' || *first_error != '\0')
return FALSE;
if (val != NULL)
*val = j;
*result = value;
return TRUE;
}
@@ -132,7 +129,7 @@ bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
firstpart = mallocstrcpy(NULL, str);
firstpart[comma - str] = '\0';
retval = parse_num(firstpart, line);
retval = parse_num(firstpart, line) && retval;
free(firstpart);
@@ -318,46 +315,66 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
}
#endif /* !DISABLE_SPELLER */
/* If we are searching backwards, we will find the last match that
* starts no later than start. Otherwise we find the first match
* starting no earlier than start. If we are doing a regexp search, we
* fill in the global variable regmatches with at most 9 subexpression
* matches. Also, all .rm_so elements are relative to the start of the
* whole match, so regmatches[0].rm_so == 0. */
/* Return the position of the needle in the haystack, or NULL if not found.
* When searching backwards, we will find the last match that starts no later
* than the given start; otherwise, we find the first match starting no earlier
* than start. If we are doing a regexp search, and we find a match, we fill
* in the global variable regmatches with at most 9 subexpression matches. */
const char *strstrwrapper(const char *haystack, const char *needle,
const char *start)
{
/* start can be 1 character before the start or after the end of the
* line. In either case, we just say no match was found. */
if ((start > haystack && *(start - 1) == '\0') || start < haystack)
return NULL;
#ifdef HAVE_REGEX_H
if (ISSET(USE_REGEXP)) {
if (ISSET(BACKWARDS_SEARCH)) {
if (regexec(&search_regexp, haystack, 1, regmatches, 0) == 0 &&
haystack + regmatches[0].rm_so <= start) {
const char *retval = haystack + regmatches[0].rm_so;
size_t last_find, ceiling, far_end;
size_t floor = 0, next_rung = 0;
/* The start of the search range, and the next start. */
/* Search forward until there are no more matches. */
while (regexec(&search_regexp, retval + 1, 1,
regmatches, REG_NOTBOL) == 0 &&
retval + regmatches[0].rm_so + 1 <= start)
retval += regmatches[0].rm_so + 1;
/* Finally, put the subexpression matches in global
* variable regmatches. The REG_NOTBOL flag doesn't
* matter now. */
regexec(&search_regexp, retval, 10, regmatches, 0);
return retval;
if (regexec(&search_regexp, haystack, 1, regmatches, 0) != 0)
return NULL;
far_end = strlen(haystack);
ceiling = start - haystack;
last_find = regmatches[0].rm_so;
/* A result beyond the search range also means: no match. */
if (last_find > ceiling)
return NULL;
/* Move the start-of-range forward until there is no more match;
* then the last match found is the first match backwards. */
while (regmatches[0].rm_so <= ceiling) {
floor = next_rung;
last_find = regmatches[0].rm_so;
/* If this is the last possible match, don't try to advance. */
if (last_find == ceiling)
break;
next_rung = move_mbright(haystack, last_find);
regmatches[0].rm_so = next_rung;
regmatches[0].rm_eo = far_end;
if (regexec(&search_regexp, haystack, 1, regmatches,
REG_STARTEND) != 0)
break;
}
} else if (regexec(&search_regexp, start, 10, regmatches,
(start > haystack) ? REG_NOTBOL : 0) == 0) {
const char *retval = start + regmatches[0].rm_so;
regexec(&search_regexp, retval, 10, regmatches, 0);
return retval;
/* Find the last match again, to get possible submatches. */
regmatches[0].rm_so = floor;
regmatches[0].rm_eo = far_end;
if (regexec(&search_regexp, haystack, 10, regmatches,
REG_STARTEND) != 0)
statusline(ALERT, "BAD: failed to refind the match!");
return haystack + regmatches[0].rm_so;
}
return NULL;
/* Do a forward regex search from the starting point. */
regmatches[0].rm_so = start - haystack;
regmatches[0].rm_eo = strlen(haystack);
if (regexec(&search_regexp, haystack, 10, regmatches,
REG_STARTEND) != 0)
return NULL;
else
return haystack + regmatches[0].rm_so;
}
#endif /* HAVE_REGEX_H */
if (ISSET(CASE_SENSITIVE)) {
@@ -513,14 +530,8 @@ size_t strlenpt(const char *text)
/* Append a new magicline to filebot. */
void new_magicline(void)
{
openfile->filebot->next = (filestruct *)nmalloc(sizeof(filestruct));
openfile->filebot->next = make_new_node(openfile->filebot);
openfile->filebot->next->data = mallocstrcpy(NULL, "");
openfile->filebot->next->prev = openfile->filebot;
openfile->filebot->next->next = NULL;
openfile->filebot->next->lineno = openfile->filebot->lineno + 1;
#ifndef DISABLE_COLOR
openfile->filebot->next->multidata = NULL;
#endif
openfile->filebot = openfile->filebot->next;
openfile->totsize++;
}

View File

@@ -3,7 +3,7 @@
* *
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
* Copyright (C) 2014, 2015, 2016, 2017 Benno Schulenberg *
* *
* GNU nano is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published *
@@ -1726,7 +1726,7 @@ const sc *get_shortcut(int *kbinput)
/* Move to (x, y) in win, and display a line of n spaces with the
* current attributes. */
void blank_line(WINDOW *win, int y, int x, int n)
void blank_row(WINDOW *win, int y, int x, int n)
{
wmove(win, y, x);
@@ -1737,23 +1737,23 @@ void blank_line(WINDOW *win, int y, int x, int n)
/* Blank the first line of the top portion of the window. */
void blank_titlebar(void)
{
blank_line(topwin, 0, 0, COLS);
blank_row(topwin, 0, 0, COLS);
}
/* Blank all the lines of the middle portion of the window, i.e. the
* edit window. */
void blank_edit(void)
{
int i;
int row;
for (i = 0; i < editwinrows; i++)
blank_line(edit, i, 0, COLS);
for (row = 0; row < editwinrows; row++)
blank_row(edit, row, 0, COLS);
}
/* Blank the first line of the bottom portion of the window. */
void blank_statusbar(void)
{
blank_line(bottomwin, 0, 0, COLS);
blank_row(bottomwin, 0, 0, COLS);
}
/* If the NO_HELP flag isn't set, blank the last two lines of the bottom
@@ -1761,8 +1761,8 @@ void blank_statusbar(void)
void blank_bottombars(void)
{
if (!ISSET(NO_HELP) && LINES > 4) {
blank_line(bottomwin, 1, 0, COLS);
blank_line(bottomwin, 2, 0, COLS);
blank_row(bottomwin, 1, 0, COLS);
blank_row(bottomwin, 2, 0, COLS);
}
}
@@ -1832,10 +1832,10 @@ char *display_string(const char *buf, size_t start_col, size_t span,
#endif
buf += start_index;
if (*buf != '\0' && *buf != '\t' &&
(column < start_col || (isdata && column > 0))) {
/* We don't display the complete first character as it starts to
* the left of the screen. */
/* If the first character starts before the left edge, or would be
* overwritten by a "$" token, then show spaces instead. */
if (*buf != '\0' && *buf != '\t' && (column < start_col ||
(column > 0 && isdata && !ISSET(SOFTWRAP)))) {
if (is_cntrl_mbchar(buf)) {
if (column < start_col) {
converted[index++] = control_mbrep(buf, isdata);
@@ -2088,6 +2088,7 @@ void warn_and_shortly_pause(const char *msg)
void statusline(message_type importance, const char *msg, ...)
{
va_list ap;
static int alerts = 0;
char *compound, *message;
size_t start_col;
bool bracketed;
@@ -2112,12 +2113,20 @@ void statusline(message_type importance, const char *msg, ...)
(lastmessage == MILD && importance == HUSH))
return;
/* Delay another alert message, to allow an earlier one to be noticed. */
if (lastmessage == ALERT)
/* If the ALERT status has been reset, reset the counter. */
if (lastmessage == HUSH)
alerts = 0;
/* Shortly pause after each of the first three alert messages,
* to give the user time to read them. */
if (lastmessage == ALERT && alerts < 4)
napms(1200);
if (importance == ALERT)
if (importance == ALERT) {
if (++alerts > 3)
msg = "Some warnings were suppressed";
beep();
}
lastmessage = importance;
@@ -2287,7 +2296,7 @@ void reset_cursor(void)
}
/* edit_draw() takes care of the job of actually painting a line into
* the edit window. fileptr is the line to be painted, at row line of
* the edit window. fileptr is the line to be painted, at row row of
* the window. converted is the actual string to be written to the
* window, with tabs and control characters replaced by strings of
* regular characters. from_col is the column number of the first
@@ -2295,7 +2304,7 @@ void reset_cursor(void)
* corresponds to character number actual_x(fileptr->data, from_col) of the
* line. */
void edit_draw(filestruct *fileptr, const char *converted,
int line, size_t from_col)
int row, size_t from_col)
{
#if !defined(NANO_TINY) || !defined(DISABLE_COLOR)
size_t from_x = actual_x(fileptr->data, from_col);
@@ -2317,24 +2326,24 @@ void edit_draw(filestruct *fileptr, const char *converted,
wattron(edit, interface_color_pair[LINE_NUMBER]);
#ifndef NANO_TINY
if (ISSET(SOFTWRAP) && from_x != 0)
mvwprintw(edit, line, 0, "%*s", margin - 1, " ");
mvwprintw(edit, row, 0, "%*s", margin - 1, " ");
else
#endif
mvwprintw(edit, line, 0, "%*ld", margin - 1, (long)fileptr->lineno);
mvwprintw(edit, row, 0, "%*ld", margin - 1, (long)fileptr->lineno);
wattroff(edit, interface_color_pair[LINE_NUMBER]);
}
#endif
/* First simply write the line -- afterward we'll add colors and the
* marking highlight on just the pieces that need it. */
mvwaddstr(edit, line, margin, converted);
/* First simply write the converted line -- afterward we'll add colors
* and the marking highlight on just the pieces that need it. */
mvwaddstr(edit, row, margin, converted);
#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. */
if (seen_wide)
wredrawln(edit, line, 1);
wredrawln(edit, row, 1);
#endif
#ifndef DISABLE_COLOR
@@ -2356,8 +2365,8 @@ void edit_draw(filestruct *fileptr, const char *converted,
/* The number of characters to paint. */
const char *thetext;
/* The place in converted from where painting starts. */
regmatch_t startmatch, endmatch;
/* Match positions of the start and end regexes. */
regmatch_t match;
/* The match positions of a single-line regex. */
/* Two notes about regexec(). A return value of zero means
* that there is a match. Also, rm_eo is the first
@@ -2378,36 +2387,35 @@ void edit_draw(filestruct *fileptr, const char *converted,
* REG_NOMATCH, there are no more matches in the
* line. */
if (regexec(varnish->start, &fileptr->data[index], 1,
&startmatch, (index == 0) ? 0 : REG_NOTBOL) ==
REG_NOMATCH)
&match, (index == 0) ? 0 : REG_NOTBOL) != 0)
break;
/* Skip over a zero-length regex match. */
if (startmatch.rm_so == startmatch.rm_eo) {
index += startmatch.rm_eo + 1;
/* If the match is of length zero, skip it. */
if (match.rm_so == match.rm_eo) {
index = move_mbright(fileptr->data,
index + match.rm_eo);
continue;
}
/* Translate the match to the beginning of the line. */
startmatch.rm_so += index;
startmatch.rm_eo += index;
index = startmatch.rm_eo;
match.rm_so += index;
match.rm_eo += index;
index = match.rm_eo;
/* If the matching piece is not visible, skip it. */
if (startmatch.rm_so >= till_x ||
startmatch.rm_eo <= from_x)
/* If the matching part is not visible, skip it. */
if (match.rm_eo <= from_x || match.rm_so >= till_x)
continue;
start_col = (startmatch.rm_so <= from_x) ?
0 : strnlenpt(fileptr->data,
startmatch.rm_so) - from_col;
start_col = (match.rm_so <= from_x) ?
0 : strnlenpt(fileptr->data,
match.rm_so) - from_col;
thetext = converted + actual_x(converted, start_col);
paintlen = actual_x(thetext, strnlenpt(fileptr->data,
startmatch.rm_eo) - from_col - start_col);
match.rm_eo) - from_col - start_col);
mvwaddnstr(edit, line, margin + start_col,
mvwaddnstr(edit, row, margin + start_col,
thetext, paintlen);
}
goto tail_of_loop;
@@ -2418,44 +2426,33 @@ void edit_draw(filestruct *fileptr, const char *converted,
/* The first line before fileptr that matches 'start'. */
const filestruct *end_line = fileptr;
/* The line that matches 'end'. */
regmatch_t startmatch, endmatch;
/* The match positions of the start and end regexes. */
/* First see if the multidata was maybe already calculated. */
if (fileptr->multidata[varnish->id] == CNONE)
goto tail_of_loop;
else if (fileptr->multidata[varnish->id] == CWHOLELINE) {
mvwaddnstr(edit, line, margin, converted, -1);
goto tail_of_loop;
} else if (fileptr->multidata[varnish->id] == CBEGINBEFORE) {
regexec(varnish->end, fileptr->data, 1, &endmatch, 0);
/* If the coloured part is scrolled off, skip it. */
if (endmatch.rm_eo <= from_x)
goto tail_of_loop;
paintlen = actual_x(converted, strnlenpt(fileptr->data,
endmatch.rm_eo) - from_col);
mvwaddnstr(edit, line, margin, converted, paintlen);
goto tail_of_loop;
/* Assume nothing gets painted until proven otherwise below. */
fileptr->multidata[varnish->id] = CNONE;
/* First check the multidata of the preceding line -- it tells
* us about the situation so far, and thus what to do here. */
if (start_line != NULL && start_line->multidata != NULL) {
if (start_line->multidata[varnish->id] == CWHOLELINE ||
start_line->multidata[varnish->id] == CENDAFTER ||
start_line->multidata[varnish->id] == CWOULDBE)
goto seek_an_end;
if (start_line->multidata[varnish->id] == CNONE ||
start_line->multidata[varnish->id] == CBEGINBEFORE ||
start_line->multidata[varnish->id] == CSTARTENDHERE)
goto step_two;
}
/* There is no precalculated multidata, or it is CENDAFTER or
* CSTARTENDHERE. In all cases, find out what to paint. */
/* When the multidata is unitialized, assume CNONE until one
* of the steps below concludes otherwise. */
if (fileptr->multidata[varnish->id] == -1)
fileptr->multidata[varnish->id] = CNONE;
/* First check if the beginning of the line is colored by a
* start on an earlier line, and an end on this line or later.
*
* So: find the first line before fileptr matching the start.
* If every match on that line is followed by an end, then go
* to step two. Otherwise, find a line after start_line that
* matches the end. If that line is not before fileptr, then
* paint the beginning of this line. */
/* The preceding line has no precalculated multidata. So, do
* some backtracking to find out what to paint. */
/* First step: see if there is a line before current that
* matches 'start' and is not complemented by an 'end'. */
while (start_line != NULL && regexec(varnish->start,
start_line->data, 1, &startmatch, 0) == REG_NOMATCH) {
/* There is no start; but if there is an end on this line,
/* There is no start on this line; but if there is an end,
* there is no need to look for starts on earlier lines. */
if (regexec(varnish->end, start_line->data, 0, NULL, 0) == 0)
goto step_two;
@@ -2473,30 +2470,31 @@ void edit_draw(filestruct *fileptr, const char *converted,
start_line->multidata[varnish->id] == CSTARTENDHERE))
goto step_two;
/* Skip over a zero-length regex match. */
if (startmatch.rm_so == startmatch.rm_eo)
goto tail_of_loop;
/* Now start_line is the first line before fileptr containing
* a start match. Is there a start on that line not followed
* by an end on that line? */
/* Is there an uncomplemented start on the found line? */
while (TRUE) {
index += startmatch.rm_so;
startmatch.rm_eo -= startmatch.rm_so;
if (regexec(varnish->end, start_line->data + index +
startmatch.rm_eo, 0, NULL,
(index + startmatch.rm_eo == 0) ?
0 : REG_NOTBOL) == REG_NOMATCH)
/* No end found after this start. */
/* Begin searching for an end after the start match. */
index += startmatch.rm_eo;
/* If there is no end after this last start, good. */
if (regexec(varnish->end, start_line->data + index, 1, &endmatch,
(index == 0) ? 0 : REG_NOTBOL) == REG_NOMATCH)
break;
index++;
/* Begin searching for a new start after the end match. */
index += endmatch.rm_eo;
/* If both start and end match are mere anchors, advance. */
if (startmatch.rm_so == startmatch.rm_eo &&
endmatch.rm_so == endmatch.rm_eo) {
if (start_line->data[index] == '\0')
break;
index = move_mbright(start_line->data, index);
}
/* If there is no later start on this line, next step. */
if (regexec(varnish->start, start_line->data + index,
1, &startmatch, REG_NOTBOL) == REG_NOMATCH)
/* No later start on this line. */
goto step_two;
}
/* Indeed, there is a start without an end on that line. */
seek_an_end:
/* We've already checked that there is no end between the start
* and the current line. But is there an end after the start
* at all? We don't paint unterminated starts. */
@@ -2505,33 +2503,26 @@ void edit_draw(filestruct *fileptr, const char *converted,
end_line = end_line->next;
/* If there is no end, there is nothing to paint. */
if (end_line == NULL)
if (end_line == NULL) {
fileptr->multidata[varnish->id] = CWOULDBE;
goto tail_of_loop;
/* If the end is scrolled off to the left, next step. */
if (end_line == fileptr && endmatch.rm_eo <= from_x) {
fileptr->multidata[varnish->id] = CBEGINBEFORE;
goto step_two;
}
/* Now paint the start of the line. However, if the end match
* is on a different line, paint the whole line, and go on. */
/* If the end is on a later line, paint whole line, and be done. */
if (end_line != fileptr) {
mvwaddnstr(edit, line, margin, converted, -1);
mvwaddnstr(edit, row, margin, converted, -1);
fileptr->multidata[varnish->id] = CWHOLELINE;
#ifdef DEBUG
fprintf(stderr, " Marking for id %i line %i as CWHOLELINE\n", varnish->id, line);
#endif
/* Don't bother looking for any more starts. */
goto tail_of_loop;
} else {
}
/* Only if it is visible, paint the part to be coloured. */
if (endmatch.rm_eo > from_x) {
paintlen = actual_x(converted, strnlenpt(fileptr->data,
endmatch.rm_eo) - from_col);
mvwaddnstr(edit, line, margin, converted, paintlen);
fileptr->multidata[varnish->id] = CBEGINBEFORE;
#ifdef DEBUG
fprintf(stderr, " Marking for id %i line %i as CBEGINBEFORE\n", varnish->id, line);
#endif
mvwaddnstr(edit, row, margin, converted, paintlen);
}
fileptr->multidata[varnish->id] = CBEGINBEFORE;
step_two:
/* Second step: look for starts on this line, but begin
* looking only after an end match, if there is one. */
@@ -2565,18 +2556,19 @@ void edit_draw(filestruct *fileptr, const char *converted,
paintlen = actual_x(thetext, strnlenpt(fileptr->data,
endmatch.rm_eo) - from_col - start_col);
mvwaddnstr(edit, line, margin + start_col,
mvwaddnstr(edit, row, margin + start_col,
thetext, paintlen);
fileptr->multidata[varnish->id] = CSTARTENDHERE;
#ifdef DEBUG
fprintf(stderr, " Marking for id %i line %i as CSTARTENDHERE\n", varnish->id, line);
#endif
}
index = endmatch.rm_eo;
/* Skip over a zero-length match. */
if (endmatch.rm_so == endmatch.rm_eo)
index += 1;
/* If both start and end match are anchors, advance. */
if (startmatch.rm_so == startmatch.rm_eo &&
endmatch.rm_so == endmatch.rm_eo) {
if (fileptr->data[index] == '\0')
break;
index = move_mbright(fileptr->data, index);
}
continue;
}
@@ -2588,17 +2580,14 @@ void edit_draw(filestruct *fileptr, const char *converted,
end_line = end_line->next;
/* If there is no end, we're done with this regex. */
if (end_line == NULL)
if (end_line == NULL) {
fileptr->multidata[varnish->id] = CWOULDBE;
break;
}
/* Paint the rest of the line. */
mvwaddnstr(edit, line, margin + start_col, thetext, -1);
/* Paint the rest of the line, and we're done. */
mvwaddnstr(edit, row, margin + start_col, thetext, -1);
fileptr->multidata[varnish->id] = CENDAFTER;
#ifdef DEBUG
fprintf(stderr, " Marking for id %i line %i as CENDAFTER\n", varnish->id, line);
#endif
/* We've painted to the end of the line, so don't
* bother checking for any more starts. */
break;
}
tail_of_loop:
@@ -2648,97 +2637,87 @@ void edit_draw(filestruct *fileptr, const char *converted,
}
wattron(edit, hilite_attribute);
mvwaddnstr(edit, line, margin + start_col, thetext, paintlen);
mvwaddnstr(edit, row, margin + start_col, thetext, paintlen);
wattroff(edit, hilite_attribute);
}
}
#endif /* !NANO_TINY */
}
/* Just update one line in the edit buffer. This is basically a wrapper
* for edit_draw(). The line will be displayed starting with
* fileptr->data[index]. Likely arguments are current_x or zero.
* Returns: Number of additional lines consumed (needed for SOFTWRAP). */
/* Redraw the line at fileptr. The line will be displayed so that the
* character with the given index is visible -- if necessary, the line
* will be horizontally scrolled. In softwrap mode, however, the entire
* line will be displayed. Likely values of index are current_x or zero.
* Return the number of additional rows consumed (when softwrapping). */
int update_line(filestruct *fileptr, size_t index)
{
int line = 0;
int row = 0;
/* The row in the edit window we will be updating. */
int extralinesused = 0;
char *converted;
/* The data of the line with tabs and control characters expanded. */
size_t page_start;
size_t from_col = 0;
/* From which column a horizontally scrolled line is displayed. */
#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
filestruct *tmp;
filestruct *line = openfile->edittop;
for (tmp = openfile->edittop; tmp && tmp != fileptr; tmp = tmp->next)
line += (strlenpt(tmp->data) / editwincols) + 1;
/* Find out on which screen row the target line should be shown. */
while (line != fileptr && line != NULL) {
row += (strlenpt(line->data) / editwincols) + 1;
line = line->next;
}
} else
#endif
line = fileptr->lineno - openfile->edittop->lineno;
row = fileptr->lineno - openfile->edittop->lineno;
if (line < 0 || line >= editwinrows)
return 1;
/* First, blank out the line. */
blank_line(edit, line, 0, COLS);
/* Next, convert variables that index the line to their equivalent
* positions in the expanded line. */
#ifndef NANO_TINY
if (ISSET(SOFTWRAP))
index = 0;
else
#endif
index = strnlenpt(fileptr->data, index);
page_start = get_page_start(index);
/* Expand the line, replacing tabs with spaces, and control
* characters with their displayed forms. */
converted = display_string(fileptr->data, page_start, editwincols, TRUE);
#ifdef DEBUG
if (ISSET(SOFTWRAP) && strlen(converted) >= editwincols - 2)
fprintf(stderr, "update_line(): converted(1) line = %s\n", converted);
#endif
/* Paint the line. */
edit_draw(fileptr, converted, line, page_start);
free(converted);
/* If the line is offscreen, don't even try to display it. */
if (row < 0 || row >= editwinrows)
return 0;
#ifndef NANO_TINY
if (!ISSET(SOFTWRAP)) {
#endif
if (page_start > 0)
mvwaddch(edit, line, margin, '$');
if (strlenpt(fileptr->data) > page_start + editwincols)
mvwaddch(edit, line, COLS - 1, '$');
#ifndef NANO_TINY
} else {
if (ISSET(SOFTWRAP)) {
size_t full_length = strlenpt(fileptr->data);
for (index += editwincols; index <= full_length && line < editwinrows - 1; index += editwincols) {
line++;
#ifdef DEBUG
fprintf(stderr, "update_line(): softwrap code, moving to %d index %lu\n", line, (unsigned long)index);
#endif
blank_line(edit, line, 0, COLS);
int starting_row = row;
for (from_col = 0; from_col <= full_length &&
row < editwinrows; from_col += editwincols) {
/* First, blank out the row. */
blank_row(edit, row, 0, COLS);
/* Expand the line, replacing tabs with spaces, and control
* characters with their displayed forms. */
converted = display_string(fileptr->data, index, editwincols, TRUE);
#ifdef DEBUG
if (ISSET(SOFTWRAP) && strlen(converted) >= editwincols - 2)
fprintf(stderr, "update_line(): converted(2) line = %s\n", converted);
converted = display_string(fileptr->data, from_col, editwincols, TRUE);
/* Draw the line. */
edit_draw(fileptr, converted, row++, from_col);
free(converted);
}
return (row - starting_row);
}
#endif
/* Paint the line. */
edit_draw(fileptr, converted, line, index);
free(converted);
extralinesused++;
}
}
#endif /* !NANO_TINY */
return extralinesused;
/* First, blank out the row. */
blank_row(edit, row, 0, COLS);
/* Next, find out from which column to start displaying the line. */
from_col = get_page_start(strnlenpt(fileptr->data, index));
/* Expand the line, replacing tabs with spaces, and control
* characters with their displayed forms. */
converted = display_string(fileptr->data, from_col, editwincols, TRUE);
/* Draw the line. */
edit_draw(fileptr, converted, row, from_col);
free(converted);
if (from_col > 0)
mvwaddch(edit, row, margin, '$');
if (strlenpt(fileptr->data) > from_col + editwincols)
mvwaddch(edit, row, COLS - 1, '$');
return 1;
}
/* Check whether old_column and new_column are on different "pages" (or that
@@ -2753,52 +2732,47 @@ bool need_horizontal_scroll(const size_t old_column, const size_t new_column)
return (get_page_start(old_column) != get_page_start(new_column));
}
/* When edittop changes, try and figure out how many lines we really
* have to work with, accounting for softwrap mode. */
void compute_maxrows(void)
/* Determine how many file lines we can display, accounting for softwraps. */
void compute_maxlines(void)
{
#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
int screenrow;
filestruct *line = openfile->edittop;
int row = 0;
maxrows = 0;
maxlines = 0;
for (screenrow = 0; screenrow < editwinrows && line != NULL; screenrow++) {
screenrow += strlenpt(line->data) / editwincols;
while (row < editwinrows && line != NULL) {
row += (strlenpt(line->data) / editwincols) + 1;
line = line->next;
maxrows++;
maxlines++;
}
if (screenrow < editwinrows)
maxrows += editwinrows - screenrow;
if (row < editwinrows)
maxlines += (editwinrows - row);
#ifdef DEBUG
fprintf(stderr, "recomputed: maxrows = %d\n", maxrows);
fprintf(stderr, "recomputed: maxlines = %d\n", maxlines);
#endif
} else
#endif /* !NANO_TINY */
maxrows = editwinrows;
maxlines = editwinrows;
}
/* Scroll the edit window in the given direction and the given number
* of lines, and draw new lines on the blank lines left after the
* scrolling. direction is the direction to scroll, either UPWARD or
* DOWNWARD, and nlines is the number of lines to scroll. We change
* edittop, and assume that current and current_x are up to date. We
* also assume that scrollok(edit) is FALSE. */
void edit_scroll(scroll_dir direction, ssize_t nlines)
/* Scroll the edit window in the given direction and the given number of rows,
* and draw new lines on the blank lines left after the scrolling. We change
* edittop, and assume that current and current_x are up to date. */
void edit_scroll(scroll_dir direction, int nrows)
{
ssize_t i;
filestruct *foo;
int i;
filestruct *line;
/* Part 1: nlines is the number of lines we're going to scroll the
* text of the edit window. */
/* Part 1: nrows is the number of rows we're going to scroll the text of
* the edit window. */
/* Move the top line of the edit window up or down (depending on the
* value of direction) nlines lines, or as many lines as we can if
* there are fewer than nlines lines available. */
for (i = nlines; i > 0; i--) {
/* Move the top line of the edit window up or down (depending on the value
* of direction) nrows rows, or as many rows as we can if there are fewer
* than nrows rows available. */
for (i = nrows; i > 0; i--) {
if (direction == UPWARD) {
if (openfile->edittop == openfile->fileage)
break;
@@ -2820,64 +2794,61 @@ void edit_scroll(scroll_dir direction, ssize_t nlines)
#endif
}
/* Limit nlines to the number of lines we could scroll. */
nlines -= i;
/* Limit nrows to the number of rows we could scroll. */
nrows -= i;
/* Don't bother scrolling zero lines, nor more than the window can hold. */
if (nlines == 0)
/* Don't bother scrolling zero rows, nor more than the window can hold. */
if (nrows == 0)
return;
if (nlines >= editwinrows)
if (nrows >= editwinrows)
refresh_needed = TRUE;
if (refresh_needed == TRUE)
return;
/* Scroll the text of the edit window up or down nlines lines,
* depending on the value of direction. */
/* Scroll the text of the edit window a number of rows up or down. */
scrollok(edit, TRUE);
wscrl(edit, (direction == UPWARD) ? -nlines : nlines);
wscrl(edit, (direction == UPWARD) ? -nrows : nrows);
scrollok(edit, FALSE);
/* Part 2: nlines is the number of lines in the scrolled region of
* the edit window that we need to draw. */
/* Part 2: nrows is now the number of rows in the scrolled region of the
* edit window that we need to draw. */
/* If the scrolled region contains only one line, and the line
* before it is visible in the edit window, we need to draw it too.
* If the scrolled region contains more than one line, and the lines
* before and after the scrolled region are visible in the edit
* window, we need to draw them too. */
nlines += (nlines == 1) ? 1 : 2;
/* If the scrolled region contains only one row, and the row before it is
* visible in the edit window, we need to draw it too. If the scrolled
* region is more than one row, and the rows before and after it are
* visible in the edit window, we need to draw them too. */
nrows += (nrows == 1) ? 1 : 2;
if (nlines > editwinrows)
nlines = editwinrows;
if (nrows > editwinrows)
nrows = editwinrows;
/* If we scrolled up, we're on the line before the scrolled region. */
foo = openfile->edittop;
line = openfile->edittop;
/* If we scrolled down, move down to the line before the scrolled region. */
if (direction == DOWNWARD) {
for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
foo = foo->next;
for (i = editwinrows - nrows; i > 0 && line != NULL; i--)
line = line->next;
}
/* Draw new lines on any blank lines before or inside the scrolled
* region. If we scrolled down and we're on the top line, or if we
* scrolled up and we're on the bottom line, the line won't be
* blank, so we don't need to draw it unless the mark is on or we're
* not on the first page. */
for (i = nlines; i > 0 && foo != NULL; i--) {
if ((i == nlines && direction == DOWNWARD) ||
/* Draw new lines on any blank rows before or inside the scrolled region.
* If we scrolled down and we're on the top row, or if we scrolled up and
* we're on the bottom row, the row won't be blank, so we don't need to
* draw it unless the mark is on or we're not on the first "page". */
for (i = nrows; i > 0 && line != NULL; i--) {
if ((i == nrows && direction == DOWNWARD) ||
(i == 1 && direction == UPWARD)) {
if (need_horizontal_scroll(openfile->placewewant, 0))
update_line(foo, (foo == openfile->current) ?
update_line(line, (line == openfile->current) ?
openfile->current_x : 0);
} else
update_line(foo, (foo == openfile->current) ?
update_line(line, (line == openfile->current) ?
openfile->current_x : 0);
foo = foo->next;
line = line->next;
}
compute_maxrows();
compute_maxlines();
}
/* Update any lines between old_current and current that need to be
@@ -2889,9 +2860,9 @@ void edit_redraw(filestruct *old_current)
openfile->placewewant = xplustabs();
/* If the current line is offscreen, scroll until it's onscreen. */
if (openfile->current->lineno >= openfile->edittop->lineno + maxrows ||
if (openfile->current->lineno >= openfile->edittop->lineno + maxlines ||
#ifndef NANO_TINY
(openfile->current->lineno == openfile->edittop->lineno + maxrows - 1 &&
(openfile->current->lineno == openfile->edittop->lineno + maxlines - 1 &&
ISSET(SOFTWRAP) && strlenpt(openfile->current->data) >= editwincols) ||
#endif
openfile->current->lineno < openfile->edittop->lineno) {
@@ -2903,13 +2874,13 @@ void edit_redraw(filestruct *old_current)
#ifndef NANO_TINY
/* If the mark is on, update all lines between old_current and current. */
if (openfile->mark_set) {
filestruct *foo = old_current;
filestruct *line = old_current;
while (foo != openfile->current) {
update_line(foo, 0);
while (line != openfile->current) {
update_line(line, 0);
foo = (foo->lineno > openfile->current->lineno) ?
foo->prev : foo->next;
line = (line->lineno > openfile->current->lineno) ?
line->prev : line->next;
}
} else
#endif
@@ -2918,8 +2889,8 @@ void edit_redraw(filestruct *old_current)
if (old_current != openfile->current && get_page_start(was_pww) > 0)
update_line(old_current, 0);
/* Update current if we've changed page, or if it differs from
* old_current and needs to be horizontally scrolled. */
/* Update current if the mark is on or it has changed "page", or if it
* differs from old_current and needs to be horizontally scrolled. */
if (need_horizontal_scroll(was_pww, openfile->placewewant) ||
(old_current != openfile->current &&
get_page_start(openfile->placewewant) > 0))
@@ -2933,15 +2904,15 @@ void edit_refresh(void)
filestruct *line;
int row = 0;
/* Figure out what maxrows should really be. */
compute_maxrows();
/* Figure out what maxlines should really be. */
compute_maxlines();
/* If the current line is out of view, get it back on screen. */
if (openfile->current->lineno < openfile->edittop->lineno ||
openfile->current->lineno >= openfile->edittop->lineno + maxrows) {
openfile->current->lineno >= openfile->edittop->lineno + maxlines) {
#ifdef DEBUG
fprintf(stderr, "edit-refresh: line = %ld, edittop = %ld and maxrows = %d\n",
(long)openfile->current->lineno, (long)openfile->edittop->lineno, maxrows);
fprintf(stderr, "edit-refresh: line = %ld, edittop = %ld and maxlines = %d\n",
(long)openfile->current->lineno, (long)openfile->edittop->lineno, maxlines);
#endif
adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : STATIONARY);
}
@@ -2954,14 +2925,14 @@ void edit_refresh(void)
while (row < editwinrows && line != NULL) {
if (line == openfile->current)
row += update_line(line, openfile->current_x) + 1;
row += update_line(line, openfile->current_x);
else
row += update_line(line, 0) + 1;
row += update_line(line, 0);
line = line->next;
}
while (row < editwinrows)
blank_line(edit, row++, 0, COLS);
blank_row(edit, row++, 0, COLS);
reset_cursor();
wnoutrefresh(edit);
@@ -2978,15 +2949,14 @@ void adjust_viewport(update_type manner)
{
int goal = 0;
/* If manner is CENTERING, move edittop half the number of window
* lines back from current. If manner is STATIONARY, move edittop
* back current_y lines if current_y is in range of the screen,
* 0 lines if current_y is below zero, or (editwinrows - 1) lines
* if current_y is too big. This puts current at the same place
* on the screen as before, or at the top or bottom if current_y is
* beyond either. If manner is FLOWING, move edittop back 0 lines
* or (editwinrows - 1) lines, depending or where current has moved.
* This puts the cursor on the first or the last line. */
/* If manner is CENTERING, move edittop half the number of window rows
* back from current. If manner is FLOWING, move edittop back 0 rows
* or (editwinrows - 1) rows, depending on where current has moved.
* This puts the cursor on the first or the last row. If manner is
* STATIONARY, move edittop back current_y rows if current_y is in range
* of the screen, 0 rows if current_y is below zero, or (editwinrows - 1)
* rows if current_y is too big. This puts current at the same place on
* the screen as before, or... at some undefined place. */
if (manner == CENTERING)
goal = editwinrows / 2;
else if (manner == FLOWING) {
@@ -3000,7 +2970,7 @@ void adjust_viewport(update_type manner)
} else {
goal = openfile->current_y;
/* Limit goal to (editwinrows - 1) lines maximum. */
/* Limit goal to (editwinrows - 1) rows maximum. */
if (goal > editwinrows - 1)
goal = editwinrows - 1;
}
@@ -3021,7 +2991,7 @@ void adjust_viewport(update_type manner)
#ifdef DEBUG
fprintf(stderr, "adjust_viewport(): setting edittop to lineno %ld\n", (long)openfile->edittop->lineno);
#endif
compute_maxrows();
compute_maxlines();
}
/* Unconditionally redraw the entire screen. */

View File

@@ -7,7 +7,7 @@ comment "//"
color brightred "\<[A-Z_][0-9A-Z_]+\>"
color green "\<(float|double|bool|char|int|short|long|sizeof|enum|void|auto|static|const|struct|union|typedef|extern|(un)?signed|inline)\>"
color green "\<((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\>"
color green "\<(class|namespace|template|public|protected|private|typename|this|friend|virtual|using|mutable|volatile|register|explicit)\>"
color green "\<(class|namespace|template|public|protected|private|typename|this|friend|virtual|override|using|mutable|volatile|register|explicit)\>"
color brightyellow "\<(for|if|while|do|else|case|default|switch)\>"
color brightyellow "\<(try|throw|catch|operator|new|delete)\>"
color magenta "\<(goto|continue|break|return)\>"

View File

@@ -1,6 +1,6 @@
## Here is an example for Gentoo ebuilds/eclasses.
syntax "ebuild" "\.e(build|class)$"
syntax "ebuild" "\.e(build|class|blit)$"
comment "#"
## All the standard portage functions
@@ -43,6 +43,8 @@ color yellow "(^|[[:space:]])#.*$"
color brightyellow ""(\\.|[^\"])*"" "'(\\.|[^'])*'"
## Trailing space is bad!
color ,green "[[:space:]]+$"
## Mixed whitespace is also bad.
color ,green " "
## Here is an example for Portage control files.
##
@@ -66,3 +68,5 @@ color brightmagenta "^[[:space:]]*(=|~|<|<=|>|>=)"
color yellow "#.*$"
## Trailing space is bad!
color ,green "[[:space:]]+$"
## Mixed whitespace is also bad.
color ,green " "