Compare commits

...

76 Commits

Author SHA1 Message Date
Benno Schulenberg
084dda3837 po: update translations and regenerate POT file and PO files 2018-01-02 16:07:04 +01:00
Benno Schulenberg
30f367e0db bump version numbers and add a news item for the 2.9.2 release 2018-01-02 15:51:12 +01:00
Benno Schulenberg
5965e80a38 tweaks: fold some regexes into one another, for conciseness
The anchored "^texture" appears to have been a mistake.

Inspired-by: Tom Levy <tomlevy93@gmail.com>
2018-01-01 16:00:18 +01:00
Tom Levy
a794c3318b syntax: go: sign of exponent in number literal is optional
Signed-off-by: Tom Levy <tomlevy93@gmail.com>
2018-01-01 15:27:31 +01:00
Tom Levy
d04b0c123e syntax: go: fix word boundary before dot in number literal
The fragment "\<\." can never match anything because \< matches the
beginning of a word but "." is not a word character.

Replace \< with \B (the empty string not at the edge of a word).

Signed-off-by: Tom Levy <tomlevy93@gmail.com>
2018-01-01 15:25:26 +01:00
Benno Schulenberg
21cd953e85 syntax: lua: condense some regexes, tweak comments, reorder things
Also remove some redundant backslashes and parentheses.
2018-01-01 14:59:00 +01:00
Tom Levy
058b9da9b9 syntax: lua: add new and missing standard library functions
The list now includes all the Lua 5.3 functions listed on
https://www.lua.org/manual/5.3/#index.

Also, remove the coloring of just the library name, so that
only known library functions get highlighted.

