Compare commits
215 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7b1f0f03f | ||
|
|
c782b4cb72 | ||
|
|
5234475781 | ||
|
|
80605c3918 | ||
|
|
d3012be095 | ||
|
|
03bc19fd0c | ||
|
|
e4cef3086b | ||
|
|
9936a6357a | ||
|
|
899bf0ae3a | ||
|
|
1f7384ebd2 | ||
|
|
95fffa99aa | ||
|
|
22f7861694 | ||
|
|
ba96d507dd | ||
|
|
9bf57e5ca0 | ||
|
|
f9103a5cb5 | ||
|
|
e9eabdcdcb | ||
|
|
a1be8b6a19 | ||
|
|
de4fbadf20 | ||
|
|
bdd8920081 | ||
|
|
ae9ec6d4ad | ||
|
|
8f1a657a37 | ||
|
|
7f88eff96f | ||
|
|
3b8c898880 | ||
|
|
6f4f1878fc | ||
|
|
082e5db4b7 | ||
|
|
5eccaa7633 | ||
|
|
d9ac785a07 | ||
|
|
01457ae3d3 | ||
|
|
c757aee235 | ||
|
|
48749a9500 | ||
|
|
4cd3987791 | ||
|
|
aa41eb69c0 | ||
|
|
54103d8ed1 | ||
|
|
53a10ddcaf | ||
|
|
65bf04060b | ||
|
|
a95fb64dd6 | ||
|
|
b235404ade | ||
|
|
ffebd31cbb | ||
|
|
e55227f65f | ||
|
|
b77b54bf73 | ||
|
|
2428620b16 | ||
|
|
cb0289f0dc | ||
|
|
b027263a37 | ||
|
|
1a926d79c5 | ||
|
|
c79fe1a160 | ||
|
|
fef195bce9 | ||
|
|
dd9766c2e0 | ||
|
|
5b870a7632 | ||
|
|
0cf455bc48 | ||
|
|
3e1fc6385b | ||
|
|
544cda6a62 | ||
|
|
28933cf572 | ||
|
|
1635060ba6 | ||
|
|
7a038adfd4 | ||
|
|
f1b5be4bbf | ||
|
|
9ceeabda38 | ||
|
|
204e1b8353 | ||
|
|
d865d7ac8f | ||
|
|
16d237ba1b | ||
|
|
c3031b9b8f | ||
|
|
d289510724 | ||
|
|
60f1090da0 | ||
|
|
8f6ee22b41 | ||
|
|
a083d7f1e1 | ||
|
|
919df09ffa | ||
|
|
ddbff6dcb2 | ||
|
|
4295baa5fe | ||
|
|
467cc8edf3 | ||
|
|
6d111c9343 | ||
|
|
bb667beb5a | ||
|
|
eed765f4f7 | ||
|
|
361267cf25 | ||
|
|
ed493bb99b | ||
|
|
ae7366616f | ||
|
|
58ed3a8152 | ||
|
|
e11021a7a5 | ||
|
|
83c264939b | ||
|
|
d48f3e5e7b | ||
|
|
b18e76d4d8 | ||
|
|
f5c87a7fee | ||
|
|
90ebff00ca | ||
|
|
cdc9a29598 | ||
|
|
ddc1de1939 | ||
|
|
18bf2af9c1 | ||
|
|
452008c81d | ||
|
|
97cbbb0cc8 | ||
|
|
7b9bd65362 | ||
|
|
f72fecee9b | ||
|
|
97a8a62128 | ||
|
|
f095e20a86 | ||
|
|
fa7e9b11df | ||
|
|
838b175d4f | ||
|
|
ba1f990582 | ||
|
|
6795d079b1 | ||
|
|
e739448cd0 | ||
|
|
8e328e43c2 | ||
|
|
cb56a575fd | ||
|
|
a429dc4a76 | ||
|
|
91073be49c | ||
|
|
d5f9be7dc8 | ||
|
|
4ad0490ce4 | ||
|
|
d85098abda | ||
|
|
13f8ddcaf2 | ||
|
|
37e9ada964 | ||
|
|
a99158c7c0 | ||
|
|
3981217e5a | ||
|
|
96b47f2877 | ||
|
|
7da391beb7 | ||
|
|
90cf4838d2 | ||
|
|
4c7ec18a55 | ||
|
|
704a7d7b4f | ||
|
|
64366d9992 | ||
|
|
bd97ae7255 | ||
|
|
2ff398c685 | ||
|
|
4b24ce1c11 | ||
|
|
00c1105c1b | ||
|
|
6a4d88cb4c | ||
|
|
898c4c6fbb | ||
|
|
c1bb6485de | ||
|
|
4bcce96a4f | ||
|
|
caeed6821c | ||
|
|
eb1bf8f927 | ||
|
|
2c8b99d5e9 | ||
|
|
091dd71f08 | ||
|
|
837475519b | ||
|
|
31540e3e7e | ||
|
|
ae3b8579fa | ||
|
|
e1199cd94d | ||
|
|
45d2458b47 | ||
|
|
4c505e5127 | ||
|
|
e3b13ae124 | ||
|
|
e5440b390e | ||
|
|
2a17527381 | ||
|
|
8067efa6cc | ||
|
|
0bb6c0234f | ||
|
|
7947d9d2a5 | ||
|
|
c9ccb39752 | ||
|
|
ada78dc89d | ||
|
|
c6f367268b | ||
|
|
084dda3837 | ||
|
|
30f367e0db | ||
|
|
5965e80a38 | ||
|
|
a794c3318b | ||
|
|
d04b0c123e | ||
|
|
21cd953e85 | ||
|
|
058b9da9b9 | ||
|
|
38a10a62d0 | ||
|
|
091e8faf6d | ||
|
|
d8ea89f6a6 | ||
|
|
1f48ed0412 | ||
|
|
b18bcbbe9f | ||
|
|
920730f1aa | ||
|
|
9506b51101 | ||
|
|
918d0e71ab | ||
|
|
484a199175 | ||
|
|
17429d7f38 | ||
|
|
87206c0607 | ||
|
|
b574f73e60 | ||
|
|
eac90c3eff | ||
|
|
440a128d25 | ||
|
|
4f2b01c7e5 | ||
|
|
12073001c2 | ||
|
|
4c20135749 | ||
|
|
f9ebf038e0 | ||
|
|
62ebd93579 | ||
|
|
a10fdc3fb1 | ||
|
|
8581e702d6 | ||
|
|
bdbd5ff0e7 | ||
|
|
f769465284 | ||
|
|
1b5b52d2e4 | ||
|
|
ab62d28817 | ||
|
|
8e0a7ec20d | ||
|
|
23d66949e1 | ||
|
|
184bb11fd9 | ||
|
|
a70db34fc9 | ||
|
|
fbde1b2d71 | ||
|
|
c22fef18e4 | ||
|
|
ee5b250b66 | ||
|
|
fb85c05594 | ||
|
|
25b1114e03 | ||
|
|
4b8a387529 | ||
|
|
df41114e0e | ||
|
|
dc3618a127 | ||
|
|
31fe0753e3 | ||
|
|
7ad5afb935 | ||
|
|
e1b0f2b275 | ||
|
|
0e0fb452a3 | ||
|
|
f66432e999 | ||
|
|
08e9d30fa2 | ||
|
|
d2270e514b | ||
|
|
031305c205 | ||
|
|
e2843ede7e | ||
|
|
09958ebdff | ||
|
|
53fc9a66a6 | ||
|
|
a95c6c5fe8 | ||
|
|
bcd187d7d6 | ||
|
|
03783a7d1b | ||
|
|
f2fb8c01f4 | ||
|
|
ddb8e95d39 | ||
|
|
fbac4505ce | ||
|
|
eb937f81fa | ||
|
|
5144162a2d | ||
|
|
b4411b4f28 | ||
|
|
29f7654ab1 | ||
|
|
66fd6a5ab1 | ||
|
|
c30d3d8010 | ||
|
|
0c40f87b55 | ||
|
|
4761e00852 | ||
|
|
0133d5cba8 | ||
|
|
9066a96dde | ||
|
|
6abb551fdd | ||
|
|
97bdf13b59 | ||
|
|
dae88f8dc7 | ||
|
|
64d1711a24 | ||
|
|
b9638cb7cc |
249
ChangeLog
249
ChangeLog
@@ -1,3 +1,252 @@
|
||||
Changes between v2.9.3 and v2.9.4:
|
||||
----------------------------------
|
||||
|
||||
Benno Schulenberg (65):
|
||||
bindings: make a key defined as string work also in browser and viewer
|
||||
bindings: rename the bindable function 'gototext' to 'flipgoto'
|
||||
bindings: revert the ^/ changes, as ^/ is not always Go-To-Line
|
||||
bindings: show ^/ instead of ^_ for Go-To-Line
|
||||
build: fix compilation when configured with --enable-tiny
|
||||
bump version numbers and add a news item for the 2.9.4 release
|
||||
docs: mention that a key can be bound to a string
|
||||
docs: note also in the Info manual that text can be selected with Shift
|
||||
editing: when --smooth is used, make <Enter>-at-bottom scroll one row
|
||||
general: detect in a better way whether we're running on a Linux console
|
||||
gnulib: update to its current upstream state
|
||||
goto: avoid a segfault, by initializing 'answer' when it is NULL
|
||||
help: mention that some keys work on a region when the mark is on
|
||||
help: tweak the descriptions of ^X and ^R
|
||||
input: handle the implant() function separately also for the prompt
|
||||
input: handle the implant() function separately, as it is special
|
||||
memory: avoid a leak when toggling from Search to Goto
|
||||
memory: squeal when there is something wrong, instead of stumbling on
|
||||
new feature: allow binding a key to a string (in a nanorc file)
|
||||
prompt: disallow pasting when in restricted mode
|
||||
rcfile: allow a syntax name to be unquoted
|
||||
search: clear the existing answer when starting a new search
|
||||
search: get rid of some unneeded recursion when just toggling things
|
||||
selecting: cancel the softmark upon any attempt to move the cursor
|
||||
small addition: allow customizing the color of an error message
|
||||
syntax: color also ^/ in nano's help texts and in nanorc files
|
||||
syntaxes: remove quotes from each syntax name, and color it differently
|
||||
syntax: nanorc: color also bindings to a string as valid
|
||||
tweaks: adjust comments and indentation after the previous change
|
||||
tweaks: adjust two comments, move two declarations, rewrap three lines
|
||||
tweaks: appease valgrind concerning syscalls with uninitialized values
|
||||
tweaks: condense a comment and elide an 'if'
|
||||
tweaks: correct a typo in NEWS
|
||||
tweaks: correct a typo that broke binding a key to a string
|
||||
tweaks: do not needlessly renumber the lines in the buffer
|
||||
tweaks: don't call strcmp() to determine whether a string is empty
|
||||
tweaks: drop an assert, add a warning, and change a 'for' to a 'while'
|
||||
tweaks: drop some debugging stuff, and adjust what remains of it
|
||||
tweaks: elide another variable, to call a function less often
|
||||
tweaks: elide an unneeded variable
|
||||
tweaks: elide an unneeded variable
|
||||
tweaks: elide an unneeded variable
|
||||
tweaks: elide an unused variable and parameter
|
||||
tweaks: elide two unneeded booleans
|
||||
tweaks: exclude an unlikely error message from the tiny version
|
||||
tweaks: exclude an unlikely warning from the tiny version
|
||||
tweaks: fix a copy-and-paste error
|
||||
tweaks: make the fsfromline() call only for the undo types that need it
|
||||
tweaks: plug a memory leak when using Verbatim Input at a prompt
|
||||
tweaks: refactor the implanting of a key expansion
|
||||
tweaks: remove another superfluous check
|
||||
tweaks: remove a superfluous check
|
||||
tweaks: remove two deprecated options and six rebindable function names
|
||||
tweaks: remove two superfluous checks, and restrict two others
|
||||
tweaks: rename a parameter and a variable, to be more fitting
|
||||
tweaks: rename a variable to be more distinct and greppable
|
||||
tweaks: rename two variables, to be more meaningful
|
||||
tweaks: reshuffle some code, to be slightly less ugly
|
||||
tweaks: reshuffle some of the search-and-replace cleanup calls
|
||||
tweaks: reshuffle the undo types into mostly the same order everywhere
|
||||
tweaks: shorten the name of two record elements
|
||||
tweaks: slightly rewrap the FAQ's table of contents
|
||||
tweaks: transform a 'do' to a 'while', and reshuffle a comment
|
||||
tweaks: unabbreviate two variable names
|
||||
undo: when redoing, don't try to find a line number that might not exist
|
||||
|
||||
Brand Huntsman (1):
|
||||
color: remove unneeded bright comparision to prevent duplicate pairs
|
||||
|
||||
David Lawrence Ramsey (3):
|
||||
docs: mention that errorcolor does have default colors
|
||||
input: don't stop prepending when the user adds text via a shortcut
|
||||
tweaks: fix typo in rebindable function name
|
||||
|
||||
Tom Levy (1):
|
||||
syntax: go: highlight also floats with leading zeroes as valid
|
||||
|
||||
|
||||
Changes between v2.9.2 and v2.9.3:
|
||||
----------------------------------
|
||||
|
||||
Benno Schulenberg (65):
|
||||
build: fix compilation when configured with --enable(tiny,color,nanorc}
|
||||
build: fix compilation with --enable-tiny --enable-justify
|
||||
build: let ./configure fail (not just warn) when curses.h is missing
|
||||
bump version numbers and add a news item for the 2.9.3 release
|
||||
copyright: update the years for the FSF
|
||||
display: wipe the status bar when doing a total refresh
|
||||
docs: remove the note about needing a recent ncurses for macros to work
|
||||
docs: update the FAQ for the changed default location of history files
|
||||
docs: update the TODO file to the current state of affairs
|
||||
gnulib: update to its current upstream state
|
||||
help: don't get stuck when there is an unwrappable piece of text
|
||||
input: consume only the actual length of an escape sequence
|
||||
input: fully reset state when a three-digit character code is cut short
|
||||
input: make <Shift+Tab> do an unindent also on a Manjaro console
|
||||
input: recognize escape sequences for <Shift+PageUp> and <Shift+PageDown>
|
||||
input: recognize more escape sequences for <Shift+Home> and <Shift+End>
|
||||
input: recognize the deviant keycode for <Ctrl+End> in urxvt
|
||||
options: recognize -M and --trimblanks on the command line
|
||||
painting: look for an end match only after a start match, if any
|
||||
prompt: show whitespace only in the filename, not in the whole line
|
||||
replacing: don't skip the first character of a backwards-marked region
|
||||
search: suppress the occurrence at the cursor only when replacing
|
||||
startup: allow a named pipe as file argument when --noread is used
|
||||
startup: make an error message succinct and to the point
|
||||
startup: move the initialization of colors, so any error gets printed
|
||||
syntax: go: colorize only valid octal numbers
|
||||
syntax: lua: do not color debug.setinfo as it doesn't exist
|
||||
syntax: nanohelp: color also the Sh-Tab key combo
|
||||
tweaks: change a 'do' to a 'while', and return early to elide an 'if'
|
||||
tweaks: check for the type of terminal far earlier
|
||||
tweaks: condense a condition and a comment, and reshuffle a line
|
||||
tweaks: condense and rewrap some comments, and reindent two lines
|
||||
tweaks: condense the conditional compilation of shortcut reassignments
|
||||
tweaks: don't bother freeing the key buffer, just reallocate it
|
||||
tweaks: don't bother to reallocate when the keybuffer size decreases
|
||||
tweaks: drop a superfluous parameter, as it is always 1
|
||||
tweaks: drop a useless assert, and don't abort over an unhandled option
|
||||
tweaks: drop two unneeded initializations, and trim a comment
|
||||
tweaks: elide a tiny intermediate buffer, and rename two variables
|
||||
tweaks: exclude --trimblanks when no wrapping or justifying is configured
|
||||
tweaks: fully include Savefile and Wherewas in the tiny version
|
||||
tweaks: indenting text files with tabs is not a good idea
|
||||
tweaks: mark the two blocks that have a deviant indentation
|
||||
tweaks: move a bunch of comments to the lines that they refer to
|
||||
tweaks: move two functions to their proper place, orderingwise
|
||||
tweaks: remove a fragment of dead code
|
||||
tweaks: remove a handful of redundant (because always true) asserts
|
||||
tweaks: remove a superfluous case -- there can never be four digits
|
||||
tweaks: remove a superfluous check, as we insert always one code
|
||||
tweaks: rename a function, for aptness, and drop a superfluous check
|
||||
tweaks: rename a function, to be more distinct
|
||||
tweaks: rename a variable, and further condense some comments
|
||||
tweaks: rename a variable, for more contrast
|
||||
tweaks: rename a variable, to better fit its usage
|
||||
tweaks: rename two variables, and swap their declaration order
|
||||
tweaks: rename two variables, for preciseness and shortness
|
||||
tweaks: reshuffle a couple of lines
|
||||
tweaks: reshuffle a couple of lines, to make a bit more sense
|
||||
tweaks: reshuffle some stuff, and avoid a memory leak
|
||||
tweaks: reshuffle two condition series, to look better
|
||||
tweaks: rewrap a bunch of lines in the NEWS file
|
||||
tweaks: set a modifier in a single place, for conciseness
|
||||
tweaks: swap the row and col parameters to a more consistent order
|
||||
tweaks: transform a parameter, from a pointer to the value itself
|
||||
wrapping: don't trim a blank character that the user just typed
|
||||
|
||||
Brand Huntsman (1):
|
||||
startup: parse interface colors when they are read, not when initialized
|
||||
|
||||
|
||||
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:
|
||||
----------------------------------
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@ Improvements in GNU nano
|
||||
========================
|
||||
|
||||
Since 2.9.0:
|
||||
- A key can be bound to a string -- any mix of text and commands.
|
||||
- Error messages are shown by default in bright white on red.
|
||||
- <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.
|
||||
|
||||
92
README
92
README
@@ -1,76 +1,76 @@
|
||||
|
||||
GNU nano -- an enhanced clone of the Pico text editor
|
||||
GNU nano -- an enhanced clone of the Pico text editor
|
||||
|
||||
Overview
|
||||
|
||||
The nano project was started because of a few "problems" with the
|
||||
wonderfully easy-to-use and friendly Pico text editor.
|
||||
The nano project was started because of a few "problems" with the
|
||||
wonderfully easy-to-use and friendly Pico text editor.
|
||||
|
||||
First and foremost was its license: the Pine suite does not use
|
||||
the GPL or a GPL-friendly license, and has unclear restrictions on
|
||||
redistribution. Because of this, Pine and Pico are not included
|
||||
with many GNU/Linux distributions. Also, other features (like
|
||||
go-to-line-number or search-and-replace) were unavailable until
|
||||
recently or require a command-line flag. Yuck.
|
||||
First and foremost was its license: the Pine suite does not use
|
||||
the GPL or a GPL-friendly license, and has unclear restrictions on
|
||||
redistribution. Because of this, Pine and Pico are not included
|
||||
with many GNU/Linux distributions. Also, other features (like
|
||||
go-to-line-number or search-and-replace) were unavailable until
|
||||
recently or require a command-line flag. Yuck.
|
||||
|
||||
nano aims to solve these problems by emulating the functionality of
|
||||
Pico as closely as possible while addressing the problems above and
|
||||
providing other extra functionality.
|
||||
nano aims to solve these problems by emulating the functionality of
|
||||
Pico as closely as possible while addressing the problems above and
|
||||
providing other extra functionality.
|
||||
|
||||
The nano editor is an official GNU package. For more information on
|
||||
GNU and the Free Software Foundation, please see http://www.gnu.org/.
|
||||
The nano editor is an official GNU package. For more information on
|
||||
GNU and the Free Software Foundation, please see http://www.gnu.org/.
|
||||
|
||||
How to compile and install nano
|
||||
|
||||
Download the nano source code, then:
|
||||
Download the nano source code, then:
|
||||
|
||||
tar xvzf nano-x.y.z.tar.gz
|
||||
cd nano-x.y.z
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
tar xvzf nano-x.y.z.tar.gz
|
||||
cd nano-x.y.z
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
It's that simple. Use --prefix with configure to override the
|
||||
default installation directory of /usr/local.
|
||||
It's that simple. Use --prefix with configure to override the
|
||||
default installation directory of /usr/local.
|
||||
|
||||
If you haven't configured with the --disable-nanorc option, after
|
||||
installation you may want to copy the doc/sample.nanorc file to
|
||||
your home directory, rename it to ".nanorc", and then edit it
|
||||
according to your taste.
|
||||
If you haven't configured with the --disable-nanorc option, after
|
||||
installation you may want to copy the doc/sample.nanorc file to
|
||||
your home directory, rename it to ".nanorc", and then edit it
|
||||
according to your taste.
|
||||
|
||||
Web Page
|
||||
|
||||
https://nano-editor.org/
|
||||
https://nano-editor.org/
|
||||
|
||||
Mailing Lists
|
||||
|
||||
There are three nano-related mailing-lists.
|
||||
There are three nano-related mailing-lists.
|
||||
|
||||
+ info-nano@gnu.org is a very low traffic list used to announce
|
||||
new nano versions or other important info about the project.
|
||||
+ help-nano@gnu.org is for those seeking to get help without
|
||||
wanting to hear about the technical details of its development.
|
||||
+ nano-devel@gnu.org is the list used by the people that make nano
|
||||
and a general development discussion list, with moderate traffic.
|
||||
+ info-nano@gnu.org is a very low traffic list used to announce
|
||||
new nano versions or other important info about the project.
|
||||
+ help-nano@gnu.org is for those seeking to get help without
|
||||
wanting to hear about the technical details of its development.
|
||||
+ nano-devel@gnu.org is the list used by the people that make nano
|
||||
and a general development discussion list, with moderate traffic.
|
||||
|
||||
To subscribe, send email to <name>-request@gnu.org with a subject
|
||||
of "subscribe", where <name> is the list you want to subscribe to.
|
||||
To subscribe, send email to <name>-request@gnu.org with a subject
|
||||
of "subscribe", where <name> is the list you want to subscribe to.
|
||||
|
||||
Bug Reports
|
||||
|
||||
To report a bug, please file a description of the problem on nano's
|
||||
bug tracker (https://savannah.gnu.org/bugs/?group=nano -- hover on
|
||||
"Bugs", then click "Submit new"). The issue may have already been
|
||||
reported, so please look first.
|
||||
To report a bug, please file a description of the problem on nano's
|
||||
bug tracker (https://savannah.gnu.org/bugs/?group=nano -- hover on
|
||||
"Bugs", then click "Submit new"). The issue may have already been
|
||||
reported, so please look first.
|
||||
|
||||
Current Status
|
||||
|
||||
Since version 2.5.0, GNU nano has abandoned the distinction between
|
||||
a stable and a development branch: it is now on a "rolling" release
|
||||
-- fixing bugs and adding new features go hand in hand.
|
||||
Since version 2.5.0, GNU nano has abandoned the distinction between
|
||||
a stable and a development branch: it is now on a "rolling" release
|
||||
-- fixing bugs and adding new features go hand in hand.
|
||||
|
||||
Copyright Years
|
||||
|
||||
When in any file of this package a copyright notice mentions a
|
||||
year range (such as 1999-2011), it is a shorthand for a list of
|
||||
all the years in that interval.
|
||||
When in any file of this package a copyright notice mentions a
|
||||
year range (such as 1999-2011), it is a shorthand for a list of
|
||||
all the years in that interval.
|
||||
|
||||
@@ -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
168
THANKS
@@ -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
|
||||
|
||||
16
TODO
16
TODO
@@ -2,11 +2,9 @@ A list of desired features
|
||||
--------------------------
|
||||
|
||||
Somewhat urgent:
|
||||
- Make undo/redo work also for justifying and indenting.
|
||||
- Make undo/redo work also for justifying.
|
||||
- Detect when text is being pasted, so that we can handle it faster.
|
||||
See https://savannah.gnu.org/bugs/?40060.
|
||||
- Allow to define and execute a macro: a stored sequence of keystrokes.
|
||||
See https://savannah.gnu.org/bugs/?50314.
|
||||
- Allow color syntaxes to apply to more than just color, so that we can
|
||||
e.g. specify a different alternate spell checker depending on which
|
||||
file type we have open.
|
||||
@@ -15,15 +13,16 @@ Somewhat urgent:
|
||||
See also https://savannah.gnu.org/bugs/?28993.
|
||||
|
||||
Vague musings:
|
||||
- FriBidi support?
|
||||
- Add support for right-to-left text (RTL), through FriBidi?
|
||||
- Allow setting marks (saved positions, not to be confused with the
|
||||
mark set via Ctrl-^) at various lines and/or columns in the buffer,
|
||||
and allow movement between them with a single keystroke?
|
||||
- Make matching bracket searches sophisticated enough to skip over
|
||||
brackets inside comments?
|
||||
- Allow indentation of marked text by spaces as well as tabs?
|
||||
- Allow indentation to add just enough columns to reach the nearest
|
||||
multiple of tabsize, rather than always adding tabsize columns?
|
||||
|
||||
For version 2.9:
|
||||
- Make undo/redo work also for indenting. [DONE]
|
||||
- Allow to record and replay a macro: a stored series of keystrokes. [DONE]
|
||||
|
||||
For version 2.8:
|
||||
- Allow text searches in the help viewer. [DONE]
|
||||
@@ -41,8 +40,7 @@ For version 2.2:
|
||||
- Undo/Redo keys (M-U and M-E)? [DONE]
|
||||
- Fix problems with color syntaxes highlighting lines too aggressively. [DONE]
|
||||
- Allow nano to work like a pager (reading from stdin). [DONE]
|
||||
- Allow color syntaxes to be selected based on more than just filename
|
||||
extension. [DONE]
|
||||
- Select a color syntax based on more than just the filename extension. [DONE]
|
||||
- Allow soft wrapping as well as hard wrapping? [DONE]
|
||||
|
||||
For version 2.0:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Generate configure & friends for GIT users.
|
||||
|
||||
gnulib_url="git://git.sv.gnu.org/gnulib.git"
|
||||
gnulib_hash="b9d0b50f6cd122a1748e1e5b79ecca7a0fef214e"
|
||||
gnulib_hash="59e59d99bc1ca635d178778b9b4ee544330775c4"
|
||||
|
||||
modules="
|
||||
futimens
|
||||
|
||||
750
configure.ac
750
configure.ac
File diff suppressed because it is too large
Load Diff
31
doc/faq.html
31
doc/faq.html
@@ -14,13 +14,15 @@
|
||||
<a href="#1.2">1.2. What is the history behind nano?</a><br>
|
||||
<a href="#1.3">1.3. Why the name change from TIP?</a><br>
|
||||
<a href="#1.4">1.4. What is the current version of nano?</a><br>
|
||||
<a href="#1.5">1.5. I want to read the manpage without having to download the program!</a></p></blockquote>
|
||||
<a href="#1.5">1.5. I want to read the manpage without having to download the program!</a>
|
||||
</p></blockquote>
|
||||
<h2><a href="#2">2. Where to get GNU nano.</a></h2>
|
||||
<blockquote><p>
|
||||
<a href="#2.1">2.1. FTP and WWW sites that carry nano.</a><br>
|
||||
<a href="#2.2">2.2. RedHat and derivatives (.rpm) packages.</a><br>
|
||||
<a href="#2.3">2.3. Debian (.deb) packages.</a><br>
|
||||
<a href="#2.4">2.4. By GIT (for the brave).</a></p></blockquote>
|
||||
<a href="#2.4">2.4. By GIT (for the brave).</a>
|
||||
</p></blockquote>
|
||||
<h2><a href="#3">3. Installation and Configuration</a></h2>
|
||||
<blockquote><p>
|
||||
<a href="#3.1">3.1. How do I install the RPM or DEB package?</a><br>
|
||||
@@ -31,7 +33,8 @@
|
||||
<a href="#3.7">3.7. Tell me more about this multibuffer stuff!</a><br>
|
||||
<a href="#3.8">3.8. Tell me more about this verbatim input stuff!</a><br>
|
||||
<a href="#3.9a">3.9a. How do I make a .nanorc file that nano will read when I start it?</a><br>
|
||||
<a href="#3.9b">3.9b. How about in Win32?</a></p></blockquote>
|
||||
<a href="#3.9b">3.9b. How about in Win32?</a>
|
||||
</p></blockquote>
|
||||
<h2><a href="#4">4. Running</a></h2>
|
||||
<blockquote><p>
|
||||
<a href="#4.1">4.1. How do I open a file with a name beginning with '+' from the command line?</a><br>
|
||||
@@ -46,25 +49,29 @@
|
||||
<a href="#4.9">4.9. I've compiled nano with color support, but I don't see any color when I run it!</a><br>
|
||||
<a href="#4.10">4.10. How do I make nano my default editor (in Pine, mutt, etc.)?</a><br>
|
||||
<a href="#4.11">4.11. How do I select text for or paste text from the clipboard in an X terminal when I'm running nano in one and nano's mouse support is turned on?</a><br>
|
||||
<a href="#4.12">4.12. On startup I get a message that says "Detected a legacy nano history file". Now older nano versions can't find my search history!</a></p></blockquote>
|
||||
<a href="#4.12">4.12. On startup I get a message that says "Detected a legacy nano history file". Now older nano versions can't find my search history!</a>
|
||||
</p></blockquote>
|
||||
<h2><a href="#5">5. Internationalization</a></h2>
|
||||
<blockquote><p>
|
||||
<a href="#5.1">5.1. There's no translation for my language!</a><br>
|
||||
<a href="#5.2">5.2. I don't like the translation for <x> in my language. How can I fix it?</a><br>
|
||||
<a href="#5.3">5.3. What is the status of Unicode support?</a></p></blockquote>
|
||||
<a href="#5.3">5.3. What is the status of Unicode support?</a>
|
||||
</p></blockquote>
|
||||
<h2><a href="#6">6. Advocacy and Licensing</a></h2>
|
||||
<blockquote><p>
|
||||
<a href="#6.1">6.1. Why should I use nano instead of Pico?</a><br>
|
||||
<a href="#6.2">6.2. Why should I use Pico instead of nano?</a><br>
|
||||
<a href="#6.3">6.3. What is so bad about the older Pine license?</a><br>
|
||||
<a href="#6.4">6.4. Okay, well, what mail program should I use then?</a></p></blockquote>
|
||||
<a href="#6.4">6.4. Okay, well, what mail program should I use then?</a>
|
||||
</p></blockquote>
|
||||
<h2><a href="#7">7. Miscellaneous</a></h2>
|
||||
<blockquote><p>
|
||||
<a href="#7.1">7.1. Where can I ask questions or send suggestions?</a><br>
|
||||
<a href="#7.2">7.2. How do I submit a bug report or patch?</a><br>
|
||||
<a href="#7.3">7.3. I want to send the development team a big load of cash (or just a thank you).</a><br>
|
||||
<a href="#7.4">7.4. How do I join the development team?</a><br>
|
||||
<a href="#7.5">7.5. Can I have write access to the GIT tree?</a></p></blockquote>
|
||||
<a href="#7.5">7.5. Can I have write access to the GIT tree?</a>
|
||||
</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="1"></a>1. General</h1>
|
||||
@@ -83,7 +90,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 "establishes a full duplex terminal connection to a remote host", and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
|
||||
<h2><a name="1.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.4</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<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%">
|
||||
@@ -217,18 +224,18 @@
|
||||
<h2><a name="4.12"></a>4.12. On startup I get a message that says "Detected a legacy nano history file". Now older nano versions can't find my search history!</h2>
|
||||
<blockquote><p>In nano 2.3.0, cursor-position history was introduced, and both history files now reside in a .nano subdirectory in your home directory. A newer nano will move an existing search-history file to this new location so it can continue to be used. This means that if you then try and use an earlier version of nano, it will be unable to see your current search history. To fix this, run the following command:</p>
|
||||
<p><b>ln -sf ~/.nano/search_history ~/.nano_history</b></p>
|
||||
<p>The "migration service" (moving the search-history file to its new location) will be deleted from nano in early 2018.</p></blockquote>
|
||||
<p>The "migration service" (moving the search-history file to its new location) has been deleted from nano in late 2017, since version 2.9.0. The search-history and position-history files will now be looked for first in ~/.nano/ and, when not found there, then in ~/.local/share/nano/.</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="5"></a>5. Internationalization</h1>
|
||||
<h2><a name="5.1"></a>5.1. There's no translation for my language!</h2>
|
||||
<blockquote><p>In June 2001, GNU nano entered the <a href="http://translationproject.org/html/welcome.html">Translation Project</a> and since then, translations should be managed from there.</p>
|
||||
<p>If there isn't a translation for your language, you could ask <a href="http://translationproject.org/team/">your language team</a> to translate nano, or better still, join that team and do it yourself. Joining a team is easy. You just need to ask the team leader to add you, and then send a <a href="http://translationproject.org/disclaim.txt">translation disclaimer to the FSF</a> (this is necessary as nano is an official GNU package, but it does <b>not</b> mean that you transfer the rights of your work to the FSF, it's just so the FSF can legally manage them).</p>
|
||||
<p>In any case, translating nano is very easy. Just grab the latest <b>nano.pot</b> file listed on <a href="http://translationproject.org/domain/nano.html">nano's page</a> at the TP, and translate each <b>msgid</b> line into your native language on the <b>msgstr</b> line. When you're done, you should send it to the TP's central po repository.</p></blockquote>
|
||||
<p>In any case, translating nano is easy. Just grab the latest <b>nano.pot</b> file listed on <a href="http://translationproject.org/domain/nano.html">nano's page</a> at the TP, and translate each <b>msgid</b> line into your native language on the <b>msgstr</b> line. When you're done, you should send it to the TP's central PO-file repository.</p></blockquote>
|
||||
<h2><a name="5.2"></a>5.2. I don't like the translation for <x> in my language. How can I fix it?</h2>
|
||||
<blockquote><p>The best way would probably be to send an e-mail to the team's mailing listed mentione in the <code>Language-Team:</code> field in the <b><your_language>.po</b> file with your suggested corrections, and then they can make the changes reach the nano-devel list.</p></blockquote>
|
||||
<blockquote><p>The best way is to send an e-mail with your suggested corrections to the team's mailing list. The address is mentioned in the <code>Language-Team:</code> field in the relevant PO file. The team leader or the assigned translator can then make the changes reach the nano-devel list.</p></blockquote>
|
||||
<h2><a name="5.3"></a>5.3. What is the status of Unicode support?</h2>
|
||||
<blockquote><p>Since versions 1.3.12, Unicode should be usable. With your terminal, locale (LC_ALL and similar environment variables), and encoding configured to properly support UTF-8, you should be able to enter and save Unicode text.</p></blockquote>
|
||||
<blockquote><p>Unicode should be fully usable nowadays. When the encoding of your terminal is set to UTF-8, and your locale (mainly the LANG environment variable) is UTF-8 too, then you should be able to read, enter and save Unicode text.</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="6"></a>6. Advocacy and Licensing</h1>
|
||||
|
||||
15
doc/nano.1
15
doc/nano.1
@@ -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.4" "March 2018"
|
||||
|
||||
.SH NAME
|
||||
nano \- Nano's ANOther editor, an enhanced free Pico clone
|
||||
@@ -54,9 +54,9 @@ highlighted), and then use \fB^K\fR to cut it, or \fBM\-6\fR to copy it to the
|
||||
cutbuffer. One can also save the marked text to a file with \fB^O\fR, or
|
||||
spell check it with \fB^T\fR.
|
||||
.PP
|
||||
Since nano-2.7.0, text can also be selected by holding Shift and moving the
|
||||
cursor with the arrow keys. Holding down the Alt key too will increase the
|
||||
stride.
|
||||
On some terminals, text can be selected also by holding down Shift while
|
||||
using the arrow keys. Holding down the Alt key too will increase the stride.
|
||||
Any cursor movement without Shift being held will cancel such a selection.
|
||||
.PP
|
||||
The two lines at the bottom of the screen show some important commands;
|
||||
the built-in help (\fB^G\fR) lists all the available ones.
|
||||
@@ -108,6 +108,10 @@ won't work properly with this option enabled.
|
||||
.BR \-L ", " \-\-nonewlines
|
||||
Don't add newlines to the ends of files.
|
||||
.TP
|
||||
.BR \-M ", " \-\-trimblanks
|
||||
Snip trailing whitespace from the wrapped line when automatic
|
||||
hard-wrapping occurs or when text is justified.
|
||||
.TP
|
||||
.BR \-N ", " \-\-noconvert
|
||||
Disable automatic conversion of files from DOS/Mac format.
|
||||
.TP
|
||||
@@ -117,7 +121,6 @@ Use the blank line below the title bar as extra editing space.
|
||||
.BR \-P ", " \-\-positionlog
|
||||
For the 200 most recent files, log the last position of the cursor,
|
||||
and place it at that position again upon reopening such a file.
|
||||
(The old form of this option, \fB\-\-poslog\fR, is deprecated.)
|
||||
.TP
|
||||
.BR "\-Q ""\fIcharacters\fB""" ", " "\-\-quotestr=""" \fIcharacters """
|
||||
Set the quoting string for justifying. The default is
|
||||
@@ -301,7 +304,7 @@ saving.
|
||||
.sp
|
||||
The recording and playback of keyboard macros works correctly only on a
|
||||
terminal emulator, not on a Linux console (VT), because the latter is a
|
||||
deficient terminal. And it works only with recent versions of ncurses.
|
||||
deficient terminal.
|
||||
.sp
|
||||
Please report any other bugs that you encounter via:
|
||||
.br
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
@smallbook
|
||||
@set EDITION 0.5
|
||||
@set VERSION 2.9.1
|
||||
@set UPDATED November 2017
|
||||
@set VERSION 2.9.4
|
||||
@set UPDATED March 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.4
|
||||
|
||||
@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.4.
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
@@ -200,6 +200,11 @@ won't work properly with this option enabled.
|
||||
@itemx --nonewlines
|
||||
Don't add newlines to the ends of files.
|
||||
|
||||
@item -M
|
||||
@itemx --trimblanks
|
||||
Snip trailing whitespace from the wrapped line when automatic
|
||||
hard-wrapping occurs or when text is justified.
|
||||
|
||||
@item -N
|
||||
@itemx --noconvert
|
||||
Disable automatic conversion of files from DOS/Mac format.
|
||||
@@ -212,7 +217,6 @@ Use the blank line below the title bar as extra editing space.
|
||||
@itemx --positionlog
|
||||
For the 200 most recent files, log the last position of the cursor,
|
||||
and place it at that position again upon reopening such a file.
|
||||
(The old form of this option, @option{--poslog}, is deprecated.)
|
||||
|
||||
@item -Q "@var{characters}"
|
||||
@itemx --quotestr="@var{characters}"
|
||||
@@ -493,12 +497,15 @@ the 'Copy Text' command (default key binding: @kbd{M-6}).
|
||||
|
||||
Text can be selected by first 'setting the Mark' (default key bindings:
|
||||
@kbd{^6} and @kbd{M-A}) and then moving the cursor to the other end of the portion
|
||||
to be selected. The selected portion of text will be highlighted in
|
||||
reverse video (or in bold if you set the boldtext option).
|
||||
to be selected. The selected portion of text will be highlighted.
|
||||
This selection can now be cut or copied in its entirety with a single
|
||||
@kbd{^K} or @kbd{M-6}. Or the selection can be used to limit the scope of
|
||||
a search-and-replace (@kbd{^\}) or spell-checking session (@kbd{^T}).
|
||||
|
||||
On some terminals, it is also possible to select text by holding down
|
||||
@kbd{Shift} together with the cursor keys. Such a selection is cancelled
|
||||
upon any cursor movement where @kbd{Shift} isn't held.
|
||||
|
||||
Cutting or copying selected text will toggle the mark off automatically.
|
||||
If necessary, it can be toggled off manually with another @kbd{^6} or @kbd{M-A}.
|
||||
|
||||
@@ -563,7 +570,7 @@ saving.
|
||||
|
||||
The recording and playback of keyboard macros works correctly only on a
|
||||
terminal emulator, not on a Linux console (VT), because the latter is a
|
||||
deficient terminal. And it works only with recent versions of ncurses.
|
||||
deficient terminal.
|
||||
|
||||
@node Built-in Help
|
||||
@chapter Built-in Help
|
||||
@@ -726,13 +733,16 @@ Do case-sensitive searches by default.
|
||||
|
||||
@item set constantshow
|
||||
Constantly display the cursor position on the status bar.
|
||||
(The old form of this option, @code{set const}, is deprecated.)
|
||||
Note that this overrides @option{quickblank}.
|
||||
|
||||
@item set cutfromcursor
|
||||
Use cut-from-cursor-to-end-of-line by default, instead of cutting the whole line.
|
||||
(The old form of this option, @code{set cut}, is deprecated.)
|
||||
|
||||
@item set errorcolor @var{fgcolor},@var{bgcolor}
|
||||
Use this color combination for the status bar when an error message is displayed.
|
||||
@xref{@code{set functioncolor}} for valid color names.
|
||||
|
||||
@item set fill @var{number}
|
||||
Hard-wrap lines at column number @var{number}. If @var{number} is 0 or less,
|
||||
the maximum line length will be the screen width less @var{number} columns.
|
||||
@@ -753,9 +763,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.
|
||||
@@ -813,7 +820,6 @@ directory feature is turned off.
|
||||
@item set positionlog
|
||||
Save the cursor position of files between editing sessions.
|
||||
The cursor position is remembered for the 200 most-recently edited files.
|
||||
(The old form of this option, @code{set poslog}, is deprecated.)
|
||||
|
||||
@item set preserve
|
||||
Preserve the XON and XOFF keys (@kbd{^Q} and @kbd{^S}).
|
||||
@@ -899,6 +905,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.
|
||||
@@ -1031,7 +1041,7 @@ in one of the system-installed files (which normally are not writable).
|
||||
@node Rebinding Keys
|
||||
@section Rebinding Keys
|
||||
|
||||
Key bindings can be changed via the following two commands in a
|
||||
Key bindings can be changed via the following three commands in a
|
||||
nanorc file:
|
||||
|
||||
@table @code
|
||||
@@ -1040,6 +1050,13 @@ nanorc file:
|
||||
Rebinds @code{key} to @code{function} in the context of @code{menu}
|
||||
(or in all menus where the function exists by using @code{all}).
|
||||
|
||||
@item bind key "string" menu
|
||||
Makes @code{key} produce @code{string} in the context of @code{menu}
|
||||
(or in all menus where the key exists when @code{all} is used).
|
||||
The @code{string} can consist of text or commands or a mix of them.
|
||||
(To enter a command into the @code{string}, precede its keystroke
|
||||
with @kbd{M-V}.)
|
||||
|
||||
@item unbind key menu
|
||||
Unbinds @code{key} from @code{menu}
|
||||
(or from all menus where it exists by using @code{all}).
|
||||
@@ -1096,7 +1113,6 @@ Starts a backward search for text in the current buffer.
|
||||
|
||||
@item searchagain
|
||||
Repeats the last search command without prompting.
|
||||
(The form @code{research} is deprecated.)
|
||||
|
||||
@item findprevious
|
||||
As @code{searchagain}, but always in the backward direction.
|
||||
@@ -1131,7 +1147,6 @@ Cuts all text from the cursor position till the end of the buffer.
|
||||
|
||||
@item curpos
|
||||
Shows the current cursor position: the line, column, and character positions.
|
||||
(The form @code{cursorpos} is deprecated.)
|
||||
|
||||
@item wordcount
|
||||
Counts the number of words, lines and characters in the current buffer.
|
||||
@@ -1219,9 +1234,6 @@ Goes to the last line of the file.
|
||||
Goes to a specific line (and column if specified). Negative numbers count
|
||||
from the end of the file (and end of the line).
|
||||
|
||||
@item gototext
|
||||
Switches from targeting a line number to searching for text.
|
||||
|
||||
@item findbracket
|
||||
Moves the cursor to the bracket (brace, parenthesis, etc.) that matches
|
||||
(pairs) with the one under the cursor.
|
||||
@@ -1272,7 +1284,6 @@ Toggles case sensitivity in searching (search/replace menus only).
|
||||
|
||||
@item regexp
|
||||
Toggles whether searching/replacing is based on literal strings or regular expressions.
|
||||
(The form @code{regex} is deprecated.)
|
||||
|
||||
@item backwards
|
||||
Toggles whether searching/replacing goes forward or backward.
|
||||
@@ -1285,7 +1296,10 @@ Shows the next history entry in the prompt menus (e.g.@: search).
|
||||
|
||||
@item flipreplace
|
||||
Toggles between searching for something and replacing something.
|
||||
(The form @code{dontreplace} is deprecated.)
|
||||
|
||||
@item flipgoto
|
||||
Toggles between searching for text and targeting a line number.
|
||||
(The form @code{gototext} is deprecated.)
|
||||
|
||||
@item flipexecute
|
||||
Toggles between inserting a file and executing a command.
|
||||
@@ -1293,7 +1307,6 @@ Toggles between inserting a file and executing a command.
|
||||
@item flipnewbuffer
|
||||
Toggles between inserting into the current buffer and into a new
|
||||
empty buffer.
|
||||
(The form @code{newbuffer} is deprecated.)
|
||||
|
||||
@item dosformat
|
||||
When writing a file, switches to writing a DOS format (CR/LF).
|
||||
@@ -1399,7 +1412,6 @@ The 'search to replace' menu.
|
||||
|
||||
@item replacewith
|
||||
The 'replace with' menu, which comes up after 'search to replace'.
|
||||
(The form @code{replace2} is deprecated.)
|
||||
|
||||
@item gotoline
|
||||
The 'goto line (and column)' menu.
|
||||
|
||||
40
doc/nanorc.5
40
doc/nanorc.5
@@ -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.4" "March 2018"
|
||||
|
||||
.SH NAME
|
||||
nanorc \- GNU nano's configuration file
|
||||
@@ -96,13 +96,16 @@ Do case-sensitive searches by default.
|
||||
.TP
|
||||
.B set constantshow
|
||||
Constantly display the cursor position in the status bar.
|
||||
(The old form of this option, '\fBset const\fR', is deprecated.)
|
||||
This overrides the option \fBquickblank\fR.
|
||||
.TP
|
||||
.B set cutfromcursor
|
||||
Use cut-from-cursor-to-end-of-line by default, instead of cutting the whole line.
|
||||
(The old form of this option, '\fBset cut\fR', is deprecated.)
|
||||
.TP
|
||||
.B set errorcolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Use this color combination for the status bar when an error message is displayed.
|
||||
See \fBset titlecolor\fR for valid color names.
|
||||
.TP
|
||||
.B set fill \fInumber\fR
|
||||
Hard-wrap lines at column number \fInumber\fR. If \fInumber\fR is 0 or less,
|
||||
the maximum line length will be the screen width less \fInumber\fP columns.
|
||||
@@ -118,9 +121,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.
|
||||
@@ -181,7 +181,6 @@ directory feature is turned off.
|
||||
.B set positionlog
|
||||
Save the cursor position of files between editing sessions.
|
||||
The cursor position is remembered for the 200 most-recently edited files.
|
||||
(The old form of this option, '\fBset poslog\fR', is deprecated.)
|
||||
.TP
|
||||
.B set preserve
|
||||
Preserve the XON and XOFF keys (^Q and ^S).
|
||||
@@ -269,6 +268,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.
|
||||
@@ -392,16 +395,26 @@ slightly improve a syntax defined in one of the system-installed
|
||||
files (which normally are not writable).
|
||||
|
||||
.SH REBINDING KEYS
|
||||
Key bindings can be changed via the following two commands:
|
||||
Key bindings can be changed via the following three commands:
|
||||
.RS 3
|
||||
.TP
|
||||
.BI bind " key function menu"
|
||||
Rebinds the key \fIkey\fP to a new function named \fIfunction\fP in the
|
||||
context of menu \fImenu\fP (or in all menus where the function exists
|
||||
by using \fBall\fP).
|
||||
.TP
|
||||
.BI bind " key " """" string """" " menu"
|
||||
Makes the given \fIkey\fR produce the given \fIstring\fR in the given
|
||||
\fImenu\fR (or in all menus where the key exists when \fBall\fR is used).
|
||||
The \fIstring\fR can consist of text or commands or a mix of them.
|
||||
(To enter a command into the \fIstring\fR, precede its keystroke
|
||||
with \fBM-V\fR.)
|
||||
|
||||
.TP
|
||||
.BI unbind " key menu"
|
||||
Unbinds the key \fIkey\fP from the menu named \fImenu\fP (or from all
|
||||
menus where it exists by using \fBall\fP).
|
||||
.RE
|
||||
|
||||
.TP
|
||||
The format of \fIkey\fP should be one of:
|
||||
@@ -452,7 +465,6 @@ Starts a backward search for text in the current buffer.
|
||||
.TP
|
||||
.B searchagain
|
||||
Repeats the last search command without prompting.
|
||||
(The form 'research' is deprecated.)
|
||||
.TP
|
||||
.B findprevious
|
||||
As \fBsearchagain\fR, but always in the backward direction.
|
||||
@@ -487,7 +499,6 @@ Cuts all text from the cursor position till the end of the buffer.
|
||||
.TP
|
||||
.B curpos
|
||||
Shows the current cursor position: the line, column, and character positions.
|
||||
(The form 'cursorpos' is deprecated.)
|
||||
.TP
|
||||
.B wordcount
|
||||
Counts the number of words, lines and characters in the current buffer.
|
||||
@@ -578,9 +589,6 @@ Goes to the last line of the file.
|
||||
Goes to a specific line (and column if specified). Negative numbers count
|
||||
from the end of the file (and end of the line).
|
||||
.TP
|
||||
.B gototext
|
||||
Switches from targeting a line number to searching for text.
|
||||
.TP
|
||||
.B findbracket
|
||||
Moves the cursor to the bracket (brace, parenthesis, etc.) that matches
|
||||
(pairs) with the one under the cursor.
|
||||
@@ -631,7 +639,6 @@ Toggles case sensitivity in searching (search/replace menus only).
|
||||
.TP
|
||||
.B regexp
|
||||
Toggles whether searching/replacing is based on literal strings or regular expressions.
|
||||
(The form 'regex' is deprecated.)
|
||||
.TP
|
||||
.B backwards
|
||||
Toggles whether searching/replacing goes forward or backward.
|
||||
@@ -644,7 +651,10 @@ Shows the next history entry in the prompt menus (e.g. search).
|
||||
.TP
|
||||
.B flipreplace
|
||||
Toggles between searching for something and replacing something.
|
||||
(The form 'dontreplace' is deprecated.)
|
||||
.TP
|
||||
.B flipgoto
|
||||
Toggles between searching for text and targeting a line number.
|
||||
(The form 'gototext' is deprecated.)
|
||||
.TP
|
||||
.B flipexecute
|
||||
Toggles between inserting a file and executing a command.
|
||||
@@ -652,7 +662,6 @@ Toggles between inserting a file and executing a command.
|
||||
.B flipnewbuffer
|
||||
Toggles between inserting into the current buffer and into a new
|
||||
empty buffer.
|
||||
(The form 'newbuffer' is deprecated.)
|
||||
.TP
|
||||
.B dosformat
|
||||
When writing a file, switches to writing a DOS format (CR/LF).
|
||||
@@ -756,7 +765,6 @@ The 'search to replace' menu.
|
||||
.TP
|
||||
.B replacewith
|
||||
The 'replace with' menu, which comes up after 'search to replace'.
|
||||
(The form 'replace2' is deprecated.)
|
||||
.TP
|
||||
.B gotoline
|
||||
The 'goto line (and column)' menu.
|
||||
|
||||
@@ -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.4" "March 2018"
|
||||
|
||||
.SH NAME
|
||||
rnano \- a restricted nano
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -196,17 +196,19 @@
|
||||
# set wordchars "<_>."
|
||||
|
||||
|
||||
## Paint the interface elements of nano.
|
||||
## These are examples; by default there are no colors.
|
||||
## Paint the interface elements of nano. These are examples;
|
||||
## by default there are no colors, except for errorcolor.
|
||||
# set titlecolor brightwhite,blue
|
||||
# set statuscolor brightwhite,green
|
||||
# set errorcolor brightwhite,red
|
||||
# set selectedcolor brightwhite,magenta
|
||||
# set numbercolor cyan
|
||||
# set keycolor cyan
|
||||
# set functioncolor green
|
||||
## In root's .nanorc you might want to use:
|
||||
# set titlecolor brightwhite,red
|
||||
# set statuscolor brightwhite,red
|
||||
# set titlecolor brightwhite,magenta
|
||||
# set statuscolor brightwhite,magenta
|
||||
# set errorcolor brightwhite,red
|
||||
# set selectedcolor brightwhite,cyan
|
||||
# set numbercolor magenta
|
||||
# set keycolor brightmagenta
|
||||
|
||||
@@ -10,7 +10,7 @@ Summary : a user-friendly editor, a Pico clone with enhancements
|
||||
License : GPLv3+
|
||||
Group : Applications/Editors
|
||||
URL : https://nano-editor.org/
|
||||
Source : https://nano-editor.org/dist/v2.6/%{name}-%{version}.tar.gz
|
||||
Source : https://nano-editor.org/dist/latest/%{name}-%{version}.tar.gz
|
||||
|
||||
BuildRoot : %{_tmppath}/%{name}-%{version}-root
|
||||
BuildRequires : autoconf, automake, gettext-devel, ncurses-devel, texinfo
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# List of available languages.
|
||||
bg ca cs da de eo es eu fi fr ga gl hr hu id it ja ms nb nl nn pl pt_BR ro ru sl sr sv tr uk vi zh_CN zh_TW
|
||||
bg ca cs da de eo es eu fi fr ga gl hr hu id it ja ms nb nl nn pl pt pt_BR ro ru sl sr sv tr uk vi zh_CN zh_TW
|
||||
|
||||
1193
po/nano.pot
1193
po/nano.pot
File diff suppressed because it is too large
Load Diff
1186
po/pt_BR.po
1186
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1120
po/zh_CN.po
1120
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1120
po/zh_TW.po
1120
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
1146
src/browser.c
1146
src/browser.c
File diff suppressed because it is too large
Load Diff
764
src/chars.c
764
src/chars.c
File diff suppressed because it is too large
Load Diff
578
src/color.c
578
src/color.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* color.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2001-2011, 2013-2018 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -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;
|
||||
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++) {
|
||||
colortype *combo = color_combo[i];
|
||||
|
||||
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 (combo != NULL) {
|
||||
if (combo->fg == -1 && !using_defaults)
|
||||
combo->fg = COLOR_WHITE;
|
||||
if (combo->bg == -1 && !using_defaults)
|
||||
combo->bg = COLOR_BLACK;
|
||||
init_pair(i + 1, combo->fg, combo->bg);
|
||||
interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BANDAID |
|
||||
(combo->bright ? A_BOLD : A_NORMAL);
|
||||
} else {
|
||||
if (i == FUNCTION_TAG)
|
||||
interface_color_pair[i] = A_NORMAL;
|
||||
else if (i == ERROR_MESSAGE) {
|
||||
init_pair(i + 1, COLOR_WHITE, COLOR_RED);
|
||||
interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BOLD | A_BANDAID;
|
||||
} else
|
||||
interface_color_pair[i] = hilite_attribute;
|
||||
}
|
||||
|
||||
free(color_combo[i]);
|
||||
}
|
||||
|
||||
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 = 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;
|
||||
char *afterstart;
|
||||
|
||||
/* 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);
|
||||
afterstart = line->data + (astart ? startmatch.rm_eo : 0);
|
||||
anend = (regexec(ink->end, afterstart, 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 */
|
||||
|
||||
302
src/cut.c
302
src/cut.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* cut.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2018 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014 Mark Majeres *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* *
|
||||
@@ -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,82 @@ 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;
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
refresh_needed = TRUE;
|
||||
|
||||
#ifdef DEBUG
|
||||
dump_filestruct(cutbuffer);
|
||||
dump_filestruct(cutbuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -201,11 +197,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 +211,75 @@ 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;
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
dump_filestruct_reverse();
|
||||
#endif
|
||||
set_modified();
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
3789
src/files.c
3789
src/files.c
File diff suppressed because it is too large
Load Diff
2376
src/global.c
2376
src/global.c
File diff suppressed because it is too large
Load Diff
952
src/help.c
952
src/help.c
File diff suppressed because it is too large
Load Diff
800
src/history.c
800
src/history.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* history.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2003-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2003-2011, 2013-2018 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -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 */
|
||||
|
||||
670
src/move.c
670
src/move.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* move.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2018 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
3405
src/nano.c
3405
src/nano.c
File diff suppressed because it is too large
Load Diff
633
src/nano.h
633
src/nano.h
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* nano.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2018 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -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,421 @@
|
||||
|
||||
/* 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;
|
||||
|
||||
/* The kinds of undo actions. ADD...REPLACE must come first. */
|
||||
typedef enum {
|
||||
ADD, DEL, BACK, CUT, CUT_TO_EOF, REPLACE,
|
||||
ADD, ENTER, BACK, DEL, JOIN, 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
|
||||
CUT, CUT_TO_EOF, PASTE, INSERT, 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 (*func)(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. */
|
||||
#ifdef ENABLE_NANORC
|
||||
char *expansion;
|
||||
/* The string of keycodes to which this shortcut is expanded. */
|
||||
#endif
|
||||
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 (*func)(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,
|
||||
ERROR_MESSAGE,
|
||||
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 +595,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 +611,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. */
|
||||
|
||||
1040
src/prompt.c
1040
src/prompt.c
File diff suppressed because it is too large
Load Diff
82
src/proto.h
82
src/proto.h
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* proto.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2018 Free Software Foundation, Inc. *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -30,7 +30,7 @@ extern volatile sig_atomic_t the_window_resized;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
extern bool console;
|
||||
extern bool on_a_vt;
|
||||
#endif
|
||||
|
||||
extern bool meta_key;
|
||||
@@ -54,6 +54,8 @@ extern char *title;
|
||||
|
||||
extern bool more_than_one;
|
||||
|
||||
extern bool also_the_last;
|
||||
|
||||
extern int didfind;
|
||||
|
||||
extern int controlleft;
|
||||
@@ -170,7 +172,7 @@ extern regmatch_t regmatches[10];
|
||||
|
||||
extern int hilite_attribute;
|
||||
#ifdef ENABLE_COLOR
|
||||
extern char* specified_color_combo[NUMBER_OF_ELEMENTS];
|
||||
extern colortype *color_combo[NUMBER_OF_ELEMENTS];
|
||||
#endif
|
||||
extern int interface_color_pair[NUMBER_OF_ELEMENTS];
|
||||
|
||||
@@ -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
|
||||
@@ -403,12 +404,12 @@ void unlink_node(filestruct *fileptr);
|
||||
void delete_node(filestruct *fileptr);
|
||||
filestruct *copy_filestruct(const filestruct *src);
|
||||
void free_filestruct(filestruct *src);
|
||||
void renumber(filestruct *fileptr);
|
||||
void renumber(filestruct *line);
|
||||
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);
|
||||
@@ -441,17 +442,10 @@ void enable_flow_control(void);
|
||||
void terminal_init(void);
|
||||
void unbound_key(int code);
|
||||
int do_input(bool allow_funcs);
|
||||
#ifdef ENABLE_MOUSE
|
||||
int do_mouse(void);
|
||||
#endif
|
||||
void do_output(char *output, size_t output_len, bool allow_cntrls);
|
||||
|
||||
/* Most functions in prompt.c. */
|
||||
#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 +464,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 +482,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 +493,12 @@ 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 ask_for_replacement(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 +587,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 +604,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,15 +614,17 @@ 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. */
|
||||
void record_macro(void);
|
||||
void run_macro(void);
|
||||
void get_key_buffer(WINDOW *win);
|
||||
size_t get_key_buffer_len(void);
|
||||
void put_back(int keycode);
|
||||
void unget_kbinput(int kbinput, bool metakey);
|
||||
#ifdef ENABLE_NANORC
|
||||
void implant(const char *string);
|
||||
#endif
|
||||
int get_kbinput(WINDOW *win, bool showcursor);
|
||||
int parse_kbinput(WINDOW *win);
|
||||
int arrow_from_abcd(int kbinput);
|
||||
@@ -636,17 +634,17 @@ int get_control_kbinput(int kbinput);
|
||||
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
|
||||
int *parse_verbatim_kbinput(WINDOW *win, size_t *count);
|
||||
#ifdef ENABLE_MOUSE
|
||||
int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
|
||||
int get_mouseinput(int *mouse_row, int *mouse_col, bool allow_shortcuts);
|
||||
#endif
|
||||
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 +652,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 +664,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);
|
||||
@@ -699,7 +697,7 @@ void case_sens_void(void);
|
||||
void regexp_void(void);
|
||||
void backwards_void(void);
|
||||
void flip_replace(void);
|
||||
void gototext_void(void);
|
||||
void flip_goto(void);
|
||||
#ifdef ENABLE_BROWSER
|
||||
void to_files_void(void);
|
||||
void goto_dir_void(void);
|
||||
|
||||
1757
src/rcfile.c
1757
src/rcfile.c
File diff suppressed because it is too large
Load Diff
1524
src/search.c
1524
src/search.c
File diff suppressed because it is too large
Load Diff
5688
src/text.c
5688
src/text.c
File diff suppressed because it is too large
Load Diff
658
src/utils.c
658
src/utils.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* utils.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2018 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -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 && *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,64 @@ 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);
|
||||
#ifndef NANO_TINY
|
||||
if (src == dest)
|
||||
fprintf(stderr, "\r*** Copying a string to itself -- please report a bug ***");
|
||||
#endif
|
||||
dest = charealloc(dest, 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 +409,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 */
|
||||
|
||||
5321
src/winio.c
5321
src/winio.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
## Here is an example for assembler.
|
||||
|
||||
syntax "asm" "\.(S|s|asm)$"
|
||||
syntax asm "\.(S|s|asm)$"
|
||||
magic "assembler source"
|
||||
comment "//"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for Autoconf.
|
||||
|
||||
syntax "autoconf" "\.(ac|m4)$"
|
||||
syntax autoconf "\.(ac|m4)$"
|
||||
comment "#"
|
||||
|
||||
# Keywords:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for awk.
|
||||
|
||||
syntax "awk" "\.awk$"
|
||||
syntax awk "\.awk$"
|
||||
magic "awk script"
|
||||
comment "#"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for C/C++.
|
||||
|
||||
syntax "c" "\.(c(c|pp|xx|\+\+)?|C)$" "\.(h(h|pp|xx)?|H)$" "\.ii?$"
|
||||
syntax c "\.(c(c|pp|xx|\+\+)?|C)$" "\.(h(h|pp|xx)?|H)$" "\.ii?$"
|
||||
magic "^(C|C\+\+) (source|program)"
|
||||
comment "//"
|
||||
|
||||
@@ -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:]]+$"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Colouring for Changelogs.
|
||||
|
||||
syntax "changelog" "Change[Ll]og.*"
|
||||
syntax changelog "Change[Ll]og.*"
|
||||
|
||||
# Author lines.
|
||||
color green "^(19|20).*$"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
## Syntax highlighting for CMake files.
|
||||
|
||||
syntax "cmake" "(CMakeLists\.txt|\.cmake)$"
|
||||
syntax cmake "(CMakeLists\.txt|\.cmake)$"
|
||||
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)?)\>"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for CSS files.
|
||||
|
||||
syntax "css" "\.css$"
|
||||
syntax css "\.css$"
|
||||
comment "/*|*/"
|
||||
|
||||
color brightred "."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for apt's sources.list.
|
||||
|
||||
syntax "sources.list" "sources\.list(~|\.old|\.save)?$" "sources\.list\.d/.*\.list(~|\.old|\.save)?$"
|
||||
syntax sources.list "sources\.list(~|\.old|\.save)?$" "sources\.list\.d/.*\.list(~|\.old|\.save)?$"
|
||||
comment "#"
|
||||
|
||||
# Coloring the deb lines, working from tail to head. First the
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## An example of a default syntax. The default syntax is used for
|
||||
## files that do not match any other syntax.
|
||||
|
||||
syntax "default"
|
||||
syntax default
|
||||
comment "#"
|
||||
|
||||
# Comments.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for Emacs Lisp.
|
||||
|
||||
syntax "elisp" "\.el$"
|
||||
syntax elisp "\.el$"
|
||||
magic "Lisp/Scheme program"
|
||||
comment ";"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for Fortran 90/95.
|
||||
|
||||
syntax "fortran" "\.(f|f90|f95)$"
|
||||
syntax fortran "\.(f|f90|f95)$"
|
||||
comment "!"
|
||||
|
||||
color red "\<[0-9]+\>"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Here is an example for Gentoo ebuilds/eclasses,
|
||||
## and (further down) one for Portage control files.
|
||||
|
||||
syntax "ebuild" "\.e(build|class|blit)$"
|
||||
syntax ebuild "\.e(build|class|blit)$"
|
||||
comment "#"
|
||||
|
||||
## All the standard portage functions:
|
||||
@@ -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\>"
|
||||
@@ -48,7 +48,7 @@ color ,green "[[:space:]]+$"
|
||||
color ,green " "
|
||||
|
||||
|
||||
syntax "/etc/portage" "\.(accept_keywords|env|keywords|mask|unmask|use)(/.+)?$"
|
||||
syntax /etc/portage "\.(accept_keywords|env|keywords|mask|unmask|use)(/.+)?$"
|
||||
comment "#"
|
||||
|
||||
## Base text:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for Go.
|
||||
|
||||
syntax "go" "\.go$"
|
||||
syntax go "\.go$"
|
||||
comment "//"
|
||||
|
||||
# Set up a formatter since spelling is probably useless...
|
||||
@@ -24,13 +24,11 @@ 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 "\<([1-9][0-9]*|0[0-7]*|0[xX][0-9A-Fa-f]+)\>"
|
||||
color red "\<[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?i?\>"
|
||||
color red "\<[0-9]+[eE][+-]?[0-9]+i?\>"
|
||||
color red "\B\.[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]+\>"
|
||||
|
||||
# Strings and characters; slightly fuzzy.
|
||||
color red "\<(true|false|nil|iota|_)\>"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for groff.
|
||||
|
||||
syntax "groff" "\.m[ems]$" "\.rof" "\.tmac$" "^tmac."
|
||||
syntax groff "\.m[ems]$" "\.rof" "\.tmac$" "^tmac."
|
||||
comment ".\""
|
||||
|
||||
# The argument of .ds or .nr
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for Guile Scheme.
|
||||
|
||||
syntax "guile" "\.scm$"
|
||||
syntax guile "\.scm$"
|
||||
header "^#!.*guile"
|
||||
comment ";"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for HTML.
|
||||
|
||||
syntax "html" "\.html?$"
|
||||
syntax html "\.html?$"
|
||||
magic "HTML document"
|
||||
comment "<!--|-->"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for Java.
|
||||
|
||||
syntax "java" "\.java$"
|
||||
syntax java "\.java$"
|
||||
magic "Java "
|
||||
comment "//"
|
||||
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
## Here is an example for Javascript.
|
||||
## Syntax highlighting for Javascript.
|
||||
|
||||
syntax "javascript" "\.js$"
|
||||
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.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Original author: Aapo Rantalainen
|
||||
# License: GPLv3 or newer
|
||||
|
||||
syntax "json" "\.json$"
|
||||
syntax json "\.json$"
|
||||
# No comments are permitted in JSON.
|
||||
comment ""
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
## 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$"
|
||||
syntax lua "\.lua$"
|
||||
magic "Lua script"
|
||||
comment "--"
|
||||
|
||||
@@ -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|local|metatable|(up|user)value)|getinfo|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 ""(\\.|[^"\])*"|'(\\.|[^'\])*'"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for Makefiles.
|
||||
|
||||
syntax "makefile" "Makefile[^/]*$" "\.(make|mk)$"
|
||||
syntax makefile "Makefile[^/]*$" "\.(make|mk)$"
|
||||
magic "makefile script"
|
||||
comment "#"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for manpages.
|
||||
|
||||
syntax "man" "\.[1-9]x?$"
|
||||
syntax man "\.[1-9]x?$"
|
||||
magic "troff or preprocessor input"
|
||||
comment ".\""
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for Magicpoint presentations.
|
||||
|
||||
syntax "mgp" "\.mgp$"
|
||||
syntax mgp "\.mgp$"
|
||||
header "^%include.*"
|
||||
comment "#"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for quoted emails (under e.g. mutt).
|
||||
|
||||
syntax "mutt"
|
||||
syntax mutt
|
||||
|
||||
# Quoted lines.
|
||||
color green "^>.*"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
## This is meant for highlighting key combos in a nano help text.
|
||||
|
||||
# It should not apply to any normal file, so no fileregex.
|
||||
syntax "nanohelp"
|
||||
syntax nanohelp
|
||||
|
||||
# Key combos:
|
||||
color cyan "\^[]4-8A-Z^\_◀▶▲▼]" "[◀▶▲▼]" "(\^|M-)Space" "\<M-." "\<F1?[0-9]"
|
||||
color cyan "\<(Tab|Enter|Ins|Del|Bsp|Up|Down|Left|Right|Home|End|PgUp|PgDn)\>"
|
||||
color cyan "\<(Tab|Sh-Tab|Enter|Ins|Del|Bsp|Up|Down|Left|Right|Home|End|PgUp|PgDn)\>"
|
||||
|
||||
# Quoted indicators:
|
||||
color brightred "'(\^|M-)'"
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
## Here is an example for nanorc files.
|
||||
|
||||
syntax "nanorc" "\.?nanorc$"
|
||||
syntax nanorc "\.?nanorc$"
|
||||
comment "#"
|
||||
|
||||
# Possible errors and parameters
|
||||
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 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:]]*$)"
|
||||
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:]]+((error|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|errorcolor|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:]]*$)"
|
||||
icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
|
||||
icolor brightgreen "^[[:space:]]*extendsyntax[[:space:]]+[[:alpha:]]+[[:space:]]+(i?color|header|magic|comment|linter|formatter)[[:space:]]+.*$"
|
||||
icolor brightgreen "^[[:space:]]*(linter|formatter)[[:space:]]+[[:alpha:]]+"
|
||||
icolor brightgreen "^[[:space:]]*(syntax|linter|formatter)[[:space:]]+[^[:blank:]]+"
|
||||
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:]]*##.*$"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for nftables.
|
||||
|
||||
syntax "nftables" "\.(nft|nftables)$"
|
||||
syntax nftables "\.(nft|nftables)$"
|
||||
header "^#!.*(nft|nftables)"
|
||||
comment "#"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for C/C++/Obj-C.
|
||||
|
||||
syntax "m" "\.m$"
|
||||
syntax m "\.m$"
|
||||
magic "Objective-C source"
|
||||
comment "//"
|
||||
|
||||
@@ -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)__"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Syntax highlighting for OCaml.
|
||||
|
||||
syntax "ocaml" "\.mli?$"
|
||||
syntax ocaml "\.mli?$"
|
||||
magic "OCaml"
|
||||
comment "(*|*)"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Here is an example for patch files.
|
||||
|
||||
syntax "patch" "\.(patch|diff|debdiff)$"
|
||||
syntax patch "\.(patch|diff|debdiff)$"
|
||||
magic "diff output"
|
||||
# There is no official support for comments in patch files.
|
||||
comment ""
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user