Compare commits
219 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
758b4e66db | ||
|
|
a09eedf0a3 | ||
|
|
1a7ceb8774 | ||
|
|
69fcb001ea | ||
|
|
59451da3ac | ||
|
|
a850bb2513 | ||
|
|
047cf9be9c | ||
|
|
97896d30f1 | ||
|
|
fc367a32eb | ||
|
|
5e10528759 | ||
|
|
243380c4a2 | ||
|
|
49fb755cfc | ||
|
|
24a64d37dd | ||
|
|
a56a881c4b | ||
|
|
633343de24 | ||
|
|
5fcda555ea | ||
|
|
873f99d96a | ||
|
|
b38b020d18 | ||
|
|
54a92614b2 | ||
|
|
86e71fa09d | ||
|
|
5237a42d65 | ||
|
|
46ccc9ba6a | ||
|
|
e09dbf18b1 | ||
|
|
f08d169aa1 | ||
|
|
cf14ee2ef3 | ||
|
|
8555820afc | ||
|
|
e7bdfebdf4 | ||
|
|
4bbbb1859b | ||
|
|
6645351bfc | ||
|
|
a5981ab043 | ||
|
|
807f5c2e69 | ||
|
|
1b2a091de9 | ||
|
|
bd770ea2e7 | ||
|
|
c3de3ece32 | ||
|
|
8b86af3fef | ||
|
|
21a5978027 | ||
|
|
b4fd08fa5e | ||
|
|
252dc138a2 | ||
|
|
de57d8b722 | ||
|
|
dbbe267d71 | ||
|
|
eed0090e32 | ||
|
|
52e2e52db3 | ||
|
|
3f0e42c13b | ||
|
|
d8e5799e84 | ||
|
|
0f4716e168 | ||
|
|
749b1b3d79 | ||
|
|
566a2daf12 | ||
|
|
9f6c3a6269 | ||
|
|
6273768797 | ||
|
|
4562401505 | ||
|
|
1cc030f7c1 | ||
|
|
65d1655134 | ||
|
|
8e779b6e85 | ||
|
|
3ab943c49a | ||
|
|
ec20e3a7a8 | ||
|
|
dd88842d5a | ||
|
|
751e7f0fbe | ||
|
|
ee3254b614 | ||
|
|
938aa63dfa | ||
|
|
06ffcfaf40 | ||
|
|
f2317cc64e | ||
|
|
b281fd7a9d | ||
|
|
7e334c95cb | ||
|
|
11072ed587 | ||
|
|
67915f5dae | ||
|
|
884d410d9d | ||
|
|
1c1cbae6bc | ||
|
|
276ab2c85e | ||
|
|
80686bb525 | ||
|
|
969e99bc85 | ||
|
|
94b484ea97 | ||
|
|
ac2c81fad1 | ||
|
|
829a1a5050 | ||
|
|
5dcf375f33 | ||
|
|
50379cc4ff | ||
|
|
e2d3ee2364 | ||
|
|
beae2da10d | ||
|
|
79c836b11b | ||
|
|
c24432edc4 | ||
|
|
85bffcfeb9 | ||
|
|
381a386b01 | ||
|
|
6f9bb53b2d | ||
|
|
4d54231967 | ||
|
|
8f2ac1b7f6 | ||
|
|
ee8681d7cc | ||
|
|
a1fba43452 | ||
|
|
0e4cbd4bfd | ||
|
|
ce68f81b2b | ||
|
|
255f5478e4 | ||
|
|
2a7c9b7f62 | ||
|
|
1146381765 | ||
|
|
8b1f283a73 | ||
|
|
43a5c87682 | ||
|
|
e4a69f8b94 | ||
|
|
8b3213cadb | ||
|
|
14c5f03e38 | ||
|
|
1e2d9a697a | ||
|
|
63c428ad08 | ||
|
|
f55b65bd99 | ||
|
|
f4c3670f64 | ||
|
|
6d121cc81f | ||
|
|
e57b755665 | ||
|
|
fb5478338f | ||
|
|
961294f533 | ||
|
|
46cec27b26 | ||
|
|
baa73d69e3 | ||
|
|
6855b79267 | ||
|
|
934a2192dc | ||
|
|
5df47bfef6 | ||
|
|
fb51d617fd | ||
|
|
7e9799d42b | ||
|
|
d02c1993d8 | ||
|
|
42f5a84c6f | ||
|
|
109ad0915d | ||
|
|
ee52f45b01 | ||
|
|
2367f3d8e6 | ||
|
|
684fc8f84a | ||
|
|
092174dad5 | ||
|
|
78bc8b698c | ||
|
|
d58ef8d579 | ||
|
|
4f3249de56 | ||
|
|
ecc7c26641 | ||
|
|
fbbf501f8f | ||
|
|
ac7a071893 | ||
|
|
09723b07a8 | ||
|
|
dd667ce92c | ||
|
|
482fb352b8 | ||
|
|
8766e7bdcb | ||
|
|
bb4d0d548a | ||
|
|
aa04ad4f83 | ||
|
|
a4c2eaa2e6 | ||
|
|
4d7735c8f9 | ||
|
|
8490f4acab | ||
|
|
e375995d98 | ||
|
|
35f6a1767a | ||
|
|
5bc4abeefe | ||
|
|
ac726f08fa | ||
|
|
30986db708 | ||
|
|
1439016c20 | ||
|
|
79971a309f | ||
|
|
a7901dd1e0 | ||
|
|
1695463347 | ||
|
|
f46544f67b | ||
|
|
9462ba8217 | ||
|
|
23f5515fbb | ||
|
|
747310562c | ||
|
|
1ae97076cd | ||
|
|
09f516a58b | ||
|
|
025232b25b | ||
|
|
7c41c8641f | ||
|
|
6295cca03b | ||
|
|
1c05090a4a | ||
|
|
14bd52ced8 | ||
|
|
7d46eff738 | ||
|
|
84b6525914 | ||
|
|
2abe7c03fe | ||
|
|
bf72cdd814 | ||
|
|
8e3f40155c | ||
|
|
4239e5fe1a | ||
|
|
d1ee41f319 | ||
|
|
b93767b54f | ||
|
|
8fbf10428c | ||
|
|
3719d8e208 | ||
|
|
50cbde8b23 | ||
|
|
9ffd3c0222 | ||
|
|
2704b3874b | ||
|
|
139f9c2fe5 | ||
|
|
580fa53aba | ||
|
|
2380ee20c5 | ||
|
|
c0a52372f1 | ||
|
|
fd8ce7af8e | ||
|
|
c5a0c9b6b2 | ||
|
|
6520aa0079 | ||
|
|
3d8b9895b8 | ||
|
|
9026e04c73 | ||
|
|
92befae93d | ||
|
|
dbbc14e0ac | ||
|
|
8b80ec3e1a | ||
|
|
a71a2f9a0c | ||
|
|
56ce5f2ba8 | ||
|
|
5ebdd3fe6e | ||
|
|
426e6d37c5 | ||
|
|
4dd9aadf8a | ||
|
|
5ecd81bd19 | ||
|
|
b4a955512e | ||
|
|
33c7a4ca95 | ||
|
|
40d34862fd | ||
|
|
bee670424e | ||
|
|
8dffb00fd9 | ||
|
|
403e87c0a0 | ||
|
|
942bb39547 | ||
|
|
52b7a41ea4 | ||
|
|
6807e06a74 | ||
|
|
84cd0abd6f | ||
|
|
6a70d2b6e2 | ||
|
|
16482f99b8 | ||
|
|
621eb904b3 | ||
|
|
84ff9ebb91 | ||
|
|
a2038a9b2b | ||
|
|
a969adf804 | ||
|
|
59b0f81bfa | ||
|
|
6ad3d3d6c0 | ||
|
|
ca70885564 | ||
|
|
cfa20c3f42 | ||
|
|
4781d4d351 | ||
|
|
ef1a3b08ae | ||
|
|
4063fce6a0 | ||
|
|
3db2beefd3 | ||
|
|
5907f8801b | ||
|
|
c68398f18f | ||
|
|
d653aeab93 | ||
|
|
491e02f532 | ||
|
|
f1a47a2aae | ||
|
|
7b23878b42 | ||
|
|
5cdadc3eb1 | ||
|
|
8f89e23adb | ||
|
|
8302ff700b | ||
|
|
a32d21c759 | ||
|
|
f8214440c2 |
244
ChangeLog
244
ChangeLog
@@ -1,3 +1,247 @@
|
||||
Changes between v2.8.6 and v2.8.7:
|
||||
----------------------------------
|
||||
|
||||
Benno Schulenberg (54):
|
||||
bindings: hard-bind Alt+Up and Alt+Down to findprevious and findnext
|
||||
browser: correct the inverted search behavior for Alt+Up/Alt+Down
|
||||
bump version numbers and add a news item for the 2.8.7 release
|
||||
display: catch all cases where the cursor can be pushed offscreen
|
||||
display: don't doubly show tabs that cross a chunk boundary
|
||||
files: do not silently ignore an invalid backup directory, but die
|
||||
files: don't close a file descriptor when opening failed [coverity scan]
|
||||
files: don't try to open a negative file descriptor [coverity scan]
|
||||
gnulib: update to its current upstream state
|
||||
linting: don't try to put the cursor at a negative x position
|
||||
linting: skip the introductory message produced by 'gcc -fshow-column'
|
||||
mouse: one click of the wheel should move three lines, not three pages
|
||||
moving: don't push x forward when backward movement lands on a split tab
|
||||
moving: get <Up> unstuck when trying to pass over a sprawling tab
|
||||
moving: improve retention of the target column somewhat
|
||||
moving: the current chunk is always 0 when not in softwrap mode
|
||||
moving: use the correct formula for pushing the index forward
|
||||
rcfile: don't leak a shortcut when something goes wrong [coverity scan]
|
||||
softwrap: properly move up and down over tabs that are split over rows
|
||||
syntax: c: give labels some color too
|
||||
syntax: html: don't bother coloring tags that cross line boundaries
|
||||
syntax: python: don't require a character after an opening triple quote
|
||||
text: properly unindent lines that consist of only whitespace
|
||||
tweaks: a comma does not end a sentence, and is not part of a variable
|
||||
tweaks: adjust the indentation after the previous change
|
||||
tweaks: adjust the indentation after the previous change
|
||||
tweaks: adjust the indentation after the previous change
|
||||
tweaks: allow enough space for the Y/N/A characters [coverity scan]
|
||||
tweaks: avoid trying to stat a file that might be NULL [coverity scan]
|
||||
tweaks: close a file also in the error path [coverity scan]
|
||||
tweaks: condense or improve some comments
|
||||
tweaks: condense some logic, to elide a variable and a comment
|
||||
tweaks: do not leak the indentation when all lines are empty
|
||||
tweaks: don't close a descriptor when its stream has already been closed
|
||||
tweaks: drop some debugging stuff
|
||||
tweaks: drop some debugging stuff, and frob two comments
|
||||
tweaks: elide an unneeded pointer
|
||||
tweaks: elide the global variable 'full_operating_dir'
|
||||
tweaks: fix compilation with --enable-{tiny,help,multibuffer}
|
||||
tweaks: group all movement routines in corresponding pairs
|
||||
tweaks: keep the const qualifier of the syntax name [coverity scan]
|
||||
tweaks: remove includes that appear to be superfluous
|
||||
tweaks: rename a function, to let it make more sense
|
||||
tweaks: rename a label, to better match its task
|
||||
tweaks: renumber the special key codes, to be in sequence and grouped
|
||||
tweaks: reshuffle code and frob comments, to reduce the number of lines
|
||||
tweaks: reshuffle some code to harmonize two related functions
|
||||
tweaks: reshuffle some declarations and trim a few comments
|
||||
tweaks: restore an include that is necessary on some platforms
|
||||
tweaks: show "where is next" in the help lines of the file browser
|
||||
tweaks: simply set the proper scrolling mode, instead of imitating it
|
||||
tweaks: snip a superfluous clearing of the bottom bars after help
|
||||
tweaks: sort the includes, so it's a little easier to see what is there
|
||||
tweaks: specify more directly in what manner to move the viewport
|
||||
|
||||
David Lawrence Ramsey (23):
|
||||
browser: allow backward/forward re-searches with Alt+Up/Alt+Down
|
||||
display: constrain line numbers on softwrapped lines with sprawling tabs
|
||||
display: do show the visible character for a tab when it starts a row
|
||||
display: revamp how screen updates are done in the movement code
|
||||
moving: redraw not just the new current line but also the prior one
|
||||
small addition: allow customizing the color of selected text
|
||||
softwrap: correctly move vertically through overwide tabs
|
||||
softwrap: don't push a straddling tab to the next chunk
|
||||
softwrap: improve left/right navigation across line boundaries
|
||||
softwrap: make sure char_len is set when a tab is wider than a chunk
|
||||
softwrap: properly update the viewport when adding text at firstcolumn
|
||||
text: make indenting add to the beginning of the line
|
||||
text: make unindenting remove from the beginning of the line
|
||||
tweaks: adjust spacing and wording in sample.nanorc
|
||||
tweaks: correct a comment typo and an indentation error
|
||||
tweaks: harmonize some prototypes with their functions
|
||||
tweaks: remove unneeded parentheses and blank line and braces
|
||||
tweaks: replace a misplaced tab with a space
|
||||
tweaks: set the target row for smooth scrolling more directly
|
||||
tweaks: use charalloc() instead of (char *)nmalloc() * sizeof(char)
|
||||
weeding: drop the forreal parameter from place_the_cursor()
|
||||
weeding: remove redundant casts of nmalloc()
|
||||
weeding: remove the unused be_clever parameter from do_home()/do_end()
|
||||
|
||||
Rishabh Dave (1):
|
||||
new feature: allow pasting at all input prompts
|
||||
|
||||
Urja Rannikko (1):
|
||||
bindings: hard-bind Alt+Left and Alt+Right to buffer switching
|
||||
|
||||
|
||||
Changes between v2.8.5 and v2.8.6:
|
||||
----------------------------------
|
||||
|
||||
Benno Schulenberg (58):
|
||||
build: for Solaris, tell the linker to use a threading lib
|
||||
bump version numbers and add a news item for the 2.8.6 release
|
||||
display: avoid a jumpy cursor by redrawing bottom bars only when needed
|
||||
display: when back in the main loop, always redraw the help lines
|
||||
display: wipe stale messages from the status bar straightaway
|
||||
docs: add some more mark-up to the Info document
|
||||
docs: be more precise about when a dash is given instead of a filename
|
||||
docs: drop the cluttering Info-style links from the HTML manual
|
||||
docs: improve cross references and mark-up in the Info document
|
||||
docs: improve some spacing, especially of the synopsis in the PDF
|
||||
docs: make the guillemot and the middle dot appear correctly in HTML
|
||||
docs: move the descriptions of 'header' and 'magic' next to 'syntax'
|
||||
docs: remove the mention of backslashes for the argument of 'comment'
|
||||
docs: reword the explanation of the 'syntax' command
|
||||
docs: use real cross references in the Info document
|
||||
docs: use the @command and @option mark-up more consistently
|
||||
files: don't bother counting rows when opening a fresh buffer
|
||||
files: warn more conspicuously when the file on disk has changed
|
||||
gnulib: update to its current state
|
||||
input: recognize the Ctrl+Arrow key sequences from Haiku's Terminal
|
||||
options: recognize -a and --atblanks on the command line
|
||||
options: rename --cut to --cutfromcursor, to be clearer
|
||||
pasting: restore the cap on the number of chunks to move backward
|
||||
rcfile: don't require backslashing in the argument of 'comment'
|
||||
screen: defeat a VTE/Konsole bug also for the case of --constantshow
|
||||
screen: retain the same help-line tags when the window is resized
|
||||
softwrap: when possible, go back a whole bunch of chunks at a time
|
||||
startup: don't try parsing color names that were not specified
|
||||
startup: in default mode, display the tail of the file as Pico does
|
||||
suspension: prevent entering an invalid byte upon resume (with S-Lang)
|
||||
syntax: gentoo: make it clearer that the file contains two syntaxes
|
||||
syntax: man, groff: fix the string that introduces a comment
|
||||
syntax: nanorc: don't color numeric arguments specially
|
||||
syntax: nanorc: don't color the argument of 'linter' as if invalid
|
||||
syntax: texinfo: cover also some special cases like @U, @OE and @TeX
|
||||
tweaks: adjust an error message so it fits all possible cases
|
||||
tweaks: avoid a clang warning about an expression being treated as NULL
|
||||
tweaks: avoid a failure with black diamonds in a PDF
|
||||
tweaks: avoid an unused-variable warning for the tiny version
|
||||
tweaks: chuck some debugging stuff
|
||||
tweaks: chuck two useless asserts, and elide a call to strncasecmp()
|
||||
tweaks: correct two conditions for conditional compilation
|
||||
tweaks: drop a bunch of useless asserts
|
||||
tweaks: elide unneeded calls of get_last_chunk_leftedge()
|
||||
tweaks: fix compilation with --enable-tiny
|
||||
tweaks: move an include to the file that actually makes use of it
|
||||
tweaks: put declarations always first, so it will compile on Haiku
|
||||
tweaks: recognize the empty string as comment inhibitor, instead of NULL
|
||||
tweaks: remove two superfluous includes
|
||||
tweaks: rename a constant, to match the corresponding option
|
||||
tweaks: rename another constant, to be more precise
|
||||
tweaks: rename a variable, to have more contrast
|
||||
tweaks: rename four functions, to be more distinct
|
||||
tweaks: rename two variables, to make a little sense
|
||||
tweaks: reshuffle some things to condense the code
|
||||
tweaks: simplify the parsing of color combinations
|
||||
tweaks: spell an option correctly in NEWS
|
||||
tweaks: swap ^X and ^L in the help lines of the help viewer
|
||||
|
||||
David Lawrence Ramsey (29):
|
||||
display: when converting tabs, don't go beyond the screen width
|
||||
docs: consistently describe the -U/-c and -r/-w overrides
|
||||
docs: mention that boldtext can be overridden also for function tags
|
||||
docs: mention the default values for comment and whitespace directives
|
||||
moving: fix the cursor jumping back and forth with non-smooth paging
|
||||
moving: make vertical movement account for varying chunk width
|
||||
new feature: allow lines to be softwrapped at whitespace
|
||||
replacing: make spotlight() account for varying chunk width
|
||||
softwrap: add new functions for chunks of varying width
|
||||
softwrap: don't flag EOL too early, nor break continuous text too early
|
||||
softwrap: in do_mouse(), keep the cursor before a softwrap breakpoint
|
||||
softwrap: make the changes to actually allow the chunk width to vary
|
||||
softwrap: prepare for allowing the chunk width to vary
|
||||
softwrap: remove unneeded caps on the number of chunks to move
|
||||
syntax: nanorc: properly color a "fill" option with a negative value
|
||||
text: adjust the comments in do_indent() and do_unindent()
|
||||
text: make do_unindent() an exact copy of do_indent()
|
||||
text: make sure commenting is disabled when comment "" was specified
|
||||
text: normalize the indentation in do_indent() and do_unindent()
|
||||
text: remove indent-related code from do_unindent()
|
||||
text: remove the last usage of cols in do_indent() and do_unindent()
|
||||
text: remove unindent-related code from do_indent()
|
||||
text: remove unneeded references to cols from the indentation routines
|
||||
text: update placewewant properly when indenting/unindenting
|
||||
tweaks: correct a parameter type, and correct two empty initializations
|
||||
tweaks: fix a typo in NEWS
|
||||
tweaks: only compensate for a partially-offscreen line in softwrap mode
|
||||
tweaks: remove unneeded braces, and mark empty parameter list as void
|
||||
usage: a dash doesn't have to come first among the filenames
|
||||
|
||||
|
||||
Changes between v2.8.4 and v2.8.5:
|
||||
----------------------------------
|
||||
|
||||
Benno Schulenberg (35):
|
||||
bindings: in the tiny version exclude word jumping from the prompts
|
||||
bump version numbers and add a news item for the 2.8.5 release
|
||||
display: don't let a SIGCONT write anything to the screen
|
||||
display: don't show the cursor while we are busy calculating its position
|
||||
display: redraw title bar and edit window only when needed
|
||||
display: show the cursor position also when searching took a while
|
||||
docs: avoid a double "see" for cross references in the HTML manual
|
||||
docs: spell "title bar" and "status bar" correctly
|
||||
gnulib: update to its current state
|
||||
input: give an appropriate message when there are too many errors
|
||||
startup: allow negative line and column numbers on the command line
|
||||
startup: allow positioning the cursor also when reading standard input
|
||||
startup: always open with the file that was mentioned first
|
||||
startup: don't crash when opening standard input would fail
|
||||
startup: don't mark the buffer as modified when in view mode
|
||||
startup: don't mark the buffer as modified when nothing was read
|
||||
startup: don't try placing the cursor when reading standard input failed
|
||||
startup: don't use position history when reading from standard input
|
||||
suspension: fake a SIGWINCH when coming back out of the background
|
||||
suspension: remove a duplicate setting of the HUP and TERM handler
|
||||
syntax: default: allow leading whitespace before a hash comment
|
||||
tweaks: adjust indentation after preceding changes
|
||||
tweaks: avoid compiler warning about implicit type
|
||||
tweaks: be consistent in the spelling of title bar and status bar
|
||||
tweaks: don't bother calculating the position when we won't show it
|
||||
tweaks: elide a function that should not be a separate one
|
||||
tweaks: elide a variable
|
||||
tweaks: frob a few comments, and elide and #ifndef
|
||||
tweaks: reduce the scope of three variables, and rename them besides
|
||||
tweaks: reduce the scope of two variables, and rename them too
|
||||
tweaks: rename a function and a variable, to better match what they do
|
||||
tweaks: rename a variable, and frob a couple of comments
|
||||
tweaks: rename two functions and a variable, and invert its logic
|
||||
tweaks: reshuffle some stuff, to put related things closer together
|
||||
tweaks: unglobalize the nodelay_mode variable
|
||||
|
||||
|
||||
Changes between v2.8.3 and v2.8.4:
|
||||
----------------------------------
|
||||
|
||||
Benno Schulenberg (11):
|
||||
build: correct the inverted logic for the nanorc man page
|
||||
bump version numbers and add a news item for the 2.8.4 release
|
||||
gnulib: update to its current state
|
||||
syntax: default: color also hash comments and email addresses
|
||||
syntax: php: color "static" again as "function", like it used to be
|
||||
tweaks: adjust the indentation after the preceding change
|
||||
tweaks: avoid an unused-variable warning when using --disable-comment
|
||||
tweaks: do actual screen refreshes in a single call, when possible
|
||||
tweaks: remove the no-op x$disable tests
|
||||
tweaks: reorder three items in the Info document
|
||||
tweaks: reshuffle a few things to reduce duplication
|
||||
|
||||
|
||||
Changes between v2.8.2 and v2.8.3:
|
||||
----------------------------------
|
||||
|
||||
|
||||
@@ -2,10 +2,13 @@ Improvements in GNU nano
|
||||
========================
|
||||
|
||||
Since 2.8.0:
|
||||
- Meta-Up/Meta-Down will search the previous/next occurrence.
|
||||
- ^U pastes the first line of the cutbuffer at a prompt.
|
||||
- Softwrapping can be done at whitespace (with --soft --atblanks).
|
||||
- The ^G help texts have become searchable (with ^W and M-W).
|
||||
- Ctrl+Home and Ctrl+End jump to start and end of file.
|
||||
- In softwrap mode the cursor now moves per visual row instead of per
|
||||
logical line, and the screen will scroll per row.
|
||||
- In softwrap mode the cursor now moves per visual row instead of
|
||||
per logical line, and the screen will scroll per row.
|
||||
|
||||
Since 2.7.0:
|
||||
- The keystroke ^] to complete a fragment to an existing full word.
|
||||
|
||||
43
NEWS
43
NEWS
@@ -1,3 +1,34 @@
|
||||
2017.08.27 - GNU nano 2.8.7 "Fragrance" fixes a lockup when tabs are
|
||||
wider than the screen, makes indenting + unindenting
|
||||
more predictable by retaining relative indentations,
|
||||
allows pasting (^U) at a prompt, allows triple quotes
|
||||
in Python to not be followed by a character, does not
|
||||
scroll three pages on a roll of the mouse wheel, binds
|
||||
Alt+Up and Alt+Down to findprevious and findnext, and
|
||||
fixes some hard-to-describe issues with softwrapping
|
||||
and boundary-crossing tabs. Enjoy.
|
||||
|
||||
2017.07.21 - GNU nano 2.8.6 "Kekulé" offers a new feature: the ability
|
||||
to do softwrapping between words -- at whitespace --
|
||||
instead of always at the edge of the screen. This can
|
||||
be activated with -a or --atblanks or 'set atblanks'
|
||||
together with the softwrap option. This release further
|
||||
fixes a handful of rare display glitches, fixes a build
|
||||
failure on AIX, harmonizes the quoting rules in the rc
|
||||
files, and renames the option 'cut' to 'cutfromcursor'
|
||||
(please update your nanorc files before 2020).
|
||||
|
||||
2017.06.25 - GNU nano 2.8.5 "Farouche" avoids a crash when waking from
|
||||
a suspension that was induced from the outside, allows
|
||||
negative line and column numbers on the command line,
|
||||
avoids some flickering when resizing the screen while
|
||||
in the file browser, opens files in the order they were
|
||||
mentioned on the command line, and does not pretend to
|
||||
have woken from suspension when receiving a SIGCONT.
|
||||
|
||||
2017.05.21 - GNU nano 2.8.4 "Our Version of Events" includes the nanorc
|
||||
man page again.
|
||||
|
||||
2017.05.18 - GNU nano 2.8.3 "Hirsch" fixes a misplacement of the spotlight
|
||||
during interactive replacing, avoids build failures on AIX
|
||||
and Solaris, fixes a crash on Solaris, speeds up backwards
|
||||
@@ -123,7 +154,7 @@
|
||||
input (M-V followed by a six-digit hexadecimal number which
|
||||
must start with 0 or 10), avoids a crash when resizing the
|
||||
window during Verbatim input, doesn't drop a keystroke after
|
||||
having been suspended, and replaces the beginning-of-line
|
||||
having been suspended, and replaces the beginning-of-line
|
||||
anchor (^) just once per line. There are also several tiny
|
||||
improvements in screen rendering and key handling. Come get
|
||||
your hair tousled!
|
||||
@@ -286,7 +317,7 @@
|
||||
many many improvements to the core system, including
|
||||
substantial improvements to the undo/redo code, UTF-8
|
||||
handling, the configure script, and display of shortcuts
|
||||
on very wide terminals, New features include the
|
||||
on very wide terminals. New features include the
|
||||
ability to write to named pipes (--noread), as well as
|
||||
linter support (see the nanorc man page for details). Also
|
||||
included are much improved syntax highlighting code, and
|
||||
@@ -570,7 +601,7 @@
|
||||
compiling on AIX, and a segfault when making the terminal
|
||||
window too small. Rest in Peace Tim and George!
|
||||
|
||||
2008.04.01 - GNU nano 2.1.1 wont get fooled again. This release contains
|
||||
2008.04.01 - GNU nano 2.1.1 won't get fooled again. This release contains
|
||||
fixes for the new user-rebindable keys (in particular
|
||||
bracket match which was mis-bound), and various
|
||||
problems with translations and configure-related
|
||||
@@ -735,7 +766,7 @@
|
||||
focuses mostly on bugfixes, which include better
|
||||
handling of the cursor at the statusbar prompt, support
|
||||
for certain combinations of Shift and keypad keys in
|
||||
both normal and --rebind-keypad mode, a fix for a minor
|
||||
both normal and --rebindkeypad mode, a fix for a minor
|
||||
display problem after some searches, a real fix for a
|
||||
long-standing segfault when displaying overly long
|
||||
lines, and a real fix for nano's not hanging up properly
|
||||
@@ -1263,12 +1294,12 @@
|
||||
|
||||
|
||||
2001.02.19 - Nano 0.9.99pre3 brings a lot of changes! The most important
|
||||
being that nano is now officially a GNU program. Some
|
||||
being that nano is now officially a GNU program. Some
|
||||
changes have been made for GNU compatibility (like in the
|
||||
default list of shortcuts: "^G Get Help" is now listed
|
||||
and "^_ Goto Line" is not). The Yes/No/All keys have
|
||||
finally been internationalized also. All in all, quite
|
||||
a few changes, considering nano is supposed to be in
|
||||
a few changes, considering nano is supposed to be in
|
||||
a code freeze. But there are the usual helping of
|
||||
bugfixes, a nasty bug when cutting text in -k mode and
|
||||
some compatibility issues with older ncurses libraries
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Generate configure & friends for GIT users.
|
||||
|
||||
gnulib_url="git://git.sv.gnu.org/gnulib.git"
|
||||
gnulib_hash="3eee3a1e3c5b8883e0d4934bfc1326ee605cb7c1"
|
||||
gnulib_hash="a1971db1d4fe4430a48475a751602f861812503e"
|
||||
|
||||
modules="
|
||||
futimens
|
||||
|
||||
63
configure.ac
63
configure.ac
@@ -16,7 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
AC_INIT([GNU nano], [2.8.3], [nano-devel@gnu.org], [nano])
|
||||
AC_INIT([GNU nano], [2.8.7], [nano-devel@gnu.org], [nano])
|
||||
AC_CONFIG_SRCDIR([src/nano.c])
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE([1.14])
|
||||
@@ -69,10 +69,8 @@ if test "x$enable_tiny" = xyes; then
|
||||
enable_browser=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_browser" != xyes; then
|
||||
if test "x$enable_browser" != xno; then
|
||||
AC_DEFINE(ENABLE_BROWSER, 1, [Define this to enable the built-in file browser.])
|
||||
fi
|
||||
if test "x$enable_browser" != xno; then
|
||||
AC_DEFINE(ENABLE_BROWSER, 1, [Define this to enable the built-in file browser.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(color,
|
||||
@@ -100,10 +98,8 @@ if test "x$enable_tiny" = xyes; then
|
||||
enable_comment=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_comment" != xyes; then
|
||||
if test "x$enable_comment" != xno; then
|
||||
AC_DEFINE(ENABLE_COMMENT, 1, [Define this to enable the comment/uncomment function.])
|
||||
fi
|
||||
if test "x$enable_comment" != xno; then
|
||||
AC_DEFINE(ENABLE_COMMENT, 1, [Define this to enable the comment/uncomment function.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(extra,
|
||||
@@ -117,7 +113,7 @@ AS_HELP_STRING([--disable-help], [Disable the built-in help texts]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_help" = xyes; then
|
||||
if test "x$enable_multibuffer" != xyes; then
|
||||
AC_MSG_ERROR([--enable-help cannot work without --enable-multibuffer])
|
||||
AC_MSG_ERROR([--enable-help needs --enable-multibuffer to work])
|
||||
fi
|
||||
else
|
||||
enable_help=no
|
||||
@@ -131,10 +127,8 @@ if test "x$enable_multibuffer" = xno; then
|
||||
enable_help=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_help" != xyes; then
|
||||
if test "x$enable_help" != xno; then
|
||||
AC_DEFINE(ENABLE_HELP, 1, [Define this to enable the Ctrl+G help texts.])
|
||||
fi
|
||||
if test "x$enable_help" != xno; then
|
||||
AC_DEFINE(ENABLE_HELP, 1, [Define this to enable the Ctrl+G help texts.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(histories,
|
||||
@@ -159,10 +153,8 @@ if test "x$enable_tiny" = xyes; then
|
||||
enable_linenumbers=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_linenumbers" != xyes; then
|
||||
if test "x$enable_linenumbers" != xno; then
|
||||
AC_DEFINE(ENABLE_LINENUMBERS, 1, [Define this to enable line numbering.])
|
||||
fi
|
||||
if test "x$enable_linenumbers" != xno; then
|
||||
AC_DEFINE(ENABLE_LINENUMBERS, 1, [Define this to enable line numbering.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(mouse,
|
||||
@@ -172,10 +164,8 @@ if test "x$enable_tiny" = xyes; then
|
||||
enable_mouse=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_mouse" != xyes; then
|
||||
if test "x$enable_mouse" != xno; then
|
||||
AC_DEFINE(ENABLE_MOUSE, 1, [Define this to enable mouse support.])
|
||||
fi
|
||||
if test "x$enable_mouse" != xno; then
|
||||
AC_DEFINE(ENABLE_MOUSE, 1, [Define this to enable mouse support.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(multibuffer,
|
||||
@@ -185,10 +175,8 @@ if test "x$enable_tiny" = xyes; then
|
||||
enable_multibuffer=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_multibuffer" != xyes; then
|
||||
if test "x$enable_multibuffer" != xno; then
|
||||
AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.])
|
||||
fi
|
||||
if test "x$enable_multibuffer" != xno; then
|
||||
AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(nanorc,
|
||||
@@ -198,12 +186,9 @@ if test "x$enable_tiny" = xyes; then
|
||||
enable_nanorc=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_nanorc" != xyes; then
|
||||
if test "x$enable_nanorc" != xno; then
|
||||
AC_DEFINE(ENABLE_NANORC, 1, [Define this to enable the use of .nanorc files.])
|
||||
else
|
||||
nanorc_support=yes
|
||||
fi
|
||||
if test "x$enable_nanorc" != xno; then
|
||||
AC_DEFINE(ENABLE_NANORC, 1, [Define this to enable the use of .nanorc files.])
|
||||
nanorc_support=yes
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(operatingdir,
|
||||
@@ -225,10 +210,8 @@ if test "x$enable_tiny" = xyes; then
|
||||
enable_tabcomp=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_tabcomp" != xyes; then
|
||||
if test "x$enable_tabcomp" != xno; then
|
||||
AC_DEFINE(ENABLE_TABCOMP, 1, [Define this to have tab completion for filenames and search strings.])
|
||||
fi
|
||||
if test "x$enable_tabcomp" != xno; then
|
||||
AC_DEFINE(ENABLE_TABCOMP, 1, [Define this to have tab completion for filenames and search strings.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(wordcomp,
|
||||
@@ -240,10 +223,8 @@ if test "x$enable_tiny" = xyes; then
|
||||
enable_wordcomp=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_wordcomp" != xyes; then
|
||||
if test "x$enable_wordcomp" != xno; then
|
||||
AC_DEFINE(ENABLE_WORDCOMPLETION, 1, [Define this to enable the word-completion function.])
|
||||
fi
|
||||
if test "x$enable_wordcomp" != xno; then
|
||||
AC_DEFINE(ENABLE_WORDCOMPLETION, 1, [Define this to enable the word-completion function.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(wrapping,
|
||||
@@ -275,7 +256,7 @@ if test "x$enable_tiny" = xyes; then
|
||||
color_support=no
|
||||
else
|
||||
if test "x$enable_nanorc" != xyes; then
|
||||
AC_MSG_ERROR([--enable-color with --enable-tiny cannot work without --enable-nanorc])
|
||||
AC_MSG_ERROR([--enable-color needs --enable-nanorc to work])
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_extra" != xyes; then
|
||||
|
||||
@@ -28,6 +28,6 @@ info_TEXINFOS = nano.texi
|
||||
BUILT_SOURCES += nano.html
|
||||
dist_html_DATA += nano.html
|
||||
|
||||
AM_MAKEINFOHTMLFLAGS = --no-split
|
||||
AM_MAKEINFOHTMLFLAGS = --no-split -c HEADERS=0
|
||||
|
||||
EXTRA_DIST = $(BUILT_SOURCES) $(info_TEXINFOS)
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
<h2><a name="1.3"></a>1.3. Why the name change from TIP?</h2>
|
||||
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program "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.8.3</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.8.7</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%">
|
||||
@@ -161,7 +161,7 @@
|
||||
<blockquote><p>To use multiple file buffers, you must not have configured nano with <b>--disable-multibuffer</b> nor with <b>--enable-tiny</b> (use <b>nano -V</b> to check the compilation options). Then when you want to insert a file into its own buffer instead of into the current file, just hit <b>Meta-F</b> after typing <b>^R</b>. If you always want files to be loaded into their own buffers, use the <b>--multibuffer</b> or <b>-F</b> flag when you invoke nano.</p>
|
||||
<p>You can move between the buffers you have open with the <b>Meta-<</b> and <b>Meta-></b> keys, or more easily without holding Shift: <b>Meta-,</b> and <b>Meta-.</b> (clear as mud, right? =-). When you have more than one file buffer open, the ^X shortcut will say "Close", instead of the normal "Exit" when only one buffer is open.</p></blockquote>
|
||||
<h2><a name="3.8"></a>3.8. Tell me more about this verbatim input stuff!</h2>
|
||||
<blockquote><p>When you want to insert a literal character into the file you're editing, such as a control character that nano usually treats as a command, first press <b>Meta-V</b> (if you're not at a prompt, you'll get the message "Verbatim Input" on the statusbar), then press the key(s) that generate the character you want.</p>
|
||||
<blockquote><p>When you want to insert a literal character into the file you're editing, such as a control character that nano usually treats as a command, first press <b>Meta-V</b> (if you're not at a prompt, you'll get the message "Verbatim Input" on the status bar), then press the key(s) that generate the character you want.</p>
|
||||
<p>Alternatively, if you've enabled Unicode support (see section <a href="#5.3">5.3</a>), you can press <b>Meta-V</b> and then type a six-digit hexadecimal code (from 000000 to 10FFFF, case-insensitive), and the character with the corresponding value will be inserted. The statubar will change to "Unicode Input: ......" when you do this.</p></blockquote>
|
||||
<h2><a name="3.9a"></a>3.9a. How do I make a .nanorc file that will be read when I start nano?</h2>
|
||||
<blockquote><p>It's not hard at all! But, your nano must <b>not</b> have been compiled with <b>--disable-nanorc</b>. Then simply copy the <b>sample.nanorc</b> that came with the nano source or your nano package (most likely in /usr/doc/nano) to .nanorc in your home directory. If you didn't get one, the syntax of the file is simple. Flags are turned on and off by using the words <b>set</b> and <b>unset</b> plus the long option name for the feature. For example, "set nowrap" or "set smarthome".</p></blockquote>
|
||||
|
||||
29
doc/nano.1
29
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.8.3" "May 2017"
|
||||
.TH NANO 1 "version 2.8.7" "August 2017"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
|
||||
.SH NAME
|
||||
@@ -36,8 +36,8 @@ When giving a filename on the command line, the cursor can be put on a
|
||||
specific line by adding the line number with a plus sign (\fB+\fR) before
|
||||
the filename, and even in a specific column by adding it with a comma.
|
||||
|
||||
If the first file specified is a dash (\fB\-\fR), \fBnano\fR will read
|
||||
data from standard input.
|
||||
As a special case: if instead of a filename a dash (\fB\-\fR) is given,
|
||||
\fBnano\fR will read data from standard input.
|
||||
|
||||
.SH EDITING
|
||||
Entering text and moving around in a file is straightforward: typing the
|
||||
@@ -113,7 +113,7 @@ Don't add newlines to the ends of files.
|
||||
Disable automatic conversion of files from DOS/Mac format.
|
||||
.TP
|
||||
.BR \-O ", " \-\-morespace
|
||||
Use the blank line below the titlebar as extra editing space.
|
||||
Use the blank line below the title bar as extra editing space.
|
||||
.TP
|
||||
.BR \-P ", " \-\-positionlog
|
||||
For the 200 most recent files, log the last position of the cursor,
|
||||
@@ -144,8 +144,9 @@ Set the size (width) of a tab to \fInumber\fP columns. The value of
|
||||
\fInumber\fP must be greater than 0. The default value is 8.
|
||||
.TP
|
||||
.BR \-U ", " \-\-quickblank
|
||||
Do quick statusbar blanking: statusbar messages will disappear after 1
|
||||
keystroke instead of 25. Note that \fB\-c\fP overrides this.
|
||||
Do quick status-bar blanking: status-bar messages will disappear after 1
|
||||
keystroke instead of 25. Note that option \fB\-c\fR (\fB\-\-constantshow\fR)
|
||||
overrides this.
|
||||
.TP
|
||||
.BR \-V ", " \-\-version
|
||||
Show the current version number and exit.
|
||||
@@ -163,9 +164,13 @@ should be considered as part of a word. This overrides option
|
||||
Specify the name of the syntax highlighting to use from among the ones
|
||||
defined in the \fInanorc\fP files.
|
||||
.TP
|
||||
.BR \-a ", " \-\-atblanks
|
||||
When doing soft line wrapping, wrap lines at whitespace
|
||||
instead of always at the edge of the screen.
|
||||
.TP
|
||||
.BR \-c ", " \-\-constantshow
|
||||
Constantly show the cursor position on the statusbar.
|
||||
Note that this overrides \fB\-U\fP.
|
||||
Constantly show the cursor position on the status bar.
|
||||
Note that this overrides option \fB\-U\fR (\fB\-\-quickblank\fR).
|
||||
.TP
|
||||
.BR \-d ", " \-\-rebinddelete
|
||||
Interpret the Delete key differently so that both Backspace and Delete
|
||||
@@ -183,7 +188,7 @@ Show a summary of the available command-line options and exit.
|
||||
Indent new lines to the previous line's indentation. Useful when
|
||||
editing source code.
|
||||
.TP
|
||||
.BR \-k ", " \-\-cut
|
||||
.BR \-k ", " \-\-cutfromcursor
|
||||
Make the 'Cut Text' command (normally \fB^K\fR) cut from the current cursor
|
||||
position to the end of the line, instead of cutting the entire line.
|
||||
.TP
|
||||
@@ -221,7 +226,7 @@ Hard-wrap lines at column \fInumber\fP. If this value is 0 or less, wrapping
|
||||
will occur at the width of the screen less \fInumber\fP columns, allowing
|
||||
the wrap point to vary along with the width of the screen if the screen
|
||||
is resized. The default value is \-8. This option conflicts with
|
||||
\fB\-w\fR -- the last one given takes effect.
|
||||
\fB\-w\fR (\fB\-\-nowrap\fR) -- the last one given takes effect.
|
||||
.TP
|
||||
.BR \-s\ \fIprogram\fR ", " \-\-speller= \fIprogram
|
||||
Use this alternative spell checker command.
|
||||
@@ -239,7 +244,7 @@ Just view the file and disallow editing: read-only mode.
|
||||
.TP
|
||||
.BR \-w ", " \-\-nowrap
|
||||
Disable the hard-wrapping of long lines. This option conflicts with
|
||||
\fB\-r\fR -- the last one given takes effect.
|
||||
\fB\-r\fR (\fB\-\-fill\fR) -- the last one given takes effect.
|
||||
.TP
|
||||
.BR \-x ", " \-\-nohelp
|
||||
Don't show the two help lines at the bottom of the screen.
|
||||
@@ -255,7 +260,7 @@ continuing it over multiple screen lines. Since
|
||||
this option last when using other options (e.g.\& 'nano \-wS$') or pass it
|
||||
separately (e.g.\& 'nano \-wS \-$').
|
||||
.TP
|
||||
.BR \-a ", " \-b ", " \-e ", " \-f ", " \-j
|
||||
.BR \-b ", " \-e ", " \-f ", " \-j
|
||||
Ignored, for compatibility with Pico.
|
||||
|
||||
.SH TOGGLES
|
||||
|
||||
649
doc/nano.texi
649
doc/nano.texi
File diff suppressed because it is too large
Load Diff
134
doc/nanorc.5
134
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.8.3" "May 2017"
|
||||
.TH NANORC 5 "version 2.8.7" "August 2017"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
|
||||
.SH NAME
|
||||
@@ -57,6 +57,10 @@ When backing up files, allow the backup to succeed even if its permissions
|
||||
can't be (re)set due to special OS considerations. You should
|
||||
NOT enable this option unless you are sure you need it.
|
||||
.TP
|
||||
.B set atblanks
|
||||
When soft line wrapping is enabled, make it wrap lines at blank characters
|
||||
(tabs and spaces) instead of always at the edge of the screen.
|
||||
.TP
|
||||
.B set autoindent
|
||||
Use auto-indentation.
|
||||
.TP
|
||||
@@ -66,7 +70,7 @@ the file's name.
|
||||
.TP
|
||||
.B set backupdir "\fIdirectory\fP"
|
||||
Make and keep not just one backup file, but make and keep a uniquely
|
||||
numbered one every time a file is saved --- when backups are enabled
|
||||
numbered one every time a file is saved -- when backups are enabled
|
||||
with \fBset backup\fR or \fB\-\-backup\fR or \fB\-B\fR.
|
||||
The uniquely numbered files are stored in the specified \fIdirectory\fR.
|
||||
.TP
|
||||
@@ -74,10 +78,10 @@ The uniquely numbered files are stored in the specified \fIdirectory\fR.
|
||||
Do backwards searches by default.
|
||||
.TP
|
||||
.B set boldtext
|
||||
Use bold instead of reverse video for the titlebar, statusbar, key combos,
|
||||
line numbers, and selected text. This can be overridden for the first four
|
||||
by setting the options \fBtitlecolor\fP, \fBstatuscolor\fP, \fBkeycolor\fP,
|
||||
and \fBnumbercolor\fP.
|
||||
Use bold instead of reverse video for the title bar, status bar, key combos,
|
||||
function tags, line numbers, and selected text. This can be overridden by
|
||||
setting the options \fBtitlecolor\fP, \fBstatuscolor\fP, \fBkeycolor\fP,
|
||||
\fBfunctioncolor\fP, \fBnumbercolor\fP, and \fBselectedcolor\fP.
|
||||
.TP
|
||||
.B set brackets "\fIstring\fP"
|
||||
Set the characters treated as closing brackets when justifying
|
||||
@@ -91,14 +95,17 @@ Do case-sensitive searches by default.
|
||||
.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 cut
|
||||
Use cut-to-end-of-line by default, instead of cutting the whole line.
|
||||
.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 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.
|
||||
The default value is \fB\-8\fR.
|
||||
The default value is \fB\-8\fR. This option conflicts with
|
||||
\fBnowrap\fR -- the last one given takes effect.
|
||||
.TP
|
||||
.B set functioncolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Specify the color combination to use for the function descriptions
|
||||
@@ -130,7 +137,7 @@ come before the closing set, and the two sets must be in the same order.
|
||||
The default value is "\fB(<[{)>]}\fP".
|
||||
.TP
|
||||
.B set morespace
|
||||
Use the blank line below the titlebar as extra editing space.
|
||||
Use the blank line below the title bar as extra editing space.
|
||||
.TP
|
||||
.B set mouse
|
||||
Enable mouse support, if available for your system. When enabled, mouse
|
||||
@@ -156,7 +163,8 @@ Don't pause between warnings at startup. This means that only
|
||||
the last one will be visible (when there are multiple ones).
|
||||
.TP
|
||||
.B set nowrap
|
||||
Don't hard-wrap text at all.
|
||||
Don't hard-wrap text at all. This option conflicts with
|
||||
\fBfill\fR -- the last one given takes effect.
|
||||
.TP
|
||||
.B set numbercolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Specify the color combination to use for line numbers.
|
||||
@@ -183,8 +191,8 @@ specfified closing punctuation, optionally followed by closing brackets
|
||||
(see \fBbrackets\fP), can end sentences. The default value is "\fB!.?\fP".
|
||||
.TP
|
||||
.B set quickblank
|
||||
Do quick statusbar blanking. Statusbar messages will disappear after 1
|
||||
keystroke instead of 25.
|
||||
Do quick status-bar blanking: status-bar messages will disappear after 1
|
||||
keystroke instead of 25. The option \fBconstantshow\fR overrides this.
|
||||
.TP
|
||||
.B set quiet
|
||||
\fBnano\fP will not report errors in the \fInanorc\fP file nor ask them
|
||||
@@ -212,6 +220,10 @@ won't work properly with this option enabled.
|
||||
.B set regexp
|
||||
Do extended regular expression searches by default.
|
||||
.TP
|
||||
.B set selectedcolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Specify the color combination to use for selected text.
|
||||
See \fBset titlecolor\fR for more details.
|
||||
.TP
|
||||
.B set showcursor
|
||||
Put the cursor on the highlighted item in the file browser, to aid
|
||||
braille users.
|
||||
@@ -234,7 +246,7 @@ Use spelling checker \fIspellprog\fP instead of the built-in one, which
|
||||
calls \fIspell\fP.
|
||||
.TP
|
||||
.B set statuscolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Specify the color combination to use for the statusbar.
|
||||
Specify the color combination to use for the status bar.
|
||||
See \fBset titlecolor\fR for more details.
|
||||
.TP
|
||||
.B set suspend
|
||||
@@ -251,7 +263,7 @@ Convert typed tabs to spaces.
|
||||
Save automatically on exit, don't prompt.
|
||||
.TP
|
||||
.B set titlecolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Specify the color combination to use for the titlebar.
|
||||
Specify the color combination to use for the title bar.
|
||||
Valid names for the foreground and background colors are:
|
||||
.BR white ", " black ", " blue ", " green ", " red ", " cyan ", " yellow ", and " magenta .
|
||||
The name of the foreground color may be prefixed with \fBbright\fR.
|
||||
@@ -267,7 +279,8 @@ Disallow file modification.
|
||||
.TP
|
||||
.B set whitespace "\fIstring\fP"
|
||||
Set the two characters used to indicate the presence of tabs and
|
||||
spaces. They must be single-column characters.
|
||||
spaces. They must be single-column characters. The default pair
|
||||
for a UTF-8 locale is "\fB\[Fc]\[md]\fR", and for other locales "\fB>.\fR".
|
||||
.TP
|
||||
.B set wordbounds
|
||||
Detect word boundaries differently by treating punctuation
|
||||
@@ -286,53 +299,58 @@ powerful enough to fully parse a file. Nevertheless, regular
|
||||
expressions can do a lot and are easy to make, so they are a
|
||||
good fit for a small editor like \fBnano\fR.
|
||||
.sp
|
||||
A separate syntax can be defined for each kind of file
|
||||
For each kind of file a separate syntax can be defined
|
||||
via the following commands:
|
||||
.TP
|
||||
.BR syntax " ""\fIname\fR"" [""\fIfileregex\fR"" ...]"
|
||||
Defines a syntax named \fIname\fP which can be activated via the
|
||||
.BR \-Y / \-\-syntax
|
||||
command-line option, or will be automatically activated if
|
||||
the current filename matches the extended regular expression
|
||||
\fIfileregex\fP. All subsequent \fBcolor\fR, \fBicolor\fR,
|
||||
\fBheader\fR and other such statements will apply to this
|
||||
\fIname\fP syntax until a new \fBsyntax\fR command is encountered.
|
||||
Start the definition of a syntax with this \fIname\fR.
|
||||
All subsequent \fBcolor\fR and other such commands
|
||||
will be added to this syntax, until a new \fBsyntax\fR
|
||||
command is encountered.
|
||||
|
||||
The \fBnone\fP syntax is reserved; specifying it on the command line is
|
||||
the same as not having a syntax at all. The \fBdefault\fP syntax is
|
||||
special: it takes no \fIfileregex\fP, and applies to files that don't
|
||||
match any syntax's \fIfileregex\fP.
|
||||
When \fBnano\fR is run, this syntax will be automatically
|
||||
activated if the current filename matches the extended regular
|
||||
expression \fIfileregex\fR. Or the syntax can be explicitly
|
||||
activated by using the \fB-Y\fR or \fB\-\-syntax\fR
|
||||
command-line option followed by the \fIname\fR.
|
||||
|
||||
The syntax "\fBdefault\fP" is special: it takes no \fIfileregex\fR,
|
||||
and applies to files that don't match any syntax's regexes.
|
||||
The syntax "\fBnone\fP" is reserved; specifying it on the command line
|
||||
is the same as not having a syntax at all.
|
||||
.TP
|
||||
.BR header " ""\fIregex\fR"" " ...
|
||||
If from all defined syntaxes no \fIfileregex\fR matched, then compare
|
||||
this \fIregex\fR (or regexes) against the first line of the current file,
|
||||
to determine whether this syntax should be used for it.
|
||||
.TP
|
||||
.BR magic " ""\fIregex\fR"" " ...
|
||||
If no \fIfileregex\fR matched and no \fBheader\fR regex matched
|
||||
either, then compare this \fIregex\fR (or regexes) against the
|
||||
result of querying the \fBmagic\fP database about the current
|
||||
file, to determine whether this syntax should be used for it.
|
||||
(This functionality only works when \fBlibmagic\fP is installed on the
|
||||
system and will be silently ignored otherwise.)
|
||||
.TP
|
||||
.BI linter " program " \fR[ "arg " \fR...]
|
||||
Use the given \fIprogram\fR to run a syntax check on the current file
|
||||
(this overrides the speller function when defined).
|
||||
Use the given \fIprogram\fR to run a syntax check on the current file.
|
||||
(This overrides the speller function.)
|
||||
.TP
|
||||
.BI formatter " program " \fR[ "arg " \fR...]
|
||||
Use the given \fIprogram\fR to automatically reformat text.
|
||||
Useful in certain programming languages (e.g. Go).
|
||||
Use the given \fIprogram\fR to automatically reformat text --
|
||||
useful in a programming language like Go.
|
||||
(This overrides the speller and linter functions.)
|
||||
.TP
|
||||
.BR header " \fIregex\fR " ...
|
||||
Add one or more regexes which will
|
||||
be compared against the very first line of the file to be edited,
|
||||
to determine whether this syntax should be used for that file.
|
||||
.TP
|
||||
.BR magic " \fIregex\fR " ...
|
||||
Add one or more regexes which
|
||||
will be compared against the result of querying the \fBmagic\fP
|
||||
database about the file to be edited, to determine whether this
|
||||
syntax should be used for that file. This
|
||||
functionality only works when \fBlibmagic\fP is installed on the
|
||||
system and will be silently ignored otherwise.
|
||||
.TP
|
||||
.BI comment " string"
|
||||
Use the given string for commenting and uncommenting lines. A vertical bar or
|
||||
pipe character (|) designates bracket-style comments; for example, "/*|*/" for
|
||||
.BR comment " ""\fIstring\fR"""
|
||||
Use the given string for commenting and uncommenting lines.
|
||||
If the string contains a vertical bar or pipe character (\fB|\fR),
|
||||
this designates bracket-style comments; for example, "\fB/*|*/\fR" for
|
||||
CSS files. The characters before the pipe are prepended to the line and the
|
||||
characters after the pipe are appended at the end of the line. If no pipe
|
||||
character is present, the entire string is prepended; for example, "#" for
|
||||
Python files. If empty double quotes are specified, the comment/uncomment
|
||||
function is disabled; for example, "" for JSON. Double quotes or backslashes
|
||||
may be escaped with a backslash; for example, ".\\"" for man page source.
|
||||
character is present, the full string is prepended; for example, "\fB#\fR"
|
||||
for Python files. If empty double quotes are specified, the comment/uncomment
|
||||
function is disabled; for example, "" for JSON.
|
||||
The default value is "\fB#\fP".
|
||||
.TP
|
||||
.B color \fIfgcolor\fR,\fIbgcolor\fR """\fIregex\fR""" ...
|
||||
Display all pieces of text that match
|
||||
@@ -365,13 +383,13 @@ Read in self-contained color syntaxes from \fIsyntaxfile\fP. Note that
|
||||
\fIsyntaxfile\fP may contain only the above commands, from \fBsyntax\fP
|
||||
to \fBicolor\fP.
|
||||
.TP
|
||||
.BI extendsyntax " name directive " \fR[ "arg " \fR...]
|
||||
Extend the syntax previously defined as \fIname\fP to include
|
||||
new information. This allows adding a new \fBcolor\fP, \fBicolor\fP,
|
||||
.BI extendsyntax " name command " \fR[ "arg " \fR...]
|
||||
Extend the syntax previously defined as \fIname\fR with another
|
||||
\fIcommand\fR. This allows adding a new \fBcolor\fP, \fBicolor\fP,
|
||||
\fBheader\fP, \fBmagic\fP, \fBcomment\fP, \fBlinter\fP, or \fBformatter\fP
|
||||
directive to an already defined syntax -- useful when you want to
|
||||
command to an already defined syntax -- useful when you want to
|
||||
slightly improve a syntax defined in one of the system-installed
|
||||
files (which are normally not writable).
|
||||
files (which normally are not writable).
|
||||
|
||||
.SH REBINDING KEYS
|
||||
Key bindings can be changed via the following two commands:
|
||||
@@ -666,7 +684,7 @@ Toggles the presence of the two-line list of key bindings at the bottom of the s
|
||||
Toggles the constant display of the current line, column, and character positions.
|
||||
.TP
|
||||
.B morespace
|
||||
Toggles the presence of the blank line which 'separates' the titlebar from the file text.
|
||||
Toggles the presence of the blank line that 'separates' the title bar from the file text.
|
||||
.TP
|
||||
.B smoothscroll
|
||||
Toggles smooth scrolling (when moving around with the arrow keys).
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 2.8.3" "May 2017"
|
||||
.TH RNANO 1 "version 2.8.7" "August 2017"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
|
||||
.SH NAME
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
## versions of nano installed (e.g. your home directory is on NFS).
|
||||
# set quiet
|
||||
|
||||
## When soft line wrapping is enabled, make it wrap lines at blanks
|
||||
## (tabs and spaces) instead of always at the edge of the screen.
|
||||
# set atblanks
|
||||
|
||||
## Use auto-indentation.
|
||||
# set autoindent
|
||||
|
||||
@@ -44,13 +48,14 @@
|
||||
## Do case-sensitive searches by default.
|
||||
# set casesensitive
|
||||
|
||||
## Constantly display the cursor position in the statusbar. Note that
|
||||
## Constantly display the cursor position in the status bar. Note that
|
||||
## this overrides "quickblank".
|
||||
# set constantshow
|
||||
## (The old form, 'const', is deprecated.)
|
||||
|
||||
## Use cut-to-end-of-line by default.
|
||||
# set cut
|
||||
## Use cut-from-cursor-to-end-of-line by default.
|
||||
# set cutfromcursor
|
||||
## (The old form, 'cut', is deprecated.)
|
||||
|
||||
## Set the line length for wrapping text and justifying paragraphs.
|
||||
## If the value is 0 or less, the wrapping point will be the screen
|
||||
@@ -67,7 +72,7 @@
|
||||
# set linenumbers
|
||||
|
||||
## Enable vim-style lock-files. This is just to let a vim user know you
|
||||
## are editing a file [s]he is trying to edit and vice versa. There are
|
||||
## are editing a file [s]he is trying to edit and vice versa. There are
|
||||
## no plans to implement vim-style undo state in these files.
|
||||
# set locking
|
||||
|
||||
@@ -76,7 +81,7 @@
|
||||
## come before the latter set, and both must be in the same order.
|
||||
# set matchbrackets "(<[{)>]}"
|
||||
|
||||
## Use the blank line below the titlebar as extra editing space.
|
||||
## Use the blank line below the title bar as extra editing space.
|
||||
# set morespace
|
||||
|
||||
## Enable mouse support, if available for your system. When enabled,
|
||||
@@ -124,8 +129,8 @@
|
||||
## sentences.
|
||||
# set punct "!.?"
|
||||
|
||||
## Do quick statusbar blanking. Statusbar messages will disappear after
|
||||
## 1 keystroke instead of 26. Note that "const" overrides this.
|
||||
## Do quick status-bar blanking. Status-bar messages will disappear after
|
||||
## 1 keystroke instead of 26. Note that "constantshow" overrides this.
|
||||
# set quickblank
|
||||
|
||||
## The email-quote string, used to justify email-quoted paragraphs.
|
||||
@@ -163,7 +168,7 @@
|
||||
# set softwrap
|
||||
|
||||
## Use this spelling checker instead of the internal one. This option
|
||||
## does not properly have a default value.
|
||||
## does not have a default value.
|
||||
# set speller "aspell -x -c"
|
||||
|
||||
## Allow nano to be suspended.
|
||||
@@ -203,12 +208,14 @@
|
||||
## These are examples; by default there are no colors.
|
||||
# set titlecolor brightwhite,blue
|
||||
# set statuscolor brightwhite,green
|
||||
# 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 selectedcolor brightwhite,cyan
|
||||
# set numbercolor magenta
|
||||
# set keycolor brightmagenta
|
||||
# set functioncolor magenta
|
||||
@@ -262,11 +269,9 @@
|
||||
## Key bindings.
|
||||
## See nanorc(5) (section REBINDING KEYS) for more details on this.
|
||||
##
|
||||
## The following five functions are not bound to any key by default.
|
||||
## The following three functions are not bound to any key by default.
|
||||
## You may wish to choose different keys than the ones suggested here.
|
||||
# bind ^S savefile main
|
||||
# bind M-Q findprevious main
|
||||
# bind M-W findnext main
|
||||
# bind M-B cutwordleft main
|
||||
# bind M-N cutwordright main
|
||||
|
||||
|
||||
1142
po/nano.pot
1142
po/nano.pot
File diff suppressed because it is too large
Load Diff
1098
po/pt_BR.po
1098
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1094
po/zh_CN.po
1094
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1090
po/zh_TW.po
1090
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -37,9 +37,10 @@ nano_SOURCES = browser.c \
|
||||
search.c \
|
||||
text.c \
|
||||
utils.c \
|
||||
winio.c
|
||||
winio.c
|
||||
|
||||
nano_LDADD = @LIBINTL@ $(top_builddir)/lib/libgnu.a $(LIB_CLOCK_GETTIME)
|
||||
nano_LDADD = @LIBINTL@ $(top_builddir)/lib/libgnu.a \
|
||||
$(LIB_CLOCK_GETTIME) $(LIBTHREAD)
|
||||
|
||||
install-exec-hook:
|
||||
cd $(DESTDIR)$(bindir) && rm -f rnano && $(LN_S) nano rnano
|
||||
|
||||
@@ -21,11 +21,10 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef ENABLE_BROWSER
|
||||
|
||||
@@ -172,11 +171,15 @@ char *do_browser(char *path)
|
||||
say_there_is_no_help();
|
||||
#endif
|
||||
} else if (func == do_search) {
|
||||
/* Search for a filename. */
|
||||
do_filesearch();
|
||||
} else if (func == do_research) {
|
||||
/* Search for another filename. */
|
||||
do_fileresearch();
|
||||
do_fileresearch(TRUE);
|
||||
#ifndef NANO_TINY
|
||||
} else if (func == do_findprevious) {
|
||||
do_fileresearch(FALSE);
|
||||
} else if (func == do_findnext) {
|
||||
do_fileresearch(TRUE);
|
||||
#endif
|
||||
} else if (func == do_left) {
|
||||
if (selected > 0)
|
||||
selected--;
|
||||
@@ -249,11 +252,10 @@ char *do_browser(char *path)
|
||||
}
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
if (check_operating_dir(path, FALSE)) {
|
||||
if (outside_of_confinement(path, FALSE)) {
|
||||
/* TRANSLATORS: This refers to the confining effect of the
|
||||
* option --operatingdir, not of --restricted. */
|
||||
statusline(ALERT, _("Can't go outside of %s"),
|
||||
full_operating_dir);
|
||||
statusline(ALERT, _("Can't go outside of %s"), operating_dir);
|
||||
path = mallocstrcpy(path, present_path);
|
||||
continue;
|
||||
}
|
||||
@@ -283,9 +285,8 @@ char *do_browser(char *path)
|
||||
/* Note: The selected file can be outside the operating
|
||||
* directory if it's ".." or if it's a symlink to a
|
||||
* directory outside the operating directory. */
|
||||
if (check_operating_dir(filelist[selected], FALSE)) {
|
||||
statusline(ALERT, _("Can't go outside of %s"),
|
||||
full_operating_dir);
|
||||
if (outside_of_confinement(filelist[selected], FALSE)) {
|
||||
statusline(ALERT, _("Can't go outside of %s"), operating_dir);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
@@ -382,7 +383,7 @@ char *do_browse_from(const char *inpath)
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
/* If the resulting path isn't in the operating directory, use
|
||||
* the operating directory instead. */
|
||||
if (check_operating_dir(path, FALSE))
|
||||
if (outside_of_confinement(path, FALSE))
|
||||
path = mallocstrcpy(path, operating_dir);
|
||||
#endif
|
||||
|
||||
@@ -491,6 +492,9 @@ functionptrtype parse_browser_input(int *kbinput)
|
||||
case '/':
|
||||
return do_search;
|
||||
case 'N':
|
||||
#ifndef NANO_TINY
|
||||
return do_findprevious;
|
||||
#endif
|
||||
case 'n':
|
||||
return do_research;
|
||||
}
|
||||
@@ -539,7 +543,7 @@ void browser_refresh(void)
|
||||
/* If this is the selected item, start its highlighting, and
|
||||
* remember its location to be able to place the cursor on it. */
|
||||
if (i == selected) {
|
||||
wattron(edit, hilite_attribute);
|
||||
wattron(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
the_row = row;
|
||||
the_column = col;
|
||||
}
|
||||
@@ -611,7 +615,7 @@ void browser_refresh(void)
|
||||
|
||||
/* If this is the selected item, finish its highlighting. */
|
||||
if (i == selected)
|
||||
wattroff(edit, hilite_attribute);
|
||||
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
free(info);
|
||||
|
||||
@@ -700,8 +704,9 @@ int filesearch_init(void)
|
||||
return input;
|
||||
}
|
||||
|
||||
/* Look for the given needle in the list of files. */
|
||||
void findnextfile(const char *needle)
|
||||
/* Look for the given needle in the list of files. If forwards is TRUE,
|
||||
* search forward in the list; otherwise, search backward. */
|
||||
void findfile(const char *needle, bool forwards)
|
||||
{
|
||||
size_t looking_at = selected;
|
||||
/* The location in the file list of the filename we're looking at. */
|
||||
@@ -721,12 +726,16 @@ void findnextfile(const char *needle)
|
||||
/* Step through each filename in the list until a match is found or
|
||||
* we've come back to the point where we started. */
|
||||
while (TRUE) {
|
||||
/* Move to the next filename in the list, or back to the first. */
|
||||
if (looking_at < filelist_len - 1)
|
||||
looking_at++;
|
||||
else {
|
||||
looking_at = 0;
|
||||
statusbar(_("Search Wrapped"));
|
||||
if (forwards) {
|
||||
if (looking_at++ == filelist_len - 1) {
|
||||
looking_at = 0;
|
||||
statusbar(_("Search Wrapped"));
|
||||
}
|
||||
} else {
|
||||
if (looking_at-- == 0) {
|
||||
looking_at = filelist_len - 1;
|
||||
statusbar(_("Search Wrapped"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the bare filename, without the path. */
|
||||
@@ -773,16 +782,17 @@ void do_filesearch(void)
|
||||
update_history(&search_history, answer);
|
||||
#endif
|
||||
|
||||
findnextfile(answer);
|
||||
findfile(answer, TRUE);
|
||||
}
|
||||
|
||||
/* Search again for the last given filename, without prompting. */
|
||||
void do_fileresearch(void)
|
||||
/* Search again without prompting for the last given search string,
|
||||
* either forwards or backwards. */
|
||||
void do_fileresearch(bool forwards)
|
||||
{
|
||||
if (*last_search == '\0')
|
||||
statusbar(_("No current search pattern"));
|
||||
else
|
||||
findnextfile(last_search);
|
||||
findfile(last_search, forwards);
|
||||
}
|
||||
|
||||
/* Select the first file in the list. */
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
#include <wchar.h>
|
||||
|
||||
15
src/color.c
15
src/color.c
@@ -21,15 +21,12 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_MAGIC_H
|
||||
#include <magic.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
|
||||
@@ -54,8 +51,9 @@ void set_colorpairs(void)
|
||||
for (i = 0; i < NUMBER_OF_ELEMENTS; i++) {
|
||||
bool bright = FALSE;
|
||||
|
||||
if (parse_color_names(specified_color_combo[i],
|
||||
&foreground, &background, &bright)) {
|
||||
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)
|
||||
@@ -63,8 +61,7 @@ void set_colorpairs(void)
|
||||
init_pair(i + 1, foreground, background);
|
||||
interface_color_pair[i] =
|
||||
COLOR_PAIR(i + 1) | (bright ? A_BOLD : A_NORMAL);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (i != FUNCTION_TAG)
|
||||
interface_color_pair[i] = hilite_attribute;
|
||||
else
|
||||
|
||||
12
src/cut.c
12
src/cut.c
@@ -23,7 +23,6 @@
|
||||
#include "proto.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static bool keep_cutbuffer = FALSE;
|
||||
/* Should we keep the contents of the cutbuffer? */
|
||||
@@ -155,7 +154,7 @@ void do_cut_text(bool copy_text, bool cut_till_eof)
|
||||
/* Move the marked text to the cutbuffer, and turn the mark off. */
|
||||
cut_marked(&right_side_up);
|
||||
openfile->mark_set = FALSE;
|
||||
} else if (ISSET(CUT_TO_END))
|
||||
} else if (ISSET(CUT_FROM_CURSOR))
|
||||
/* Move all text up to the end of the line into the cutbuffer. */
|
||||
cut_to_eol();
|
||||
else
|
||||
@@ -248,9 +247,9 @@ void do_copy_text(void)
|
||||
/* Cut from the current cursor position to the end of the file. */
|
||||
void do_cut_till_eof(void)
|
||||
{
|
||||
add_undo(CUT_EOF);
|
||||
add_undo(CUT_TO_EOF);
|
||||
do_cut_text(FALSE, TRUE);
|
||||
update_undo(CUT_EOF);
|
||||
update_undo(CUT_TO_EOF);
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
@@ -270,7 +269,7 @@ void do_uncut_text(void)
|
||||
add_undo(PASTE);
|
||||
|
||||
if (ISSET(SOFTWRAP))
|
||||
was_leftedge = (xplustabs() / editwincols) * editwincols;
|
||||
was_leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
#endif
|
||||
|
||||
/* Add a copy of the text in the cutbuffer to the current buffer
|
||||
@@ -291,9 +290,6 @@ void do_uncut_text(void)
|
||||
/* Mark the file as modified. */
|
||||
set_modified();
|
||||
|
||||
/* Update current_y to account for the inserted lines. */
|
||||
place_the_cursor(TRUE);
|
||||
|
||||
refresh_needed = TRUE;
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
|
||||
336
src/files.c
336
src/files.c
@@ -21,17 +21,14 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utime.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LOCKBUFSIZE 8192
|
||||
|
||||
@@ -261,6 +258,7 @@ int write_lockfile(const char *lockfilename, const char *origfilename, bool modi
|
||||
if (wroteamt < lockdatalen) {
|
||||
statusline(MILD, _("Error writing lock file %s: %s"),
|
||||
lockfilename, ferror(filestream));
|
||||
fclose(filestream);
|
||||
goto free_the_data;
|
||||
}
|
||||
|
||||
@@ -430,15 +428,13 @@ bool open_buffer(const char *filename, bool undoable)
|
||||
/* rc == -2 means that we have a new file. -1 means that the
|
||||
* open() failed. 0 means that the open() succeeded. */
|
||||
|
||||
assert(filename != NULL);
|
||||
|
||||
/* Display newlines in filenames as ^J. */
|
||||
as_an_at = FALSE;
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
if (check_operating_dir(filename, FALSE)) {
|
||||
statusline(ALERT, _("Can't insert file from outside of %s"),
|
||||
full_operating_dir);
|
||||
if (outside_of_confinement(filename, FALSE)) {
|
||||
statusline(ALERT, _("Can't read file from outside of %s"),
|
||||
operating_dir);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
@@ -527,8 +523,6 @@ void replace_buffer(const char *filename)
|
||||
FILE *f;
|
||||
int descriptor;
|
||||
|
||||
assert(filename != NULL && filename[0] != '\0');
|
||||
|
||||
/* Open the file quietly. */
|
||||
descriptor = open_file(filename, FALSE, TRUE, &f);
|
||||
|
||||
@@ -605,8 +599,6 @@ void prepare_for_display(void)
|
||||
* otherwise, to the previous one. */
|
||||
void switch_to_prevnext_buffer(bool to_next)
|
||||
{
|
||||
assert(openfile != NULL);
|
||||
|
||||
/* If only one file buffer is open, say so and get out. */
|
||||
if (openfile == openfile->next && !inhelp) {
|
||||
statusbar(_("No more open file buffers"));
|
||||
@@ -631,9 +623,14 @@ void switch_to_prevnext_buffer(bool to_next)
|
||||
/* Update titlebar and multiline info to match the current buffer. */
|
||||
prepare_for_display();
|
||||
|
||||
if (inhelp)
|
||||
return;
|
||||
|
||||
/* Ensure that the main loop will redraw the help lines. */
|
||||
currmenu = MMOST;
|
||||
|
||||
/* Indicate the switch on the statusbar. */
|
||||
if (!inhelp)
|
||||
statusline(HUSH, _("Switched to %s"),
|
||||
statusline(HUSH, _("Switched to %s"),
|
||||
((openfile->filename[0] == '\0') ?
|
||||
_("New Buffer") : openfile->filename));
|
||||
|
||||
@@ -659,8 +656,6 @@ void switch_to_next_buffer_void(void)
|
||||
* open buffers. */
|
||||
bool close_buffer(void)
|
||||
{
|
||||
assert(openfile != NULL);
|
||||
|
||||
/* If only one file buffer is open, get out. */
|
||||
if (openfile == openfile->next)
|
||||
return FALSE;
|
||||
@@ -677,7 +672,7 @@ bool close_buffer(void)
|
||||
/* Close the file buffer we had open before. */
|
||||
unlink_opennode(openfile->prev);
|
||||
|
||||
/* If only one buffer is open now, show Exit in the help lines. */
|
||||
/* If now just one buffer remains open, show "Exit" in the help lines. */
|
||||
if (openfile == openfile->next)
|
||||
exitfunc->desc = exit_tag;
|
||||
|
||||
@@ -691,34 +686,30 @@ bool close_buffer(void)
|
||||
* warnings. */
|
||||
int is_file_writable(const char *filename)
|
||||
{
|
||||
struct stat fileinfo, fileinfo2;
|
||||
char *full_filename;
|
||||
struct stat fileinfo;
|
||||
int fd;
|
||||
FILE *f;
|
||||
char *full_filename;
|
||||
bool result = TRUE;
|
||||
|
||||
if (ISSET(VIEW_MODE))
|
||||
return TRUE;
|
||||
|
||||
assert(filename != NULL);
|
||||
|
||||
/* Get the specified file's full path. */
|
||||
full_filename = get_full_path(filename);
|
||||
|
||||
/* Okay, if we can't stat the absolute path due to some component's
|
||||
* permissions, just try the relative one. */
|
||||
if (full_filename == NULL ||
|
||||
(stat(full_filename, &fileinfo) == -1 && stat(filename, &fileinfo2) != -1))
|
||||
/* If the absolute path is unusable, use the given relative one. */
|
||||
if (full_filename == NULL || stat(full_filename, &fileinfo) == -1)
|
||||
full_filename = mallocstrcpy(NULL, filename);
|
||||
|
||||
if ((fd = open(full_filename, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR |
|
||||
S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1 ||
|
||||
(f = fdopen(fd, "a")) == NULL)
|
||||
S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1)
|
||||
result = FALSE;
|
||||
else
|
||||
else if ((f = fdopen(fd, "a")) == NULL) {
|
||||
result = FALSE;
|
||||
close(fd);
|
||||
} else
|
||||
fclose(f);
|
||||
|
||||
close(fd);
|
||||
free(full_filename);
|
||||
|
||||
return result;
|
||||
@@ -777,7 +768,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
|
||||
add_undo(INSERT);
|
||||
|
||||
if (ISSET(SOFTWRAP))
|
||||
was_leftedge = (xplustabs() / editwincols) * editwincols;
|
||||
was_leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
#endif
|
||||
|
||||
/* Create an empty buffer. */
|
||||
@@ -931,7 +922,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
|
||||
(unsigned long)num_lines), (unsigned long)num_lines);
|
||||
|
||||
/* If we inserted less than a screenful, don't center the cursor. */
|
||||
if (less_than_a_screenful(was_lineno, was_leftedge))
|
||||
if (undoable && less_than_a_screenful(was_lineno, was_leftedge))
|
||||
focusing = FALSE;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -953,8 +944,6 @@ int open_file(const char *filename, bool newfie, bool quiet, FILE **f)
|
||||
int fd;
|
||||
char *full_filename;
|
||||
|
||||
assert(filename != NULL && f != NULL);
|
||||
|
||||
/* Get the specified file's full path. */
|
||||
full_filename = get_full_path(filename);
|
||||
|
||||
@@ -1018,8 +1007,6 @@ char *get_next_filename(const char *name, const char *suffix)
|
||||
char *buf;
|
||||
size_t wholenamelen;
|
||||
|
||||
assert(name != NULL && suffix != NULL);
|
||||
|
||||
wholenamelen = strlen(name) + strlen(suffix);
|
||||
|
||||
/* Reserve space for: the name plus the suffix plus a dot plus
|
||||
@@ -1197,9 +1184,6 @@ void do_insertfile(void)
|
||||
openfile->current_x != was_current_x)
|
||||
set_modified();
|
||||
|
||||
/* Update current_y to account for inserted lines. */
|
||||
place_the_cursor(TRUE);
|
||||
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
@@ -1386,8 +1370,6 @@ char *safe_tempfile(FILE **f)
|
||||
int fd;
|
||||
mode_t original_umask = 0;
|
||||
|
||||
assert(f != NULL);
|
||||
|
||||
/* If $TMPDIR is set, set tempdir to it, run it through
|
||||
* get_full_path(), and save the result in full_tempdir. Otherwise,
|
||||
* leave full_tempdir set to NULL. */
|
||||
@@ -1425,44 +1407,31 @@ char *safe_tempfile(FILE **f)
|
||||
}
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
/* Initialize full_operating_dir based on operating_dir. */
|
||||
/* Change to the specified operating directory, when it's valid. */
|
||||
void init_operating_dir(void)
|
||||
{
|
||||
assert(full_operating_dir == NULL);
|
||||
|
||||
if (operating_dir == NULL)
|
||||
return;
|
||||
|
||||
full_operating_dir = get_full_path(operating_dir);
|
||||
operating_dir = free_and_assign(operating_dir, get_full_path(operating_dir));
|
||||
|
||||
/* If the operating directory is inaccessible, fail. */
|
||||
if (full_operating_dir == NULL || chdir(full_operating_dir) == -1)
|
||||
if (operating_dir == NULL || chdir(operating_dir) == -1)
|
||||
die(_("Invalid operating directory\n"));
|
||||
|
||||
snuggly_fit(&full_operating_dir);
|
||||
snuggly_fit(&operating_dir);
|
||||
}
|
||||
|
||||
/* Check to see if we're inside the operating directory. Return FALSE
|
||||
* if we are, or TRUE otherwise. If allow_tabcomp is TRUE, allow
|
||||
* incomplete names that would be matches for the operating directory,
|
||||
* so that tab completion will work. */
|
||||
bool check_operating_dir(const char *currpath, bool allow_tabcomp)
|
||||
/* Check whether the given path is outside of the operating directory.
|
||||
* Return TRUE if it is, and FALSE otherwise. If allow_tabcomp is TRUE,
|
||||
* incomplete names that can grow into matches for the operating directory
|
||||
* are considered to be inside, so that tab completion will work. */
|
||||
bool outside_of_confinement(const char *currpath, bool allow_tabcomp)
|
||||
{
|
||||
/* full_operating_dir is global for memory cleanup. It should have
|
||||
* already been initialized by init_operating_dir(). Also, a
|
||||
* relative operating directory path will only be handled properly
|
||||
* if this is done. */
|
||||
|
||||
char *fullpath;
|
||||
bool retval = FALSE;
|
||||
const char *whereami1, *whereami2 = NULL;
|
||||
bool is_inside, begins_to_be;
|
||||
|
||||
/* If no operating directory is set, don't bother doing anything. */
|
||||
/* If no operating directory is set, there is nothing to check. */
|
||||
if (operating_dir == NULL)
|
||||
return FALSE;
|
||||
|
||||
assert(full_operating_dir != NULL);
|
||||
|
||||
fullpath = get_full_path(currpath);
|
||||
|
||||
/* If fullpath is NULL, it means some directory in the path doesn't
|
||||
@@ -1470,26 +1439,17 @@ bool check_operating_dir(const char *currpath, bool allow_tabcomp)
|
||||
* is what the user typed somewhere. We don't want to report a
|
||||
* non-existent directory as being outside the operating directory,
|
||||
* so we return FALSE. If allow_tabcomp is TRUE, then currpath
|
||||
* exists, but is not executable. So we say it isn't in the
|
||||
* exists, but is not executable. So we say it is outside the
|
||||
* operating directory. */
|
||||
if (fullpath == NULL)
|
||||
return allow_tabcomp;
|
||||
|
||||
whereami1 = strstr(fullpath, full_operating_dir);
|
||||
if (allow_tabcomp)
|
||||
whereami2 = strstr(full_operating_dir, fullpath);
|
||||
|
||||
/* If both searches failed, we're outside the operating directory.
|
||||
* Otherwise, check the search results. If the full operating
|
||||
* directory path is not at the beginning of the full current path
|
||||
* (for normal usage) and vice versa (for tab completion, if we're
|
||||
* allowing it), we're outside the operating directory. */
|
||||
if (whereami1 != fullpath && whereami2 != full_operating_dir)
|
||||
retval = TRUE;
|
||||
is_inside = (strstr(fullpath, operating_dir) == fullpath);
|
||||
begins_to_be = (allow_tabcomp &&
|
||||
strstr(operating_dir, fullpath) == operating_dir);
|
||||
free(fullpath);
|
||||
|
||||
/* Otherwise, we're still inside it. */
|
||||
return retval;
|
||||
return (!is_inside && !begins_to_be);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1511,27 +1471,18 @@ int prompt_failed_backupwrite(const char *filename)
|
||||
return response;
|
||||
}
|
||||
|
||||
/* Transform the specified backup directory to an absolute path,
|
||||
* and verify that it is usable. */
|
||||
void init_backup_dir(void)
|
||||
{
|
||||
char *full_backup_dir;
|
||||
backup_dir = free_and_assign(backup_dir, get_full_path(backup_dir));
|
||||
|
||||
if (backup_dir == NULL)
|
||||
return;
|
||||
/* If we can't get an absolute path (which means it doesn't exist or
|
||||
isn't accessible), or it's not a directory, fail. */
|
||||
if (backup_dir == NULL || backup_dir[strlen(backup_dir) - 1] != '/')
|
||||
die(_("Invalid backup directory\n"));
|
||||
|
||||
full_backup_dir = get_full_path(backup_dir);
|
||||
|
||||
/* If get_full_path() failed or the backup directory is
|
||||
* inaccessible, unset backup_dir. */
|
||||
if (full_backup_dir == NULL ||
|
||||
full_backup_dir[strlen(full_backup_dir) - 1] != '/') {
|
||||
free(full_backup_dir);
|
||||
free(backup_dir);
|
||||
backup_dir = NULL;
|
||||
} else {
|
||||
free(backup_dir);
|
||||
backup_dir = full_backup_dir;
|
||||
snuggly_fit(&backup_dir);
|
||||
}
|
||||
snuggly_fit(&backup_dir);
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
@@ -1621,8 +1572,8 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
/* If we're writing a temporary file, we're probably going outside
|
||||
* the operating directory, so skip the operating directory test. */
|
||||
if (!tmp && check_operating_dir(realname, FALSE)) {
|
||||
statusline(ALERT, _("Can't write outside of %s"), full_operating_dir);
|
||||
if (!tmp && outside_of_confinement(realname, FALSE)) {
|
||||
statusline(ALERT, _("Can't write outside of %s"), operating_dir);
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
#endif
|
||||
@@ -1650,11 +1601,10 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
if (ISSET(BACKUP_FILE) && !tmp && realexists && openfile->current_stat &&
|
||||
(method != OVERWRITE || openfile->mark_set ||
|
||||
openfile->current_stat->st_mtime == st.st_mtime)) {
|
||||
int backup_fd;
|
||||
FILE *backup_file;
|
||||
char *backupname;
|
||||
static struct timespec filetime[2];
|
||||
int backup_cflags;
|
||||
char *backupname;
|
||||
int backup_cflags, backup_fd;
|
||||
FILE *backup_file = NULL;
|
||||
|
||||
/* Save the original file's access and modification times. */
|
||||
filetime[0].tv_sec = openfile->current_stat->st_atime;
|
||||
@@ -1668,7 +1618,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
statusline(ALERT, _("Error reading %s: %s"), realname,
|
||||
strerror(errno));
|
||||
/* If we can't read from the original file, go on, since
|
||||
* only saving the original file is better than saving
|
||||
* only saving the current buffer is better than saving
|
||||
* nothing. */
|
||||
goto skip_backup;
|
||||
}
|
||||
@@ -1682,13 +1632,10 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
if (backup_dir != NULL) {
|
||||
char *backuptemp = get_full_path(realname);
|
||||
|
||||
/* If we can't get a canonical absolute path, just use the
|
||||
* filename portion of the given path. Otherwise, replace
|
||||
* slashes with exclamation marks in the full path. */
|
||||
if (backuptemp == NULL)
|
||||
/* If get_full_path() failed, we don't have a
|
||||
* canonicalized absolute pathname, so just use the
|
||||
* filename portion of the pathname. We use tail() so
|
||||
* that e.g. ../backupname will be backed up in
|
||||
* backupdir/backupname~ instead of
|
||||
* backupdir/../backupname~. */
|
||||
backuptemp = mallocstrcpy(NULL, tail(realname));
|
||||
else {
|
||||
size_t i = 0;
|
||||
@@ -1709,10 +1656,9 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
free(backuptemp);
|
||||
free(backupname);
|
||||
/* If we can't write to the backup, DON'T go on, since
|
||||
* whatever caused the backup file to fail (e.g. disk
|
||||
* full may well cause the real file write to fail,
|
||||
* which means we could lose both the backup and the
|
||||
* original! */
|
||||
* whatever caused the backup-file write to fail (e.g.
|
||||
* disk full) may well cause the real file write to fail
|
||||
* too, which means we could lose the original! */
|
||||
goto cleanup_and_exit;
|
||||
} else {
|
||||
free(backupname);
|
||||
@@ -1742,18 +1688,14 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
|
||||
backup_fd = open(backupname, backup_cflags,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
/* Now we've got a safe file stream. If the previous open()
|
||||
* call failed, this will return NULL. */
|
||||
backup_file = fdopen(backup_fd, "wb");
|
||||
|
||||
if (backup_fd < 0 || backup_file == NULL) {
|
||||
if (backup_fd >= 0)
|
||||
backup_file = fdopen(backup_fd, "wb");
|
||||
|
||||
if (backup_file == NULL) {
|
||||
statusline(HUSH, _("Error writing backup file %s: %s"),
|
||||
backupname, strerror(errno));
|
||||
free(backupname);
|
||||
/* If we can't make a backup, DON'T go on, since whatever caused
|
||||
* the backup to fail (e.g. disk full) may well cause the real
|
||||
* file write to fail, in which case we could lose both the
|
||||
* backup and the original! */
|
||||
goto cleanup_and_exit;
|
||||
}
|
||||
|
||||
@@ -1815,8 +1757,7 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
if (f_open == NULL) {
|
||||
original_umask = umask(0);
|
||||
|
||||
/* If we create a temp file, we don't let anyone else access it.
|
||||
* We create a temp file if tmp is TRUE. */
|
||||
/* If we create a temp file, we don't let anyone else access it. */
|
||||
if (tmp)
|
||||
umask(S_IRWXG | S_IRWXO);
|
||||
else
|
||||
@@ -1987,8 +1928,9 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
/* If we must set the filename, and it changed, adjust things. */
|
||||
if (!nonamechange && strcmp(openfile->filename, realname) != 0) {
|
||||
#ifndef DISABLE_COLOR
|
||||
char *oldname = openfile->syntax ? openfile->syntax->name : "";
|
||||
filestruct *line = openfile->fileage;
|
||||
const char *oldname, *newname;
|
||||
|
||||
oldname = openfile->syntax ? openfile->syntax->name : "";
|
||||
#endif
|
||||
openfile->filename = mallocstrcpy(openfile->filename, realname);
|
||||
|
||||
@@ -1997,13 +1939,16 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
color_update();
|
||||
color_init();
|
||||
|
||||
char *newname = openfile->syntax ? openfile->syntax->name : "";
|
||||
newname = openfile->syntax ? openfile->syntax->name : "";
|
||||
|
||||
/* If the syntax changed, discard and recompute the multidata. */
|
||||
if (strcmp(oldname, newname) != 0) {
|
||||
for (; line != NULL; line = line->next) {
|
||||
filestruct *line = openfile->fileage;
|
||||
|
||||
while (line != NULL) {
|
||||
free(line->multidata);
|
||||
line->multidata = NULL;
|
||||
line = line->next;
|
||||
}
|
||||
precalc_multicolorinfo();
|
||||
refresh_needed = TRUE;
|
||||
@@ -2284,6 +2229,8 @@ int do_writeout(bool exiting)
|
||||
openfile->current_stat->st_dev != st.st_dev ||
|
||||
openfile->current_stat->st_ino != st.st_ino)) {
|
||||
|
||||
warn_and_shortly_pause(_("File on disk has changed"));
|
||||
|
||||
if (do_yesno_prompt(FALSE, _("File was modified since "
|
||||
"you opened it; continue saving? ")) < 1)
|
||||
continue;
|
||||
@@ -2455,14 +2402,15 @@ char **username_tab_completion(const char *buf, size_t *num_matches,
|
||||
size_t buf_len)
|
||||
{
|
||||
char **matches = NULL;
|
||||
#ifdef HAVE_PWD_H
|
||||
const struct passwd *userdata;
|
||||
#endif
|
||||
|
||||
assert(buf != NULL && num_matches != NULL && buf_len > 0);
|
||||
|
||||
*num_matches = 0;
|
||||
|
||||
#ifdef HAVE_PWD_H
|
||||
const struct passwd *userdata;
|
||||
|
||||
while ((userdata = getpwent()) != NULL) {
|
||||
if (strncmp(userdata->pw_name, buf + 1, buf_len - 1) == 0) {
|
||||
/* Cool, found a match. Add it to the list. This makes a
|
||||
@@ -2471,7 +2419,7 @@ char **username_tab_completion(const char *buf, size_t *num_matches,
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
/* ...unless the match exists outside the operating
|
||||
* directory, in which case just go to the next match. */
|
||||
if (check_operating_dir(userdata->pw_dir, TRUE))
|
||||
if (outside_of_confinement(userdata->pw_dir, TRUE))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
@@ -2557,14 +2505,12 @@ char **cwd_tab_completion(const char *buf, bool allow_files, size_t
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
/* ...unless the match exists outside the operating
|
||||
* directory, in which case just go to the next match. */
|
||||
if (check_operating_dir(tmp, TRUE))
|
||||
skip_match = TRUE;
|
||||
skip_match = outside_of_confinement(tmp, TRUE);
|
||||
#endif
|
||||
|
||||
/* ...or unless the match isn't a directory and allow_files
|
||||
* isn't set, in which case just go to the next match. */
|
||||
if (!allow_files && !is_dir(tmp))
|
||||
skip_match = TRUE;
|
||||
skip_match = skip_match || (!allow_files && !is_dir(tmp));
|
||||
|
||||
free(tmp);
|
||||
|
||||
@@ -2831,59 +2777,62 @@ int check_dotnano(void)
|
||||
/* Load the search and replace histories from ~/.nano/search_history. */
|
||||
void load_history(void)
|
||||
{
|
||||
char *nanohist = histfilename();
|
||||
char *searchhist = histfilename();
|
||||
char *legacyhist = legacyhistfilename();
|
||||
struct stat hstat;
|
||||
FILE *hist;
|
||||
|
||||
/* If no home directory was found, we can't do anything. */
|
||||
if (searchhist == NULL || legacyhist == NULL)
|
||||
return;
|
||||
|
||||
/* If there is an old history file, migrate it. */
|
||||
/* (To be removed in 2018.) */
|
||||
if (stat(legacyhist, &hstat) != -1 && stat(nanohist, &hstat) == -1) {
|
||||
if (rename(legacyhist, nanohist) == -1)
|
||||
if (stat(legacyhist, &hstat) != -1 && stat(searchhist, &hstat) == -1) {
|
||||
if (rename(legacyhist, searchhist) == -1)
|
||||
history_error(N_("Detected a legacy nano history file (%s) which I tried to move\n"
|
||||
"to the preferred location (%s) but encountered an error: %s"),
|
||||
legacyhist, nanohist, strerror(errno));
|
||||
legacyhist, searchhist, strerror(errno));
|
||||
else
|
||||
history_error(N_("Detected a legacy nano history file (%s) which I moved\n"
|
||||
"to the preferred location (%s)\n(see the nano FAQ about this change)"),
|
||||
legacyhist, nanohist);
|
||||
legacyhist, searchhist);
|
||||
}
|
||||
|
||||
/* Assume do_rcfile() has reported a missing home directory. */
|
||||
if (nanohist != NULL) {
|
||||
FILE *hist = fopen(nanohist, "rb");
|
||||
hist = fopen(searchhist, "rb");
|
||||
|
||||
if (hist == NULL) {
|
||||
if (errno != ENOENT) {
|
||||
/* Don't save history when we quit. */
|
||||
UNSET(HISTORYLOG);
|
||||
history_error(N_("Error reading %s: %s"), nanohist,
|
||||
if (hist == NULL) {
|
||||
if (errno != ENOENT) {
|
||||
/* When reading failed, don't save history when we quit. */
|
||||
UNSET(HISTORYLOG);
|
||||
history_error(N_("Error reading %s: %s"), searchhist,
|
||||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
/* Load a history list (first the search history, then the
|
||||
* replace history) from the oldest entry to the newest.
|
||||
* Assume the last history entry is a blank line. */
|
||||
filestruct **history = &search_history;
|
||||
char *line = NULL;
|
||||
size_t buf_len = 0;
|
||||
ssize_t read;
|
||||
|
||||
while ((read = getline(&line, &buf_len, hist)) > 0) {
|
||||
line[--read] = '\0';
|
||||
if (read > 0) {
|
||||
/* Encode any embedded NUL as 0x0A. */
|
||||
unsunder(line, read);
|
||||
update_history(history, line);
|
||||
} else
|
||||
history = &replace_history;
|
||||
}
|
||||
|
||||
fclose(hist);
|
||||
free(line);
|
||||
}
|
||||
free(nanohist);
|
||||
free(legacyhist);
|
||||
} else {
|
||||
/* Load the two history lists -- first the search history, then
|
||||
* the replace history -- from the oldest entry to the newest.
|
||||
* The two lists are separated by an empty line. */
|
||||
filestruct **history = &search_history;
|
||||
char *line = NULL;
|
||||
size_t buf_len = 0;
|
||||
ssize_t read;
|
||||
|
||||
while ((read = getline(&line, &buf_len, hist)) > 0) {
|
||||
line[--read] = '\0';
|
||||
if (read > 0) {
|
||||
/* Encode any embedded NUL as 0x0A. */
|
||||
unsunder(line, read);
|
||||
update_history(history, line);
|
||||
} else
|
||||
history = &replace_history;
|
||||
}
|
||||
|
||||
fclose(hist);
|
||||
free(line);
|
||||
}
|
||||
|
||||
free(searchhist);
|
||||
free(legacyhist);
|
||||
}
|
||||
|
||||
/* Write the lines of a history list, starting with the line at head, to
|
||||
@@ -2912,35 +2861,36 @@ bool writehist(FILE *hist, const filestruct *head)
|
||||
/* Save the search and replace histories to ~/.nano/search_history. */
|
||||
void save_history(void)
|
||||
{
|
||||
char *nanohist;
|
||||
char *searchhist;
|
||||
FILE *hist;
|
||||
|
||||
/* Don't save unchanged or empty histories. */
|
||||
/* If the histories are unchanged or empty, don't bother saving them. */
|
||||
if (!history_has_changed() || (searchbot->lineno == 1 &&
|
||||
replacebot->lineno == 1))
|
||||
replacebot->lineno == 1))
|
||||
return;
|
||||
|
||||
nanohist = histfilename();
|
||||
searchhist = histfilename();
|
||||
|
||||
if (nanohist != NULL) {
|
||||
FILE *hist = fopen(nanohist, "wb");
|
||||
if (searchhist == NULL)
|
||||
return;
|
||||
|
||||
if (hist == NULL)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), nanohist,
|
||||
hist = fopen(searchhist, "wb");
|
||||
|
||||
if (hist == NULL)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), searchhist,
|
||||
strerror(errno));
|
||||
else {
|
||||
/* Make sure no one else can read from or write to the
|
||||
* history file. */
|
||||
chmod(nanohist, S_IRUSR | S_IWUSR);
|
||||
else {
|
||||
/* Don't allow others to read or write the history file. */
|
||||
chmod(searchhist, S_IRUSR | S_IWUSR);
|
||||
|
||||
if (!writehist(hist, searchage) || !writehist(hist, replaceage))
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), nanohist,
|
||||
if (!writehist(hist, searchage) || !writehist(hist, replaceage))
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), searchhist,
|
||||
strerror(errno));
|
||||
|
||||
fclose(hist);
|
||||
}
|
||||
|
||||
free(nanohist);
|
||||
fclose(hist);
|
||||
}
|
||||
|
||||
free(searchhist);
|
||||
}
|
||||
|
||||
/* Save the recorded last file positions to ~/.nano/filepos_history. */
|
||||
|
||||
152
src/global.c
152
src/global.c
@@ -24,7 +24,6 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "assert.h"
|
||||
|
||||
/* Global variables. */
|
||||
#ifndef NANO_TINY
|
||||
@@ -57,6 +56,9 @@ bool have_palette = FALSE;
|
||||
/* Whether the colors for the current syntax have been initialized. */
|
||||
#endif
|
||||
|
||||
bool suppress_cursorpos = FALSE;
|
||||
/* Should we skip constant position display for current keystroke? */
|
||||
|
||||
message_type lastmessage = HUSH;
|
||||
/* Messages of type HUSH should not overwrite type MILD nor ALERT. */
|
||||
|
||||
@@ -75,6 +77,7 @@ int controlleft, controlright, controlup, controldown, controlhome, controlend;
|
||||
#ifndef NANO_TINY
|
||||
int shiftcontrolleft, shiftcontrolright, shiftcontrolup, shiftcontroldown;
|
||||
int shiftcontrolhome, shiftcontrolend;
|
||||
int altleft, altright, altup, altdown;
|
||||
int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown;
|
||||
#endif
|
||||
|
||||
@@ -146,9 +149,6 @@ char *quoteerr = NULL;
|
||||
char *word_chars = NULL;
|
||||
/* Nonalphanumeric characters that also form words. */
|
||||
|
||||
bool nodelay_mode = FALSE;
|
||||
/* Are we checking for a cancel wile doing something? */
|
||||
|
||||
char *answer = NULL;
|
||||
/* The answer string used by the statusbar prompt. */
|
||||
|
||||
@@ -166,10 +166,7 @@ const char *locking_suffix = ".swp";
|
||||
#endif
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
char *operating_dir = NULL;
|
||||
/* The relative path to the operating directory, which we can't
|
||||
* move outside of. */
|
||||
char *full_operating_dir = NULL;
|
||||
/* The full path to it. */
|
||||
/* The path to our confining "operating" directory, when given. */
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_SPELLER
|
||||
@@ -227,10 +224,10 @@ regmatch_t regmatches[10];
|
||||
int hilite_attribute = A_REVERSE;
|
||||
/* The curses attribute we use to highlight something. */
|
||||
#ifndef DISABLE_COLOR
|
||||
char* specified_color_combo[] = {};
|
||||
char* specified_color_combo[] = {NULL};
|
||||
/* The color combinations as specified in the rcfile. */
|
||||
#endif
|
||||
int interface_color_pair[] = {};
|
||||
int interface_color_pair[] = {0};
|
||||
/* The processed color pairs for the interface elements. */
|
||||
|
||||
char *homedir = NULL;
|
||||
@@ -313,7 +310,7 @@ void discard_buffer(void)
|
||||
void add_to_funcs(void (*func)(void), int menus, const char *desc, const char *help,
|
||||
bool blank_after, bool viewok)
|
||||
{
|
||||
subnfunc *f = (subnfunc *)nmalloc(sizeof(subnfunc));
|
||||
subnfunc *f = nmalloc(sizeof(subnfunc));
|
||||
|
||||
if (allfuncs == NULL)
|
||||
allfuncs = f;
|
||||
@@ -344,7 +341,7 @@ void add_to_sclist(int menus, const char *scstring, const int keycode,
|
||||
#ifndef NANO_TINY
|
||||
static int counter = 0;
|
||||
#endif
|
||||
sc *s = (sc *)nmalloc(sizeof(sc));
|
||||
sc *s = nmalloc(sizeof(sc));
|
||||
|
||||
/* Start the list, or tack on the next item. */
|
||||
if (sclist == NULL)
|
||||
@@ -424,28 +421,45 @@ functionptrtype func_from_key(int *kbinput)
|
||||
void assign_keyinfo(sc *s, const char *keystring, const int keycode)
|
||||
{
|
||||
s->keystr = keystring;
|
||||
s->meta = (keystring[0] == 'M');
|
||||
s->meta = (keystring[0] == 'M' && keystring[2] != '\xE2');
|
||||
|
||||
assert(strlen(keystring) > 1 && (!s->meta || strlen(keystring) > 2));
|
||||
|
||||
if (keycode)
|
||||
s->keycode = keycode;
|
||||
else if (keystring[0] == '^') {
|
||||
else
|
||||
s->keycode = keycode_from_string(keystring);
|
||||
}
|
||||
|
||||
/* Parse the given keystring and return the corresponding keycode,
|
||||
* or return -1 when the string is invalid. */
|
||||
int keycode_from_string(const char *keystring)
|
||||
{
|
||||
if (keystring[0] == '^') {
|
||||
if (strcasecmp(keystring, "^Space") == 0)
|
||||
s->keycode = 0;
|
||||
return 0;
|
||||
if (strlen(keystring) == 2)
|
||||
return keystring[1] - 64;
|
||||
else
|
||||
s->keycode = keystring[1] - 64;
|
||||
} else if (s->meta) {
|
||||
return -1;
|
||||
} else if (keystring[0] == 'M') {
|
||||
if (strcasecmp(keystring, "M-Space") == 0)
|
||||
s->keycode = (int)' ';
|
||||
return (int)' ';
|
||||
if (keystring[1] == '-')
|
||||
return tolower((unsigned char)keystring[2]);
|
||||
else
|
||||
s->keycode = tolower((unsigned char)keystring[2]);
|
||||
} else if (keystring[0] == 'F')
|
||||
s->keycode = KEY_F0 + atoi(&keystring[1]);
|
||||
else if (!strcasecmp(keystring, "Ins"))
|
||||
s->keycode = KEY_IC;
|
||||
return -1;
|
||||
} else if (keystring[0] == 'F') {
|
||||
int fn = atoi(&keystring[1]);
|
||||
if (fn < 0 || fn > 63)
|
||||
return -1;
|
||||
return KEY_F0 + fn;
|
||||
} else if (!strcasecmp(keystring, "Ins"))
|
||||
return KEY_IC;
|
||||
else if (!strcasecmp(keystring, "Del"))
|
||||
s->keycode = KEY_DC;
|
||||
return KEY_DC;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -493,11 +507,8 @@ void shortcut_init(void)
|
||||
const char *whereis_next_tag = N_("WhereIs Next");
|
||||
|
||||
#ifdef ENABLE_HELP
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
/* TRANSLATORS: The next long series of strings are shortcut descriptions;
|
||||
* they are best kept shorter than 56 characters, but may be longer. */
|
||||
const char *nano_justify_msg = N_("Justify the current paragraph");
|
||||
#endif
|
||||
const char *nano_cancel_msg = N_("Cancel the current function");
|
||||
const char *nano_help_msg = N_("Display this help text");
|
||||
const char *nano_exit_msg =
|
||||
@@ -589,6 +600,7 @@ void shortcut_init(void)
|
||||
N_("Cut from the cursor position to the end of the file");
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
const char *nano_justify_msg = N_("Justify the current paragraph");
|
||||
const char *nano_fulljustify_msg = N_("Justify the entire file");
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
@@ -623,9 +635,6 @@ void shortcut_init(void)
|
||||
const char *nano_next_history_msg =
|
||||
N_("Recall the next search/replace string");
|
||||
#endif
|
||||
#ifdef ENABLE_BROWSER
|
||||
const char *nano_tofiles_msg = N_("Go to file browser");
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
const char *nano_dos_msg = N_("Toggle the use of DOS format");
|
||||
const char *nano_mac_msg = N_("Toggle the use of Mac format");
|
||||
@@ -639,6 +648,7 @@ void shortcut_init(void)
|
||||
#endif
|
||||
const char *nano_discard_buffer_msg = N_("Close buffer without saving it");
|
||||
#ifdef ENABLE_BROWSER
|
||||
const char *nano_tofiles_msg = N_("Go to file browser");
|
||||
const char *nano_exitbrowser_msg = N_("Exit from the file browser");
|
||||
const char *nano_firstfile_msg = N_("Go to the first file in the list");
|
||||
const char *nano_lastfile_msg = N_("Go to the last file in the list");
|
||||
@@ -717,22 +727,24 @@ void shortcut_init(void)
|
||||
add_to_funcs(do_search, MBROWSER,
|
||||
whereis_tag, IFSCHELP(nano_browser_whereis_msg), TOGETHER, VIEW);
|
||||
|
||||
add_to_funcs(do_research, MBROWSER,
|
||||
whereis_next_tag, IFSCHELP(nano_whereis_next_msg), BLANKAFTER, VIEW);
|
||||
|
||||
add_to_funcs(goto_dir_void, MBROWSER,
|
||||
N_("Go To Dir"), IFSCHELP(nano_gotodir_msg), BLANKAFTER, VIEW);
|
||||
N_("Go To Dir"), IFSCHELP(nano_gotodir_msg), TOGETHER, VIEW);
|
||||
|
||||
add_to_funcs(total_refresh, MBROWSER,
|
||||
refresh_tag, IFSCHELP(nano_browser_refresh_msg), BLANKAFTER, VIEW);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_HELP
|
||||
/* The description ("x") and blank_after (0) are irrelevant,
|
||||
* because the help viewer does not have a help text. */
|
||||
add_to_funcs(do_exit, MHELP, exit_tag, "x", 0, VIEW);
|
||||
|
||||
add_to_funcs(total_refresh, MHELP, refresh_tag, "x", 0, VIEW);
|
||||
add_to_funcs(do_exit, MHELP, close_tag, "x", 0, VIEW);
|
||||
|
||||
add_to_funcs(do_search, MHELP, whereis_tag, "x", 0, VIEW);
|
||||
add_to_funcs(do_research, MHELP, whereis_next_tag, "x", 0, VIEW);
|
||||
|
||||
add_to_funcs(do_up_void, MHELP, prev_line_tag, "x", 0, VIEW);
|
||||
add_to_funcs(do_down_void, MHELP, next_line_tag, "x", 0, VIEW);
|
||||
#endif
|
||||
|
||||
add_to_funcs(do_cut_text_void, MMAIN,
|
||||
@@ -836,14 +848,14 @@ void shortcut_init(void)
|
||||
add_to_funcs(do_next_word_void, MMAIN,
|
||||
N_("Next Word"), IFSCHELP(nano_nextword_msg), TOGETHER, VIEW);
|
||||
|
||||
add_to_funcs(do_home_void, MMAIN,
|
||||
add_to_funcs(do_home, MMAIN,
|
||||
N_("Home"), IFSCHELP(nano_home_msg), TOGETHER, VIEW);
|
||||
add_to_funcs(do_end_void, MMAIN,
|
||||
add_to_funcs(do_end, MMAIN,
|
||||
N_("End"), IFSCHELP(nano_end_msg), BLANKAFTER, VIEW);
|
||||
|
||||
add_to_funcs(do_up_void, MMAIN|MBROWSER,
|
||||
add_to_funcs(do_up_void, MMAIN|MHELP|MBROWSER,
|
||||
prev_line_tag, IFSCHELP(nano_prevline_msg), TOGETHER, VIEW);
|
||||
add_to_funcs(do_down_void, MMAIN|MBROWSER,
|
||||
add_to_funcs(do_down_void, MMAIN|MHELP|MBROWSER,
|
||||
next_line_tag, IFSCHELP(nano_nextline_msg), TOGETHER, VIEW);
|
||||
#ifndef NANO_TINY
|
||||
add_to_funcs(do_scroll_up, MMAIN,
|
||||
@@ -938,7 +950,7 @@ void shortcut_init(void)
|
||||
N_("Suspend"), IFSCHELP(nano_suspend_msg), BLANKAFTER, VIEW);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
add_to_funcs(do_indent_void, MMAIN,
|
||||
add_to_funcs(do_indent, MMAIN,
|
||||
N_("Indent Text"), IFSCHELP(nano_indent_msg), TOGETHER, NOVIEW);
|
||||
add_to_funcs(do_unindent, MMAIN,
|
||||
N_("Unindent Text"), IFSCHELP(nano_unindent_msg), BLANKAFTER, NOVIEW);
|
||||
@@ -1023,16 +1035,6 @@ void shortcut_init(void)
|
||||
N_("First File"), IFSCHELP(nano_firstfile_msg), TOGETHER, VIEW);
|
||||
add_to_funcs(do_last_file, (MBROWSER|MWHEREISFILE),
|
||||
N_("Last File"), IFSCHELP(nano_lastfile_msg), BLANKAFTER, VIEW);
|
||||
#endif
|
||||
|
||||
add_to_funcs(discard_buffer, MWRITEFILE,
|
||||
N_("Discard buffer"), IFSCHELP(nano_discard_buffer_msg), BLANKAFTER, NOVIEW);
|
||||
|
||||
#ifdef ENABLE_BROWSER
|
||||
add_to_funcs(do_research, MBROWSER,
|
||||
whereis_next_tag, IFSCHELP(nano_whereis_next_msg), TOGETHER, VIEW);
|
||||
add_to_funcs(total_refresh, MBROWSER,
|
||||
refresh_tag, IFSCHELP(nano_browser_refresh_msg), BLANKAFTER, VIEW);
|
||||
#ifndef NANO_TINY
|
||||
add_to_funcs(do_prev_word_void, MBROWSER,
|
||||
N_("Left Column"), IFSCHELP(nano_browser_lefthand_msg), TOGETHER, VIEW);
|
||||
@@ -1043,7 +1045,10 @@ void shortcut_init(void)
|
||||
add_to_funcs(do_next_block, MBROWSER,
|
||||
N_("Bottom Row"), IFSCHELP(nano_browser_bottomrow_msg), BLANKAFTER, VIEW);
|
||||
#endif
|
||||
#endif
|
||||
#endif /* ENABLE_BROWSER */
|
||||
|
||||
add_to_funcs(discard_buffer, MWRITEFILE,
|
||||
N_("Discard buffer"), IFSCHELP(nano_discard_buffer_msg), BLANKAFTER, NOVIEW);
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
add_to_funcs(do_page_up, MLINTER,
|
||||
@@ -1071,8 +1076,8 @@ void shortcut_init(void)
|
||||
add_to_sclist(MMAIN, "F14", 0, do_replace, 0);
|
||||
add_to_sclist(MMOST, "^K", 0, do_cut_text_void, 0);
|
||||
add_to_sclist(MMOST, "F9", 0, do_cut_text_void, 0);
|
||||
add_to_sclist(MMAIN, "^U", 0, do_uncut_text, 0);
|
||||
add_to_sclist(MMAIN, "F10", 0, do_uncut_text, 0);
|
||||
add_to_sclist(MMOST, "^U", 0, do_uncut_text, 0);
|
||||
add_to_sclist(MMOST, "F10", 0, do_uncut_text, 0);
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
add_to_sclist(MMAIN, "^J", 0, do_justify_void, 0);
|
||||
add_to_sclist(MMAIN, "F4", 0, do_justify_void, 0);
|
||||
@@ -1114,7 +1119,7 @@ void shortcut_init(void)
|
||||
add_to_sclist(MMAIN, "F15", 0, do_mark, 0);
|
||||
add_to_sclist(MMAIN, "M-6", 0, do_copy_text, 0);
|
||||
add_to_sclist(MMAIN, "M-^", 0, do_copy_text, 0);
|
||||
add_to_sclist(MMAIN, "M-}", 0, do_indent_void, 0);
|
||||
add_to_sclist(MMAIN, "M-}", 0, do_indent, 0);
|
||||
add_to_sclist(MMAIN, "M-{", 0, do_unindent, 0);
|
||||
add_to_sclist(MMAIN, "M-U", 0, do_undo, 0);
|
||||
add_to_sclist(MMAIN, "M-E", 0, do_redo, 0);
|
||||
@@ -1131,22 +1136,30 @@ void shortcut_init(void)
|
||||
if (using_utf8()) {
|
||||
add_to_sclist(MMOST, "\xE2\x86\x90", KEY_LEFT, do_left, 0);
|
||||
add_to_sclist(MMOST, "\xE2\x86\x92", KEY_RIGHT, do_right, 0);
|
||||
add_to_sclist(MMOST, "^\xE2\x86\x90", CONTROL_LEFT, do_prev_word_void, 0);
|
||||
add_to_sclist(MMOST, "^\xE2\x86\x92", CONTROL_RIGHT, do_next_word_void, 0);
|
||||
add_to_sclist(MSOME, "^\xE2\x86\x90", CONTROL_LEFT, do_prev_word_void, 0);
|
||||
add_to_sclist(MSOME, "^\xE2\x86\x92", CONTROL_RIGHT, do_next_word_void, 0);
|
||||
#ifdef ENABLE_MULTIBUFFER
|
||||
add_to_sclist(MMAIN, "M-\xE2\x86\x90", ALT_LEFT, switch_to_prev_buffer_void, 0);
|
||||
add_to_sclist(MMAIN, "M-\xE2\x86\x92", ALT_RIGHT, switch_to_next_buffer_void, 0);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "M-\xE2\x86\x91", ALT_UP, do_findprevious, 0);
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "M-\xE2\x86\x93", ALT_DOWN, do_findnext, 0);
|
||||
#endif
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
add_to_sclist(MMOST, "Left", KEY_LEFT, do_left, 0);
|
||||
add_to_sclist(MMOST, "Right", KEY_RIGHT, do_right, 0);
|
||||
add_to_sclist(MMOST, "^Left", CONTROL_LEFT, do_prev_word_void, 0);
|
||||
add_to_sclist(MMOST, "^Right", CONTROL_RIGHT, do_next_word_void, 0);
|
||||
add_to_sclist(MSOME, "^Left", CONTROL_LEFT, do_prev_word_void, 0);
|
||||
add_to_sclist(MSOME, "^Right", CONTROL_RIGHT, do_next_word_void, 0);
|
||||
}
|
||||
add_to_sclist(MMOST, "M-Space", 0, do_prev_word_void, 0);
|
||||
add_to_sclist(MMOST, "^Space", 0, do_next_word_void, 0);
|
||||
add_to_sclist((MMOST & ~MBROWSER), "^A", 0, do_home_void, 0);
|
||||
add_to_sclist((MMOST & ~MBROWSER), "Home", KEY_HOME, do_home_void, 0);
|
||||
add_to_sclist((MMOST & ~MBROWSER), "^E", 0, do_end_void, 0);
|
||||
add_to_sclist((MMOST & ~MBROWSER), "End", KEY_END, do_end_void, 0);
|
||||
add_to_sclist((MMOST & ~MBROWSER), "^A", 0, do_home, 0);
|
||||
add_to_sclist((MMOST & ~MBROWSER), "Home", KEY_HOME, do_home, 0);
|
||||
add_to_sclist((MMOST & ~MBROWSER), "^E", 0, do_end, 0);
|
||||
add_to_sclist((MMOST & ~MBROWSER), "End", KEY_END, do_end, 0);
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "^P", 0, do_up_void, 0);
|
||||
add_to_sclist(MMAIN|MHELP|MBROWSER, "^N", 0, do_down_void, 0);
|
||||
#ifdef ENABLE_UTF8
|
||||
@@ -1212,7 +1225,7 @@ void shortcut_init(void)
|
||||
/* Group of "Editing-behavior" toggles. */
|
||||
add_to_sclist(MMAIN, "M-H", 0, do_toggle_void, SMART_HOME);
|
||||
add_to_sclist(MMAIN, "M-I", 0, do_toggle_void, AUTOINDENT);
|
||||
add_to_sclist(MMAIN, "M-K", 0, do_toggle_void, CUT_TO_END);
|
||||
add_to_sclist(MMAIN, "M-K", 0, do_toggle_void, CUT_FROM_CURSOR);
|
||||
#ifndef DISABLE_WRAPPING
|
||||
add_to_sclist(MMAIN, "M-L", 0, do_toggle_void, NO_WRAP);
|
||||
#endif
|
||||
@@ -1384,7 +1397,7 @@ const char *flagtostr(int flag)
|
||||
return N_("Smart home key");
|
||||
case AUTOINDENT:
|
||||
return N_("Auto indent");
|
||||
case CUT_TO_END:
|
||||
case CUT_FROM_CURSOR:
|
||||
return N_("Cut to end");
|
||||
case NO_WRAP:
|
||||
return N_("Hard wrapping of overlong lines");
|
||||
@@ -1497,7 +1510,7 @@ sc *strtosc(const char *input)
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
else if (!strcasecmp(input, "indent"))
|
||||
s->scfunc = do_indent_void;
|
||||
s->scfunc = do_indent;
|
||||
else if (!strcasecmp(input, "unindent"))
|
||||
s->scfunc = do_unindent;
|
||||
else if (!strcasecmp(input, "scrollup"))
|
||||
@@ -1534,9 +1547,9 @@ sc *strtosc(const char *input)
|
||||
else if (!strcasecmp(input, "nextword"))
|
||||
s->scfunc = do_next_word_void;
|
||||
else if (!strcasecmp(input, "home"))
|
||||
s->scfunc = do_home_void;
|
||||
s->scfunc = do_home;
|
||||
else if (!strcasecmp(input, "end"))
|
||||
s->scfunc = do_end_void;
|
||||
s->scfunc = do_end;
|
||||
else if (!strcasecmp(input, "prevblock"))
|
||||
s->scfunc = do_prev_block;
|
||||
else if (!strcasecmp(input, "nextblock"))
|
||||
@@ -1643,7 +1656,7 @@ sc *strtosc(const char *input)
|
||||
else if (!strcasecmp(input, "autoindent"))
|
||||
s->toggle = AUTOINDENT;
|
||||
else if (!strcasecmp(input, "cuttoend"))
|
||||
s->toggle = CUT_TO_END;
|
||||
s->toggle = CUT_FROM_CURSOR;
|
||||
#ifndef DISABLE_WRAPPING
|
||||
else if (!strcasecmp(input, "nowrap"))
|
||||
s->toggle = NO_WRAP;
|
||||
@@ -1744,7 +1757,6 @@ void thanks_for_all_the_fish(void)
|
||||
#endif
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
free(operating_dir);
|
||||
free(full_operating_dir);
|
||||
#endif
|
||||
free(answer);
|
||||
free(last_search);
|
||||
|
||||
22
src/help.c
22
src/help.c
@@ -22,10 +22,8 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ENABLE_HELP
|
||||
|
||||
@@ -210,8 +208,11 @@ void do_help(void)
|
||||
bottombars(MHELP);
|
||||
} else if (func == do_research) {
|
||||
do_research();
|
||||
currmenu = MHELP;
|
||||
#ifndef NANO_TINY
|
||||
} else if (func == do_findprevious) {
|
||||
do_findprevious();
|
||||
} else if (func == do_findnext) {
|
||||
do_findnext();
|
||||
} else if (kbinput == KEY_WINCH) {
|
||||
; /* Nothing to do. */
|
||||
#endif
|
||||
@@ -228,11 +229,9 @@ void do_help(void)
|
||||
unbound_key(kbinput);
|
||||
|
||||
/* If we searched and found something, let the cursor show it. */
|
||||
if (didfind == 1)
|
||||
curs_set(1);
|
||||
else
|
||||
curs_set(0);
|
||||
curs_set(didfind == 1 ? 1 : 0);
|
||||
|
||||
currmenu = MHELP;
|
||||
edit_refresh();
|
||||
|
||||
location = 0;
|
||||
@@ -260,8 +259,6 @@ void do_help(void)
|
||||
switch_to_prev_buffer_void();
|
||||
|
||||
if (ISSET(NO_HELP)) {
|
||||
blank_bottombars();
|
||||
wnoutrefresh(bottomwin);
|
||||
currmenu = oldmenu;
|
||||
window_init();
|
||||
} else
|
||||
@@ -514,7 +511,7 @@ void help_init(void)
|
||||
if (scsfound == 1) {
|
||||
sprintf(ptr, "%s ", s->keystr);
|
||||
/* Unicode arrows take three bytes instead of one. */
|
||||
if (s->keystr[0] == '\xE2' || s->keystr[1] == '\xE2')
|
||||
if (strstr(s->keystr, "\xE2") != NULL)
|
||||
ptr += 8;
|
||||
else
|
||||
ptr += 6;
|
||||
@@ -580,6 +577,9 @@ functionptrtype parse_help_input(int *kbinput)
|
||||
case '/':
|
||||
return do_search;
|
||||
case 'N':
|
||||
#ifndef NANO_TINY
|
||||
return do_findprevious;
|
||||
#endif
|
||||
case 'n':
|
||||
return do_research;
|
||||
case 'E':
|
||||
|
||||
327
src/move.c
327
src/move.c
@@ -22,7 +22,6 @@
|
||||
#include "proto.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* Move to the first line of the file. */
|
||||
void do_first_line(void)
|
||||
@@ -53,13 +52,10 @@ void get_edge_and_target(size_t *leftedge, size_t *target_column)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
size_t realspan = strlenpt(openfile->current->data);
|
||||
size_t shim = editwincols * (1 + (tabsize / editwincols));
|
||||
|
||||
if (realspan > openfile->placewewant)
|
||||
realspan = openfile->placewewant;
|
||||
|
||||
*leftedge = (realspan / editwincols) * editwincols;
|
||||
*target_column = openfile->placewewant % editwincols;
|
||||
*leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
*target_column = (openfile->placewewant + shim - *leftedge) % editwincols;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -68,6 +64,51 @@ void get_edge_and_target(size_t *leftedge, size_t *target_column)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the index in line->data that corresponds to the given column on the
|
||||
* chunk that starts at the given leftedge. If the index lands on a tab, and
|
||||
* this tab starts on an earlier chunk, and the tab ends on this row OR we're
|
||||
* going forward, then increment the index and recalculate leftedge. */
|
||||
size_t proper_x(filestruct *line, size_t *leftedge, bool forward,
|
||||
size_t column, bool *shifted)
|
||||
{
|
||||
size_t index = actual_x(line->data, column);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP) && line->data[index] == '\t' && (forward ||
|
||||
*leftedge / tabsize < (*leftedge + editwincols) / tabsize) &&
|
||||
*leftedge % tabsize != 0 && column < *leftedge + tabsize) {
|
||||
index++;
|
||||
|
||||
*leftedge = leftedge_for(strnlenpt(line->data, index), line);
|
||||
|
||||
if (shifted != NULL)
|
||||
*shifted = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
size_t newer_x = actual_x(openfile->current->data, *leftedge + target);
|
||||
|
||||
if (newer_x > openfile->current_x)
|
||||
openfile->current_x = newer_x;
|
||||
}
|
||||
|
||||
openfile->placewewant = *leftedge + target;
|
||||
}
|
||||
|
||||
/* Move up nearly one screenful. */
|
||||
void do_page_up(void)
|
||||
{
|
||||
@@ -78,11 +119,12 @@ void do_page_up(void)
|
||||
* beginning of the top line of the edit window, as Pico does. */
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
openfile->current = openfile->edittop;
|
||||
openfile->placewewant = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
}
|
||||
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
leftedge = leftedge_for(openfile->firstcolumn, openfile->edittop);
|
||||
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. */
|
||||
@@ -91,9 +133,7 @@ void do_page_up(void)
|
||||
return;
|
||||
}
|
||||
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
openfile->placewewant);
|
||||
set_proper_index_and_pww(&leftedge, target_column, FALSE);
|
||||
|
||||
/* Move the viewport so that the cursor stays immobile, if possible. */
|
||||
adjust_viewport(STATIONARY);
|
||||
@@ -110,11 +150,12 @@ void do_page_down(void)
|
||||
* beginning of the top line of the edit window, as Pico does. */
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
openfile->current = openfile->edittop;
|
||||
openfile->placewewant = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
}
|
||||
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
leftedge = leftedge_for(openfile->firstcolumn, openfile->edittop);
|
||||
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. */
|
||||
@@ -123,9 +164,7 @@ void do_page_down(void)
|
||||
return;
|
||||
}
|
||||
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
openfile->placewewant);
|
||||
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||
|
||||
/* Move the viewport so that the cursor stays immobile, if possible. */
|
||||
adjust_viewport(STATIONARY);
|
||||
@@ -148,13 +187,7 @@ void do_para_begin(bool update_screen)
|
||||
openfile->current_x = 0;
|
||||
|
||||
if (update_screen)
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Move up to first start of a paragraph before the current line. */
|
||||
void do_para_begin_void(void)
|
||||
{
|
||||
do_para_begin(TRUE);
|
||||
edit_redraw(was_current, CENTERING);
|
||||
}
|
||||
|
||||
/* Move down to the beginning of the last line of the current paragraph.
|
||||
@@ -184,7 +217,13 @@ void do_para_end(bool update_screen)
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
|
||||
if (update_screen)
|
||||
edit_redraw(was_current);
|
||||
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);
|
||||
}
|
||||
|
||||
/* Move down to just after the first end of a paragraph. */
|
||||
@@ -213,7 +252,7 @@ void do_prev_block(void)
|
||||
openfile->current = openfile->current->next;
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current);
|
||||
edit_redraw(was_current, CENTERING);
|
||||
}
|
||||
|
||||
/* Move to the next block of text in the file. */
|
||||
@@ -231,7 +270,7 @@ void do_next_block(void)
|
||||
}
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current);
|
||||
edit_redraw(was_current, CENTERING);
|
||||
}
|
||||
|
||||
/* Move to the previous word in the file. If allow_punct is TRUE, treat
|
||||
@@ -274,17 +313,8 @@ void do_prev_word(bool allow_punct, bool update_screen)
|
||||
openfile->current_x = move_mbright(openfile->current->data,
|
||||
openfile->current_x);
|
||||
|
||||
if (update_screen) {
|
||||
focusing = FALSE;
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
|
||||
/* Move to the next word in the file. If allow_punct is TRUE, treat
|
||||
@@ -323,15 +353,20 @@ bool do_next_word(bool allow_punct, bool update_screen)
|
||||
break;
|
||||
}
|
||||
|
||||
if (update_screen) {
|
||||
focusing = FALSE;
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
@@ -340,23 +375,24 @@ void do_next_word_void(void)
|
||||
}
|
||||
|
||||
/* Move to the beginning of the current line (or softwrapped chunk).
|
||||
* If be_clever is TRUE, do a smart home when wanted and possible,
|
||||
* and do a dynamic home when in softwrap mode and it's possible.
|
||||
* If be_clever is FALSE, just do a simple home. */
|
||||
void do_home(bool be_clever)
|
||||
* When enabled, do a smart home. When softwrapping, go the beginning
|
||||
* 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 = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
bool moved_off_chunk = TRUE;
|
||||
#ifndef NANO_TINY
|
||||
bool moved = FALSE;
|
||||
size_t leftedge_x = 0;
|
||||
size_t leftedge = 0, leftedge_x = 0;
|
||||
|
||||
if (ISSET(SOFTWRAP))
|
||||
leftedge_x = actual_x(openfile->current->data,
|
||||
(was_column / editwincols) * editwincols);
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
leftedge = leftedge_for(was_column, openfile->current);
|
||||
leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (ISSET(SMART_HOME) && be_clever) {
|
||||
if (ISSET(SMART_HOME)) {
|
||||
size_t indent_x = indent_length(openfile->current->data);
|
||||
|
||||
if (openfile->current->data[indent_x] != '\0') {
|
||||
@@ -376,11 +412,11 @@ void do_home(bool be_clever)
|
||||
if (!moved && ISSET(SOFTWRAP)) {
|
||||
/* If already at the left edge of the screen, move fully home.
|
||||
* Otherwise, move to the left edge. */
|
||||
if (was_column % editwincols == 0 && be_clever)
|
||||
if (openfile->current_x == leftedge_x)
|
||||
openfile->current_x = 0;
|
||||
else {
|
||||
openfile->current_x = leftedge_x;
|
||||
openfile->placewewant = (was_column / editwincols) * editwincols;
|
||||
openfile->placewewant = leftedge;
|
||||
moved_off_chunk = FALSE;
|
||||
}
|
||||
} else if (!moved)
|
||||
@@ -392,70 +428,68 @@ void do_home(bool be_clever)
|
||||
|
||||
/* 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) {
|
||||
focusing = FALSE;
|
||||
edit_redraw(was_current);
|
||||
} else if (line_needs_update(was_column, openfile->placewewant))
|
||||
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);
|
||||
}
|
||||
|
||||
/* Do a (smart or dynamic) home. */
|
||||
void do_home_void(void)
|
||||
{
|
||||
do_home(TRUE);
|
||||
}
|
||||
|
||||
/* Move to the end of the current line (or softwrapped chunk).
|
||||
* If be_clever is TRUE, do a dynamic end when in softwrap mode and
|
||||
* it's possible. If be_clever is FALSE, just do a simple end. */
|
||||
void do_end(bool be_clever)
|
||||
* When softwrapping and alredy at the end of a chunk, go to the
|
||||
* end of the full line. */
|
||||
void do_end(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_column = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
size_t line_len = strlen(openfile->current->data);
|
||||
bool moved_off_chunk = TRUE;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
size_t rightedge_x = actual_x(openfile->current->data,
|
||||
((was_column / editwincols) * editwincols) +
|
||||
(editwincols - 1));
|
||||
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--;
|
||||
|
||||
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 && be_clever)
|
||||
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->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) {
|
||||
focusing = FALSE;
|
||||
edit_redraw(was_current);
|
||||
} else if (line_needs_update(was_column, openfile->placewewant))
|
||||
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);
|
||||
}
|
||||
|
||||
/* Do a (dynamic) end. */
|
||||
void do_end_void(void)
|
||||
{
|
||||
do_end(TRUE);
|
||||
}
|
||||
|
||||
/* 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 was_column = xplustabs();
|
||||
size_t leftedge, target_column;
|
||||
|
||||
/* When just scrolling and the top of the file is onscreen, get out. */
|
||||
@@ -469,34 +503,15 @@ void do_up(bool scroll_only)
|
||||
if (go_back_chunks(1, &openfile->current, &leftedge) > 0)
|
||||
return;
|
||||
|
||||
set_proper_index_and_pww(&leftedge, target_column, FALSE);
|
||||
|
||||
if (scroll_only)
|
||||
edit_scroll(UPWARD, 1);
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
|
||||
/* <Up> should not change placewewant, so restore it. */
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
openfile->placewewant);
|
||||
|
||||
/* When the cursor was on the first line of the edit window (or when just
|
||||
* scrolling without moving the cursor), scroll the edit window up -- one
|
||||
* line if we're in smooth scrolling mode, and half a page otherwise. */
|
||||
if (openfile->current_y == 0 || scroll_only)
|
||||
edit_scroll(UPWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ?
|
||||
1 : editwinrows / 2 + 1);
|
||||
|
||||
if (openfile->current_y > 0) {
|
||||
/* Redraw the prior line if it's not offscreen, and it's not the same
|
||||
* line as the current one, and the line was horizontally scrolled. */
|
||||
if ((!scroll_only || openfile->current_y < editwinrows - 1) &&
|
||||
openfile->current != was_current &&
|
||||
line_needs_update(was_column, 0))
|
||||
update_line(openfile->current->next, 0);
|
||||
/* Redraw the current line if it needs to be horizontally scrolled. */
|
||||
if (line_needs_update(0, xplustabs()))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move up one line or chunk. */
|
||||
void do_up_void(void)
|
||||
{
|
||||
do_up(FALSE);
|
||||
}
|
||||
|
||||
/* Move the cursor to next line or chunk. If scroll_only is TRUE, also
|
||||
@@ -504,7 +519,6 @@ void do_up_void(void)
|
||||
void do_down(bool scroll_only)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_column = xplustabs();
|
||||
size_t leftedge, target_column;
|
||||
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
@@ -513,28 +527,21 @@ void do_down(bool scroll_only)
|
||||
if (go_forward_chunks(1, &openfile->current, &leftedge) > 0)
|
||||
return;
|
||||
|
||||
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||
|
||||
if (scroll_only)
|
||||
edit_scroll(DOWNWARD, 1);
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
|
||||
/* <Down> should not change placewewant, so restore it. */
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
openfile->placewewant);
|
||||
}
|
||||
|
||||
/* When the cursor was on the last line of the edit window (or when just
|
||||
* scrolling without moving the cursor), scroll the edit window down -- one
|
||||
* line if we're in smooth scrolling mode, and half a page otherwise. */
|
||||
if (openfile->current_y == editwinrows - 1 || scroll_only)
|
||||
edit_scroll(DOWNWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ?
|
||||
1 : editwinrows / 2 + 1);
|
||||
|
||||
if (openfile->current_y < editwinrows - 1) {
|
||||
/* Redraw the prior line if it's not offscreen, and it's not the same
|
||||
* line as the current one, and the line was horizontally scrolled. */
|
||||
if ((!scroll_only || openfile->current_y > 0) &&
|
||||
openfile->current != was_current &&
|
||||
line_needs_update(was_column, 0))
|
||||
update_line(openfile->current->prev, 0);
|
||||
/* Redraw the current line if it needs to be horizontally scrolled. */
|
||||
if (line_needs_update(0, xplustabs()))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
/* Move up one line or chunk. */
|
||||
void do_up_void(void)
|
||||
{
|
||||
do_up(FALSE);
|
||||
}
|
||||
|
||||
/* Move down one line or chunk. */
|
||||
@@ -560,71 +567,31 @@ void do_scroll_down(void)
|
||||
/* Move left one character. */
|
||||
void do_left(void)
|
||||
{
|
||||
size_t was_column = xplustabs();
|
||||
#ifndef NANO_TINY
|
||||
size_t was_chunk = (was_column / editwincols);
|
||||
filestruct *was_current = openfile->current;
|
||||
#endif
|
||||
|
||||
if (openfile->current_x > 0)
|
||||
openfile->current_x = move_mbleft(openfile->current->data,
|
||||
openfile->current_x);
|
||||
else if (openfile->current != openfile->fileage) {
|
||||
do_up_void();
|
||||
do_end(FALSE);
|
||||
return;
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
}
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If we were on the first line of the edit window, and we changed chunk,
|
||||
* we're now above the first line of the edit window, so scroll up. */
|
||||
if (ISSET(SOFTWRAP) && openfile->current_y == 0 &&
|
||||
openfile->current == was_current &&
|
||||
openfile->placewewant / editwincols != was_chunk) {
|
||||
edit_scroll(UPWARD, ISSET(SMOOTH_SCROLL) ? 1 : editwinrows / 2 + 1);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update current if the mark is on or it has changed "page". */
|
||||
if (line_needs_update(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
|
||||
/* Move right one character. */
|
||||
void do_right(void)
|
||||
{
|
||||
size_t was_column = xplustabs();
|
||||
#ifndef NANO_TINY
|
||||
size_t was_chunk = (was_column / editwincols);
|
||||
filestruct *was_current = openfile->current;
|
||||
#endif
|
||||
|
||||
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) {
|
||||
do_home(FALSE);
|
||||
do_down_void();
|
||||
return;
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current_x = 0;
|
||||
}
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If we were on the last line of the edit window, and we changed chunk,
|
||||
* we're now below the first line of the edit window, so scroll down. */
|
||||
if (ISSET(SOFTWRAP) && openfile->current_y == editwinrows - 1 &&
|
||||
openfile->current == was_current &&
|
||||
openfile->placewewant / editwincols != was_chunk) {
|
||||
edit_scroll(DOWNWARD, ISSET(SMOOTH_SCROLL) ? 1 : editwinrows / 2 + 1);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update current if the mark is on or it has changed "page". */
|
||||
if (line_needs_update(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
|
||||
394
src/nano.c
394
src/nano.c
@@ -22,24 +22,22 @@
|
||||
#include "proto.h"
|
||||
#include "revision.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#ifdef ENABLE_UTF8
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#ifndef NANO_TINY
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef ENABLE_UTF8
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef ENABLE_MOUSE
|
||||
static int oldinterval = -1;
|
||||
@@ -59,6 +57,9 @@ static struct termios oldterm;
|
||||
static struct sigaction act;
|
||||
/* Used to set up all our fun signal handlers. */
|
||||
|
||||
static bool input_was_aborted = FALSE;
|
||||
/* Whether reading from standard input was aborted via ^C. */
|
||||
|
||||
/* Create a new linestruct node. Note that we do not set prevnode->next
|
||||
* to the new line. */
|
||||
filestruct *make_new_node(filestruct *prevnode)
|
||||
@@ -777,7 +778,7 @@ void usage(void)
|
||||
* It's best to keep its lines within 80 characters. */
|
||||
printf(_("To place the cursor on a specific line of a file, put the line number with\n"
|
||||
"a '+' before the filename. The column number can be added after a comma.\n"));
|
||||
printf(_("When the first filename is '-', nano reads data from standard input.\n\n"));
|
||||
printf(_("When a filename is '-', nano reads data from standard input.\n\n"));
|
||||
printf(_("Option\t\tGNU long option\t\tMeaning\n"));
|
||||
#ifndef NANO_TINY
|
||||
print_opt("-A", "--smarthome",
|
||||
@@ -847,6 +848,9 @@ void usage(void)
|
||||
if (!ISSET(RESTRICTED))
|
||||
print_opt(_("-Y <name>"), _("--syntax=<name>"),
|
||||
N_("Syntax definition to use for coloring"));
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
print_opt("-a", "--atblanks", N_("When soft-wrapping, do it at whitespace"));
|
||||
#endif
|
||||
print_opt("-c", "--constantshow", N_("Constantly show cursor position"));
|
||||
print_opt("-d", "--rebinddelete",
|
||||
@@ -858,7 +862,7 @@ void usage(void)
|
||||
print_opt("-h", "--help", N_("Show this help text and exit"));
|
||||
#ifndef NANO_TINY
|
||||
print_opt("-i", "--autoindent", N_("Automatically indent new lines"));
|
||||
print_opt("-k", "--cut", N_("Cut from cursor to end of line"));
|
||||
print_opt("-k", "--cutfromcursor", N_("Cut from cursor to end of line"));
|
||||
#endif
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
print_opt("-l", "--linenumbers", N_("Show line numbers in front of the text"));
|
||||
@@ -1100,54 +1104,26 @@ void do_cancel(void)
|
||||
;
|
||||
}
|
||||
|
||||
static struct sigaction pager_oldaction, pager_newaction;
|
||||
/* Make a note that reading from stdin was concluded with ^C. */
|
||||
RETSIGTYPE make_a_note(int signal)
|
||||
{
|
||||
input_was_aborted = TRUE;
|
||||
}
|
||||
|
||||
/* Read whatever comes from standard input into a new buffer. */
|
||||
bool scoop_stdin(void)
|
||||
{
|
||||
struct sigaction oldaction, newaction;
|
||||
/* Original and temporary handlers for SIGINT. */
|
||||
static bool pager_sig_failed = FALSE;
|
||||
/* Did sigaction() fail without changing the signal handlers? */
|
||||
static bool pager_input_aborted = FALSE;
|
||||
/* Did someone invoke the pager and abort it via ^C? */
|
||||
bool setup_failed = FALSE;
|
||||
/* Whether setting up the SIGINT handler failed. */
|
||||
FILE *stream;
|
||||
int thetty;
|
||||
|
||||
/* Things which need to be run regardless of whether
|
||||
* we finished the stdin pipe correctly or not. */
|
||||
void finish_stdin_pager(void)
|
||||
{
|
||||
FILE *f;
|
||||
int ttystdin;
|
||||
|
||||
/* Read whatever we did get from stdin. */
|
||||
f = fopen("/dev/stdin", "rb");
|
||||
if (f == NULL)
|
||||
nperror("fopen");
|
||||
|
||||
read_file(f, 0, "stdin", TRUE, FALSE);
|
||||
openfile->edittop = openfile->fileage;
|
||||
|
||||
ttystdin = open("/dev/tty", O_RDONLY);
|
||||
if (!ttystdin)
|
||||
die(_("Couldn't reopen stdin from keyboard, sorry\n"));
|
||||
|
||||
dup2(ttystdin,0);
|
||||
close(ttystdin);
|
||||
if (!pager_input_aborted)
|
||||
tcgetattr(0, &oldterm);
|
||||
if (!pager_sig_failed && sigaction(SIGINT, &pager_oldaction, NULL) == -1)
|
||||
nperror("sigaction");
|
||||
terminal_init();
|
||||
doupdate();
|
||||
}
|
||||
|
||||
/* Cancel reading from stdin like a pager. */
|
||||
RETSIGTYPE cancel_stdin_pager(int signal)
|
||||
{
|
||||
pager_input_aborted = TRUE;
|
||||
}
|
||||
|
||||
/* Let nano read stdin for the first file at least. */
|
||||
void stdin_pager(void)
|
||||
{
|
||||
/* Exit from curses mode and put the terminal into its original state. */
|
||||
endwin();
|
||||
if (!pager_input_aborted)
|
||||
tcsetattr(0, TCSANOW, &oldterm);
|
||||
tcsetattr(0, TCSANOW, &oldterm);
|
||||
|
||||
fprintf(stderr, _("Reading from stdin, ^C to abort\n"));
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -1156,23 +1132,59 @@ void stdin_pager(void)
|
||||
enable_signals();
|
||||
#endif
|
||||
|
||||
/* Set things up so that SIGINT will cancel the new process. */
|
||||
if (sigaction(SIGINT, NULL, &pager_newaction) == -1) {
|
||||
pager_sig_failed = TRUE;
|
||||
/* Set things up so that SIGINT will cancel the reading. */
|
||||
if (sigaction(SIGINT, NULL, &newaction) == -1) {
|
||||
setup_failed = TRUE;
|
||||
nperror("sigaction");
|
||||
} else {
|
||||
pager_newaction.sa_handler = cancel_stdin_pager;
|
||||
if (sigaction(SIGINT, &pager_newaction, &pager_oldaction) == -1) {
|
||||
pager_sig_failed = TRUE;
|
||||
newaction.sa_handler = make_a_note;
|
||||
if (sigaction(SIGINT, &newaction, &oldaction) == -1) {
|
||||
setup_failed = TRUE;
|
||||
nperror("sigaction");
|
||||
}
|
||||
}
|
||||
|
||||
/* Open standard input. */
|
||||
stream = fopen("/dev/stdin", "rb");
|
||||
if (stream == NULL) {
|
||||
int errnumber = errno;
|
||||
|
||||
terminal_init();
|
||||
doupdate();
|
||||
statusline(ALERT, _("Failed to open stdin: %s"), strerror(errnumber));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read the input into a new buffer. */
|
||||
open_buffer("", FALSE);
|
||||
finish_stdin_pager();
|
||||
read_file(stream, 0, "stdin", TRUE, FALSE);
|
||||
openfile->edittop = openfile->fileage;
|
||||
|
||||
/* Reconnect the tty as the input source. */
|
||||
thetty = open("/dev/tty", O_RDONLY);
|
||||
if (!thetty)
|
||||
die(_("Couldn't reopen stdin from keyboard, sorry\n"));
|
||||
dup2(thetty, 0);
|
||||
close(thetty);
|
||||
|
||||
/* If things went well, store the current state of the terminal. */
|
||||
if (!input_was_aborted)
|
||||
tcgetattr(0, &oldterm);
|
||||
|
||||
/* If it was changed, restore the handler for SIGINT. */
|
||||
if (!setup_failed && sigaction(SIGINT, &oldaction, NULL) == -1)
|
||||
nperror("sigaction");
|
||||
|
||||
terminal_init();
|
||||
doupdate();
|
||||
|
||||
if (!ISSET(VIEW_MODE) && openfile->totsize > 0)
|
||||
set_modified();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Initialize the signal handlers. */
|
||||
/* Register half a dozen signal handlers. */
|
||||
void signal_init(void)
|
||||
{
|
||||
/* Trap SIGINT and SIGQUIT because we want them to do useful things. */
|
||||
@@ -1196,25 +1208,23 @@ void signal_init(void)
|
||||
sigaction(SIGWINCH, &act, NULL);
|
||||
#endif
|
||||
|
||||
/* Trap normal suspend (^Z) so we can handle it ourselves. */
|
||||
if (!ISSET(SUSPEND)) {
|
||||
act.sa_handler = SIG_IGN;
|
||||
#ifdef SIGTSTP
|
||||
sigaction(SIGTSTP, &act, NULL);
|
||||
#endif
|
||||
} else {
|
||||
if (ISSET(SUSPEND)) {
|
||||
/* Block all other signals in the suspend and continue handlers.
|
||||
* If we don't do this, other stuff interrupts them! */
|
||||
sigfillset(&act.sa_mask);
|
||||
|
||||
act.sa_handler = do_suspend;
|
||||
#ifdef SIGTSTP
|
||||
/* Trap a normal suspend (^Z) so we can handle it ourselves. */
|
||||
act.sa_handler = do_suspend;
|
||||
sigaction(SIGTSTP, &act, NULL);
|
||||
#endif
|
||||
|
||||
act.sa_handler = do_continue;
|
||||
#ifdef SIGCONT
|
||||
act.sa_handler = do_continue;
|
||||
sigaction(SIGCONT, &act, NULL);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef SIGTSTP
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction(SIGTSTP, &act, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1243,21 +1253,13 @@ RETSIGTYPE do_suspend(int signal)
|
||||
/* Restore the old terminal settings. */
|
||||
tcsetattr(0, TCSANOW, &oldterm);
|
||||
|
||||
/* Trap SIGHUP and SIGTERM so we can properly deal with them while
|
||||
* suspended. */
|
||||
act.sa_handler = handle_hupterm;
|
||||
#ifdef SIGHUP
|
||||
sigaction(SIGHUP, &act, NULL);
|
||||
#endif
|
||||
sigaction(SIGTERM, &act, NULL);
|
||||
|
||||
/* Do what mutt does: send ourselves a SIGSTOP. */
|
||||
#ifdef SIGSTOP
|
||||
/* Do what mutt does: send ourselves a SIGSTOP. */
|
||||
kill(0, SIGSTOP);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The version of above function that is bound to a key. */
|
||||
/* Put nano to sleep (if suspension is enabled). */
|
||||
void do_suspend_void(void)
|
||||
{
|
||||
if (ISSET(SUSPEND))
|
||||
@@ -1277,14 +1279,14 @@ RETSIGTYPE do_continue(int signal)
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Perhaps the user resized the window while we slept. So act as if,
|
||||
* and restore the terminal to its previous state in the process. */
|
||||
regenerate_screen();
|
||||
/* Perhaps the user resized the window while we slept. */
|
||||
the_window_resized = TRUE;
|
||||
#else
|
||||
/* Restore the state of the terminal and redraw the whole screen. */
|
||||
/* Put the terminal in the desired state again. */
|
||||
terminal_init();
|
||||
total_refresh();
|
||||
#endif
|
||||
/* Tickle the input routine so it will update the screen. */
|
||||
ungetch(KEY_FLUSH);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -1336,21 +1338,16 @@ void regenerate_screen(void)
|
||||
SLsmg_reset_smg();
|
||||
SLsmg_init_smg();
|
||||
#else
|
||||
/* Do the equivalent of what Minimum Profit does: Leave and
|
||||
* immediately reenter curses mode. */
|
||||
/* Do the equivalent of what Minimum Profit does: leave and immediately
|
||||
* reenter curses mode. */
|
||||
endwin();
|
||||
doupdate();
|
||||
#endif
|
||||
|
||||
/* Restore the terminal to its previous state. */
|
||||
/* Put the terminal in the desired state again, recreate the subwindows
|
||||
* with their (new) sizes, and redraw the contents of these windows. */
|
||||
terminal_init();
|
||||
|
||||
/* Do the equivalent of what both mutt and Minimum Profit do:
|
||||
* Reinitialize all the windows based on the new screen
|
||||
* dimensions. */
|
||||
window_init();
|
||||
|
||||
/* Redraw the contents of the windows that need it. */
|
||||
total_refresh();
|
||||
}
|
||||
|
||||
@@ -1364,9 +1361,7 @@ void allow_sigwinch(bool allow)
|
||||
sigaddset(&winch, SIGWINCH);
|
||||
sigprocmask(allow ? SIG_UNBLOCK : SIG_BLOCK, &winch, NULL);
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Handle the global toggle specified in flag. */
|
||||
void do_toggle(int flag)
|
||||
{
|
||||
@@ -1690,7 +1685,7 @@ int do_input(bool allow_funcs)
|
||||
#ifndef NANO_TINY
|
||||
if (s->scfunc == do_toggle_void) {
|
||||
do_toggle(s->toggle);
|
||||
if (s->toggle != CUT_TO_END)
|
||||
if (s->toggle != CUT_FROM_CURSOR)
|
||||
preserve = TRUE;
|
||||
} else
|
||||
#endif
|
||||
@@ -1765,7 +1760,7 @@ int do_mouse(void)
|
||||
/* Whether the click was on the row where the cursor is. */
|
||||
|
||||
if (ISSET(SOFTWRAP))
|
||||
leftedge = (xplustabs() / editwincols) * editwincols;
|
||||
leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
else
|
||||
#endif
|
||||
leftedge = get_page_start(xplustabs());
|
||||
@@ -1781,7 +1776,7 @@ int do_mouse(void)
|
||||
go_forward_chunks(row_count, &openfile->current, &leftedge);
|
||||
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
leftedge + mouse_col);
|
||||
actual_last_column(leftedge, mouse_col));
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Clicking where the cursor is toggles the mark, as does clicking
|
||||
@@ -1793,7 +1788,7 @@ int do_mouse(void)
|
||||
/* The cursor moved; clean the cutbuffer on the next cut. */
|
||||
cutbuffer_reset();
|
||||
|
||||
edit_redraw(current_save);
|
||||
edit_redraw(current_save, CENTERING);
|
||||
}
|
||||
|
||||
/* No more handling is needed. */
|
||||
@@ -1811,12 +1806,12 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
size_t current_len = strlen(openfile->current->data);
|
||||
size_t i = 0;
|
||||
#ifndef NANO_TINY
|
||||
size_t orig_rows = 0, original_row = 0;
|
||||
size_t original_row = 0, old_amount = 0;
|
||||
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
if (openfile->current_y == editwinrows - 1)
|
||||
original_row = xplustabs() / editwincols;
|
||||
orig_rows = strlenpt(openfile->current->data) / editwincols;
|
||||
original_row = chunk_for(xplustabs(), openfile->current);
|
||||
old_amount = number_of_chunks_in(openfile->current);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1860,6 +1855,15 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
if (openfile->mark_set && openfile->current == openfile->mark_begin &&
|
||||
openfile->current_x < openfile->mark_begin_x)
|
||||
openfile->mark_begin_x += char_len;
|
||||
|
||||
/* When the cursor is on the top row and not on the first chunk
|
||||
* of a line, adding text there might change the preceding chunk
|
||||
* and thus require an adjustment of firstcolumn. */
|
||||
if (openfile->current == openfile->edittop &&
|
||||
openfile->firstcolumn > 0) {
|
||||
ensure_firstcolumn_is_aligned();
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
openfile->current_x += char_len;
|
||||
@@ -1881,9 +1885,9 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
* of the edit window, and we moved one screen row, we're now below
|
||||
* the last line of the edit window, so we need a full refresh too. */
|
||||
if (ISSET(SOFTWRAP) && refresh_needed == FALSE &&
|
||||
(strlenpt(openfile->current->data) / editwincols != orig_rows ||
|
||||
(number_of_chunks_in(openfile->current) != old_amount ||
|
||||
(openfile->current_y == editwinrows - 1 &&
|
||||
xplustabs() / editwincols != original_row)))
|
||||
chunk_for(xplustabs(), openfile->current) != original_row)))
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
|
||||
@@ -1900,8 +1904,6 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int optchr;
|
||||
ssize_t startline = 0, startcol = 0;
|
||||
/* Target line and column when specified on the command line. */
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
bool fill_used = FALSE;
|
||||
/* Was the fill option used on the command line? */
|
||||
@@ -1911,9 +1913,9 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENABLE_MULTIBUFFER
|
||||
bool old_multibuffer;
|
||||
/* The old value of the multibuffer option, restored after we
|
||||
* load all files on the command line. */
|
||||
bool is_multibuffer;
|
||||
/* The actual value of the multibuffer option, restored after
|
||||
* we've loaded all files given on the command line. */
|
||||
#endif
|
||||
const struct option long_options[] = {
|
||||
{"boldtext", 0, NULL, 'D'},
|
||||
@@ -1980,8 +1982,9 @@ int main(int argc, char **argv)
|
||||
{"smooth", 0, NULL, 'S'},
|
||||
{"wordbounds", 0, NULL, 'W'},
|
||||
{"wordchars", 1, NULL, 'X'},
|
||||
{"atblanks", 0, NULL, 'a'},
|
||||
{"autoindent", 0, NULL, 'i'},
|
||||
{"cut", 0, NULL, 'k'},
|
||||
{"cutfromcursor", 0, NULL, 'k'},
|
||||
{"unix", 0, NULL, 'u'},
|
||||
{"softwrap", 0, NULL, '$'},
|
||||
#endif
|
||||
@@ -2032,7 +2035,6 @@ int main(int argc, char **argv)
|
||||
"ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$",
|
||||
long_options, NULL)) != -1) {
|
||||
switch (optchr) {
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'e':
|
||||
case 'f':
|
||||
@@ -2135,6 +2137,11 @@ int main(int argc, char **argv)
|
||||
case 'Y':
|
||||
syntaxstr = mallocstrcpy(syntaxstr, optarg);
|
||||
break;
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
case 'a':
|
||||
SET(AT_BLANKS);
|
||||
break;
|
||||
#endif
|
||||
case 'c':
|
||||
SET(CONSTANT_SHOW);
|
||||
@@ -2150,7 +2157,7 @@ int main(int argc, char **argv)
|
||||
SET(AUTOINDENT);
|
||||
break;
|
||||
case 'k':
|
||||
SET(CUT_TO_END);
|
||||
SET(CUT_FROM_CURSOR);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_MOUSE
|
||||
@@ -2377,19 +2384,18 @@ int main(int argc, char **argv)
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Set up the backup directory (unless we're using restricted mode,
|
||||
* in which case backups are disabled, since they would allow
|
||||
* reading from or writing to files not specified on the command
|
||||
* line). This entails making sure it exists and is a directory, so
|
||||
* that backup files will be saved there. */
|
||||
if (!ISSET(RESTRICTED))
|
||||
/* If backups are enabled and a backup directory was specified and
|
||||
* we're not in restricted mode, make sure the path exists and is
|
||||
* a directory, so that backup files can be saved there. */
|
||||
if (ISSET(BACKUP_FILE) && backup_dir != NULL && !ISSET(RESTRICTED))
|
||||
init_backup_dir();
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
/* Set up the operating directory. This entails chdir()ing there,
|
||||
* so that file reads and writes will be based there. */
|
||||
init_operating_dir();
|
||||
if (operating_dir != NULL)
|
||||
init_operating_dir();
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
@@ -2436,13 +2442,12 @@ int main(int argc, char **argv)
|
||||
if (matchbrackets == NULL)
|
||||
matchbrackets = mallocstrcpy(NULL, "(<[{)>]}");
|
||||
|
||||
/* If whitespace wasn't specified, set its default value. If we're
|
||||
* using UTF-8, it's Unicode 00BB (Right-Pointing Double Angle
|
||||
* Quotation Mark) and Unicode 00B7 (Middle Dot). Otherwise, it's
|
||||
* ">" and ".". */
|
||||
/* If the whitespace option wasn't specified, set its default value. */
|
||||
if (whitespace == NULL) {
|
||||
#ifdef ENABLE_UTF8
|
||||
if (using_utf8()) {
|
||||
/* A tab is shown as a Right-Pointing Double Angle Quotation Mark
|
||||
* (U+00BB), and a space as a Middle Dot (U+00B7). */
|
||||
whitespace = mallocstrcpy(NULL, "\xC2\xBB\xC2\xB7");
|
||||
whitespace_len[0] = 2;
|
||||
whitespace_len[1] = 2;
|
||||
@@ -2479,8 +2484,7 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "Main: set up windows\n");
|
||||
#endif
|
||||
|
||||
/* Initialize all the windows based on the current screen
|
||||
* dimensions. */
|
||||
/* Create the three subwindows, based on the current screen dimensions. */
|
||||
window_init();
|
||||
|
||||
editwincols = COLS;
|
||||
@@ -2498,6 +2502,7 @@ int main(int argc, char **argv)
|
||||
#else
|
||||
interface_color_pair[TITLE_BAR] = hilite_attribute;
|
||||
interface_color_pair[LINE_NUMBER] = hilite_attribute;
|
||||
interface_color_pair[SELECTED_TEXT] = hilite_attribute;
|
||||
interface_color_pair[STATUS_BAR] = hilite_attribute;
|
||||
interface_color_pair[KEY_COMBO] = hilite_attribute;
|
||||
interface_color_pair[FUNCTION_TAG] = A_NORMAL;
|
||||
@@ -2520,6 +2525,11 @@ int main(int argc, char **argv)
|
||||
/* Ask for the codes for Shift+Control+Home/End. */
|
||||
shiftcontrolhome = get_keycode("kHOM6", SHIFT_CONTROL_HOME);
|
||||
shiftcontrolend = get_keycode("kEND6", SHIFT_CONTROL_END);
|
||||
/* Ask for the codes for Alt+Left/Right/Up/Down. */
|
||||
altleft = get_keycode("kLFT3", ALT_LEFT);
|
||||
altright = get_keycode("kRIT3", ALT_RIGHT);
|
||||
altup = get_keycode("kUP3", ALT_UP);
|
||||
altdown = get_keycode("kDN3", ALT_DOWN);
|
||||
/* Ask for the codes for Shift+Alt+Left/Right/Up/Down. */
|
||||
shiftaltleft = get_keycode("kLFT4", SHIFT_ALT_LEFT);
|
||||
shiftaltright = get_keycode("kRIT4", SHIFT_ALT_RIGHT);
|
||||
@@ -2536,90 +2546,56 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "Main: open file\n");
|
||||
#endif
|
||||
|
||||
/* If there's a +LINE or +LINE,COLUMN flag here, it is the first
|
||||
* non-option argument, and it is followed by at least one other
|
||||
* argument, the filename it applies to. */
|
||||
if (0 < optind && optind < argc - 1 && argv[optind][0] == '+') {
|
||||
if (!parse_line_column(&argv[optind][1], &startline, &startcol))
|
||||
statusline(ALERT, _("Invalid line or column number"));
|
||||
optind++;
|
||||
}
|
||||
|
||||
/* If one of the arguments is a dash, read text from standard input. */
|
||||
if (optind < argc && !strcmp(argv[optind], "-")) {
|
||||
stdin_pager();
|
||||
set_modified();
|
||||
optind++;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MULTIBUFFER
|
||||
old_multibuffer = ISSET(MULTIBUFFER);
|
||||
is_multibuffer = ISSET(MULTIBUFFER);
|
||||
SET(MULTIBUFFER);
|
||||
|
||||
/* Read all the files after the first one on the command line into
|
||||
* new buffers. */
|
||||
{
|
||||
int i = optind + 1;
|
||||
ssize_t iline = 0, icol = 0;
|
||||
|
||||
for (; i < argc; i++) {
|
||||
/* If there's a +LINE or +LINE,COLUMN flag here, it is followed
|
||||
* by at least one other argument: the filename it applies to. */
|
||||
if (i < argc - 1 && argv[i][0] == '+') {
|
||||
if (!parse_line_column(&argv[i][1], &iline, &icol))
|
||||
statusline(ALERT, _("Invalid line or column number"));
|
||||
} else {
|
||||
/* If opening fails, don't try to position the cursor. */
|
||||
if (!open_buffer(argv[i], FALSE))
|
||||
continue;
|
||||
|
||||
/* If a position was given on the command line, go there. */
|
||||
if (iline > 0 || icol > 0) {
|
||||
do_gotolinecolumn(iline, icol, FALSE, FALSE);
|
||||
iline = 0;
|
||||
icol = 0;
|
||||
}
|
||||
#ifndef DISABLE_HISTORIES
|
||||
else if (ISSET(POS_HISTORY)) {
|
||||
ssize_t savedposline, savedposcol;
|
||||
/* If edited before, restore the last cursor position. */
|
||||
if (has_old_position(argv[i], &savedposline, &savedposcol))
|
||||
do_gotolinecolumn(savedposline, savedposcol,
|
||||
FALSE, FALSE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Read the files mentioned on the command line into new buffers. */
|
||||
while (optind < argc && (!openfile || ISSET(MULTIBUFFER))) {
|
||||
ssize_t givenline = 0, givencol = 0;
|
||||
|
||||
/* If there's a +LINE[,COLUMN] argument here, eat it up. */
|
||||
if (optind < argc - 1 && argv[optind][0] == '+') {
|
||||
if (!parse_line_column(&argv[optind++][1], &givenline, &givencol))
|
||||
statusline(ALERT, _("Invalid line or column number"));
|
||||
}
|
||||
|
||||
/* If the filename is a dash, read from standard input; otherwise,
|
||||
* open the file; skip positioning the cursor if either failed. */
|
||||
if (strcmp(argv[optind], "-") == 0) {
|
||||
if (!scoop_stdin())
|
||||
continue;
|
||||
optind++;
|
||||
} else if (!open_buffer(argv[optind++], FALSE))
|
||||
continue;
|
||||
|
||||
/* If a position was given on the command line, go there. */
|
||||
if (givenline != 0 || givencol != 0)
|
||||
do_gotolinecolumn(givenline, givencol, FALSE, FALSE);
|
||||
#ifndef DISABLE_HISTORIES
|
||||
else if (ISSET(POS_HISTORY) && openfile->filename[0] != '\0') {
|
||||
ssize_t savedline, savedcol;
|
||||
/* If edited before, restore the last cursor position. */
|
||||
if (has_old_position(argv[optind - 1], &savedline, &savedcol))
|
||||
do_gotolinecolumn(savedline, savedcol, FALSE, FALSE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* ENABLE_MULTIBUFFER */
|
||||
|
||||
/* Now read the first file on the command line into a new buffer. */
|
||||
if (optind < argc)
|
||||
open_buffer(argv[optind], FALSE);
|
||||
|
||||
/* If all the command-line arguments were invalid files like directories,
|
||||
* or if there were no filenames given, we didn't open any file. In this
|
||||
* case, load a blank buffer. Also, unset view mode to allow editing. */
|
||||
/* If no filenames were given, or all of them were invalid things like
|
||||
* directories, then open a blank buffer and allow editing. Otherwise,
|
||||
* switch from the last opened file to the next, that is: the first. */
|
||||
if (openfile == NULL) {
|
||||
open_buffer("", FALSE);
|
||||
UNSET(VIEW_MODE);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MULTIBUFFER
|
||||
if (!old_multibuffer)
|
||||
UNSET(MULTIBUFFER);
|
||||
#endif
|
||||
else
|
||||
openfile = openfile->next;
|
||||
|
||||
/* If a starting position was given on the command line, go there. */
|
||||
if (startline > 0 || startcol > 0)
|
||||
do_gotolinecolumn(startline, startcol, FALSE, FALSE);
|
||||
#ifndef DISABLE_HISTORIES
|
||||
else if (ISSET(POS_HISTORY)) {
|
||||
ssize_t savedposline, savedposcol;
|
||||
/* If the file was edited before, restore the last cursor position. */
|
||||
if (has_old_position(argv[optind], &savedposline, &savedposcol))
|
||||
do_gotolinecolumn(savedposline, savedposcol, FALSE, FALSE);
|
||||
}
|
||||
if (!is_multibuffer)
|
||||
UNSET(MULTIBUFFER);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -2632,7 +2608,7 @@ int main(int argc, char **argv)
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
int needed_margin = digits(openfile->filebot->lineno) + 1;
|
||||
|
||||
/* Only enable line numbers when there is enough room for them. */
|
||||
/* Suppress line numbers when there is not enough room for them. */
|
||||
if (!ISSET(LINE_NUMBERS) || needed_margin > COLS - 4)
|
||||
needed_margin = 0;
|
||||
|
||||
@@ -2662,7 +2638,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Refresh just the cursor position or the entire edit window. */
|
||||
if (!refresh_needed) {
|
||||
place_the_cursor(TRUE);
|
||||
place_the_cursor();
|
||||
wnoutrefresh(edit);
|
||||
} else
|
||||
edit_refresh();
|
||||
|
||||
67
src/nano.h
67
src/nano.h
@@ -48,8 +48,6 @@
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Suppress warnings for __attribute__((warn_unused_result)). */
|
||||
#define IGNORE_CALL_RESULT(call) do { if (call) {} } while(0)
|
||||
|
||||
@@ -160,11 +158,11 @@ typedef enum {
|
||||
} update_type;
|
||||
|
||||
typedef enum {
|
||||
ADD, DEL, BACK, CUT, CUT_EOF, REPLACE,
|
||||
ADD, DEL, BACK, CUT, CUT_TO_EOF, REPLACE,
|
||||
#ifndef DISABLE_WRAPPING
|
||||
SPLIT_BEGIN, SPLIT_END,
|
||||
#endif
|
||||
#ifndef DISABLE_COMMENT
|
||||
#ifdef ENABLE_COMMENT
|
||||
COMMENT, UNCOMMENT, PREFLIGHT,
|
||||
#endif
|
||||
JOIN, PASTE, INSERT, ENTER, OTHER
|
||||
@@ -220,8 +218,10 @@ typedef struct syntaxtype {
|
||||
/* 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. */
|
||||
#endif
|
||||
colortype *color;
|
||||
/* The colors and their regexes used in this syntax. */
|
||||
int nmultis;
|
||||
@@ -469,6 +469,7 @@ enum
|
||||
{
|
||||
TITLE_BAR = 0,
|
||||
LINE_NUMBER,
|
||||
SELECTED_TEXT,
|
||||
STATUS_BAR,
|
||||
KEY_COMBO,
|
||||
FUNCTION_TAG,
|
||||
@@ -489,7 +490,7 @@ enum
|
||||
USE_MOUSE,
|
||||
USE_REGEXP,
|
||||
TEMP_FILE,
|
||||
CUT_TO_END,
|
||||
CUT_FROM_CURSOR,
|
||||
BACKWARDS_SEARCH,
|
||||
MULTIBUFFER,
|
||||
SMOOTH_SCROLL,
|
||||
@@ -519,7 +520,8 @@ enum
|
||||
JUSTIFY_TRIM,
|
||||
SHOW_CURSOR,
|
||||
LINE_NUMBERS,
|
||||
NO_PAUSES
|
||||
NO_PAUSES,
|
||||
AT_BLANKS
|
||||
};
|
||||
|
||||
/* Flags for the menus in which a given function should be present. */
|
||||
@@ -542,6 +544,11 @@ enum
|
||||
/* 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)
|
||||
#ifndef NANO_TINY
|
||||
#define MSOME MMOST
|
||||
#else
|
||||
#define MSOME MMAIN|MBROWSER
|
||||
#endif
|
||||
|
||||
/* Basic control codes. */
|
||||
#define TAB_CODE 0x09
|
||||
@@ -553,22 +560,35 @@ enum
|
||||
#define CONTROL_RIGHT 0x402
|
||||
#define CONTROL_UP 0x403
|
||||
#define CONTROL_DOWN 0x404
|
||||
#define CONTROL_HOME 0x411
|
||||
#define CONTROL_END 0x412
|
||||
#define SHIFT_CONTROL_LEFT 0x405
|
||||
#define SHIFT_CONTROL_RIGHT 0x406
|
||||
#define SHIFT_CONTROL_UP 0x407
|
||||
#define SHIFT_CONTROL_DOWN 0x408
|
||||
#define SHIFT_CONTROL_HOME 0x413
|
||||
#define SHIFT_CONTROL_END 0x414
|
||||
#define SHIFT_ALT_LEFT 0x409
|
||||
#define SHIFT_ALT_RIGHT 0x40a
|
||||
#define SHIFT_ALT_UP 0x40b
|
||||
#define SHIFT_ALT_DOWN 0x40c
|
||||
#define SHIFT_PAGEUP 0x40d
|
||||
#define SHIFT_PAGEDOWN 0x40e
|
||||
#define SHIFT_HOME 0x40f
|
||||
#define SHIFT_END 0x410
|
||||
#define CONTROL_HOME 0x405
|
||||
#define CONTROL_END 0x406
|
||||
#define SHIFT_CONTROL_LEFT 0x411
|
||||
#define SHIFT_CONTROL_RIGHT 0x412
|
||||
#define SHIFT_CONTROL_UP 0x413
|
||||
#define SHIFT_CONTROL_DOWN 0x414
|
||||
#define SHIFT_CONTROL_HOME 0x415
|
||||
#define SHIFT_CONTROL_END 0x416
|
||||
#define ALT_LEFT 0x421
|
||||
#define ALT_RIGHT 0x422
|
||||
#define ALT_UP 0x423
|
||||
#define ALT_DOWN 0x424
|
||||
#define SHIFT_ALT_LEFT 0x431
|
||||
#define SHIFT_ALT_RIGHT 0x432
|
||||
#define SHIFT_ALT_UP 0x433
|
||||
#define SHIFT_ALT_DOWN 0x434
|
||||
#define SHIFT_HOME 0x455
|
||||
#define SHIFT_END 0x456
|
||||
#define SHIFT_PAGEUP 0x457
|
||||
#define SHIFT_PAGEDOWN 0x458
|
||||
|
||||
#ifdef USE_SLANG
|
||||
#ifdef ENABLE_UTF8
|
||||
#define KEY_BAD 0xFF /* Clipped error code. */
|
||||
#endif
|
||||
#define KEY_FLUSH 0x91 /* User-definable control code. */
|
||||
#else
|
||||
#define KEY_FLUSH KEY_F0 /* Nonexistent function key. */
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* An imaginary key for when we get a SIGWINCH (window resize). */
|
||||
@@ -592,6 +612,9 @@ enum
|
||||
/* The default width of a tab in spaces. */
|
||||
#define WIDTH_OF_TAB 8
|
||||
|
||||
/* The default comment character when a syntax does not specify any. */
|
||||
#define GENERAL_COMMENT_CHARACTER "#"
|
||||
|
||||
/* The maximum number of search/replace history strings saved, not
|
||||
* counting the blank lines at their ends. */
|
||||
#define MAX_SEARCH_HISTORY 100
|
||||
|
||||
39
src/prompt.c
39
src/prompt.c
@@ -21,8 +21,6 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *prompt = NULL;
|
||||
@@ -124,9 +122,9 @@ int do_statusbar_input(bool *ran_func, bool *finished)
|
||||
else if (s->scfunc == do_next_word_void)
|
||||
do_statusbar_next_word();
|
||||
#endif
|
||||
else if (s->scfunc == do_home_void)
|
||||
else if (s->scfunc == do_home)
|
||||
do_statusbar_home();
|
||||
else if (s->scfunc == do_end_void)
|
||||
else if (s->scfunc == do_end)
|
||||
do_statusbar_end();
|
||||
/* When in restricted mode at the "Write File" prompt and the
|
||||
* filename isn't blank, disallow any input and deletion. */
|
||||
@@ -137,15 +135,18 @@ int do_statusbar_input(bool *ran_func, bool *finished)
|
||||
s->scfunc == do_delete ||
|
||||
s->scfunc == do_backspace))
|
||||
;
|
||||
else if (s->scfunc == do_verbatim_input) {
|
||||
else if (s->scfunc == do_verbatim_input)
|
||||
do_statusbar_verbatim_input();
|
||||
} else if (s->scfunc == do_cut_text_void)
|
||||
else if (s->scfunc == do_cut_text_void)
|
||||
do_statusbar_cut_text();
|
||||
else if (s->scfunc == do_delete)
|
||||
do_statusbar_delete();
|
||||
else if (s->scfunc == do_backspace)
|
||||
do_statusbar_backspace();
|
||||
else {
|
||||
else if (s->scfunc == do_uncut_text) {
|
||||
if (cutbuffer != NULL)
|
||||
do_statusbar_uncut_text();
|
||||
} else {
|
||||
/* Handle any other shortcut in the current menu, setting
|
||||
* ran_func to TRUE if we try to run their associated functions,
|
||||
* and setting finished to TRUE to indicatethat we're done after
|
||||
@@ -291,7 +292,7 @@ void do_statusbar_delete(void)
|
||||
/* Zap some or all text from the answer. */
|
||||
void do_statusbar_cut_text(void)
|
||||
{
|
||||
if (!ISSET(CUT_TO_END))
|
||||
if (!ISSET(CUT_FROM_CURSOR))
|
||||
statusbar_x = 0;
|
||||
|
||||
answer[statusbar_x] = '\0';
|
||||
@@ -363,6 +364,23 @@ size_t statusbar_xplustabs(void)
|
||||
return strnlenpt(answer, statusbar_x);
|
||||
}
|
||||
|
||||
/* Paste the first line of the cutbuffer into the current answer. */
|
||||
void do_statusbar_uncut_text(void)
|
||||
{
|
||||
size_t pastelen = strlen(cutbuffer->data);
|
||||
char *fusion = charalloc(strlen(answer) + pastelen + 1);
|
||||
|
||||
/* Concatenate: the current answer before the cursor, the first line
|
||||
* of the cutbuffer, plus the rest of the current answer. */
|
||||
strncpy(fusion, answer, statusbar_x);
|
||||
strncpy(fusion + statusbar_x, cutbuffer->data, pastelen);
|
||||
strcpy(fusion + statusbar_x + pastelen, answer + statusbar_x);
|
||||
|
||||
free(answer);
|
||||
answer = fusion;
|
||||
statusbar_x += pastelen;
|
||||
}
|
||||
|
||||
/* Return the column number of the first character of the answer that is
|
||||
* displayed in the statusbar when the cursor is at the given column,
|
||||
* with the available room for the answer starting at base. Note that
|
||||
@@ -411,8 +429,7 @@ void update_the_statusbar(void)
|
||||
|
||||
/* Work around a cursor-misplacement bug in VTEs. */
|
||||
wmove(bottomwin, 0, 0);
|
||||
wnoutrefresh(bottomwin);
|
||||
doupdate();
|
||||
wrefresh(bottomwin);
|
||||
|
||||
/* Place the cursor at statusbar_x in the answer. */
|
||||
column = base + statusbar_xplustabs();
|
||||
@@ -692,7 +709,7 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
functionptrtype func;
|
||||
|
||||
if (!ISSET(NO_HELP)) {
|
||||
char shortstr[3];
|
||||
char shortstr[MAXCHARLEN + 2];
|
||||
/* Temporary string for (translated) " Y", " N" and " A". */
|
||||
|
||||
if (COLS < 32)
|
||||
|
||||
60
src/proto.h
60
src/proto.h
@@ -47,6 +47,8 @@ extern int editwincols;
|
||||
extern bool have_palette;
|
||||
#endif
|
||||
|
||||
extern bool suppress_cursorpos;
|
||||
|
||||
extern message_type lastmessage;
|
||||
|
||||
extern filestruct *pletion_line;
|
||||
@@ -69,6 +71,10 @@ extern int shiftcontrolup;
|
||||
extern int shiftcontroldown;
|
||||
extern int shiftcontrolhome;
|
||||
extern int shiftcontrolend;
|
||||
extern int altleft;
|
||||
extern int altright;
|
||||
extern int altup;
|
||||
extern int altdown;
|
||||
extern int shiftaltleft;
|
||||
extern int shiftaltright;
|
||||
extern int shiftaltup;
|
||||
@@ -119,8 +125,6 @@ extern char *quoteerr;
|
||||
|
||||
extern char *word_chars;
|
||||
|
||||
extern bool nodelay_mode;
|
||||
|
||||
extern char *answer;
|
||||
|
||||
extern ssize_t tabsize;
|
||||
@@ -132,7 +136,6 @@ extern const char *locking_suffix;
|
||||
#endif
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
extern char *operating_dir;
|
||||
extern char *full_operating_dir;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_SPELLER
|
||||
@@ -183,7 +186,7 @@ functionptrtype parse_browser_input(int *kbinput);
|
||||
void browser_refresh(void);
|
||||
void browser_select_dirname(const char *needle);
|
||||
void do_filesearch(void);
|
||||
void do_fileresearch(void);
|
||||
void do_fileresearch(bool forwards);
|
||||
void do_first_file(void);
|
||||
void do_last_file(void);
|
||||
char *strip_last_component(const char *path);
|
||||
@@ -284,7 +287,7 @@ char *get_full_path(const char *origpath);
|
||||
char *safe_tempfile(FILE **f);
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
void init_operating_dir(void);
|
||||
bool check_operating_dir(const char *currpath, bool allow_tabcomp);
|
||||
bool outside_of_confinement(const char *currpath, bool allow_tabcomp);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
void init_backup_dir(void);
|
||||
@@ -328,6 +331,7 @@ size_t length_of_list(int menu);
|
||||
const sc *first_sc_for(int menu, void (*func)(void));
|
||||
int the_code_for(void (*func)(void), int defaultval);
|
||||
functionptrtype func_from_key(int *kbinput);
|
||||
int keycode_from_string(const char *keystring);
|
||||
void assign_keyinfo(sc *s, const char *keystring, const int keycode);
|
||||
void print_sclist(void);
|
||||
void shortcut_init(void);
|
||||
@@ -353,30 +357,28 @@ size_t help_line_len(const char *ptr);
|
||||
#endif
|
||||
void do_help_void(void);
|
||||
|
||||
/* All functions in move.c. */
|
||||
/* Most functions in move.c. */
|
||||
void do_first_line(void);
|
||||
void do_last_line(void);
|
||||
void do_page_up(void);
|
||||
void do_page_down(void);
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
void do_para_begin(bool update_screen);
|
||||
void do_para_begin_void(void);
|
||||
void do_para_end(bool update_screen);
|
||||
void do_para_begin_void(void);
|
||||
void do_para_end_void(void);
|
||||
#endif
|
||||
void do_prev_block(void);
|
||||
void do_next_block(void);
|
||||
void do_prev_word(bool allow_punct, bool update_screen);
|
||||
void do_prev_word_void(void);
|
||||
bool do_next_word(bool allow_punct, bool update_screen);
|
||||
void do_prev_word_void(void);
|
||||
void do_next_word_void(void);
|
||||
void do_home(bool be_clever);
|
||||
void do_home_void(void);
|
||||
void do_end(bool be_clever);
|
||||
void do_end_void(void);
|
||||
void do_home(void);
|
||||
void do_end(void);
|
||||
void do_up(bool scroll_only);
|
||||
void do_up_void(void);
|
||||
void do_down(bool scroll_only);
|
||||
void do_up_void(void);
|
||||
void do_down_void(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_scroll_up(void);
|
||||
@@ -448,6 +450,7 @@ void do_statusbar_right(void);
|
||||
void do_statusbar_backspace(void);
|
||||
void do_statusbar_delete(void);
|
||||
void do_statusbar_cut_text(void);
|
||||
void do_statusbar_uncut_text(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_statusbar_prev_word(void);
|
||||
void do_statusbar_next_word(void);
|
||||
@@ -523,8 +526,7 @@ void do_cut_next_word(void);
|
||||
#endif
|
||||
void do_tab(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_indent(ssize_t cols);
|
||||
void do_indent_void(void);
|
||||
void do_indent(void);
|
||||
void do_unindent(void);
|
||||
#endif
|
||||
bool white_string(const char *s);
|
||||
@@ -540,7 +542,7 @@ RETSIGTYPE cancel_command(int signal);
|
||||
bool execute_command(const char *command);
|
||||
void discard_until(const undo *thisitem, openfilestruct *thefile);
|
||||
void add_undo(undo_type action);
|
||||
#ifndef DISABLE_COMMENT
|
||||
#ifdef ENABLE_COMMENT
|
||||
void update_comment_undo(ssize_t lineno);
|
||||
#endif
|
||||
void update_undo(undo_type action);
|
||||
@@ -601,9 +603,9 @@ char *mallocstrcpy(char *dest, const char *src);
|
||||
char *free_and_assign(char *dest, char *src);
|
||||
size_t get_page_start(size_t column);
|
||||
size_t xplustabs(void);
|
||||
size_t actual_x(const char *s, size_t column);
|
||||
size_t strnlenpt(const char *s, size_t maxlen);
|
||||
size_t strlenpt(const char *s);
|
||||
size_t actual_x(const char *text, size_t column);
|
||||
size_t strnlenpt(const char *text, size_t maxlen);
|
||||
size_t strlenpt(const char *text);
|
||||
void new_magicline(void);
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
|
||||
void remove_magicline(void);
|
||||
@@ -650,7 +652,7 @@ void warn_and_shortly_pause(const char *msg);
|
||||
void statusline(message_type importance, const char *msg, ...);
|
||||
void bottombars(int menu);
|
||||
void onekey(const char *keystroke, const char *desc, int length);
|
||||
void place_the_cursor(bool forreal);
|
||||
void place_the_cursor(void);
|
||||
void edit_draw(filestruct *fileptr, const char *converted,
|
||||
int line, size_t from_col);
|
||||
int update_line(filestruct *fileptr, size_t index);
|
||||
@@ -663,9 +665,16 @@ int go_forward_chunks(int nrows, filestruct **line, size_t *leftedge);
|
||||
bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge);
|
||||
void edit_scroll(scroll_dir direction, int nrows);
|
||||
#ifndef NANO_TINY
|
||||
size_t get_softwrap_breakpoint(const char *text, size_t leftedge,
|
||||
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);
|
||||
size_t number_of_chunks_in(filestruct *line);
|
||||
void ensure_firstcolumn_is_aligned(void);
|
||||
#endif
|
||||
void edit_redraw(filestruct *old_current);
|
||||
size_t actual_last_column(size_t leftedge, size_t column);
|
||||
void edit_redraw(filestruct *old_current, update_type manner);
|
||||
void edit_refresh(void);
|
||||
void adjust_viewport(update_type location);
|
||||
void total_redraw(void);
|
||||
@@ -673,12 +682,15 @@ void total_refresh(void);
|
||||
void display_main_list(void);
|
||||
void do_cursorpos(bool force);
|
||||
void do_cursorpos_void(void);
|
||||
void spotlight(bool active, const char *word);
|
||||
void spotlight(bool active, size_t from_col, size_t to_col);
|
||||
#ifndef NANO_TINY
|
||||
void spotlight_softwrapped(bool active, size_t from_col, size_t to_col);
|
||||
#endif
|
||||
void xon_complaint(void);
|
||||
void xoff_complaint(void);
|
||||
void do_suspend_void(void);
|
||||
void enable_nodelay(void);
|
||||
void disable_nodelay(void);
|
||||
void disable_waiting(void);
|
||||
void enable_waiting(void);
|
||||
#ifndef DISABLE_EXTRA
|
||||
void do_credits(void);
|
||||
#endif
|
||||
|
||||
131
src/rcfile.c
131
src/rcfile.c
@@ -22,13 +22,11 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <glob.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <glob.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef ENABLE_NANORC
|
||||
|
||||
@@ -90,12 +88,14 @@ static const rcoption rcopts[] = {
|
||||
{"view", VIEW_MODE},
|
||||
#ifndef NANO_TINY
|
||||
{"allow_insecure_backup", INSECURE_BACKUP},
|
||||
{"atblanks", AT_BLANKS},
|
||||
{"autoindent", AUTOINDENT},
|
||||
{"backup", BACKUP_FILE},
|
||||
{"backupdir", 0},
|
||||
{"backwards", BACKWARDS_SEARCH},
|
||||
{"casesensitive", CASE_SENSITIVE},
|
||||
{"cut", CUT_TO_END},
|
||||
{"cut", CUT_FROM_CURSOR}, /* deprecated form, remove in 2020 */
|
||||
{"cutfromcursor", CUT_FROM_CURSOR},
|
||||
{"justifytrim", JUSTIFY_TRIM},
|
||||
{"locking", LOCKING},
|
||||
{"matchbrackets", 0},
|
||||
@@ -114,6 +114,7 @@ static const rcoption rcopts[] = {
|
||||
#ifndef DISABLE_COLOR
|
||||
{"titlecolor", 0},
|
||||
{"numbercolor", 0},
|
||||
{"selectedcolor", 0},
|
||||
{"statuscolor", 0},
|
||||
{"keycolor", 0},
|
||||
{"functioncolor", 0},
|
||||
@@ -315,7 +316,9 @@ void parse_syntax(char *ptr)
|
||||
live_syntax->magics = NULL;
|
||||
live_syntax->linter = NULL;
|
||||
live_syntax->formatter = NULL;
|
||||
live_syntax->comment = NULL;
|
||||
#ifdef ENABLE_COMMENT
|
||||
live_syntax->comment = mallocstrcpy(NULL, GENERAL_COMMENT_CHARACTER);
|
||||
#endif
|
||||
live_syntax->color = NULL;
|
||||
lastcolor = NULL;
|
||||
live_syntax->nmultis = 0;
|
||||
@@ -346,14 +349,16 @@ void parse_syntax(char *ptr)
|
||||
/* Check whether the given executable function is "universal" (meaning
|
||||
* any horizontal movement or deletion) and thus is present in almost
|
||||
* all menus. */
|
||||
bool is_universal(void (*func))
|
||||
bool is_universal(void (*func)(void))
|
||||
{
|
||||
if (func == do_left || func == do_right ||
|
||||
func == do_home_void || func == do_end_void ||
|
||||
func == do_home || func == do_end ||
|
||||
#ifndef NANO_TINY
|
||||
func == do_prev_word_void || func == do_next_word_void ||
|
||||
func == do_verbatim_input || func == do_cut_text_void ||
|
||||
#endif
|
||||
func == do_delete || func == do_backspace ||
|
||||
func == do_tab || func == do_enter)
|
||||
func == do_cut_text_void || func == do_uncut_text ||
|
||||
func == do_tab || func == do_enter || func == do_verbatim_input)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
@@ -383,7 +388,7 @@ void parse_binding(char *ptr, bool dobind)
|
||||
|
||||
if (strlen(keycopy) < 2) {
|
||||
rcfile_error(N_("Key name is too short"));
|
||||
goto free_copy;
|
||||
goto free_things;
|
||||
}
|
||||
|
||||
/* Uppercase only the first two or three characters of the key name. */
|
||||
@@ -394,7 +399,7 @@ void parse_binding(char *ptr, bool dobind)
|
||||
keycopy[2] = toupper((unsigned char)keycopy[2]);
|
||||
else {
|
||||
rcfile_error(N_("Key name is too short"));
|
||||
goto free_copy;
|
||||
goto free_things;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,15 +409,10 @@ void parse_binding(char *ptr, bool dobind)
|
||||
keycopy[1] = tolower((unsigned char)keycopy[1]);
|
||||
else if (keycopy[0] != '^' && keycopy[0] != 'M' && keycopy[0] != 'F') {
|
||||
rcfile_error(N_("Key name must begin with \"^\", \"M\", or \"F\""));
|
||||
goto free_copy;
|
||||
} else if ((keycopy[0] == 'M' && keycopy[1] != '-') ||
|
||||
(keycopy[0] == '^' && ((keycopy[1] < 'A' || keycopy[1] > 'z') ||
|
||||
keycopy[1] == '[' || keycopy[1] == '`' ||
|
||||
(strlen(keycopy) > 2 && strcmp(keycopy, "^Space") != 0))) ||
|
||||
(strlen(keycopy) > 3 && strcmp(keycopy, "^Space") != 0 &&
|
||||
strcmp(keycopy, "M-Space") != 0)) {
|
||||
goto free_things;
|
||||
} else if (keycode_from_string(keycopy) < 0) {
|
||||
rcfile_error(N_("Key name %s is invalid"), keycopy);
|
||||
goto free_copy;
|
||||
goto free_things;
|
||||
}
|
||||
|
||||
if (dobind) {
|
||||
@@ -421,7 +421,7 @@ void parse_binding(char *ptr, bool dobind)
|
||||
|
||||
if (funcptr[0] == '\0') {
|
||||
rcfile_error(N_("Must specify a function to bind the key to"));
|
||||
goto free_copy;
|
||||
goto free_things;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,21 +431,21 @@ void parse_binding(char *ptr, bool dobind)
|
||||
if (menuptr[0] == '\0') {
|
||||
/* TRANSLATORS: Do not translate the word "all". */
|
||||
rcfile_error(N_("Must specify a menu (or \"all\") in which to bind/unbind the key"));
|
||||
goto free_copy;
|
||||
goto free_things;
|
||||
}
|
||||
|
||||
if (dobind) {
|
||||
newsc = strtosc(funcptr);
|
||||
if (newsc == NULL) {
|
||||
rcfile_error(N_("Cannot map name \"%s\" to a function"), funcptr);
|
||||
goto free_copy;
|
||||
goto free_things;
|
||||
}
|
||||
}
|
||||
|
||||
menu = strtomenu(menuptr);
|
||||
if (menu < 1) {
|
||||
rcfile_error(N_("Cannot map name \"%s\" to a menu"), menuptr);
|
||||
goto free_copy;
|
||||
goto free_things;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -479,8 +479,7 @@ void parse_binding(char *ptr, bool dobind)
|
||||
|
||||
if (!menu) {
|
||||
rcfile_error(N_("Function '%s' does not exist in menu '%s'"), funcptr, menuptr);
|
||||
free(newsc);
|
||||
goto free_copy;
|
||||
goto free_things;
|
||||
}
|
||||
|
||||
newsc->menus = menu;
|
||||
@@ -489,8 +488,7 @@ void parse_binding(char *ptr, bool dobind)
|
||||
/* Do not allow rebinding a frequent escape-sequence starter: Esc [. */
|
||||
if (newsc->meta && newsc->keycode == 91) {
|
||||
rcfile_error(N_("Sorry, keystroke \"%s\" may not be rebound"), newsc->keystr);
|
||||
free(newsc);
|
||||
goto free_copy;
|
||||
goto free_things;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "s->keystr = \"%s\"\n", newsc->keystr);
|
||||
@@ -524,7 +522,8 @@ void parse_binding(char *ptr, bool dobind)
|
||||
return;
|
||||
}
|
||||
|
||||
free_copy:
|
||||
free_things:
|
||||
free(newsc);
|
||||
free(keycopy);
|
||||
}
|
||||
|
||||
@@ -607,8 +606,6 @@ void parse_includes(char *ptr)
|
||||
* and set bright to TRUE if that color is bright. */
|
||||
short color_to_short(const char *colorname, bool *bright)
|
||||
{
|
||||
assert(colorname != NULL && bright != NULL);
|
||||
|
||||
if (strncasecmp(colorname, "bright", 6) == 0) {
|
||||
*bright = TRUE;
|
||||
colorname += 6;
|
||||
@@ -648,8 +645,6 @@ void parse_colors(char *ptr, int rex_flags)
|
||||
bool bright = FALSE;
|
||||
char *item;
|
||||
|
||||
assert(ptr != NULL);
|
||||
|
||||
if (!opensyntax) {
|
||||
rcfile_error(
|
||||
N_("A '%s' command requires a preceding 'syntax' command"),
|
||||
@@ -723,9 +718,6 @@ void parse_colors(char *ptr, int rex_flags)
|
||||
|
||||
newcolor->next = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Adding an entry for fg %hd, bg %hd\n", fg, bg);
|
||||
#endif
|
||||
if (lastcolor == NULL)
|
||||
live_syntax->color = newcolor;
|
||||
else
|
||||
@@ -776,33 +768,22 @@ void parse_colors(char *ptr, int rex_flags)
|
||||
/* Parse the color name, or pair of color names, in combostr. */
|
||||
bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright)
|
||||
{
|
||||
bool no_fgcolor = FALSE;
|
||||
char *comma = strchr(combostr, ',');
|
||||
|
||||
if (combostr == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (strchr(combostr, ',') != NULL) {
|
||||
char *bgcolorname;
|
||||
strtok(combostr, ",");
|
||||
bgcolorname = strtok(NULL, ",");
|
||||
if (bgcolorname == NULL) {
|
||||
/* If we have a background color without a foreground color,
|
||||
* parse it properly. */
|
||||
bgcolorname = combostr + 1;
|
||||
no_fgcolor = TRUE;
|
||||
}
|
||||
if (strncasecmp(bgcolorname, "bright", 6) == 0) {
|
||||
rcfile_error(N_("Background color \"%s\" cannot be bright"), bgcolorname);
|
||||
if (comma != NULL) {
|
||||
*bg = color_to_short(comma + 1, bright);
|
||||
if (*bright) {
|
||||
rcfile_error(N_("A background color cannot be bright"));
|
||||
return FALSE;
|
||||
}
|
||||
*bg = color_to_short(bgcolorname, bright);
|
||||
*comma = '\0';
|
||||
} else
|
||||
*bg = -1;
|
||||
|
||||
if (!no_fgcolor) {
|
||||
if (comma != combostr) {
|
||||
*fg = color_to_short(combostr, bright);
|
||||
|
||||
/* Don't try to parse screwed-up foreground colors. */
|
||||
/* If the specified foreground color is bad, ignore the regexes. */
|
||||
if (*fg == -1)
|
||||
return FALSE;
|
||||
} else
|
||||
@@ -875,7 +856,7 @@ void grab_and_store(const char *kind, char *ptr, regexlisttype **storage)
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse and store the name given after a linter/formatter command. */
|
||||
/* Gather and store the string after a comment/linter/formatter command. */
|
||||
void pick_up_name(const char *kind, char *ptr, char **storage)
|
||||
{
|
||||
assert(ptr != NULL);
|
||||
@@ -887,35 +868,27 @@ void pick_up_name(const char *kind, char *ptr, char **storage)
|
||||
}
|
||||
|
||||
if (*ptr == '\0') {
|
||||
rcfile_error(N_("Missing command after '%s'"), kind);
|
||||
rcfile_error(N_("Missing argument after '%s'"), kind);
|
||||
return;
|
||||
}
|
||||
|
||||
free(*storage);
|
||||
/* If the argument starts with a quote, find the terminating quote. */
|
||||
if (*ptr == '"') {
|
||||
char *look = ++ptr;
|
||||
|
||||
/* Allow unsetting the command by using an empty string. */
|
||||
if (!strcmp(ptr, "\"\""))
|
||||
*storage = NULL;
|
||||
else if (*ptr == '"') {
|
||||
*storage = mallocstrcpy(NULL, ++ptr);
|
||||
char* q = *storage;
|
||||
char* p = *storage;
|
||||
/* Snip out the backslashes of escaped characters. */
|
||||
while (*p != '"') {
|
||||
if (*p == '\0') {
|
||||
look += strlen(ptr);
|
||||
|
||||
while (*look != '"') {
|
||||
if (--look < ptr) {
|
||||
rcfile_error(N_("Argument of '%s' lacks closing \""), kind);
|
||||
free(*storage);
|
||||
*storage = NULL;
|
||||
return;
|
||||
} else if (*p == '\\' && *(p + 1) != '\0') {
|
||||
p++;
|
||||
}
|
||||
*q++ = *p++;
|
||||
}
|
||||
*q = '\0';
|
||||
*look = '\0';
|
||||
}
|
||||
else
|
||||
*storage = mallocstrcpy(NULL, ptr);
|
||||
|
||||
*storage = mallocstrcpy(*storage, ptr);
|
||||
|
||||
}
|
||||
#endif /* !DISABLE_COLOR */
|
||||
|
||||
@@ -1135,6 +1108,8 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
specified_color_combo[TITLE_BAR] = option;
|
||||
else if (strcasecmp(rcopts[i].name, "numbercolor") == 0)
|
||||
specified_color_combo[LINE_NUMBER] = option;
|
||||
else if (strcasecmp(rcopts[i].name, "selectedcolor") == 0)
|
||||
specified_color_combo[SELECTED_TEXT] = option;
|
||||
else if (strcasecmp(rcopts[i].name, "statuscolor") == 0)
|
||||
specified_color_combo[STATUS_BAR] = option;
|
||||
else if (strcasecmp(rcopts[i].name, "keycolor") == 0)
|
||||
|
||||
52
src/search.c
52
src/search.c
@@ -22,11 +22,9 @@
|
||||
#include "proto.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#ifdef DEBUG
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
static bool came_full_circle = FALSE;
|
||||
/* Have we reached the starting line again while searching? */
|
||||
@@ -234,8 +232,10 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
size_t found_x;
|
||||
/* The x coordinate of a found occurrence. */
|
||||
time_t lastkbcheck = time(NULL);
|
||||
/* The time we last looked at the keyboard. */
|
||||
|
||||
enable_nodelay();
|
||||
/* Set non-blocking input so that we can just peek for a Cancel. */
|
||||
disable_waiting();
|
||||
|
||||
if (begin == NULL)
|
||||
came_full_circle = FALSE;
|
||||
@@ -252,7 +252,7 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
while (input) {
|
||||
if (func_from_key(&input) == do_cancel) {
|
||||
statusbar(_("Cancelled"));
|
||||
disable_nodelay();
|
||||
enable_waiting();
|
||||
return -2;
|
||||
}
|
||||
input = parse_kbinput(NULL);
|
||||
@@ -303,7 +303,7 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
/* If we're back at the beginning, then there is no needle. */
|
||||
if (came_full_circle) {
|
||||
not_found_msg(needle);
|
||||
disable_nodelay();
|
||||
enable_waiting();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
* but stop when spell-checking or replacing in a region. */
|
||||
if (line == NULL) {
|
||||
if (whole_word_only || have_region) {
|
||||
disable_nodelay();
|
||||
enable_waiting();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -343,16 +343,15 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
|
||||
found_x = found - line->data;
|
||||
|
||||
enable_waiting();
|
||||
|
||||
/* Ensure that the found occurrence is not beyond the starting x. */
|
||||
if (came_full_circle && ((!ISSET(BACKWARDS_SEARCH) && found_x > begin_x) ||
|
||||
(ISSET(BACKWARDS_SEARCH) && found_x < begin_x))) {
|
||||
not_found_msg(needle);
|
||||
disable_nodelay();
|
||||
return 0;
|
||||
}
|
||||
|
||||
disable_nodelay();
|
||||
|
||||
/* Set the current position to point at what we found. */
|
||||
openfile->current = line;
|
||||
openfile->current_x = found_x;
|
||||
@@ -361,8 +360,11 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
if (match_len != NULL)
|
||||
*match_len = found_len;
|
||||
|
||||
if (feedback > 0)
|
||||
/* Wipe the "Searching..." message and unset the suppression flag. */
|
||||
if (feedback > 0) {
|
||||
blank_statusbar();
|
||||
suppress_cursorpos = FALSE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -457,7 +459,7 @@ void go_looking(void)
|
||||
statusline(HUSH, "Took: %.2f", (double)(clock() - start) / CLOCKS_PER_SEC);
|
||||
#endif
|
||||
|
||||
edit_redraw(was_current);
|
||||
edit_redraw(was_current, CENTERING);
|
||||
search_replace_abort();
|
||||
}
|
||||
|
||||
@@ -610,10 +612,9 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
numreplaced = 0;
|
||||
|
||||
if (!replaceall) {
|
||||
size_t xpt = xplustabs();
|
||||
char *exp_word = display_string(openfile->current->data,
|
||||
xpt, strnlenpt(openfile->current->data,
|
||||
openfile->current_x + match_len) - xpt, FALSE);
|
||||
size_t from_col = xplustabs();
|
||||
size_t to_col = strnlenpt(openfile->current->data,
|
||||
openfile->current_x + match_len);
|
||||
|
||||
/* Refresh the edit window, scrolling it if necessary. */
|
||||
edit_refresh();
|
||||
@@ -621,14 +622,12 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
/* Don't show cursor, to not distract from highlighted match. */
|
||||
curs_set(0);
|
||||
|
||||
spotlight(TRUE, exp_word);
|
||||
spotlight(TRUE, from_col, to_col);
|
||||
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
i = do_yesno_prompt(TRUE, _("Replace this instance?"));
|
||||
|
||||
spotlight(FALSE, exp_word);
|
||||
|
||||
free(exp_word);
|
||||
spotlight(FALSE, from_col, to_col);
|
||||
|
||||
if (i == -1) /* The replacing was cancelled. */
|
||||
break;
|
||||
@@ -855,10 +854,10 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (line < 1)
|
||||
if (line == 0)
|
||||
line = openfile->current->lineno;
|
||||
|
||||
if (column < 1)
|
||||
if (column == 0)
|
||||
column = openfile->placewewant + 1;
|
||||
}
|
||||
|
||||
@@ -899,7 +898,7 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
filestruct *line = openfile->current;
|
||||
size_t leftedge = (xplustabs() / editwincols) * editwincols;
|
||||
size_t leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
|
||||
rows_from_tail = (editwinrows / 2) -
|
||||
go_forward_chunks(editwinrows / 2, &line, &leftedge);
|
||||
@@ -911,7 +910,7 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
/* If the target line is close to the tail of the file, put the last
|
||||
* line or chunk on the bottom line of the screen; otherwise, just
|
||||
* center the target line. */
|
||||
if (rows_from_tail < editwinrows / 2) {
|
||||
if (rows_from_tail < editwinrows / 2 && ISSET(SMOOTH_SCROLL)) {
|
||||
openfile->current_y = editwinrows - 1 - rows_from_tail;
|
||||
adjust_viewport(STATIONARY);
|
||||
} else
|
||||
@@ -1074,8 +1073,7 @@ void do_find_bracket(void)
|
||||
/* If count is zero, we've found a matching bracket. Update
|
||||
* the screen and get out. */
|
||||
if (count == 0) {
|
||||
focusing = FALSE;
|
||||
edit_redraw(current_save);
|
||||
edit_redraw(current_save, FLOWING);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
404
src/text.c
404
src/text.c
@@ -24,13 +24,11 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#ifndef NANO_TINY
|
||||
static pid_t pid = -1;
|
||||
@@ -52,7 +50,7 @@ static filestruct *jusbottom = NULL;
|
||||
static int pletion_x = 0;
|
||||
/* The x position in pletion_line of the last found completion. */
|
||||
static completion_word *list_of_completions;
|
||||
/* A linked list of the completions that have been attepmted. */
|
||||
/* A linked list of the completions that have been attempted. */
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -91,7 +89,7 @@ char *invocation_error(const char *name)
|
||||
void do_deletion(undo_type action)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
size_t orig_rows = 0;
|
||||
size_t old_amount = 0;
|
||||
#endif
|
||||
|
||||
assert(openfile->current != NULL && openfile->current->data != NULL &&
|
||||
@@ -112,7 +110,7 @@ void do_deletion(undo_type action)
|
||||
update_undo(action);
|
||||
|
||||
if (ISSET(SOFTWRAP))
|
||||
orig_rows = strlenpt(openfile->current->data) / editwincols;
|
||||
old_amount = number_of_chunks_in(openfile->current);
|
||||
#endif
|
||||
|
||||
/* Move the remainder of the line "in", over the current character. */
|
||||
@@ -181,7 +179,7 @@ void do_deletion(undo_type action)
|
||||
/* If the number of screen rows that a softwrapped line occupies
|
||||
* has changed, we need a full refresh. */
|
||||
if (ISSET(SOFTWRAP) && refresh_needed == FALSE &&
|
||||
strlenpt(openfile->current->data) / editwincols != orig_rows)
|
||||
number_of_chunks_in(openfile->current) != old_amount)
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
|
||||
@@ -277,171 +275,165 @@ void do_tab(void)
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Indent or unindent the current line (or, if the mark is on, all lines
|
||||
* covered by the mark) len columns, depending on whether len is
|
||||
* positive or negative. If the TABS_TO_SPACES flag is set, indent or
|
||||
* unindent by len spaces. Otherwise, indent or unindent by (len /
|
||||
* tabsize) tabs and (len % tabsize) spaces. */
|
||||
void do_indent(ssize_t cols)
|
||||
/* Indent the current line (or the marked lines) by tabsize columns.
|
||||
* This inserts either a tab character or a tab's worth of spaces,
|
||||
* depending on whether --tabstospaces is in effect. */
|
||||
void do_indent(void)
|
||||
{
|
||||
bool indent_changed = FALSE;
|
||||
/* Whether any indenting or unindenting was done. */
|
||||
bool unindent = FALSE;
|
||||
/* Whether we're unindenting text. */
|
||||
char *line_indent = NULL;
|
||||
/* The text added to each line in order to indent it. */
|
||||
char *line_indent = charalloc(tabsize + 1);
|
||||
/* The whitespace added to each line in order to indent it. */
|
||||
size_t line_indent_len = 0;
|
||||
/* The length of the text added to each line in order to indent
|
||||
* it. */
|
||||
/* The number of bytes added to each line in order to indent it. */
|
||||
filestruct *top, *bot, *f;
|
||||
size_t top_x, bot_x;
|
||||
|
||||
assert(openfile->current != NULL && openfile->current->data != NULL);
|
||||
|
||||
/* If cols is zero, get out. */
|
||||
if (cols == 0)
|
||||
return;
|
||||
|
||||
/* If cols is negative, make it positive and set unindent to TRUE. */
|
||||
if (cols < 0) {
|
||||
cols = -cols;
|
||||
unindent = TRUE;
|
||||
/* Otherwise, we're indenting, in which case the file will always be
|
||||
* modified, so set indent_changed to TRUE. */
|
||||
} else
|
||||
indent_changed = TRUE;
|
||||
|
||||
/* If the mark is on, use all lines covered by the mark. */
|
||||
/* Use either all the marked lines or just the current line. */
|
||||
if (openfile->mark_set)
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
/* Otherwise, use the current line. */
|
||||
else {
|
||||
top = openfile->current;
|
||||
bot = top;
|
||||
}
|
||||
|
||||
if (!unindent) {
|
||||
/* Set up the text we'll be using as indentation. */
|
||||
line_indent = charalloc(cols + 1);
|
||||
|
||||
if (ISSET(TABS_TO_SPACES)) {
|
||||
/* Set the indentation to cols spaces. */
|
||||
charset(line_indent, ' ', cols);
|
||||
line_indent_len = cols;
|
||||
} else {
|
||||
/* Set the indentation to (cols / tabsize) tabs and (cols %
|
||||
* tabsize) spaces. */
|
||||
size_t num_tabs = cols / tabsize;
|
||||
size_t num_spaces = cols % tabsize;
|
||||
|
||||
charset(line_indent, '\t', num_tabs);
|
||||
charset(line_indent + num_tabs, ' ', num_spaces);
|
||||
|
||||
line_indent_len = num_tabs + num_spaces;
|
||||
}
|
||||
|
||||
line_indent[line_indent_len] = '\0';
|
||||
/* Go through the lines to see if there's a non-empty one. */
|
||||
for (f = top; f != bot->next; f = f->next) {
|
||||
if (f->data[0] != '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
/* Go through each line of the text. */
|
||||
/* If all lines are empty, there is nothing to do. */
|
||||
if (f == bot->next) {
|
||||
free(line_indent);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the indentation to either a bunch of spaces or a single tab. */
|
||||
if (ISSET(TABS_TO_SPACES)) {
|
||||
charset(line_indent, ' ', tabsize);
|
||||
line_indent_len = tabsize;
|
||||
} else {
|
||||
line_indent[0] = '\t';
|
||||
line_indent_len = 1;
|
||||
}
|
||||
|
||||
line_indent[line_indent_len] = '\0';
|
||||
|
||||
/* Go through each of the lines, but skip empty ones. */
|
||||
for (f = top; f != bot->next; f = f->next) {
|
||||
size_t line_len = strlen(f->data);
|
||||
size_t indent_len = indent_length(f->data);
|
||||
|
||||
if (!unindent) {
|
||||
/* If we're indenting, add the characters in line_indent to
|
||||
* the beginning of the non-whitespace text of this line. */
|
||||
f->data = charealloc(f->data, line_len + line_indent_len + 1);
|
||||
charmove(&f->data[indent_len + line_indent_len],
|
||||
&f->data[indent_len], line_len - indent_len + 1);
|
||||
strncpy(f->data + indent_len, line_indent, line_indent_len);
|
||||
openfile->totsize += line_indent_len;
|
||||
if (f->data[0] == '\0')
|
||||
continue;
|
||||
|
||||
/* Keep track of the change in the current line. */
|
||||
if (openfile->mark_set && f == openfile->mark_begin &&
|
||||
openfile->mark_begin_x >= indent_len)
|
||||
openfile->mark_begin_x += line_indent_len;
|
||||
/* Add the fabricated indentation to the beginning of the line. */
|
||||
f->data = charealloc(f->data, line_len + line_indent_len + 1);
|
||||
charmove(&f->data[line_indent_len], f->data, line_len + 1);
|
||||
strncpy(f->data, line_indent, line_indent_len);
|
||||
|
||||
if (f == openfile->current && openfile->current_x >= indent_len)
|
||||
openfile->current_x += line_indent_len;
|
||||
openfile->totsize += line_indent_len;
|
||||
|
||||
/* If the NO_NEWLINES flag isn't set, and this is the
|
||||
* magicline, add a new magicline. */
|
||||
if (!ISSET(NO_NEWLINES) && f == openfile->filebot)
|
||||
new_magicline();
|
||||
} else {
|
||||
size_t indent_col = strnlenpt(f->data, indent_len);
|
||||
/* The length in columns of the indentation on this line. */
|
||||
|
||||
if (cols <= indent_col) {
|
||||
size_t indent_new = actual_x(f->data, indent_col - cols);
|
||||
/* The length of the indentation remaining on
|
||||
* this line after we unindent. */
|
||||
size_t indent_shift = indent_len - indent_new;
|
||||
/* The change in the indentation on this line
|
||||
* after we unindent. */
|
||||
|
||||
/* If we're unindenting, and there's at least cols
|
||||
* columns' worth of indentation at the beginning of the
|
||||
* non-whitespace text of this line, remove it. */
|
||||
charmove(&f->data[indent_new], &f->data[indent_len],
|
||||
line_len - indent_shift - indent_new + 1);
|
||||
null_at(&f->data, line_len - indent_shift + 1);
|
||||
openfile->totsize -= indent_shift;
|
||||
|
||||
/* Keep track of the change in the current line. */
|
||||
if (openfile->mark_set && f == openfile->mark_begin &&
|
||||
openfile->mark_begin_x > indent_new) {
|
||||
if (openfile->mark_begin_x <= indent_len)
|
||||
openfile->mark_begin_x = indent_new;
|
||||
else
|
||||
openfile->mark_begin_x -= indent_shift;
|
||||
}
|
||||
|
||||
if (f == openfile->current &&
|
||||
openfile->current_x > indent_new) {
|
||||
if (openfile->current_x <= indent_len)
|
||||
openfile->current_x = indent_new;
|
||||
else
|
||||
openfile->current_x -= indent_shift;
|
||||
}
|
||||
|
||||
/* We've unindented, so the indentation changed. */
|
||||
indent_changed = TRUE;
|
||||
}
|
||||
/* Compensate for the change in the current line. */
|
||||
if (openfile->mark_set && f == openfile->mark_begin)
|
||||
openfile->mark_begin_x += line_indent_len;
|
||||
if (f == openfile->current) {
|
||||
openfile->current_x += line_indent_len;
|
||||
openfile->placewewant = xplustabs();
|
||||
}
|
||||
}
|
||||
|
||||
if (!unindent)
|
||||
/* Clean up. */
|
||||
free(line_indent);
|
||||
free(line_indent);
|
||||
|
||||
if (indent_changed) {
|
||||
/* Throw away the undo stack, to prevent making mistakes when
|
||||
* the user tries to undo something in the reindented text. */
|
||||
discard_until(NULL, openfile);
|
||||
/* Throw away the undo stack, to prevent making mistakes when
|
||||
* the user tries to undo something in the indented text. */
|
||||
discard_until(NULL, openfile);
|
||||
|
||||
/* Mark the file as modified. */
|
||||
set_modified();
|
||||
set_modified();
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
/* Update the screen. */
|
||||
refresh_needed = TRUE;
|
||||
/* If the given text starts with a tab's worth of whitespace, return the
|
||||
* number of bytes this whitespace occupies. Otherwise, return zero. */
|
||||
size_t length_of_white(const char *text)
|
||||
{
|
||||
size_t bytes_of_white = 1;
|
||||
|
||||
while (TRUE) {
|
||||
if (*text == '\t')
|
||||
return bytes_of_white;
|
||||
|
||||
if (*text != ' ')
|
||||
return 0;
|
||||
|
||||
if (bytes_of_white == tabsize)
|
||||
return tabsize;
|
||||
|
||||
bytes_of_white++;
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Indent the current line, or all lines covered by the mark if the mark
|
||||
* is on, tabsize columns. */
|
||||
void do_indent_void(void)
|
||||
{
|
||||
do_indent(tabsize);
|
||||
}
|
||||
|
||||
/* Unindent the current line, or all lines covered by the mark if the
|
||||
* mark is on, tabsize columns. */
|
||||
/* Unindent the current line (or the marked lines) by tabsize columns.
|
||||
* The removed indent can be a mixture of spaces plus at most one tab. */
|
||||
void do_unindent(void)
|
||||
{
|
||||
do_indent(-tabsize);
|
||||
filestruct *top, *bot, *f;
|
||||
size_t top_x, bot_x;
|
||||
|
||||
/* Use either all the marked lines or just the current line. */
|
||||
if (openfile->mark_set)
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
else {
|
||||
top = openfile->current;
|
||||
bot = top;
|
||||
}
|
||||
|
||||
/* If any of the lines cannot be unindented and does not consist of
|
||||
* only whitespace, we don't change anything. */
|
||||
for (f = top; f != bot->next; f = f->next) {
|
||||
if (length_of_white(f->data) == 0 && !white_string(f->data)) {
|
||||
statusline(HUSH, _("Can unindent only by a full tab size"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go through each of the lines and remove their leading indent. */
|
||||
for (f = top; f != bot->next; f = f->next) {
|
||||
size_t line_len = strlen(f->data);
|
||||
size_t indent_len = length_of_white(f->data);
|
||||
|
||||
/* If this line cannot be unindeted, simply skip it. */
|
||||
if (indent_len == 0)
|
||||
continue;
|
||||
|
||||
/* Remove the first tab's worth of whitespace from this line. */
|
||||
charmove(f->data, &f->data[indent_len], line_len - indent_len + 1);
|
||||
null_at(&f->data, line_len - indent_len + 1);
|
||||
openfile->totsize -= indent_len;
|
||||
|
||||
/* Compensate for the change in the current line. */
|
||||
if (openfile->mark_set && f == openfile->mark_begin) {
|
||||
if (openfile->mark_begin_x <= indent_len)
|
||||
openfile->mark_begin_x = 0;
|
||||
else
|
||||
openfile->mark_begin_x -= indent_len;
|
||||
}
|
||||
if (f == openfile->current) {
|
||||
if (openfile->current_x <= indent_len)
|
||||
openfile->current_x = 0;
|
||||
else
|
||||
openfile->current_x -= indent_len;
|
||||
openfile->placewewant = xplustabs();
|
||||
}
|
||||
}
|
||||
|
||||
/* Throw away the undo stack, to prevent making mistakes when
|
||||
* the user tries to undo something in the unindented text. */
|
||||
discard_until(NULL, openfile);
|
||||
|
||||
set_modified();
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
@@ -456,9 +448,9 @@ bool white_string(const char *s)
|
||||
|
||||
#ifdef ENABLE_COMMENT
|
||||
/* Comment or uncomment the current line or the marked lines. */
|
||||
void do_comment()
|
||||
void do_comment(void)
|
||||
{
|
||||
const char *comment_seq = "#";
|
||||
const char *comment_seq = GENERAL_COMMENT_CHARACTER;
|
||||
undo_type action = UNCOMMENT;
|
||||
filestruct *top, *bot, *f;
|
||||
size_t top_x, bot_x;
|
||||
@@ -467,11 +459,10 @@ void do_comment()
|
||||
assert(openfile->current != NULL && openfile->current->data != NULL);
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
if (openfile->syntax && openfile->syntax->comment)
|
||||
if (openfile->syntax)
|
||||
comment_seq = openfile->syntax->comment;
|
||||
|
||||
/* Does the syntax not allow comments? */
|
||||
if (strlen(comment_seq) == 0) {
|
||||
if (*comment_seq == '\0') {
|
||||
statusbar(_("Commenting is not supported for this file type"));
|
||||
return;
|
||||
}
|
||||
@@ -653,12 +644,14 @@ void undo_cut(undo *u)
|
||||
/* Redo a cut, or undo an uncut. */
|
||||
void redo_cut(undo *u)
|
||||
{
|
||||
filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
|
||||
|
||||
/* If we cut the magicline, we may as well not crash. :/ */
|
||||
if (!u->cutbuffer)
|
||||
return;
|
||||
|
||||
filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
|
||||
cutbuffer = cutbottom = NULL;
|
||||
cutbuffer = NULL;
|
||||
cutbottom = NULL;
|
||||
|
||||
goto_line_posx(u->lineno, u->begin);
|
||||
|
||||
@@ -678,7 +671,9 @@ void do_undo(void)
|
||||
{
|
||||
undo *u = openfile->current_undo;
|
||||
filestruct *f, *t = NULL;
|
||||
filestruct *oldcutbuffer, *oldcutbottom;
|
||||
char *data, *undidmsg = NULL;
|
||||
size_t from_x, to_x;
|
||||
|
||||
if (!u) {
|
||||
statusbar(_("Nothing in undo buffer!"));
|
||||
@@ -749,7 +744,7 @@ void do_undo(void)
|
||||
splice_node(f, t);
|
||||
goto_line_posx(u->lineno, u->begin);
|
||||
break;
|
||||
case CUT_EOF:
|
||||
case CUT_TO_EOF:
|
||||
case CUT:
|
||||
undidmsg = _("text cut");
|
||||
undo_cut(u);
|
||||
@@ -767,8 +762,8 @@ void do_undo(void)
|
||||
break;
|
||||
}
|
||||
undidmsg = _("line break");
|
||||
size_t from_x = (u->begin == 0) ? 0 : u->mark_begin_x;
|
||||
size_t to_x = (u->begin == 0) ? u->mark_begin_x : u->begin;
|
||||
from_x = (u->begin == 0) ? 0 : u->mark_begin_x;
|
||||
to_x = (u->begin == 0) ? u->mark_begin_x : u->begin;
|
||||
f->data = charealloc(f->data, strlen(f->data) +
|
||||
strlen(&u->strdata[from_x]) + 1);
|
||||
strcat(f->data, &u->strdata[from_x]);
|
||||
@@ -787,7 +782,8 @@ void do_undo(void)
|
||||
#endif
|
||||
case INSERT:
|
||||
undidmsg = _("text insert");
|
||||
filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
|
||||
oldcutbuffer = cutbuffer;
|
||||
oldcutbottom = cutbottom;
|
||||
cutbuffer = NULL;
|
||||
cutbottom = NULL;
|
||||
openfile->mark_begin = fsfromline(u->mark_begin_lineno);
|
||||
@@ -832,7 +828,7 @@ void do_undo(void)
|
||||
/* Redo the last thing(s) we undid. */
|
||||
void do_redo(void)
|
||||
{
|
||||
filestruct *f;
|
||||
filestruct *f, *shoveline;
|
||||
char *data, *redidmsg = NULL;
|
||||
undo *u = openfile->undotop;
|
||||
|
||||
@@ -883,7 +879,7 @@ void do_redo(void)
|
||||
break;
|
||||
case ENTER:
|
||||
redidmsg = _("line break");
|
||||
filestruct *shoveline = make_new_node(f);
|
||||
shoveline = make_new_node(f);
|
||||
shoveline->data = mallocstrcpy(NULL, u->strdata);
|
||||
data = mallocstrncpy(NULL, f->data, u->begin + 1);
|
||||
data[u->begin] = '\0';
|
||||
@@ -926,7 +922,7 @@ void do_redo(void)
|
||||
renumber(f);
|
||||
goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
|
||||
break;
|
||||
case CUT_EOF:
|
||||
case CUT_TO_EOF:
|
||||
case CUT:
|
||||
redidmsg = _("text cut");
|
||||
redo_cut(u);
|
||||
@@ -1140,7 +1136,9 @@ bool execute_command(const char *command)
|
||||
void discard_until(const undo *thisitem, openfilestruct *thefile)
|
||||
{
|
||||
undo *dropit = thefile->undotop;
|
||||
#ifdef ENABLE_COMMENT
|
||||
undo_group *group;
|
||||
#endif
|
||||
|
||||
while (dropit != NULL && dropit != thisitem) {
|
||||
thefile->undotop = dropit->next;
|
||||
@@ -1259,7 +1257,7 @@ void add_undo(undo_type action)
|
||||
case REPLACE:
|
||||
u->strdata = mallocstrcpy(NULL, openfile->current->data);
|
||||
break;
|
||||
case CUT_EOF:
|
||||
case CUT_TO_EOF:
|
||||
cutbuffer_reset();
|
||||
break;
|
||||
case CUT:
|
||||
@@ -1268,7 +1266,7 @@ void add_undo(undo_type action)
|
||||
u->mark_begin_lineno = openfile->mark_begin->lineno;
|
||||
u->mark_begin_x = openfile->mark_begin_x;
|
||||
u->xflags = MARK_WAS_SET;
|
||||
} else if (!ISSET(CUT_TO_END)) {
|
||||
} else if (!ISSET(CUT_FROM_CURSOR)) {
|
||||
/* The entire line is being cut regardless of the cursor position. */
|
||||
u->begin = 0;
|
||||
u->xflags = WAS_WHOLE_LINE;
|
||||
@@ -1393,7 +1391,7 @@ fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openf
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case CUT_EOF:
|
||||
case CUT_TO_EOF:
|
||||
case CUT:
|
||||
if (!cutbuffer)
|
||||
break;
|
||||
@@ -1404,11 +1402,12 @@ fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openf
|
||||
* bottom-->top, then swap the mark points. */
|
||||
if ((u->lineno == u->mark_begin_lineno && u->begin < u->mark_begin_x)
|
||||
|| u->lineno < u->mark_begin_lineno) {
|
||||
ssize_t line = u->lineno;
|
||||
size_t x_loc = u->begin;
|
||||
|
||||
u->begin = u->mark_begin_x;
|
||||
u->mark_begin_x = x_loc;
|
||||
|
||||
ssize_t line = u->lineno;
|
||||
u->lineno = u->mark_begin_lineno;
|
||||
u->mark_begin_lineno = line;
|
||||
} else
|
||||
@@ -1420,7 +1419,7 @@ fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openf
|
||||
u->cutbottom = u->cutbottom->next;
|
||||
u->lineno = u->mark_begin_lineno + u->cutbottom->lineno -
|
||||
u->cutbuffer->lineno;
|
||||
if (ISSET(CUT_TO_END) || u->type == CUT_EOF) {
|
||||
if (ISSET(CUT_FROM_CURSOR) || u->type == CUT_TO_EOF) {
|
||||
u->begin = strlen(u->cutbottom->data);
|
||||
if (u->lineno == u->mark_begin_lineno)
|
||||
u->begin += u->mark_begin_x;
|
||||
@@ -1485,6 +1484,9 @@ bool do_wrap(filestruct *line)
|
||||
size_t next_line_len = 0;
|
||||
/* The length of next_line. */
|
||||
|
||||
size_t old_x = openfile->current_x;
|
||||
filestruct * old_line = openfile->current;
|
||||
|
||||
/* There are three steps. First, we decide where to wrap. Then, we
|
||||
* create the new wrap line. Finally, we clean up. */
|
||||
|
||||
@@ -1527,8 +1529,6 @@ bool do_wrap(filestruct *line)
|
||||
add_undo(SPLIT_BEGIN);
|
||||
#endif
|
||||
|
||||
size_t old_x = openfile->current_x;
|
||||
filestruct * oldLine = openfile->current;
|
||||
openfile->current = line;
|
||||
|
||||
/* Step 2, making the new wrap line. It will consist of indentation
|
||||
@@ -1591,7 +1591,7 @@ bool do_wrap(filestruct *line)
|
||||
|
||||
if (old_x < wrap_loc) {
|
||||
openfile->current_x = old_x;
|
||||
openfile->current = oldLine;
|
||||
openfile->current = old_line;
|
||||
prepend_wrap = TRUE;
|
||||
} else {
|
||||
openfile->current_x += (old_x - wrap_loc);
|
||||
@@ -2429,7 +2429,7 @@ void do_justify(bool full_justify)
|
||||
|
||||
edit_refresh();
|
||||
|
||||
/* Display the shortcut list with UnJustify. */
|
||||
/* Show "Unjustify" in the help lines. */
|
||||
uncutfunc->desc = unjust_tag;
|
||||
display_main_list();
|
||||
|
||||
@@ -2439,17 +2439,15 @@ void do_justify(bool full_justify)
|
||||
do {
|
||||
#endif
|
||||
statusbar(_("Can now UnJustify!"));
|
||||
place_the_cursor(TRUE);
|
||||
place_the_cursor();
|
||||
curs_set(1);
|
||||
kbinput = do_input(FALSE);
|
||||
#ifndef NANO_TINY
|
||||
} while (kbinput == KEY_WINCH);
|
||||
#endif
|
||||
|
||||
/* If needed, unset the cursor-position suppression flag, so the cursor
|
||||
* position /will/ be displayed upon a return to the main loop. */
|
||||
if (ISSET(CONSTANT_SHOW))
|
||||
do_cursorpos(FALSE);
|
||||
/* Unset the suppression flag after showing the Unjustify message. */
|
||||
suppress_cursorpos = FALSE;
|
||||
|
||||
func = func_from_key(&kbinput);
|
||||
|
||||
@@ -2507,10 +2505,11 @@ void do_justify(bool full_justify)
|
||||
jusbuffer = NULL;
|
||||
|
||||
blank_statusbar();
|
||||
wnoutrefresh(bottomwin);
|
||||
|
||||
/* Display the shortcut list with UnCut. */
|
||||
/* Show "Uncut" again in the help lines, and force their redrawing. */
|
||||
uncutfunc->desc = uncut_tag;
|
||||
display_main_list();
|
||||
currmenu = MMOST;
|
||||
}
|
||||
|
||||
/* Justify the current paragraph. */
|
||||
@@ -2531,7 +2530,7 @@ void do_full_justify(void)
|
||||
* return FALSE if the user cancels. */
|
||||
bool do_int_spell_fix(const char *word)
|
||||
{
|
||||
char *save_search, *exp_word;
|
||||
char *save_search;
|
||||
size_t firstcolumn_save = openfile->firstcolumn;
|
||||
size_t current_x_save = openfile->current_x;
|
||||
filestruct *edittop_save = openfile->edittop;
|
||||
@@ -2596,11 +2595,12 @@ bool do_int_spell_fix(const char *word)
|
||||
proceed = TRUE;
|
||||
napms(2800);
|
||||
} else if (result == 1) {
|
||||
exp_word = display_string(openfile->current->data, xplustabs(),
|
||||
strlenpt(word), FALSE);
|
||||
size_t from_col = xplustabs();
|
||||
size_t to_col = from_col + strlenpt(word);
|
||||
|
||||
edit_refresh();
|
||||
|
||||
spotlight(TRUE, exp_word);
|
||||
spotlight(TRUE, from_col, to_col);
|
||||
|
||||
/* Let the user supply a correctly spelled alternative. */
|
||||
proceed = (do_prompt(FALSE, FALSE, MSPELL, word,
|
||||
@@ -2609,9 +2609,7 @@ bool do_int_spell_fix(const char *word)
|
||||
#endif
|
||||
edit_refresh, _("Edit a replacement")) != -1);
|
||||
|
||||
spotlight(FALSE, exp_word);
|
||||
|
||||
free(exp_word);
|
||||
spotlight(FALSE, from_col, to_col);
|
||||
|
||||
/* If a replacement was given, go through all occurrences. */
|
||||
if (proceed && strcmp(word, answer) != 0) {
|
||||
@@ -3028,14 +3026,13 @@ void do_spell(void)
|
||||
* termination, and the error string otherwise. */
|
||||
void do_linter(void)
|
||||
{
|
||||
char *read_buff, *read_buff_ptr, *read_buff_word, *ptr;
|
||||
char *read_buff, *read_buff_ptr, *read_buff_word, *ptr, *lintcopy;
|
||||
size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread;
|
||||
size_t parsesuccess = 0;
|
||||
int lint_status, lint_fd[2];
|
||||
pid_t pid_lint;
|
||||
static int arglen = 3;
|
||||
static char **lintargs = NULL;
|
||||
char *lintcopy, *convendptr = NULL;
|
||||
lintstruct *lints = NULL, *tmplint = NULL, *curlint = NULL;
|
||||
|
||||
if (ISSET(RESTRICTED)) {
|
||||
@@ -3126,9 +3123,6 @@ void do_linter(void)
|
||||
read_buff = read_buff_ptr = charalloc(read_buff_size);
|
||||
|
||||
while ((bytesread = read(lint_fd[0], read_buff_ptr, pipe_buff_size)) > 0) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "text.c:do_linter:%ld bytes (%s)\n", (long)bytesread, read_buff_ptr);
|
||||
#endif
|
||||
read_buff_read += bytesread;
|
||||
read_buff_size += pipe_buff_size;
|
||||
read_buff = read_buff_ptr = charealloc(read_buff, read_buff_size);
|
||||
@@ -3138,10 +3132,6 @@ void do_linter(void)
|
||||
*read_buff_ptr = '\0';
|
||||
close(lint_fd[0]);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "text.c:do_lint:Raw output: %s\n", read_buff);
|
||||
#endif
|
||||
|
||||
/* Process the linter output. */
|
||||
read_buff_word = read_buff_ptr = read_buff;
|
||||
|
||||
@@ -3152,15 +3142,14 @@ void do_linter(void)
|
||||
char *filename = NULL, *linestr = NULL, *maybecol = NULL;
|
||||
char *message = mallocstrcpy(NULL, read_buff_word);
|
||||
|
||||
/* At the moment we're assuming the following formats:
|
||||
/* At the moment we handle the following formats:
|
||||
*
|
||||
* filenameorcategory:line:column:message (e.g. splint)
|
||||
* filenameorcategory:line,column:message (e.g. pylint)
|
||||
* filenameorcategory:line:message (e.g. pyflakes)
|
||||
* filenameorcategory:line,col:message (e.g. pylint)
|
||||
*
|
||||
* This could be turned into some scanf() based parser,
|
||||
* but ugh. */
|
||||
if ((filename = strtok(read_buff_word, ":")) != NULL) {
|
||||
*/
|
||||
if (strstr(message, ": ") != NULL) {
|
||||
filename = strtok(read_buff_word, ":");
|
||||
if ((linestr = strtok(NULL, ":")) != NULL) {
|
||||
if ((maybecol = strtok(NULL, ":")) != NULL) {
|
||||
ssize_t tmplineno = 0, tmpcolno = 0;
|
||||
@@ -3173,18 +3162,16 @@ void do_linter(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
tmpcolno = strtol(maybecol, &convendptr, 10);
|
||||
if (*convendptr != '\0') {
|
||||
/* Previous field might still be
|
||||
* line,col format. */
|
||||
tmpcolno = strtol(maybecol, NULL, 10);
|
||||
/* Check if the middle field is in comma format. */
|
||||
if (tmpcolno <= 0) {
|
||||
strtok(linestr, ",");
|
||||
if ((tmplinecol = strtok(NULL, ",")) != NULL)
|
||||
tmpcolno = strtol(tmplinecol, NULL, 10);
|
||||
else
|
||||
tmpcolno = 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "text.c:do_lint:Successful parse! %ld:%ld:%s\n", (long)tmplineno, (long)tmpcolno, message);
|
||||
#endif
|
||||
/* Nice. We have a lint message we can use. */
|
||||
parsesuccess++;
|
||||
tmplint = curlint;
|
||||
@@ -3311,7 +3298,7 @@ void do_linter(void)
|
||||
}
|
||||
|
||||
/* Place and show the cursor to indicate the affected line. */
|
||||
place_the_cursor(TRUE);
|
||||
place_the_cursor();
|
||||
wnoutrefresh(edit);
|
||||
curs_set(1);
|
||||
|
||||
@@ -3343,6 +3330,7 @@ void do_linter(void)
|
||||
}
|
||||
|
||||
blank_statusbar();
|
||||
wnoutrefresh(bottomwin);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
free_lints_and_return:
|
||||
@@ -3408,7 +3396,7 @@ void do_formatter(void)
|
||||
formatargs[0] = strtok(openfile->syntax->formatter, " ");
|
||||
while ((ptr = strtok(NULL, " ")) != NULL) {
|
||||
arglen++;
|
||||
formatargs = (char **)nrealloc(formatargs, arglen * sizeof(char *));
|
||||
formatargs = (char **)nrealloc(formatargs, arglen * sizeof(char *));
|
||||
formatargs[arglen - 3] = ptr;
|
||||
}
|
||||
formatargs[arglen - 1] = NULL;
|
||||
@@ -3558,7 +3546,7 @@ void do_verbatim_input(void)
|
||||
/* TRANSLATORS: This is displayed when the next keystroke will be
|
||||
* inserted verbatim. */
|
||||
statusbar(_("Verbatim Input"));
|
||||
place_the_cursor(TRUE);
|
||||
place_the_cursor();
|
||||
curs_set(1);
|
||||
|
||||
/* Read in all the verbatim characters. */
|
||||
@@ -3566,7 +3554,7 @@ void do_verbatim_input(void)
|
||||
|
||||
/* Unsuppress cursor-position display or blank the statusbar. */
|
||||
if (ISSET(CONSTANT_SHOW))
|
||||
do_cursorpos(FALSE);
|
||||
suppress_cursorpos = FALSE;
|
||||
else {
|
||||
blank_statusbar();
|
||||
wnoutrefresh(bottomwin);
|
||||
@@ -3601,7 +3589,7 @@ char *copy_completion(char *check_line, int start)
|
||||
position = next;
|
||||
}
|
||||
|
||||
word = (char *)nmalloc((len_of_word + 1) * sizeof(char));
|
||||
word = charalloc(len_of_word + 1);
|
||||
|
||||
/* Simply copy the word. */
|
||||
while (index < len_of_word)
|
||||
@@ -3666,7 +3654,7 @@ void complete_a_word(void)
|
||||
return;
|
||||
}
|
||||
|
||||
shard = (char *)nmalloc((openfile->current_x - start_of_shard + 1) * sizeof(char));
|
||||
shard = charalloc(openfile->current_x - start_of_shard + 1);
|
||||
|
||||
/* Copy the fragment that has to be searched for. */
|
||||
while (start_of_shard < openfile->current_x)
|
||||
|
||||
@@ -21,14 +21,12 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Return the user's home directory. We use $HOME, and if that fails,
|
||||
* we fall back on the home directory of the effective user ID. */
|
||||
|
||||
569
src/winio.c
569
src/winio.c
@@ -22,15 +22,11 @@
|
||||
#include "proto.h"
|
||||
#include "revision.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef __linux__
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef REVISION
|
||||
#define BRANDING REVISION
|
||||
@@ -45,10 +41,10 @@ static size_t key_buffer_len = 0;
|
||||
/* The length of the keystroke buffer. */
|
||||
static bool solitary = FALSE;
|
||||
/* Whether an Esc arrived by itself -- not as leader of a sequence. */
|
||||
static bool waiting_mode = TRUE;
|
||||
/* Whether getting a character will wait for a key to be pressed. */
|
||||
static int statusblank = 0;
|
||||
/* The number of keystrokes left before we blank the statusbar. */
|
||||
static bool suppress_cursorpos = FALSE;
|
||||
/* Should we skip constant position display for one keystroke? */
|
||||
#ifdef USING_OLD_NCURSES
|
||||
static bool seen_wide = FALSE;
|
||||
/* Whether we've seen a multicolumn character in the current line. */
|
||||
@@ -135,7 +131,7 @@ void get_key_buffer(WINDOW *win)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (input == ERR && nodelay_mode)
|
||||
if (input == ERR && !waiting_mode)
|
||||
return;
|
||||
|
||||
while (input == ERR) {
|
||||
@@ -144,7 +140,7 @@ void get_key_buffer(WINDOW *win)
|
||||
* check if errno is set to EIO ("Input/output error") and die in
|
||||
* that case, but it's not always set properly. Argh. */
|
||||
if (++errcount == MAX_BUF_SIZE)
|
||||
handle_hupterm(0);
|
||||
die(_("Too many errors from stdin"));
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (the_window_resized) {
|
||||
@@ -188,7 +184,7 @@ void get_key_buffer(WINDOW *win)
|
||||
}
|
||||
|
||||
/* Restore waiting mode if it was on. */
|
||||
if (!nodelay_mode)
|
||||
if (waiting_mode)
|
||||
nodelay(win, FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -327,7 +323,7 @@ int parse_kbinput(WINDOW *win)
|
||||
/* Read in a character. */
|
||||
kbinput = get_input(win, 1);
|
||||
|
||||
if (kbinput == NULL && nodelay_mode)
|
||||
if (kbinput == NULL && !waiting_mode)
|
||||
return 0;
|
||||
|
||||
while (kbinput == NULL)
|
||||
@@ -527,7 +523,15 @@ int parse_kbinput(WINDOW *win)
|
||||
} else if (retval == shiftcontrolend) {
|
||||
shift_held = TRUE;
|
||||
return CONTROL_END;
|
||||
} else if (retval == shiftaltleft) {
|
||||
} else if (retval == altleft)
|
||||
return ALT_LEFT;
|
||||
else if (retval == altright)
|
||||
return ALT_RIGHT;
|
||||
else if (retval == altup)
|
||||
return ALT_UP;
|
||||
else if (retval == altdown)
|
||||
return ALT_DOWN;
|
||||
else if (retval == shiftaltleft) {
|
||||
shift_held = TRUE;
|
||||
return KEY_HOME;
|
||||
} else if (retval == shiftaltright) {
|
||||
@@ -703,8 +707,12 @@ int parse_kbinput(WINDOW *win)
|
||||
#ifdef KEY_RESIZE
|
||||
/* Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
|
||||
case KEY_RESIZE:
|
||||
return ERR;
|
||||
#endif
|
||||
#if defined(USE_SLANG) && defined(ENABLE_UTF8)
|
||||
case KEY_BAD:
|
||||
#endif
|
||||
case KEY_FLUSH:
|
||||
return ERR;
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -772,6 +780,19 @@ int convert_sequence(const int *seq, size_t seq_len)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '5':
|
||||
if (seq_len >= 3) {
|
||||
switch (seq[2]) {
|
||||
case 'A': /* Esc O 5 A == Ctrl-Up on Haiku. */
|
||||
return CONTROL_UP;
|
||||
case 'B': /* Esc O 5 B == Ctrl-Down on Haiku. */
|
||||
return CONTROL_DOWN;
|
||||
case 'C': /* Esc O 5 C == Ctrl-Right on Haiku. */
|
||||
return CONTROL_RIGHT;
|
||||
case 'D': /* Esc O 5 D == Ctrl-Left on Haiku. */
|
||||
return CONTROL_LEFT;
|
||||
}
|
||||
}
|
||||
case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
|
||||
case 'B': /* Esc O B == Down on VT100/VT320/xterm. */
|
||||
case 'C': /* Esc O C == Right on VT100/VT320/xterm. */
|
||||
@@ -941,6 +962,18 @@ int convert_sequence(const int *seq, size_t seq_len)
|
||||
}
|
||||
break;
|
||||
#ifndef NANO_TINY
|
||||
case '3':
|
||||
switch (seq[4]) {
|
||||
case 'A': /* Esc [ 1 ; 3 A == Alt-Up on xterm. */
|
||||
return ALT_UP;
|
||||
case 'B': /* Esc [ 1 ; 3 B == Alt-Down on xterm. */
|
||||
return ALT_DOWN;
|
||||
case 'C': /* Esc [ 1 ; 3 C == Alt-Right on xterm. */
|
||||
return ALT_RIGHT;
|
||||
case 'D': /* Esc [ 1 ; 3 D == Alt-Left on xterm. */
|
||||
return ALT_LEFT;
|
||||
}
|
||||
break;
|
||||
case '4':
|
||||
/* When the arrow keys are held together with Shift+Meta,
|
||||
* act as if they are Home/End/PgUp/PgDown with Shift. */
|
||||
@@ -1235,7 +1268,7 @@ int parse_escape_sequence(WINDOW *win, int kbinput)
|
||||
suppress_cursorpos = FALSE;
|
||||
lastmessage = HUSH;
|
||||
if (currmenu == MMAIN) {
|
||||
place_the_cursor(TRUE);
|
||||
place_the_cursor();
|
||||
curs_set(1);
|
||||
}
|
||||
}
|
||||
@@ -1638,9 +1671,7 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
|
||||
/* Adjust the index if we hit the last two wider ones. */
|
||||
if ((j > number) && (*mouse_x % i < COLS % i))
|
||||
j -= 2;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Calculated %i as index in shortcut list, currmenu = %x.\n", j, currmenu);
|
||||
#endif
|
||||
|
||||
/* Ignore releases/clicks of the first mouse button beyond
|
||||
* the last shortcut. */
|
||||
if (j > number)
|
||||
@@ -1658,9 +1689,6 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
|
||||
if (j == 0)
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Stopped on func %ld present in menus %x\n", (long)f->scfunc, f->menus);
|
||||
#endif
|
||||
|
||||
/* And put the corresponding key into the keyboard buffer. */
|
||||
if (f != NULL) {
|
||||
@@ -1688,12 +1716,10 @@ int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
|
||||
if (in_edit || (in_bottomwin && *mouse_y == 0)) {
|
||||
int i;
|
||||
|
||||
/* One upward roll of the mouse wheel is equivalent to
|
||||
* moving up three lines, and one downward roll of the mouse
|
||||
* wheel is equivalent to moving down three lines. */
|
||||
/* One roll of the mouse wheel should move three lines. */
|
||||
for (i = 0; i < 3; i++)
|
||||
unget_kbinput((mevent.bstate & BUTTON4_PRESSED) ?
|
||||
KEY_PPAGE : KEY_NPAGE, FALSE);
|
||||
KEY_UP : KEY_DOWN, FALSE);
|
||||
|
||||
return 1;
|
||||
} else
|
||||
@@ -1878,7 +1904,9 @@ char *display_string(const char *buf, size_t column, size_t span, bool isdata)
|
||||
} else if (*buf == '\t') {
|
||||
/* Show a tab as a visible character, or as as a space. */
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(WHITESPACE_DISPLAY)) {
|
||||
if (ISSET(WHITESPACE_DISPLAY) && (index > 0 || !isdata ||
|
||||
!ISSET(SOFTWRAP) || column % tabsize == 0 ||
|
||||
column == start_col)) {
|
||||
int i = 0;
|
||||
|
||||
while (i < whitespace_len[0])
|
||||
@@ -1888,7 +1916,7 @@ char *display_string(const char *buf, size_t column, size_t span, bool isdata)
|
||||
converted[index++] = ' ';
|
||||
column++;
|
||||
/* Fill the tab up with the required number of spaces. */
|
||||
while (column % tabsize != 0) {
|
||||
while (column % tabsize != 0 && column < beyond) {
|
||||
converted[index++] = ' ';
|
||||
column++;
|
||||
}
|
||||
@@ -2070,8 +2098,7 @@ void titlebar(const char *path)
|
||||
|
||||
wattroff(topwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
wnoutrefresh(topwin);
|
||||
doupdate();
|
||||
wrefresh(topwin);
|
||||
}
|
||||
|
||||
/* Display a normal message on the statusbar, quietly. */
|
||||
@@ -2162,9 +2189,12 @@ void statusline(message_type importance, const char *msg, ...)
|
||||
waddstr(bottomwin, " ]");
|
||||
wattroff(bottomwin, interface_color_pair[STATUS_BAR]);
|
||||
|
||||
/* Defeat a VTE/Konsole bug, where the cursor can go off-limits. */
|
||||
if (ISSET(CONSTANT_SHOW) && ISSET(NO_HELP))
|
||||
wmove(bottomwin, 0, 0);
|
||||
|
||||
/* Push the message to the screen straightaway. */
|
||||
wnoutrefresh(bottomwin);
|
||||
doupdate();
|
||||
wrefresh(bottomwin);
|
||||
|
||||
suppress_cursorpos = TRUE;
|
||||
|
||||
@@ -2210,40 +2240,25 @@ void bottombars(int menu)
|
||||
|
||||
blank_bottombars();
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "In bottombars, number of items == \"%d\"\n", (int) number);
|
||||
#endif
|
||||
|
||||
/* Display the first number of shortcuts in the given menu that
|
||||
* have a key combination assigned to them. */
|
||||
for (f = allfuncs, i = 0; i < number && f != NULL; f = f->next) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Checking menu items....");
|
||||
#endif
|
||||
if ((f->menus & menu) == 0)
|
||||
continue;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "found one! f->menus = %x, desc = \"%s\"\n", f->menus, f->desc);
|
||||
#endif
|
||||
s = first_sc_for(menu, f->scfunc);
|
||||
if (s == NULL) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Whoops, guess not, no shortcut key found for func!\n");
|
||||
#endif
|
||||
if (s == NULL)
|
||||
continue;
|
||||
}
|
||||
|
||||
wmove(bottomwin, 1 + i % 2, (i / 2) * itemwidth);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Calling onekey with keystr \"%s\" and desc \"%s\"\n", s->keystr, f->desc);
|
||||
#endif
|
||||
|
||||
onekey(s->keystr, _(f->desc), itemwidth + (COLS % itemwidth));
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Defeat a VTE bug by moving the cursor and forcing a screen update. */
|
||||
/* Defeat a VTE bug by homing the cursor and forcing a screen update. */
|
||||
wmove(bottomwin, 0, 0);
|
||||
wnoutrefresh(bottomwin);
|
||||
doupdate();
|
||||
wrefresh(bottomwin);
|
||||
}
|
||||
|
||||
/* Write a shortcut key to the help area at the bottom of the window.
|
||||
@@ -2271,7 +2286,7 @@ void onekey(const char *keystroke, const char *desc, int length)
|
||||
|
||||
/* Redetermine current_y from the position of current relative to edittop,
|
||||
* and put the cursor in the edit window at (current_y, "current_x"). */
|
||||
void place_the_cursor(bool forreal)
|
||||
void place_the_cursor(void)
|
||||
{
|
||||
ssize_t row = 0;
|
||||
size_t col, xpt = xplustabs();
|
||||
@@ -2279,24 +2294,19 @@ void place_the_cursor(bool forreal)
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
filestruct *line = openfile->edittop;
|
||||
size_t leftedge;
|
||||
|
||||
row -= (openfile->firstcolumn / editwincols);
|
||||
row -= chunk_for(openfile->firstcolumn, openfile->edittop);
|
||||
|
||||
/* Calculate how many rows the lines from edittop to current use. */
|
||||
while (line != NULL && line != openfile->current) {
|
||||
row += strlenpt(line->data) / editwincols + 1;
|
||||
row += number_of_chunks_in(line) + 1;
|
||||
line = line->next;
|
||||
}
|
||||
|
||||
/* Add the number of wraps in the current line before the cursor. */
|
||||
row += xpt / editwincols;
|
||||
col = xpt % editwincols;
|
||||
|
||||
/* If the cursor ought to be in column zero, nudge it there. */
|
||||
if (forreal && openfile->placewewant % editwincols == 0 && col != 0) {
|
||||
row++;
|
||||
col = 0;
|
||||
}
|
||||
row += get_chunk_and_edge(xpt, openfile->current, &leftedge);
|
||||
col = xpt - leftedge;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -2307,8 +2317,7 @@ void place_the_cursor(bool forreal)
|
||||
if (row < editwinrows)
|
||||
wmove(edit, row, margin + col);
|
||||
|
||||
if (forreal)
|
||||
openfile->current_y = row;
|
||||
openfile->current_y = row;
|
||||
}
|
||||
|
||||
/* edit_draw() takes care of the job of actually painting a line into
|
||||
@@ -2341,7 +2350,7 @@ void edit_draw(filestruct *fileptr, const char *converted,
|
||||
if (margin > 0) {
|
||||
wattron(edit, interface_color_pair[LINE_NUMBER]);
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP) && from_x != 0)
|
||||
if (ISSET(SOFTWRAP) && from_col != 0)
|
||||
mvwprintw(edit, row, 0, "%*s", margin - 1, " ");
|
||||
else
|
||||
#endif
|
||||
@@ -2383,6 +2392,12 @@ void edit_draw(filestruct *fileptr, const char *converted,
|
||||
/* The place in converted from where painting starts. */
|
||||
regmatch_t match;
|
||||
/* The match positions of a single-line regex. */
|
||||
const filestruct *start_line = fileptr->prev;
|
||||
/* The first line before fileptr that matches 'start'. */
|
||||
const filestruct *end_line = fileptr;
|
||||
/* The line that matches 'end'. */
|
||||
regmatch_t startmatch, endmatch;
|
||||
/* The match positions of the start and end regexes. */
|
||||
|
||||
/* Two notes about regexec(). A return value of zero means
|
||||
* that there is a match. Also, rm_eo is the first
|
||||
@@ -2438,12 +2453,6 @@ void edit_draw(filestruct *fileptr, const char *converted,
|
||||
}
|
||||
|
||||
/* Second case: varnish is a multiline expression. */
|
||||
const filestruct *start_line = fileptr->prev;
|
||||
/* The first line before fileptr that matches 'start'. */
|
||||
const filestruct *end_line = fileptr;
|
||||
/* The line that matches 'end'. */
|
||||
regmatch_t startmatch, endmatch;
|
||||
/* The match positions of the start and end regexes. */
|
||||
|
||||
/* Assume nothing gets painted until proven otherwise below. */
|
||||
fileptr->multidata[varnish->id] = CNONE;
|
||||
@@ -2655,9 +2664,9 @@ void edit_draw(filestruct *fileptr, const char *converted,
|
||||
paintlen = actual_x(thetext, end_col - start_col);
|
||||
}
|
||||
|
||||
wattron(edit, hilite_attribute);
|
||||
wattron(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
mvwaddnstr(edit, row, margin + start_col, thetext, paintlen);
|
||||
wattroff(edit, hilite_attribute);
|
||||
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
}
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
@@ -2730,19 +2739,19 @@ int update_softwrapped_line(filestruct *fileptr)
|
||||
/* The first row in the edit window that gets updated. */
|
||||
size_t from_col = 0;
|
||||
/* The starting column of the current chunk. */
|
||||
size_t to_col = 0;
|
||||
/* To which column a line is displayed. */
|
||||
char *converted;
|
||||
/* The data of the chunk with tabs and control characters expanded. */
|
||||
size_t full_length;
|
||||
/* The length of the expanded line. */
|
||||
|
||||
if (fileptr == openfile->edittop)
|
||||
from_col = openfile->firstcolumn;
|
||||
else
|
||||
row -= (openfile->firstcolumn / editwincols);
|
||||
row -= chunk_for(openfile->firstcolumn, openfile->edittop);
|
||||
|
||||
/* Find out on which screen row the target line should be shown. */
|
||||
while (line != fileptr && line != NULL) {
|
||||
row += (strlenpt(line->data) / editwincols) + 1;
|
||||
row += number_of_chunks_in(line) + 1;
|
||||
line = line->next;
|
||||
}
|
||||
|
||||
@@ -2753,18 +2762,30 @@ int update_softwrapped_line(filestruct *fileptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
full_length = strlenpt(fileptr->data);
|
||||
starting_row = row;
|
||||
|
||||
while (from_col <= full_length && row < editwinrows) {
|
||||
while (row < editwinrows) {
|
||||
bool end_of_line = FALSE;
|
||||
|
||||
to_col = get_softwrap_breakpoint(fileptr->data, from_col, &end_of_line);
|
||||
|
||||
blank_row(edit, row, 0, COLS);
|
||||
|
||||
/* Convert the chunk to its displayable form and draw it. */
|
||||
converted = display_string(fileptr->data, from_col, editwincols, TRUE);
|
||||
converted = display_string(fileptr->data, from_col, to_col - from_col, TRUE);
|
||||
edit_draw(fileptr, converted, row++, from_col);
|
||||
free(converted);
|
||||
|
||||
from_col += editwincols;
|
||||
if (end_of_line)
|
||||
break;
|
||||
|
||||
/* If the line is softwrapped before its last column, add a ">" just
|
||||
* after its softwrap breakpoint, unless we're softwrapping at blanks
|
||||
* and not in the middle of a word. */
|
||||
if (!ISSET(AT_BLANKS) && to_col - from_col < editwincols)
|
||||
mvwaddch(edit, row - 1, to_col - from_col, '>');
|
||||
|
||||
from_col = to_col;
|
||||
}
|
||||
|
||||
return (row - starting_row);
|
||||
@@ -2792,31 +2813,27 @@ int go_back_chunks(int nrows, filestruct **line, size_t *leftedge)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Don't move more chunks than the window can hold. */
|
||||
if (nrows > editwinrows - 1)
|
||||
nrows = (editwinrows < 2) ? 1 : editwinrows - 1;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
size_t current_chunk = (*leftedge) / editwincols;
|
||||
|
||||
/* Recede through the requested number of chunks. */
|
||||
for (i = nrows; i > 0; i--) {
|
||||
if (current_chunk > 0) {
|
||||
current_chunk--;
|
||||
continue;
|
||||
}
|
||||
size_t chunk = chunk_for(*leftedge, *line);
|
||||
|
||||
*leftedge = 0;
|
||||
|
||||
if (chunk >= i)
|
||||
return go_forward_chunks(chunk - i, line, leftedge);
|
||||
|
||||
if (*line == openfile->fileage)
|
||||
break;
|
||||
|
||||
i -= chunk;
|
||||
*line = (*line)->prev;
|
||||
current_chunk = strlenpt((*line)->data) / editwincols;
|
||||
*leftedge = HIGHEST_POSITIVE;
|
||||
}
|
||||
|
||||
/* Only change leftedge when we actually could move. */
|
||||
if (i < nrows)
|
||||
*leftedge = current_chunk * editwincols;
|
||||
if (*leftedge == HIGHEST_POSITIVE)
|
||||
*leftedge = leftedge_for(*leftedge, *line);
|
||||
} else
|
||||
#endif
|
||||
for (i = nrows; i > 0 && (*line)->prev != NULL; i--)
|
||||
@@ -2833,33 +2850,30 @@ int go_forward_chunks(int nrows, filestruct **line, size_t *leftedge)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Don't move more chunks than the window can hold. */
|
||||
if (nrows > editwinrows - 1)
|
||||
nrows = (editwinrows < 2) ? 1 : editwinrows - 1;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
size_t current_chunk = (*leftedge) / editwincols;
|
||||
size_t last_chunk = strlenpt((*line)->data) / editwincols;
|
||||
size_t current_leftedge = *leftedge;
|
||||
|
||||
/* Advance through the requested number of chunks. */
|
||||
for (i = nrows; i > 0; i--) {
|
||||
if (current_chunk < last_chunk) {
|
||||
current_chunk++;
|
||||
bool end_of_line = FALSE;
|
||||
|
||||
current_leftedge = get_softwrap_breakpoint((*line)->data,
|
||||
current_leftedge, &end_of_line);
|
||||
|
||||
if (!end_of_line)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*line == openfile->filebot)
|
||||
break;
|
||||
|
||||
*line = (*line)->next;
|
||||
current_chunk = 0;
|
||||
last_chunk = strlenpt((*line)->data) / editwincols;
|
||||
current_leftedge = 0;
|
||||
}
|
||||
|
||||
/* Only change leftedge when we actually could move. */
|
||||
if (i < nrows)
|
||||
*leftedge = current_chunk * editwincols;
|
||||
*leftedge = current_leftedge;
|
||||
} else
|
||||
#endif
|
||||
for (i = nrows; i > 0 && (*line)->next != NULL; i--)
|
||||
@@ -2876,7 +2890,7 @@ bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge)
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
filestruct *line = openfile->current;
|
||||
size_t leftedge = (xplustabs() / editwincols) * editwincols;
|
||||
size_t leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
int rows_left = go_back_chunks(editwinrows - 1, &line, &leftedge);
|
||||
|
||||
return (rows_left > 0 || line->lineno < was_lineno ||
|
||||
@@ -2941,12 +2955,14 @@ void edit_scroll(scroll_dir direction, int nrows)
|
||||
go_forward_chunks(editwinrows - nrows, &line, &leftedge);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Compensate for the earlier chunks of a softwrapped line. */
|
||||
nrows += leftedge / editwincols;
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
/* Compensate for the earlier chunks of a softwrapped line. */
|
||||
nrows += chunk_for(leftedge, line);
|
||||
|
||||
/* Don't compensate for the chunks that are offscreen. */
|
||||
if (line == openfile->edittop)
|
||||
nrows -= openfile->firstcolumn / editwincols;
|
||||
/* Don't compensate for the chunks that are offscreen. */
|
||||
if (line == openfile->edittop)
|
||||
nrows -= chunk_for(openfile->firstcolumn, line);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Draw new content on the blank rows inside the scrolled region
|
||||
@@ -2959,19 +2975,174 @@ void edit_scroll(scroll_dir direction, int nrows)
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Get the column number after leftedge where we can break the given text, and
|
||||
* return it. This will always be editwincols or less after leftedge. Set
|
||||
* end_of_line to TRUE if we reach the end of the line while searching the
|
||||
* text. Assume leftedge is the leftmost column of a softwrapped chunk. */
|
||||
size_t get_softwrap_breakpoint(const char *text, size_t leftedge,
|
||||
bool *end_of_line)
|
||||
{
|
||||
size_t index = 0;
|
||||
/* Current index in text. */
|
||||
size_t column = 0;
|
||||
/* Current column position in text. */
|
||||
size_t prev_column = 0;
|
||||
/* Previous column position in text. */
|
||||
size_t goal_column;
|
||||
/* Column of the last character where we can break the text. */
|
||||
bool found_blank = FALSE;
|
||||
/* Did we find at least one blank? */
|
||||
size_t lastblank_index = 0;
|
||||
/* Current index of the last blank in text. */
|
||||
size_t lastblank_column = 0;
|
||||
/* Current column position of the last blank in text. */
|
||||
int char_len = 0;
|
||||
/* Length of current character, in bytes. */
|
||||
|
||||
while (*text != '\0' && column < leftedge) {
|
||||
char_len = parse_mbchar(text, NULL, &column);
|
||||
text += char_len;
|
||||
}
|
||||
|
||||
/* The intention is to use the entire available width. */
|
||||
goal_column = leftedge + editwincols;
|
||||
|
||||
while (*text != '\0' && column <= goal_column) {
|
||||
/* When breaking at blanks, do it *before* the target column. */
|
||||
if (ISSET(AT_BLANKS) && is_blank_mbchar(text) && column < goal_column) {
|
||||
found_blank = TRUE;
|
||||
lastblank_index = index;
|
||||
lastblank_column = column;
|
||||
}
|
||||
|
||||
prev_column = column;
|
||||
char_len = parse_mbchar(text, NULL, &column);
|
||||
text += char_len;
|
||||
index += char_len;
|
||||
}
|
||||
|
||||
/* If we didn't overshoot the target, we've found a breaking point. */
|
||||
if (column <= goal_column) {
|
||||
/* We've reached EOL if we didn't even reach the target. */
|
||||
*end_of_line = (column < goal_column);
|
||||
return column;
|
||||
}
|
||||
|
||||
/* If we're softwrapping at blanks and we found at least one blank, move
|
||||
* the pointer back to the last blank, step beyond it, and we're done. */
|
||||
if (found_blank) {
|
||||
text = text - index + lastblank_index;
|
||||
parse_mbchar(text, NULL, &lastblank_column);
|
||||
|
||||
/* If we've now overshot the screen's edge, then break there. */
|
||||
if (lastblank_column > goal_column)
|
||||
return goal_column;
|
||||
|
||||
return lastblank_column;
|
||||
}
|
||||
|
||||
/* If a tab is split over two chunks, break at the screen's edge. */
|
||||
if (*(text - char_len) == '\t')
|
||||
prev_column = goal_column;
|
||||
|
||||
/* Otherwise, return the column of the last character that doesn't
|
||||
* overshoot the target, since we can't break the text anywhere else. */
|
||||
return (editwincols > 1) ? prev_column : column - 1;
|
||||
}
|
||||
|
||||
/* Get the row of the softwrapped chunk of the given line that column is on,
|
||||
* relative to the first row (zero-based), and return it. If leftedge isn't
|
||||
* NULL, return the leftmost column of the chunk in it. */
|
||||
size_t get_chunk_and_edge(size_t column, filestruct *line, size_t *leftedge)
|
||||
{
|
||||
size_t current_chunk = 0, start_col = 0, end_col;
|
||||
bool end_of_line = FALSE;
|
||||
|
||||
while (TRUE) {
|
||||
end_col = get_softwrap_breakpoint(line->data, start_col, &end_of_line);
|
||||
|
||||
/* We reached the end of the line and/or found column, so get out. */
|
||||
if (end_of_line || (column >= start_col && column < end_col)) {
|
||||
if (leftedge != NULL)
|
||||
*leftedge = start_col;
|
||||
return current_chunk;
|
||||
}
|
||||
|
||||
current_chunk++;
|
||||
start_col = end_col;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the row of the softwrapped chunk of the given line that column is on,
|
||||
* relative to the first row (zero-based). */
|
||||
size_t chunk_for(size_t column, filestruct *line)
|
||||
{
|
||||
if (ISSET(SOFTWRAP))
|
||||
return get_chunk_and_edge(column, line, NULL);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the leftmost column of the softwrapped chunk of the given line that
|
||||
* column is on. */
|
||||
size_t leftedge_for(size_t column, filestruct *line)
|
||||
{
|
||||
size_t leftedge;
|
||||
|
||||
if (!ISSET(SOFTWRAP))
|
||||
return 0;
|
||||
|
||||
get_chunk_and_edge(column, line, &leftedge);
|
||||
|
||||
return leftedge;
|
||||
}
|
||||
|
||||
/* Return the row of the last softwrapped chunk of the given line, relative to
|
||||
* the first row (zero-based). */
|
||||
size_t number_of_chunks_in(filestruct *line)
|
||||
{
|
||||
return chunk_for((size_t)-1, line);
|
||||
}
|
||||
|
||||
/* Ensure that firstcolumn is at the starting column of the softwrapped chunk
|
||||
* it's on. We need to do this when the number of columns of the edit window
|
||||
* has changed, because then the width of softwrapped chunks has changed. */
|
||||
void ensure_firstcolumn_is_aligned(void)
|
||||
{
|
||||
if (openfile->firstcolumn % editwincols != 0)
|
||||
openfile->firstcolumn -= (openfile->firstcolumn % editwincols);
|
||||
openfile->firstcolumn = leftedge_for(openfile->firstcolumn,
|
||||
openfile->edittop);
|
||||
|
||||
/* If smooth scrolling is on, make sure the viewport doesn't center. */
|
||||
focusing = FALSE;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* When in softwrap mode, and the given column is on or after the breakpoint of
|
||||
* a softwrapped chunk, shift it back to the last column before the breakpoint.
|
||||
* The given column is relative to the given leftedge in current. The returned
|
||||
* column is relative to the start of the text. */
|
||||
size_t actual_last_column(size_t leftedge, size_t column)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
bool last_chunk;
|
||||
size_t end_col = get_softwrap_breakpoint(openfile->current->data,
|
||||
leftedge, &last_chunk) - leftedge;
|
||||
|
||||
/* If we're not on the last chunk, we're one column past the end of
|
||||
* the row. Shifting back one column might put us in the middle of
|
||||
* a multi-column character, but actual_x() will fix that later. */
|
||||
if (!last_chunk)
|
||||
end_col--;
|
||||
|
||||
if (column > end_col)
|
||||
column = end_col;
|
||||
}
|
||||
#endif
|
||||
|
||||
return leftedge + column;
|
||||
}
|
||||
|
||||
/* Return TRUE if current[current_x] is above the top of the screen, and FALSE
|
||||
* otherwise. */
|
||||
bool current_is_above_screen(void)
|
||||
@@ -3002,7 +3173,8 @@ bool current_is_below_screen(void)
|
||||
return (go_forward_chunks(editwinrows - 1, &line, &leftedge) == 0 &&
|
||||
(line->lineno < openfile->current->lineno ||
|
||||
(line->lineno == openfile->current->lineno &&
|
||||
leftedge < (xplustabs() / editwincols) * editwincols)));
|
||||
leftedge < leftedge_for(xplustabs(),
|
||||
openfile->current))));
|
||||
} else
|
||||
#endif
|
||||
return (openfile->current->lineno >=
|
||||
@@ -3018,7 +3190,7 @@ bool current_is_offscreen(void)
|
||||
|
||||
/* Update any lines between old_current and current that need to be
|
||||
* updated. Use this if we've moved without changing any text. */
|
||||
void edit_redraw(filestruct *old_current)
|
||||
void edit_redraw(filestruct *old_current, update_type manner)
|
||||
{
|
||||
size_t was_pww = openfile->placewewant;
|
||||
|
||||
@@ -3026,7 +3198,7 @@ void edit_redraw(filestruct *old_current)
|
||||
|
||||
/* If the current line is offscreen, scroll until it's onscreen. */
|
||||
if (current_is_offscreen()) {
|
||||
adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : FLOWING);
|
||||
adjust_viewport(ISSET(SMOOTH_SCROLL) ? manner : CENTERING);
|
||||
refresh_needed = TRUE;
|
||||
return;
|
||||
}
|
||||
@@ -3071,17 +3243,8 @@ void edit_refresh(void)
|
||||
#endif
|
||||
|
||||
/* If the current line is out of view, get it back on screen. */
|
||||
if (current_is_offscreen()) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "edit-refresh: line = %ld, edittop = %ld and editwinrows = %d\n",
|
||||
(long)openfile->current->lineno, (long)openfile->edittop->lineno, editwinrows);
|
||||
#endif
|
||||
adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : STATIONARY);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "edit-refresh: now edittop = %ld\n", (long)openfile->edittop->lineno);
|
||||
#endif
|
||||
if (current_is_offscreen())
|
||||
adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : FLOWING);
|
||||
|
||||
line = openfile->edittop;
|
||||
|
||||
@@ -3096,7 +3259,7 @@ void edit_refresh(void)
|
||||
while (row < editwinrows)
|
||||
blank_row(edit, row++, 0, COLS);
|
||||
|
||||
place_the_cursor(TRUE);
|
||||
place_the_cursor();
|
||||
wnoutrefresh(edit);
|
||||
|
||||
refresh_needed = FALSE;
|
||||
@@ -3121,15 +3284,11 @@ void adjust_viewport(update_type manner)
|
||||
openfile->edittop = openfile->current;
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP))
|
||||
openfile->firstcolumn = (xplustabs() / editwincols) * editwincols;
|
||||
openfile->firstcolumn = leftedge_for(xplustabs(), openfile->current);
|
||||
#endif
|
||||
|
||||
/* Move edittop back goal rows, starting at current[current_x]. */
|
||||
go_back_chunks(goal, &openfile->edittop, &openfile->firstcolumn);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "adjust_viewport(): setting edittop to lineno %ld\n", (long)openfile->edittop->lineno);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Unconditionally redraw the entire screen. */
|
||||
@@ -3145,17 +3304,19 @@ void total_redraw(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Unconditionally redraw the entire screen, and then refresh it using
|
||||
* the current file. */
|
||||
/* Redraw the entire screen, then refresh the title bar and the content of
|
||||
* the edit window (when not in the file browser), and the bottom bars. */
|
||||
void total_refresh(void)
|
||||
{
|
||||
total_redraw();
|
||||
titlebar(title);
|
||||
if (currmenu != MBROWSER && currmenu != MWHEREISFILE && currmenu != MGOTODIR)
|
||||
titlebar(title);
|
||||
#ifdef ENABLE_HELP
|
||||
if (inhelp)
|
||||
wrap_the_help_text(TRUE);
|
||||
else
|
||||
#endif
|
||||
if (currmenu != MBROWSER && currmenu != MWHEREISFILE && currmenu != MGOTODIR)
|
||||
edit_refresh();
|
||||
bottombars(currmenu);
|
||||
}
|
||||
@@ -3185,7 +3346,14 @@ void do_cursorpos(bool force)
|
||||
size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
|
||||
int linepct, colpct, charpct;
|
||||
|
||||
assert(openfile->fileage != NULL && openfile->current != NULL);
|
||||
/* If the showing needs to be suppressed, don't suppress it next time. */
|
||||
if (suppress_cursorpos && !force) {
|
||||
suppress_cursorpos = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Hide the cursor while we are calculating. */
|
||||
curs_set(0);
|
||||
|
||||
/* Determine the size of the file up to the cursor. */
|
||||
saved_byte = openfile->current->data[openfile->current_x];
|
||||
@@ -3199,12 +3367,6 @@ void do_cursorpos(bool force)
|
||||
if (openfile->current != openfile->filebot)
|
||||
sum--;
|
||||
|
||||
/* If the showing needs to be suppressed, don't suppress it next time. */
|
||||
if (suppress_cursorpos && !force) {
|
||||
suppress_cursorpos = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Display the current cursor position on the statusbar. */
|
||||
linepct = 100 * openfile->current->lineno / openfile->filebot->lineno;
|
||||
colpct = 100 * cur_xpt / cur_lenpt;
|
||||
@@ -3227,54 +3389,121 @@ void do_cursorpos_void(void)
|
||||
do_cursorpos(TRUE);
|
||||
}
|
||||
|
||||
void enable_nodelay(void)
|
||||
void disable_waiting(void)
|
||||
{
|
||||
nodelay_mode = TRUE;
|
||||
waiting_mode = FALSE;
|
||||
nodelay(edit, TRUE);
|
||||
}
|
||||
|
||||
void disable_nodelay(void)
|
||||
void enable_waiting(void)
|
||||
{
|
||||
nodelay_mode = FALSE;
|
||||
waiting_mode = TRUE;
|
||||
nodelay(edit, FALSE);
|
||||
}
|
||||
|
||||
/* Highlight the current word being replaced or spell checked. We
|
||||
* expect word to have tabs and control characters expanded. */
|
||||
void spotlight(bool active, const char *word)
|
||||
/* Highlight the text between from_col and to_col when active is TRUE.
|
||||
* Remove the highlight when active is FALSE. */
|
||||
void spotlight(bool active, size_t from_col, size_t to_col)
|
||||
{
|
||||
size_t word_span = strlenpt(word);
|
||||
size_t room = word_span;
|
||||
char *word;
|
||||
size_t word_span, room;
|
||||
|
||||
/* Compute the number of columns that are available for the word. */
|
||||
if (!ISSET(SOFTWRAP)) {
|
||||
room = editwincols + get_page_start(xplustabs()) - xplustabs();
|
||||
place_the_cursor();
|
||||
|
||||
/* If the word is partially offscreen, reserve space for the "$". */
|
||||
if (word_span > room)
|
||||
room--;
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
spotlight_softwrapped(active, from_col, to_col);
|
||||
return;
|
||||
}
|
||||
|
||||
place_the_cursor(FALSE);
|
||||
|
||||
if (active)
|
||||
wattron(edit, hilite_attribute);
|
||||
#endif
|
||||
|
||||
/* This is so we can show zero-length matches. */
|
||||
if (word_span == 0)
|
||||
waddch(edit, ' ');
|
||||
else
|
||||
waddnstr(edit, word, actual_x(word, room));
|
||||
if (to_col == from_col) {
|
||||
word = mallocstrcpy(NULL, " ");
|
||||
to_col++;
|
||||
} else
|
||||
word = display_string(openfile->current->data, from_col,
|
||||
to_col - from_col, FALSE);
|
||||
|
||||
word_span = strlenpt(word);
|
||||
|
||||
/* Compute the number of columns that are available for the word. */
|
||||
room = editwincols + get_page_start(from_col) - from_col;
|
||||
|
||||
/* If the word is partially offscreen, reserve space for the "$". */
|
||||
if (word_span > room)
|
||||
room--;
|
||||
|
||||
if (active)
|
||||
wattron(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
waddnstr(edit, word, actual_x(word, room));
|
||||
|
||||
if (word_span > room)
|
||||
waddch(edit, '$');
|
||||
|
||||
if (active)
|
||||
wattroff(edit, hilite_attribute);
|
||||
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
free(word);
|
||||
|
||||
wnoutrefresh(edit);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Highlight the text between from_col and to_col when active is TRUE; remove
|
||||
* the highlight when active is FALSE. This will not highlight softwrapped
|
||||
* line breaks, since they're not actually part of the spotlighted text. */
|
||||
void spotlight_softwrapped(bool active, size_t from_col, size_t to_col)
|
||||
{
|
||||
ssize_t row = openfile->current_y;
|
||||
size_t leftedge = leftedge_for(from_col, openfile->current);
|
||||
size_t break_col;
|
||||
bool end_of_line = FALSE;
|
||||
char *word;
|
||||
|
||||
while (row < editwinrows) {
|
||||
break_col = get_softwrap_breakpoint(openfile->current->data,
|
||||
leftedge, &end_of_line);
|
||||
|
||||
/* Stop after the end of the word, by pretending the end of the word is
|
||||
* the end of the line. */
|
||||
if (break_col >= to_col) {
|
||||
end_of_line = TRUE;
|
||||
break_col = to_col;
|
||||
}
|
||||
|
||||
/* This is so we can show zero-length matches. */
|
||||
if (break_col == from_col) {
|
||||
word = mallocstrcpy(NULL, " ");
|
||||
break_col++;
|
||||
} else
|
||||
word = display_string(openfile->current->data, from_col,
|
||||
break_col - from_col, FALSE);
|
||||
|
||||
if (active)
|
||||
wattron(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
waddnstr(edit, word, actual_x(word, break_col));
|
||||
|
||||
if (active)
|
||||
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
free(word);
|
||||
|
||||
if (end_of_line)
|
||||
break;
|
||||
|
||||
wmove(edit, ++row, 0);
|
||||
|
||||
leftedge = break_col;
|
||||
from_col = break_col;
|
||||
}
|
||||
|
||||
wnoutrefresh(edit);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_EXTRA
|
||||
#define CREDIT_LEN 54
|
||||
#define XLCREDIT_LEN 9
|
||||
|
||||
@@ -4,7 +4,11 @@ syntax "c" "\.(c(c|pp|xx|\+\+)?|C)$" "\.(h(h|pp|xx)?|H)$" "\.ii?$"
|
||||
magic "(ASCII|UTF-8 Unicode) C(\+\+)? program text"
|
||||
comment "//"
|
||||
|
||||
# Constants.
|
||||
color brightred "\<[A-Z_][0-9A-Z_]+\>"
|
||||
# Labels.
|
||||
color brightmagenta "^[[:space:]]*[A-Z_a-z]+:[[:space:]]*$"
|
||||
|
||||
color green "\<(float|double|bool|char|int|short|long|sizeof|enum|void|auto|static|const|struct|union|typedef|extern|(un)?signed|inline)\>"
|
||||
color green "\<((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\>"
|
||||
color green "\<(class|namespace|template|public|protected|private|typename|this|friend|virtual|override|using|mutable|volatile|register|explicit)\>"
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
## A default syntax, which is used
|
||||
## for files that do not match any other syntax.
|
||||
## An example of a default syntax. The default syntax is used for
|
||||
## files that do not match any other syntax.
|
||||
|
||||
syntax "default"
|
||||
comment "#"
|
||||
|
||||
# Comments.
|
||||
color cyan "^[[:space:]]*#.*"
|
||||
|
||||
# Spaces in front of tabs.
|
||||
color ,red " + +"
|
||||
|
||||
# Nano's name, including version.
|
||||
color brightred "(GNU )?nano [1-9]\.[0-9]\.[^[:space:][:punct:]]+"
|
||||
|
||||
# Email addresses.
|
||||
color yellow "<[[:alnum:].%_+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}>"
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
## Here is an example for Gentoo ebuilds/eclasses.
|
||||
## Here is an example for Gentoo ebuilds/eclasses,
|
||||
## and (further down) one for Portage control files.
|
||||
|
||||
syntax "ebuild" "\.e(build|class|blit)$"
|
||||
comment "#"
|
||||
|
||||
## All the standard portage functions
|
||||
## All the standard portage functions:
|
||||
color brightgreen "(^|\<default_)src_(unpack|prepare|configure|compile|install|test)\>"
|
||||
color brightgreen "^pkg_(config|nofetch|info|pretend|setup|(pre|post)(inst|rm))\>"
|
||||
color brightgreen "\<default(_pkg_nofetch|_src_(unpack|prepare|configure|compile|test))?\>"
|
||||
## Highlight bash related syntax
|
||||
## Bash-related syntax:
|
||||
color green "\<(break|case|continue|do|done|elif|else|esac|exit|fi|for|function|if|in|read|return|select|shift|then|time|until|while)\>"
|
||||
color green "\<(declare|eval|exec|export|let|local)\>"
|
||||
color green "[{}():;|`$<>!=&\\]" "(\]|\[)"
|
||||
color green "-[defhnrsuwxzL]\>"
|
||||
color green "-(eq|ne|gt|lt|ge|le)\>"
|
||||
## Highlight variables ... official portage ones in red, all others in bright red
|
||||
## Variables... official portage ones in red, all others in bright red:
|
||||
color brightred "\$[-0-9@*#?$!]" "\$[[:alpha:]_][[:alnum:]_]*"
|
||||
color brightred "\$\{[#!]?([-@*#?$!]|[0-9]+|[[:alpha:]_][[:alnum:]_]*)(\[([[:digit:]]|@)+\])?(([#%/]|:?[-=?+])[^}]*\}|\[|\})"
|
||||
color red "\<(EAPI|ARCH|HOMEPAGE|DESCRIPTION|IUSE|SRC_URI|LICENSE|SLOT|KEYWORDS|[HPR]?DEPEND|PROVIDE|PROPERTIES|REQUIRED_USE|RESTRICT|USERLAND)\>"
|
||||
@@ -22,7 +23,7 @@ color red "\<(AS|C(PP|XX)?|LD)FLAGS\>" "\<C(HOST|TARGET|BUILD)\>" "\<(MERGE_TYPE
|
||||
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\>"
|
||||
## Highlight portage commands
|
||||
## Portage commands:
|
||||
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)\>"
|
||||
@@ -35,20 +36,21 @@ color brightblue "\<prepall(docs|info|man|strip)?\>" "\<prep(info|lib|lib\.(so|a
|
||||
color brightblue "\<(doc|ins|exe)?into\>" "\<(f|games)(owners|perms)\>" "\<(exe|ins|dir)opts\>"
|
||||
color brightblue "\<tc-get(BUILD_)?(AR|AS|CC|CPP|CXX|LD|NM|OBJCOPY|PKG_CONFIG|RANLIB)\>"
|
||||
color brightblue "\<tc-(arch(-kernel)?|export|has-(tls|openmp))\>"
|
||||
## Highlight common commands used in ebuilds
|
||||
## Common commands used in ebuilds:
|
||||
color blue "\<(awk|cat|cd|chmod|chown|cp|echo|env|find|e?grep|ln|make|mkdir|mv|popd|printf|pushd|rm|rmdir|sed|set|tar|touch|unset|xargs)\>"
|
||||
## Highlight comments (doesnt work that well)
|
||||
## Comments (doesn't work that well):
|
||||
color yellow "(^|[[:space:]])#.*$"
|
||||
## Highlight strings (doesnt work that well)
|
||||
## Strings (doesn't work that well):
|
||||
color brightyellow ""(\\.|[^\"])*"" "'(\\.|[^'])*'"
|
||||
## Trailing space is bad!
|
||||
color ,green "[[:space:]]+$"
|
||||
## Mixed whitespace is also bad.
|
||||
color ,green " "
|
||||
|
||||
## Here is an example for Portage control files.
|
||||
##
|
||||
|
||||
syntax "/etc/portage" "\.(accept_keywords|env|keywords|mask|unmask|use)(/.+)?$"
|
||||
comment "#"
|
||||
|
||||
## Base text:
|
||||
color green "^.+$"
|
||||
## Likely version and slot numbers:
|
||||
|
||||
@@ -5,7 +5,7 @@ magic "HTML document text"
|
||||
comment "<!--|-->"
|
||||
|
||||
# Tags:
|
||||
color cyan start="<[[:alpha:]/!?]" end=">"
|
||||
color cyan "<[[:alpha:]/!?][^>]*>"
|
||||
# Bold, italic, and underlined:
|
||||
color brightmagenta "</?[biu]>"
|
||||
|
||||
|
||||
@@ -4,15 +4,16 @@ syntax "nanorc" "\.?nanorc$"
|
||||
comment "#"
|
||||
|
||||
# Possible errors and parameters
|
||||
icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|comment|magic|linter|i?color|extendsyntax).*$"
|
||||
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|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cut|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:]]+[[:digit:]]+|tabstospaces|tempfile|unix|view|wordbounds)\>"
|
||||
icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>" "[[:space:]]+[[:digit:]]+$"
|
||||
icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+"
|
||||
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|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:]]*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 green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|extendsyntax)\>"
|
||||
|
||||
# Colors
|
||||
|
||||
@@ -13,10 +13,10 @@ color white "\<[a-z_]*\("
|
||||
color cyan "\$[a-z_]+"
|
||||
|
||||
# Types.
|
||||
color green "\<(array|bool|callable|const|float|global|int|object|static|string|var)\>"
|
||||
color green "\<(array|bool|callable|const|float|global|int|object|string|var)\>"
|
||||
|
||||
# Directives and structure.
|
||||
color brightyellow "\<(abstract|as|class|clone|declare|enddeclare|extends|function|implements|include(_once)?|inst(ance|ead)of|interface|namespace|new|private|protected|public|require(_once)?|trait|use|yield)\>"
|
||||
color brightyellow "\<(abstract|as|class|clone|(end)?declare|extends|function|implements|include(_once)?|inst(ance|ead)of|interface|namespace|new|private|protected|public|require(_once)?|static|trait|use|yield)\>"
|
||||
color brightyellow "\<(case|catch|default|do|echo|else(if)?|end(for(each)?|if|switch|while)|final(ly)?|for(each)?|if|print|switch|throw|try|while)\>"
|
||||
# Operators.
|
||||
color brightyellow "\<(and|or|xor)\>"
|
||||
|
||||
@@ -17,8 +17,8 @@ color brightgreen ""([^"\]|\\.)+""
|
||||
# Comments.
|
||||
color brightred "(^|[[:blank:]])#.*$"
|
||||
# Triple-quoted strings.
|
||||
color brightgreen start="'''[^'),]" end="(^|[^(\])'''"
|
||||
color brightgreen start="\"\"\"[^"),]" end="(^|[^(\])\"\"\""
|
||||
color brightgreen start="'''([^'),]|$)" end="(^|[^(\])'''"
|
||||
color brightgreen start="\"\"\"([^"),]|$)" end="(^|[^(\])\"\"\""
|
||||
|
||||
# Reminders.
|
||||
color ,yellow "(FIXME|TODO|XXX)"
|
||||
|
||||
@@ -7,9 +7,9 @@ comment "@c "
|
||||
|
||||
# Command arguments, trailing and enclosed.
|
||||
color cyan "^@[a-z]+[[:space:]]+.*$"
|
||||
color brightmagenta "@[a-z]+\{[^}]*\}"
|
||||
color brightmagenta "@[a-zA-Z]+\{[^}]*\}"
|
||||
# Commands themselves.
|
||||
color yellow "@[a-z]+\{?" "\}"
|
||||
color yellow "@[a-zA-Z]+\{?" "\}"
|
||||
|
||||
# Menu items.
|
||||
color brightred "^\*[[:space:]]+.*::.*$"
|
||||
|
||||
Reference in New Issue
Block a user