Signed-off-by: Tom Levy <tomlevy93@gmail.com>
2018-01-01 14:35:19 +01:00
Tom Levy
38a10a62d0 syntax: lua: support fractional part and exponent for decimal and hex
As of Lua 5.2: "Hexadecimal constants also accept an optional fractional
part plus an optional binary exponent, marked by a letter 'p' or 'P'"
(see at the end of https://www.lua.org/manual/5.2/manual.html#3.1).

The new regexes do not match a leading nor a trailing dot, but they
are good enough.  Discussion on the mailing list:
https://lists.gnu.org/archive/html/nano-devel/2017-12/msg00121.html

Signed-off-by: Tom Levy <tomlevy93@gmail.com>
2018-01-01 14:15:14 +01:00
Tom Levy
091e8faf6d syntax: lua: require at least one digit for hexadecimal numbers
Since a "0x" by itself is invalid.  Also add word boundaries, so that
e.g. "00x1" (which is invalid) does not get partial highlighting.

Also remove some redundant backslashes from the strings regex.

Signed-off-by: Tom Levy <tomlevy93@gmail.com>
2018-01-01 13:51:10 +01:00
Benno Schulenberg
d8ea89f6a6 gnulib: update to its current upstream state 2017-12-31 10:21:52 +01:00
Benno Schulenberg
1f48ed0412 syntaxes: remove redundant word-boundary markers 2017-12-30 17:32:15 +01:00
Benno Schulenberg
b18bcbbe9f tweaks: use for git the more faithful "less -x1,5" suggested by Brand 2017-12-30 16:38:19 +01:00
Benno Schulenberg
920730f1aa tweaks: use spaces for alignment also in the THANKS file 2017-12-30 16:34:12 +01:00
Benno Schulenberg
9506b51101 docs: say thanks to some fairly recent translators, and rename one 2017-12-30 16:27:58 +01:00
Benno Schulenberg
918d0e71ab docs: mention that the source code is best viewed with a tab size of 4 2017-12-30 11:47:22 +01:00
Benno Schulenberg
484a199175 tweaks: convert the indentation of the NEWS file too
To keep the blocks of text more-or-less aligned.
2017-12-30 11:31:49 +01:00
Benno Schulenberg
17429d7f38 tweaks: fix some whitespace errors, and convert alignment tabs to spaces 2017-12-29 21:35:14 +01:00
Benno Schulenberg
87206c0607 tweaks: convert the indentation to use only tabs
Each leading tab is converted to two tabs, and any leading four spaces
is converted to one tab.  The intended tab size (for keeping most lines
within 80 columns) is now four.
2017-12-29 20:06:50 +01:00
Benno Schulenberg
b574f73e60 tweaks: add a separate function that actually wipes the status bar 2017-12-29 17:40:41 +01:00
Benno Schulenberg
eac90c3eff prompt: blank the bar when a "continue?" is answered with No or ^C
This fixes https://savannah.gnu.org/bugs/?52755.
Reported-by: Brand Huntsman <alpha@qzx.com>
2017-12-29 17:01:15 +01:00
Benno Schulenberg
440a128d25 indenting: keep affecting last line of marked region if it was at first
When unindenting/uncommenting affected the bottom line of the marked
region, keep affecting this line also during subsequent consecutive
indenting/commenting.

This fixes https://savannah.gnu.org/bugs/?52718.
2017-12-29 16:52:17 +01:00
Tom Levy
4f2b01c7e5 syntax: lua: correct the word boundaries on standard library functions
Functions such as "io.close" should only be highlighted when the
package name ("io") is a word by itself, otherwise code such as
"fooio.close" gets unexpected partial highlighting.

Signed-off-by: Tom Levy <tomlevy93@gmail.com>
2017-12-28 21:46:26 +01:00
Benno Schulenberg
12073001c2 tweaks: condense, reword, and rewrap a bunch of comments 2017-12-26 22:14:25 +01:00
Benno Schulenberg
4c20135749 help: swap the order of the Complete and Comment functions
So that Commenting comes closer to the somewhat related Indenting
and Unindenting functions.
2017-12-26 21:36:29 +01:00
Benno Schulenberg
f9ebf038e0 tweaks: slightly rename four functions, for aptness and variety 2017-12-26 14:15:49 +01:00
David Lawrence Ramsey
62ebd93579 tweaks: use printf's z modifier for (s)size_t, instead of casting 2017-12-26 14:11:18 +01:00
Benno Schulenberg
a10fdc3fb1 help: show that "Tab" will indent, just like "Sh-Tab" will unindent
Also, make the descriptions for indenting/unindenting more precise.
2017-12-26 13:46:34 +01:00
Benno Schulenberg
8581e702d6 tweaks: move some frequently-used keystrokes to the top of the list
So they will be found quicker.

Also fold two assignments into one.
2017-12-26 13:31:50 +01:00
Benno Schulenberg
bdbd5ff0e7 syntax: javascript: add some comments, and color explicit numbers too 2017-12-25 16:03:05 +01:00
Benno Schulenberg
f769465284 syntax: javascript: add some keywords, and sort them more logically
Also, remove angle-bracketed "strings" -- they don't exist.
2017-12-25 15:40:05 +01:00
Benno Schulenberg
1b5b52d2e4 syntax: javascript: color strings differently from major keywords
Also, remove the coloring of special single-quoted strings as they
get recolored by the subsequent general string-coloring command.

And remove the coloring of all-uppercase words, as other editors
do not color those either.
2017-12-25 15:36:35 +01:00
Benno Schulenberg
ab62d28817 syntax: javascript: require that a comment is preceded by whitespace
Either by whitespace or by the start of a line.

This avoids treating part of a URL as a comment.
2017-12-25 15:25:04 +01:00
Mike Frysinger
8e0a7ec20d syntax: javascript: add newer keywords and string syntax 2017-12-25 15:08:03 +01:00
Benno Schulenberg
23d66949e1 tweaks: frob four comments, and rewrap two lines 2017-12-24 11:53:38 +01:00
Benno Schulenberg
184bb11fd9 tweaks: factor out a piece of common code 2017-12-24 11:25:10 +01:00
Benno Schulenberg
a70db34fc9 tweaks: remove two irrelevant conditions
They were mistakenly added by changeset fb85c055, four commits ago.
2017-12-24 11:10:41 +01:00
Benno Schulenberg
fbde1b2d71 tweaks: reshuffle another bit of code, for conciseness 2017-12-24 10:56:16 +01:00
Benno Schulenberg
c22fef18e4 tweaks: reshuffle a bit of common code, moving it to an existing function 2017-12-23 21:50:18 +01:00
Benno Schulenberg
ee5b250b66 indenting: don't exclude last line of region when region is empty
This fixes https://savannah.gnu.org/bugs/?52717.
2017-12-23 11:42:25 +01:00
Benno Schulenberg
fb85c05594 text: keep cursor at left edge when it IS there when indenting/commenting
Suggested-by: Brand Huntsman <alpha@qzx.com>
2017-12-21 19:47:22 +01:00
Benno Schulenberg
25b1114e03 tweaks: elide two parameters from the get_region() function 2017-12-21 19:47:22 +01:00
Benno Schulenberg
4b8a387529 text: let indenting/commenting skip the last line if its x is zero
If the marked region ends at the start of a line, do not include that
line in the indenting/undenting or commenting/uncommenting.  This is
closer to what the eye would expect.
2017-12-21 19:47:22 +01:00
Benno Schulenberg
df41114e0e tweaks: drop some old debugging code plus a superfluous comment 2017-12-21 19:45:18 +01:00
Benno Schulenberg
dc3618a127 text: set and reset the Modified state correctly when undoing/redoing
Unset the "Modified" marker only at the point where the file was last
saved -- if there is such a point, because it can be missing when the
undo stack was discarded.

This fixes https://savannah.gnu.org/bugs/?52689.
Reported-by: Liu Hao <lh_mouse@126.com>

Original-idea-by: Brand Huntsman <alpha@qzx.com>
2017-12-19 19:22:52 +01:00
Benno Schulenberg
31fe0753e3 tweaks: limit the resetting of "Modified" to writing a full buffer
When doing that, there is no need to save and restore the Modified
state when writing a marked region.
2017-12-19 17:57:49 +01:00
Benno Schulenberg
7ad5afb935 tweaks: remove some unneeded parentheses, and shorten two function calls 2017-12-17 20:32:17 +01:00
Benno Schulenberg
e1b0f2b275 display: ensure that cursor is visible when compiled with --with-slang
This fixes https://savannah.gnu.org/bugs/?52651.
Reported-by: David Lawrence Ramsey <pooka109@gmail.com>
2017-12-17 16:34:02 +01:00
Benno Schulenberg
0e0fb452a3 input: optimize a bit for non-shortcut keys, as they are most frequent 2017-12-17 12:49:04 +01:00
David Lawrence Ramsey
f66432e999 input: support backtab when Slang and/or --rebindkeypad is used
The escape sequence "Esc [ Z" is a backtab on most supported terminals,
so make sure convert_sequence() treats it as such.
2017-12-17 12:11:35 +01:00
Benno Schulenberg
08e9d30fa2 tweaks: condense some debugging code, and rewrap a line 2017-12-16 21:50:10 +01:00
Benno Schulenberg
d2270e514b input: make <Ctrl+Shift+Arrow> work also when using --rebindkeypad
The function get_keycode() should never return zero -- it should
return either the code from ncurses or the given fallback code.

This fixes https://savannah.gnu.org/bugs/?52682.
2017-12-16 21:09:01 +01:00
Benno Schulenberg
031305c205 tweaks: strip some debugging stuff, and condense a bit of code 2017-12-16 19:56:15 +01:00
Benno Schulenberg
e2843ede7e text: let a Shift-selection persist when indenting and commenting
To achieve that, fake the Shift key being held when indenting/
unindenting/commenting/uncommenting.

Reported-by: Brand Huntsman <alpha@qzx.com>
2017-12-12 21:09:28 +01:00
Benno Schulenberg
09958ebdff input: allow using <Tab> and <Shift+Tab> to (un)indent selected region
When the mark is on, instead of letting a <Tab> simply insert a Tab
character at the cursor position, let it indent the marked region.

Original-idea-by: Chris Allegretta <chrisa@asty.org>
2017-12-12 20:37:41 +01:00
Michael Francis
53fc9a66a6 syntax: php: function and variable names can contain uppercase and digits
Reference: http://php.net/manual/en/language.variables.basics.php

Also color keywords differently from strings.

Signed-off-by: Michael Francis <mikefrancis95@gmail.com>
2017-12-11 21:02:36 +01:00
Benno Schulenberg
a95c6c5fe8 tweaks: condense or rewrap a bunch of repetitious comments 2017-12-11 20:02:43 +01:00
Benno Schulenberg
bcd187d7d6 tweaks: rewrap some lines and some comments, and trim two others 2017-12-10 20:03:51 +01:00
Benno Schulenberg
03783a7d1b tweaks: trim another placing of a terminating nul byte
Make both preceding character moves include the terminating byte.
2017-12-10 19:56:36 +01:00
Benno Schulenberg
f2fb8c01f4 tweaks: remove a superfluous placing of a terminating nul byte
The character move has already copied the terminating byte.
And a reallocation to save just one character of memory is
a waste of time.
2017-12-10 19:49:57 +01:00
Benno Schulenberg
ddb8e95d39 syntax: python: color also the special values 'False', 'None', 'True'
And increase the contrast for the reminders, both for PO and Python.
2017-12-10 14:35:13 +01:00
Benjamin Mintz
fbac4505ce syntax: python: add 'async', 'await', and 'nonlocal' as keywords
A list of keywords can be obtained from `keyword.kwlist`.

Signed-off-by: Benjamin Mintz <bmintz@protonmail.com>
2017-12-10 14:23:51 +01:00
Benno Schulenberg
eb937f81fa text: allow unindenting when not all lines are indented
And also allow it when lines are only partially indented.

This makes it possible to equalize the indentations of (accidentally)
unevenly indented lines: by first fully unindenting a group of lines,
and then reindenting them to the desired amount.

Suggested-by: Liu Hao <lh_mouse@126.com>
2017-12-09 17:44:12 +01:00
Liu Hao
5144162a2d syntax: c: increase the color contrast of reminders like FIXME
Bright white on yellow stands out much more than grey on yellow.

Signed-off-by: Liu Hao <lh_mouse@126.com>
2017-12-09 16:58:57 +01:00
Benno Schulenberg
b4411b4f28 wrapping: we're still on the same line if the next line has not changed
In this way we can delete things on the current line with ^K (after
Shift-selecting some text) without nano misdetecting a line change,

This fully fixes https://savannah.gnu.org/bugs/?52576.
2017-12-07 19:41:10 +01:00
Benno Schulenberg
29f7654ab1 wrapping: keep prepending to the same next line as long as possible
Only when the cursor has moved off of the currrent line do we stop
prepending wrapped words to the next line.

This partially fixes https://savannah.gnu.org/bugs/?52576.
2017-12-07 19:41:04 +01:00
Benno Schulenberg
66fd6a5ab1 options: rename 'justifytrim' to 'trimblanks', because it has morphed
The option now causes nano to trim trailing whitespace also when
hardwrapping occurs while the user is typing.
2017-12-06 20:38:13 +01:00
Benno Schulenberg
c30d3d8010 wrapping: delete trailing blanks upon hardwrapping, when requested
This fulfills https://savannah.gnu.org/bugs/?52198.
2017-12-06 20:32:08 +01:00
Benno Schulenberg
0c40f87b55 tweaks: invert the logic of a variable, and rename it
To get rid of two double negatives.
2017-12-03 20:49:01 +01:00
Benno Schulenberg
4761e00852 syntax: nanorc: don't color parts of valid strings as if invalid
It's better to color some invalid things as if valid than the other
way around.  So, as strings can validly contain any number of double
quotes, just accept *anything* between the delimiting double quotes
and demand that the closing quote is followed by whitespace or EOL.
2017-12-03 20:09:47 +01:00
Benno Schulenberg
0133d5cba8 tweaks: elide two variables that are used just once 2017-12-02 18:07:50 +01:00
Benno Schulenberg
9066a96dde tweaks: rename three variables, for more contrast and variety 2017-12-02 18:07:22 +01:00
Benno Schulenberg
6abb551fdd tweaks: avoid incrementing a variable that won't be used again later 2017-12-02 17:55:27 +01:00
Benno Schulenberg
97bdf13b59 tweaks: remove a redundant call of renumber()
The call of do_delete() four lines earlier already does a renumber.
2017-12-02 17:47:01 +01:00
Benno Schulenberg
dae88f8dc7 tweaks: remove a superfluous condition
When the WAS_FINAL_LINE flag is relevant (when NO_NEWLINES isn't set),
the only way for 'current' to be equal to 'filebot' is when 'current_x'
is zero.
2017-12-02 17:40:16 +01:00
Benno Schulenberg
64d1711a24 gnulib: pull in the fix for the missing stat include
This addresses https://savannah.gnu.org/bugs/?52546.
Reported-by: Marius Schamschula <mschamschula@gmail.com>
2017-11-30 21:27:08 +01:00
David Lawrence Ramsey
b9638cb7cc undo: when adding text adds a magicline, an undo should remove both
This fixes http://savannah.gnu.org/bugs/?52523.
2017-11-30 21:20:38 +01:00
77 changed files with 31946 additions and 31920 deletions

View File

@@ -1,3 +1,96 @@
Changes between v2.9.1 and v2.9.2:
----------------------------------
Benjamin Mintz (1):
syntax: python: add 'async', 'await', and 'nonlocal' as keywords
Benno Schulenberg (62):
bump version numbers and add a news item for the 2.9.2 release
display: ensure that cursor is visible when compiled with --with-slang
docs: mention that the source code is best viewed with a tab size of 4
docs: say thanks to some fairly recent translators, and rename one
gnulib: pull in the fix for the missing stat include
gnulib: update to its current upstream state
help: show that "Tab" will indent, just like "Sh-Tab" will unindent
help: swap the order of the Complete and Comment functions
indenting: don't exclude last line of region when region is empty
indenting: keep affecting last line of marked region if it was at first
input: allow using <Tab> and <Shift+Tab> to (un)indent selected region
input: make <Ctrl+Shift+Arrow> work also when using --rebindkeypad
input: optimize a bit for non-shortcut keys, as they are most frequent
options: rename 'justifytrim' to 'trimblanks', because it has morphed
prompt: blank the bar when a "continue?" is answered with No or ^C
syntaxes: remove redundant word-boundary markers
syntax: javascript: add some comments, and color explicit numbers too
syntax: javascript: add some keywords, and sort them more logically
syntax: javascript: color strings differently from major keywords
syntax: javascript: require that a comment is preceded by whitespace
syntax: lua: condense some regexes, tweak comments, reorder things
syntax: nanorc: don't color parts of valid strings as if invalid
syntax: python: color also the special values 'False', 'None', 'True'
text: allow unindenting when not all lines are indented
text: keep cursor at left edge when it IS there when indenting/commenting
text: let a Shift-selection persist when indenting and commenting
text: let indenting/commenting skip the last line if its x is zero
text: set and reset the Modified state correctly when undoing/redoing
tweaks: add a separate function that actually wipes the status bar
tweaks: avoid incrementing a variable that won't be used again later
tweaks: condense or rewrap a bunch of repetitious comments
tweaks: condense, reword, and rewrap a bunch of comments
tweaks: condense some debugging code, and rewrap a line
tweaks: convert the indentation of the NEWS file too
tweaks: convert the indentation to use only tabs
tweaks: drop some old debugging code plus a superfluous comment
tweaks: elide two parameters from the get_region() function
tweaks: elide two variables that are used just once
tweaks: factor out a piece of common code
tweaks: fix some whitespace errors, and convert alignment tabs to spaces
tweaks: fold some regexes into one another, for conciseness
tweaks: frob four comments, and rewrap two lines
tweaks: invert the logic of a variable, and rename it
tweaks: limit the resetting of "Modified" to writing a full buffer
tweaks: move some frequently-used keystrokes to the top of the list
tweaks: remove a redundant call of renumber()
tweaks: remove a superfluous condition
tweaks: remove a superfluous placing of a terminating nul byte
tweaks: remove some unneeded parentheses, and shorten two function calls
tweaks: remove two irrelevant conditions
tweaks: rename three variables, for more contrast and variety
tweaks: reshuffle a bit of common code, moving it to an existing function
tweaks: reshuffle another bit of code, for conciseness
tweaks: rewrap some lines and some comments, and trim two others
tweaks: slightly rename four functions, for aptness and variety
tweaks: strip some debugging stuff, and condense a bit of code
tweaks: trim another placing of a terminating nul byte
tweaks: use for git the more faithful "less -x1,5" suggested by Brand
tweaks: use spaces for alignment also in the THANKS file
wrapping: delete trailing blanks upon hardwrapping, when requested
wrapping: keep prepending to the same next line as long as possible
wrapping: we're still on the same line if the next line has not changed
David Lawrence Ramsey (3):
input: support backtab when Slang and/or --rebindkeypad is used
tweaks: use printf's z modifier for (s)size_t, instead of casting
undo: when adding text adds a magicline, an undo should remove both
Liu Hao (1):
syntax: c: increase the color contrast of reminders like FIXME
Michael Francis (1):
syntax: php: function and variable names can contain uppercase and digits
Mike Frysinger (1):
syntax: javascript: add newer keywords and string syntax
Tom Levy (6):
syntax: go: fix word boundary before dot in number literal
syntax: go: sign of exponent in number literal is optional
syntax: lua: add new and missing standard library functions
syntax: lua: correct the word boundaries on standard library functions
syntax: lua: require at least one digit for hexadecimal numbers
syntax: lua: support fractional part and exponent for decimal and hex
Changes between v2.9.0 and v2.9.1:
----------------------------------

View File

@@ -2,6 +2,8 @@ Improvements in GNU nano
========================
Since 2.9.0:
- <Tab> and <Shift+Tab> can be used to indent/unindent a marked region.
- Can snip trailing whitespace while typing, with 'set trimblanks'.
- The ability to record and replay a series of keystrokes (a macro).
- Assigned functions to ^S (save file) and ^Q (start backward search).
- Indenting and unindenting have been integrated into the undo system.

2799
NEWS

File diff suppressed because it is too large Load Diff

View File

@@ -107,3 +107,10 @@ the license that covers nano. Then create a patch (or patches):
Send that patch (or patches) to <nano-devel@gnu.org>, as an attachment
or with git send-email.
To keep most lines of nano's source code within a width of 80 characters,
a tab size of four should be used. So in your nanorc file you may want
to include 'set tabsize 4', or you could use -T4 on the command line.
To make git display things as intended, you can do:
$ git config --local core.pager "less -x1,5"

168
THANKS
View File

@@ -4,90 +4,94 @@ If we missed you here, let us know!
Translations:
============
Sharuzzaman Ahmat Raslan <sharuzzaman@excite.com> Malay
Josef Andersson <josef.andersson@fripost.org> Swedish
Laurentiu Buzdugan <buzdugan@voyager.net> Romanian
Mario Blättermann <mario.blaettermann@gmail.com> German
Ricardo Cárdenes Medina <ricardo@conisys.com> Spanish
Antonio Ceballos <aceballos@gmail.com> Spanish
Wei-Lun CHAO <chaoweilun@pcmail.com.tw> Chinese (traditional)
Yuri Chornoivan <yurchor@ukr.net> Ukrainian
Marco Colombo <magicdice@inwind.it> Italian
Mihai Cristescu <mihai.cristescu@archlinux.info> Romanian
Yavor Doganov <yavor@doganov.org> Bulgarian
Karl Eichwalder <keichwa@gmx.net> German
A. Murat EREN <meren@comu.edu.tr> Turkish
Rafael Ferreira <rafael.f.f1@gmail.com> Brazilian Portuguese
Doruk Fisek <dfisek@fisek.com.tr> Turkish
Pavel Fric <pavelfric@seznam.cz> Czech
Jorge González <aloriel@gmail.com> Spanish
Sharuzzaman Ahmat Raslan <sharuzzaman@excite.com> Malay
Josef Andersson <josef.andersson@fripost.org> Swedish
Laurentiu Buzdugan <buzdugan@voyager.net> Romanian
Mario Blättermann <mario.blaettermann@gmail.com> German
Ricardo Cárdenes Medina <ricardo@conisys.com> Spanish
Antonio Ceballos <aceballos@gmail.com> Spanish
Wei-Lun CHAO <chaoweilun@pcmail.com.tw> Chinese (traditional)
Yuri Chornoivan <yurchor@ukr.net> Ukrainian
Marco Colombo <magicdice@inwind.it> Italian
Mihai Cristescu <mihai.cristescu@archlinux.info> Romanian
Yavor Doganov <yavor@doganov.org> Bulgarian
Karl Eichwalder <keichwa@gmx.net> German
A. Murat EREN <meren@comu.edu.tr> Turkish
Doruk Fisek <dfisek@fisek.com.tr> Turkish
Rafael Fontenelle <rffontenelle@gmail.com> Brazilian Portuguese
Pavel Fric <pavelfric@seznam.cz> Czech
Jorge González <aloriel@gmail.com> Spanish
Jean-Philippe Guérard <jean-philippe.guerard@laposte.net> French
Geir Helland <pjallabais@users.sourceforge.net> Norwegian Bokmål
Tedi Heriyanto <tedi_h@gmx.net> Indonesian
Václav Haisman <V.Haisman@sh.cvut.cz> Czech
Kjetil Torgrim Homme <kjetilho@linpro.no> Norwegian Nynorsk
Szabolcs Horvath <horvaths@janus.gimsz.sulinet.hu> Hungarian
Jorma Karvonen <karvonen.jorma@gmail.com> Finnish
Gabor Kelemen <kelemeng@gnome.hu> Hungarian
Kalle Kivimaa <kalle.kivimaa@iki.fi> Finnish
Eivind Kjørstad <ekj@vestdata.no> Norwegian Nynorsk
Florian König <floki@bigfoot.com> German
Klemen Košir <klemen913@gmail.com> Slovenian
Wojciech Kotwica <wkotwica@post.pl> Polish
Ask Hjorth Larsen <asklarsen@gmail.com> Danish
Clement Laforet <clem_laf@wanadoo.fr> French
LI Daobing <lidaobing@gmail.com> Chinese (simplified)
Jordi Mallach <jordi@gnu.org> Catalan
João Victor Duarte Martins <jvdm@sdf.lonestar.org> Brazilian Portuguese
Pavel Maryanov <acid@jack.kiev.ua> Russian
Daniele Medri <madrid@linux.it> Italian
Gergely Nagy <algernon@debian.org> Hungarian
Kalle Olavi Niemitalo <kon@iki.fi> Finnish
Мирослав Николић <miroslavnikolic@rocketmail.com> Serbian
Claudio Neves <cneves@nextis.com> Brazilian Portuguese
Daniel Nylander <po@danielnylander.se> Swedish
Mikel Olasagasti <hey_neken@mundurat.net> Basque
Michael Piefel <piefel@informatik.hu-berlin.de> German
Sergey Poznyakoff <gray@gnu.org> Polish
Božidar Putanec <bozidarp@yahoo.com> Croatian
Trần Ngọc Quân <vnwildman@gmail.com> Vietnamese
Sergey A. Ribalchenko <fisher@obu.ck.ua> Ukrainian and Russian
Michel Robitaille <robitail@IRO.UMontreal.CA> French
Christian Rose <menthos@menthos.com> Swedish
Dimitriy Ryazantcev <DJm00n@mail.ru> Russian
Stig E Sandø <stig@ii.uib.no> Norwegian Bokmål
Kevin Patrick Scannell <kscanne@gmail.com> Irish
Benno Schulenberg <benno@vertaalt.nl> Dutch and Esperanto
Danilo Segan <dsegan@gmx.net> Serbian
Clytie Siddall <clytie@riverland.net.au> Vietnamese
Keld Simonsen <keld@dkuug.dk> Danish
Guus Sliepen <guus@nl.linux.org> Dutch
Cezary Sliwa <sliwa@cft.edu.pl> Polish
Johnny A. Solbu <johnny@solbu.net> Norwegian Bokmål
Pierre Tane <tanep@bigfoot.com> French
Yasuaki Taniguchi <yasuakit@gmail.com> Japanese
Jacobo Tarrío <jtarrio@trasno.net> Galician
Francisco Javier Tsao Santín <tsao@members.fsf.org> Galician
Miquel Vidal <miquel@sindominio.net> Catalan
Phan Vinh Thinh <teppi82@gmail.com> Vietnamese
Pauli Virtanen <pauli.virtanen@saunalahti.fi> Finnish
Aron Xu <happyaron.xu@gmail.com> Chinese (simplified)
Peio Ziarsolo <peio@sindominio.net> Basque
Anton Zinoviev <zinoviev@debian.org> Bulgarian
Geir Helland <pjallabais@users.sourceforge.net> Norwegian Bokmål
Tedi Heriyanto <tedi_h@gmx.net> Indonesian
Václav Haisman <V.Haisman@sh.cvut.cz> Czech
Takeshi Hamasaki <hmatrjp@users.sourceforge.jp> Japanese
Kjetil Torgrim Homme <kjetilho@linpro.no> Norwegian Nynorsk
Szabolcs Horvath <horvaths@janus.gimsz.sulinet.hu> Hungarian
Jorma Karvonen <karvonen.jorma@gmail.com> Finnish
Mehmet Kececi <mkececi@mehmetkececi.com> Turkish
Gabor Kelemen <kelemeng@gnome.hu> Hungarian
Kalle Kivimaa <kalle.kivimaa@iki.fi> Finnish
Eivind Kjørstad <ekj@vestdata.no> Norwegian Nynorsk
Florian König <floki@bigfoot.com> German
Klemen Košir <klemen913@gmail.com> Slovenian
Wojciech Kotwica <wkotwica@post.pl> Polish
Ask Hjorth Larsen <asklarsen@gmail.com> Danish
Clement Laforet <clem_laf@wanadoo.fr> French
LI Daobing <lidaobing@gmail.com> Chinese (simplified)
Jordi Mallach <jordi@gnu.org> Catalan
João Victor Duarte Martins <jvdm@sdf.lonestar.org> Brazilian Portuguese
Pavel Maryanov <acid@jack.kiev.ua> Russian
Daniele Medri <madrid@linux.it> Italian
Gergely Nagy <algernon@debian.org> Hungarian
Kalle Olavi Niemitalo <kon@iki.fi> Finnish
Мирослав Николић <miroslavnikolic@rocketmail.com> Serbian
Claudio Neves <cneves@nextis.com> Brazilian Portuguese
Lauri Nurmi <lanurmi@iki.fi> Finnish
Daniel Nylander <po@danielnylander.se> Swedish
Mikel Olasagasti <hey_neken@mundurat.net> Basque
Michael Piefel <piefel@informatik.hu-berlin.de> German
Sergey Poznyakoff <gray@gnu.org> Polish
Božidar Putanec <bozidarp@yahoo.com> Croatian
Trần Ngọc Quân <vnwildman@gmail.com> Vietnamese
Sergey A. Ribalchenko <fisher@obu.ck.ua> Ukrainian and Russian
Michel Robitaille <robitail@IRO.UMontreal.CA> French
Christian Rose <menthos@menthos.com> Swedish
Dimitriy Ryazantcev <DJm00n@mail.ru> Russian
Stig E Sandø <stig@ii.uib.no> Norwegian Bokmål
Kevin Patrick Scannell <kscanne@gmail.com> Irish
Benno Schulenberg <benno@vertaalt.nl> Dutch and Esperanto
Danilo Segan <dsegan@gmx.net> Serbian
Clytie Siddall <clytie@riverland.net.au> Vietnamese
Keld Simonsen <keld@dkuug.dk> Danish
Guus Sliepen <guus@nl.linux.org> Dutch
Cezary Sliwa <sliwa@cft.edu.pl> Polish
Johnny A. Solbu <johnny@solbu.net> Norwegian Bokmål
Pierre Tane <tanep@bigfoot.com> French
Yasuaki Taniguchi <yasuakit@gmail.com> Japanese
Jacobo Tarrío <jtarrio@trasno.net> Galician
Francisco Javier Tsao Santín <tsao@members.fsf.org> Galician
Balázs Úr <urbalazs@gmail.com> Hungarian
Miquel Vidal <miquel@sindominio.net> Catalan
Phan Vinh Thinh <teppi82@gmail.com> Vietnamese
Pauli Virtanen <pauli.virtanen@saunalahti.fi> Finnish
Aron Xu <happyaron.xu@gmail.com> Chinese (simplified)
Peio Ziarsolo <peio@sindominio.net> Basque
Anton Zinoviev <zinoviev@debian.org> Bulgarian
Other stuff:
===========
Ben Armstrong <synrg@sanctuary.nslug.ns.ca> Negative -r value idea, code
Thomas Dickey <dickey@herndon4.his.com> Curses help and advice
Sven Guckes <guckes@math.fu-berlin.de> Advice and advocacy
Thijs Kinkhorst <thijs@kinkhorst.com> rnano.1 manpage
Jim Knoble <jmknoble@pobox.com> Pico compat for browser
Ryan Krebs <fluffy@highwire.stanford.edu> Many bug fixes and testing
Roy Lanek <lanek@ranahminang.net> Advice and advocacy
Chuck Mead <csm@MoonGroup.com> Feedback and RPM stuff
Mike Melanson <melanson@pcisys.net> Bugs
Neil Parks <nparks@acsmail.com> Bug reports and fixes
Jeremy Robichaud <robicj@yahoo.com> Beta tester
Bill Soudan <wes0472@rit.edu> Regex code, etc
Ken Tyler <kent@werple.net.au> Search fixes and more
Ben Armstrong <synrg@sanctuary.nslug.ns.ca> Negative -r value idea, code
Thomas Dickey <dickey@herndon4.his.com> Curses help and advice
Sven Guckes <guckes@math.fu-berlin.de> Advice and advocacy
Thijs Kinkhorst <thijs@kinkhorst.com> rnano.1 manpage
Jim Knoble <jmknoble@pobox.com> Pico compat for browser
Ryan Krebs <fluffy@highwire.stanford.edu> Many bug fixes and testing
Roy Lanek <lanek@ranahminang.net> Advice and advocacy
Chuck Mead <csm@MoonGroup.com> Feedback and RPM stuff
Mike Melanson <melanson@pcisys.net> Bug reports
Neil Parks <nparks@acsmail.com> Bug reports and fixes
Jeremy Robichaud <robicj@yahoo.com> Beta tester
Bill Soudan <wes0472@rit.edu> Regex code, etc
Ken Tyler <kent@werple.net.au> Search fixes and more

View File

@@ -2,7 +2,7 @@
# Generate configure & friends for GIT users.
gnulib_url="git://git.sv.gnu.org/gnulib.git"
gnulib_hash="b9d0b50f6cd122a1748e1e5b79ecca7a0fef214e"
gnulib_hash="44100f563482fe469a33abecda5797da04fc3c61"
modules="
futimens

File diff suppressed because it is too large Load Diff

View File

@@ -83,7 +83,7 @@
<h2><a name="1.3"></a>1.3. Why the name change from TIP?</h2>
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program &quot;establishes a full duplex terminal connection to a remote host&quot;, and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
<h2><a name="1.4"></a>1.4. What is the current version of nano?</h2>
<blockquote><p>The current version of nano <i>should</i> be <b>2.9.1</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.9.2</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.5"></a>1.5. 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%">

View File

@@ -16,7 +16,7 @@
.\" Documentation License along with this program. If not, see
.\" <http://www.gnu.org/licenses/>.
.\"
.TH NANO 1 "version 2.9.1" "November 2017"
.TH NANO 1 "version 2.9.2" "January 2018"
.SH NAME
nano \- Nano's ANOther editor, an enhanced free Pico clone

View File

@@ -8,8 +8,8 @@
@smallbook
@set EDITION 0.5
@set VERSION 2.9.1
@set UPDATED November 2017
@set VERSION 2.9.2
@set UPDATED January 2018
@dircategory Editors
@direntry
@@ -23,7 +23,7 @@
@titlepage
@title GNU @command{nano}
@subtitle a small and friendly text editor
@subtitle version 2.9.1
@subtitle version 2.9.2
@author Chris Allegretta
@page
@@ -63,7 +63,7 @@ e-mail: @email{chrisa@@asty.org}@*
@node Top
@top
This manual documents the GNU @command{nano} editor, version 2.9.1.
This manual documents the GNU @command{nano} editor, version 2.9.2.
@menu
* Introduction::
@@ -753,9 +753,6 @@ And either @var{fgcolor} or ,@var{bgcolor} may be left out.
Save the last hundred search strings and replacement strings and
executed commands, so they can be easily reused in later sessions.
@item set justifytrim
When justifying text, trailing whitespace will automatically be removed.
@item set keycolor @var{fgcolor},@var{bgcolor}
Use this color combination for the shortcut key combos
in the two help lines at the bottom of the screen.
@@ -899,6 +896,10 @@ Save automatically on exit, don't prompt.
Use this color combination for the title bar.
@xref{@code{set functioncolor}} for valid color names.
@item set trimblanks
Remove trailing whitespace from wrapped lines when automatic
hard-wrapping occurs or when text is justified.
@item set unix
Save a file by default in Unix format. This overrides nano's
default behavior of saving a file in the format that it had.

View File

@@ -16,7 +16,7 @@
.\" Documentation License along with this program. If not, see
.\" <http://www.gnu.org/licenses/>.
.\"
.TH NANORC 5 "version 2.9.1" "November 2017"
.TH NANORC 5 "version 2.9.2" "January 2018"
.SH NAME
nanorc \- GNU nano's configuration file
@@ -118,9 +118,6 @@ See \fBset titlecolor\fR for more details.
Save the last hundred search strings and replacement strings and
executed commands, so they can be easily reused in later sessions.
.TP
.B set justifytrim
When justifying text, trailing whitespace will automatically be removed.
.TP
.B set keycolor \fIfgcolor\fR,\fIbgcolor\fR
Specify the color combination to use for the shortcut key combos
in the two help lines at the bottom of the screen.
@@ -269,6 +266,10 @@ Valid names for the foreground and background colors are:
The name of the foreground color may be prefixed with \fBbright\fR.
And either "\fIfgcolor\fR" or ",\fIbgcolor\fR" may be left out.
.TP
.B set trimblanks
Remove trailing whitespace from wrapped lines when automatic
hard-wrapping occurs or when text is justified.
.TP
.B set unix
Save a file by default in Unix format. This overrides nano's
default behavior of saving a file in the format that it had.

View File

@@ -16,7 +16,7 @@
.\" Documentation License along with this program. If not, see
.\" <http://www.gnu.org/licenses/>.
.\"
.TH RNANO 1 "version 2.9.1" "November 2017"
.TH RNANO 1 "version 2.9.2" "January 2018"
.SH NAME
rnano \- a restricted nano

View File

@@ -57,9 +57,6 @@
## Remember the used search/replace strings for the next session.
# set historylog
## Make the justify command kill whitespace at the end of lines.
# set justifytrim
## Display line numbers to the left of the text.
# set linenumbers
@@ -175,6 +172,9 @@
## Save automatically on exit; don't prompt.
# set tempfile
## Snip whitespace at the end of lines when justifying or hard-wrapping.
# set trimblanks
## Disallow file modification. Why would you want this in an rcfile? ;)
# set view

820
po/bg.po

File diff suppressed because it is too large Load Diff

827
po/ca.po

File diff suppressed because it is too large Load Diff

1037
po/cs.po

File diff suppressed because it is too large Load Diff

826
po/da.po

File diff suppressed because it is too large Load Diff

820
po/de.po

File diff suppressed because it is too large Load Diff

833
po/eo.po

File diff suppressed because it is too large Load Diff

901
po/es.po

File diff suppressed because it is too large Load Diff

810
po/eu.po

File diff suppressed because it is too large Load Diff

820
po/fi.po

File diff suppressed because it is too large Load Diff

908
po/fr.po

File diff suppressed because it is too large Load Diff

831
po/ga.po

File diff suppressed because it is too large Load Diff

820
po/gl.po

File diff suppressed because it is too large Load Diff

969
po/hr.po

File diff suppressed because it is too large Load Diff

823
po/hu.po

File diff suppressed because it is too large Load Diff

815
po/id.po

File diff suppressed because it is too large Load Diff

828
po/it.po

File diff suppressed because it is too large Load Diff

831
po/ja.po

File diff suppressed because it is too large Load Diff

820
po/ms.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

826
po/nb.po

File diff suppressed because it is too large Load Diff

847
po/nl.po

File diff suppressed because it is too large Load Diff

815
po/nn.po

File diff suppressed because it is too large Load Diff

820
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

884
po/ro.po

File diff suppressed because it is too large Load Diff

820
po/ru.po

File diff suppressed because it is too large Load Diff

820
po/sl.po

File diff suppressed because it is too large Load Diff

823
po/sr.po

File diff suppressed because it is too large Load Diff

826
po/sv.po

File diff suppressed because it is too large Load Diff

879
po/tr.po

File diff suppressed because it is too large Load Diff

919
po/uk.po

File diff suppressed because it is too large Load Diff

827
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -33,7 +33,7 @@
/* For early versions of ncurses-6.0, use an additional A_PROTECT attribute
* for all colors, in order to work around an ncurses miscoloring bug. */
#if defined(NCURSES_VERSION_MAJOR) && (NCURSES_VERSION_MAJOR == 6) && \
(NCURSES_VERSION_MINOR == 0) && (NCURSES_VERSION_PATCH < 20151017)
(NCURSES_VERSION_MINOR == 0) && (NCURSES_VERSION_PATCH < 20151017)
#define A_BANDAID A_PROTECT
#else
#define A_BANDAID A_NORMAL
@@ -43,394 +43,394 @@
* for the colors in each syntax. */
void set_colorpairs(void)
{
const syntaxtype *sint;
bool using_defaults = FALSE;
short foreground, background;
size_t i;
const syntaxtype *sint;
bool using_defaults = FALSE;
short foreground, background;
size_t i;
/* Tell ncurses to enable colors. */
start_color();
/* Tell ncurses to enable colors. */
start_color();
#ifdef HAVE_USE_DEFAULT_COLORS
/* Allow using the default colors, if available. */
using_defaults = (use_default_colors() != ERR);
/* Allow using the default colors, if available. */
using_defaults = (use_default_colors() != ERR);
#endif
/* Initialize the color pairs for nano's interface elements. */
for (i = 0; i < NUMBER_OF_ELEMENTS; i++) {
bool bright = FALSE;
/* Initialize the color pairs for nano's interface elements. */
for (i = 0; i < NUMBER_OF_ELEMENTS; i++) {
bool bright = FALSE;
if (specified_color_combo[i] != NULL &&
parse_color_names(specified_color_combo[i],
&foreground, &background, &bright)) {
if (foreground == -1 && !using_defaults)
foreground = COLOR_WHITE;
if (background == -1 && !using_defaults)
background = COLOR_BLACK;
init_pair(i + 1, foreground, background);
interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BANDAID |
(bright ? A_BOLD : A_NORMAL);
} else {
if (i != FUNCTION_TAG)
interface_color_pair[i] = hilite_attribute;
else
interface_color_pair[i] = A_NORMAL;
if (specified_color_combo[i] != NULL &&
parse_color_names(specified_color_combo[i],
&foreground, &background, &bright)) {
if (foreground == -1 && !using_defaults)
foreground = COLOR_WHITE;
if (background == -1 && !using_defaults)
background = COLOR_BLACK;
init_pair(i + 1, foreground, background);
interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BANDAID |
(bright ? A_BOLD : A_NORMAL);
} else {
if (i != FUNCTION_TAG)
interface_color_pair[i] = hilite_attribute;
else
interface_color_pair[i] = A_NORMAL;
}
free(specified_color_combo[i]);
specified_color_combo[i] = NULL;
}
free(specified_color_combo[i]);
specified_color_combo[i] = NULL;
}
/* For each syntax, go through its list of colors and assign each
* its pair number, giving identical color pairs the same number. */
for (sint = syntaxes; sint != NULL; sint = sint->next) {
colortype *ink;
int new_number = NUMBER_OF_ELEMENTS + 1;
/* For each syntax, go through its list of colors and assign each
* its pair number, giving identical color pairs the same number. */
for (sint = syntaxes; sint != NULL; sint = sint->next) {
colortype *ink;
int new_number = NUMBER_OF_ELEMENTS + 1;
for (ink = sint->color; ink != NULL; ink = ink->next) {
const colortype *beforenow = sint->color;
for (ink = sint->color; ink != NULL; ink = ink->next) {
const colortype *beforenow = sint->color;
while (beforenow != ink && (beforenow->fg != ink->fg ||
beforenow->bg != ink->bg ||
beforenow->bright != ink->bright))
beforenow = beforenow->next;
while (beforenow != ink && (beforenow->fg != ink->fg ||
beforenow->bg != ink->bg ||
beforenow->bright != ink->bright))
beforenow = beforenow->next;
if (beforenow != ink)
ink->pairnum = beforenow->pairnum;
else
ink->pairnum = new_number++;
if (beforenow != ink)
ink->pairnum = beforenow->pairnum;
else
ink->pairnum = new_number++;
ink->attributes = COLOR_PAIR(ink->pairnum) | A_BANDAID |
(ink->bright ? A_BOLD : A_NORMAL);
ink->attributes = COLOR_PAIR(ink->pairnum) | A_BANDAID |
(ink->bright ? A_BOLD : A_NORMAL);
}
}
}
}
/* Initialize the color information. */
void color_init(void)
{
const colortype *ink;
bool using_defaults = FALSE;
short foreground, background;
const colortype *ink;
bool using_defaults = FALSE;
short foreground, background;
/* If the terminal is not capable of colors, forget it. */
if (!has_colors())
return;
/* If the terminal is not capable of colors, forget it. */
if (!has_colors())
return;
#ifdef HAVE_USE_DEFAULT_COLORS
/* Allow using the default colors, if available. */
using_defaults = (use_default_colors() != ERR);
/* Allow using the default colors, if available. */
using_defaults = (use_default_colors() != ERR);
#endif
/* For each coloring expression, initialize the color pair. */
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
foreground = ink->fg;
background = ink->bg;
/* For each coloring expression, initialize the color pair. */
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
foreground = ink->fg;
background = ink->bg;
if (foreground == -1 && !using_defaults)
foreground = COLOR_WHITE;
if (foreground == -1 && !using_defaults)
foreground = COLOR_WHITE;
if (background == -1 && !using_defaults)
background = COLOR_BLACK;
if (background == -1 && !using_defaults)
background = COLOR_BLACK;
init_pair(ink->pairnum, foreground, background);
}
init_pair(ink->pairnum, foreground, background);
}
have_palette = TRUE;
have_palette = TRUE;
}
/* Try to match the given shibboleth string with one of the regexes in
* the list starting at head. Return TRUE upon success. */
bool found_in_list(regexlisttype *head, const char *shibboleth)
{
regexlisttype *item;
regex_t rgx;
regexlisttype *item;
regex_t rgx;
for (item = head; item != NULL; item = item->next) {
regcomp(&rgx, fixbounds(item->full_regex), NANO_REG_EXTENDED);
for (item = head; item != NULL; item = item->next) {
regcomp(&rgx, fixbounds(item->full_regex), NANO_REG_EXTENDED);
if (regexec(&rgx, shibboleth, 0, NULL, 0) == 0) {
regfree(&rgx);
return TRUE;
if (regexec(&rgx, shibboleth, 0, NULL, 0) == 0) {
regfree(&rgx);
return TRUE;
}
regfree(&rgx);
}
regfree(&rgx);
}
return FALSE;
return FALSE;
}
/* Update the color information based on the current filename and content. */
void color_update(void)
{
syntaxtype *sint = NULL;
colortype *ink;
syntaxtype *sint = NULL;
colortype *ink;
/* If the rcfiles were not read, or contained no syntaxes, get out. */
if (syntaxes == NULL)
return;
/* If the rcfiles were not read, or contained no syntaxes, get out. */
if (syntaxes == NULL)
return;
/* If we specified a syntax-override string, use it. */
if (syntaxstr != NULL) {
/* An override of "none" is like having no syntax at all. */
if (strcmp(syntaxstr, "none") == 0)
return;
/* If we specified a syntax-override string, use it. */
if (syntaxstr != NULL) {
/* An override of "none" is like having no syntax at all. */
if (strcmp(syntaxstr, "none") == 0)
return;
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (strcmp(sint->name, syntaxstr) == 0)
break;
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (strcmp(sint->name, syntaxstr) == 0)
break;
}
if (sint == NULL && !inhelp)
statusline(ALERT, _("Unknown syntax name: %s"), syntaxstr);
}
if (sint == NULL && !inhelp)
statusline(ALERT, _("Unknown syntax name: %s"), syntaxstr);
}
/* If no syntax-override string was specified, or it didn't match,
* try finding a syntax based on the filename (extension). */
if (sint == NULL && !inhelp) {
char *reserved = charalloc(PATH_MAX + 1);
char *currentdir = getcwd(reserved, PATH_MAX + 1);
char *joinednames = charalloc(PATH_MAX + 1);
char *fullname = NULL;
/* If no syntax-override string was specified, or it didn't match,
* try finding a syntax based on the filename (extension). */
if (sint == NULL && !inhelp) {
char *reserved = charalloc(PATH_MAX + 1);
char *currentdir = getcwd(reserved, PATH_MAX + 1);
char *joinednames = charalloc(PATH_MAX + 1);
char *fullname = NULL;
if (currentdir == NULL)
free(reserved);
else {
/* Concatenate the current working directory with the
* specified filename, and canonicalize the result. */
sprintf(joinednames, "%s/%s", currentdir, openfile->filename);
fullname = get_full_path(joinednames);
free(currentdir);
}
if (currentdir == NULL)
free(reserved);
else {
/* Concatenate the current working directory with the
* specified filename, and canonicalize the result. */
sprintf(joinednames, "%s/%s", currentdir, openfile->filename);
fullname = get_full_path(joinednames);
free(currentdir);
if (fullname == NULL)
fullname = mallocstrcpy(fullname, openfile->filename);
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (found_in_list(sint->extensions, fullname))
break;
}
free(joinednames);
free(fullname);
}
if (fullname == NULL)
fullname = mallocstrcpy(fullname, openfile->filename);
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (found_in_list(sint->extensions, fullname))
break;
/* If the filename didn't match anything, try the first line. */
if (sint == NULL && !inhelp) {
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (found_in_list(sint->headers, openfile->fileage->data))
break;
}
}
free(joinednames);
free(fullname);
}
/* If the filename didn't match anything, try the first line. */
if (sint == NULL && !inhelp) {
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (found_in_list(sint->headers, openfile->fileage->data))
break;
}
}
#ifdef HAVE_LIBMAGIC
/* If we still don't have an answer, try using magic. */
if (sint == NULL && !inhelp) {
struct stat fileinfo;
magic_t cookie = NULL;
const char *magicstring = NULL;
/* If we still don't have an answer, try using magic. */
if (sint == NULL && !inhelp) {
struct stat fileinfo;
magic_t cookie = NULL;
const char *magicstring = NULL;
if (stat(openfile->filename, &fileinfo) == 0) {
/* Open the magic database and get a diagnosis of the file. */
cookie = magic_open(MAGIC_SYMLINK |
if (stat(openfile->filename, &fileinfo) == 0) {
/* Open the magic database and get a diagnosis of the file. */
cookie = magic_open(MAGIC_SYMLINK |
#ifdef DEBUG
MAGIC_DEBUG | MAGIC_CHECK |
MAGIC_DEBUG | MAGIC_CHECK |
#endif
MAGIC_ERROR);
if (cookie == NULL || magic_load(cookie, NULL) < 0)
statusline(ALERT, _("magic_load() failed: %s"), strerror(errno));
else {
magicstring = magic_file(cookie, openfile->filename);
if (magicstring == NULL)
statusline(ALERT, _("magic_file(%s) failed: %s"),
openfile->filename, magic_error(cookie));
}
}
MAGIC_ERROR);
if (cookie == NULL || magic_load(cookie, NULL) < 0)
statusline(ALERT, _("magic_load() failed: %s"), strerror(errno));
else {
magicstring = magic_file(cookie, openfile->filename);
if (magicstring == NULL)
statusline(ALERT, _("magic_file(%s) failed: %s"),
openfile->filename, magic_error(cookie));
}
}
/* Now try and find a syntax that matches the magic string. */
if (magicstring != NULL) {
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (found_in_list(sint->magics, magicstring))
break;
}
}
/* Now try and find a syntax that matches the magic string. */
if (magicstring != NULL) {
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (found_in_list(sint->magics, magicstring))
break;
}
}
if (stat(openfile->filename, &fileinfo) == 0)
magic_close(cookie);
}
if (stat(openfile->filename, &fileinfo) == 0)
magic_close(cookie);
}
#endif /* HAVE_LIBMAGIC */
/* If nothing at all matched, see if there is a default syntax. */
if (sint == NULL && !inhelp) {
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (strcmp(sint->name, "default") == 0)
break;
}
}
openfile->syntax = sint;
openfile->colorstrings = (sint == NULL ? NULL : sint->color);
/* If a syntax was found, compile its specified regexes (which have
* already been checked for validity when they were read in). */
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
if (ink->start == NULL) {
ink->start = (regex_t *)nmalloc(sizeof(regex_t));
regcomp(ink->start, fixbounds(ink->start_regex), ink->rex_flags);
/* If nothing at all matched, see if there is a default syntax. */
if (sint == NULL && !inhelp) {
for (sint = syntaxes; sint != NULL; sint = sint->next) {
if (strcmp(sint->name, "default") == 0)
break;
}
}
if (ink->end_regex != NULL && ink->end == NULL) {
ink->end = (regex_t *)nmalloc(sizeof(regex_t));
regcomp(ink->end, fixbounds(ink->end_regex), ink->rex_flags);
openfile->syntax = sint;
openfile->colorstrings = (sint == NULL ? NULL : sint->color);
/* If a syntax was found, compile its specified regexes (which have
* already been checked for validity when they were read in). */
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
if (ink->start == NULL) {
ink->start = (regex_t *)nmalloc(sizeof(regex_t));
regcomp(ink->start, fixbounds(ink->start_regex), ink->rex_flags);
}
if (ink->end_regex != NULL && ink->end == NULL) {
ink->end = (regex_t *)nmalloc(sizeof(regex_t));
regcomp(ink->end, fixbounds(ink->end_regex), ink->rex_flags);
}
}
}
}
/* 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;
bool astart, anend;
regmatch_t startmatch, endmatch;
const colortype *ink;
bool astart, anend;
regmatch_t startmatch, endmatch;
/* If there is no syntax or no multiline regex, there is nothing to do. */
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
return;
/* If there is no syntax or no multiline regex, there is nothing to do. */
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
return;
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
/* If it's not a multiline regex, skip. */
if (ink->end == NULL)
continue;
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
/* If it's not a multiline regex, skip. */
if (ink->end == NULL)
continue;
alloc_multidata_if_needed(line);
alloc_multidata_if_needed(line);
astart = (regexec(ink->start, line->data, 1, &startmatch, 0) == 0);
anend = (regexec(ink->end, line->data, 1, &endmatch, 0) == 0);
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 (line->multidata[ink->id] == CSTARTENDHERE) {
if (astart && anend && startmatch.rm_so < endmatch.rm_so)
continue;
} else if (line->multidata[ink->id] == CBEGINBEFORE) {
if (!astart && anend)
continue;
} else if (line->multidata[ink->id] == CENDAFTER) {
if (astart && !anend)
continue;
/* 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 (line->multidata[ink->id] == CSTARTENDHERE) {
if (astart && anend && startmatch.rm_so < endmatch.rm_so)
continue;
} else if (line->multidata[ink->id] == CBEGINBEFORE) {
if (!astart && anend)
continue;
} else if (line->multidata[ink->id] == CENDAFTER) {
if (astart && !anend)
continue;
}
/* There is a mismatch, so something changed: repaint. */
refresh_needed = TRUE;
return;
}
/* There is a mismatch, so something changed: repaint. */
refresh_needed = TRUE;
return;
}
}
/* Allocate (for one line) the cache space for multiline color regexes. */
void alloc_multidata_if_needed(filestruct *fileptr)
{
int i;
int i;
if (fileptr->multidata == NULL) {
fileptr->multidata = (short *)nmalloc(openfile->syntax->nmultis * sizeof(short));
if (fileptr->multidata == NULL) {
fileptr->multidata = (short *)nmalloc(openfile->syntax->nmultis * sizeof(short));
for (i = 0; i < openfile->syntax->nmultis; i++)
fileptr->multidata[i] = -1;
}
for (i = 0; i < openfile->syntax->nmultis; i++)
fileptr->multidata[i] = -1;
}
}
/* Precalculate the multi-line start and end regex info so we can
* speed up rendering (with any hope at all...). */
void precalc_multicolorinfo(void)
{
const colortype *ink;
regmatch_t startmatch, endmatch;
filestruct *line, *tailline;
const colortype *ink;
regmatch_t startmatch, endmatch;
filestruct *line, *tailline;
if (openfile->colorstrings == NULL || ISSET(NO_COLOR_SYNTAX))
return;
if (openfile->colorstrings == NULL || ISSET(NO_COLOR_SYNTAX))
return;
#ifdef DEBUG
fprintf(stderr, "Precalculating the 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;
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
/* If this is not a multi-line regex, skip it. */
if (ink->end == NULL)
continue;
for (line = openfile->fileage; line != NULL; line = line->next) {
int index = 0;
for (line = openfile->fileage; line != NULL; line = line->next) {
int index = 0;
alloc_multidata_if_needed(line);
/* Assume nothing applies until proven otherwise below. */
line->multidata[ink->id] = CNONE;
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;
}
/* 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;
/* 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) {
/* When at end-of-line, we're done. */
if (line->data[index] == '\0')
break;
index = move_mbright(line->data, index);
}
continue;
/* 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) {
/* When at end-of-line, we're done. */
if (line->data[index] == '\0')
break;
index = move_mbright(line->data, index);
}
continue;
}
/* 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 (tailline == NULL) {
line->multidata[ink->id] = CWOULDBE;
break;
}
/* We found it, we found it, la la la la la. Mark all
* the lines in between and the end properly. */
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(tailline);
tailline->multidata[ink->id] = CBEGINBEFORE;
/* Begin looking for a new start after the end match. */
index = endmatch.rm_eo;
}
}
/* 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 (tailline == NULL) {
line->multidata[ink->id] = CWOULDBE;
break;
}
/* We found it, we found it, la la la la la. Mark all
* the lines in between and the end properly. */
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(tailline);
tailline->multidata[ink->id] = CBEGINBEFORE;
/* Begin looking for a new start after the end match. */
index = endmatch.rm_eo;
}
}
}
}
#endif /* ENABLE_COLOR */

