Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4474bc0970 | ||
|
|
926fe5f789 | ||
|
|
d0c64e8086 | ||
|
|
de3260cdb1 | ||
|
|
23c3fd9bcd | ||
|
|
c118397a14 | ||
|
|
cd5d7faa4e | ||
|
|
3ca6c9241f | ||
|
|
a847d37b24 | ||
|
|
1cb945fe8e | ||
|
|
330741b650 | ||
|
|
f773d715e8 | ||
|
|
407f2d5bcf | ||
|
|
61e8b3d542 | ||
|
|
de36e1c120 | ||
|
|
a8c1dc1402 | ||
|
|
d60e7d374c | ||
|
|
2358badc65 | ||
|
|
efdb543f8c | ||
|
|
c24545fe9a | ||
|
|
8fbadecf0a | ||
|
|
a6605dce00 | ||
|
|
9ec546d293 | ||
|
|
fccfcccd37 | ||
|
|
03148804e6 | ||
|
|
3b86c7a190 | ||
|
|
7ef5c53263 | ||
|
|
6bd94040df | ||
|
|
b3bcc8eeac | ||
|
|
fb8fdcaa0a | ||
|
|
7fac9ec51c | ||
|
|
17f5c056ca | ||
|
|
914af36546 | ||
|
|
5c3d529761 | ||
|
|
8f10e364bb | ||
|
|
b1b9770c57 | ||
|
|
78037831f8 | ||
|
|
83ff644b6a | ||
|
|
3e22240fd5 | ||
|
|
34e086f038 | ||
|
|
f2ac20114e | ||
|
|
da5643853f | ||
|
|
437cb410e9 | ||
|
|
94e563232e | ||
|
|
ef7a7c5360 | ||
|
|
64aa8757a8 | ||
|
|
4ed3591703 | ||
|
|
3534d8ff25 | ||
|
|
a8a70f0f29 | ||
|
|
1d10d79860 | ||
|
|
8441887ec0 | ||
|
|
775f007348 | ||
|
|
414a1ecc8d | ||
|
|
e0bdf671b8 | ||
|
|
13fbf13b85 | ||
|
|
96f50b8d55 | ||
|
|
76d83070c4 | ||
|
|
1194a41cdb | ||
|
|
eba470a869 | ||
|
|
9a4a5454f2 | ||
|
|
af7201f9a0 | ||
|
|
2f80193d96 | ||
|
|
23595c8376 | ||
|
|
669453506c | ||
|
|
9de376deed | ||
|
|
94907aa534 | ||
|
|
7e5524bb66 | ||
|
|
e8c7cf2071 | ||
|
|
605f031833 | ||
|
|
c88d7ce530 | ||
|
|
9f884810b6 | ||
|
|
5d5666fba6 | ||
|
|
980e334e37 | ||
|
|
9bb64fccef | ||
|
|
6e3adf31b8 | ||
|
|
c67c431239 | ||
|
|
bf0268d41d | ||
|
|
b7c2513f7d | ||
|
|
892762d99c | ||
|
|
f7d320d932 | ||
|
|
0208ae7149 | ||
|
|
26fb907aa6 | ||
|
|
ea40765904 | ||
|
|
16a7fd4bfc | ||
|
|
eca6faee5b |
94
ChangeLog
94
ChangeLog
@@ -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
10
NEWS
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
14
doc/faq.html
14
doc/faq.html
@@ -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 "establishes a full duplex terminal connection to a remote host", and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
|
||||
<h2><a name="1.6"></a>1.6. What is the current version of nano?</h2>
|
||||
<blockquote><p>The current 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, "set nowrap" or "set smarthome".</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>
|
||||
|
||||
14
doc/nano.1
14
doc/nano.1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
481
po/nano.pot
481
po/nano.pot
File diff suppressed because it is too large
Load Diff
494
po/pt_BR.po
494
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
487
po/zh_CN.po
487
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
484
po/zh_TW.po
484
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
213
src/color.c
213
src/color.c
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
src/cut.c
26
src/cut.c
@@ -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
|
||||
|
||||
18
src/files.c
18
src/files.c
@@ -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 */
|
||||
{
|
||||
|
||||
@@ -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. */
|
||||
|
||||
12
src/move.c
12
src/move.c
@@ -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)
|
||||
|
||||
96
src/nano.c
96
src/nano.c
@@ -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();
|
||||
|
||||
@@ -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. */
|
||||
|
||||
20
src/proto.h
20
src/proto.h
@@ -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);
|
||||
|
||||
36
src/rcfile.c
36
src/rcfile.c
@@ -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);
|
||||
}
|
||||
|
||||
144
src/search.c
144
src/search.c
@@ -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 {
|
||||
|
||||
42
src/text.c
42
src/text.c
@@ -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
|
||||
|
||||
107
src/utils.c
107
src/utils.c
@@ -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++;
|
||||
}
|
||||
|
||||
522
src/winio.c
522
src/winio.c
@@ -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. */
|
||||
|
||||
@@ -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)\>"
|
||||
|
||||
@@ -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 " "
|
||||
|
||||
Reference in New Issue
Block a user