296
src/cut.c
View File

@@ -25,18 +25,18 @@
#include <string.h>
static bool keep_cutbuffer = FALSE;
/* Should we keep the contents of the cutbuffer? */
/* Should we keep the contents of the cutbuffer? */
/* Indicate that we should no longer keep the contents of the cutbuffer. */
void cutbuffer_reset(void)
{
keep_cutbuffer = FALSE;
keep_cutbuffer = FALSE;
}
/* Return the status of cutbuffer preservation. */
inline bool keeping_cutbuffer(void)
{
return keep_cutbuffer;
return keep_cutbuffer;
}
/* If we aren't on the last line of the file, move all the text of the
@@ -46,13 +46,13 @@ inline bool keeping_cutbuffer(void)
* current line. */
void cut_line(void)
{
if (openfile->current != openfile->filebot)
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
openfile->current->next, 0);
else
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
openfile->current, strlen(openfile->current->data));
openfile->placewewant = 0;
if (openfile->current != openfile->filebot)
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
openfile->current->next, 0);
else
extract_buffer(&cutbuffer, &cutbottom, openfile->current, 0,
openfile->current, strlen(openfile->current->data));
openfile->placewewant = 0;
}
#ifndef NANO_TINY
@@ -60,14 +60,14 @@ void cut_line(void)
* current place we want to where the text used to start. */
void cut_marked(bool *right_side_up)
{
filestruct *top, *bot;
size_t top_x, bot_x;
filestruct *top, *bot;
size_t top_x, bot_x;
mark_order((const filestruct **)&top, &top_x,
(const filestruct **)&bot, &bot_x, right_side_up);
mark_order((const filestruct **)&top, &top_x,
(const filestruct **)&bot, &bot_x, right_side_up);
extract_buffer(&cutbuffer, &cutbottom, top, top_x, bot, bot_x);
openfile->placewewant = xplustabs();
extract_buffer(&cutbuffer, &cutbottom, top, top_x, bot, bot_x);
openfile->placewewant = xplustabs();
}
/* If we aren't at the end of the current line, move all the text from
@@ -78,32 +78,32 @@ void cut_marked(bool *right_side_up)
* newline used to be. */
void cut_to_eol(void)
{
size_t data_len = strlen(openfile->current->data);
size_t data_len = strlen(openfile->current->data);
if (openfile->current_x < data_len)
/* 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. */
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. */
extract_buffer(&cutbuffer, &cutbottom, openfile->current,
openfile->current_x, openfile->current->next, 0);
openfile->placewewant = xplustabs();
}
if (openfile->current_x < data_len)
/* 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. */
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. */
extract_buffer(&cutbuffer, &cutbottom, openfile->current,
openfile->current_x, openfile->current->next, 0);
openfile->placewewant = xplustabs();
}
}
/* Move all the text from the current cursor position to the end of the
* file into the cutbuffer. */
void cut_to_eof(void)
{
extract_buffer(&cutbuffer, &cutbottom,
openfile->current, openfile->current_x,
openfile->filebot, strlen(openfile->filebot->data));
extract_buffer(&cutbuffer, &cutbottom,
openfile->current, openfile->current_x,
openfile->filebot, strlen(openfile->filebot->data));
}
#endif /* !NANO_TINY */
@@ -114,86 +114,86 @@ void cut_to_eof(void)
void do_cut_text(bool copy_text, bool cut_till_eof)
{
#ifndef NANO_TINY
filestruct *cb_save = NULL;
/* The current end of the cutbuffer, before we add text to it. */
size_t cb_save_len = 0;
/* The length of the string at the current end of the cutbuffer,
* before we add text to it. */
bool old_no_newlines = ISSET(NO_NEWLINES);
bool right_side_up = TRUE;
/* There *is* no region, *or* it is marked forward. */
filestruct *cb_save = NULL;
/* The current end of the cutbuffer, before we add text to it. */
size_t cb_save_len = 0;
/* The length of the string at the current end of the cutbuffer,
* before we add text to it. */
bool old_no_newlines = ISSET(NO_NEWLINES);
bool right_side_up = TRUE;
/* There *is* no region, *or* it is marked forward. */
#endif
size_t was_totsize = openfile->totsize;
size_t was_totsize = openfile->totsize;
/* If a chain of cuts was broken, empty the cutbuffer. */
if (!keep_cutbuffer) {
free_filestruct(cutbuffer);
cutbuffer = NULL;
/* Indicate that future cuts should add to the cutbuffer. */
keep_cutbuffer = TRUE;
}
/* If a chain of cuts was broken, empty the cutbuffer. */
if (!keep_cutbuffer) {
free_filestruct(cutbuffer);
cutbuffer = NULL;
/* Indicate that future cuts should add to the cutbuffer. */
keep_cutbuffer = TRUE;
}
#ifndef NANO_TINY
if (copy_text) {
/* If the cutbuffer isn't empty, remember where it currently ends. */
if (cutbuffer != NULL) {
cb_save = cutbottom;
cb_save_len = strlen(cutbottom->data);
if (copy_text) {
/* If the cutbuffer isn't empty, remember where it currently ends. */
if (cutbuffer != NULL) {
cb_save = cutbottom;
cb_save_len = strlen(cutbottom->data);
}
/* Don't add a magicline when moving text to the cutbuffer. */
SET(NO_NEWLINES);
}
/* Don't add a magicline when moving text to the cutbuffer. */
SET(NO_NEWLINES);
}
if (cut_till_eof) {
/* Move all text up to the end of the file into the cutbuffer. */
cut_to_eof();
} else if (openfile->mark) {
/* Move the marked text to the cutbuffer, and turn the mark off. */
cut_marked(&right_side_up);
openfile->mark = NULL;
} else if (ISSET(CUT_FROM_CURSOR))
/* Move all text up to the end of the line into the cutbuffer. */
cut_to_eol();
else
if (cut_till_eof) {
/* Move all text up to the end of the file into the cutbuffer. */
cut_to_eof();
} else if (openfile->mark) {
/* Move the marked text to the cutbuffer, and turn the mark off. */
cut_marked(&right_side_up);
openfile->mark = NULL;
} else if (ISSET(CUT_FROM_CURSOR))
/* Move all text up to the end of the line into the cutbuffer. */
cut_to_eol();
else
#endif
/* Move the entire line into the cutbuffer. */
cut_line();
/* Move the entire line into the cutbuffer. */
cut_line();
#ifndef NANO_TINY
if (copy_text) {
/* Copy the text that is in the cutbuffer (starting at its saved end,
* if there is one) back into the current buffer. This effectively
* uncuts the text we just cut. */
if (cutbuffer != NULL) {
if (cb_save != NULL) {
cb_save->data += cb_save_len;
copy_from_buffer(cb_save);
cb_save->data -= cb_save_len;
} else
copy_from_buffer(cutbuffer);
if (copy_text) {
/* Copy the text that is in the cutbuffer (starting at its saved end,
* if there is one) back into the current buffer. This effectively
* uncuts the text we just cut. */
if (cutbuffer != NULL) {
if (cb_save != NULL) {
cb_save->data += cb_save_len;
copy_from_buffer(cb_save);
cb_save->data -= cb_save_len;
} else
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. */
if (right_side_up)
openfile->placewewant = xplustabs();
}
/* Restore the magicline behavior now that we're done fiddling. */
if (!old_no_newlines)
UNSET(NO_NEWLINES);
} else
/* If the copied region was marked forward, put the new desired
* x position at its end; otherwise, leave it at its beginning. */
if (right_side_up)
openfile->placewewant = xplustabs();
}
/* Restore the magicline behavior now that we're done fiddling. */
if (!old_no_newlines)
UNSET(NO_NEWLINES);
} else
#endif /* !NANO_TINY */
/* Only set the modification flag if actually something was cut. */
if (openfile->totsize != was_totsize)
set_modified();
/* Only set the modification flag if actually something was cut. */
if (openfile->totsize != was_totsize)
set_modified();
refresh_needed = TRUE;
refresh_needed = TRUE;
#ifdef ENABLE_COLOR
check_the_multis(openfile->current);
check_the_multis(openfile->current);
#endif
#ifdef DEBUG
dump_filestruct(cutbuffer);
dump_filestruct(cutbuffer);
#endif
}
@@ -201,11 +201,11 @@ void do_cut_text(bool copy_text, bool cut_till_eof)
void do_cut_text_void(void)
{
#ifndef NANO_TINY
add_undo(CUT);
add_undo(CUT);
#endif
do_cut_text(FALSE, FALSE);
do_cut_text(FALSE, FALSE);
#ifndef NANO_TINY
update_undo(CUT);
update_undo(CUT);
#endif
}
@@ -215,85 +215,79 @@ void do_cut_text_void(void)
* was moved, blow away previous contents of the cutbuffer. */
void do_copy_text(void)
{
static struct filestruct *next_contiguous_line = NULL;
bool mark_is_set = (openfile->mark != NULL);
static struct filestruct *next_contiguous_line = NULL;
bool mark_is_set = (openfile->mark != NULL);
/* Remember the current viewport and cursor position. */
ssize_t is_edittop_lineno = openfile->edittop->lineno;
size_t is_firstcolumn = openfile->firstcolumn;
ssize_t is_current_lineno = openfile->current->lineno;
size_t is_current_x = openfile->current_x;
/* Remember the current viewport and cursor position. */
ssize_t is_edittop_lineno = openfile->edittop->lineno;
size_t is_firstcolumn = openfile->firstcolumn;
ssize_t is_current_lineno = openfile->current->lineno;
size_t is_current_x = openfile->current_x;
if (mark_is_set || openfile->current != next_contiguous_line)
cutbuffer_reset();
if (mark_is_set || openfile->current != next_contiguous_line)
cutbuffer_reset();
do_cut_text(TRUE, FALSE);
do_cut_text(TRUE, FALSE);
/* If the mark was set, blow away the cutbuffer on the next copy. */
next_contiguous_line = (mark_is_set ? NULL : openfile->current);
/* If the mark was set, blow away the cutbuffer on the next copy. */
next_contiguous_line = (mark_is_set ? NULL : openfile->current);
/* If the mark was set, restore the viewport and cursor position. */
if (mark_is_set) {
openfile->edittop = fsfromline(is_edittop_lineno);
openfile->firstcolumn = is_firstcolumn;
openfile->current = fsfromline(is_current_lineno);
openfile->current_x = is_current_x;
}
/* If the mark was set, restore the viewport and cursor position. */
if (mark_is_set) {
openfile->edittop = fsfromline(is_edittop_lineno);
openfile->firstcolumn = is_firstcolumn;
openfile->current = fsfromline(is_current_lineno);
openfile->current_x = is_current_x;
}
}
/* Cut from the current cursor position to the end of the file. */
void do_cut_till_eof(void)
{
add_undo(CUT_TO_EOF);
do_cut_text(FALSE, TRUE);
update_undo(CUT_TO_EOF);
add_undo(CUT_TO_EOF);
do_cut_text(FALSE, TRUE);
update_undo(CUT_TO_EOF);
}
#endif /* !NANO_TINY */
/* Copy text from the cutbuffer into the current buffer. */
void do_uncut_text(void)
{
ssize_t was_lineno = openfile->current->lineno;
/* The line number where we started the paste. */
size_t was_leftedge = 0;
/* The leftedge where we started the paste. */
ssize_t was_lineno = openfile->current->lineno;
/* The line number where we started the paste. */
size_t was_leftedge = 0;
/* The leftedge where we started the paste. */
/* If the cutbuffer is empty, there is nothing to do. */
if (cutbuffer == NULL)
return;
/* If the cutbuffer is empty, there is nothing to do. */
if (cutbuffer == NULL)
return;
#ifndef NANO_TINY
add_undo(PASTE);
add_undo(PASTE);
if (ISSET(SOFTWRAP))
was_leftedge = leftedge_for(xplustabs(), openfile->current);
if (ISSET(SOFTWRAP))
was_leftedge = leftedge_for(xplustabs(), openfile->current);
#endif
/* Add a copy of the text in the cutbuffer to the current buffer
* at the current cursor position. */
copy_from_buffer(cutbuffer);
/* Add a copy of the text in the cutbuffer to the current buffer
* at the current cursor position. */
copy_from_buffer(cutbuffer);
#ifndef NANO_TINY
update_undo(PASTE);
update_undo(PASTE);
#endif
/* If we pasted less than a screenful, don't center the cursor. */
if (less_than_a_screenful(was_lineno, was_leftedge))
focusing = FALSE;
/* If we pasted less than a screenful, don't center the cursor. */
if (less_than_a_screenful(was_lineno, was_leftedge))
focusing = FALSE;
/* Set the desired x position to where the pasted text ends. */
openfile->placewewant = xplustabs();
/* Set the desired x position to where the pasted text ends. */
openfile->placewewant = xplustabs();
/* Mark the file as modified. */
set_modified();
refresh_needed = TRUE;
set_modified();
refresh_needed = TRUE;
#ifdef ENABLE_COLOR
check_the_multis(openfile->current);
#endif
#ifdef DEBUG
dump_filestruct_reverse();
check_the_multis(openfile->current);
#endif
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -35,146 +35,146 @@
#endif
static bool history_changed = FALSE;
/* Whether any of the history lists has changed. */
/* Whether any of the history lists has changed. */
static struct stat stat_of_positions_file;
/* The last-obtained stat information of the positions file. */
/* The last-obtained stat information of the positions file. */
static char *poshistname = NULL;
/* The name of the positions-history file. */
/* The name of the positions-history file. */
/* Initialize the lists of historical search and replace strings
* and the list of historical executed commands. */
void history_init(void)
{
search_history = make_new_node(NULL);
search_history->data = mallocstrcpy(NULL, "");
searchtop = search_history;
searchbot = search_history;
search_history = make_new_node(NULL);
search_history->data = mallocstrcpy(NULL, "");
searchtop = search_history;
searchbot = search_history;
replace_history = make_new_node(NULL);
replace_history->data = mallocstrcpy(NULL, "");
replacetop = replace_history;
replacebot = replace_history;
replace_history = make_new_node(NULL);
replace_history->data = mallocstrcpy(NULL, "");
replacetop = replace_history;
replacebot = replace_history;
execute_history = make_new_node(NULL);
execute_history->data = mallocstrcpy(NULL, "");
executetop = execute_history;
executebot = execute_history;
execute_history = make_new_node(NULL);
execute_history->data = mallocstrcpy(NULL, "");
executetop = execute_history;
executebot = execute_history;
}
/* Set the current position in the given history list to the bottom. */
void history_reset(const filestruct *list)
{
if (list == search_history)
search_history = searchbot;
else if (list == replace_history)
replace_history = replacebot;
else if (list == execute_history)
execute_history = executebot;
if (list == search_history)
search_history = searchbot;
else if (list == replace_history)
replace_history = replacebot;
else if (list == execute_history)
execute_history = executebot;
}
/* Return from the history list that starts at start and ends at end
* the first node that contains the first len characters of the given
* text, or NULL if there is no such node. */
filestruct *find_history(const filestruct *start, const filestruct *end,
const char *text, size_t len)
const char *text, size_t len)
{
const filestruct *item;
const filestruct *item;
for (item = start; item != end->prev && item != NULL; item = item->prev) {
if (strncmp(item->data, text, len) == 0)
return (filestruct *)item;
}
for (item = start; item != end->prev && item != NULL; item = item->prev) {
if (strncmp(item->data, text, len) == 0)
return (filestruct *)item;
}
return NULL;
return NULL;
}
/* Update a history list (the one in which item is the current position)
* with a fresh string text. That is: add text, or move it to the end. */
void update_history(filestruct **item, const char *text)
{
filestruct **htop = NULL, **hbot = NULL, *thesame;
filestruct **htop = NULL, **hbot = NULL, *thesame;
if (*item == search_history) {
htop = &searchtop;
hbot = &searchbot;
} else if (*item == replace_history) {
htop = &replacetop;
hbot = &replacebot;
} else if (*item == execute_history) {
htop = &executetop;
hbot = &executebot;
}
if (*item == search_history) {
htop = &searchtop;
hbot = &searchbot;
} else if (*item == replace_history) {
htop = &replacetop;
hbot = &replacebot;
} else if (*item == execute_history) {
htop = &executetop;
hbot = &executebot;
}
/* See if the string is already in the history. */
thesame = find_history(*hbot, *htop, text, HIGHEST_POSITIVE);
/* See if the string is already in the history. */
thesame = find_history(*hbot, *htop, text, HIGHEST_POSITIVE);
/* If an identical string was found, delete that item. */
if (thesame != NULL) {
filestruct *after = thesame->next;
/* If an identical string was found, delete that item. */
if (thesame != NULL) {
filestruct *after = thesame->next;
/* If the string is at the head of the list, move the head. */
if (thesame == *htop)
*htop = after;
/* If the string is at the head of the list, move the head. */
if (thesame == *htop)
*htop = after;
unlink_node(thesame);
renumber(after);
}
unlink_node(thesame);
renumber(after);
}
/* If the history is full, delete the oldest item (the one at the
* head of the list), to make room for a new item at the end. */
if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
filestruct *oldest = *htop;
/* If the history is full, delete the oldest item (the one at the
* head of the list), to make room for a new item at the end. */
if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
filestruct *oldest = *htop;
*htop = (*htop)->next;
unlink_node(oldest);
renumber(*htop);
}
*htop = (*htop)->next;
unlink_node(oldest);
renumber(*htop);
}
/* Store the fresh string in the last item, then create a new item. */
(*hbot)->data = mallocstrcpy((*hbot)->data, text);
splice_node(*hbot, make_new_node(*hbot));
*hbot = (*hbot)->next;
(*hbot)->data = mallocstrcpy(NULL, "");
/* Store the fresh string in the last item, then create a new item. */
(*hbot)->data = mallocstrcpy((*hbot)->data, text);
splice_node(*hbot, make_new_node(*hbot));
*hbot = (*hbot)->next;
(*hbot)->data = mallocstrcpy(NULL, "");
/* Indicate that the history needs to be saved on exit. */
history_changed = TRUE;
/* Indicate that the history needs to be saved on exit. */
history_changed = TRUE;
/* Set the current position in the list to the bottom. */
*item = *hbot;
/* Set the current position in the list to the bottom. */
*item = *hbot;
}
/* Move h to the string in the history list just before it, and return
* that string. If there isn't one, don't move h and return NULL. */
char *get_history_older(filestruct **h)
{
if ((*h)->prev == NULL)
return NULL;
if ((*h)->prev == NULL)
return NULL;
*h = (*h)->prev;
*h = (*h)->prev;
return (*h)->data;
return (*h)->data;
}
/* Move h to the string in the history list just after it, and return
* that string. If there isn't one, don't move h and return NULL. */
char *get_history_newer(filestruct **h)
{
if ((*h)->next == NULL)
return NULL;
if ((*h)->next == NULL)
return NULL;
*h = (*h)->next;
*h = (*h)->next;
return (*h)->data;
return (*h)->data;
}
/* More placeholders. */
void get_history_newer_void(void)
{
;
;
}
void get_history_older_void(void)
{
;
;
}
#ifdef ENABLE_TABCOMP
@@ -184,408 +184,408 @@ void get_history_older_void(void)
* s. */
char *get_history_completion(filestruct **h, char *s, size_t len)
{
if (len > 0) {
filestruct *htop = NULL, *hbot = NULL, *p;
if (len > 0) {
filestruct *htop = NULL, *hbot = NULL, *p;
if (*h == search_history) {
htop = searchtop;
hbot = searchbot;
} else if (*h == replace_history) {
htop = replacetop;
hbot = replacebot;
} else if (*h == execute_history) {
htop = executetop;
hbot = executebot;
if (*h == search_history) {
htop = searchtop;
hbot = searchbot;
} else if (*h == replace_history) {
htop = replacetop;
hbot = replacebot;
} else if (*h == execute_history) {
htop = executetop;
hbot = executebot;
}
/* Search the history list from the current position to the top
* for a match of len characters. Skip over an exact match. */
p = find_history((*h)->prev, htop, s, len);
while (p != NULL && strcmp(p->data, s) == 0)
p = find_history(p->prev, htop, s, len);
if (p != NULL) {
*h = p;
return mallocstrcpy(s, (*h)->data);
}
/* Search the history list from the bottom to the current position
* for a match of len characters. Skip over an exact match. */
p = find_history(hbot, *h, s, len);
while (p != NULL && strcmp(p->data, s) == 0)
p = find_history(p->prev, *h, s, len);
if (p != NULL) {
*h = p;
return mallocstrcpy(s, (*h)->data);
}
}
/* Search the history list from the current position to the top
* for a match of len characters. Skip over an exact match. */
p = find_history((*h)->prev, htop, s, len);
while (p != NULL && strcmp(p->data, s) == 0)
p = find_history(p->prev, htop, s, len);
if (p != NULL) {
*h = p;
return mallocstrcpy(s, (*h)->data);
}
/* Search the history list from the bottom to the current position
* for a match of len characters. Skip over an exact match. */
p = find_history(hbot, *h, s, len);
while (p != NULL && strcmp(p->data, s) == 0)
p = find_history(p->prev, *h, s, len);
if (p != NULL) {
*h = p;
return mallocstrcpy(s, (*h)->data);
}
}
/* If we're here, we didn't find a match, we didn't find an inexact
* match, or len is 0. Return s. */
return (char *)s;
/* If we're here, we didn't find a match, we didn't find an inexact
* match, or len is 0. Return s. */
return (char *)s;
}
#endif /* ENSABLE_TABCOMP */
void history_error(const char *msg, ...)
{
va_list ap;
va_list ap;
va_start(ap, msg);
vfprintf(stderr, _(msg), ap);
va_end(ap);
va_start(ap, msg);
vfprintf(stderr, _(msg), ap);
va_end(ap);
fprintf(stderr, _("\nPress Enter to continue\n"));
while (getchar() != '\n')
;
fprintf(stderr, _("\nPress Enter to continue\n"));
while (getchar() != '\n')
;
}
/* Check whether we have or could make a directory for history files. */
bool have_statedir(void)
{
struct stat dirstat;
const char *xdgdatadir;
struct stat dirstat;
const char *xdgdatadir;
get_homedir();
get_homedir();
if (homedir != NULL) {
statedir = concatenate(homedir, "/.nano/");
if (homedir != NULL) {
statedir = concatenate(homedir, "/.nano/");
if (stat(statedir, &dirstat) == 0 && S_ISDIR(dirstat.st_mode)) {
poshistname = concatenate(statedir, POSITION_HISTORY);
return TRUE;
if (stat(statedir, &dirstat) == 0 && S_ISDIR(dirstat.st_mode)) {
poshistname = concatenate(statedir, POSITION_HISTORY);
return TRUE;
}
}
}
free(statedir);
xdgdatadir = getenv("XDG_DATA_HOME");
free(statedir);
xdgdatadir = getenv("XDG_DATA_HOME");
if (homedir == NULL && xdgdatadir == NULL)
return FALSE;
if (homedir == NULL && xdgdatadir == NULL)
return FALSE;
if (xdgdatadir != NULL)
statedir = concatenate(xdgdatadir, "/nano/");
else
statedir = concatenate(homedir, "/.local/share/nano/");
if (xdgdatadir != NULL)
statedir = concatenate(xdgdatadir, "/nano/");
else
statedir = concatenate(homedir, "/.local/share/nano/");
if (stat(statedir, &dirstat) == -1) {
if (xdgdatadir == NULL) {
char *statepath = concatenate(homedir, "/.local");
mkdir(statepath, S_IRWXU | S_IRWXG | S_IRWXO);
free(statepath);
statepath = concatenate(homedir, "/.local/share");
mkdir(statepath, S_IRWXU);
free(statepath);
if (stat(statedir, &dirstat) == -1) {
if (xdgdatadir == NULL) {
char *statepath = concatenate(homedir, "/.local");
mkdir(statepath, S_IRWXU | S_IRWXG | S_IRWXO);
free(statepath);
statepath = concatenate(homedir, "/.local/share");
mkdir(statepath, S_IRWXU);
free(statepath);
}
if (mkdir(statedir, S_IRWXU) == -1) {
history_error(N_("Unable to create directory %s: %s\n"
"It is required for saving/loading "
"search history or cursor positions.\n"),
statedir, strerror(errno));
return FALSE;
}
} else if (!S_ISDIR(dirstat.st_mode)) {
history_error(N_("Path %s is not a directory and needs to be.\n"
"Nano will be unable to load or save "
"search history or cursor positions.\n"),
statedir);
return FALSE;
}
if (mkdir(statedir, S_IRWXU) == -1) {
history_error(N_("Unable to create directory %s: %s\n"
"It is required for saving/loading "
"search history or cursor positions.\n"),
statedir, strerror(errno));
return FALSE;
}
} else if (!S_ISDIR(dirstat.st_mode)) {
history_error(N_("Path %s is not a directory and needs to be.\n"
"Nano will be unable to load or save "
"search history or cursor positions.\n"),
statedir);
return FALSE;
}
poshistname = concatenate(statedir, POSITION_HISTORY);
return TRUE;
poshistname = concatenate(statedir, POSITION_HISTORY);
return TRUE;
}
/* Load the histories for Search and Replace and Execute Command. */
void load_history(void)
{
char *histname = concatenate(statedir, SEARCH_HISTORY);
FILE *hisfile = fopen(histname, "rb");
char *histname = concatenate(statedir, SEARCH_HISTORY);
FILE *hisfile = fopen(histname, "rb");
if (hisfile == NULL) {
if (errno != ENOENT) {
/* When reading failed, don't save history when we quit. */
UNSET(HISTORYLOG);
history_error(N_("Error reading %s: %s"), histname,
strerror(errno));
}
} else {
/* Load the three history lists -- first search, then replace,
* then execute -- from oldest entry to newest. Between two
* lists there is an empty line. */
filestruct **history = &search_history;
char *line = NULL;
size_t buf_len = 0;
ssize_t read;
if (hisfile == NULL) {
if (errno != ENOENT) {
/* When reading failed, don't save history when we quit. */
UNSET(HISTORYLOG);
history_error(N_("Error reading %s: %s"), histname,
strerror(errno));
}
} else {
/* Load the three history lists -- first search, then replace,
* then execute -- from oldest entry to newest. Between two
* lists there is an empty line. */
filestruct **history = &search_history;
char *line = NULL;
size_t buf_len = 0;
ssize_t read;
while ((read = getline(&line, &buf_len, hisfile)) > 0) {
line[--read] = '\0';
if (read > 0) {
/* Encode any embedded NUL as 0x0A. */
unsunder(line, read);
update_history(history, line);
} else if (history == &search_history)
history = &replace_history;
else
history = &execute_history;
while ((read = getline(&line, &buf_len, hisfile)) > 0) {
line[--read] = '\0';
if (read > 0) {
/* Encode any embedded NUL as 0x0A. */
unsunder(line, read);
update_history(history, line);
} else if (history == &search_history)
history = &replace_history;
else
history = &execute_history;
}
fclose(hisfile);
free(line);
}
fclose(hisfile);
free(line);
}
/* After reading them in, set the status of the lists to "unchanged". */
history_changed = FALSE;
/* After reading them in, set the status of the lists to "unchanged". */
history_changed = FALSE;
free(histname);
free(histname);
}
/* Write the lines of a history list, starting at head, from oldest to newest,
* to the given file. Return TRUE if writing succeeded, and FALSE otherwise. */
bool write_list(const filestruct *head, FILE *hisfile)
{
const filestruct *item;
const filestruct *item;
for (item = head; item != NULL; item = item->next) {
size_t length = strlen(item->data);
for (item = head; item != NULL; item = item->next) {
size_t length = strlen(item->data);
/* Decode 0x0A bytes as embedded NULs. */
sunder(item->data);
/* Decode 0x0A bytes as embedded NULs. */
sunder(item->data);
if (fwrite(item->data, sizeof(char), length, hisfile) < length)
return FALSE;
if (putc('\n', hisfile) == EOF)
return FALSE;
}
if (fwrite(item->data, sizeof(char), length, hisfile) < length)
return FALSE;
if (putc('\n', hisfile) == EOF)
return FALSE;
}
return TRUE;
return TRUE;
}
/* Save the histories for Search and Replace and Execute Command. */
void save_history(void)
{
char *histname;
FILE *hisfile;
char *histname;
FILE *hisfile;
/* If the histories are unchanged, don't bother saving them. */
if (!history_changed)
return;
/* If the histories are unchanged, don't bother saving them. */
if (!history_changed)
return;
histname = concatenate(statedir, SEARCH_HISTORY);
hisfile = fopen(histname, "wb");
histname = concatenate(statedir, SEARCH_HISTORY);
hisfile = fopen(histname, "wb");
if (hisfile == NULL)
fprintf(stderr, _("Error writing %s: %s\n"), histname,
strerror(errno));
else {
/* Don't allow others to read or write the history file. */
chmod(histname, S_IRUSR | S_IWUSR);
if (hisfile == NULL)
fprintf(stderr, _("Error writing %s: %s\n"), histname,
strerror(errno));
else {
/* Don't allow others to read or write the history file. */
chmod(histname, S_IRUSR | S_IWUSR);
if (!write_list(searchtop, hisfile) ||
!write_list(replacetop, hisfile) ||
!write_list(executetop, hisfile))
fprintf(stderr, _("Error writing %s: %s\n"), histname,
strerror(errno));
if (!write_list(searchtop, hisfile) ||
!write_list(replacetop, hisfile) ||
!write_list(executetop, hisfile))
fprintf(stderr, _("Error writing %s: %s\n"), histname,
strerror(errno));
fclose(hisfile);
}
fclose(hisfile);
}
free(histname);
free(histname);
}
/* Load the recorded cursor positions for files that were edited. */
void load_poshistory(void)
{
FILE *hisfile = fopen(poshistname, "rb");
FILE *hisfile = fopen(poshistname, "rb");
if (hisfile == NULL) {
if (errno != ENOENT) {
/* When reading failed, don't save history when we quit. */
UNSET(POS_HISTORY);
history_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
if (hisfile == NULL) {
if (errno != ENOENT) {
/* When reading failed, don't save history when we quit. */
UNSET(POS_HISTORY);
history_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
}
} else {
char *line = NULL, *lineptr, *xptr;
size_t buf_len = 0;
ssize_t read, count = 0;
poshiststruct *record_ptr = NULL, *newrecord;
/* Read and parse each line, and store the extracted data. */
while ((read = getline(&line, &buf_len, hisfile)) > 5) {
/* Decode nulls as embedded newlines. */
unsunder(line, read);
/* Find where the x index and line number are in the line. */
xptr = revstrstr(line, " ", line + read - 3);
if (xptr == NULL)
continue;
lineptr = revstrstr(line, " ", xptr - 2);
if (lineptr == NULL)
continue;
/* Now separate the three elements of the line. */
*(xptr++) = '\0';
*(lineptr++) = '\0';
/* Create a new position record. */
newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct));
newrecord->filename = mallocstrcpy(NULL, line);
newrecord->lineno = atoi(lineptr);
newrecord->xno = atoi(xptr);
newrecord->next = NULL;
/* Add the record to the list. */
if (position_history == NULL)
position_history = newrecord;
else
record_ptr->next = newrecord;
record_ptr = newrecord;
/* Impose a limit, so the file will not grow indefinitely. */
if (++count > 200) {
poshiststruct *drop_record = position_history;
position_history = position_history->next;
free(drop_record->filename);
free(drop_record);
}
}
fclose(hisfile);
free(line);
stat(poshistname, &stat_of_positions_file);
}
} else {
char *line = NULL, *lineptr, *xptr;
size_t buf_len = 0;
ssize_t read, count = 0;
poshiststruct *record_ptr = NULL, *newrecord;
/* Read and parse each line, and store the extracted data. */
while ((read = getline(&line, &buf_len, hisfile)) > 5) {
/* Decode nulls as embedded newlines. */
unsunder(line, read);
/* Find where the x index and line number are in the line. */
xptr = revstrstr(line, " ", line + read - 3);
if (xptr == NULL)
continue;
lineptr = revstrstr(line, " ", xptr - 2);
if (lineptr == NULL)
continue;
/* Now separate the three elements of the line. */
*(xptr++) = '\0';
*(lineptr++) = '\0';
/* Create a new position record. */
newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct));
newrecord->filename = mallocstrcpy(NULL, line);
newrecord->lineno = atoi(lineptr);
newrecord->xno = atoi(xptr);
newrecord->next = NULL;
/* Add the record to the list. */
if (position_history == NULL)
position_history = newrecord;
else
record_ptr->next = newrecord;
record_ptr = newrecord;
/* Impose a limit, so the file will not grow indefinitely. */
if (++count > 200) {
poshiststruct *drop_record = position_history;
position_history = position_history->next;
free(drop_record->filename);
free(drop_record);
}
}
fclose(hisfile);
free(line);
stat(poshistname, &stat_of_positions_file);
}
}
/* Save the recorded cursor positions for files that were edited. */
void save_poshistory(void)
{
poshiststruct *posptr;
FILE *hisfile = fopen(poshistname, "wb");
poshiststruct *posptr;
FILE *hisfile = fopen(poshistname, "wb");
if (hisfile == NULL)
fprintf(stderr, _("Error writing %s: %s\n"), poshistname, strerror(errno));
else {
/* Don't allow others to read or write the history file. */
chmod(poshistname, S_IRUSR | S_IWUSR);
if (hisfile == NULL)
fprintf(stderr, _("Error writing %s: %s\n"), poshistname, strerror(errno));
else {
/* Don't allow others to read or write the history file. */
chmod(poshistname, S_IRUSR | S_IWUSR);
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
char *path_and_place;
size_t length;
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
char *path_and_place;
size_t length;
/* Assume 20 decimal positions each for line and column number,
* plus two spaces, plus the line feed, plus the null byte. */
path_and_place = charalloc(strlen(posptr->filename) + 44);
sprintf(path_and_place, "%s %zd %zd\n",
posptr->filename, posptr->lineno, posptr->xno);
length = strlen(path_and_place);
/* Assume 20 decimal positions each for line and column number,
* plus two spaces, plus the line feed, plus the null byte. */
path_and_place = charalloc(strlen(posptr->filename) + 44);
sprintf(path_and_place, "%s %zd %zd\n",
posptr->filename, posptr->lineno, posptr->xno);
length = strlen(path_and_place);
/* Encode newlines in filenames as nulls. */
sunder(path_and_place);
/* Restore the terminating newline. */
path_and_place[length - 1] = '\n';
/* Encode newlines in filenames as nulls. */
sunder(path_and_place);
/* Restore the terminating newline. */
path_and_place[length - 1] = '\n';
if (fwrite(path_and_place, sizeof(char), length, hisfile) < length)
fprintf(stderr, _("Error writing %s: %s\n"),
poshistname, strerror(errno));
free(path_and_place);
if (fwrite(path_and_place, sizeof(char), length, hisfile) < length)
fprintf(stderr, _("Error writing %s: %s\n"),
poshistname, strerror(errno));
free(path_and_place);
}
fclose(hisfile);
stat(poshistname, &stat_of_positions_file);
}
fclose(hisfile);
stat(poshistname, &stat_of_positions_file);
}
}
/* Reload the position history file if it has been modified since last load. */
void reload_positions_if_needed(void)
{
struct stat newstat;
struct stat newstat;
stat(poshistname, &newstat);
stat(poshistname, &newstat);
if (newstat.st_mtime != stat_of_positions_file.st_mtime) {
poshiststruct *ptr, *nextone;
if (newstat.st_mtime != stat_of_positions_file.st_mtime) {
poshiststruct *ptr, *nextone;
for (ptr = position_history; ptr != NULL; ptr = nextone) {
nextone = ptr->next;
free(ptr->filename);
free(ptr);
for (ptr = position_history; ptr != NULL; ptr = nextone) {
nextone = ptr->next;
free(ptr->filename);
free(ptr);
}
position_history = NULL;
load_poshistory();
}
position_history = NULL;
load_poshistory();
}
}
/* Update the recorded last file positions, given a filename, a line
* and a column. If no entry is found, add a new one at the end. */
void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos)
{
poshiststruct *posptr, *theone, *posprev = NULL;
char *fullpath = get_full_path(filename);
poshiststruct *posptr, *theone, *posprev = NULL;
char *fullpath = get_full_path(filename);
if (fullpath == NULL || fullpath[strlen(fullpath) - 1] == '/' || inhelp) {
free(fullpath);
return;
}
reload_positions_if_needed();
/* Look for a matching filename in the list. */
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
if (!strcmp(posptr->filename, fullpath))
break;
posprev = posptr;
}
/* Don't record files that have the default cursor position. */
if (lineno == 1 && xpos == 1) {
if (posptr != NULL) {
if (posprev == NULL)
position_history = posptr->next;
else
posprev->next = posptr->next;
free(posptr->filename);
free(posptr);
save_poshistory();
if (fullpath == NULL || fullpath[strlen(fullpath) - 1] == '/' || inhelp) {
free(fullpath);
return;
}
reload_positions_if_needed();
/* Look for a matching filename in the list. */
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
if (!strcmp(posptr->filename, fullpath))
break;
posprev = posptr;
}
/* Don't record files that have the default cursor position. */
if (lineno == 1 && xpos == 1) {
if (posptr != NULL) {
if (posprev == NULL)
position_history = posptr->next;
else
posprev->next = posptr->next;
free(posptr->filename);
free(posptr);
save_poshistory();
}
free(fullpath);
return;
}
theone = posptr;
/* If we didn't find it, make a new node; otherwise, if we're
* not at the end, move the matching one to the end. */
if (theone == NULL) {
theone = (poshiststruct *)nmalloc(sizeof(poshiststruct));
theone->filename = mallocstrcpy(NULL, fullpath);
if (position_history == NULL)
position_history = theone;
else
posprev->next = theone;
} else if (posptr->next != NULL) {
if (posprev == NULL)
position_history = posptr->next;
else
posprev->next = posptr->next;
while (posptr->next != NULL)
posptr = posptr->next;
posptr->next = theone;
}
/* Store the last cursor position. */
theone->lineno = lineno;
theone->xno = xpos;
theone->next = NULL;
free(fullpath);
return;
}
theone = posptr;
/* If we didn't find it, make a new node; otherwise, if we're
* not at the end, move the matching one to the end. */
if (theone == NULL) {
theone = (poshiststruct *)nmalloc(sizeof(poshiststruct));
theone->filename = mallocstrcpy(NULL, fullpath);
if (position_history == NULL)
position_history = theone;
else
posprev->next = theone;
} else if (posptr->next != NULL) {
if (posprev == NULL)
position_history = posptr->next;
else
posprev->next = posptr->next;
while (posptr->next != NULL)
posptr = posptr->next;
posptr->next = theone;
}
/* Store the last cursor position. */
theone->lineno = lineno;
theone->xno = xpos;
theone->next = NULL;
free(fullpath);
save_poshistory();
save_poshistory();
}
/* Check whether the given file matches an existing entry in the recorded
@@ -593,24 +593,24 @@ void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos)
* set line and column to the retrieved values. */
bool has_old_position(const char *file, ssize_t *line, ssize_t *column)
{
poshiststruct *posptr = position_history;
char *fullpath = get_full_path(file);
poshiststruct *posptr = position_history;
char *fullpath = get_full_path(file);
if (fullpath == NULL)
return FALSE;
if (fullpath == NULL)
return FALSE;
reload_positions_if_needed();
reload_positions_if_needed();
while (posptr != NULL && strcmp(posptr->filename, fullpath) != 0)
posptr = posptr->next;
while (posptr != NULL && strcmp(posptr->filename, fullpath) != 0)
posptr = posptr->next;
free(fullpath);
free(fullpath);
if (posptr == NULL)
return FALSE;
if (posptr == NULL)
return FALSE;
*line = posptr->lineno;
*column = posptr->xno;
return TRUE;
*line = posptr->lineno;
*column = posptr->xno;
return TRUE;
}
#endif /* ENABLE_HISTORIES */

View File

@@ -24,44 +24,44 @@
#include <string.h>
/* Move to the first line of the file. */
void do_first_line(void)
void to_first_line(void)
{
openfile->current = openfile->fileage;
openfile->current_x = 0;
openfile->placewewant = 0;
openfile->current = openfile->fileage;
openfile->current_x = 0;
openfile->placewewant = 0;
refresh_needed = TRUE;
refresh_needed = TRUE;
}
/* Move to the last line of the file. */
void do_last_line(void)
void to_last_line(void)
{
openfile->current = openfile->filebot;
openfile->current_x = strlen(openfile->filebot->data);
openfile->placewewant = xplustabs();
openfile->current = openfile->filebot;
openfile->current_x = strlen(openfile->filebot->data);
openfile->placewewant = xplustabs();
/* Set the last line of the screen as the target for the cursor. */
openfile->current_y = editwinrows - 1;
/* Set the last line of the screen as the target for the cursor. */
openfile->current_y = editwinrows - 1;
refresh_needed = TRUE;
focusing = FALSE;
refresh_needed = TRUE;
focusing = FALSE;
}
/* Determine the actual current chunk and the target column. */
void get_edge_and_target(size_t *leftedge, size_t *target_column)
{
#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
size_t shim = editwincols * (1 + (tabsize / editwincols));
if (ISSET(SOFTWRAP)) {
size_t shim = editwincols * (1 + (tabsize / editwincols));
*leftedge = leftedge_for(xplustabs(), openfile->current);
*target_column = (openfile->placewewant + shim - *leftedge) % editwincols;
} else
*leftedge = leftedge_for(xplustabs(), openfile->current);
*target_column = (openfile->placewewant + shim - *leftedge) % editwincols;
} else
#endif
{
*leftedge = 0;
*target_column = openfile->placewewant;
}
{
*leftedge = 0;
*target_column = openfile->placewewant;
}
}
/* Return the index in line->data that corresponds to the given column on the
@@ -69,104 +69,104 @@ void get_edge_and_target(size_t *leftedge, size_t *target_column)
* on a tab, prevent the cursor from falling back a row when moving forward,
* or from skipping a row when moving backward, by incrementing the index. */
size_t proper_x(filestruct *line, size_t *leftedge, bool forward,
size_t column, bool *shifted)
size_t column, bool *shifted)
{
size_t index = actual_x(line->data, column);
size_t index = actual_x(line->data, column);
#ifndef NANO_TINY
if (ISSET(SOFTWRAP) && line->data[index] == '\t' &&
((forward && strnlenpt(line->data, index) < *leftedge) ||
(!forward && column / tabsize == (*leftedge - 1) / tabsize &&
column / tabsize < (*leftedge + editwincols - 1) / tabsize))) {
index++;
if (ISSET(SOFTWRAP) && line->data[index] == '\t' &&
((forward && strnlenpt(line->data, index) < *leftedge) ||
(!forward && column / tabsize == (*leftedge - 1) / tabsize &&
column / tabsize < (*leftedge + editwincols - 1) / tabsize))) {
index++;
if (shifted != NULL)
*shifted = TRUE;
}
if (shifted != NULL)
*shifted = TRUE;
}
if (ISSET(SOFTWRAP))
*leftedge = leftedge_for(strnlenpt(line->data, index), line);
if (ISSET(SOFTWRAP))
*leftedge = leftedge_for(strnlenpt(line->data, index), line);
#endif
return index;
return index;
}
/* Adjust the values for current_x and placewewant in case we have landed in
* the middle of a tab that crosses a row boundary. */
void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward)
{
bool shifted = FALSE;
size_t was_edge = *leftedge;
bool shifted = FALSE;
size_t was_edge = *leftedge;
openfile->current_x = proper_x(openfile->current, leftedge, forward,
actual_last_column(*leftedge, target), &shifted);
/* If the index was incremented, try going to the target column. */
if (shifted || *leftedge < was_edge)
openfile->current_x = proper_x(openfile->current, leftedge, forward,
actual_last_column(*leftedge, target), &shifted);
actual_last_column(*leftedge, target), &shifted);
openfile->placewewant = *leftedge + target;
/* If the index was incremented, try going to the target column. */
if (shifted || *leftedge < was_edge)
openfile->current_x = proper_x(openfile->current, leftedge, forward,
actual_last_column(*leftedge, target), &shifted);
openfile->placewewant = *leftedge + target;
}
/* Move up nearly one screenful. */
void do_page_up(void)
{
int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
size_t leftedge, target_column;
int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
size_t leftedge, target_column;
/* If we're not in smooth scrolling mode, put the cursor at the
* beginning of the top line of the edit window, as Pico does. */
if (!ISSET(SMOOTH_SCROLL)) {
openfile->current = openfile->edittop;
leftedge = openfile->firstcolumn;
openfile->current_y = 0;
target_column = 0;
} else
get_edge_and_target(&leftedge, &target_column);
/* If we're not in smooth scrolling mode, put the cursor at the
* beginning of the top line of the edit window, as Pico does. */
if (!ISSET(SMOOTH_SCROLL)) {
openfile->current = openfile->edittop;
leftedge = openfile->firstcolumn;
openfile->current_y = 0;
target_column = 0;
} else
get_edge_and_target(&leftedge, &target_column);
/* Move up the required number of lines or chunks. If we can't, we're
* at the top of the file, so put the cursor there and get out. */
if (go_back_chunks(mustmove, &openfile->current, &leftedge) > 0) {
do_first_line();
return;
}
/* Move up the required number of lines or chunks. If we can't, we're
* at the top of the file, so put the cursor there and get out. */
if (go_back_chunks(mustmove, &openfile->current, &leftedge) > 0) {
to_first_line();
return;
}
set_proper_index_and_pww(&leftedge, target_column, FALSE);
set_proper_index_and_pww(&leftedge, target_column, FALSE);
/* Move the viewport so that the cursor stays immobile, if possible. */
adjust_viewport(STATIONARY);
refresh_needed = TRUE;
/* Move the viewport so that the cursor stays immobile, if possible. */
adjust_viewport(STATIONARY);
refresh_needed = TRUE;
}
/* Move down nearly one screenful. */
void do_page_down(void)
{
int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
size_t leftedge, target_column;
int mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
size_t leftedge, target_column;
/* If we're not in smooth scrolling mode, put the cursor at the
* beginning of the top line of the edit window, as Pico does. */
if (!ISSET(SMOOTH_SCROLL)) {
openfile->current = openfile->edittop;
leftedge = openfile->firstcolumn;
openfile->current_y = 0;
target_column = 0;
} else
get_edge_and_target(&leftedge, &target_column);
/* If we're not in smooth scrolling mode, put the cursor at the
* beginning of the top line of the edit window, as Pico does. */
if (!ISSET(SMOOTH_SCROLL)) {
openfile->current = openfile->edittop;
leftedge = openfile->firstcolumn;
openfile->current_y = 0;
target_column = 0;
} else
get_edge_and_target(&leftedge, &target_column);
/* Move down the required number of lines or chunks. If we can't, we're
* at the bottom of the file, so put the cursor there and get out. */
if (go_forward_chunks(mustmove, &openfile->current, &leftedge) > 0) {
do_last_line();
return;
}
/* Move down the required number of lines or chunks. If we can't, we're
* at the bottom of the file, so put the cursor there and get out. */
if (go_forward_chunks(mustmove, &openfile->current, &leftedge) > 0) {
to_last_line();
return;
}
set_proper_index_and_pww(&leftedge, target_column, TRUE);
set_proper_index_and_pww(&leftedge, target_column, TRUE);
/* Move the viewport so that the cursor stays immobile, if possible. */
adjust_viewport(STATIONARY);
refresh_needed = TRUE;
/* Move the viewport so that the cursor stays immobile, if possible. */
adjust_viewport(STATIONARY);
refresh_needed = TRUE;
}
#ifdef ENABLE_JUSTIFY
@@ -174,18 +174,18 @@ void do_page_down(void)
* current line. If update_screen is TRUE, update the screen afterwards. */
void do_para_begin(bool update_screen)
{
filestruct *was_current = openfile->current;
filestruct *was_current = openfile->current;
if (openfile->current != openfile->fileage)
openfile->current = openfile->current->prev;
if (openfile->current != openfile->fileage)
openfile->current = openfile->current->prev;
while (!begpar(openfile->current))
openfile->current = openfile->current->prev;
while (!begpar(openfile->current))
openfile->current = openfile->current->prev;
openfile->current_x = 0;
openfile->current_x = 0;
if (update_screen)
edit_redraw(was_current, CENTERING);
if (update_screen)
edit_redraw(was_current, CENTERING);
}
/* Move down to the beginning of the last line of the current paragraph.
@@ -196,122 +196,122 @@ void do_para_begin(bool update_screen)
* paragraph or isn't in a paragraph. */
void do_para_end(bool update_screen)
{
filestruct *was_current = openfile->current;
filestruct *was_current = openfile->current;
while (openfile->current != openfile->filebot &&
!inpar(openfile->current))
openfile->current = openfile->current->next;
while (openfile->current != openfile->filebot &&
!inpar(openfile->current))
openfile->current = openfile->current->next;
while (openfile->current != openfile->filebot &&
inpar(openfile->current->next) &&
!begpar(openfile->current->next)) {
openfile->current = openfile->current->next;
}
while (openfile->current != openfile->filebot &&
inpar(openfile->current->next) &&
!begpar(openfile->current->next)) {
openfile->current = openfile->current->next;
}
if (openfile->current != openfile->filebot) {
openfile->current = openfile->current->next;
openfile->current_x = 0;
} else
openfile->current_x = strlen(openfile->current->data);
if (openfile->current != openfile->filebot) {
openfile->current = openfile->current->next;
openfile->current_x = 0;
} else
openfile->current_x = strlen(openfile->current->data);
if (update_screen)
edit_redraw(was_current, CENTERING);
if (update_screen)
edit_redraw(was_current, CENTERING);
}
/* Move up to first start of a paragraph before the current line. */
void do_para_begin_void(void)
{
do_para_begin(TRUE);
do_para_begin(TRUE);
}
/* Move down to just after the first end of a paragraph. */
void do_para_end_void(void)
{
do_para_end(TRUE);
do_para_end(TRUE);
}
#endif /* ENABLE_JUSTIFY */
/* Move to the preceding block of text. */
void do_prev_block(void)
{
filestruct *was_current = openfile->current;
bool is_text = FALSE, seen_text = FALSE;
filestruct *was_current = openfile->current;
bool is_text = FALSE, seen_text = FALSE;
/* Skip backward until first blank line after some nonblank line(s). */
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
openfile->current = openfile->current->prev;
is_text = !white_string(openfile->current->data);
seen_text = seen_text || is_text;
}
/* Skip backward until first blank line after some nonblank line(s). */
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
openfile->current = openfile->current->prev;
is_text = !white_string(openfile->current->data);
seen_text = seen_text || is_text;
}
/* Step forward one line again if this one is blank. */
if (openfile->current->next != NULL &&
white_string(openfile->current->data))
openfile->current = openfile->current->next;
/* Step forward one line again if this one is blank. */
if (openfile->current->next != NULL &&
white_string(openfile->current->data))
openfile->current = openfile->current->next;
openfile->current_x = 0;
edit_redraw(was_current, CENTERING);
openfile->current_x = 0;
edit_redraw(was_current, CENTERING);
}
/* Move to the next block of text. */
void do_next_block(void)
{
filestruct *was_current = openfile->current;
bool is_white = white_string(openfile->current->data);
bool seen_white = is_white;
filestruct *was_current = openfile->current;
bool is_white = white_string(openfile->current->data);
bool seen_white = is_white;
/* Skip forward until first nonblank line after some blank line(s). */
while (openfile->current->next != NULL && (!seen_white || is_white)) {
openfile->current = openfile->current->next;
is_white = white_string(openfile->current->data);
seen_white = seen_white || is_white;
}
/* Skip forward until first nonblank line after some blank line(s). */
while (openfile->current->next != NULL && (!seen_white || is_white)) {
openfile->current = openfile->current->next;
is_white = white_string(openfile->current->data);
seen_white = seen_white || is_white;
}
openfile->current_x = 0;
edit_redraw(was_current, CENTERING);
openfile->current_x = 0;
edit_redraw(was_current, CENTERING);
}
/* Move to the previous word. If allow_punct is TRUE, treat punctuation
* as part of a word. When requested, update the screen afterwards. */
void do_prev_word(bool allow_punct, bool update_screen)
{
filestruct *was_current = openfile->current;
bool seen_a_word = FALSE, step_forward = FALSE;
filestruct *was_current = openfile->current;
bool seen_a_word = FALSE, step_forward = FALSE;
/* Move backward until we pass over the start of a word. */
while (TRUE) {
/* If at the head of a line, move to the end of the preceding one. */
if (openfile->current_x == 0) {
if (openfile->current->prev == NULL)
break;
openfile->current = openfile->current->prev;
openfile->current_x = strlen(openfile->current->data);
/* Move backward until we pass over the start of a word. */
while (TRUE) {
/* If at the head of a line, move to the end of the preceding one. */
if (openfile->current_x == 0) {
if (openfile->current->prev == NULL)
break;
openfile->current = openfile->current->prev;
openfile->current_x = strlen(openfile->current->data);
}
/* Step back one character. */
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
if (is_word_mbchar(openfile->current->data + openfile->current_x,
allow_punct)) {
seen_a_word = TRUE;
/* If at the head of a line now, this surely is a word start. */
if (openfile->current_x == 0)
break;
} else if (seen_a_word) {
/* This is space now: we've overshot the start of the word. */
step_forward = TRUE;
break;
}
}
/* Step back one character. */
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
if (step_forward)
/* Move one character forward again to sit on the start of the word. */
openfile->current_x = move_mbright(openfile->current->data,
openfile->current_x);
if (is_word_mbchar(openfile->current->data + openfile->current_x,
allow_punct)) {
seen_a_word = TRUE;
/* If at the head of a line now, this surely is a word start. */
if (openfile->current_x == 0)
break;
} else if (seen_a_word) {
/* This is space now: we've overshot the start of the word. */
step_forward = TRUE;
break;
}
}
if (step_forward)
/* Move one character forward again to sit on the start of the word. */
openfile->current_x = move_mbright(openfile->current->data,
openfile->current_x);
if (update_screen)
edit_redraw(was_current, FLOWING);
if (update_screen)
edit_redraw(was_current, FLOWING);
}
/* Move to the next word. If allow_punct is TRUE, treat punctuation
@@ -319,55 +319,55 @@ void do_prev_word(bool allow_punct, bool update_screen)
* Return TRUE if we started on a word, and FALSE otherwise. */
bool do_next_word(bool allow_punct, bool update_screen)
{
filestruct *was_current = openfile->current;
bool started_on_word = is_word_mbchar(openfile->current->data +
openfile->current_x, allow_punct);
bool seen_space = !started_on_word;
filestruct *was_current = openfile->current;
bool started_on_word = is_word_mbchar(openfile->current->data +
openfile->current_x, allow_punct);
bool seen_space = !started_on_word;
/* Move forward until we reach the start of a word. */
while (TRUE) {
/* If at the end of a line, move to the beginning of the next one. */
if (openfile->current->data[openfile->current_x] == '\0') {
/* When at end of file, stop. */
if (openfile->current->next == NULL)
break;
openfile->current = openfile->current->next;
openfile->current_x = 0;
seen_space = TRUE;
} else {
/* Step forward one character. */
openfile->current_x = move_mbright(openfile->current->data,
openfile->current_x);
/* Move forward until we reach the start of a word. */
while (TRUE) {
/* If at the end of a line, move to the beginning of the next one. */
if (openfile->current->data[openfile->current_x] == '\0') {
/* When at end of file, stop. */
if (openfile->current->next == NULL)
break;
openfile->current = openfile->current->next;
openfile->current_x = 0;
seen_space = TRUE;
} else {
/* Step forward one character. */
openfile->current_x = move_mbright(openfile->current->data,
openfile->current_x);
}
/* If this is not a word character, then it's a separator; else
* if we've already seen a separator, then it's a word start. */
if (!is_word_mbchar(openfile->current->data + openfile->current_x,
allow_punct))
seen_space = TRUE;
else if (seen_space)
break;
}
/* If this is not a word character, then it's a separator; else
* if we've already seen a separator, then it's a word start. */
if (!is_word_mbchar(openfile->current->data + openfile->current_x,
allow_punct))
seen_space = TRUE;
else if (seen_space)
break;
}
if (update_screen)
edit_redraw(was_current, FLOWING);
if (update_screen)
edit_redraw(was_current, FLOWING);
/* Return whether we started on a word. */
return started_on_word;
/* Return whether we started on a word. */
return started_on_word;
}
/* Move to the previous word in the file, treating punctuation as part of a
* word if the WORD_BOUNDS flag is set, and update the screen afterwards. */
void do_prev_word_void(void)
{
do_prev_word(ISSET(WORD_BOUNDS), TRUE);
do_prev_word(ISSET(WORD_BOUNDS), TRUE);
}
/* Move to the next word in the file, treating punctuation as part of a word
* if the WORD_BOUNDS flag is set, and update the screen afterwards. */
void do_next_word_void(void)
{
do_next_word(ISSET(WORD_BOUNDS), TRUE);
do_next_word(ISSET(WORD_BOUNDS), TRUE);
}
/* Move to the beginning of the current line (or softwrapped chunk).
@@ -375,59 +375,59 @@ void do_next_word_void(void)
* of the full line when already at the start of a chunk. */
void do_home(void)
{
filestruct *was_current = openfile->current;
size_t was_column = xplustabs();
bool moved_off_chunk = TRUE;
filestruct *was_current = openfile->current;
size_t was_column = xplustabs();
bool moved_off_chunk = TRUE;
#ifndef NANO_TINY
bool moved = FALSE;
size_t leftedge = 0, leftedge_x = 0;
bool moved = FALSE;
size_t leftedge = 0, leftedge_x = 0;
if (ISSET(SOFTWRAP)) {
leftedge = leftedge_for(was_column, openfile->current);
leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge,
NULL);
}
if (ISSET(SMART_HOME)) {
size_t indent_x = indent_length(openfile->current->data);
if (openfile->current->data[indent_x] != '\0') {
/* If we're exactly on the indent, move fully home. Otherwise,
* when not softwrapping or not after the first nonblank chunk,
* move to the first nonblank character. */
if (openfile->current_x == indent_x) {
openfile->current_x = 0;
moved = TRUE;
} else if (!ISSET(SOFTWRAP) || leftedge_x <= indent_x) {
openfile->current_x = indent_x;
moved = TRUE;
}
if (ISSET(SOFTWRAP)) {
leftedge = leftedge_for(was_column, openfile->current);
leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge,
NULL);
}
}
if (!moved && ISSET(SOFTWRAP)) {
/* If already at the left edge of the screen, move fully home.
* Otherwise, move to the left edge. */
if (openfile->current_x == leftedge_x)
openfile->current_x = 0;
else {
openfile->current_x = leftedge_x;
openfile->placewewant = leftedge;
moved_off_chunk = FALSE;
if (ISSET(SMART_HOME)) {
size_t indent_x = indent_length(openfile->current->data);
if (openfile->current->data[indent_x] != '\0') {
/* If we're exactly on the indent, move fully home. Otherwise,
* when not softwrapping or not after the first nonblank chunk,
* move to the first nonblank character. */
if (openfile->current_x == indent_x) {
openfile->current_x = 0;
moved = TRUE;
} else if (!ISSET(SOFTWRAP) || leftedge_x <= indent_x) {
openfile->current_x = indent_x;
moved = TRUE;
}
}
}
} else if (!moved)
if (!moved && ISSET(SOFTWRAP)) {
/* If already at the left edge of the screen, move fully home.
* Otherwise, move to the left edge. */
if (openfile->current_x == leftedge_x)
openfile->current_x = 0;
else {
openfile->current_x = leftedge_x;
openfile->placewewant = leftedge;
moved_off_chunk = FALSE;
}
} else if (!moved)
#endif
openfile->current_x = 0;
openfile->current_x = 0;
if (moved_off_chunk)
openfile->placewewant = xplustabs();
if (moved_off_chunk)
openfile->placewewant = xplustabs();
/* If we changed chunk, we might be offscreen. Otherwise,
* update current if the mark is on or we changed "page". */
if (ISSET(SOFTWRAP) && moved_off_chunk)
edit_redraw(was_current, FLOWING);
else if (line_needs_update(was_column, openfile->placewewant))
update_line(openfile->current, openfile->current_x);
/* If we changed chunk, we might be offscreen. Otherwise,
* update current if the mark is on or we changed "page". */
if (ISSET(SOFTWRAP) && moved_off_chunk)
edit_redraw(was_current, FLOWING);
else if (line_needs_update(was_column, openfile->placewewant))
update_line(openfile->current, openfile->current_x);
}
/* Move to the end of the current line (or softwrapped chunk).
@@ -435,159 +435,159 @@ void do_home(void)
* end of the full line. */
void do_end(void)
{
filestruct *was_current = openfile->current;
size_t was_column = xplustabs();
size_t line_len = strlen(openfile->current->data);
bool moved_off_chunk = TRUE;
filestruct *was_current = openfile->current;
size_t was_column = xplustabs();
size_t line_len = strlen(openfile->current->data);
bool moved_off_chunk = TRUE;
#ifndef NANO_TINY
if (ISSET(SOFTWRAP)) {
bool last_chunk = FALSE;
size_t leftedge = leftedge_for(was_column, openfile->current);
size_t rightedge = get_softwrap_breakpoint(openfile->current->data,
leftedge, &last_chunk);
size_t rightedge_x;
if (ISSET(SOFTWRAP)) {
bool last_chunk = FALSE;
size_t leftedge = leftedge_for(was_column, openfile->current);
size_t rightedge = get_softwrap_breakpoint(openfile->current->data,
leftedge, &last_chunk);
size_t rightedge_x;
/* If we're on the last chunk, we're already at the end of the line.
* Otherwise, we're one column past the end of the line. Shifting
* backwards one column might put us in the middle of a multi-column
* character, but actual_x() will fix that. */
if (!last_chunk)
rightedge--;
/* If we're on the last chunk, we're already at the end of the line.
* Otherwise, we're one column past the end of the line. Shifting
* backwards one column might put us in the middle of a multi-column
* character, but actual_x() will fix that. */
if (!last_chunk)
rightedge--;
rightedge_x = actual_x(openfile->current->data, rightedge);
rightedge_x = actual_x(openfile->current->data, rightedge);
/* If already at the right edge of the screen, move fully to
* the end of the line. Otherwise, move to the right edge. */
if (openfile->current_x == rightedge_x)
openfile->current_x = line_len;
else {
openfile->current_x = rightedge_x;
openfile->placewewant = rightedge;
moved_off_chunk = FALSE;
}
} else
/* If already at the right edge of the screen, move fully to
* the end of the line. Otherwise, move to the right edge. */
if (openfile->current_x == rightedge_x)
openfile->current_x = line_len;
else {
openfile->current_x = rightedge_x;
openfile->placewewant = rightedge;
moved_off_chunk = FALSE;
}
} else
#endif
openfile->current_x = line_len;
openfile->current_x = line_len;
if (moved_off_chunk)
openfile->placewewant = xplustabs();
if (moved_off_chunk)
openfile->placewewant = xplustabs();
/* If we changed chunk, we might be offscreen. Otherwise,
* update current if the mark is on or we changed "page". */
if (ISSET(SOFTWRAP) && moved_off_chunk)
edit_redraw(was_current, FLOWING);
else if (line_needs_update(was_column, openfile->placewewant))
update_line(openfile->current, openfile->current_x);
/* If we changed chunk, we might be offscreen. Otherwise,
* update current if the mark is on or we changed "page". */
if (ISSET(SOFTWRAP) && moved_off_chunk)
edit_redraw(was_current, FLOWING);
else if (line_needs_update(was_column, openfile->placewewant))
update_line(openfile->current, openfile->current_x);
}
/* Move the cursor to the preceding line or chunk. If scroll_only is TRUE,
* also scroll the screen one row, so the cursor stays in the same spot. */
void do_up(bool scroll_only)
{
filestruct *was_current = openfile->current;
size_t leftedge, target_column;
filestruct *was_current = openfile->current;
size_t leftedge, target_column;
/* When just scrolling and the top of the file is onscreen, get out. */
if (scroll_only && openfile->edittop == openfile->fileage &&
openfile->firstcolumn == 0)
return;
/* When just scrolling and the top of the file is onscreen, get out. */
if (scroll_only && openfile->edittop == openfile->fileage &&
openfile->firstcolumn == 0)
return;
get_edge_and_target(&leftedge, &target_column);
get_edge_and_target(&leftedge, &target_column);
/* If we can't move up one line or chunk, we're at top of file. */
if (go_back_chunks(1, &openfile->current, &leftedge) > 0)
return;
/* If we can't move up one line or chunk, we're at top of file. */
if (go_back_chunks(1, &openfile->current, &leftedge) > 0)
return;
set_proper_index_and_pww(&leftedge, target_column, FALSE);
set_proper_index_and_pww(&leftedge, target_column, FALSE);
if (scroll_only)
edit_scroll(BACKWARD, 1);
if (scroll_only)
edit_scroll(BACKWARD, 1);
edit_redraw(was_current, FLOWING);
edit_redraw(was_current, FLOWING);
/* <Up> should not change placewewant, so restore it. */
openfile->placewewant = leftedge + target_column;
/* <Up> should not change placewewant, so restore it. */
openfile->placewewant = leftedge + target_column;
}
/* Move the cursor to next line or chunk. If scroll_only is TRUE, also
* scroll the screen one row, so the cursor stays in the same spot. */
void do_down(bool scroll_only)
{
filestruct *was_current = openfile->current;
size_t leftedge, target_column;
filestruct *was_current = openfile->current;
size_t leftedge, target_column;
get_edge_and_target(&leftedge, &target_column);
get_edge_and_target(&leftedge, &target_column);
/* If we can't move down one line or chunk, we're at bottom of file. */
if (go_forward_chunks(1, &openfile->current, &leftedge) > 0)
return;
/* If we can't move down one line or chunk, we're at bottom of file. */
if (go_forward_chunks(1, &openfile->current, &leftedge) > 0)
return;
set_proper_index_and_pww(&leftedge, target_column, TRUE);
set_proper_index_and_pww(&leftedge, target_column, TRUE);
if (scroll_only)
edit_scroll(FORWARD, 1);
if (scroll_only)
edit_scroll(FORWARD, 1);
edit_redraw(was_current, FLOWING);
edit_redraw(was_current, FLOWING);
/* <Down> should not change placewewant, so restore it. */
openfile->placewewant = leftedge + target_column;
/* <Down> should not change placewewant, so restore it. */
openfile->placewewant = leftedge + target_column;
}
/* Move up one line or chunk. */
void do_up_void(void)
{
do_up(FALSE);
do_up(FALSE);
}
/* Move down one line or chunk. */
void do_down_void(void)
{
do_down(FALSE);
do_down(FALSE);
}
#ifndef NANO_TINY
/* Scroll up one line or chunk without scrolling the cursor. */
void do_scroll_up(void)
{
do_up(TRUE);
do_up(TRUE);
}
/* Scroll down one line or chunk without scrolling the cursor. */
void do_scroll_down(void)
{
do_down(TRUE);
do_down(TRUE);
}
#endif
/* Move left one character. */
void do_left(void)
{
filestruct *was_current = openfile->current;
filestruct *was_current = openfile->current;
if (openfile->current_x > 0)
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->fileage) {
openfile->current = openfile->current->prev;
openfile->current_x = strlen(openfile->current->data);
}
if (openfile->current_x > 0)
openfile->current_x = move_mbleft(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->fileage) {
openfile->current = openfile->current->prev;
openfile->current_x = strlen(openfile->current->data);
}
edit_redraw(was_current, FLOWING);
edit_redraw(was_current, FLOWING);
}
/* Move right one character. */
void do_right(void)
{
filestruct *was_current = openfile->current;
filestruct *was_current = openfile->current;
if (openfile->current->data[openfile->current_x] != '\0')
openfile->current_x = move_mbright(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->filebot) {
openfile->current = openfile->current->next;
openfile->current_x = 0;
}
if (openfile->current->data[openfile->current_x] != '\0')
openfile->current_x = move_mbright(openfile->current->data,
openfile->current_x);
else if (openfile->current != openfile->filebot) {
openfile->current = openfile->current->next;
openfile->current_x = 0;
}
edit_redraw(was_current, FLOWING);
edit_redraw(was_current, FLOWING);
}

3265
src/nano.c

File diff suppressed because it is too large Load Diff

View File

@@ -111,7 +111,7 @@
#endif
#define gettext_noop(string) (string)
#define N_(string) gettext_noop(string)
/* Mark a string that will be sent to gettext() later. */
/* Mark a string that will be sent to gettext() later. */
#include <stddef.h>
#include <stdlib.h>
@@ -144,416 +144,415 @@
/* Enumeration types. */
typedef enum {
NIX_FILE, DOS_FILE, MAC_FILE
NIX_FILE, DOS_FILE, MAC_FILE
} file_format;
typedef enum {
HUSH, MILD, ALERT
HUSH, MILD, ALERT
} message_type;
typedef enum {
OVERWRITE, APPEND, PREPEND
OVERWRITE, APPEND, PREPEND
} kind_of_writing_type;
typedef enum {
SOFTMARK, HARDMARK
SOFTMARK, HARDMARK
} mark_type;
typedef enum {
CENTERING, FLOWING, STATIONARY
CENTERING, FLOWING, STATIONARY
} update_type;
typedef enum {
ADD, DEL, BACK, CUT, CUT_TO_EOF, REPLACE,
ADD, DEL, BACK, CUT, CUT_TO_EOF, REPLACE,
#ifdef ENABLE_WRAPPING
SPLIT_BEGIN, SPLIT_END,
SPLIT_BEGIN, SPLIT_END,
#endif
INDENT, UNINDENT,
INDENT, UNINDENT,
#ifdef ENABLE_COMMENT
COMMENT, UNCOMMENT, PREFLIGHT,
COMMENT, UNCOMMENT, PREFLIGHT,
#endif
JOIN, PASTE, INSERT, ENTER, OTHER
JOIN, PASTE, INSERT, ENTER, OTHER
} undo_type;
/* Structure types. */
#ifdef ENABLE_COLOR
typedef struct colortype {
short fg;
/* This syntax's foreground color. */
short bg;
/* This syntax's background color. */
bool bright;
/* Is this color A_BOLD? */
int pairnum;
/* The color pair number used for this foreground color and
* background color. */
int attributes;
/* Pair number and brightness composed into ready-to-use attributes. */
int rex_flags;
/* The regex compilation flags (with or without REG_ICASE). */
char *start_regex;
/* The start (or all) of the regex string. */
regex_t *start;
/* The compiled start (or all) of the regex string. */
char *end_regex;
/* The end (if any) of the regex string. */
regex_t *end;
/* The compiled end (if any) of the regex string. */
struct colortype *next;
/* Next set of colors. */
int id;
/* Basic id for assigning to lines later. */
short fg;
/* This syntax's foreground color. */
short bg;
/* This syntax's background color. */
bool bright;
/* Is this color A_BOLD? */
int pairnum;
/* The color pair number used for this foreground color and
* background color. */
int attributes;
/* Pair number and brightness composed into ready-to-use attributes. */
int rex_flags;
/* The regex compilation flags (with or without REG_ICASE). */
char *start_regex;
/* The start (or all) of the regex string. */
regex_t *start;
/* The compiled start (or all) of the regex string. */
char *end_regex;
/* The end (if any) of the regex string. */
regex_t *end;
/* The compiled end (if any) of the regex string. */
struct colortype *next;
/* Next set of colors. */
int id;
/* Basic id for assigning to lines later. */
} colortype;
typedef struct regexlisttype {
char *full_regex;
/* A regex string to match things that imply a certain syntax. */
struct regexlisttype *next;
/* The next regex. */
char *full_regex;
/* A regex string to match things that imply a certain syntax. */
struct regexlisttype *next;
/* The next regex. */
} regexlisttype;
typedef struct syntaxtype {
char *name;
/* The name of this syntax. */
regexlisttype *extensions;
/* The list of extensions that this syntax applies to. */
regexlisttype *headers;
/* The list of headerlines that this syntax applies to. */
regexlisttype *magics;
/* The list of libmagic results that this syntax applies to. */
char *linter;
/* The command with which to lint this type of file. */
char *formatter;
/* The formatting command (for programming languages mainly). */
char *name;
/* The name of this syntax. */
regexlisttype *extensions;
/* The list of extensions that this syntax applies to. */
regexlisttype *headers;
/* The list of headerlines that this syntax applies to. */
regexlisttype *magics;
/* The list of libmagic results that this syntax applies to. */
char *linter;
/* The command with which to lint this type of file. */
char *formatter;
/* The formatting command (for programming languages mainly). */
#ifdef ENABLE_COMMENT
char *comment;
/* The line comment prefix (and postfix) for this type of file. */
char *comment;
/* The line comment prefix (and postfix) for this type of file. */
#endif
colortype *color;
/* The colors and their regexes used in this syntax. */
int nmultis;
/* How many multiline regex strings this syntax has. */
struct syntaxtype *next;
/* Next syntax. */
colortype *color;
/* The colors and their regexes used in this syntax. */
int nmultis;
/* How many multiline regex strings this syntax has. */
struct syntaxtype *next;
/* Next syntax. */
} syntaxtype;
typedef struct lintstruct {
ssize_t lineno;
/* Line number of the error. */
ssize_t colno;
/* Column # of the error. */
char *msg;
/* Error message text. */
char *filename;
/* Filename. */
struct lintstruct *next;
/* Next error. */
struct lintstruct *prev;
/* Previous error. */
ssize_t lineno;
/* Line number of the error. */
ssize_t colno;
/* Column # of the error. */
char *msg;
/* Error message text. */
char *filename;
/* Filename. */
struct lintstruct *next;
/* Next error. */
struct lintstruct *prev;
/* Previous error. */
} lintstruct;
/* Flags that indicate how a multiline regex applies to a line. */
#define CNONE (1<<1)
/* Yay, regex doesn't apply to this line at all! */
#define CBEGINBEFORE (1<<2)
/* Regex starts on an earlier line, ends on this one. */
#define CENDAFTER (1<<3)
/* Regex starts on this line and ends on a later one. */
#define CWHOLELINE (1<<4)
/* 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. */
#define CNONE (1<<1)
/* Yay, regex doesn't apply to this line at all! */
#define CBEGINBEFORE (1<<2)
/* Regex starts on an earlier line, ends on this one. */
#define CENDAFTER (1<<3)
/* Regex starts on this line and ends on a later one. */
#define CWHOLELINE (1<<4)
/* 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 /* ENABLE_COLOR */
/* More structure types. */
typedef struct filestruct {
char *data;
/* The text of this line. */
ssize_t lineno;
/* The number of this line. */
struct filestruct *next;
/* Next node. */
struct filestruct *prev;
/* Previous node. */
char *data;
/* The text of this line. */
ssize_t lineno;
/* The number of this line. */
struct filestruct *next;
/* Next node. */
struct filestruct *prev;
/* Previous node. */
#ifdef ENABLE_COLOR
short *multidata;
/* Array of which multi-line regexes apply to this line. */
short *multidata;
/* Array of which multi-line regexes apply to this line. */
#endif
} filestruct;
typedef struct partition {
filestruct *fileage;
/* The top line of this portion of the file. */
filestruct *top_prev;
/* The line before the top line of this portion of the file. */
char *top_data;
/* The text before the beginning of the top line of this portion
* of the file. */
filestruct *filebot;
/* The bottom line of this portion of the file. */
filestruct *bot_next;
/* The line after the bottom line of this portion of the
* file. */
char *bot_data;
/* The text after the end of the bottom line of this portion of
* the file. */
filestruct *fileage;
/* The top line of this portion of the file. */
filestruct *top_prev;
/* The line before the top line of this portion of the file. */
char *top_data;
/* The text before the beginning of the top line of this portion
* of the file. */
filestruct *filebot;
/* The bottom line of this portion of the file. */
filestruct *bot_next;
/* The line after the bottom line of this portion of the
* file. */
char *bot_data;
/* The text after the end of the bottom line of this portion of
* the file. */
} partition;
#ifndef NANO_TINY
typedef struct undo_group {
ssize_t top_line;
/* First line of group. */
ssize_t bottom_line;
/* Last line of group. */
char **indentations;
/* String data used to restore the affected lines; one per line. */
struct undo_group *next;
ssize_t top_line;
/* First line of group. */
ssize_t bottom_line;
/* Last line of group. */
char **indentations;
/* String data used to restore the affected lines; one per line. */
struct undo_group *next;
} undo_group;
typedef struct undo {
ssize_t lineno;
undo_type type;
/* What type of undo this was. */
size_t begin;
/* Where did this action begin or end. */
char *strdata;
/* String type data we will use for copying the affected line back. */
size_t wassize;
/* The file size before the action. */
size_t newsize;
/* The file size after the action. */
int xflags;
/* Some flag data we need. */
undo_group *grouping;
/* Undo info specific to groups of lines. */
ssize_t lineno;
undo_type type;
/* What type of undo this was. */
size_t begin;
/* Where did this action begin or end. */
char *strdata;
/* String type data we will use for copying the affected line back. */
size_t wassize;
/* The file size before the action. */
size_t newsize;
/* The file size after the action. */
int xflags;
/* Some flag data we need. */
undo_group *grouping;
/* Undo info specific to groups of lines. */
/* Cut-specific stuff we need. */
filestruct *cutbuffer;
/* Copy of the cutbuffer. */
filestruct *cutbottom;
/* Copy of cutbottom. */
ssize_t mark_begin_lineno;
/* Mostly the line number of the current line; sometimes something else. */
size_t mark_begin_x;
/* The x position corresponding to the above line number. */
struct undo *next;
/* A pointer to the undo item of the preceding action. */
/* Cut-specific stuff we need. */
filestruct *cutbuffer;
/* Copy of the cutbuffer. */
filestruct *cutbottom;
/* Copy of cutbottom. */
ssize_t mark_begin_lineno;
/* Mostly the line number of the current line; sometimes something else. */
size_t mark_begin_x;
/* The x position corresponding to the above line number. */
struct undo *next;
/* A pointer to the undo item of the preceding action. */
} undo;
#endif /* !NANO_TINY */
#ifdef ENABLE_HISTORIES
typedef struct poshiststruct {
char *filename;
/* The file. */
ssize_t lineno;
/* Line number we left off on. */
ssize_t xno;
/* x position in the file we left off on. */
struct poshiststruct *next;
char *filename;
/* The file. */
ssize_t lineno;
/* Line number we left off on. */
ssize_t xno;
/* x position in the file we left off on. */
struct poshiststruct *next;
} poshiststruct;
#endif
typedef struct openfilestruct {
char *filename;
/* The file's name. */
filestruct *fileage;
/* The file's first line. */
filestruct *filebot;
/* The file's last line. */
filestruct *edittop;
/* The current top of the edit window for this file. */
filestruct *current;
/* The current line for this file. */
size_t totsize;
/* The file's total number of characters. */
size_t firstcolumn;
/* The starting column of the top line of the edit window.
* When not in softwrap mode, it's always zero. */
size_t current_x;
/* The file's x-coordinate position. */
size_t placewewant;
/* The file's x position we would like. */
ssize_t current_y;
/* The file's y-coordinate position. */
bool modified;
/* Whether the file has been modified. */
struct stat *current_stat;
/* The file's current stat information. */
char *filename;
/* The file's name. */
filestruct *fileage;
/* The file's first line. */
filestruct *filebot;
/* The file's last line. */
filestruct *edittop;
/* The current top of the edit window for this file. */
filestruct *current;
/* The current line for this file. */
size_t totsize;
/* The file's total number of characters. */
size_t firstcolumn;
/* The starting column of the top line of the edit window.
* When not in softwrap mode, it's always zero. */
size_t current_x;
/* The file's x-coordinate position. */
size_t placewewant;
/* The file's x position we would like. */
ssize_t current_y;
/* The file's y-coordinate position. */
bool modified;
/* Whether the file has been modified. */
struct stat *current_stat;
/* The file's current stat information. */
#ifndef NANO_TINY
filestruct *mark;
/* The line in the file where the mark is set; NULL if not set. */
size_t mark_x;
/* The mark's x position in the above line. */
mark_type kind_of_mark;
/* Whether it is a soft (with Shift) or a hard mark. */
file_format fmt;
/* The file's format -- Unix or DOS or Mac or mixed. */
undo *undotop;
/* The top of the undo list. */
undo *current_undo;
/* The current (i.e. next) level of undo. */
undo_type last_action;
/* The type of the last action the user performed. */
bool pristine;
/* Whether the undo stack still contains the first edit -- it won't
* when a justification or spell check discarded the undo stack. */
char *lock_filename;
/* The path of the lockfile, if we created one. */
filestruct *mark;
/* The line in the file where the mark is set; NULL if not set. */
size_t mark_x;
/* The mark's x position in the above line. */
mark_type kind_of_mark;
/* Whether it is a soft (with Shift) or a hard mark. */
file_format fmt;
/* The file's format -- Unix or DOS or Mac or mixed. */
undo *undotop;
/* The top of the undo list. */
undo *current_undo;
/* The current (i.e. next) level of undo. */
undo *last_saved;
/* The undo item at which the file was last saved. */
undo_type last_action;
/* The type of the last action the user performed. */
char *lock_filename;
/* The path of the lockfile, if we created one. */
#endif
#ifdef ENABLE_COLOR
syntaxtype *syntax;
/* The syntax struct for this file, if any. */
colortype *colorstrings;
/* The file's associated colors. */
syntaxtype *syntax;
/* The syntax struct for this file, if any. */
colortype *colorstrings;
/* The file's associated colors. */
#endif
struct openfilestruct *next;
/* The next open file, if any. */
struct openfilestruct *prev;
/* The preceding open file, if any. */
struct openfilestruct *next;
/* The next open file, if any. */
struct openfilestruct *prev;
/* The preceding open file, if any. */
} openfilestruct;
#ifdef ENABLE_NANORC
typedef struct rcoption {
const char *name;
/* The name of the rcfile option. */
long flag;
/* The flag associated with it, if any. */
const char *name;
/* The name of the rcfile option. */
long flag;
/* The flag associated with it, if any. */
} rcoption;
#endif
typedef struct sc {
const char *keystr;
/* The string that describes a keystroke, like "^C" or "M-R". */
bool meta;
/* Whether this is a Meta keystroke. */
int keycode;
/* The integer that, together with meta, identifies the keystroke. */
int menus;
/* Which menus this applies to. */
void (*scfunc)(void);
/* The function we're going to run. */
const char *keystr;
/* The string that describes a keystroke, like "^C" or "M-R". */
bool meta;
/* Whether this is a Meta keystroke. */
int keycode;
/* The integer that, together with meta, identifies the keystroke. */
int menus;
/* Which menus this applies to. */
void (*scfunc)(void);
/* The function we're going to run. */
#ifndef NANO_TINY
int toggle;
/* If a toggle, what we're toggling. */
int ordinal;
/* The how-manieth toggle this is, in order to be able to
* keep them in sequence. */
int toggle;
/* If a toggle, what we're toggling. */
int ordinal;
/* The how-manieth toggle this is, in order to be able to
* keep them in sequence. */
#endif
struct sc *next;
/* Next in the list. */
struct sc *next;
/* Next in the list. */
} sc;
typedef struct subnfunc {
void (*scfunc)(void);
/* The actual function to call. */
int menus;
/* In what menus this function applies. */
const char *desc;
/* The function's short description, for example "Where Is". */
void (*scfunc)(void);
/* The actual function to call. */
int menus;
/* In what menus this function applies. */
const char *desc;
/* The function's short description, for example "Where Is". */
#ifdef ENABLE_HELP
const char *help;
/* The help-screen text for this function. */
bool blank_after;
/* Whether there should be a blank line after the help text
* for this function. */
const char *help;
/* The help-screen text for this function. */
bool blank_after;
/* Whether there should be a blank line after the help text
* for this function. */
#endif
bool viewok;
/* Is this function allowed when in view mode? */
long toggle;
/* If this is a toggle, which toggle to affect. */
struct subnfunc *next;
/* Next item in the list. */
bool viewok;
/* Is this function allowed when in view mode? */
long toggle;
/* If this is a toggle, which toggle to affect. */
struct subnfunc *next;
/* Next item in the list. */
} subnfunc;
#ifdef ENABLE_WORDCOMPLETION
typedef struct completion_word {
char *word;
struct completion_word *next;
char *word;
struct completion_word *next;
} completion_word;
#endif
/* The elements of the interface that can be colored differently. */
enum
{
TITLE_BAR = 0,
LINE_NUMBER,
SELECTED_TEXT,
STATUS_BAR,
KEY_COMBO,
FUNCTION_TAG,
NUMBER_OF_ELEMENTS
TITLE_BAR = 0,
LINE_NUMBER,
SELECTED_TEXT,
STATUS_BAR,
KEY_COMBO,
FUNCTION_TAG,
NUMBER_OF_ELEMENTS
};
/* Enumeration used in the flags array. See the definition of FLAGMASK. */
enum
{
DONTUSE,
CASE_SENSITIVE,
CONSTANT_SHOW,
NO_HELP,
SUSPEND,
NO_WRAP,
AUTOINDENT,
VIEW_MODE,
USE_MOUSE,
USE_REGEXP,
TEMP_FILE,
CUT_FROM_CURSOR,
BACKWARDS_SEARCH,
MULTIBUFFER,
SMOOTH_SCROLL,
REBIND_DELETE,
REBIND_KEYPAD,
NO_CONVERT,
BACKUP_FILE,
INSECURE_BACKUP,
NO_COLOR_SYNTAX,
PRESERVE,
HISTORYLOG,
RESTRICTED,
SMART_HOME,
WHITESPACE_DISPLAY,
MORE_SPACE,
TABS_TO_SPACES,
QUICK_BLANK,
WORD_BOUNDS,
NO_NEWLINES,
BOLD_TEXT,
QUIET,
SOFTWRAP,
POS_HISTORY,
LOCKING,
NOREAD_MODE,
MAKE_IT_UNIX,
JUSTIFY_TRIM,
SHOW_CURSOR,
LINE_NUMBERS,
NO_PAUSES,
AT_BLANKS
DONTUSE,
CASE_SENSITIVE,
CONSTANT_SHOW,
NO_HELP,
SUSPEND,
NO_WRAP,
AUTOINDENT,
VIEW_MODE,
USE_MOUSE,
USE_REGEXP,
TEMP_FILE,
CUT_FROM_CURSOR,
BACKWARDS_SEARCH,
MULTIBUFFER,
SMOOTH_SCROLL,
REBIND_DELETE,
REBIND_KEYPAD,
NO_CONVERT,
BACKUP_FILE,
INSECURE_BACKUP,
NO_COLOR_SYNTAX,
PRESERVE,
HISTORYLOG,
RESTRICTED,
SMART_HOME,
WHITESPACE_DISPLAY,
MORE_SPACE,
TABS_TO_SPACES,
QUICK_BLANK,
WORD_BOUNDS,
NO_NEWLINES,
BOLD_TEXT,
QUIET,
SOFTWRAP,
POS_HISTORY,
LOCKING,
NOREAD_MODE,
MAKE_IT_UNIX,
TRIM_BLANKS,
SHOW_CURSOR,
LINE_NUMBERS,
NO_PAUSES,
AT_BLANKS
};
/* Flags for the menus in which a given function should be present. */
#define MMAIN (1<<0)
#define MWHEREIS (1<<1)
#define MREPLACE (1<<2)
#define MREPLACEWITH (1<<3)
#define MGOTOLINE (1<<4)
#define MWRITEFILE (1<<5)
#define MINSERTFILE (1<<6)
#define MEXTCMD (1<<7)
#define MHELP (1<<8)
#define MSPELL (1<<9)
#define MBROWSER (1<<10)
#define MWHEREISFILE (1<<11)
#define MGOTODIR (1<<12)
#define MYESNO (1<<13)
#define MLINTER (1<<14)
#define MFINDINHELP (1<<15)
#define MMAIN (1<<0)
#define MWHEREIS (1<<1)
#define MREPLACE (1<<2)
#define MREPLACEWITH (1<<3)
#define MGOTOLINE (1<<4)
#define MWRITEFILE (1<<5)
#define MINSERTFILE (1<<6)
#define MEXTCMD (1<<7)
#define MHELP (1<<8)
#define MSPELL (1<<9)
#define MBROWSER (1<<10)
#define MWHEREISFILE (1<<11)
#define MGOTODIR (1<<12)
#define MYESNO (1<<13)
#define MLINTER (1<<14)
#define MFINDINHELP (1<<15)
/* This is an abbreviation for all menus except Help and YesNo. */
#define MMOST (MMAIN|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MWRITEFILE|MINSERTFILE|\
MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MFINDINHELP|MSPELL|MLINTER)
MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MFINDINHELP|MSPELL|MLINTER)
#ifndef NANO_TINY
#define MSOME MMOST
#else
@@ -590,6 +589,7 @@ enum
#define SHIFT_END 0x456
#define SHIFT_PAGEUP 0x457
#define SHIFT_PAGEDOWN 0x458
#define SHIFT_TAB 0x45F
#ifdef USE_SLANG
#ifdef ENABLE_UTF8
@@ -605,11 +605,12 @@ enum
#define KEY_WINCH -2
/* Some extra flags for the undo function. */
#define WAS_FINAL_BACKSPACE (1<<1)
#define WAS_WHOLE_LINE (1<<2)
#define WAS_FINAL_BACKSPACE (1<<1)
#define WAS_WHOLE_LINE (1<<2)
#define WAS_FINAL_LINE (1<<3)
/* The flags for the mark need to be the highest. */
#define MARK_WAS_SET (1<<3)
#define WAS_MARKED_FORWARD (1<<4)
#define MARK_WAS_SET (1<<4)
#define WAS_MARKED_FORWARD (1<<5)
#endif /* !NANO_TINY */
/* The maximum number of entries displayed in the main shortcut list. */

File diff suppressed because it is too large Load Diff

View File

@@ -54,6 +54,8 @@ extern char *title;
extern bool more_than_one;
extern bool also_the_last;
extern int didfind;
extern int controlleft;
@@ -189,8 +191,8 @@ void browser_refresh(void);
void browser_select_dirname(const char *needle);
void do_filesearch(void);
void do_fileresearch(bool forwards);
void do_first_file(void);
void do_last_file(void);
void to_first_file(void);
void to_last_file(void);
char *strip_last_component(const char *path);
#endif
@@ -216,10 +218,8 @@ size_t move_mbright(const char *buf, size_t pos);
int mbstrcasecmp(const char *s1, const char *s2);
int mbstrncasecmp(const char *s1, const char *s2, size_t n);
char *mbstrcasestr(const char *haystack, const char *needle);
char *revstrstr(const char *haystack, const char *needle,
const char *index);
char *mbrevstrcasestr(const char *haystack, const char *needle,
const char *index);
char *revstrstr(const char *haystack, const char *needle, const char *index);
char *mbrevstrcasestr(const char *haystack, const char *needle, const char *index);
size_t mbstrlen(const char *s);
size_t mbstrnlen(const char *s, size_t maxlen);
#if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
@@ -266,12 +266,13 @@ void do_uncut_text(void);
/* Most functions in files.c. */
void initialize_buffer_text(void);
void set_modified(void);
bool open_buffer(const char *filename, bool undoable);
#ifdef ENABLE_SPELLER
void replace_buffer(const char *filename);
#ifndef NANO_TINY
void replace_marked_buffer(const char *filename, filestruct *top, size_t top_x,
filestruct *bot, size_t bot_x);
filestruct *bot, size_t bot_x);
#endif
#endif
void prepare_for_display(void);
@@ -281,7 +282,7 @@ void switch_to_next_buffer(void);
bool close_buffer(void);
#endif
void read_file(FILE *f, int fd, const char *filename, bool undoable,
bool checkwritable);
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);
@@ -298,10 +299,10 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi
#endif
int copy_file(FILE *inn, FILE *out, bool close_out);
bool write_file(const char *name, FILE *f_open, bool tmp,
kind_of_writing_type method, bool nonamechange);
kind_of_writing_type method, bool fullbuffer);
#ifndef NANO_TINY
bool write_marked_file(const char *name, FILE *f_open, bool tmp,
kind_of_writing_type method);
kind_of_writing_type method);
#endif
int do_writeout(bool exiting, bool withprompt);
void do_writeout_void(void);
@@ -312,7 +313,7 @@ int diralphasort(const void *va, const void *vb);
#endif
#ifdef ENABLE_TABCOMP
char *input_tab(char *buf, bool allow_files, size_t *place,
bool *lastwastab, void (*refresh_func)(void), bool *listed);
bool *lastwastab, void (*refresh_func)(void), bool *listed);
#endif
/* Some functions in global.c. */
@@ -367,8 +368,8 @@ bool has_old_position(const char *file, ssize_t *line, ssize_t *column);
#endif
/* Most functions in move.c. */
void do_first_line(void);
void do_last_line(void);
void to_first_line(void);
void to_last_line(void);
void do_page_up(void);
void do_page_down(void);
#ifdef ENABLE_JUSTIFY
@@ -405,10 +406,10 @@ filestruct *copy_filestruct(const filestruct *src);
void free_filestruct(filestruct *src);
void renumber(filestruct *fileptr);
partition *partition_filestruct(filestruct *top, size_t top_x,
filestruct *bot, size_t bot_x);
filestruct *bot, size_t bot_x);
void unpartition_filestruct(partition **p);
void extract_buffer(filestruct **file_top, filestruct **file_bot,
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x);
filestruct *top, size_t top_x, filestruct *bot, size_t bot_x);
void ingraft_buffer(filestruct *somebuffer);
void copy_from_buffer(filestruct *somebuffer);
openfilestruct *make_new_opennode(void);
@@ -450,8 +451,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls);
#ifdef ENABLE_MOUSE
int do_statusbar_mouse(void);
#endif
void do_statusbar_output(int *the_input, size_t input_len,
bool filtering);
void do_statusbar_output(int *the_input, size_t input_len, bool filtering);
void do_statusbar_home(void);
void do_statusbar_end(void);
void do_statusbar_left(void);
@@ -470,8 +470,8 @@ size_t get_statusbar_page_start(size_t start_col, size_t column);
void reinit_statusbar_x(void);
void update_the_statusbar(void);
int do_prompt(bool allow_tabs, bool allow_files,
int menu, const char *curranswer, filestruct **history_list,
void (*refresh_func)(void), const char *msg, ...);
int menu, const char *curranswer, filestruct **history_list,
void (*refresh_func)(void), const char *msg, ...);
int do_yesno_prompt(bool all, const char *msg);
/* Most functions in rcfile.c. */
@@ -488,7 +488,7 @@ void do_rcfiles(void);
void not_found_msg(const char *str);
void search_replace_abort(void);
int findnextstr(const char *needle, bool whole_word_only, int modus,
size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x);
size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x);
void do_search(void);
void do_search_forward(void);
void do_search_backward(void);
@@ -499,11 +499,11 @@ void do_findnext(void);
void do_research(void);
void go_looking(void);
ssize_t do_replace_loop(const char *needle, bool whole_word_only,
const filestruct *real_current, size_t *real_current_x);
const filestruct *real_current, size_t *real_current_x);
void do_replace(void);
void goto_line_posx(ssize_t line, size_t pos_x);
void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
bool interactive);
bool interactive);
void do_gotolinecolumn_void(void);
#ifndef NANO_TINY
void do_find_bracket(void);
@@ -592,7 +592,7 @@ const char *fixbounds(const char *r);
bool is_separate_word(size_t position, size_t length, const char *buf);
#endif
const char *strstrwrapper(const char *haystack, const char *needle,
const char *start);
const char *start);
void nperror(const char *s);
void *nmalloc(size_t howmuch);
void *nrealloc(void *ptr, size_t howmuch);
@@ -609,8 +609,9 @@ void new_magicline(void);
void remove_magicline(void);
#endif
#ifndef NANO_TINY
void mark_order(const filestruct **top, size_t *top_x, const filestruct
**bot, size_t *bot_x, bool *right_side_up);
void mark_order(const filestruct **top, size_t *top_x,
const filestruct **bot, size_t *bot_x, bool *right_side_up);
void get_range(const filestruct **top, const filestruct **bot);
#endif
size_t get_totsize(const filestruct *begin, const filestruct *end);
#ifndef NANO_TINY
@@ -618,7 +619,6 @@ filestruct *fsfromline(ssize_t lineno);
#endif
#ifdef DEBUG
void dump_filestruct(const filestruct *inptr);
void dump_filestruct_reverse(void);
#endif
/* Most functions in winio.c. */
@@ -642,11 +642,11 @@ const sc *get_shortcut(int *kbinput);
void blank_row(WINDOW *win, int y, int x, int n);
void blank_edit(void);
void blank_statusbar(void);
void wipe_statusbar(void);
void blank_bottombars(void);
void check_statusblank(void);
char *display_string(const char *buf, size_t column, size_t span, bool isdata);
void titlebar(const char *path);
extern void set_modified(void);
void statusbar(const char *msg);
void warn_and_shortly_pause(const char *msg);
void statusline(message_type importance, const char *msg, ...);
@@ -654,7 +654,7 @@ void bottombars(int menu);
void post_one_key(const char *keystroke, const char *tag, int width);
void place_the_cursor(void);
void edit_draw(filestruct *fileptr, const char *converted,
int line, size_t from_col);
int line, size_t from_col);
int update_line(filestruct *fileptr, size_t index);
#ifndef NANO_TINY
int update_softwrapped_line(filestruct *fileptr);
@@ -666,7 +666,7 @@ bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge);
void edit_scroll(bool direction, int nrows);
#ifndef NANO_TINY
size_t get_softwrap_breakpoint(const char *text, size_t leftedge,
bool *end_of_line);
bool *end_of_line);
size_t get_chunk_and_edge(size_t column, filestruct *line, size_t *leftedge);
size_t chunk_for(size_t column, filestruct *line);
size_t leftedge_for(size_t column, filestruct *line);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

5685
src/text.c

File diff suppressed because it is too large Load Diff

View File

@@ -32,79 +32,79 @@
* we fall back on the home directory of the effective user ID. */
void get_homedir(void)
{
if (homedir == NULL) {
const char *homenv = getenv("HOME");
if (homedir == NULL) {
const char *homenv = getenv("HOME");
#ifdef HAVE_PWD_H
/* When HOME isn't set, or when we're root, get the home directory
* from the password file instead. */
if (homenv == NULL || geteuid() == 0) {
const struct passwd *userage = getpwuid(geteuid());
/* When HOME isn't set, or when we're root, get the home directory
* from the password file instead. */
if (homenv == NULL || geteuid() == 0) {
const struct passwd *userage = getpwuid(geteuid());
if (userage != NULL)
homenv = userage->pw_dir;
}
if (userage != NULL)
homenv = userage->pw_dir;
}
#endif
/* Only set homedir if some home directory could be determined,
* otherwise keep homedir NULL. */
if (homenv != NULL && strcmp(homenv, "") != 0)
homedir = mallocstrcpy(NULL, homenv);
}
/* Only set homedir if some home directory could be determined,
* otherwise keep homedir NULL. */
if (homenv != NULL && strcmp(homenv, "") != 0)
homedir = mallocstrcpy(NULL, homenv);
}
}
/* Return the filename part of the given path. */
const char *tail(const char *path)
{
const char *slash = strrchr(path, '/');
const char *slash = strrchr(path, '/');
if (slash == NULL)
return path;
else
return ++slash;
if (slash == NULL)
return path;
else
return ++slash;
}
/* Return a copy of the two given strings, welded together. */
char *concatenate(const char *path, const char *name)
{
size_t pathlen = strlen(path);
char *joined = charalloc(pathlen + strlen(name) + 1);
size_t pathlen = strlen(path);
char *joined = charalloc(pathlen + strlen(name) + 1);
strcpy(joined, path);
strcpy(joined + pathlen, name);
strcpy(joined, path);
strcpy(joined + pathlen, name);
return joined;
return joined;
}
#ifdef ENABLE_LINENUMBERS
/* Return the number of digits that the given integer n takes up. */
int digits(ssize_t n)
{
if (n < 100000) {
if (n < 1000) {
if (n < 100)
return 2;
else
return 3;
if (n < 100000) {
if (n < 1000) {
if (n < 100)
return 2;
else
return 3;
} else {
if (n < 10000)
return 4;
else
return 5;
}
} else {
if (n < 10000)
return 4;
else
return 5;
if (n < 10000000) {
if (n < 1000000)
return 6;
else
return 7;
} else {
if (n < 100000000)
return 8;
else
return 9;
}
}
} else {
if (n < 10000000) {
if (n < 1000000)
return 6;
else
return 7;
} else {
if (n < 100000000)
return 8;
else
return 9;
}
}
}
#endif
@@ -112,98 +112,98 @@ int digits(ssize_t n)
* and return TRUE; otherwise, return FALSE. */
bool parse_num(const char *str, ssize_t *result)
{
char *first_error;
ssize_t value;
char *first_error;
ssize_t value;
/* The manual page for strtol() says this is required. */
errno = 0;
/* The manual page for strtol() says this is required. */
errno = 0;
value = (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 (errno == ERANGE || *str == '\0' || *first_error != '\0')
return FALSE;
*result = value;
*result = value;
return TRUE;
return TRUE;
}
/* Read two numbers, separated by a comma, from str, and store them in
* *line and *column. Return FALSE on error, and TRUE otherwise. */
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
{
bool retval;
char *firstpart;
const char *comma;
bool retval;
char *firstpart;
const char *comma;
while (*str == ' ')
str++;
while (*str == ' ')
str++;
comma = strpbrk(str, "m,. /;");
comma = strpbrk(str, "m,. /;");
if (comma == NULL)
return parse_num(str, line);
if (comma == NULL)
return parse_num(str, line);
retval = parse_num(comma + 1, column);
retval = parse_num(comma + 1, column);
if (comma == str)
return retval;
firstpart = mallocstrcpy(NULL, str);
firstpart[comma - str] = '\0';
retval = parse_num(firstpart, line) && retval;
free(firstpart);
if (comma == str)
return retval;
firstpart = mallocstrcpy(NULL, str);
firstpart[comma - str] = '\0';
retval = parse_num(firstpart, line) && retval;
free(firstpart);
return retval;
}
/* Reduce the memory allocation of a string to what is needed. */
void snuggly_fit(char **str)
{
if (*str != NULL)
*str = charealloc(*str, strlen(*str) + 1);
if (*str != NULL)
*str = charealloc(*str, strlen(*str) + 1);
}
/* Null a string at a certain index and align it. */
void null_at(char **data, size_t index)
{
*data = charealloc(*data, index + 1);
(*data)[index] = '\0';
*data = charealloc(*data, index + 1);
(*data)[index] = '\0';
}
/* For non-null-terminated lines. A line, by definition, shouldn't
* normally have newlines in it, so encode its nulls as newlines. */
void unsunder(char *str, size_t true_len)
{
for (; true_len > 0; true_len--, str++) {
if (*str == '\0')
*str = '\n';
}
for (; true_len > 0; true_len--, str++) {
if (*str == '\0')
*str = '\n';
}
}
/* For non-null-terminated lines. A line, by definition, shouldn't
* normally have newlines in it, so decode its newlines as nulls. */
void sunder(char *str)
{
for (; *str != '\0'; str++) {
if (*str == '\n')
*str = '\0';
}
for (; *str != '\0'; str++) {
if (*str == '\n')
*str = '\0';
}
}
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
/* Free the memory of the given array, which should contain len elements. */
void free_chararray(char **array, size_t len)
{
if (array == NULL)
return;
if (array == NULL)
return;
while (len > 0)
free(array[--len]);
while (len > 0)
free(array[--len]);
free(array);
free(array);
}
#endif
@@ -212,30 +212,30 @@ void free_chararray(char **array, size_t len)
const char *fixbounds(const char *r)
{
#ifndef GNU_WORDBOUNDS
int i, j = 0;
char *r2 = charalloc(strlen(r) * 5);
char *r3;
int i, j = 0;
char *r2 = charalloc(strlen(r) * 5);
char *r3;
for (i = 0; i < strlen(r); i++) {
if (r[i] != '\0' && r[i] == '\\' && (r[i + 1] == '>' || r[i + 1] == '<')) {
strcpy(&r2[j], "[[:");
r2[j + 3] = r[i + 1];
strcpy(&r2[j + 4], ":]]");
i++;
j += 6;
} else
r2[j] = r[i];
j++;
}
for (i = 0; i < strlen(r); i++) {
if (r[i] != '\0' && r[i] == '\\' && (r[i + 1] == '>' || r[i + 1] == '<')) {
strcpy(&r2[j], "[[:");
r2[j + 3] = r[i + 1];
strcpy(&r2[j + 4], ":]]");
i++;
j += 6;
} else
r2[j] = r[i];
j++;
}
r2[j] = '\0';
r3 = mallocstrcpy(NULL, r2);
free(r2);
r2[j] = '\0';
r3 = mallocstrcpy(NULL, r2);
free(r2);
return (const char *) r3;
return (const char *) r3;
#endif /* !GNU_WORDBOUNDS */
return r;
return r;
}
#ifdef ENABLE_SPELLER
@@ -243,18 +243,18 @@ const char *fixbounds(const char *r)
* a separate word? That is: is it not part of a longer word?*/
bool is_separate_word(size_t position, size_t length, const char *buf)
{
char before[MAXCHARLEN], after[MAXCHARLEN];
size_t word_end = position + length;
char before[MAXCHARLEN], after[MAXCHARLEN];
size_t word_end = position + length;
/* Get the characters before and after the word, if any. */
parse_mbchar(buf + move_mbleft(buf, position), before, NULL);
parse_mbchar(buf + word_end, after, NULL);
/* Get the characters before and after the word, if any. */
parse_mbchar(buf + move_mbleft(buf, position), before, NULL);
parse_mbchar(buf + word_end, after, NULL);
/* If the word starts at the beginning of the line OR the character before
* the word isn't a letter, and if the word ends at the end of the line OR
* the character after the word isn't a letter, we have a whole word. */
return ((position == 0 || !is_alpha_mbchar(before)) &&
(buf[word_end] == '\0' || !is_alpha_mbchar(after)));
/* If the word starts at the beginning of the line OR the character before
* the word isn't a letter, and if the word ends at the end of the line OR
* the character after the word isn't a letter, we have a whole word. */
return ((position == 0 || !is_alpha_mbchar(before)) &&
(buf[word_end] == '\0' || !is_alpha_mbchar(after)));
}
#endif /* ENABLE_SPELLER */
@@ -264,76 +264,76 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
* 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)
const char *start)
{
if (*needle == '\0') {
if (*needle == '\0') {
#ifndef NANO_TINY
statusline(ALERT, "Searching for nothing -- please report a bug");
statusline(ALERT, "Searching for nothing -- please report a bug");
#endif
return (char *)start;
}
if (ISSET(USE_REGEXP)) {
if (ISSET(BACKWARDS_SEARCH)) {
size_t last_find, ceiling, far_end;
size_t floor = 0, next_rung = 0;
/* The start of the search range, and the next start. */
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;
}
/* 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)
return NULL;
return haystack + regmatches[0].rm_so;
return (char *)start;
}
/* 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;
}
if (ISSET(CASE_SENSITIVE)) {
if (ISSET(BACKWARDS_SEARCH))
return revstrstr(haystack, needle, start);
else
return strstr(start, needle);
} else if (ISSET(BACKWARDS_SEARCH))
return mbrevstrcasestr(haystack, needle, start);
if (ISSET(USE_REGEXP)) {
if (ISSET(BACKWARDS_SEARCH)) {
size_t last_find, ceiling, far_end;
size_t floor = 0, next_rung = 0;
/* The start of the search range, and the next start. */
return mbstrcasestr(start, needle);
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;
}
/* 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)
return NULL;
return haystack + regmatches[0].rm_so;
}
/* 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;
}
if (ISSET(CASE_SENSITIVE)) {
if (ISSET(BACKWARDS_SEARCH))
return revstrstr(haystack, needle, start);
else
return strstr(start, needle);
} else if (ISSET(BACKWARDS_SEARCH))
return mbrevstrcasestr(haystack, needle, start);
return mbstrcasestr(start, needle);
}
/* This is a wrapper for the perror() function. The wrapper temporarily
@@ -342,64 +342,63 @@ const char *strstrwrapper(const char *haystack, const char *needle,
* nperror() causes the window to flicker once. */
void nperror(const char *s)
{
endwin();
perror(s);
doupdate();
endwin();
perror(s);
doupdate();
}
/* This is a wrapper for the malloc() function that properly handles
* things when we run out of memory. Thanks, BG, many people have been
* asking for this... */
* things when we run out of memory. */
void *nmalloc(size_t howmuch)
{
void *r = malloc(howmuch);
void *r = malloc(howmuch);
if (r == NULL && howmuch != 0)
die(_("nano is out of memory!"));
if (r == NULL && howmuch != 0)
die(_("nano is out of memory!"));
return r;
return r;
}
/* This is a wrapper for the realloc() function that properly handles
* things when we run out of memory. */
void *nrealloc(void *ptr, size_t howmuch)
{
void *r = realloc(ptr, howmuch);
void *r = realloc(ptr, howmuch);
if (r == NULL && howmuch != 0)
die(_("nano is out of memory!"));
if (r == NULL && howmuch != 0)
die(_("nano is out of memory!"));
return r;
return r;
}
/* Allocate and copy the first n characters of the given src string, after
* freeing the destination. Usage: "dest = mallocstrncpy(dest, src, n);". */
char *mallocstrncpy(char *dest, const char *src, size_t n)
{
if (src == NULL)
src = "";
if (src == NULL)
src = "";
if (src != dest)
free(dest);
if (src != dest)
free(dest);
dest = charalloc(n);
strncpy(dest, src, n);
dest = charalloc(n);
strncpy(dest, src, n);
return dest;
return dest;
}
/* Free the dest string and return a malloc'ed copy of src. Should be used as:
* "dest = mallocstrcpy(dest, src);". */
char *mallocstrcpy(char *dest, const char *src)
{
return mallocstrncpy(dest, src, (src == NULL) ? 1 : strlen(src) + 1);
return mallocstrncpy(dest, src, (src == NULL) ? 1 : strlen(src) + 1);
}
/* Free the string at dest and return the string at src. */
char *free_and_assign(char *dest, char *src)
{
free(dest);
return src;
free(dest);
return src;
}
/* When not in softwrap mode, nano scrolls horizontally within a line in
@@ -409,193 +408,199 @@ char *free_and_assign(char *dest, char *src)
* get_page_start(column) < COLS). */
size_t get_page_start(size_t column)
{
if (column < editwincols - 1 || ISSET(SOFTWRAP) || column == 0)
return 0;
else if (editwincols > 8)
return column - 7 - (column - 7) % (editwincols - 8);
else
return column - (editwincols - 2);
if (column < editwincols - 1 || ISSET(SOFTWRAP) || column == 0)
return 0;
else if (editwincols > 8)
return column - 7 - (column - 7) % (editwincols - 8);
else
return column - (editwincols - 2);
}
/* Return the placewewant associated with current_x, i.e. the zero-based
* column position of the cursor. */
size_t xplustabs(void)
{
return strnlenpt(openfile->current->data, openfile->current_x);
return strnlenpt(openfile->current->data, openfile->current_x);
}
/* Return the index in text of the character that (when displayed) will
* not overshoot the given column. */
size_t actual_x(const char *text, size_t column)
{
const char *start = text;
/* From where we start walking through the text. */
size_t width = 0;
/* The current accumulated span, in columns. */
const char *start = text;
/* From where we start walking through the text. */
size_t width = 0;
/* The current accumulated span, in columns. */
while (*text != '\0') {
int charlen = parse_mbchar(text, NULL, &width);
while (*text != '\0') {
int charlen = parse_mbchar(text, NULL, &width);
if (width > column)
break;
if (width > column)
break;
text += charlen;
}
text += charlen;
}
return (text - start);
return (text - start);
}
/* A strnlen() with tabs and multicolumn characters factored in:
* how many columns wide are the first maxlen bytes of text? */
size_t strnlenpt(const char *text, size_t maxlen)
{
size_t width = 0;
/* The screen display width to text[maxlen]. */
size_t width = 0;
/* The screen display width to text[maxlen]. */
if (maxlen == 0)
return 0;
if (maxlen == 0)
return 0;
while (*text != '\0') {
int charlen = parse_mbchar(text, NULL, &width);
while (*text != '\0') {
int charlen = parse_mbchar(text, NULL, &width);
if (maxlen <= charlen)
break;
if (maxlen <= charlen)
break;
maxlen -= charlen;
text += charlen;
}
maxlen -= charlen;
text += charlen;
}
return width;
return width;
}
/* Return the number of columns that the given text occupies. */
size_t strlenpt(const char *text)
{
size_t span = 0;
size_t span = 0;
while (*text != '\0')
text += parse_mbchar(text, NULL, &span);
while (*text != '\0')
text += parse_mbchar(text, NULL, &span);
return span;
return span;
}
/* Append a new magicline to filebot. */
/* Append a new magicline to the end of the buffer. */
void new_magicline(void)
{
openfile->filebot->next = make_new_node(openfile->filebot);
openfile->filebot->next->data = mallocstrcpy(NULL, "");
openfile->filebot = openfile->filebot->next;
openfile->totsize++;
openfile->filebot->next = make_new_node(openfile->filebot);
openfile->filebot->next->data = mallocstrcpy(NULL, "");
openfile->filebot = openfile->filebot->next;
openfile->totsize++;
}
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
/* Remove the magicline from filebot, if there is one and it isn't the
* only line in the file. Assume that edittop and current are not at
* filebot. */
/* Remove the magicline from the end of the buffer, if there is one and
* it isn't the only line in the file. */
void remove_magicline(void)
{
if (openfile->filebot->data[0] == '\0' &&
openfile->filebot != openfile->fileage) {
openfile->filebot = openfile->filebot->prev;
free_filestruct(openfile->filebot->next);
openfile->filebot->next = NULL;
openfile->totsize--;
}
if (openfile->filebot->data[0] == '\0' &&
openfile->filebot != openfile->fileage) {
openfile->filebot = openfile->filebot->prev;
free_filestruct(openfile->filebot->next);
openfile->filebot->next = NULL;
openfile->totsize--;
}
}
#endif
#ifndef NANO_TINY
/* Set top_x and bot_x to the top and bottom x-coordinates of the mark,
* respectively, based on the locations of top and bot. If
* right_side_up isn't NULL, set it to TRUE if the mark begins with
* (mark_begin, mark_begin_x) and ends with (current, current_x), or
* FALSE otherwise. */
void mark_order(const filestruct **top, size_t *top_x, const filestruct
**bot, size_t *bot_x, bool *right_side_up)
/* Set (top, top_x) and (bot, bot_x) to the start and end "coordinates" of
* the marked region. If right_side_up isn't NULL, set it to TRUE when the
* mark is at the top of the marked region, and to FALSE otherwise. */
void mark_order(const filestruct **top, size_t *top_x,
const filestruct **bot, size_t *bot_x, bool *right_side_up)
{
if ((openfile->current->lineno == openfile->mark->lineno &&
openfile->current_x > openfile->mark_x) ||
openfile->current->lineno > openfile->mark->lineno) {
*top = openfile->mark;
*top_x = openfile->mark_x;
*bot = openfile->current;
*bot_x = openfile->current_x;
if (right_side_up != NULL)
*right_side_up = TRUE;
} else {
*bot = openfile->mark;
*bot_x = openfile->mark_x;
*top = openfile->current;
*top_x = openfile->current_x;
if (right_side_up != NULL)
*right_side_up = FALSE;
}
if ((openfile->current->lineno == openfile->mark->lineno &&
openfile->current_x > openfile->mark_x) ||
openfile->current->lineno > openfile->mark->lineno) {
*top = openfile->mark;
*top_x = openfile->mark_x;
*bot = openfile->current;
*bot_x = openfile->current_x;
if (right_side_up != NULL)
*right_side_up = TRUE;
} else {
*bot = openfile->mark;
*bot_x = openfile->mark_x;
*top = openfile->current;
*top_x = openfile->current_x;
if (right_side_up != NULL)
*right_side_up = FALSE;
}
}
/* Get the set of lines to work on -- either just the current line, or the
* first to last lines of the marked region. When the cursor (or mark) is
* at the start of the last line of the region, exclude that line. */
void get_range(const filestruct **top, const filestruct **bot)
{
if (!openfile->mark) {
*top = openfile->current;
*bot = openfile->current;
} else {
size_t top_x, bot_x;
mark_order(top, &top_x, bot, &bot_x, NULL);
if (bot_x == 0 && *bot != *top && !also_the_last)
*bot = (*bot)->prev;
else
also_the_last = TRUE;
}
}
/* Given a line number, return a pointer to the corresponding struct. */
filestruct *fsfromline(ssize_t lineno)
{
filestruct *f = openfile->current;
filestruct *f = openfile->current;
if (lineno <= openfile->current->lineno)
while (f->lineno != lineno && f->prev != NULL)
f = f->prev;
else
while (f->lineno != lineno && f->next != NULL)
f = f->next;
if (lineno <= openfile->current->lineno)
while (f->lineno != lineno && f->prev != NULL)
f = f->prev;
else
while (f->lineno != lineno && f->next != NULL)
f = f->next;
if (f->lineno != lineno) {
statusline(ALERT, "Gone undo line -- please report a bug");
return NULL;
}
if (f->lineno != lineno) {
statusline(ALERT, "Gone undo line -- please report a bug");
return NULL;
}
return f;
return f;
}
#endif /* !NANO_TINY */
/* Count the number of characters from begin to end, and return it. */
size_t get_totsize(const filestruct *begin, const filestruct *end)
{
const filestruct *line;
size_t totsize = 0;
const filestruct *line;
size_t totsize = 0;
/* Sum the number of characters (plus a newline) in each line. */
for (line = begin; line != end->next; line = line->next)
totsize += mbstrlen(line->data) + 1;
/* Sum the number of characters (plus a newline) in each line. */
for (line = begin; line != end->next; line = line->next)
totsize += mbstrlen(line->data) + 1;
/* The last line of a file doesn't have a newline -- otherwise it
* wouldn't be the last line -- so subtract 1 when at EOF. */
if (line == NULL)
totsize--;
/* The last line of a file doesn't have a newline -- otherwise it
* wouldn't be the last line -- so subtract 1 when at EOF. */
if (line == NULL)
totsize--;
return totsize;
return totsize;
}
#ifdef DEBUG
/* Dump the given buffer to stderr. */
void dump_filestruct(const filestruct *inptr)
{
if (inptr == openfile->fileage)
fprintf(stderr, "Dumping file buffer to stderr...\n");
else if (inptr == cutbuffer)
fprintf(stderr, "Dumping cutbuffer to stderr...\n");
else
fprintf(stderr, "Dumping a buffer to stderr...\n");
if (inptr == openfile->fileage)
fprintf(stderr, "Dumping file buffer to stderr...\n");
else if (inptr == cutbuffer)
fprintf(stderr, "Dumping cutbuffer to stderr...\n");
else
fprintf(stderr, "Dumping a buffer to stderr...\n");
while (inptr != NULL) {
fprintf(stderr, "(%zd) %s\n", inptr->lineno, inptr->data);
inptr = inptr->next;
}
}
/* Dump the current buffer to stderr in reverse. */
void dump_filestruct_reverse(void)
{
const filestruct *fileptr = openfile->filebot;
while (fileptr != NULL) {
fprintf(stderr, "(%zd) %s\n", fileptr->lineno, fileptr->data);
fileptr = fileptr->prev;
}
while (inptr != NULL) {
fprintf(stderr, "(%zd) %s\n", inptr->lineno, inptr->data);
inptr = inptr->next;
}
}
#endif /* DEBUG */

File diff suppressed because it is too large Load Diff

View File

@@ -33,7 +33,7 @@ color brightblue "//.*"
color brightblue start="/\*" end="\*/"
# Reminders.
color ,yellow "\<(FIXME|TODO|XXX)\>"
color brightwhite,yellow "\<(FIXME|TODO|XXX)\>"
# Trailing whitespace.
color ,green "[[:space:]]+$"

View File

@@ -6,11 +6,11 @@ comment "#"
icolor green "^[[:space:]]*[A-Z0-9_]+"
icolor brightyellow "^[[:space:]]*(include|include_directories|include_external_msproject)\>"
icolor brightgreen "^[[:space:]]*\<((else|end)?if|else|(end)?while|(end)?foreach|break)\>"
color brightgreen "\<(NOT|COMMAND|POLICY|TARGET|EXISTS|IS_(DIRECTORY|ABSOLUTE)|DEFINED)\>[[:space:]]"
color brightgreen "[[:space:]]\<(OR|AND|IS_NEWER_THAN|MATCHES|(STR|VERSION_)?(LESS|GREATER|EQUAL))\>[[:space:]]"
icolor brightgreen "^[[:space:]]*((else|end)?if|else|(end)?while|(end)?foreach|break)\>"
color brightgreen "\<(NOT|COMMAND|POLICY|TARGET|EXISTS|IS_(DIRECTORY|ABSOLUTE)|DEFINED)[[:space:]]"
color brightgreen "[[:space:]](OR|AND|IS_NEWER_THAN|MATCHES|(STR|VERSION_)?(LESS|GREATER|EQUAL))[[:space:]]"
icolor brightred "^[[:space:]]*\<((end)?(function|macro)|return)"
icolor brightred "^[[:space:]]*((end)?(function|macro)|return)"
icolor cyan start="\$(\{|ENV\{)" end="\}"
color magenta "\<(APPLE|UNIX|WIN32|CYGWIN|BORLAND|MINGW|MSVC(_IDE|60|71|80|90)?)\>"

View File

@@ -24,7 +24,7 @@ color red "\<EBUILD_PHASE(_FUNC)?\>"
color red "\<QA_((TEXTRELS|EXECSTACK|WX_LOAD)(_[a-zA-Z_0-9]+)?|DT_HASH|PRESTRIPPED)\>"
color red "\<(PATCHES|(HTML_)?DOCS)\>" "\<WANT_(AUTO(CONF|MAKE)|LIBTOOL)\>" "\<AT_M4DIR\>"
## Portage commands:
color magenta "\<(use(_(with|enable|if_iuse)|x)?|in_iuse)\> [!a-zA-Z0-9_+ -]*" "inherit.*"
color magenta "\<(use(_(with|enable|if_iuse)|x)?|in_iuse) [!a-zA-Z0-9_+ -]*" "inherit.*"
color brightblue "\<e(begin|end|conf|install|make|qmake4|ant|(qa)?warn|infon?|error|log|patch(_user)?|new(group|user))\>"
color brightblue "\<e(pause|beep|mktemp|(cvs|svn)_clean|punt_cxx)\>" "\<e(aclocal|auto(reconf|header|conf|make)|libtoolize)\>"
color brightblue "\<e(stack|shopts|umask)_(push|pop)\>" "\<version_is_at_least\>"

View File

@@ -24,13 +24,9 @@ color brightcyan "\<(package|import)\>"
color brightcyan "//[[:space:]]*\+build[[:space:]]+(([a-zA-Z_0-9]+[[:space:]]*)+,[[:space:]]*)*[a-zA-Z_0-9]+"
# Literals.
color red "\<[0-9]+\.[0-9]*([Ee][+-][0-9]+)?i?\>"
color red "\<[0-9]+[Ee][+-][0-9]+i?\>"
color red "\<\.[0-9]+([Ee][+-][0-9]+)?i?\>"
color red "\<[0-9]+i\>"
color red "\<[1-9][0-9]*\>"
color red "\<0[0-7]*\>"
icolor red "\<0x[0-9a-f]+\>"
color red "\<[0-9]+(\.[0-9]*)?([Ee][+-]?[0-9]+)?i?\>"
color red "\B\.[0-9]+([Ee][+-]?[0-9]+)?i?\>"
color red "\<(0[0-7]*|[1-9][0-9]*|0[xX][0-9a-fA-F]+)\>"
# Strings and characters; slightly fuzzy.
color red "\<(true|false|nil|iota|_)\>"

View File

@@ -1,19 +1,23 @@
## Here is an example for Javascript.
## Syntax highlighting for Javascript.
syntax "javascript" "\.js$"
comment "//"
color brightred "\<[A-Z_][0-9A-Z_]+\>"
color green "\<(const|function|let|this|typeof|var|void)\>"
color brightyellow "\<(for|if|while|with|do|else|case|default|switch)\>"
color brightyellow "\<(export|try|throw|catch|new|delete)\>"
color magenta "\<(continue|break|return|yield)\>"
color brightmagenta "'([^'\]|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
# Declarational stuff.
color green "\<(async|class|const|extends|function|let|this|typeof|var|void)\>"
# Flow control and special keywords.
color brightyellow "\<(do|while|if|else|switch|case|default|for|each|in|of|with)\>"
color brightyellow "\<(await|export|import|throw|try|catch|finally|new|delete)\>"
# "Exit" points.
color magenta "\<(break|continue|return|yield)\>"
# Octal/decimal and hexadecimal numbers.
color cyan "\<[0-9]+\>" "\<0x[0-9A-Fa-f]+\>"
# Strings.
color brightyellow "<[^= ]*>" ""(\\.|[^"])*"" "'(\\.|[^'])*'"
color brightmagenta ""(\\.|[^"])*"" "'(\\.|[^'])*'" "`(\\.|[^`])*`"
# Comments.
color brightblue "//.*"
color brightblue "(^|[[:space:]])//.*"
color brightblue start="/\*" end="\*/"
# Trailing whitespace.

View File

@@ -1,8 +1,7 @@
## Syntax highlighting for Lua.
#
## Author: Matthew Wild <mwild1 (at) gmail.com>
## Original author: Matthew Wild <mwild1 (at) gmail.com>
## License: GPL 3 or later
## Version: 2011-05-05
syntax "lua" "\.lua$"
magic "Lua script"
@@ -17,48 +16,42 @@ color brightyellow ":|\*|/|%|\+|-|\^|>|>=|<|<=|~=|=|\.\.|\<(not|and|or)\>"
color brightblue "\<(do|end|while|repeat|until|if|elseif|then|else|for|in|function|local|return|break)\>"
# Keywords
color brightyellow "\<(io|math|os|string|table|coroutine|debug)\>\."
color brightyellow "\<(_G|_VERSION|assert|collectgarbage|dofile|error|getfenv|getmetatable|ipairs|load|loadfile|module|next|pairs|pcall|print|rawequal|rawget|rawset|require|select|setfenv|setmetatable|tonumber|tostring|type|unpack|xpcall)\s*\("
color brightyellow "\<(_G|_VERSION|assert|collectgarbage|dofile|error|getfenv|getmetatable|ipairs|load|loadfile|module|next|pairs|pcall|print|rawequal|rawget|rawlen|rawset|require|select|setfenv|setmetatable|tonumber|tostring|type|unpack|xpcall)\s*\("
# Standard library
color brightyellow "io\.\<(close|flush|input|lines|open|output|popen|read|tmpfile|type|write|stdin|stdout|stderr)\>"
color brightyellow "math\.\<(abs|acos|asin|atan2|atan|ceil|cosh|cos|deg|exp|floor|fmod|frexp|huge|ldexp|log10|log)\>"
color brightyellow "math\.\<(max|min|mod|modf|pi|pow|rad|random|randomseed|sinh|tan)\>"
color brightyellow "os\.\<(clock|date|difftime|execute|exit|getenv|remove|rename|setlocale|time|tmpname)\>"
color brightyellow "package\.\<(cpath|loaded|loadlib|path|preload|seeall)\>"
color brightyellow "string\.\<(byte|char|dump|find|format|gmatch|gsub|len|lower|match|rep|reverse|sub|upper)\>"
color brightyellow "table\.\<(concat|insert|maxn|remove|sort)\>"
color brightyellow "coroutine\.\<(create|resume|running|status|wrap|yield)\>"
color brightyellow "debug\.\<(debug|getfenv|gethook|getinfo|getlocal|getmetatable|getregistry|getupvalue)\>"
color brightyellow "debug\.\<(setfenv|sethook|setlocal|setmetatable|setupvalue|traceback)\>"
color brightyellow "\<coroutine\.(create|isyieldable|resume|running|status|wrap|yield)\>"
color brightyellow "\<debug\.(debug|(get|set)(fenv|hook|info|local|metatable|(up|user)value)|getregistry|traceback|upvalue(id|join))\>"
color brightyellow "\<io\.(close|flush|input|lines|output|p?open|read|tmpfile|type|write|std(in|out|err))\>"
color brightyellow "\<math\.(abs|acos|asin|atan2?|ceil|cosh?|deg|exp|floor|fmod|frexp|huge|ldexp|log10|log)\>"
color brightyellow "\<math\.((max|min)(integer)?|modf?|pi|pow|rad|random(seed)?|sinh?|sqrt|tan|tointeger|type|ult)\>"
color brightyellow "\<os\.(clock|date|difftime|execute|exit|getenv|remove|rename|setlocale|time|tmpname)\>"
color brightyellow "\<package\.(config|cpath|loaded|loadlib|path|preload|searchers|searchpath|seeall)\>"
color brightyellow "\<string\.(byte|char|dump|find|format|gmatch|gsub|len|lower|match|pack|packsize|rep|reverse|sub|unpack|upper)\>"
color brightyellow "\<table\.(concat|insert|maxn|move|pack|remove|sort|unpack)\>"
color brightyellow "\<utf8\.(char|charpattern|codepoint|codes|len|offset)\>"
# File handle methods
color brightyellow "\:\<(close|flush|lines|read|seek|setvbuf|write)\>"
# false, nil, true
color brightmagenta "\<(false|nil|true)\>"
color brightyellow ":(close|flush|lines|read|seek|setvbuf|write)\>"
# External files
color brightgreen "\<(dofile|require)\>"
# Numbers
color red "\<([0-9]+)\>"
# Special words
color brightmagenta "\<(false|nil|true)\>"
# Symbols
color brightmagenta "(\(|\)|\[|\]|\{|\})"
# Decimal and hexadecimal numbers
color red "\<[0-9]+(\.[0-9]*)?([Ee][+-]?[0-9]+)?\>"
icolor red "\<0x[0-9a-f]+(\.[0-9a-f]*)?(p[+-]?[0-9]+)?\>"
# Brackets
color brightmagenta "\(|\)|\[|\]|\{|\}"
# Shebang
color brightcyan "^#!.*"
color brightcyan "^#!.*"
# Simple comments
color green "\-\-.*$"
# Multiline comments
color green start="\-\-\[\[" end="\]\]"
# Simple comments and multiline comments
color green "--.*"
color green start="--\[\[" end="\]\]"
# Strings
color red "\"(\\.|[^\\\"])*\"|'(\\.|[^\\'])*'"
##color red start="\[\[" end="\]\]"
# Hex literals
color red "0x[0-9a-fA-F]*"
color red ""(\\.|[^"\])*"|'(\\.|[^'\])*'"

View File

@@ -7,7 +7,7 @@ comment "#"
icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|i?color|extendsyntax).*$"
# Keywords
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cutfromcursor|fill[[:space:]]+-?[[:digit:]]+|historylog|justifytrim|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[1-9][0-9]*|tabstospaces|tempfile|unix|view|wordbounds)\>"
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cutfromcursor|fill[[:space:]]+-?[[:digit:]]+|historylog|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[1-9][0-9]*|tabstospaces|tempfile|trimblanks|unix|view|wordbounds)\>"
icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|selected|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>"
icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|selectedcolor|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+"
icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
@@ -16,12 +16,13 @@ icolor brightgreen "^[[:space:]]*extendsyntax[[:space:]]+[[:alpha:]]+[[:space:]]
icolor brightgreen "^[[:space:]]*(linter|formatter)[[:space:]]+[[:alpha:]]+"
icolor green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|extendsyntax)\>"
# Strings
color brightmagenta "".+"([[:space:]]|$)"
# Colors
icolor yellow "^[[:space:]]*i?color[[:space:]]*(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>"
icolor magenta "^[[:space:]]*i?color\>" "\<(start|end)="
# Strings
color brightmagenta ""(\\.|[^"])*""
# Comments
color brightblue "(^|[[:space:]]+)#.*$"
color cyan "^[[:space:]]*##.*$"

View File

@@ -12,7 +12,7 @@ color green "\<(class|namespace|template|public|protected|private|typename|this|
color brightgreen "\<(for|if|while|do|else|case|default|switch)\>"
color brightgreen "\<(try|throw|catch|operator|new|delete)\>"
color brightgreen "\<(goto|continue|break|return)\>"
color brightgreen "@\<(en(code|d)|i(mplementation|nterface)|selector)\>"
color brightgreen "@(encode|end|implementation|interface)|selector)\>"
# GCC builtins.
color cyan "__attribute__[[:space:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"

View File

@@ -8,18 +8,18 @@ comment "//"
color brightgreen "(<\?(php)?|\?>)"
# Function names.
color white "\<[a-z_]*\("
color white "\<[A-Za-z_][A-Za-z_0-9]*\("
# Variable names.
color cyan "\$[a-z_]+"
color cyan "\$[A-Za-z_][A-Za-z_0-9]*"
# Types.
color green "\<(array|bool|callable|const|float|global|int|object|string|var)\>"
# Directives and structure.
color brightyellow "\<(abstract|as|class|clone|(end)?declare|extends|function|implements|include(_once)?|inst(ance|ead)of|interface|namespace|new|private|protected|public|require(_once)?|static|trait|use|yield)\>"
color brightyellow "\<(case|catch|default|do|echo|else(if)?|end(for(each)?|if|switch|while)|final(ly)?|for(each)?|if|print|switch|throw|try|while)\>"
color brightcyan "\<(abstract|as|class|clone|(end)?declare|extends|function|implements|include(_once)?|inst(ance|ead)of|interface|namespace|new|private|protected|public|require(_once)?|static|trait|use|yield)\>"
color brightcyan "\<(case|catch|default|do|echo|else(if)?|end(for(each)?|if|switch|while)|final(ly)?|for(each)?|if|print|switch|throw|try|while)\>"
# Operators.
color brightyellow "\<(and|or|xor)\>"
color brightcyan "\<(and|or|xor)\>"
# Control flow.
color magenta "\<(break|continue|goto|return)\>"

View File

@@ -11,7 +11,7 @@ color brightred "^\"X-Bugs:.*\"$"
color brightmagenta "\<(Project\-Id\-Version|Report\-Msgid\-Bugs\-To|Last\-Translator|Language(\-Team)?|X-Bugs|X-Generator|Plural\-Forms)\>"
color cyan "\<(POT\-Creation\-Date|PO\-Revision\-Date|MIME\-Version|Content\-Type|Content\-Transfer\-Encoding)\>"
# Encodings and numbers.
color yellow "\<(UTF|ISO|Windows|Mac|IBM)\>\-[0-9]"
color yellow "\<(UTF|ISO|Windows|Mac|IBM)-[0-9]+"
color yellow "[0-9]|pre[0-9]|[0-9]bit"
# Msgids.
color brightblue "^(msgid|msgid_plural|msgstr)\>"
@@ -24,6 +24,6 @@ color brightmagenta "%([1-9]\$)?[a-z]*"
color yellow "\""
color cyan "\\n"
# Reminders.
color ,yellow "(FIXME|TODO|XXX)"
color brightwhite,yellow "(FIXME|TODO|XXX)"
# Obsolete strings.
color red "#~.*$"

View File

@@ -7,9 +7,7 @@ color brightcyan "^[[:space:]]*#[[:space:]]*(declare)"
color brightyellow "\<(sphere|cylinder|translate|matrix|rotate|scale)\>"
color brightyellow "\<(orthographic|location|up|right|direction|clipped_by)\>"
color brightyellow "\<(fog_type|fog_offset|fog_alt|rgb|distance|transform)\>"
color brightred "^\<(texture)\>"
color brightred "\<(light_source|background)\>"
color brightred "\<(fog|object|camera)\>"
color brightred "\<(background|camera|fog|light_source|object|texture)\>"
color green "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)"
color brightmagenta "\<(union|group|subgroup)\>"

View File

@@ -9,8 +9,10 @@ comment "#"
# Function definitions.
icolor brightblue "def [0-9A-Z_]+"
# Keywords.
color brightcyan "\<(and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from)\>"
color brightcyan "\<(global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield)\>"
color brightcyan "\<(and|as|assert|async|await|break|class|continue)\>"
color brightcyan "\<(def|del|elif|else|except|exec|finally|for|from)\>"
color brightcyan "\<(global|if|import|in|is|lambda|nonlocal|not|or)\>"
color brightcyan "\<(pass|print|raise|return|try|while|with|yield)\>"
# Single-quoted strings.
color brightgreen "'([^'\]|\\.)+'"
@@ -21,8 +23,11 @@ color brightred "(^|[[:blank:]])#.*$"
color brightgreen start="'''([^'),]|$)" end="(^|[^(\])'''"
color brightgreen start="\"\"\"([^"),]|$)" end="(^|[^(\])\"\"\""
# Special values.
color brightmagenta "\<(False|None|True)\>"
# Reminders.
color ,yellow "(FIXME|TODO|XXX)"
color brightwhite,yellow "(FIXME|TODO|XXX)"
# Trailing whitespace.
color ,green "[[:space:]]+$"