Compare commits
236 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d646a3b97b | ||
|
|
800a997008 | ||
|
|
c17a8a9836 | ||
|
|
20aa167c14 | ||
|
|
0c9905dbd0 | ||
|
|
73c7f1cbdc | ||
|
|
4200ed3003 | ||
|
|
2b314ed18f | ||
|
|
88a0bb9685 | ||
|
|
1e718cec35 | ||
|
|
5487551ce9 | ||
|
|
763bf2ed26 | ||
|
|
cf63a2910a | ||
|
|
7c3c942097 | ||
|
|
77d24300f3 | ||
|
|
d33b5f3dab | ||
|
|
c24e95e3d6 | ||
|
|
c42489d946 | ||
|
|
2b438e6ef4 | ||
|
|
8165b20fc1 | ||
|
|
bacb0f717d | ||
|
|
11a3bc484c | ||
|
|
0465adb9ce | ||
|
|
7ea13d4269 | ||
|
|
06049f5141 | ||
|
|
4220854367 | ||
|
|
f6e83438da | ||
|
|
169da09424 | ||
|
|
e6a92b1406 | ||
|
|
ab14df074f | ||
|
|
5198c1f139 | ||
|
|
1e292141f3 | ||
|
|
8649c78e1e | ||
|
|
5239e7c52b | ||
|
|
f6b6e6c3ff | ||
|
|
0c2b54a276 | ||
|
|
a7f5907b43 | ||
|
|
dfcb1268ca | ||
|
|
2122a1a2b5 | ||
|
|
e2d3bba86c | ||
|
|
4567360d01 | ||
|
|
478e34a80c | ||
|
|
ea47879911 | ||
|
|
bfc53f308c | ||
|
|
f0d3685591 | ||
|
|
7e6bb91593 | ||
|
|
7b133aa6f9 | ||
|
|
477b246771 | ||
|
|
7d653e5a17 | ||
|
|
c16e79b612 | ||
|
|
1463781247 | ||
|
|
c3a11fb7ed | ||
|
|
953c2b8e79 | ||
|
|
d054044d30 | ||
|
|
9dc72cf3ba | ||
|
|
d5ac1ed395 | ||
|
|
2a4fc9591f | ||
|
|
f034992ed6 | ||
|
|
db0b849f9b | ||
|
|
c4d2a92d4c | ||
|
|
4e03a245ac | ||
|
|
028d12f4fb | ||
|
|
a5974bd1ec | ||
|
|
87da3ecbe0 | ||
|
|
ff35a61355 | ||
|
|
3f27c312c4 | ||
|
|
ab6e4e36e2 | ||
|
|
84c650b80a | ||
|
|
42497f77e2 | ||
|
|
86ef9db363 | ||
|
|
160ababa55 | ||
|
|
d84fb8d209 | ||
|
|
14bf53ddfc | ||
|
|
ded02d858f | ||
|
|
d4945c67a4 | ||
|
|
ddd300af5f | ||
|
|
d344c3d042 | ||
|
|
3018ab4706 | ||
|
|
2356693b81 | ||
|
|
4d35835189 | ||
|
|
f8c75c43ed | ||
|
|
af20d45bc1 | ||
|
|
08b49534d5 | ||
|
|
57899550aa | ||
|
|
e1e6c5f612 | ||
|
|
58ecc034d0 | ||
|
|
501d05c5d1 | ||
|
|
fc36ff7275 | ||
|
|
3f735d22a1 | ||
|
|
ba65cd48cc | ||
|
|
c7eecd74de | ||
|
|
a7fa174438 | ||
|
|
217cfbf362 | ||
|
|
80ed2568fc | ||
|
|
7a3a45e6ac | ||
|
|
4436815725 | ||
|
|
d0119833c1 | ||
|
|
d4074ca85b | ||
|
|
ca8317e820 | ||
|
|
1bd17c44b0 | ||
|
|
762fb4bec5 | ||
|
|
a2b4f00a27 | ||
|
|
15738c6b39 | ||
|
|
ede44e16ff | ||
|
|
c8a2f36e87 | ||
|
|
f2f7498f12 | ||
|
|
762f997244 | ||
|
|
504a97256b | ||
|
|
3f35e9670f | ||
|
|
b5346bccb3 | ||
|
|
7c3c3cbb3b | ||
|
|
b27ab4f0a1 | ||
|
|
c74d2632bb | ||
|
|
ae34825f58 | ||
|
|
f6b396f206 | ||
|
|
5561d22f19 | ||
|
|
aa45994bbb | ||
|
|
2d13afda40 | ||
|
|
fd86696658 | ||
|
|
09ab91c79c | ||
|
|
5f4fb8e513 | ||
|
|
7a9d010186 | ||
|
|
231fe4bf01 | ||
|
|
067a920517 | ||
|
|
36e88032cb | ||
|
|
e0a73f58f3 | ||
|
|
1be8eb3b30 | ||
|
|
fb9c180bae | ||
|
|
c10a1e54dc | ||
|
|
a1c73317f7 | ||
|
|
a75bf0a1d1 | ||
|
|
5f70229c7e | ||
|
|
c8363a0d0b | ||
|
|
4aec1649f5 | ||
|
|
153dea1732 | ||
|
|
bb8d65e89c | ||
|
|
f9bf320fd5 | ||
|
|
9738c7997b | ||
|
|
cbf4f77d6b | ||
|
|
3fc89e0853 | ||
|
|
ac8eb42a4f | ||
|
|
6c2c6b58a4 | ||
|
|
19a1129698 | ||
|
|
f722c53223 | ||
|
|
ffc550521c | ||
|
|
8d229cb712 | ||
|
|
abf7ac48a1 | ||
|
|
fc0e16f6bc | ||
|
|
57d7f8852d | ||
|
|
ae25e15d61 | ||
|
|
21ffa883f7 | ||
|
|
98ec41b4fa | ||
|
|
a4a32b910a | ||
|
|
28cfab7580 | ||
|
|
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 |
267
ChangeLog
267
ChangeLog
@@ -1,3 +1,270 @@
|
||||
Changes between v2.9.0 and v2.9.1:
|
||||
----------------------------------
|
||||
|
||||
Benno Schulenberg (20):
|
||||
build: fix compilation with --disable-browser --disable-tabcomp
|
||||
bump version numbers and add a news item for the 2.9.1 release
|
||||
files: always update the stat info when the entire file is written
|
||||
files: save the marked region only when we've prompted for a file name
|
||||
gnulib: update to its current upstream state
|
||||
history: create the path '~/.local/share/' when it is needed
|
||||
history: make nano's state directory accessible for the user only
|
||||
history: save the positions file also when a record was deleted
|
||||
input: make the macro key discoverable by giving feedback when undefined
|
||||
linting: switch the mark off when the linter starts
|
||||
selecting: do not cancel the softmark when the cursor is not moved
|
||||
selecting: let a justification cancel a softmark
|
||||
syntax: adjust the magic strings for the changes since file-5.10
|
||||
tweaks: adjust indentation after previous change
|
||||
tweaks: elide the 'mark_set' boolean -- the 'mark' pointer is enough
|
||||
tweaks: rename, rewrap, and reshuffle some stuff, and frob some comments
|
||||
tweaks: reshuffle a couple of lines, and frob a comment or two
|
||||
tweaks: reshuffle a couple of lines, to put similar things together
|
||||
undo: clear the Modified state when the very first edit is undone
|
||||
undo: discarding the stack does not always lose information
|
||||
|
||||
|
||||
Changes between v2.8.7 and v2.9.0:
|
||||
----------------------------------
|
||||
|
||||
Benno Schulenberg (103):
|
||||
bindings: don't allow calling help when searching in the help viewer
|
||||
bindings: make ^Q and ^S do something useful by default
|
||||
bindings: make the search function rebindable again in help and browser
|
||||
bindings: make ^W start always a forward search (as there is ^Q now)
|
||||
browser: place the cursor properly on the selected file when -g is used
|
||||
build: let git ignore also the generated PDF file
|
||||
bump version numbers and add a news item for the 2.9.0 release
|
||||
copyright: update some years, and standardize on the dashed format
|
||||
display: keep the cursor switched on when resizing the screen
|
||||
display: rework the switching on and off of the cursor
|
||||
display: stop the help viewer from turning on the multibuffer indicator
|
||||
display: switch off the cursor early on during startup
|
||||
docs: make it clearer that a Signed-off-by is wanted on patches
|
||||
docs: mention that macros work correctly only on terminal emulators
|
||||
docs: remove another remark about indenting lacking undo capability
|
||||
docs: update references to the nanorc files for the XDG changes
|
||||
files: avoid an abortion when excuting a command in a new buffer
|
||||
gnulib: update to its current upstream state
|
||||
help: don't fall back to other syntaxes if there is no nanohelp one
|
||||
history: after loading the lists, mark them as unchanged
|
||||
history: remove the migration service for the old searches file
|
||||
input: recognize Option+Arrow keys on iTerm2 in "xterm mode"
|
||||
moving: don't slither and slide over tabs when they are overlong
|
||||
moving: prevent the cursor sticking on or skipping over overwide tabs
|
||||
new feature: a bindable function that starts always a backward search
|
||||
options: remove '--quiet' and 'set quiet', because they hide problems
|
||||
options: retire 'set backwards' -- it's still recognized but a no-op
|
||||
organization: move all history-related stuff to its own file
|
||||
ouch: set the positions-file name also when using the legacy state dir
|
||||
painting: evade an ncurses bug by adding the A_PROTECT attribute
|
||||
search: suppress the "not found" message when replacements were made
|
||||
search: suppress the "Search Wrapped" message when doing replacements
|
||||
search: wipe reassuring feedback as soon as searching has finished
|
||||
startup: don't ask the user to press Enter upon an rcfile error
|
||||
startup: don't produce more than three consecutive beeps
|
||||
startup: when an rcfile contains errors, report this on the status bar
|
||||
syntax: default: use colors that are readable also on dark backgrounds
|
||||
titlebar: don't reshow version when dropping back to a single buffer
|
||||
titlebar: don't show nano's name and version when in the file browser
|
||||
titlebar: drop the prefix "File: " from before the filename
|
||||
tweaks: add a translator hint, and adjust two others
|
||||
tweaks: adjust a comment, and condense a fragment of code
|
||||
tweaks: adjust indentation and comments after the previous change
|
||||
tweaks: adjust two comments, and correct and a few cosmetic mistakes
|
||||
tweaks: avoid an unused-variable warning with --disable-nanorc
|
||||
tweaks: change some mayday messages, to urge the user to report a bug
|
||||
tweaks: change the arrows to triangles also for searching in file browser
|
||||
tweaks: change the help-text arrows to triangles, to be more visible
|
||||
tweaks: chuck a bunch of asserts -- they have lost their usefulness
|
||||
tweaks: chuck an assert, and then condense the code and a comment
|
||||
tweaks: constify the result strings of getenv(), as a reminder
|
||||
tweaks: correct two minor things in the documentation
|
||||
tweaks: discard another set of useless asserts
|
||||
tweaks: discard some obsolete debugging stuff
|
||||
tweaks: don't construct the positions-history filename time and again
|
||||
tweaks: drop a bunch of outdated asserts
|
||||
tweaks: drop the ineffective cgitrc -- sorting by "age" does not work
|
||||
tweaks: elide a comment, and improve a couple of others
|
||||
tweaks: elide an unneeded check
|
||||
tweaks: elide an unneeded function now that stuff is grouped together
|
||||
tweaks: elide a superfluous allocation
|
||||
tweaks: elide two variables by using a pointer instead of an index
|
||||
tweaks: fix compilation when configured with --disable-histories
|
||||
tweaks: fix compilation when configured with --enable-tiny
|
||||
tweaks: fix compilation with --enable-tiny --enable-histories
|
||||
tweaks: frob a couple of comments
|
||||
tweaks: frob some comments and rename a few variables and a function
|
||||
tweaks: get rid of some cluttering conditional compilation
|
||||
tweaks: improve some comments, and rename a variable for symmetry
|
||||
tweaks: make the switching on and off of the cursor a bit more compact
|
||||
tweaks: move a general function to the utils.c file
|
||||
tweaks: reduce a bit of code duplication
|
||||
tweaks: remove a comment from the docs that is no longer accurate
|
||||
tweaks: remove another bit of conditional compilation
|
||||
tweaks: remove a superfluous no-op function call
|
||||
tweaks: remove a useless prefix from a hundred constants
|
||||
tweaks: rename a function and swap its two parameters
|
||||
tweaks: rename a function plus two parameters, to be more fitting
|
||||
tweaks: rename a macro, to make a little more sense
|
||||
tweaks: rename a variable, to avoid a possible confusion
|
||||
tweaks: rename a variable, to make more sense
|
||||
tweaks: rename one variable once more
|
||||
tweaks: rename some constants, to follow the same underscoreless scheme
|
||||
tweaks: rename three functions, to be shorter or clearer
|
||||
tweaks: rename three variables, for more contrast
|
||||
tweaks: rename two variables, for contrast, and frob some comments
|
||||
tweaks: rename two variables, to be more indicative of what they do
|
||||
tweaks: rename two variables, to make a little more sense
|
||||
tweaks: reshuffle a bit of code and elide an unneeded variable
|
||||
tweaks: reshuffle a couple of lines, and trim some comments
|
||||
tweaks: reshuffle some code, and rename a variable
|
||||
tweaks: reshuffle some code in order to elide a variable
|
||||
tweaks: reshuffle some regexes, for order and compactness
|
||||
tweaks: strip four unneeded checks
|
||||
tweaks: transform the token DISABLE_COLOR to ENABLE_COLOR
|
||||
tweaks: transform the token DISABLE_EXTRA to ENABLE_EXTRA
|
||||
tweaks: transform the token DISABLE_HISTORIES to ENABLE_HISTORIES
|
||||
tweaks: transform the token DISABLE_JUSTIFY to ENABLE_JUSTIFY
|
||||
tweaks: transform the token DISABLE_OPERATINGDIR to ENABLE_OPERATINGDIR
|
||||
tweaks: transform the token DISABLE_SPELLER to ENABLE_SPELLER
|
||||
tweaks: transform the token DISABLE_WRAPJUSTIFY to ENABLED_WRAPORJUSTIFY
|
||||
tweaks: transform the token DISABLE_WRAPPING to ENABLE_WRAPPING
|
||||
tweaks: use mnemonic constants instead of TRUE and FALSE
|
||||
|
||||
Brand Huntsman (3):
|
||||
bindings: allow exiting from the help viewer with F1, like with ^G
|
||||
history: prevent overwriting of positions between multiple instances
|
||||
syntax: nanohelp: colorize Up, Down, Left and Right (when not in UTF-8)
|
||||
|
||||
David Lawrence Ramsey (18):
|
||||
build: add history.c to the list of files with translatable strings
|
||||
display: don't cut off zero-width characters at the end of a chunk
|
||||
docs: decribe the bindable functions 'recordmacro' and 'runmacro'
|
||||
docs: document the more everyday names of three bindable functions
|
||||
docs: remove man page reference to indent/unindent lacking undo/redo
|
||||
files: don't change file format when inserting into an existing buffer
|
||||
help: allow firstline and lastline to work at the search prompt
|
||||
history: fix the check for an existing $HOME/.nano/ directory
|
||||
moving: set the preferred column properly when doing a smart home
|
||||
search: don't bother saving and restoring the search direction
|
||||
search: trim a failed search string for width instead of length
|
||||
softwrap: break before multi-column Unicode blanks when they overshoot
|
||||
syntax: nanorc: properly color valid arguments of 'selectedcolor'
|
||||
text: hook up indenting and unindenting to the undo/redo code
|
||||
text: move the indenting of a single line into its own function
|
||||
text: move the unindenting of a single line into its own function
|
||||
tweaks: use printf's z modifier for most of the size_t/ssize_t types
|
||||
undo: generalize update_comment_undo() into update_multiline_undo()
|
||||
|
||||
Lion Yang (1):
|
||||
input: ensure that standard input uses blocking mode
|
||||
|
||||
Marco Diego Aurélio Mesquita (5):
|
||||
general: do not free strings gotten from getenv(), to avoid a crash
|
||||
history: remember the commands that were executed during this session
|
||||
history: remember the list of executed commands across sessions
|
||||
new feature: show current and total number of open buffers in title bar
|
||||
new feature: the ability to record and play back a series of keystrokes
|
||||
|
||||
Simon Ochsenreither (1):
|
||||
startup: look for nanorc and history files also in the XDG directories
|
||||
|
||||
Viorel Bota (1):
|
||||
files: check for a changed disk file also for 'savefile' and --tempfile
|
||||
|
||||
|
||||
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:
|
||||
----------------------------------
|
||||
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
Improvements in GNU nano
|
||||
========================
|
||||
|
||||
Since 2.9.0:
|
||||
- The ability to record and replay a series of keystrokes (a macro).
|
||||
- Assigned functions to ^S (save file) and ^Q (start backward search).
|
||||
- Indenting and unindenting have been integrated into the undo system.
|
||||
- Support for $XDG_CONFIG_HOME for the nanorc file, and $XDG_DATA_HOME
|
||||
for the history files (of search strings and cursor positions).
|
||||
|
||||
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.
|
||||
|
||||
37
NEWS
37
NEWS
@@ -1,3 +1,36 @@
|
||||
2017.11.27 - GNU nano 2.9.1 "Damyatta" fixes a bug where, when the mark
|
||||
is on, ^S would overwrite the file with just the marked
|
||||
region. This release further clears the "Modified" flag
|
||||
when all edits are undone, adds or updates some magic
|
||||
strings, and does not forget when the cursor was last
|
||||
at line 1, column 1.
|
||||
|
||||
2017.11.18 - GNU nano 2.9.0 "Eta" introduces the ability to record and
|
||||
replay keystrokes (M-: to start and stop recording, M-;
|
||||
to play the macro back), makes ^Q and ^S do something
|
||||
useful by default (^Q starts a backward search, and ^S
|
||||
saves the current file), changes ^W to start always a
|
||||
forward search, shows the number of open buffers (when
|
||||
more than one) in the title bar, no longer asks to press
|
||||
Enter when there are errors in an rc file, retires the
|
||||
options '--quiet' and 'set quiet' and 'set backwards',
|
||||
makes indenting and unindenting undoable, will look in
|
||||
$XDG_CONFIG_HOME for a nanorc file and in $XDG_DATA_HOME
|
||||
for the history files, adds a history stack for executed
|
||||
commands (^R^X), does not overwrite the position-history
|
||||
file of another nano, and fixes a score of tiny bugs.
|
||||
|
||||
|
||||
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
|
||||
@@ -307,7 +340,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
|
||||
@@ -1617,7 +1650,7 @@
|
||||
|
||||
2000.02.02 - Okay, I hate to go back on what I said in the last release,
|
||||
but I may be changing jobs very soon. I will release
|
||||
version 0.8.2 as is (no i18n, no help menu (yet). I
|
||||
version 0.8.2 as is (no i18n, no help menu (yet)). I
|
||||
expect things to settle down by the end of next week,
|
||||
and then I can try to start on the i18n support and help
|
||||
menu; look for these new features in version 0.8.5 to
|
||||
|
||||
@@ -93,12 +93,15 @@ first create a branch off of master:
|
||||
|
||||
$ git checkout -b somename
|
||||
|
||||
Then change the code so it does what you want, and commit it, with in the
|
||||
commit message (after the one-line summary) a rationale for the change:
|
||||
Then change the code so it does what you want, and commit it together
|
||||
with your Sign-off:
|
||||
|
||||
$ git commit -as
|
||||
|
||||
Then create a patch (or patches):
|
||||
In the commit message (after the one-line summary) give a rationale
|
||||
for the change. With your Signed-off-by you declare that the code is
|
||||
yours, or that you are free to reuse it, and that you submit it under
|
||||
the license that covers nano. Then create a patch (or patches):
|
||||
|
||||
$ git format-patch master
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Generate configure & friends for GIT users.
|
||||
|
||||
gnulib_url="git://git.sv.gnu.org/gnulib.git"
|
||||
gnulib_hash="c7711db84f251d9e580d9fa53a070fa97ae89095"
|
||||
gnulib_hash="b9d0b50f6cd122a1748e1e5b79ecca7a0fef214e"
|
||||
|
||||
modules="
|
||||
futimens
|
||||
|
||||
96
configure.ac
96
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.6], [nano-devel@gnu.org], [nano])
|
||||
AC_INIT([GNU nano], [2.9.1], [nano-devel@gnu.org], [nano])
|
||||
AC_CONFIG_SRCDIR([src/nano.c])
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE([1.14])
|
||||
@@ -75,6 +75,15 @@ fi
|
||||
|
||||
AC_ARG_ENABLE(color,
|
||||
AS_HELP_STRING([--disable-color], [Disable color and syntax highlighting]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_color" = xyes; then
|
||||
if test "x$enable_nanorc" != xyes; then
|
||||
AC_MSG_ERROR([--enable-color needs --enable-nanorc to work])
|
||||
fi
|
||||
else
|
||||
enable_color=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_nanorc" = xno; then
|
||||
if test "x$enable_color" = xyes; then
|
||||
AC_MSG_ERROR([--enable-color cannot work with --disable-nanorc])
|
||||
@@ -83,9 +92,8 @@ if test "x$enable_nanorc" = xno; then
|
||||
enable_color=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_color" = xno; then
|
||||
AC_DEFINE(DISABLE_COLOR, 1, [Define this to disable syntax highlighting.])
|
||||
else
|
||||
if test "x$enable_color" != xno; then
|
||||
AC_DEFINE(ENABLE_COLOR, 1, [Define this to have syntax highlighting.])
|
||||
color_support=yes
|
||||
fi
|
||||
|
||||
@@ -104,8 +112,13 @@ fi
|
||||
|
||||
AC_ARG_ENABLE(extra,
|
||||
AS_HELP_STRING([--disable-extra], [Disable the Easter egg]))
|
||||
if test "x$enable_extra" = xno; then
|
||||
AC_DEFINE(DISABLE_EXTRA, 1, [Define this to disable extra stuff.])
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_extra" != xyes; then
|
||||
enable_extra=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_extra" != xno; then
|
||||
AC_DEFINE(ENABLE_EXTRA, 1, [Define this to have an Easter egg.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(help,
|
||||
@@ -133,14 +146,24 @@ fi
|
||||
|
||||
AC_ARG_ENABLE(histories,
|
||||
AS_HELP_STRING([--disable-histories], [Disable search and position histories]))
|
||||
if test "x$enable_histories" = xno; then
|
||||
AC_DEFINE(DISABLE_HISTORIES, 1, [Define this to disable search and position histories.])
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_histories" != xyes; then
|
||||
enable_histories=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_histories" != xno; then
|
||||
AC_DEFINE(ENABLE_HISTORIES, 1, [Define this to have search and position histories.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(justify,
|
||||
AS_HELP_STRING([--disable-justify], [Disable the justify/unjustify functions]))
|
||||
if test "x$enable_justify" = xno; then
|
||||
AC_DEFINE(DISABLE_JUSTIFY, 1, [Define this to disable the justify routines.])
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_justify" != xyes; then
|
||||
enable_justify=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_justify" != xno; then
|
||||
AC_DEFINE(ENABLE_JUSTIFY, 1, [Define this to have the routines for justifying.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(libmagic,
|
||||
@@ -193,14 +216,24 @@ fi
|
||||
|
||||
AC_ARG_ENABLE(operatingdir,
|
||||
AS_HELP_STRING([--disable-operatingdir], [Disable the setting of an operating directory]))
|
||||
if test "x$enable_operatingdir" = xno; then
|
||||
AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable the setting of an operating directory (a chroot of sorts).])
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_operatingdir" != xyes; then
|
||||
enable_operatingdir=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_operatingdir" != xno; then
|
||||
AC_DEFINE(ENABLE_OPERATINGDIR, 1, [Define this to allow setting an operating directory (a chroot of sorts).])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(speller,
|
||||
AS_HELP_STRING([--disable-speller], [Disable the spell-checker functions]))
|
||||
if test "x$enable_speller" = xno; then
|
||||
AC_DEFINE(DISABLE_SPELLER, 1, [Define this to disable the spell-checker functions.])
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_speller" != xyes; then
|
||||
enable_speller=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_speller" != xno; then
|
||||
AC_DEFINE(ENABLE_SPELLER, 1, [Define this to have the spell-checker functions.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(tabcomp,
|
||||
@@ -229,8 +262,13 @@ fi
|
||||
|
||||
AC_ARG_ENABLE(wrapping,
|
||||
AS_HELP_STRING([--disable-wrapping], [Disable all hard-wrapping of text]))
|
||||
if test "x$enable_wrapping" = xno; then
|
||||
AC_DEFINE(DISABLE_WRAPPING, 1, [Define this to disable all hard text wrapping.])
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_wrapping" != xyes; then
|
||||
enable_wrapping=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_wrapping" != xno; then
|
||||
AC_DEFINE(ENABLE_WRAPPING, 1, [Define this to have hard text wrapping.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(wrapping-as-root,
|
||||
@@ -251,35 +289,9 @@ AC_ARG_ENABLE(tiny,
|
||||
AS_HELP_STRING([--enable-tiny], [Disable features for the sake of size]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
AC_DEFINE(NANO_TINY, 1, [Define this to make the nano executable as small as possible.])
|
||||
if test "x$enable_color" != xyes; then
|
||||
AC_DEFINE(DISABLE_COLOR, 1, [Define this to disable syntax highlighting.])
|
||||
color_support=no
|
||||
else
|
||||
if test "x$enable_nanorc" != xyes; then
|
||||
AC_MSG_ERROR([--enable-color needs --enable-nanorc to work])
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_extra" != xyes; then
|
||||
AC_DEFINE(DISABLE_EXTRA, 1, [Define this to disable extra stuff.])
|
||||
fi
|
||||
if test "x$enable_histories" != xyes; then
|
||||
AC_DEFINE(DISABLE_HISTORIES, 1, [Define this to disable search and position histories.])
|
||||
fi
|
||||
if test "x$enable_justify" != xyes; then
|
||||
AC_DEFINE(DISABLE_JUSTIFY, 1, [Define this to disable the justify routines.])
|
||||
fi
|
||||
if test "x$enable_libmagic" != xyes; then
|
||||
enable_libmagic=no
|
||||
fi
|
||||
if test "x$enable_operatingdir" != xyes; then
|
||||
AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable the setting of an operating directory (a chroot of sorts).])
|
||||
fi
|
||||
if test "x$enable_speller" != xyes; then
|
||||
AC_DEFINE(DISABLE_SPELLER, 1, [Define this to disable the spell-checker functions.])
|
||||
fi
|
||||
if test "x$enable_wrapping" != xyes; then
|
||||
AC_DEFINE(DISABLE_WRAPPING, 1, [Define this to disable all text wrapping.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(USE_COLOR, test x$color_support = xyes)
|
||||
|
||||
1
doc/.gitignore
vendored
1
doc/.gitignore
vendored
@@ -4,4 +4,5 @@ nanorc.5.html
|
||||
texinfo.tex
|
||||
nano.info
|
||||
nano.html
|
||||
nano.pdf
|
||||
sample.nanorc
|
||||
|
||||
@@ -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.6</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<blockquote><p>The current version of nano <i>should</i> be <b>2.9.1</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<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%">
|
||||
|
||||
43
doc/nano.1
43
doc/nano.1
@@ -16,8 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANO 1 "version 2.8.6" "July 2017"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.TH NANO 1 "version 2.9.1" "November 2017"
|
||||
|
||||
.SH NAME
|
||||
nano \- Nano's ANOther editor, an enhanced free Pico clone
|
||||
@@ -61,7 +60,7 @@ stride.
|
||||
.PP
|
||||
The two lines at the bottom of the screen show some important commands;
|
||||
the built-in help (\fB^G\fR) lists all the available ones.
|
||||
The default key bindings can be changed via the .nanorc file -- see
|
||||
The default key bindings can be changed via a \fInanorc\fR file -- see
|
||||
.BR nanorc (5).
|
||||
|
||||
.SH OPTIONS
|
||||
@@ -77,7 +76,7 @@ line.
|
||||
When saving a file, back up the previous version of it, using the current
|
||||
filename suffixed with a tilde (\fB~\fP).
|
||||
.TP
|
||||
.BR \-C\ \fIdirectory\fR ", " \-\-backupdir= \fIdirectory
|
||||
.BR \-C\ \fIdirectory ", " \-\-backupdir= \fIdirectory
|
||||
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 (\fB\-B\fR).
|
||||
The uniquely numbered files are stored in the specified \fIdirectory\fR.
|
||||
@@ -95,11 +94,11 @@ Read a file into a new buffer by default.
|
||||
Use vim-style file locking when editing files.
|
||||
.TP
|
||||
.BR \-H ", " \-\-historylog
|
||||
Log search and replace strings to \fI~/.nano/search_history\fP, so they can be
|
||||
retrieved in later sessions.
|
||||
Save the last hundred search strings and replacement strings and
|
||||
executed commands, so they can be easily reused in later sessions.
|
||||
.TP
|
||||
.BR \-I ", " \-\-ignorercfiles
|
||||
Don't look at the system's \fBnanorc\fP nor at \fB~/.nanorc\fP.
|
||||
Don't look at the system's \fInanorc\fR nor at the user's \fInanorc\fR.
|
||||
.TP
|
||||
.BR \-K ", " \-\-rebindkeypad
|
||||
Interpret the numeric keypad keys so that they all work properly. You
|
||||
@@ -120,7 +119,7 @@ For the 200 most recent files, log the last position of the cursor,
|
||||
and place it at that position again upon reopening such a file.
|
||||
(The old form of this option, \fB\-\-poslog\fR, is deprecated.)
|
||||
.TP
|
||||
.BR "\-Q ""\fIcharacters\fB""" ", " "\-\-quotestr=""" \fIcharacters\fR """
|
||||
.BR "\-Q ""\fIcharacters\fB""" ", " "\-\-quotestr=""" \fIcharacters """
|
||||
Set the quoting string for justifying. The default is
|
||||
\fB"^([\ \\t]*[#:>\\|}])+"\fP if extended regular expression support is
|
||||
available, or \fB">\ "\fP otherwise. Note that \fB\\t\fP stands for a
|
||||
@@ -139,7 +138,7 @@ with any name beginning with 'r' (e.g. "rnano").
|
||||
Use smooth scrolling: text will scroll line-by-line, instead of the
|
||||
usual chunk-by-chunk behavior.
|
||||
.TP
|
||||
.BR \-T\ \fInumber\fR ", " \-\-tabsize= \fInumber
|
||||
.BR \-T\ \fInumber ", " \-\-tabsize= \fInumber
|
||||
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
|
||||
@@ -160,7 +159,7 @@ Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as part of a word. This overrides option
|
||||
\fB\-W\fR (\fB\-\-wordbounds\fR).
|
||||
.TP
|
||||
.BR \-Y\ \fIname\fR ", " \-\-syntax= \fIname
|
||||
.BR \-Y\ \fIname ", " \-\-syntax= \fIname
|
||||
Specify the name of the syntax highlighting to use from among the ones
|
||||
defined in the \fInanorc\fP files.
|
||||
.TP
|
||||
@@ -209,7 +208,7 @@ and will write to the pipe when the user saves the "file". This way
|
||||
\fBnano\fR can be used as an editor in combination with for instance
|
||||
\fBgpg\fR without having to write sensitive data to disk first.
|
||||
.TP
|
||||
.BR \-o\ \fIdirectory\fR ", " \-\-operatingdir= \fIdirectory
|
||||
.BR \-o\ \fIdirectory ", " \-\-operatingdir= \fIdirectory
|
||||
Set the operating directory. This makes \fBnano\fP set up something
|
||||
similar to a chroot.
|
||||
.TP
|
||||
@@ -218,17 +217,16 @@ Preserve the XON and XOFF sequences (^Q and ^S) so they will be caught
|
||||
by the terminal.
|
||||
.TP
|
||||
.BR \-q ", " \-\-quiet
|
||||
Do not report errors in the \fInanorc\fP files nor ask them to be
|
||||
acknowledged by pressing Enter at startup.
|
||||
Obsolete option. Recognized but ignored.
|
||||
.TP
|
||||
.BR \-r\ \fInumber\fR ", " \-\-fill= \fInumber
|
||||
.BR \-r\ \fInumber ", " \-\-fill= \fInumber
|
||||
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 (\fB\-\-nowrap\fR) -- the last one given takes effect.
|
||||
.TP
|
||||
.BR \-s\ \fIprogram\fR ", " \-\-speller= \fIprogram
|
||||
.BR \-s\ \fIprogram ", " \-\-speller= \fIprogram
|
||||
Use this alternative spell checker command.
|
||||
.TP
|
||||
.BR \-t ", " \-\-tempfile
|
||||
@@ -272,9 +270,10 @@ hard-wrapping of long lines, \fBM\-$\fR toggles soft-wrapping,
|
||||
See at the end of the \fB^G\fR help text for a complete list.
|
||||
|
||||
.SH INITIALIZATION FILE
|
||||
\fBnano\fP will read initialization files in the following order:
|
||||
the system's \fBnanorc\fP (if it exists), and then the user's
|
||||
\fB~/.nanorc\fP (if it exists). Please see
|
||||
\fBnano\fR will read two configuration files: first the system's
|
||||
\fInanorc\fR (if it exists), and then the user's \fInanorc\fR (if it
|
||||
exists), either \fB~/.nanorc\fR or \fI$XDG_CONFIG_HOME\fB/nano/nanorc\fR
|
||||
or \fB~/.config/nano/nanorc\fR, whichever is encountered first. See
|
||||
.BR nanorc (5)
|
||||
for more information on the possible contents of those files.
|
||||
|
||||
@@ -294,12 +293,16 @@ it unique. In multibuffer mode, \fBnano\fP will write all the open
|
||||
buffers to their respective emergency files.
|
||||
|
||||
.SH BUGS
|
||||
Justifications (\fB^J\fR) and reindentations (\fBM\-{\fR and \fBM\-}\fR)
|
||||
Justifications (\fB^J\fR)
|
||||
are not yet covered by the general undo system. So after a justification
|
||||
that is not immediately undone, or after any reindentation, earlier edits
|
||||
that is not immediately undone, earlier edits
|
||||
cannot be undone any more. The workaround is, of course, to exit without
|
||||
saving.
|
||||
.sp
|
||||
The recording and playback of keyboard macros works correctly only on a
|
||||
terminal emulator, not on a Linux console (VT), because the latter is a
|
||||
deficient terminal. And it works only with recent versions of ncurses.
|
||||
.sp
|
||||
Please report any other bugs that you encounter via:
|
||||
.br
|
||||
\fIhttps://savannah.gnu.org/bugs/?group=nano\fR.
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
@smallbook
|
||||
@set EDITION 0.5
|
||||
@set VERSION 2.8.6
|
||||
@set UPDATED July 2017
|
||||
@set VERSION 2.9.1
|
||||
@set UPDATED November 2017
|
||||
|
||||
@dircategory Editors
|
||||
@direntry
|
||||
@@ -23,7 +23,7 @@
|
||||
@titlepage
|
||||
@title GNU @command{nano}
|
||||
@subtitle a small and friendly text editor
|
||||
@subtitle version 2.8.6
|
||||
@subtitle version 2.9.1
|
||||
|
||||
@author Chris Allegretta
|
||||
@page
|
||||
@@ -63,7 +63,7 @@ e-mail: @email{chrisa@@asty.org}@*
|
||||
@node Top
|
||||
@top
|
||||
|
||||
This manual documents the GNU @command{nano} editor, version 2.8.6.
|
||||
This manual documents the GNU @command{nano} editor, version 2.9.1.
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
@@ -130,7 +130,7 @@ adding it with a comma. So a more complete command synopsis is:
|
||||
@sp 1
|
||||
@end iftex
|
||||
|
||||
Normally, however, you set your preferred options in a @file{.nanorc}
|
||||
Normally, however, you set your preferred options in a @file{nanorc}
|
||||
file (@pxref{Nanorc Files}). And when using @code{set positionlog}
|
||||
(making @command{nano} remember the cursor position when you close a file),
|
||||
you will rarely need to specify a line number.
|
||||
@@ -183,12 +183,12 @@ Enable vim-style file locking when editing files.
|
||||
|
||||
@item -H
|
||||
@itemx --historylog
|
||||
Log search and replace strings to @file{~/.nano/search_history},
|
||||
so they can be retrieved in later sessions.
|
||||
Save the last hundred search strings and replacement strings and
|
||||
executed commands, so they can be easily reused in later sessions.
|
||||
|
||||
@item -I
|
||||
@itemx --ignorercfiles
|
||||
Don't look at the system's nanorc file nor at the user's @file{~/.nanorc}.
|
||||
Don't look at the system's nanorc file nor at the user's nanorc.
|
||||
|
||||
@item -K
|
||||
@itemx --rebindkeypad
|
||||
@@ -335,8 +335,7 @@ sent to the editor can be stopped and started.
|
||||
|
||||
@item -q
|
||||
@itemx --quiet
|
||||
Do not report errors in the nanorc file nor ask them to be acknowledged
|
||||
by pressing @kbd{Enter} at startup.
|
||||
Obsolete option. Recognized but ignored.
|
||||
|
||||
@item -r @var{number}
|
||||
@itemx --fill=@var{number}
|
||||
@@ -423,7 +422,7 @@ Ignored, for compatibility with Pico.
|
||||
* Screen Layout::
|
||||
* Search and Replace::
|
||||
* Using the Mouse::
|
||||
* Limitation::
|
||||
* Limitations::
|
||||
@end menu
|
||||
|
||||
@node Entering Text
|
||||
@@ -553,15 +552,18 @@ Shift key during those actions.
|
||||
The mouse will work in the X Window System, and on the console when gpm
|
||||
is running.
|
||||
|
||||
@node Limitation
|
||||
@section Limitation
|
||||
@node Limitations
|
||||
@section Limitations
|
||||
|
||||
Justifications (@kbd{^J}) and reindentations (@kbd{M-@{} and @kbd{M-@}})
|
||||
Justifications (@kbd{^J})
|
||||
are not yet covered by the general undo system. So after a justification
|
||||
that is not immediately undone, or after any reindentation, earlier edits
|
||||
that is not immediately undone, earlier edits
|
||||
cannot be undone any more. The workaround is, of course, to exit without
|
||||
saving.
|
||||
|
||||
The recording and playback of keyboard macros works correctly only on a
|
||||
terminal emulator, not on a Linux console (VT), because the latter is a
|
||||
deficient terminal. And it works only with recent versions of ncurses.
|
||||
|
||||
@node Built-in Help
|
||||
@chapter Built-in Help
|
||||
@@ -647,7 +649,8 @@ The nanorc files contain the default settings for @command{nano}. They
|
||||
should be in Unix format, not in DOS or Mac format. During startup,
|
||||
@command{nano} will first read the system-wide settings, from /etc/nanorc
|
||||
(the exact path might be different), and then the user-specific settings,
|
||||
from @file{~/.nanorc}.
|
||||
either from @file{~/.nanorc} or from @file{$XDG_CONFIG_HOME/nano/nanorc}
|
||||
or from @file{.config/nano/nanorc}, whichever exists first.
|
||||
|
||||
A nanorc file accepts a series of "set" and "unset" commands, which can
|
||||
be used to configure @command{nano} on startup without using command-line
|
||||
@@ -659,8 +662,7 @@ Options in nanorc files take precedence over @command{nano}'s defaults, and
|
||||
command-line options override nanorc settings. Also, options that do not
|
||||
take an argument are unset by default. So using the @code{unset} command
|
||||
is only needed when wanting to override a setting of the system's nanorc
|
||||
file in your own @file{~/.nanorc}. Options that take an argument cannot
|
||||
be unset.
|
||||
file in your own nanorc. Options that take an argument cannot be unset.
|
||||
|
||||
Quotes inside string parameters don't have to be escaped with
|
||||
backslashes. The last double quote in the string will be treated as its
|
||||
@@ -703,13 +705,14 @@ with @code{set backup} or @option{--backup} or @option{-B}.
|
||||
The uniquely numbered files are stored in the specified directory.
|
||||
|
||||
@item set backwards
|
||||
Do backwards searches by default.
|
||||
Obsolete option. Recognized but ignored. @code{^Q} is available to
|
||||
start a backward search.
|
||||
|
||||
@item set boldtext
|
||||
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 for
|
||||
the first five by setting the options @code{titlecolor}, @code{statuscolor},
|
||||
@code{keycolor}, @code{functioncolor}, and @code{numbercolor}.
|
||||
function tags, line numbers, and selected text. This can be overridden by
|
||||
setting the options @code{titlecolor}, @code{statuscolor}, @code{keycolor},
|
||||
@code{functioncolor}, @code{numbercolor}, and @code{selectedcolor}.
|
||||
|
||||
@item set brackets "@var{string}"
|
||||
Set the characters treated as closing brackets when justifying
|
||||
@@ -744,11 +747,11 @@ Valid names for foreground and background color are:
|
||||
@code{white}, @code{black}, @code{blue}, @code{green},
|
||||
@code{red}, @code{cyan}, @code{yellow}, and @code{magenta}.
|
||||
The name of the foreground color may be prefixed with @code{bright}.
|
||||
And either @var{fgcolor} or @var{,bgcolor} may be left out.
|
||||
And either @var{fgcolor} or ,@var{bgcolor} may be left out.
|
||||
|
||||
@item set historylog
|
||||
Enable the use of @file{~/.nano/search_history} for saving and reading
|
||||
search/replace strings.
|
||||
Save the last hundred search strings and replacement strings and
|
||||
executed commands, so they can be easily reused in later sessions.
|
||||
|
||||
@item set justifytrim
|
||||
When justifying text, trailing whitespace will automatically be removed.
|
||||
@@ -827,9 +830,7 @@ Do quick status-bar blanking: status-bar messages will disappear after 1
|
||||
keystroke instead of 25. Note that @option{constantshow} overrides this.
|
||||
|
||||
@item set quiet
|
||||
When set, @command{nano} will not report errors in the nanorc file nor ask them
|
||||
to be acknowledged by pressing @kbd{Enter} at startup. If this option is used, it
|
||||
should be placed at the top of the file to be fully effective.
|
||||
Obsolete option. Recognized but ignored.
|
||||
|
||||
@item set quotestr "@var{string}"
|
||||
The email-quote string, used to justify email-quoted paragraphs. This
|
||||
@@ -852,6 +853,10 @@ won't work properly with this option enabled.
|
||||
@item set regexp
|
||||
Do extended regular expression searches by default.
|
||||
|
||||
@item set selectedcolor @var{fgcolor},@var{bgcolor}
|
||||
Use this color combination for selected text.
|
||||
@xref{@code{set functioncolor}} for valid color names.
|
||||
|
||||
@item set showcursor
|
||||
Put the cursor on the highlighted item in the file browser, to aid
|
||||
braille users.
|
||||
@@ -1076,15 +1081,18 @@ Exits from the program (or from the help viewer or the file browser).
|
||||
Writes the current buffer to disk, asking for a name.
|
||||
|
||||
@item savefile
|
||||
Writes the current file to disk without prompting or warning.
|
||||
Writes the current file to disk without prompting.
|
||||
|
||||
@item insert
|
||||
Inserts a file into the current buffer (at the current cursor position),
|
||||
or into a new buffer when option @code{multibuffer} is set.
|
||||
|
||||
@item whereis
|
||||
Searches for text in the current buffer --- or for filenames matching
|
||||
a string in the current list in the file browser
|
||||
Starts a forward search for text in the current buffer --- or for filenames
|
||||
matching a string in the current list in the file browser.
|
||||
|
||||
@item wherewas
|
||||
Starts a backward search for text in the current buffer.
|
||||
|
||||
@item searchagain
|
||||
Repeats the last search command without prompting.
|
||||
@@ -1195,10 +1203,10 @@ Moves the cursor to the beginning of the current or preceding block of text.
|
||||
@item nextblock
|
||||
Moves the cursor to the beginning of the next block of text.
|
||||
|
||||
@item prevpage
|
||||
@item pageup
|
||||
Goes up one screenful.
|
||||
|
||||
@item nextpage
|
||||
@item pagedown
|
||||
Goes down one screenful.
|
||||
|
||||
@item firstline
|
||||
@@ -1239,6 +1247,13 @@ Deletes the character under the cursor.
|
||||
@item backspace
|
||||
Deletes the character before the cursor.
|
||||
|
||||
@item recordmacro
|
||||
Starts the recording of keystrokes --- the keystrokes are stored
|
||||
as a macro. When already recording, the recording is stopped.
|
||||
|
||||
@item runmacro
|
||||
Replays the keystrokes of the last recorded macro.
|
||||
|
||||
@item undo
|
||||
Undoes the last performed text action (add text, delete text, etc).
|
||||
|
||||
@@ -1300,7 +1315,7 @@ When about to write a file, discard the current buffer without saving.
|
||||
(This function is bound by default only when option @option{--tempfile}
|
||||
is in effect.)
|
||||
|
||||
@item tofiles
|
||||
@item browser
|
||||
Starts the file browser, allowing to select a file from a list.
|
||||
|
||||
@item gotodir
|
||||
@@ -1459,14 +1474,14 @@ ask any more), or Cancel (stop with replacing).
|
||||
|
||||
@item Search and Replace History
|
||||
When the option @option{-H} or @option{--historylog} is given (or set in
|
||||
the .nanorc file), text entered as search or replace strings is stored.
|
||||
the a nanorc file), text entered as search or replace strings is stored.
|
||||
These strings can be accessed with the up/down arrow keys, or you can
|
||||
type the first few characters and then use @kbd{Tab} to cycle through the
|
||||
matching strings. A retrieved string can subsequently be edited.
|
||||
|
||||
@item Position History
|
||||
When the option @option{-P} or @option{--positionlog} is given (or set in
|
||||
the .nanorc file), @command{nano} will store the position of the cursor
|
||||
a nanorc file), @command{nano} will store the position of the cursor
|
||||
when you close a file, and will place the cursor in that position
|
||||
again when you later reopen the file.
|
||||
|
||||
@@ -1587,9 +1602,8 @@ Disable support for reading the nanorc files at startup. With such
|
||||
support, you can store custom settings in a system-wide and a per-user
|
||||
nanorc file rather than having to pass command-line options to get
|
||||
the desired behavior. @xref{Nanorc Files} for more info.
|
||||
Disabling this also eliminates the @option{-I} and @option{-q} command-line
|
||||
options; the first inhibits the reading of nanorcfiles, and the second
|
||||
suppresses warnings about errors in those files.
|
||||
Disabling this also eliminates the @option{-I} command-line option,
|
||||
which inhibits the reading of nanorc files.
|
||||
|
||||
@item --disable-operatingdir
|
||||
Disable setting the operating directory. This also eliminates the @option{-o}
|
||||
|
||||
54
doc/nanorc.5
54
doc/nanorc.5
@@ -16,8 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANORC 5 "version 2.8.6" "July 2017"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.TH NANORC 5 "version 2.9.1" "November 2017"
|
||||
|
||||
.SH NAME
|
||||
nanorc \- GNU nano's configuration file
|
||||
@@ -27,7 +26,9 @@ The \fInanorc\fP file contains the default settings for \fBnano\fP, a
|
||||
small and friendly editor. The file should be in Unix format, not in
|
||||
DOS or Mac format. During startup, \fBnano\fP will first read the
|
||||
system-wide settings, from \fB/etc/nanorc\fP (the exact path might be
|
||||
different), and then the user-specific settings, from \fB~/.nanorc\fP.
|
||||
different on your system), and then the user-specific settings, either
|
||||
from \fB~/.nanorc\fR or from \fI$XDG_CONFIG_HOME\fB/nano/nanorc\fR
|
||||
or from \fB~/.config/nano/nanorc\fR, whichever is encountered first.
|
||||
|
||||
.SH OPTIONS
|
||||
The configuration file accepts a series of \fBset\fP and \fBunset\fP
|
||||
@@ -40,7 +41,7 @@ Options in \fInanorc\fP files take precedence over nano's defaults, and
|
||||
command-line options override \fInanorc\fP settings. Also, options that
|
||||
do not take an argument are unset by default. So using the \fBunset\fR
|
||||
command is only needed when wanting to override a setting of the system's
|
||||
\fInanorc\fR file in your own \fB~/.nanorc\fR. Options that take an
|
||||
\fInanorc\fR file in your own \fInanorc\fR. Options that take an
|
||||
argument cannot be unset.
|
||||
.PP
|
||||
Below, the \fIstring\fR parameters need to be enclosed in double quotes.
|
||||
@@ -75,13 +76,14 @@ with \fBset backup\fR or \fB\-\-backup\fR or \fB\-B\fR.
|
||||
The uniquely numbered files are stored in the specified \fIdirectory\fR.
|
||||
.TP
|
||||
.B set backwards
|
||||
Do backwards searches by default.
|
||||
Obsolete option. Recognized but ignored. \fB^Q\fR is available to
|
||||
start a backward search.
|
||||
.TP
|
||||
.B set boldtext
|
||||
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 for
|
||||
the first five by setting the options \fBtitlecolor\fP, \fBstatuscolor\fP,
|
||||
\fBkeycolor\fP, \fBfunctioncolor\fP, and \fBnumbercolor\fP.
|
||||
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
|
||||
@@ -113,8 +115,8 @@ in the two help lines at the bottom of the screen.
|
||||
See \fBset titlecolor\fR for more details.
|
||||
.TP
|
||||
.B set historylog
|
||||
Enable the use of \fB~/.nano/search_history\fP for saving and reading
|
||||
search/replace strings.
|
||||
Save the last hundred search strings and replacement strings and
|
||||
executed commands, so they can be easily reused in later sessions.
|
||||
.TP
|
||||
.B set justifytrim
|
||||
When justifying text, trailing whitespace will automatically be removed.
|
||||
@@ -195,9 +197,7 @@ 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
|
||||
to be acknowledged by pressing Enter at startup. If this is used, it
|
||||
should be placed at the top of the file to be fully effective.
|
||||
Obsolete option. Recognized but ignored.
|
||||
.TP
|
||||
.B set quotestr "\fIstring\fP"
|
||||
The email-quote string, used to justify email-quoted paragraphs. This
|
||||
@@ -220,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.
|
||||
@@ -433,15 +437,18 @@ Exits from the program (or from the help viewer or the file browser).
|
||||
Writes the current buffer to disk, asking for a name.
|
||||
.TP
|
||||
.B savefile
|
||||
Writes the current file to disk without prompting or warning.
|
||||
Writes the current file to disk without prompting.
|
||||
.TP
|
||||
.B insert
|
||||
Inserts a file into the current buffer (at the current cursor position),
|
||||
or into a new buffer when option \fBmultibuffer\fR is set.
|
||||
.TP
|
||||
.B whereis
|
||||
Searches for text in the current buffer -- or for filenames matching
|
||||
a string in the current list in the file browser.
|
||||
Starts a forward search for text in the current buffer -- or for filenames
|
||||
matching a string in the current list in the file browser.
|
||||
.TP
|
||||
.B wherewas
|
||||
Starts a backward search for text in the current buffer.
|
||||
.TP
|
||||
.B searchagain
|
||||
Repeats the last search command without prompting.
|
||||
@@ -555,10 +562,10 @@ Moves the cursor to the beginning of the current or preceding block of text.
|
||||
.B nextblock
|
||||
Moves the cursor to the beginning of the next block of text.
|
||||
.TP
|
||||
.B prevpage
|
||||
.B pageup
|
||||
Goes up one screenful.
|
||||
.TP
|
||||
.B nextpage
|
||||
.B pagedown
|
||||
Goes down one screenful.
|
||||
.TP
|
||||
.B firstline
|
||||
@@ -599,6 +606,13 @@ Deletes the character under the cursor.
|
||||
.B backspace
|
||||
Deletes the character before the cursor.
|
||||
.TP
|
||||
.B recordmacro
|
||||
Starts the recording of keystrokes -- the keystrokes are stored
|
||||
as a macro. When already recording, the recording is stopped.
|
||||
.TP
|
||||
.B runmacro
|
||||
Replays the keystrokes of the last recorded macro.
|
||||
.TP
|
||||
.B undo
|
||||
Undoes the last performed text action (add text, delete text, etc).
|
||||
.TP
|
||||
@@ -660,7 +674,7 @@ When about to write a file, discard the current buffer without saving.
|
||||
(This function is bound by default only when option \fB\-\-tempfile\fR
|
||||
is in effect.)
|
||||
.TP
|
||||
.B tofiles
|
||||
.B browser
|
||||
Starts the file browser, allowing to select a file from a list.
|
||||
.TP
|
||||
.B gotodir
|
||||
@@ -785,7 +799,7 @@ for \fBunbind\fR it means all menus where the specified \fIkey\fR exists.
|
||||
.B /etc/nanorc
|
||||
System-wide configuration file.
|
||||
.TP
|
||||
.B ~/.nanorc
|
||||
.BR ~/.nanorc " or " \fI$XDG_CONFIG_HOME\fB/nano/nanorc " or " ~/.config/nano/nanorc
|
||||
Per-user configuration file.
|
||||
|
||||
.SH SEE ALSO
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 2.8.6" "July 2017"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.TH RNANO 1 "version 2.9.1" "November 2017"
|
||||
|
||||
.SH NAME
|
||||
rnano \- a restricted nano
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
## its end. For example, for the "brackets" option, ""')>]}" will match
|
||||
## ", ', ), >, ], and }.
|
||||
|
||||
## Silently ignore problems with unknown directives in the nanorc file.
|
||||
## Useful when your nanorc file might be read on systems with multiple
|
||||
## 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
|
||||
@@ -33,9 +28,6 @@
|
||||
## The directory to put unique backup files in.
|
||||
# set backupdir ""
|
||||
|
||||
## Do backwards searches by default.
|
||||
# set backwards
|
||||
|
||||
## Use bold text instead of reverse video text.
|
||||
# set boldtext
|
||||
|
||||
@@ -72,7 +64,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
|
||||
|
||||
@@ -168,7 +160,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.
|
||||
@@ -208,12 +200,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
|
||||
@@ -267,11 +261,8 @@
|
||||
## 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.
|
||||
## 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
|
||||
## The following two functions are not bound to any key by default.
|
||||
## You may wish to choose other keys than the ones suggested here.
|
||||
# bind M-B cutwordleft main
|
||||
# bind M-N cutwordright main
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ src/color.c
|
||||
src/files.c
|
||||
src/global.c
|
||||
src/help.c
|
||||
src/history.c
|
||||
src/nano.c
|
||||
src/prompt.c
|
||||
src/rcfile.c
|
||||
|
||||
1471
po/nano.pot
1471
po/nano.pot
File diff suppressed because it is too large
Load Diff
1348
po/pt_BR.po
1348
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1326
po/zh_CN.po
1326
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1321
po/zh_TW.po
1321
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,7 @@ nano_SOURCES = browser.c \
|
||||
files.c \
|
||||
global.c \
|
||||
help.c \
|
||||
history.c \
|
||||
move.c \
|
||||
nano.c \
|
||||
nano.h \
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* browser.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2015, 2016 Benno Schulenberg *
|
||||
* Copyright (C) 2015-2016 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -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
|
||||
|
||||
@@ -56,9 +55,6 @@ char *do_browser(char *path)
|
||||
DIR *dir;
|
||||
/* The directory whose contents we are showing. */
|
||||
|
||||
/* Don't show a cursor in the file list. */
|
||||
curs_set(0);
|
||||
|
||||
read_directory_contents:
|
||||
/* We come here when we refresh or select a new directory. */
|
||||
|
||||
@@ -107,20 +103,18 @@ char *do_browser(char *path)
|
||||
titlebar(path);
|
||||
|
||||
while (TRUE) {
|
||||
/* Make sure that the cursor is off. */
|
||||
curs_set(0);
|
||||
lastmessage = HUSH;
|
||||
|
||||
bottombars(MBROWSER);
|
||||
|
||||
/* Display (or redisplay) the file list if the list itself or
|
||||
* the selected file has changed. */
|
||||
if (old_selected != selected)
|
||||
if (old_selected != selected || ISSET(SHOW_CURSOR))
|
||||
browser_refresh();
|
||||
|
||||
old_selected = selected;
|
||||
|
||||
kbinput = get_kbinput(edit);
|
||||
kbinput = get_kbinput(edit, ISSET(SHOW_CURSOR));
|
||||
|
||||
#ifdef ENABLE_MOUSE
|
||||
if (kbinput == KEY_MOUSE) {
|
||||
@@ -171,12 +165,16 @@ char *do_browser(char *path)
|
||||
#else
|
||||
say_there_is_no_help();
|
||||
#endif
|
||||
} else if (func == do_search) {
|
||||
/* Search for a filename. */
|
||||
} else if (func == do_search_forward) {
|
||||
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--;
|
||||
@@ -227,10 +225,7 @@ char *do_browser(char *path)
|
||||
selected = filelist_len - 1;
|
||||
} else if (func == goto_dir_void) {
|
||||
/* Ask for the directory to go to. */
|
||||
int i = do_prompt(TRUE, FALSE, MGOTODIR, NULL,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
NULL,
|
||||
#endif
|
||||
int i = do_prompt(TRUE, FALSE, MGOTODIR, NULL, NULL,
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
browser_refresh, _("Go To Directory"));
|
||||
|
||||
@@ -248,12 +243,11 @@ char *do_browser(char *path)
|
||||
sprintf(path, "%s%s", present_path, answer);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
if (check_operating_dir(path, FALSE)) {
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
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;
|
||||
}
|
||||
@@ -279,13 +273,12 @@ char *do_browser(char *path)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
/* 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
|
||||
@@ -379,10 +372,10 @@ char *do_browse_from(const char *inpath)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_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
|
||||
|
||||
@@ -489,8 +482,11 @@ functionptrtype parse_browser_input(int *kbinput)
|
||||
case 'W':
|
||||
case 'w':
|
||||
case '/':
|
||||
return do_search;
|
||||
return do_search_forward;
|
||||
case 'N':
|
||||
#ifndef NANO_TINY
|
||||
return do_findprevious;
|
||||
#endif
|
||||
case 'n':
|
||||
return do_research;
|
||||
}
|
||||
@@ -539,7 +535,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 +607,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);
|
||||
|
||||
@@ -680,10 +676,7 @@ int filesearch_init(void)
|
||||
buf = mallocstrcpy(NULL, "");
|
||||
|
||||
/* This is now one simple call. It just does a lot. */
|
||||
input = do_prompt(FALSE, FALSE, MWHEREISFILE, NULL,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
&search_history,
|
||||
#endif
|
||||
input = do_prompt(FALSE, FALSE, MWHEREISFILE, NULL, &search_history,
|
||||
browser_refresh, "%s%s", _("Search"), buf);
|
||||
|
||||
/* Release buf now that we don't need it anymore. */
|
||||
@@ -700,8 +693,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 +715,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. */
|
||||
@@ -767,22 +765,23 @@ void do_filesearch(void)
|
||||
else
|
||||
last_search = mallocstrcpy(last_search, answer);
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
/* If answer is not empty, add the string to the search history list. */
|
||||
if (*answer != '\0')
|
||||
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. */
|
||||
|
||||
14
src/chars.c
14
src/chars.c
@@ -2,7 +2,7 @@
|
||||
* chars.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* Copyright (C) 2016-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
#include <wchar.h>
|
||||
@@ -397,7 +397,7 @@ size_t move_mbleft(const char *buf, size_t pos)
|
||||
}
|
||||
|
||||
/* Move forward again until we reach the original character,
|
||||
* so we know the length of its preceding the character. */
|
||||
* so we know the length of its preceding character. */
|
||||
while (before < pos) {
|
||||
char_len = parse_mbchar(buf + before, NULL, NULL);
|
||||
before += char_len;
|
||||
@@ -579,7 +579,7 @@ size_t mbstrnlen(const char *s, size_t maxlen)
|
||||
return strnlen(s, maxlen);
|
||||
}
|
||||
|
||||
#if !defined(NANO_TINY) || !defined(DISABLE_JUSTIFY)
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
|
||||
/* This function is equivalent to strchr() for multibyte strings. */
|
||||
char *mbstrchr(const char *s, const char *c)
|
||||
{
|
||||
@@ -620,7 +620,7 @@ char *mbstrchr(const char *s, const char *c)
|
||||
#endif
|
||||
return (char *) strchr(s, *c);
|
||||
}
|
||||
#endif /* !NANO_TINY || !DISABLE_JUSTIFY */
|
||||
#endif /* !NANO_TINY || ENABLE_JUSTIFY */
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* This function is equivalent to strpbrk() for multibyte strings. */
|
||||
@@ -686,7 +686,7 @@ char *mbrevstrpbrk(const char *head, const char *accept, const char *pointer)
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#if defined(ENABLE_NANORC) && (!defined(NANO_TINY) || !defined(DISABLE_JUSTIFY))
|
||||
#if defined(ENABLE_NANORC) && (!defined(NANO_TINY) || defined(ENABLE_JUSTIFY))
|
||||
/* Return TRUE if the string s contains one or more blank characters,
|
||||
* and FALSE otherwise. */
|
||||
bool has_blank_chars(const char *s)
|
||||
@@ -719,7 +719,7 @@ bool has_blank_mbchars(const char *s)
|
||||
#endif
|
||||
return has_blank_chars(s);
|
||||
}
|
||||
#endif /* ENABLE_NANORC && (!NANO_TINY || !DISABLE_JUSTIFY) */
|
||||
#endif /* ENABLE_NANORC && (!NANO_TINY || ENABLE_JUSTIFY) */
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* Return TRUE if wc is valid Unicode, and FALSE otherwise. */
|
||||
|
||||
50
src/color.c
50
src/color.c
@@ -2,7 +2,7 @@
|
||||
* color.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014, 2015, 2016, 2017 Benno Schulenberg *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -21,16 +21,23 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_MAGIC_H
|
||||
#include <magic.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
|
||||
/* For early versions of ncurses-6.0, use an additional A_PROTECT attribute
|
||||
* for all colors, in order to work around an ncurses miscoloring bug. */
|
||||
#if defined(NCURSES_VERSION_MAJOR) && (NCURSES_VERSION_MAJOR == 6) && \
|
||||
(NCURSES_VERSION_MINOR == 0) && (NCURSES_VERSION_PATCH < 20151017)
|
||||
#define A_BANDAID A_PROTECT
|
||||
#else
|
||||
#define A_BANDAID A_NORMAL
|
||||
#endif
|
||||
|
||||
/* Initialize the colors for nano's interface, and assign pair numbers
|
||||
* for the colors in each syntax. */
|
||||
@@ -61,8 +68,8 @@ void set_colorpairs(void)
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
init_pair(i + 1, foreground, background);
|
||||
interface_color_pair[i] =
|
||||
COLOR_PAIR(i + 1) | (bright ? A_BOLD : A_NORMAL);
|
||||
interface_color_pair[i] = COLOR_PAIR(i + 1) | A_BANDAID |
|
||||
(bright ? A_BOLD : A_NORMAL);
|
||||
} else {
|
||||
if (i != FUNCTION_TAG)
|
||||
interface_color_pair[i] = hilite_attribute;
|
||||
@@ -93,7 +100,7 @@ void set_colorpairs(void)
|
||||
else
|
||||
ink->pairnum = new_number++;
|
||||
|
||||
ink->attributes = COLOR_PAIR(ink->pairnum) |
|
||||
ink->attributes = COLOR_PAIR(ink->pairnum) | A_BANDAID |
|
||||
(ink->bright ? A_BOLD : A_NORMAL);
|
||||
}
|
||||
}
|
||||
@@ -127,9 +134,6 @@ void color_init(void)
|
||||
background = COLOR_BLACK;
|
||||
|
||||
init_pair(ink->pairnum, foreground, background);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "init_pair(): fg = %hd, bg = %hd\n", foreground, background);
|
||||
#endif
|
||||
}
|
||||
|
||||
have_palette = TRUE;
|
||||
@@ -177,13 +181,13 @@ void color_update(void)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sint == NULL)
|
||||
if (sint == NULL && !inhelp)
|
||||
statusline(ALERT, _("Unknown syntax name: %s"), syntaxstr);
|
||||
}
|
||||
|
||||
/* If no syntax-override string was specified, or it didn't match,
|
||||
* try finding a syntax based on the filename (extension). */
|
||||
if (sint == NULL) {
|
||||
if (sint == NULL && !inhelp) {
|
||||
char *reserved = charalloc(PATH_MAX + 1);
|
||||
char *currentdir = getcwd(reserved, PATH_MAX + 1);
|
||||
char *joinednames = charalloc(PATH_MAX + 1);
|
||||
@@ -212,10 +216,7 @@ void color_update(void)
|
||||
}
|
||||
|
||||
/* If the filename didn't match anything, try the first line. */
|
||||
if (sint == NULL) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "No result from file extension, trying headerline...\n");
|
||||
#endif
|
||||
if (sint == NULL && !inhelp) {
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (found_in_list(sint->headers, openfile->fileage->data))
|
||||
break;
|
||||
@@ -224,13 +225,11 @@ void color_update(void)
|
||||
|
||||
#ifdef HAVE_LIBMAGIC
|
||||
/* If we still don't have an answer, try using magic. */
|
||||
if (sint == NULL) {
|
||||
if (sint == NULL && !inhelp) {
|
||||
struct stat fileinfo;
|
||||
magic_t cookie = NULL;
|
||||
const char *magicstring = NULL;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "No result from headerline either, trying libmagic...\n");
|
||||
#endif
|
||||
|
||||
if (stat(openfile->filename, &fileinfo) == 0) {
|
||||
/* Open the magic database and get a diagnosis of the file. */
|
||||
cookie = magic_open(MAGIC_SYMLINK |
|
||||
@@ -245,9 +244,6 @@ void color_update(void)
|
||||
if (magicstring == NULL)
|
||||
statusline(ALERT, _("magic_file(%s) failed: %s"),
|
||||
openfile->filename, magic_error(cookie));
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Returned magic string is: %s\n", magicstring);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +261,7 @@ void color_update(void)
|
||||
#endif /* HAVE_LIBMAGIC */
|
||||
|
||||
/* If nothing at all matched, see if there is a default syntax. */
|
||||
if (sint == NULL) {
|
||||
if (sint == NULL && !inhelp) {
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
if (strcmp(sint->name, "default") == 0)
|
||||
break;
|
||||
@@ -437,4 +433,4 @@ void precalc_multicolorinfo(void)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !DISABLE_COLOR */
|
||||
#endif /* ENABLE_COLOR */
|
||||
|
||||
25
src/cut.c
25
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? */
|
||||
@@ -130,9 +129,6 @@ void do_cut_text(bool copy_text, bool cut_till_eof)
|
||||
if (!keep_cutbuffer) {
|
||||
free_filestruct(cutbuffer);
|
||||
cutbuffer = NULL;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Blew away cutbuffer =)\n");
|
||||
#endif
|
||||
/* Indicate that future cuts should add to the cutbuffer. */
|
||||
keep_cutbuffer = TRUE;
|
||||
}
|
||||
@@ -151,10 +147,10 @@ void do_cut_text(bool copy_text, bool cut_till_eof)
|
||||
if (cut_till_eof) {
|
||||
/* Move all text up to the end of the file into the cutbuffer. */
|
||||
cut_to_eof();
|
||||
} else if (openfile->mark_set) {
|
||||
} else if (openfile->mark) {
|
||||
/* Move the marked text to the cutbuffer, and turn the mark off. */
|
||||
cut_marked(&right_side_up);
|
||||
openfile->mark_set = FALSE;
|
||||
openfile->mark = NULL;
|
||||
} else if (ISSET(CUT_FROM_CURSOR))
|
||||
/* Move all text up to the end of the line into the cutbuffer. */
|
||||
cut_to_eol();
|
||||
@@ -192,7 +188,7 @@ void do_cut_text(bool copy_text, bool cut_till_eof)
|
||||
|
||||
refresh_needed = TRUE;
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
|
||||
@@ -220,7 +216,7 @@ void do_cut_text_void(void)
|
||||
void do_copy_text(void)
|
||||
{
|
||||
static struct filestruct *next_contiguous_line = NULL;
|
||||
bool mark_set = openfile->mark_set;
|
||||
bool mark_is_set = (openfile->mark != NULL);
|
||||
|
||||
/* Remember the current viewport and cursor position. */
|
||||
ssize_t is_edittop_lineno = openfile->edittop->lineno;
|
||||
@@ -228,16 +224,16 @@ void do_copy_text(void)
|
||||
ssize_t is_current_lineno = openfile->current->lineno;
|
||||
size_t is_current_x = openfile->current_x;
|
||||
|
||||
if (mark_set || openfile->current != next_contiguous_line)
|
||||
if (mark_is_set || openfile->current != next_contiguous_line)
|
||||
cutbuffer_reset();
|
||||
|
||||
do_cut_text(TRUE, FALSE);
|
||||
|
||||
/* If the mark was set, blow away the cutbuffer on the next copy. */
|
||||
next_contiguous_line = (mark_set ? NULL : openfile->current);
|
||||
next_contiguous_line = (mark_is_set ? NULL : openfile->current);
|
||||
|
||||
if (mark_set) {
|
||||
/* Restore the viewport and cursor position. */
|
||||
/* If the mark was set, restore the viewport and cursor position. */
|
||||
if (mark_is_set) {
|
||||
openfile->edittop = fsfromline(is_edittop_lineno);
|
||||
openfile->firstcolumn = is_firstcolumn;
|
||||
openfile->current = fsfromline(is_current_lineno);
|
||||
@@ -291,12 +287,9 @@ 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
|
||||
#ifdef ENABLE_COLOR
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
|
||||
|
||||
1072
src/files.c
1072
src/files.c
File diff suppressed because it is too large
Load Diff
755
src/global.c
755
src/global.c
File diff suppressed because it is too large
Load Diff
46
src/help.c
46
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
|
||||
|
||||
@@ -105,7 +103,7 @@ void do_help(void)
|
||||
int was_margin = margin;
|
||||
#endif
|
||||
ssize_t was_tabsize = tabsize;
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
char *was_syntax = syntaxstr;
|
||||
#endif
|
||||
char *saved_answer = (answer != NULL) ? strdup(answer) : NULL;
|
||||
@@ -151,7 +149,7 @@ void do_help(void)
|
||||
margin = 0;
|
||||
#endif
|
||||
tabsize = 8;
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
syntaxstr = "nanohelp";
|
||||
#endif
|
||||
curs_set(0);
|
||||
@@ -160,6 +158,7 @@ void do_help(void)
|
||||
help_init();
|
||||
inhelp = TRUE;
|
||||
location = 0;
|
||||
didfind = 0;
|
||||
|
||||
bottombars(MHELP);
|
||||
wnoutrefresh(bottomwin);
|
||||
@@ -183,9 +182,10 @@ void do_help(void)
|
||||
while (TRUE) {
|
||||
lastmessage = HUSH;
|
||||
focusing = TRUE;
|
||||
didfind = 0;
|
||||
|
||||
kbinput = get_kbinput(edit);
|
||||
/* Show the cursor when we searched and found something. */
|
||||
kbinput = get_kbinput(edit, didfind == 1);
|
||||
didfind = 0;
|
||||
|
||||
func = parse_help_input(&kbinput);
|
||||
|
||||
@@ -205,13 +205,16 @@ void do_help(void)
|
||||
do_first_line();
|
||||
} else if (func == do_last_line) {
|
||||
do_last_line();
|
||||
} else if (func == do_search) {
|
||||
} else if (func == do_search_forward) {
|
||||
do_search();
|
||||
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
|
||||
@@ -223,16 +226,12 @@ void do_help(void)
|
||||
} else if (func == do_exit) {
|
||||
/* Exit from the help viewer. */
|
||||
close_buffer();
|
||||
curs_set(0);
|
||||
break;
|
||||
} else
|
||||
unbound_key(kbinput);
|
||||
|
||||
/* If we searched and found something, let the cursor show it. */
|
||||
if (didfind == 1)
|
||||
curs_set(1);
|
||||
else
|
||||
curs_set(0);
|
||||
|
||||
currmenu = MHELP;
|
||||
edit_refresh();
|
||||
|
||||
location = 0;
|
||||
@@ -252,16 +251,14 @@ void do_help(void)
|
||||
margin = was_margin;
|
||||
#endif
|
||||
tabsize = was_tabsize;
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
syntaxstr = was_syntax;
|
||||
#endif
|
||||
|
||||
/* Switch back to the buffer we were invoked from. */
|
||||
switch_to_prev_buffer_void();
|
||||
switch_to_prev_buffer();
|
||||
|
||||
if (ISSET(NO_HELP)) {
|
||||
blank_bottombars();
|
||||
wnoutrefresh(bottomwin);
|
||||
currmenu = oldmenu;
|
||||
window_init();
|
||||
} else
|
||||
@@ -392,7 +389,7 @@ void help_init(void)
|
||||
htx[2] = NULL;
|
||||
}
|
||||
#endif /* ENABLE_BROWSER */
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
else if (currmenu == MSPELL) {
|
||||
htx[0] = N_("Spell Check Help Text\n\n "
|
||||
"The spell checker checks the spelling of all text in "
|
||||
@@ -406,7 +403,7 @@ void help_init(void)
|
||||
htx[1] = NULL;
|
||||
htx[2] = NULL;
|
||||
}
|
||||
#endif /* !DISABLE_SPELLER */
|
||||
#endif /* ENABLE_SPELLER */
|
||||
#ifndef NANO_TINY
|
||||
else if (currmenu == MEXTCMD) {
|
||||
htx[0] = N_("Execute Command Help Text\n\n "
|
||||
@@ -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;
|
||||
@@ -578,8 +575,11 @@ functionptrtype parse_help_input(int *kbinput)
|
||||
case 'W':
|
||||
case 'w':
|
||||
case '/':
|
||||
return do_search;
|
||||
return do_search_forward;
|
||||
case 'N':
|
||||
#ifndef NANO_TINY
|
||||
return do_findprevious;
|
||||
#endif
|
||||
case 'n':
|
||||
return do_research;
|
||||
case 'E':
|
||||
|
||||
616
src/history.c
Normal file
616
src/history.c
Normal file
@@ -0,0 +1,616 @@
|
||||
/**************************************************************************
|
||||
* history.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2003-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ENABLE_HISTORIES
|
||||
|
||||
#ifndef SEARCH_HISTORY
|
||||
#define SEARCH_HISTORY "search_history"
|
||||
#endif
|
||||
|
||||
#ifndef POSITION_HISTORY
|
||||
#define POSITION_HISTORY "filepos_history"
|
||||
#endif
|
||||
|
||||
static bool history_changed = FALSE;
|
||||
/* Whether any of the history lists has changed. */
|
||||
static struct stat stat_of_positions_file;
|
||||
/* The last-obtained stat information of the positions file. */
|
||||
static char *poshistname = NULL;
|
||||
/* The name of the positions-history file. */
|
||||
|
||||
/* Initialize the lists of historical search and replace strings
|
||||
* and the list of historical executed commands. */
|
||||
void history_init(void)
|
||||
{
|
||||
search_history = make_new_node(NULL);
|
||||
search_history->data = mallocstrcpy(NULL, "");
|
||||
searchtop = search_history;
|
||||
searchbot = search_history;
|
||||
|
||||
replace_history = make_new_node(NULL);
|
||||
replace_history->data = mallocstrcpy(NULL, "");
|
||||
replacetop = replace_history;
|
||||
replacebot = replace_history;
|
||||
|
||||
execute_history = make_new_node(NULL);
|
||||
execute_history->data = mallocstrcpy(NULL, "");
|
||||
executetop = execute_history;
|
||||
executebot = execute_history;
|
||||
}
|
||||
|
||||
/* Set the current position in the given history list to the bottom. */
|
||||
void history_reset(const filestruct *list)
|
||||
{
|
||||
if (list == search_history)
|
||||
search_history = searchbot;
|
||||
else if (list == replace_history)
|
||||
replace_history = replacebot;
|
||||
else if (list == execute_history)
|
||||
execute_history = executebot;
|
||||
}
|
||||
|
||||
/* Return from the history list that starts at start and ends at end
|
||||
* the first node that contains the first len characters of the given
|
||||
* text, or NULL if there is no such node. */
|
||||
filestruct *find_history(const filestruct *start, const filestruct *end,
|
||||
const char *text, size_t len)
|
||||
{
|
||||
const filestruct *item;
|
||||
|
||||
for (item = start; item != end->prev && item != NULL; item = item->prev) {
|
||||
if (strncmp(item->data, text, len) == 0)
|
||||
return (filestruct *)item;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Update a history list (the one in which item is the current position)
|
||||
* with a fresh string text. That is: add text, or move it to the end. */
|
||||
void update_history(filestruct **item, const char *text)
|
||||
{
|
||||
filestruct **htop = NULL, **hbot = NULL, *thesame;
|
||||
|
||||
if (*item == search_history) {
|
||||
htop = &searchtop;
|
||||
hbot = &searchbot;
|
||||
} else if (*item == replace_history) {
|
||||
htop = &replacetop;
|
||||
hbot = &replacebot;
|
||||
} else if (*item == execute_history) {
|
||||
htop = &executetop;
|
||||
hbot = &executebot;
|
||||
}
|
||||
|
||||
/* See if the string is already in the history. */
|
||||
thesame = find_history(*hbot, *htop, text, HIGHEST_POSITIVE);
|
||||
|
||||
/* If an identical string was found, delete that item. */
|
||||
if (thesame != NULL) {
|
||||
filestruct *after = thesame->next;
|
||||
|
||||
/* If the string is at the head of the list, move the head. */
|
||||
if (thesame == *htop)
|
||||
*htop = after;
|
||||
|
||||
unlink_node(thesame);
|
||||
renumber(after);
|
||||
}
|
||||
|
||||
/* If the history is full, delete the oldest item (the one at the
|
||||
* head of the list), to make room for a new item at the end. */
|
||||
if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
|
||||
filestruct *oldest = *htop;
|
||||
|
||||
*htop = (*htop)->next;
|
||||
unlink_node(oldest);
|
||||
renumber(*htop);
|
||||
}
|
||||
|
||||
/* Store the fresh string in the last item, then create a new item. */
|
||||
(*hbot)->data = mallocstrcpy((*hbot)->data, text);
|
||||
splice_node(*hbot, make_new_node(*hbot));
|
||||
*hbot = (*hbot)->next;
|
||||
(*hbot)->data = mallocstrcpy(NULL, "");
|
||||
|
||||
/* Indicate that the history needs to be saved on exit. */
|
||||
history_changed = TRUE;
|
||||
|
||||
/* Set the current position in the list to the bottom. */
|
||||
*item = *hbot;
|
||||
}
|
||||
|
||||
/* Move h to the string in the history list just before it, and return
|
||||
* that string. If there isn't one, don't move h and return NULL. */
|
||||
char *get_history_older(filestruct **h)
|
||||
{
|
||||
if ((*h)->prev == NULL)
|
||||
return NULL;
|
||||
|
||||
*h = (*h)->prev;
|
||||
|
||||
return (*h)->data;
|
||||
}
|
||||
|
||||
/* Move h to the string in the history list just after it, and return
|
||||
* that string. If there isn't one, don't move h and return NULL. */
|
||||
char *get_history_newer(filestruct **h)
|
||||
{
|
||||
if ((*h)->next == NULL)
|
||||
return NULL;
|
||||
|
||||
*h = (*h)->next;
|
||||
|
||||
return (*h)->data;
|
||||
}
|
||||
|
||||
/* More placeholders. */
|
||||
void get_history_newer_void(void)
|
||||
{
|
||||
;
|
||||
}
|
||||
void get_history_older_void(void)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TABCOMP
|
||||
/* Move h to the next string that's a tab completion of the string s,
|
||||
* looking at only the first len characters of s, and return that
|
||||
* string. If there isn't one, or if len is 0, don't move h and return
|
||||
* s. */
|
||||
char *get_history_completion(filestruct **h, char *s, size_t len)
|
||||
{
|
||||
if (len > 0) {
|
||||
filestruct *htop = NULL, *hbot = NULL, *p;
|
||||
|
||||
if (*h == search_history) {
|
||||
htop = searchtop;
|
||||
hbot = searchbot;
|
||||
} else if (*h == replace_history) {
|
||||
htop = replacetop;
|
||||
hbot = replacebot;
|
||||
} else if (*h == execute_history) {
|
||||
htop = executetop;
|
||||
hbot = executebot;
|
||||
}
|
||||
|
||||
/* Search the history list from the current position to the top
|
||||
* for a match of len characters. Skip over an exact match. */
|
||||
p = find_history((*h)->prev, htop, s, len);
|
||||
|
||||
while (p != NULL && strcmp(p->data, s) == 0)
|
||||
p = find_history(p->prev, htop, s, len);
|
||||
|
||||
if (p != NULL) {
|
||||
*h = p;
|
||||
return mallocstrcpy(s, (*h)->data);
|
||||
}
|
||||
|
||||
/* Search the history list from the bottom to the current position
|
||||
* for a match of len characters. Skip over an exact match. */
|
||||
p = find_history(hbot, *h, s, len);
|
||||
|
||||
while (p != NULL && strcmp(p->data, s) == 0)
|
||||
p = find_history(p->prev, *h, s, len);
|
||||
|
||||
if (p != NULL) {
|
||||
*h = p;
|
||||
return mallocstrcpy(s, (*h)->data);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're here, we didn't find a match, we didn't find an inexact
|
||||
* match, or len is 0. Return s. */
|
||||
return (char *)s;
|
||||
}
|
||||
#endif /* ENSABLE_TABCOMP */
|
||||
|
||||
void history_error(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
vfprintf(stderr, _(msg), ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, _("\nPress Enter to continue\n"));
|
||||
while (getchar() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
/* Check whether we have or could make a directory for history files. */
|
||||
bool have_statedir(void)
|
||||
{
|
||||
struct stat dirstat;
|
||||
const char *xdgdatadir;
|
||||
|
||||
get_homedir();
|
||||
|
||||
if (homedir != NULL) {
|
||||
statedir = concatenate(homedir, "/.nano/");
|
||||
|
||||
if (stat(statedir, &dirstat) == 0 && S_ISDIR(dirstat.st_mode)) {
|
||||
poshistname = concatenate(statedir, POSITION_HISTORY);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
free(statedir);
|
||||
xdgdatadir = getenv("XDG_DATA_HOME");
|
||||
|
||||
if (homedir == NULL && xdgdatadir == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (xdgdatadir != NULL)
|
||||
statedir = concatenate(xdgdatadir, "/nano/");
|
||||
else
|
||||
statedir = concatenate(homedir, "/.local/share/nano/");
|
||||
|
||||
if (stat(statedir, &dirstat) == -1) {
|
||||
if (xdgdatadir == NULL) {
|
||||
char *statepath = concatenate(homedir, "/.local");
|
||||
mkdir(statepath, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
free(statepath);
|
||||
statepath = concatenate(homedir, "/.local/share");
|
||||
mkdir(statepath, S_IRWXU);
|
||||
free(statepath);
|
||||
}
|
||||
if (mkdir(statedir, S_IRWXU) == -1) {
|
||||
history_error(N_("Unable to create directory %s: %s\n"
|
||||
"It is required for saving/loading "
|
||||
"search history or cursor positions.\n"),
|
||||
statedir, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
} else if (!S_ISDIR(dirstat.st_mode)) {
|
||||
history_error(N_("Path %s is not a directory and needs to be.\n"
|
||||
"Nano will be unable to load or save "
|
||||
"search history or cursor positions.\n"),
|
||||
statedir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
poshistname = concatenate(statedir, POSITION_HISTORY);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Load the histories for Search and Replace and Execute Command. */
|
||||
void load_history(void)
|
||||
{
|
||||
char *histname = concatenate(statedir, SEARCH_HISTORY);
|
||||
FILE *hisfile = fopen(histname, "rb");
|
||||
|
||||
if (hisfile == NULL) {
|
||||
if (errno != ENOENT) {
|
||||
/* When reading failed, don't save history when we quit. */
|
||||
UNSET(HISTORYLOG);
|
||||
history_error(N_("Error reading %s: %s"), histname,
|
||||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
/* Load the three history lists -- first search, then replace,
|
||||
* then execute -- from oldest entry to newest. Between two
|
||||
* lists there is an empty line. */
|
||||
filestruct **history = &search_history;
|
||||
char *line = NULL;
|
||||
size_t buf_len = 0;
|
||||
ssize_t read;
|
||||
|
||||
while ((read = getline(&line, &buf_len, hisfile)) > 0) {
|
||||
line[--read] = '\0';
|
||||
if (read > 0) {
|
||||
/* Encode any embedded NUL as 0x0A. */
|
||||
unsunder(line, read);
|
||||
update_history(history, line);
|
||||
} else if (history == &search_history)
|
||||
history = &replace_history;
|
||||
else
|
||||
history = &execute_history;
|
||||
}
|
||||
|
||||
fclose(hisfile);
|
||||
free(line);
|
||||
}
|
||||
|
||||
/* After reading them in, set the status of the lists to "unchanged". */
|
||||
history_changed = FALSE;
|
||||
|
||||
free(histname);
|
||||
}
|
||||
|
||||
/* Write the lines of a history list, starting at head, from oldest to newest,
|
||||
* to the given file. Return TRUE if writing succeeded, and FALSE otherwise. */
|
||||
bool write_list(const filestruct *head, FILE *hisfile)
|
||||
{
|
||||
const filestruct *item;
|
||||
|
||||
for (item = head; item != NULL; item = item->next) {
|
||||
size_t length = strlen(item->data);
|
||||
|
||||
/* Decode 0x0A bytes as embedded NULs. */
|
||||
sunder(item->data);
|
||||
|
||||
if (fwrite(item->data, sizeof(char), length, hisfile) < length)
|
||||
return FALSE;
|
||||
if (putc('\n', hisfile) == EOF)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Save the histories for Search and Replace and Execute Command. */
|
||||
void save_history(void)
|
||||
{
|
||||
char *histname;
|
||||
FILE *hisfile;
|
||||
|
||||
/* If the histories are unchanged, don't bother saving them. */
|
||||
if (!history_changed)
|
||||
return;
|
||||
|
||||
histname = concatenate(statedir, SEARCH_HISTORY);
|
||||
hisfile = fopen(histname, "wb");
|
||||
|
||||
if (hisfile == NULL)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), histname,
|
||||
strerror(errno));
|
||||
else {
|
||||
/* Don't allow others to read or write the history file. */
|
||||
chmod(histname, S_IRUSR | S_IWUSR);
|
||||
|
||||
if (!write_list(searchtop, hisfile) ||
|
||||
!write_list(replacetop, hisfile) ||
|
||||
!write_list(executetop, hisfile))
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), histname,
|
||||
strerror(errno));
|
||||
|
||||
fclose(hisfile);
|
||||
}
|
||||
|
||||
free(histname);
|
||||
}
|
||||
|
||||
/* Load the recorded cursor positions for files that were edited. */
|
||||
void load_poshistory(void)
|
||||
{
|
||||
FILE *hisfile = fopen(poshistname, "rb");
|
||||
|
||||
if (hisfile == NULL) {
|
||||
if (errno != ENOENT) {
|
||||
/* When reading failed, don't save history when we quit. */
|
||||
UNSET(POS_HISTORY);
|
||||
history_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
char *line = NULL, *lineptr, *xptr;
|
||||
size_t buf_len = 0;
|
||||
ssize_t read, count = 0;
|
||||
poshiststruct *record_ptr = NULL, *newrecord;
|
||||
|
||||
/* Read and parse each line, and store the extracted data. */
|
||||
while ((read = getline(&line, &buf_len, hisfile)) > 5) {
|
||||
/* Decode nulls as embedded newlines. */
|
||||
unsunder(line, read);
|
||||
|
||||
/* Find where the x index and line number are in the line. */
|
||||
xptr = revstrstr(line, " ", line + read - 3);
|
||||
if (xptr == NULL)
|
||||
continue;
|
||||
lineptr = revstrstr(line, " ", xptr - 2);
|
||||
if (lineptr == NULL)
|
||||
continue;
|
||||
|
||||
/* Now separate the three elements of the line. */
|
||||
*(xptr++) = '\0';
|
||||
*(lineptr++) = '\0';
|
||||
|
||||
/* Create a new position record. */
|
||||
newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct));
|
||||
newrecord->filename = mallocstrcpy(NULL, line);
|
||||
newrecord->lineno = atoi(lineptr);
|
||||
newrecord->xno = atoi(xptr);
|
||||
newrecord->next = NULL;
|
||||
|
||||
/* Add the record to the list. */
|
||||
if (position_history == NULL)
|
||||
position_history = newrecord;
|
||||
else
|
||||
record_ptr->next = newrecord;
|
||||
|
||||
record_ptr = newrecord;
|
||||
|
||||
/* Impose a limit, so the file will not grow indefinitely. */
|
||||
if (++count > 200) {
|
||||
poshiststruct *drop_record = position_history;
|
||||
|
||||
position_history = position_history->next;
|
||||
|
||||
free(drop_record->filename);
|
||||
free(drop_record);
|
||||
}
|
||||
}
|
||||
fclose(hisfile);
|
||||
free(line);
|
||||
|
||||
stat(poshistname, &stat_of_positions_file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the recorded cursor positions for files that were edited. */
|
||||
void save_poshistory(void)
|
||||
{
|
||||
poshiststruct *posptr;
|
||||
FILE *hisfile = fopen(poshistname, "wb");
|
||||
|
||||
if (hisfile == NULL)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"), poshistname, strerror(errno));
|
||||
else {
|
||||
/* Don't allow others to read or write the history file. */
|
||||
chmod(poshistname, S_IRUSR | S_IWUSR);
|
||||
|
||||
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
|
||||
char *path_and_place;
|
||||
size_t length;
|
||||
|
||||
/* Assume 20 decimal positions each for line and column number,
|
||||
* plus two spaces, plus the line feed, plus the null byte. */
|
||||
path_and_place = charalloc(strlen(posptr->filename) + 44);
|
||||
sprintf(path_and_place, "%s %zd %zd\n",
|
||||
posptr->filename, posptr->lineno, posptr->xno);
|
||||
length = strlen(path_and_place);
|
||||
|
||||
/* Encode newlines in filenames as nulls. */
|
||||
sunder(path_and_place);
|
||||
/* Restore the terminating newline. */
|
||||
path_and_place[length - 1] = '\n';
|
||||
|
||||
if (fwrite(path_and_place, sizeof(char), length, hisfile) < length)
|
||||
fprintf(stderr, _("Error writing %s: %s\n"),
|
||||
poshistname, strerror(errno));
|
||||
free(path_and_place);
|
||||
}
|
||||
fclose(hisfile);
|
||||
|
||||
stat(poshistname, &stat_of_positions_file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reload the position history file if it has been modified since last load. */
|
||||
void reload_positions_if_needed(void)
|
||||
{
|
||||
struct stat newstat;
|
||||
|
||||
stat(poshistname, &newstat);
|
||||
|
||||
if (newstat.st_mtime != stat_of_positions_file.st_mtime) {
|
||||
poshiststruct *ptr, *nextone;
|
||||
|
||||
for (ptr = position_history; ptr != NULL; ptr = nextone) {
|
||||
nextone = ptr->next;
|
||||
free(ptr->filename);
|
||||
free(ptr);
|
||||
}
|
||||
position_history = NULL;
|
||||
|
||||
load_poshistory();
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the recorded last file positions, given a filename, a line
|
||||
* and a column. If no entry is found, add a new one at the end. */
|
||||
void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos)
|
||||
{
|
||||
poshiststruct *posptr, *theone, *posprev = NULL;
|
||||
char *fullpath = get_full_path(filename);
|
||||
|
||||
if (fullpath == NULL || fullpath[strlen(fullpath) - 1] == '/' || inhelp) {
|
||||
free(fullpath);
|
||||
return;
|
||||
}
|
||||
|
||||
reload_positions_if_needed();
|
||||
|
||||
/* Look for a matching filename in the list. */
|
||||
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
|
||||
if (!strcmp(posptr->filename, fullpath))
|
||||
break;
|
||||
posprev = posptr;
|
||||
}
|
||||
|
||||
/* Don't record files that have the default cursor position. */
|
||||
if (lineno == 1 && xpos == 1) {
|
||||
if (posptr != NULL) {
|
||||
if (posprev == NULL)
|
||||
position_history = posptr->next;
|
||||
else
|
||||
posprev->next = posptr->next;
|
||||
free(posptr->filename);
|
||||
free(posptr);
|
||||
save_poshistory();
|
||||
}
|
||||
free(fullpath);
|
||||
return;
|
||||
}
|
||||
|
||||
theone = posptr;
|
||||
|
||||
/* If we didn't find it, make a new node; otherwise, if we're
|
||||
* not at the end, move the matching one to the end. */
|
||||
if (theone == NULL) {
|
||||
theone = (poshiststruct *)nmalloc(sizeof(poshiststruct));
|
||||
theone->filename = mallocstrcpy(NULL, fullpath);
|
||||
if (position_history == NULL)
|
||||
position_history = theone;
|
||||
else
|
||||
posprev->next = theone;
|
||||
} else if (posptr->next != NULL) {
|
||||
if (posprev == NULL)
|
||||
position_history = posptr->next;
|
||||
else
|
||||
posprev->next = posptr->next;
|
||||
while (posptr->next != NULL)
|
||||
posptr = posptr->next;
|
||||
posptr->next = theone;
|
||||
}
|
||||
|
||||
/* Store the last cursor position. */
|
||||
theone->lineno = lineno;
|
||||
theone->xno = xpos;
|
||||
theone->next = NULL;
|
||||
|
||||
free(fullpath);
|
||||
|
||||
save_poshistory();
|
||||
}
|
||||
|
||||
/* Check whether the given file matches an existing entry in the recorded
|
||||
* last file positions. If not, return FALSE. If yes, return TRUE and
|
||||
* set line and column to the retrieved values. */
|
||||
bool has_old_position(const char *file, ssize_t *line, ssize_t *column)
|
||||
{
|
||||
poshiststruct *posptr = position_history;
|
||||
char *fullpath = get_full_path(file);
|
||||
|
||||
if (fullpath == NULL)
|
||||
return FALSE;
|
||||
|
||||
reload_positions_if_needed();
|
||||
|
||||
while (posptr != NULL && strcmp(posptr->filename, fullpath) != 0)
|
||||
posptr = posptr->next;
|
||||
|
||||
free(fullpath);
|
||||
|
||||
if (posptr == NULL)
|
||||
return FALSE;
|
||||
|
||||
*line = posptr->lineno;
|
||||
*column = posptr->xno;
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* ENABLE_HISTORIES */
|
||||
332
src/move.c
332
src/move.c
@@ -2,7 +2,7 @@
|
||||
* move.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -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,8 +52,10 @@ void get_edge_and_target(size_t *leftedge, size_t *target_column)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
size_t shim = editwincols * (1 + (tabsize / editwincols));
|
||||
|
||||
*leftedge = leftedge_for(xplustabs(), openfile->current);
|
||||
*target_column = openfile->placewewant - *leftedge;
|
||||
*target_column = (openfile->placewewant + shim - *leftedge) % editwincols;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -63,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 target column has landed
|
||||
* on a tab, prevent the cursor from falling back a row when moving forward,
|
||||
* or from skipping a row when moving backward, by incrementing the index. */
|
||||
size_t proper_x(filestruct *line, size_t *leftedge, bool forward,
|
||||
size_t column, bool *shifted)
|
||||
{
|
||||
size_t index = actual_x(line->data, column);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP) && line->data[index] == '\t' &&
|
||||
((forward && strnlenpt(line->data, index) < *leftedge) ||
|
||||
(!forward && column / tabsize == (*leftedge - 1) / tabsize &&
|
||||
column / tabsize < (*leftedge + editwincols - 1) / tabsize))) {
|
||||
index++;
|
||||
|
||||
if (shifted != NULL)
|
||||
*shifted = TRUE;
|
||||
}
|
||||
|
||||
if (ISSET(SOFTWRAP))
|
||||
*leftedge = leftedge_for(strnlenpt(line->data, index), line);
|
||||
#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;
|
||||
size_t was_edge = *leftedge;
|
||||
|
||||
openfile->current_x = proper_x(openfile->current, leftedge, forward,
|
||||
actual_last_column(*leftedge, target), &shifted);
|
||||
|
||||
/* If the index was incremented, try going to the target column. */
|
||||
if (shifted || *leftedge < was_edge)
|
||||
openfile->current_x = proper_x(openfile->current, leftedge, forward,
|
||||
actual_last_column(*leftedge, target), &shifted);
|
||||
|
||||
openfile->placewewant = *leftedge + target;
|
||||
}
|
||||
|
||||
/* Move up nearly one screenful. */
|
||||
void do_page_up(void)
|
||||
{
|
||||
@@ -73,13 +119,11 @@ 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_x = actual_x(openfile->current->data,
|
||||
openfile->firstcolumn);
|
||||
leftedge = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
}
|
||||
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
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. */
|
||||
@@ -88,9 +132,7 @@ void do_page_up(void)
|
||||
return;
|
||||
}
|
||||
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
actual_last_column(leftedge, target_column));
|
||||
set_proper_index_and_pww(&leftedge, target_column, FALSE);
|
||||
|
||||
/* Move the viewport so that the cursor stays immobile, if possible. */
|
||||
adjust_viewport(STATIONARY);
|
||||
@@ -107,13 +149,11 @@ 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_x = actual_x(openfile->current->data,
|
||||
openfile->firstcolumn);
|
||||
leftedge = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
}
|
||||
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
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. */
|
||||
@@ -122,38 +162,30 @@ void do_page_down(void)
|
||||
return;
|
||||
}
|
||||
|
||||
openfile->placewewant = leftedge + target_column;
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
actual_last_column(leftedge, target_column));
|
||||
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||
|
||||
/* Move the viewport so that the cursor stays immobile, if possible. */
|
||||
adjust_viewport(STATIONARY);
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
/* Move to the beginning of the last beginning-of-paragraph line before the
|
||||
* current line. If update_screen is TRUE, update the screen afterwards. */
|
||||
void do_para_begin(bool update_screen)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
|
||||
if (openfile->current != openfile->fileage) {
|
||||
do
|
||||
openfile->current = openfile->current->prev;
|
||||
while (!begpar(openfile->current));
|
||||
}
|
||||
if (openfile->current != openfile->fileage)
|
||||
openfile->current = openfile->current->prev;
|
||||
|
||||
while (!begpar(openfile->current))
|
||||
openfile->current = openfile->current->prev;
|
||||
|
||||
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.
|
||||
@@ -183,7 +215,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. */
|
||||
@@ -191,9 +229,9 @@ void do_para_end_void(void)
|
||||
{
|
||||
do_para_end(TRUE);
|
||||
}
|
||||
#endif /* !DISABLE_JUSTIFY */
|
||||
#endif /* ENABLE_JUSTIFY */
|
||||
|
||||
/* Move to the preceding block of text in the file. */
|
||||
/* Move to the preceding block of text. */
|
||||
void do_prev_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
@@ -212,10 +250,10 @@ 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. */
|
||||
/* Move to the next block of text. */
|
||||
void do_next_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
@@ -230,12 +268,11 @@ 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
|
||||
* punctuation as part of a word. If update_screen is TRUE, update the
|
||||
* screen afterwards. */
|
||||
/* Move to the previous word. If allow_punct is TRUE, treat punctuation
|
||||
* as part of a word. When requested, update the screen afterwards. */
|
||||
void do_prev_word(bool allow_punct, bool update_screen)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
@@ -273,23 +310,13 @@ 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);
|
||||
}
|
||||
if (update_screen)
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
|
||||
/* 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. If allow_punct is TRUE, treat
|
||||
* punctuation as part of a word. If update_screen is TRUE, update the
|
||||
* screen afterwards. Return TRUE if we started on a word, and FALSE
|
||||
* otherwise. */
|
||||
/* Move to the next word. If allow_punct is TRUE, treat punctuation
|
||||
* as part of a word. When requested, update the screen afterwards.
|
||||
* Return TRUE if we started on a word, and FALSE otherwise. */
|
||||
bool do_next_word(bool allow_punct, bool update_screen)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
@@ -301,7 +328,7 @@ bool do_next_word(bool allow_punct, bool update_screen)
|
||||
while (TRUE) {
|
||||
/* If at the end of a line, move to the beginning of the next one. */
|
||||
if (openfile->current->data[openfile->current_x] == '\0') {
|
||||
/* If at the end of the file, stop. */
|
||||
/* When at end of file, stop. */
|
||||
if (openfile->current->next == NULL)
|
||||
break;
|
||||
openfile->current = openfile->current->next;
|
||||
@@ -322,15 +349,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)
|
||||
@@ -339,10 +371,9 @@ 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 = xplustabs();
|
||||
@@ -353,10 +384,11 @@ void do_home(bool be_clever)
|
||||
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
leftedge = leftedge_for(was_column, openfile->current);
|
||||
leftedge_x = actual_x(openfile->current->data, leftedge);
|
||||
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,7 +408,7 @@ 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 (openfile->current_x == leftedge_x && be_clever)
|
||||
if (openfile->current_x == leftedge_x)
|
||||
openfile->current_x = 0;
|
||||
else {
|
||||
openfile->current_x = leftedge_x;
|
||||
@@ -388,27 +420,20 @@ void do_home(bool be_clever)
|
||||
openfile->current_x = 0;
|
||||
|
||||
if (moved_off_chunk)
|
||||
openfile->placewewant = 0;
|
||||
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 (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 = xplustabs();
|
||||
@@ -434,7 +459,7 @@ void do_end(bool be_clever)
|
||||
|
||||
/* 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;
|
||||
@@ -450,25 +475,17 @@ void do_end(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 (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. */
|
||||
@@ -482,34 +499,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(BACKWARD, 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,
|
||||
actual_last_column(leftedge, target_column));
|
||||
|
||||
/* 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
|
||||
@@ -517,7 +515,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);
|
||||
@@ -526,28 +523,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(FORWARD, 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,
|
||||
actual_last_column(leftedge, target_column));
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
@@ -573,73 +563,31 @@ void do_scroll_down(void)
|
||||
/* Move left one character. */
|
||||
void do_left(void)
|
||||
{
|
||||
size_t was_column = xplustabs();
|
||||
#ifndef NANO_TINY
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_chunk = chunk_for(was_column, was_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 &&
|
||||
chunk_for(openfile->placewewant,
|
||||
openfile->current) != 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
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_chunk = chunk_for(was_column, was_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 &&
|
||||
chunk_for(openfile->placewewant,
|
||||
openfile->current) != 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);
|
||||
}
|
||||
|
||||
354
src/nano.c
354
src/nano.c
@@ -2,7 +2,7 @@
|
||||
* nano.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -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;
|
||||
@@ -73,7 +71,7 @@ filestruct *make_new_node(filestruct *prevnode)
|
||||
newnode->next = NULL;
|
||||
newnode->lineno = (prevnode != NULL) ? prevnode->lineno + 1 : 1;
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
newnode->multidata = NULL;
|
||||
#endif
|
||||
|
||||
@@ -90,7 +88,7 @@ filestruct *copy_node(const filestruct *src)
|
||||
dst->prev = src->prev;
|
||||
dst->lineno = src->lineno;
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
dst->multidata = NULL;
|
||||
#endif
|
||||
|
||||
@@ -130,7 +128,7 @@ void unlink_node(filestruct *fileptr)
|
||||
void delete_node(filestruct *fileptr)
|
||||
{
|
||||
free(fileptr->data);
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
free(fileptr->multidata);
|
||||
#endif
|
||||
free(fileptr);
|
||||
@@ -308,16 +306,14 @@ void extract_buffer(filestruct **file_top, filestruct **file_bot,
|
||||
edittop_inside = (openfile->edittop->lineno >= openfile->fileage->lineno &&
|
||||
openfile->edittop->lineno <= openfile->filebot->lineno);
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set) {
|
||||
mark_inside = (openfile->mark_begin->lineno >=
|
||||
openfile->fileage->lineno &&
|
||||
openfile->mark_begin->lineno <=
|
||||
openfile->filebot->lineno &&
|
||||
(openfile->mark_begin != openfile->fileage ||
|
||||
openfile->mark_begin_x >= top_x) &&
|
||||
(openfile->mark_begin != openfile->filebot ||
|
||||
openfile->mark_begin_x <= bot_x));
|
||||
same_line = (openfile->mark_begin == openfile->fileage);
|
||||
if (openfile->mark) {
|
||||
mark_inside = (openfile->mark->lineno >= openfile->fileage->lineno &&
|
||||
openfile->mark->lineno <= openfile->filebot->lineno &&
|
||||
(openfile->mark != openfile->fileage ||
|
||||
openfile->mark_x >= top_x) &&
|
||||
(openfile->mark != openfile->filebot ||
|
||||
openfile->mark_x <= bot_x));
|
||||
same_line = (openfile->mark == openfile->fileage);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -370,11 +366,11 @@ void extract_buffer(filestruct **file_top, filestruct **file_bot,
|
||||
openfile->current_x = top_x;
|
||||
#ifndef NANO_TINY
|
||||
if (mark_inside) {
|
||||
openfile->mark_begin = openfile->current;
|
||||
openfile->mark_begin_x = openfile->current_x;
|
||||
openfile->mark = openfile->current;
|
||||
openfile->mark_x = openfile->current_x;
|
||||
} else if (same_line)
|
||||
/* Update the pointer to this partially cut line. */
|
||||
openfile->mark_begin = openfile->current;
|
||||
openfile->mark = openfile->current;
|
||||
#endif
|
||||
|
||||
top_save = openfile->fileage;
|
||||
@@ -414,7 +410,7 @@ void ingraft_buffer(filestruct *somebuffer)
|
||||
#ifndef NANO_TINY
|
||||
/* Keep track of whether the mark begins inside the partition and
|
||||
* will need adjustment. */
|
||||
if (openfile->mark_set) {
|
||||
if (openfile->mark) {
|
||||
filestruct *top, *bot;
|
||||
size_t top_x, bot_x;
|
||||
|
||||
@@ -447,10 +443,10 @@ void ingraft_buffer(filestruct *somebuffer)
|
||||
* x coordinate for the change in the current line. */
|
||||
if (openfile->fileage == openfile->filebot) {
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set && single_line) {
|
||||
openfile->mark_begin = openfile->current;
|
||||
if (openfile->mark && single_line) {
|
||||
openfile->mark = openfile->current;
|
||||
if (!right_side_up)
|
||||
openfile->mark_begin_x += openfile->current_x;
|
||||
openfile->mark_x += openfile->current_x;
|
||||
}
|
||||
#endif
|
||||
/* When the pasted stuff contains no newline, adjust the cursor's
|
||||
@@ -458,12 +454,12 @@ void ingraft_buffer(filestruct *somebuffer)
|
||||
openfile->current_x += current_x_save;
|
||||
}
|
||||
#ifndef NANO_TINY
|
||||
else if (openfile->mark_set && single_line) {
|
||||
else if (openfile->mark && single_line) {
|
||||
if (right_side_up)
|
||||
openfile->mark_begin = openfile->fileage;
|
||||
openfile->mark = openfile->fileage;
|
||||
else {
|
||||
openfile->mark_begin = openfile->current;
|
||||
openfile->mark_begin_x += openfile->current_x - current_x_save;
|
||||
openfile->mark = openfile->current;
|
||||
openfile->mark_x += openfile->current_x - current_x_save;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -509,6 +505,9 @@ void unlink_opennode(openfilestruct *fileptr)
|
||||
{
|
||||
assert(fileptr != fileptr->prev && fileptr != fileptr->next);
|
||||
|
||||
if (fileptr == firstfile)
|
||||
firstfile = firstfile->next;
|
||||
|
||||
fileptr->prev->next = fileptr->next;
|
||||
fileptr->next->prev = fileptr->prev;
|
||||
|
||||
@@ -524,7 +523,7 @@ void delete_opennode(openfilestruct *fileptr)
|
||||
free(fileptr->current_stat);
|
||||
free(fileptr->lock_filename);
|
||||
/* Free the undo stack. */
|
||||
discard_until(NULL, fileptr);
|
||||
discard_until(NULL, fileptr, TRUE);
|
||||
#endif
|
||||
free(fileptr);
|
||||
}
|
||||
@@ -563,12 +562,12 @@ void finish(void)
|
||||
/* Restore the old terminal settings. */
|
||||
tcsetattr(0, TCSANOW, &oldterm);
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
/* If the user wants history persistence, write the relevant files. */
|
||||
if (ISSET(HISTORYLOG))
|
||||
save_history();
|
||||
if (ISSET(POS_HISTORY)) {
|
||||
update_poshistory(openfile->filename, openfile->current->lineno, xplustabs() + 1);
|
||||
save_poshistory();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -719,7 +718,7 @@ void window_init(void)
|
||||
keypad(bottomwin, TRUE);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
/* Set up the wrapping point, accounting for screen width when negative. */
|
||||
fill = wrap_at;
|
||||
if (fill <= 0)
|
||||
@@ -805,7 +804,7 @@ void usage(void)
|
||||
#ifndef NANO_TINY
|
||||
print_opt("-G", "--locking", N_("Use (vim-style) lock files"));
|
||||
#endif
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
if (!ISSET(RESTRICTED))
|
||||
print_opt("-H", "--historylog",
|
||||
N_("Log & read search/replace string history"));
|
||||
@@ -823,12 +822,12 @@ void usage(void)
|
||||
N_("Don't convert files from DOS/Mac format"));
|
||||
#endif
|
||||
print_opt("-O", "--morespace", N_("Use one more line for editing"));
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
if (!ISSET(RESTRICTED))
|
||||
print_opt("-P", "--positionlog",
|
||||
N_("Log & read location of cursor position"));
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
print_opt(_("-Q <str>"), _("--quotestr=<str>"), N_("Quoting string"));
|
||||
#endif
|
||||
if (!ISSET(RESTRICTED))
|
||||
@@ -846,7 +845,7 @@ void usage(void)
|
||||
print_opt(_("-X <str>"), _("--wordchars=<str>"),
|
||||
N_("Which other characters are word parts"));
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
if (!ISSET(RESTRICTED))
|
||||
print_opt(_("-Y <name>"), _("--syntax=<name>"),
|
||||
N_("Syntax definition to use for coloring"));
|
||||
@@ -873,21 +872,16 @@ void usage(void)
|
||||
print_opt("-m", "--mouse", N_("Enable the use of the mouse"));
|
||||
#endif
|
||||
print_opt("-n", "--noread", N_("Do not read the file (only write it)"));
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
print_opt(_("-o <dir>"), _("--operatingdir=<dir>"),
|
||||
N_("Set operating directory"));
|
||||
#endif
|
||||
print_opt("-p", "--preserve", N_("Preserve XON (^Q) and XOFF (^S) keys"));
|
||||
#ifdef ENABLE_NANORC
|
||||
if (!ISSET(RESTRICTED))
|
||||
print_opt("-q", "--quiet",
|
||||
N_("Silently ignore startup issues like rc file errors"));
|
||||
#endif
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
print_opt(_("-r <#cols>"), _("--fill=<#cols>"),
|
||||
N_("Set hard-wrapping point at column #cols"));
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
if (!ISSET(RESTRICTED))
|
||||
print_opt(_("-s <prog>"), _("--speller=<prog>"),
|
||||
N_("Enable alternate speller"));
|
||||
@@ -897,7 +891,7 @@ void usage(void)
|
||||
print_opt("-u", "--unix", N_("Save a file by default in Unix format"));
|
||||
#endif
|
||||
print_opt("-v", "--view", N_("View mode (read-only)"));
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
print_opt("-w", "--nowrap", N_("Don't hard-wrap long lines"));
|
||||
#endif
|
||||
print_opt("-x", "--nohelp", N_("Don't show the two help lines"));
|
||||
@@ -928,19 +922,19 @@ void version(void)
|
||||
#ifdef ENABLE_BROWSER
|
||||
printf(" --enable-browser");
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
printf(" --enable-color");
|
||||
#endif
|
||||
#ifndef DISABLE_EXTRA
|
||||
#ifdef ENABLE_EXTRA
|
||||
printf(" --enable-extra");
|
||||
#endif
|
||||
#ifdef ENABLE_HELP
|
||||
printf(" --enable-help");
|
||||
#endif
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
printf(" --enable-histories");
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
printf(" --enable-justify");
|
||||
#endif
|
||||
#ifdef HAVE_LIBMAGIC
|
||||
@@ -958,38 +952,38 @@ void version(void)
|
||||
#ifdef ENABLE_MULTIBUFFER
|
||||
printf(" --enable-multibuffer");
|
||||
#endif
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
printf(" --enable-operatingdir");
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
printf(" --enable-speller");
|
||||
#endif
|
||||
#ifdef ENABLE_TABCOMP
|
||||
printf(" --enable-tabcomp");
|
||||
#endif
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
printf(" --enable-wrapping");
|
||||
#endif
|
||||
#else /* !NANO_TINY */
|
||||
#ifndef ENABLE_BROWSER
|
||||
printf(" --disable-browser");
|
||||
#endif
|
||||
#ifdef DISABLE_COLOR
|
||||
#ifndef ENABLE_COLOR
|
||||
printf(" --disable-color");
|
||||
#endif
|
||||
#ifndef ENABLE_COMMENT
|
||||
printf(" --disable-comment");
|
||||
#endif
|
||||
#ifdef DISABLE_EXTRA
|
||||
#ifndef ENABLE_EXTRA
|
||||
printf(" --disable-extra");
|
||||
#endif
|
||||
#ifndef ENABLE_HELP
|
||||
printf(" --disable-help");
|
||||
#endif
|
||||
#ifdef DISABLE_HISTORIES
|
||||
#ifndef ENABLE_HISTORIES
|
||||
printf(" --disable-histories");
|
||||
#endif
|
||||
#ifdef DISABLE_JUSTIFY
|
||||
#ifndef ENABLE_JUSTIFY
|
||||
printf(" --disable-justify");
|
||||
#endif
|
||||
#ifndef HAVE_LIBMAGIC
|
||||
@@ -1007,10 +1001,10 @@ void version(void)
|
||||
#ifndef ENABLE_NANORC
|
||||
printf(" --disable-nanorc");
|
||||
#endif
|
||||
#ifdef DISABLE_OPERATINGDIR
|
||||
#ifndef ENABLE_OPERATINGDIR
|
||||
printf(" --disable-operatingdir");
|
||||
#endif
|
||||
#ifdef DISABLE_SPELLER
|
||||
#ifndef ENABLE_SPELLER
|
||||
printf(" --disable-speller");
|
||||
#endif
|
||||
#ifndef ENABLE_TABCOMP
|
||||
@@ -1019,7 +1013,7 @@ void version(void)
|
||||
#ifndef ENABLE_WORDCOMPLETION
|
||||
printf(" --disable-wordcomp");
|
||||
#endif
|
||||
#ifdef DISABLE_WRAPPING
|
||||
#ifndef ENABLE_WRAPPING
|
||||
printf(" --disable-wrapping");
|
||||
#endif
|
||||
#endif /* !NANO_TINY */
|
||||
@@ -1079,7 +1073,7 @@ void do_exit(void)
|
||||
|
||||
/* If the user chose not to save, or if the user chose to save and
|
||||
* the save succeeded, we're ready to exit. */
|
||||
if (i == 0 || (i == 1 && do_writeout(TRUE)))
|
||||
if (i == 0 || (i == 1 && do_writeout(TRUE, TRUE) > 0))
|
||||
close_and_go();
|
||||
else if (i != 1)
|
||||
statusbar(_("Cancelled"));
|
||||
@@ -1399,7 +1393,7 @@ void do_toggle(int flag)
|
||||
break;
|
||||
case WHITESPACE_DISPLAY:
|
||||
titlebar(NULL); /* Fall through. */
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
case NO_COLOR_SYNTAX:
|
||||
#endif
|
||||
refresh_needed = TRUE;
|
||||
@@ -1572,13 +1566,13 @@ int do_input(bool allow_funcs)
|
||||
/* The input buffer for actual characters. */
|
||||
static size_t depth = 0;
|
||||
/* The length of the input buffer. */
|
||||
bool preserve = FALSE;
|
||||
/* Whether to preserve the contents of the cutbuffer. */
|
||||
bool retain_cuts = FALSE;
|
||||
/* Whether to conserve the current contents of the cutbuffer. */
|
||||
const sc *s;
|
||||
bool have_shortcut;
|
||||
|
||||
/* Read in a keystroke. */
|
||||
input = get_kbinput(edit);
|
||||
/* Read in a keystroke, and show the cursor while waiting. */
|
||||
input = get_kbinput(edit, VISIBLE);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (input == KEY_WINCH)
|
||||
@@ -1591,7 +1585,7 @@ int do_input(bool allow_funcs)
|
||||
if (do_mouse() == 1)
|
||||
/* The click was on a shortcut -- read in the character
|
||||
* that it was converted into. */
|
||||
input = get_kbinput(edit);
|
||||
input = get_kbinput(edit, BLIND);
|
||||
else
|
||||
/* The click was invalid or has been handled -- get out. */
|
||||
return ERR;
|
||||
@@ -1629,8 +1623,8 @@ int do_input(bool allow_funcs)
|
||||
puddle[depth++] = (char)input;
|
||||
}
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set && openfile->kind_of_mark == SOFTMARK) {
|
||||
openfile->mark_set = FALSE;
|
||||
if (openfile->mark && openfile->kind_of_mark == SOFTMARK) {
|
||||
openfile->mark = NULL;
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
#endif
|
||||
@@ -1641,7 +1635,7 @@ int do_input(bool allow_funcs)
|
||||
* all available characters in the input puddle. Note that this
|
||||
* puddle will be empty if we're in view mode. */
|
||||
if (have_shortcut || get_key_buffer_len() == 0) {
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
/* If we got a shortcut or toggle, and it's not the shortcut
|
||||
* for verbatim input, turn off prepending of wrapped text. */
|
||||
if (have_shortcut && s->scfunc != do_verbatim_input)
|
||||
@@ -1678,7 +1672,7 @@ int do_input(bool allow_funcs)
|
||||
|| s->scfunc == do_copy_text || s->scfunc == do_cut_till_eof
|
||||
#endif
|
||||
)
|
||||
preserve = TRUE;
|
||||
retain_cuts = TRUE;
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
if (s->scfunc != complete_a_word)
|
||||
@@ -1688,16 +1682,18 @@ int do_input(bool allow_funcs)
|
||||
if (s->scfunc == do_toggle_void) {
|
||||
do_toggle(s->toggle);
|
||||
if (s->toggle != CUT_FROM_CURSOR)
|
||||
preserve = TRUE;
|
||||
retain_cuts = TRUE;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_x = openfile->current_x;
|
||||
|
||||
/* If Shifted movement occurs, set the mark. */
|
||||
if (shift_held && !openfile->mark_set) {
|
||||
openfile->mark_set = TRUE;
|
||||
openfile->mark_begin = openfile->current;
|
||||
openfile->mark_begin_x = openfile->current_x;
|
||||
if (shift_held && !openfile->mark) {
|
||||
openfile->mark = openfile->current;
|
||||
openfile->mark_x = openfile->current_x;
|
||||
openfile->kind_of_mark = SOFTMARK;
|
||||
}
|
||||
#endif
|
||||
@@ -1705,14 +1701,15 @@ int do_input(bool allow_funcs)
|
||||
s->scfunc();
|
||||
#ifndef NANO_TINY
|
||||
/* If Shiftless movement occurred, discard a soft mark. */
|
||||
if (openfile->mark_set && !shift_held &&
|
||||
openfile->kind_of_mark == SOFTMARK) {
|
||||
openfile->mark_set = FALSE;
|
||||
openfile->mark_begin = NULL;
|
||||
if (!shift_held && openfile->mark &&
|
||||
openfile->kind_of_mark == SOFTMARK &&
|
||||
(openfile->current_x != was_x ||
|
||||
openfile->current != was_current)) {
|
||||
openfile->mark = NULL;
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
if (f && !f->viewok)
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
@@ -1723,23 +1720,12 @@ int do_input(bool allow_funcs)
|
||||
|
||||
/* If we aren't cutting or copying text, and the key wasn't a toggle,
|
||||
* blow away the text in the cutbuffer upon the next cutting action. */
|
||||
if (!preserve)
|
||||
if (!retain_cuts)
|
||||
cutbuffer_reset();
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
void xon_complaint(void)
|
||||
{
|
||||
statusbar(_("XON ignored, mumble mumble"));
|
||||
}
|
||||
|
||||
void xoff_complaint(void)
|
||||
{
|
||||
statusbar(_("XOFF ignored, mumble mumble"));
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_MOUSE
|
||||
/* Handle a mouse click on the edit window or the shortcut list. */
|
||||
int do_mouse(void)
|
||||
@@ -1767,10 +1753,6 @@ int do_mouse(void)
|
||||
#endif
|
||||
leftedge = get_page_start(xplustabs());
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "mouse_row = %d, current_y = %ld\n", mouse_row, (long)openfile->current_y);
|
||||
#endif
|
||||
|
||||
/* Move current up or down to the row corresponding to mouse_row. */
|
||||
if (row_count < 0)
|
||||
go_back_chunks(-row_count, &openfile->current, &leftedge);
|
||||
@@ -1790,7 +1772,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. */
|
||||
@@ -1854,9 +1836,18 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
add_undo(ADD);
|
||||
|
||||
/* Note that current_x has not yet been incremented. */
|
||||
if (openfile->mark_set && openfile->current == openfile->mark_begin &&
|
||||
openfile->current_x < openfile->mark_begin_x)
|
||||
openfile->mark_begin_x += char_len;
|
||||
if (openfile->current == openfile->mark &&
|
||||
openfile->current_x < openfile->mark_x)
|
||||
openfile->mark_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;
|
||||
@@ -1865,7 +1856,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
update_undo(ADD);
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
/* If text gets wrapped, the edit window needs a refresh. */
|
||||
if (!ISSET(NO_WRAP) && do_wrap(openfile->current))
|
||||
refresh_needed = TRUE;
|
||||
@@ -1886,7 +1877,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
|
||||
@@ -1896,15 +1887,15 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int optchr;
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
int stdin_flags, optchr;
|
||||
#if defined(ENABLED_WRAPORJUSTIFY) && defined(ENABLE_NANORC)
|
||||
bool fill_used = FALSE;
|
||||
/* Was the fill option used on the command line? */
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#endif
|
||||
#ifdef ENABLE_WRAPPING
|
||||
bool forced_wrapping = FALSE;
|
||||
/* Should long lines be automatically hard wrapped? */
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENABLE_MULTIBUFFER
|
||||
bool is_multibuffer;
|
||||
/* The actual value of the multibuffer option, restored after
|
||||
@@ -1921,14 +1912,14 @@ int main(int argc, char **argv)
|
||||
{"rebindkeypad", 0, NULL, 'K'},
|
||||
{"nonewlines", 0, NULL, 'L'},
|
||||
{"morespace", 0, NULL, 'O'},
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
{"quotestr", 1, NULL, 'Q'},
|
||||
#endif
|
||||
{"restricted", 0, NULL, 'R'},
|
||||
{"tabsize", 1, NULL, 'T'},
|
||||
{"quickblank", 0, NULL, 'U'},
|
||||
{"version", 0, NULL, 'V'},
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
{"syntax", 1, NULL, 'Y'},
|
||||
#endif
|
||||
{"constantshow", 0, NULL, 'c'},
|
||||
@@ -1944,20 +1935,20 @@ int main(int argc, char **argv)
|
||||
{"mouse", 0, NULL, 'm'},
|
||||
#endif
|
||||
{"noread", 0, NULL, 'n'},
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
{"operatingdir", 1, NULL, 'o'},
|
||||
#endif
|
||||
{"preserve", 0, NULL, 'p'},
|
||||
{"quiet", 0, NULL, 'q'},
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
{"fill", 1, NULL, 'r'},
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
{"speller", 1, NULL, 's'},
|
||||
#endif
|
||||
{"tempfile", 0, NULL, 't'},
|
||||
{"view", 0, NULL, 'v'},
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
{"nowrap", 0, NULL, 'w'},
|
||||
#endif
|
||||
{"nohelp", 0, NULL, 'x'},
|
||||
@@ -1987,6 +1978,11 @@ int main(int argc, char **argv)
|
||||
/* Back up the terminal settings so that they can be restored. */
|
||||
tcgetattr(0, &oldterm);
|
||||
|
||||
/* Get the state of standard input and ensure it uses blocking mode. */
|
||||
stdin_flags = fcntl(0, F_GETFL, 0);
|
||||
if (stdin_flags != -1)
|
||||
fcntl(0, F_SETFL, stdin_flags & ~O_NONBLOCK);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* If setting the locale is successful and it uses UTF-8, we need
|
||||
* to use the multibyte functions for text processing. */
|
||||
@@ -2063,7 +2059,7 @@ int main(int argc, char **argv)
|
||||
SET(LOCKING);
|
||||
break;
|
||||
#endif
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
case 'H':
|
||||
SET(HISTORYLOG);
|
||||
break;
|
||||
@@ -2087,12 +2083,12 @@ int main(int argc, char **argv)
|
||||
case 'O':
|
||||
SET(MORE_SPACE);
|
||||
break;
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
case 'P':
|
||||
SET(POS_HISTORY);
|
||||
break;
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
case 'Q':
|
||||
quotestr = mallocstrcpy(quotestr, optarg);
|
||||
break;
|
||||
@@ -2126,7 +2122,7 @@ int main(int argc, char **argv)
|
||||
word_chars = mallocstrcpy(word_chars, optarg);
|
||||
break;
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
case 'Y':
|
||||
syntaxstr = mallocstrcpy(syntaxstr, optarg);
|
||||
break;
|
||||
@@ -2161,7 +2157,7 @@ int main(int argc, char **argv)
|
||||
case 'n':
|
||||
SET(NOREAD_MODE);
|
||||
break;
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
case 'o':
|
||||
operating_dir = mallocstrcpy(operating_dir, optarg);
|
||||
break;
|
||||
@@ -2170,24 +2166,25 @@ int main(int argc, char **argv)
|
||||
SET(PRESERVE);
|
||||
break;
|
||||
#ifdef ENABLE_NANORC
|
||||
case 'q':
|
||||
SET(QUIET);
|
||||
case 'q': /* obsolete, ignored */
|
||||
break;
|
||||
#endif
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
case 'r':
|
||||
if (!parse_num(optarg, &wrap_at)) {
|
||||
fprintf(stderr, _("Requested fill size \"%s\" is invalid"), optarg);
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifdef ENABLE_NANORC
|
||||
fill_used = TRUE;
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#endif
|
||||
#ifdef ENABLE_WRAPPING
|
||||
forced_wrapping = TRUE;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
case 's':
|
||||
alt_speller = mallocstrcpy(alt_speller, optarg);
|
||||
break;
|
||||
@@ -2203,7 +2200,7 @@ int main(int argc, char **argv)
|
||||
case 'v':
|
||||
SET(VIEW_MODE);
|
||||
break;
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
case 'w':
|
||||
SET(NO_WRAP);
|
||||
/* If both --fill and --nowrap are given on the
|
||||
@@ -2256,20 +2253,20 @@ int main(int argc, char **argv)
|
||||
#ifdef ENABLE_NANORC
|
||||
if (!no_rcfiles) {
|
||||
/* Back up the command-line options, then read the rcfile(s). */
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
char *operating_dir_cpy = operating_dir;
|
||||
#endif
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
ssize_t wrap_at_cpy = wrap_at;
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
char *backup_dir_cpy = backup_dir;
|
||||
char *word_chars_cpy = word_chars;
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
char *quotestr_cpy = quotestr;
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
char *alt_speller_cpy = alt_speller;
|
||||
#endif
|
||||
ssize_t tabsize_cpy = tabsize;
|
||||
@@ -2278,17 +2275,17 @@ int main(int argc, char **argv)
|
||||
|
||||
memcpy(flags_cpy, flags, sizeof(flags_cpy));
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
operating_dir = NULL;
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
backup_dir = NULL;
|
||||
word_chars = NULL;
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
quotestr = NULL;
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
alt_speller = NULL;
|
||||
#endif
|
||||
|
||||
@@ -2300,13 +2297,13 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
|
||||
/* If the backed-up command-line options have a value, restore them. */
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
if (operating_dir_cpy != NULL) {
|
||||
free(operating_dir);
|
||||
operating_dir = operating_dir_cpy;
|
||||
}
|
||||
#endif
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
if (fill_used)
|
||||
wrap_at = wrap_at_cpy;
|
||||
#endif
|
||||
@@ -2320,13 +2317,13 @@ int main(int argc, char **argv)
|
||||
word_chars = word_chars_cpy;
|
||||
}
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
if (quotestr_cpy != NULL) {
|
||||
free(quotestr);
|
||||
quotestr = quotestr_cpy;
|
||||
}
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
if (alt_speller_cpy != NULL) {
|
||||
free(alt_speller);
|
||||
alt_speller = alt_speller_cpy;
|
||||
@@ -2347,52 +2344,51 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
#endif /* ENABLE_NANORC */
|
||||
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
/* Override a "set nowrap" in an rcfile (or a --disable-wrapping-as-root)
|
||||
* if --fill was given on the command line and not undone by --nowrap. */
|
||||
if (forced_wrapping)
|
||||
UNSET(NO_WRAP);
|
||||
#endif
|
||||
|
||||
/* If we're using bold text instead of reverse video text, set it up
|
||||
* now. */
|
||||
/* If the user wants bold instead of reverse video for hilited text... */
|
||||
if (ISSET(BOLD_TEXT))
|
||||
hilite_attribute = A_BOLD;
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
/* Set up the search/replace history. */
|
||||
#ifdef ENABLE_HISTORIES
|
||||
/* Initialize the pointers for the Search/Replace/Execute histories. */
|
||||
history_init();
|
||||
/* Verify that the home directory and ~/.nano subdir exist. */
|
||||
if (ISSET(HISTORYLOG) || ISSET(POS_HISTORY)) {
|
||||
get_homedir();
|
||||
if (homedir == NULL || check_dotnano() == 0) {
|
||||
UNSET(HISTORYLOG);
|
||||
UNSET(POS_HISTORY);
|
||||
}
|
||||
|
||||
/* If we need history files, verify that we have a directory for them,
|
||||
* and when not, cancel the options. */
|
||||
if ((ISSET(HISTORYLOG) || ISSET(POS_HISTORY)) && !have_statedir()) {
|
||||
UNSET(HISTORYLOG);
|
||||
UNSET(POS_HISTORY);
|
||||
}
|
||||
|
||||
/* If the user wants history persistence, read the relevant files. */
|
||||
if (ISSET(HISTORYLOG))
|
||||
load_history();
|
||||
if (ISSET(POS_HISTORY))
|
||||
load_poshistory();
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
#endif /* ENABLE_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
|
||||
#ifdef ENABLE_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
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
/* If punct wasn't specified, set its default value. */
|
||||
if (punct == NULL)
|
||||
punct = mallocstrcpy(NULL, "!.?");
|
||||
@@ -2416,16 +2412,16 @@ int main(int argc, char **argv)
|
||||
quoteerr = charalloc(size);
|
||||
regerror(quoterc, "ereg, quoteerr, size);
|
||||
}
|
||||
#endif /* !DISABLE_JUSTIFY */
|
||||
#endif /* ENABLE_JUSTIFY */
|
||||
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
/* If we don't have an alternative spell checker after reading the
|
||||
* command line and/or rcfile(s), check $SPELL for one, as Pico
|
||||
* does (unless we're using restricted mode, in which case spell
|
||||
* checking is disabled, since it would allow reading from or
|
||||
* writing to files not specified on the command line). */
|
||||
if (!ISSET(RESTRICTED) && alt_speller == NULL) {
|
||||
char *spellenv = getenv("SPELL");
|
||||
const char *spellenv = getenv("SPELL");
|
||||
if (spellenv != NULL)
|
||||
alt_speller = mallocstrcpy(NULL, spellenv);
|
||||
}
|
||||
@@ -2457,6 +2453,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Initialize the search string. */
|
||||
last_search = mallocstrcpy(NULL, "");
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
|
||||
/* If tabsize wasn't specified, set its default value. */
|
||||
if (tabsize == -1)
|
||||
@@ -2480,6 +2477,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Create the three subwindows, based on the current screen dimensions. */
|
||||
window_init();
|
||||
curs_set(0);
|
||||
|
||||
editwincols = COLS;
|
||||
|
||||
@@ -2491,11 +2489,12 @@ int main(int argc, char **argv)
|
||||
mouse_init();
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
set_colorpairs();
|
||||
#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;
|
||||
@@ -2518,6 +2517,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);
|
||||
@@ -2561,7 +2565,7 @@ int main(int argc, char **argv)
|
||||
/* 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
|
||||
#ifdef ENABLE_HISTORIES
|
||||
else if (ISSET(POS_HISTORY) && openfile->filename[0] != '\0') {
|
||||
ssize_t savedline, savedcol;
|
||||
/* If edited before, restore the last cursor position. */
|
||||
@@ -2592,6 +2596,9 @@ int main(int argc, char **argv)
|
||||
|
||||
prepare_for_display();
|
||||
|
||||
if (rcfile_with_errors != NULL)
|
||||
statusline(ALERT, _("Mistakes in '%s'"), rcfile_with_errors);
|
||||
|
||||
while (TRUE) {
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
int needed_margin = digits(openfile->filebot->lineno) + 1;
|
||||
@@ -2626,14 +2633,11 @@ 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();
|
||||
|
||||
/* Make sure the cursor is visible. */
|
||||
curs_set(1);
|
||||
|
||||
focusing = TRUE;
|
||||
|
||||
/* Forget any earlier statusbar x position. */
|
||||
|
||||
89
src/nano.h
89
src/nano.h
@@ -2,7 +2,7 @@
|
||||
* nano.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -128,10 +128,20 @@
|
||||
#undef ENABLE_MOUSE
|
||||
#endif
|
||||
|
||||
#if defined(DISABLE_WRAPPING) && defined(DISABLE_JUSTIFY)
|
||||
#define DISABLE_WRAPJUSTIFY 1
|
||||
#if defined(ENABLE_WRAPPING) || defined(ENABLE_JUSTIFY)
|
||||
#define ENABLED_WRAPORJUSTIFY 1
|
||||
#endif
|
||||
|
||||
#define BACKWARD FALSE
|
||||
#define FORWARD TRUE
|
||||
|
||||
#define BLIND FALSE
|
||||
#define VISIBLE TRUE
|
||||
|
||||
#define JUSTFIND 0
|
||||
#define REPLACING 1
|
||||
#define INREGION 2
|
||||
|
||||
/* Enumeration types. */
|
||||
typedef enum {
|
||||
NIX_FILE, DOS_FILE, MAC_FILE
|
||||
@@ -149,19 +159,16 @@ typedef enum {
|
||||
SOFTMARK, HARDMARK
|
||||
} mark_type;
|
||||
|
||||
typedef enum {
|
||||
UPWARD, DOWNWARD
|
||||
} scroll_dir;
|
||||
|
||||
typedef enum {
|
||||
CENTERING, FLOWING, STATIONARY
|
||||
} update_type;
|
||||
|
||||
typedef enum {
|
||||
ADD, DEL, BACK, CUT, CUT_TO_EOF, REPLACE,
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
SPLIT_BEGIN, SPLIT_END,
|
||||
#endif
|
||||
INDENT, UNINDENT,
|
||||
#ifdef ENABLE_COMMENT
|
||||
COMMENT, UNCOMMENT, PREFLIGHT,
|
||||
#endif
|
||||
@@ -169,7 +176,7 @@ typedef enum {
|
||||
} undo_type;
|
||||
|
||||
/* Structure types. */
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
typedef struct colortype {
|
||||
short fg;
|
||||
/* This syntax's foreground color. */
|
||||
@@ -258,7 +265,7 @@ typedef struct lintstruct {
|
||||
/* Regex starts and ends within this line. */
|
||||
#define CWOULDBE (1<<6)
|
||||
/* An unpaired start match on or before this line. */
|
||||
#endif /* !DISABLE_COLOR */
|
||||
#endif /* ENABLE_COLOR */
|
||||
|
||||
/* More structure types. */
|
||||
typedef struct filestruct {
|
||||
@@ -270,7 +277,7 @@ typedef struct filestruct {
|
||||
/* Next node. */
|
||||
struct filestruct *prev;
|
||||
/* Previous node. */
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
short *multidata;
|
||||
/* Array of which multi-line regexes apply to this line. */
|
||||
#endif
|
||||
@@ -300,6 +307,8 @@ typedef struct undo_group {
|
||||
/* First line of group. */
|
||||
ssize_t bottom_line;
|
||||
/* Last line of group. */
|
||||
char **indentations;
|
||||
/* String data used to restore the affected lines; one per line. */
|
||||
struct undo_group *next;
|
||||
} undo_group;
|
||||
|
||||
@@ -334,7 +343,7 @@ typedef struct undo {
|
||||
} undo;
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
typedef struct poshiststruct {
|
||||
char *filename;
|
||||
/* The file. */
|
||||
@@ -373,26 +382,27 @@ typedef struct openfilestruct {
|
||||
struct stat *current_stat;
|
||||
/* The file's current stat information. */
|
||||
#ifndef NANO_TINY
|
||||
bool mark_set;
|
||||
/* Whether the mark is on in this file. */
|
||||
filestruct *mark_begin;
|
||||
/* The file's line where the mark is, if any. */
|
||||
size_t mark_begin_x;
|
||||
/* The file's mark's x-coordinate position, if any. */
|
||||
filestruct *mark;
|
||||
/* The line in the file where the mark is set; NULL if not set. */
|
||||
size_t mark_x;
|
||||
/* The mark's x position in the above line. */
|
||||
mark_type kind_of_mark;
|
||||
/* Whether this is a soft or a hard mark. */
|
||||
/* Whether it is a soft (with Shift) or a hard mark. */
|
||||
file_format fmt;
|
||||
/* The file's format. */
|
||||
/* The file's format -- Unix or DOS or Mac or mixed. */
|
||||
undo *undotop;
|
||||
/* The top of the undo list. */
|
||||
undo *current_undo;
|
||||
/* The current (i.e. next) level of undo. */
|
||||
undo_type last_action;
|
||||
/* The type of the last action the user performed. */
|
||||
bool pristine;
|
||||
/* Whether the undo stack still contains the first edit -- it won't
|
||||
* when a justification or spell check discarded the undo stack. */
|
||||
char *lock_filename;
|
||||
/* The path of the lockfile, if we created one. */
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
syntaxtype *syntax;
|
||||
/* The syntax struct for this file, if any. */
|
||||
colortype *colorstrings;
|
||||
@@ -469,6 +479,7 @@ enum
|
||||
{
|
||||
TITLE_BAR = 0,
|
||||
LINE_NUMBER,
|
||||
SELECTED_TEXT,
|
||||
STATUS_BAR,
|
||||
KEY_COMBO,
|
||||
FUNCTION_TAG,
|
||||
@@ -559,22 +570,26 @@ 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
|
||||
|
||||
122
src/prompt.c
122
src/prompt.c
@@ -21,8 +21,6 @@
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *prompt = NULL;
|
||||
@@ -50,7 +48,7 @@ int do_statusbar_input(bool *ran_func, bool *finished)
|
||||
*finished = FALSE;
|
||||
|
||||
/* Read in a character. */
|
||||
input = get_kbinput(bottomwin);
|
||||
input = get_kbinput(bottomwin, VISIBLE);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (input == KEY_WINCH)
|
||||
@@ -62,7 +60,7 @@ int do_statusbar_input(bool *ran_func, bool *finished)
|
||||
* shortcut character. */
|
||||
if (input == KEY_MOUSE) {
|
||||
if (do_statusbar_mouse() == 1)
|
||||
input = get_kbinput(bottomwin);
|
||||
input = get_kbinput(bottomwin, BLIND);
|
||||
else
|
||||
return ERR;
|
||||
}
|
||||
@@ -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. */
|
||||
@@ -145,7 +143,10 @@ int do_statusbar_input(bool *ran_func, bool *finished)
|
||||
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
|
||||
@@ -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
|
||||
@@ -421,10 +439,7 @@ void update_the_statusbar(void)
|
||||
|
||||
/* Get a string of input at the statusbar prompt. */
|
||||
functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
bool allow_files, bool *listed,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
filestruct **history_list,
|
||||
#endif
|
||||
bool allow_files, bool *listed, filestruct **history_list,
|
||||
void (*refresh_func)(void))
|
||||
{
|
||||
int kbinput = ERR;
|
||||
@@ -434,7 +449,7 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
bool tabbed = FALSE;
|
||||
/* Whether we've pressed Tab. */
|
||||
#endif
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
char *history = NULL;
|
||||
/* The current history string. */
|
||||
char *magichistory = NULL;
|
||||
@@ -447,21 +462,14 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
/* The length of the original string that we're trying to
|
||||
* tab complete, if any. */
|
||||
#endif
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
#endif /* ENABLE_HISTORIES */
|
||||
|
||||
if (statusbar_x > strlen(answer))
|
||||
statusbar_x = strlen(answer);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "acquiring: answer = \"%s\", statusbar_x = %lu\n", answer, (unsigned long) statusbar_x);
|
||||
#endif
|
||||
|
||||
update_the_statusbar();
|
||||
|
||||
while (TRUE) {
|
||||
/* Ensure the cursor is shown when waiting for input. */
|
||||
curs_set(1);
|
||||
|
||||
kbinput = do_statusbar_input(&ran_func, &finished);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -469,7 +477,7 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
if (kbinput == KEY_WINCH) {
|
||||
refresh_func();
|
||||
*actual = KEY_WINCH;
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
free(magichistory);
|
||||
#endif
|
||||
return NULL;
|
||||
@@ -486,7 +494,7 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
tabbed = FALSE;
|
||||
|
||||
if (func == do_tab) {
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
if (history_list != NULL) {
|
||||
if (last_kbinput != the_code_for(do_tab, TAB_CODE))
|
||||
complete_len = strlen(answer);
|
||||
@@ -503,7 +511,7 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
&tabbed, refresh_func, listed);
|
||||
} else
|
||||
#endif /* ENABLE_TABCOMP */
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
if (func == get_history_older_void) {
|
||||
if (history_list != NULL) {
|
||||
/* If we're scrolling up at the bottom of the history list
|
||||
@@ -549,7 +557,7 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
finished = FALSE;
|
||||
}
|
||||
} else
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
#endif /* ENABLE_HISTORIES */
|
||||
if (func == do_help_void) {
|
||||
/* This key has a shortcut-list entry when it's used to go to
|
||||
* the help browser or display a message indicating that help
|
||||
@@ -566,12 +574,12 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
|
||||
update_the_statusbar();
|
||||
|
||||
#if !defined(DISABLE_HISTORIES) && defined(ENABLE_TABCOMP)
|
||||
#if defined(ENABLE_HISTORIES) && defined(ENABLE_TABCOMP)
|
||||
last_kbinput = kbinput;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
/* Set the current position in the history list to the bottom. */
|
||||
if (history_list != NULL) {
|
||||
history_reset(*history_list);
|
||||
@@ -596,10 +604,7 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
* interpreted. The allow_files parameter indicates whether we should
|
||||
* allow all files (as opposed to just directories) to be tab completed. */
|
||||
int do_prompt(bool allow_tabs, bool allow_files,
|
||||
int menu, const char *curranswer,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
filestruct **history_list,
|
||||
#endif
|
||||
int menu, const char *curranswer, filestruct **history_list,
|
||||
void (*refresh_func)(void), const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@@ -625,11 +630,7 @@ int do_prompt(bool allow_tabs, bool allow_files,
|
||||
prompt[actual_x(prompt, (COLS < 5) ? 0 : COLS - 5)] = '\0';
|
||||
|
||||
func = acquire_an_answer(&retval, allow_tabs, allow_files, &listed,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
history_list,
|
||||
#endif
|
||||
refresh_func);
|
||||
|
||||
history_list, refresh_func);
|
||||
free(prompt);
|
||||
prompt = saved_prompt;
|
||||
|
||||
@@ -653,10 +654,6 @@ int do_prompt(bool allow_tabs, bool allow_files,
|
||||
blank_statusbar();
|
||||
wnoutrefresh(bottomwin);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "answer = \"%s\"\n", answer);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_TABCOMP
|
||||
/* If we've done tab completion, there might still be a list of
|
||||
* filename matches on the edit window. Clear them off. */
|
||||
@@ -676,7 +673,7 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
char *message = display_string(msg, 0, COLS, FALSE);
|
||||
|
||||
/* TRANSLATORS: For the next three strings, if possible, specify
|
||||
* the single-byte shortcuts for both your language and English.
|
||||
* the single-byte letters for both your language and English.
|
||||
* For example, in French: "OoYy", for both "Oui" and "Yes". */
|
||||
const char *yesstr = _("Yy");
|
||||
const char *nostr = _("Nn");
|
||||
@@ -688,10 +685,9 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
|
||||
while (response == -2) {
|
||||
int kbinput;
|
||||
functionptrtype func;
|
||||
|
||||
if (!ISSET(NO_HELP)) {
|
||||
char shortstr[3];
|
||||
char shortstr[MAXCHARLEN + 2];
|
||||
/* Temporary string for (translated) " Y", " N" and " A". */
|
||||
|
||||
if (COLS < 32)
|
||||
@@ -703,20 +699,20 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
/* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */
|
||||
sprintf(shortstr, " %c", yesstr[0]);
|
||||
wmove(bottomwin, 1, 0);
|
||||
onekey(shortstr, _("Yes"), width);
|
||||
post_one_key(shortstr, _("Yes"), width);
|
||||
|
||||
if (all) {
|
||||
shortstr[1] = allstr[0];
|
||||
wmove(bottomwin, 1, width);
|
||||
onekey(shortstr, _("All"), width);
|
||||
post_one_key(shortstr, _("All"), width);
|
||||
}
|
||||
|
||||
shortstr[1] = nostr[0];
|
||||
wmove(bottomwin, 2, 0);
|
||||
onekey(shortstr, _("No"), width);
|
||||
post_one_key(shortstr, _("No"), width);
|
||||
|
||||
wmove(bottomwin, 2, width);
|
||||
onekey("^C", _("Cancel"), width);
|
||||
post_one_key("^C", _("Cancel"), width);
|
||||
}
|
||||
|
||||
/* Color the statusbar over its full width and display the question. */
|
||||
@@ -726,17 +722,19 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
wnoutrefresh(bottomwin);
|
||||
|
||||
/* When not replacing, show the cursor. */
|
||||
if (!all)
|
||||
curs_set(1);
|
||||
|
||||
currmenu = MYESNO;
|
||||
kbinput = get_kbinput(bottomwin);
|
||||
|
||||
func = func_from_key(&kbinput);
|
||||
/* When not replacing, show the cursor while waiting for a key. */
|
||||
kbinput = get_kbinput(bottomwin, !all);
|
||||
|
||||
if (func == do_cancel)
|
||||
/* See if the pressed key is in the Yes, No, or All strings. */
|
||||
if (strchr(yesstr, kbinput) != NULL)
|
||||
response = 1;
|
||||
else if (strchr(nostr, kbinput) != NULL)
|
||||
response = 0;
|
||||
else if (all && strchr(allstr, kbinput) != NULL)
|
||||
response = 2;
|
||||
else if (func_from_key(&kbinput) == do_cancel)
|
||||
response = -1;
|
||||
#ifdef ENABLE_MOUSE
|
||||
else if (kbinput == KEY_MOUSE) {
|
||||
@@ -746,14 +744,9 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE) &&
|
||||
mouse_x < (width * 2) && mouse_y > 0) {
|
||||
int x = mouse_x / width;
|
||||
/* The x-coordinate among the Yes/No/All shortcuts. */
|
||||
int y = mouse_y - 1;
|
||||
/* The y-coordinate among the Yes/No/All shortcuts. */
|
||||
|
||||
assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
|
||||
|
||||
/* x == 0 means they clicked Yes or No.
|
||||
* y == 0 means Yes or All. */
|
||||
/* x == 0 means Yes or No, y == 0 means Yes or All. */
|
||||
response = -2 * x * y + x - y + 1;
|
||||
|
||||
if (response == 2 && !all)
|
||||
@@ -761,15 +754,6 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_MOUSE */
|
||||
else {
|
||||
/* Look for the kbinput in the Yes, No (and All) strings. */
|
||||
if (strchr(yesstr, kbinput) != NULL)
|
||||
response = 1;
|
||||
else if (strchr(nostr, kbinput) != NULL)
|
||||
response = 0;
|
||||
else if (all && strchr(allstr, kbinput) != NULL)
|
||||
response = 2;
|
||||
}
|
||||
}
|
||||
|
||||
free(message);
|
||||
|
||||
187
src/proto.h
187
src/proto.h
@@ -43,10 +43,6 @@ extern bool as_an_at;
|
||||
extern int margin;
|
||||
extern int editwincols;
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
extern bool have_palette;
|
||||
#endif
|
||||
|
||||
extern bool suppress_cursorpos;
|
||||
|
||||
extern message_type lastmessage;
|
||||
@@ -56,6 +52,8 @@ extern filestruct *pletion_line;
|
||||
extern bool inhelp;
|
||||
extern char *title;
|
||||
|
||||
extern bool more_than_one;
|
||||
|
||||
extern int didfind;
|
||||
|
||||
extern int controlleft;
|
||||
@@ -71,13 +69,17 @@ 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;
|
||||
extern int shiftaltdown;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
extern ssize_t fill;
|
||||
extern ssize_t wrap_at;
|
||||
#endif
|
||||
@@ -96,12 +98,10 @@ extern filestruct *cutbuffer;
|
||||
extern filestruct *cutbottom;
|
||||
extern partition *filepart;
|
||||
extern openfilestruct *openfile;
|
||||
extern openfilestruct *firstfile;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
extern char *matchbrackets;
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
extern char *whitespace;
|
||||
extern int whitespace_len[2];
|
||||
#endif
|
||||
@@ -109,7 +109,7 @@ extern int whitespace_len[2];
|
||||
extern const char *exit_tag;
|
||||
extern const char *close_tag;
|
||||
extern const char *uncut_tag;
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
extern const char *unjust_tag;
|
||||
extern char *punct;
|
||||
extern char *brackets;
|
||||
@@ -117,7 +117,7 @@ extern char *quotestr;
|
||||
extern regex_t quotereg;
|
||||
extern int quoterc;
|
||||
extern char *quoteerr;
|
||||
#endif /* !DISABLE_JUSTIFY */
|
||||
#endif
|
||||
|
||||
extern char *word_chars;
|
||||
|
||||
@@ -130,18 +130,18 @@ extern char *backup_dir;
|
||||
extern const char *locking_prefix;
|
||||
extern const char *locking_suffix;
|
||||
#endif
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
extern char *operating_dir;
|
||||
extern char *full_operating_dir;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
extern char *alt_speller;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
extern syntaxtype *syntaxes;
|
||||
extern char *syntaxstr;
|
||||
extern bool have_palette;
|
||||
#endif
|
||||
|
||||
extern bool refresh_needed;
|
||||
@@ -152,13 +152,16 @@ extern subnfunc *allfuncs;
|
||||
extern subnfunc *exitfunc;
|
||||
extern subnfunc *uncutfunc;
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
extern filestruct *search_history;
|
||||
extern filestruct *searchage;
|
||||
extern filestruct *searchbot;
|
||||
extern filestruct *replace_history;
|
||||
extern filestruct *replaceage;
|
||||
extern filestruct *execute_history;
|
||||
#ifdef ENABLE_HISTORIES
|
||||
extern filestruct *searchtop;
|
||||
extern filestruct *searchbot;
|
||||
extern filestruct *replacetop;
|
||||
extern filestruct *replacebot;
|
||||
extern filestruct *executetop;
|
||||
extern filestruct *executebot;
|
||||
extern poshiststruct *position_history;
|
||||
#endif
|
||||
|
||||
@@ -166,12 +169,14 @@ extern regex_t search_regexp;
|
||||
extern regmatch_t regmatches[10];
|
||||
|
||||
extern int hilite_attribute;
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
extern char* specified_color_combo[NUMBER_OF_ELEMENTS];
|
||||
#endif
|
||||
extern int interface_color_pair[NUMBER_OF_ELEMENTS];
|
||||
|
||||
extern char *homedir;
|
||||
extern char *statedir;
|
||||
extern char *rcfile_with_errors;
|
||||
|
||||
typedef void (*functionptrtype)(void);
|
||||
|
||||
@@ -183,7 +188,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);
|
||||
@@ -217,7 +222,7 @@ char *mbrevstrcasestr(const char *haystack, const char *needle,
|
||||
const char *index);
|
||||
size_t mbstrlen(const char *s);
|
||||
size_t mbstrnlen(const char *s, size_t maxlen);
|
||||
#if !defined(NANO_TINY) || !defined(DISABLE_JUSTIFY)
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
|
||||
char *mbstrchr(const char *s, const char *c);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
@@ -225,7 +230,7 @@ char *mbstrpbrk(const char *s, const char *accept);
|
||||
char *revstrpbrk(const char *head, const char *accept, const char *index);
|
||||
char *mbrevstrpbrk(const char *head, const char *accept, const char *index);
|
||||
#endif
|
||||
#if defined(ENABLE_NANORC) && (!defined(NANO_TINY) || !defined(DISABLE_JUSTIFY))
|
||||
#if defined(ENABLE_NANORC) && (!defined(NANO_TINY) || defined(ENABLE_JUSTIFY))
|
||||
bool has_blank_mbchars(const char *s);
|
||||
#endif
|
||||
#ifdef ENABLE_UTF8
|
||||
@@ -236,7 +241,7 @@ bool is_valid_mbstring(const char *s);
|
||||
#endif
|
||||
|
||||
/* Most functions in color.c. */
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
void set_colorpairs(void);
|
||||
void color_init(void);
|
||||
void color_update(void);
|
||||
@@ -262,7 +267,7 @@ void do_uncut_text(void);
|
||||
/* Most functions in files.c. */
|
||||
void initialize_buffer_text(void);
|
||||
bool open_buffer(const char *filename, bool undoable);
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
void replace_buffer(const char *filename);
|
||||
#ifndef NANO_TINY
|
||||
void replace_marked_buffer(const char *filename, filestruct *top, size_t top_x,
|
||||
@@ -271,8 +276,8 @@ void replace_marked_buffer(const char *filename, filestruct *top, size_t top_x,
|
||||
#endif
|
||||
void prepare_for_display(void);
|
||||
#ifdef ENABLE_MULTIBUFFER
|
||||
void switch_to_prev_buffer_void(void);
|
||||
void switch_to_next_buffer_void(void);
|
||||
void switch_to_prev_buffer(void);
|
||||
void switch_to_next_buffer(void);
|
||||
bool close_buffer(void);
|
||||
#endif
|
||||
void read_file(FILE *f, int fd, const char *filename, bool undoable,
|
||||
@@ -282,9 +287,9 @@ char *get_next_filename(const char *name, const char *suffix);
|
||||
void do_insertfile_void(void);
|
||||
char *get_full_path(const char *origpath);
|
||||
char *safe_tempfile(FILE **f);
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_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);
|
||||
@@ -298,40 +303,28 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
kind_of_writing_type method);
|
||||
#endif
|
||||
int do_writeout(bool exiting);
|
||||
int do_writeout(bool exiting, bool withprompt);
|
||||
void do_writeout_void(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_savefile(void);
|
||||
#endif
|
||||
char *real_dir_from_tilde(const char *buf);
|
||||
#if defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
||||
int diralphasort(const void *va, const void *vb);
|
||||
void free_chararray(char **array, size_t len);
|
||||
#endif
|
||||
#ifdef ENABLE_TABCOMP
|
||||
char *input_tab(char *buf, bool allow_files, size_t *place,
|
||||
bool *lastwastab, void (*refresh_func)(void), bool *listed);
|
||||
#endif
|
||||
const char *tail(const char *path);
|
||||
#ifndef DISABLE_HISTORIES
|
||||
void load_history(void);
|
||||
void save_history(void);
|
||||
int check_dotnano(void);
|
||||
void load_poshistory(void);
|
||||
void save_poshistory(void);
|
||||
void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos);
|
||||
bool has_old_position(const char *file, ssize_t *line, ssize_t *column);
|
||||
#endif
|
||||
|
||||
/* Some functions in global.c. */
|
||||
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);
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
void set_lint_or_format_shortcuts(void);
|
||||
void set_spell_shortcuts(void);
|
||||
#endif
|
||||
@@ -353,30 +346,48 @@ size_t help_line_len(const char *ptr);
|
||||
#endif
|
||||
void do_help_void(void);
|
||||
|
||||
/* All functions in move.c. */
|
||||
/* Most functions in history.c. */
|
||||
#ifdef ENABLE_HISTORIES
|
||||
void history_init(void);
|
||||
void history_reset(const filestruct *h);
|
||||
void update_history(filestruct **h, const char *s);
|
||||
char *get_history_older(filestruct **h);
|
||||
char *get_history_newer(filestruct **h);
|
||||
void get_history_older_void(void);
|
||||
void get_history_newer_void(void);
|
||||
#ifdef ENABLE_TABCOMP
|
||||
char *get_history_completion(filestruct **h, char *s, size_t len);
|
||||
#endif
|
||||
bool have_statedir(void);
|
||||
void load_history(void);
|
||||
void save_history(void);
|
||||
void load_poshistory(void);
|
||||
void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos);
|
||||
bool has_old_position(const char *file, ssize_t *line, ssize_t *column);
|
||||
#endif
|
||||
|
||||
/* Most functions in move.c. */
|
||||
void do_first_line(void);
|
||||
void do_last_line(void);
|
||||
void do_page_up(void);
|
||||
void do_page_down(void);
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_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 +459,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);
|
||||
@@ -458,16 +470,13 @@ size_t get_statusbar_page_start(size_t start_col, size_t column);
|
||||
void reinit_statusbar_x(void);
|
||||
void update_the_statusbar(void);
|
||||
int do_prompt(bool allow_tabs, bool allow_files,
|
||||
int menu, const char *curranswer,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
filestruct **history_list,
|
||||
#endif
|
||||
int menu, const char *curranswer, filestruct **history_list,
|
||||
void (*refresh_func)(void), const char *msg, ...);
|
||||
int do_yesno_prompt(bool all, const char *msg);
|
||||
|
||||
/* Most functions in rcfile.c. */
|
||||
#ifdef ENABLE_NANORC
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright);
|
||||
void grab_and_store(const char *kind, char *ptr, regexlisttype **storage);
|
||||
#endif
|
||||
@@ -478,9 +487,11 @@ void do_rcfiles(void);
|
||||
/* Most functions in search.c. */
|
||||
void not_found_msg(const char *str);
|
||||
void search_replace_abort(void);
|
||||
int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x);
|
||||
void do_search(void);
|
||||
void do_search_forward(void);
|
||||
void do_search_backward(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_findprevious(void);
|
||||
void do_findnext(void);
|
||||
@@ -496,19 +507,6 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
void do_gotolinecolumn_void(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_find_bracket(void);
|
||||
#ifdef ENABLE_TABCOMP
|
||||
char *get_history_completion(filestruct **h, char *s, size_t len);
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DISABLE_HISTORIES
|
||||
bool history_has_changed(void);
|
||||
void history_init(void);
|
||||
void history_reset(const filestruct *h);
|
||||
void update_history(filestruct **h, const char *s);
|
||||
char *get_history_older(filestruct **h);
|
||||
char *get_history_newer(filestruct **h);
|
||||
void get_history_older_void(void);
|
||||
void get_history_newer_void(void);
|
||||
#endif
|
||||
|
||||
/* Most functions in text.c. */
|
||||
@@ -537,24 +535,22 @@ void do_enter(void);
|
||||
#ifndef NANO_TINY
|
||||
RETSIGTYPE cancel_command(int signal);
|
||||
bool execute_command(const char *command);
|
||||
void discard_until(const undo *thisitem, openfilestruct *thefile);
|
||||
void discard_until(const undo *thisitem, openfilestruct *thefile, bool keep);
|
||||
void add_undo(undo_type action);
|
||||
#ifdef ENABLE_COMMENT
|
||||
void update_comment_undo(ssize_t lineno);
|
||||
#endif
|
||||
void update_multiline_undo(ssize_t lineno, char *indentation);
|
||||
void update_undo(undo_type action);
|
||||
#endif /* !NANO_TINY */
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
void wrap_reset(void);
|
||||
bool do_wrap(filestruct *line);
|
||||
#endif
|
||||
#if defined(ENABLE_HELP) || !defined(DISABLE_WRAPJUSTIFY)
|
||||
#if defined(ENABLE_HELP) || defined(ENABLED_WRAPORJUSTIFY)
|
||||
ssize_t break_line(const char *line, ssize_t goal, bool snap_at_nl);
|
||||
#endif
|
||||
#if !defined(NANO_TINY) || !defined(DISABLE_JUSTIFY)
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
|
||||
size_t indent_length(const char *line);
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
void justify_format(filestruct *paragraph, size_t skip);
|
||||
bool begpar(const filestruct *const foo);
|
||||
bool inpar(const filestruct *const foo);
|
||||
@@ -562,10 +558,10 @@ void do_justify(bool full_justify);
|
||||
void do_justify_void(void);
|
||||
void do_full_justify(void);
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
void do_spell(void);
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
void do_linter(void);
|
||||
void do_formatter(void);
|
||||
#endif
|
||||
@@ -577,6 +573,8 @@ void complete_a_word(void);
|
||||
|
||||
/* All functions in utils.c. */
|
||||
void get_homedir(void);
|
||||
const char *tail(const char *path);
|
||||
char *concatenate(const char *path, const char *name);
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
int digits(ssize_t n);
|
||||
#endif
|
||||
@@ -586,8 +584,11 @@ void snuggly_fit(char **str);
|
||||
void null_at(char **data, size_t index);
|
||||
void unsunder(char *str, size_t true_len);
|
||||
void sunder(char *str);
|
||||
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
||||
void free_chararray(char **array, size_t len);
|
||||
#endif
|
||||
const char *fixbounds(const char *r);
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
bool is_separate_word(size_t position, size_t length, const char *buf);
|
||||
#endif
|
||||
const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
@@ -600,9 +601,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);
|
||||
@@ -621,10 +622,12 @@ void dump_filestruct_reverse(void);
|
||||
#endif
|
||||
|
||||
/* Most functions in winio.c. */
|
||||
void record_macro(void);
|
||||
void run_macro(void);
|
||||
void get_key_buffer(WINDOW *win);
|
||||
size_t get_key_buffer_len(void);
|
||||
void unget_kbinput(int kbinput, bool metakey);
|
||||
int get_kbinput(WINDOW *win);
|
||||
int get_kbinput(WINDOW *win, bool showcursor);
|
||||
int parse_kbinput(WINDOW *win);
|
||||
int arrow_from_abcd(int kbinput);
|
||||
int parse_escape_sequence(WINDOW *win, int kbinput);
|
||||
@@ -648,8 +651,8 @@ void statusbar(const char *msg);
|
||||
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 post_one_key(const char *keystroke, const char *tag, int width);
|
||||
void place_the_cursor(void);
|
||||
void edit_draw(filestruct *fileptr, const char *converted,
|
||||
int line, size_t from_col);
|
||||
int update_line(filestruct *fileptr, size_t index);
|
||||
@@ -660,7 +663,7 @@ bool line_needs_update(const size_t old_column, const size_t new_column);
|
||||
int go_back_chunks(int nrows, filestruct **line, size_t *leftedge);
|
||||
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);
|
||||
void edit_scroll(bool direction, int nrows);
|
||||
#ifndef NANO_TINY
|
||||
size_t get_softwrap_breakpoint(const char *text, size_t leftedge,
|
||||
bool *end_of_line);
|
||||
@@ -671,7 +674,7 @@ size_t number_of_chunks_in(filestruct *line);
|
||||
void ensure_firstcolumn_is_aligned(void);
|
||||
#endif
|
||||
size_t actual_last_column(size_t leftedge, size_t column);
|
||||
void edit_redraw(filestruct *old_current);
|
||||
void edit_redraw(filestruct *old_current, update_type manner);
|
||||
void edit_refresh(void);
|
||||
void adjust_viewport(update_type location);
|
||||
void total_redraw(void);
|
||||
@@ -683,12 +686,10 @@ 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 disable_waiting(void);
|
||||
void enable_waiting(void);
|
||||
#ifndef DISABLE_EXTRA
|
||||
#ifdef ENABLE_EXTRA
|
||||
void do_credits(void);
|
||||
#endif
|
||||
|
||||
|
||||
188
src/rcfile.c
188
src/rcfile.c
@@ -3,7 +3,7 @@
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014 Mike Frysinger *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -22,18 +22,16 @@
|
||||
|
||||
#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
|
||||
|
||||
#ifndef RCFILE_NAME
|
||||
#define RCFILE_NAME ".nanorc"
|
||||
#define RCFILE_NAME "nanorc"
|
||||
#endif
|
||||
|
||||
static const rcoption rcopts[] = {
|
||||
@@ -41,15 +39,15 @@ static const rcoption rcopts[] = {
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
{"linenumbers", LINE_NUMBERS},
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
{"brackets", 0},
|
||||
#endif
|
||||
{"const", CONSTANT_SHOW}, /* deprecated form, remove in 2018 */
|
||||
{"constantshow", CONSTANT_SHOW},
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
{"fill", 0},
|
||||
#endif
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
{"historylog", HISTORYLOG},
|
||||
#endif
|
||||
{"morespace", MORE_SPACE},
|
||||
@@ -62,18 +60,18 @@ static const rcoption rcopts[] = {
|
||||
{"nohelp", NO_HELP},
|
||||
{"nonewlines", NO_NEWLINES},
|
||||
{"nopauses", NO_PAUSES},
|
||||
#ifndef DISABLE_WRAPPING
|
||||
#ifdef ENABLE_WRAPPING
|
||||
{"nowrap", NO_WRAP},
|
||||
#endif
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
{"operatingdir", 0},
|
||||
#endif
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
{"poslog", POS_HISTORY}, /* deprecated form, remove in 2018 */
|
||||
{"positionlog", POS_HISTORY},
|
||||
#endif
|
||||
{"preserve", PRESERVE},
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
{"punct", 0},
|
||||
{"quotestr", 0},
|
||||
#endif
|
||||
@@ -81,7 +79,7 @@ static const rcoption rcopts[] = {
|
||||
{"rebinddelete", REBIND_DELETE},
|
||||
{"rebindkeypad", REBIND_KEYPAD},
|
||||
{"regexp", USE_REGEXP},
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
{"speller", 0},
|
||||
#endif
|
||||
{"suspend", SUSPEND},
|
||||
@@ -113,9 +111,10 @@ static const rcoption rcopts[] = {
|
||||
{"wordbounds", WORD_BOUNDS},
|
||||
{"wordchars", 0},
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
{"titlecolor", 0},
|
||||
{"numbercolor", 0},
|
||||
{"selectedcolor", 0},
|
||||
{"statuscolor", 0},
|
||||
{"keycolor", 0},
|
||||
{"functioncolor", 0},
|
||||
@@ -123,13 +122,11 @@ static const rcoption rcopts[] = {
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
static bool errors = FALSE;
|
||||
/* Whether we got any errors while parsing an rcfile. */
|
||||
static size_t lineno = 0;
|
||||
/* If we did, the line number where the last error occurred. */
|
||||
/* The line number of the last encountered error. */
|
||||
static char *nanorc = NULL;
|
||||
/* The path to the rcfile we're parsing. */
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
static bool opensyntax = FALSE;
|
||||
/* Whether we're allowed to add to the last syntax. When a file ends,
|
||||
* or when a new syntax command is seen, this bool becomes FALSE. */
|
||||
@@ -139,21 +136,16 @@ static colortype *lastcolor = NULL;
|
||||
/* The end of the color list for the current syntax. */
|
||||
#endif
|
||||
|
||||
/* We have an error in some part of the rcfile. Print the error message
|
||||
* on stderr, and then make the user hit Enter to continue starting
|
||||
* nano. */
|
||||
/* Report an error in an rcfile, printing it to stderr. */
|
||||
void rcfile_error(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (ISSET(QUIET))
|
||||
return;
|
||||
if (rcfile_with_errors == NULL)
|
||||
rcfile_with_errors = strdup(nanorc);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
if (lineno > 0) {
|
||||
errors = TRUE;
|
||||
if (lineno > 0)
|
||||
fprintf(stderr, _("Error in %s on line %lu: "), nanorc, (unsigned long)lineno);
|
||||
}
|
||||
|
||||
va_start(ap, msg);
|
||||
vfprintf(stderr, _(msg), ap);
|
||||
@@ -163,7 +155,7 @@ void rcfile_error(const char *msg, ...)
|
||||
}
|
||||
#endif /* ENABLE_NANORC */
|
||||
|
||||
#if defined(ENABLE_NANORC) || !defined(DISABLE_HISTORIES)
|
||||
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
|
||||
/* Parse the next word from the string, null-terminate it, and return
|
||||
* a pointer to the first character after the null terminator. The
|
||||
* returned pointer will point to '\0' if we hit the end of the line. */
|
||||
@@ -183,7 +175,7 @@ char *parse_next_word(char *ptr)
|
||||
|
||||
return ptr;
|
||||
}
|
||||
#endif /* ENABLE_NANORC || !DISABLE_HISTORIES */
|
||||
#endif /* ENABLE_NANORC || ENABLE_HISTORIES */
|
||||
|
||||
#ifdef ENABLE_NANORC
|
||||
/* Parse an argument, with optional quotes, after a keyword that takes
|
||||
@@ -222,7 +214,7 @@ char *parse_argument(char *ptr)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
/* Pass over the current regex string in the line starting at ptr,
|
||||
* null-terminate it, and return a pointer to the /next/ word. */
|
||||
char *parse_next_regex(char *ptr)
|
||||
@@ -345,7 +337,7 @@ void parse_syntax(char *ptr)
|
||||
if (*ptr != '\0')
|
||||
grab_and_store("extension", ptr, &live_syntax->extensions);
|
||||
}
|
||||
#endif /* !DISABLE_COLOR */
|
||||
#endif /* ENABLE_COLOR */
|
||||
|
||||
/* Check whether the given executable function is "universal" (meaning
|
||||
* any horizontal movement or deletion) and thus is present in almost
|
||||
@@ -353,13 +345,13 @@ void parse_syntax(char *ptr)
|
||||
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 ||
|
||||
#endif
|
||||
func == do_verbatim_input || func == do_cut_text_void ||
|
||||
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;
|
||||
@@ -389,7 +381,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. */
|
||||
@@ -400,7 +392,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,15 +402,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) {
|
||||
@@ -427,7 +414,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,31 +424,23 @@ 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
|
||||
if (dobind)
|
||||
fprintf(stderr, "newsc address is now %ld, assigned func = %ld, menu = %x\n",
|
||||
(long)&newsc, (long)newsc->scfunc, menu);
|
||||
else
|
||||
fprintf(stderr, "unbinding \"%s\" from menu %x\n", keycopy, menu);
|
||||
#endif
|
||||
|
||||
if (dobind) {
|
||||
subnfunc *f;
|
||||
int mask = 0;
|
||||
@@ -485,8 +464,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;
|
||||
@@ -495,23 +473,14 @@ 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);
|
||||
fprintf(stderr, "s->keycode = \"%d\"\n", newsc->keycode);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Now find and delete any existing same shortcut in the menu(s). */
|
||||
for (s = sclist; s != NULL; s = s->next) {
|
||||
if ((s->menus & menu) && !strcmp(s->keystr, keycopy)) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "deleting entry from among menus %x\n", s->menus);
|
||||
#endif
|
||||
if ((s->menus & menu) && !strcmp(s->keystr, keycopy))
|
||||
s->menus &= ~menu;
|
||||
}
|
||||
}
|
||||
|
||||
if (dobind) {
|
||||
@@ -530,15 +499,20 @@ void parse_binding(char *ptr, bool dobind)
|
||||
return;
|
||||
}
|
||||
|
||||
free_copy:
|
||||
free_things:
|
||||
free(newsc);
|
||||
free(keycopy);
|
||||
}
|
||||
|
||||
/* Verify that the given file is not a folder nor a device. */
|
||||
/* Verify that the given file exists, is not a folder nor a device. */
|
||||
bool is_good_file(char *file)
|
||||
{
|
||||
struct stat rcinfo;
|
||||
|
||||
/* First check that the file exists and is readable. */
|
||||
if (access(file, R_OK) != 0)
|
||||
return FALSE;
|
||||
|
||||
/* If the thing exists, it may not be a directory nor a device. */
|
||||
if (stat(file, &rcinfo) != -1 && (S_ISDIR(rcinfo.st_mode) ||
|
||||
S_ISCHR(rcinfo.st_mode) || S_ISBLK(rcinfo.st_mode))) {
|
||||
@@ -549,7 +523,7 @@ bool is_good_file(char *file)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
/* Read and parse one included syntax file. */
|
||||
static void parse_one_include(char *file)
|
||||
{
|
||||
@@ -895,9 +869,8 @@ void pick_up_name(const char *kind, char *ptr, char **storage)
|
||||
}
|
||||
|
||||
*storage = mallocstrcpy(*storage, ptr);
|
||||
|
||||
}
|
||||
#endif /* !DISABLE_COLOR */
|
||||
#endif /* ENABLE_COLOR */
|
||||
|
||||
/* Verify that the user has not unmapped every shortcut for a
|
||||
* function that we consider 'vital' (such as "Exit"). */
|
||||
@@ -958,7 +931,7 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
keyword = ptr;
|
||||
ptr = parse_next_word(ptr);
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
/* Handle extending first... */
|
||||
if (strcasecmp(keyword, "extendsyntax") == 0) {
|
||||
syntaxtype *sint;
|
||||
@@ -1018,7 +991,7 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
else if (strcasecmp(keyword, "linter") == 0)
|
||||
pick_up_name("linter", ptr, &live_syntax->linter);
|
||||
else if (strcasecmp(keyword, "formatter") == 0)
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
pick_up_name("formatter", ptr, &live_syntax->formatter);
|
||||
#else
|
||||
;
|
||||
@@ -1029,7 +1002,7 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
else if (strcasecmp(keyword, "include") == 0)
|
||||
parse_includes(ptr);
|
||||
else
|
||||
#endif /* !DISABLE_COLOR */
|
||||
#endif /* ENABLE_COLOR */
|
||||
if (strcasecmp(keyword, "set") == 0)
|
||||
set = 1;
|
||||
else if (strcasecmp(keyword, "unset") == 0)
|
||||
@@ -1041,7 +1014,7 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
else
|
||||
rcfile_error(N_("Command \"%s\" not understood"), keyword);
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
/* If a syntax was extended, it stops at the end of the command. */
|
||||
if (live_syntax != syntaxes)
|
||||
opensyntax = FALSE;
|
||||
@@ -1110,11 +1083,13 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
if (strcasecmp(rcopts[i].name, "titlecolor") == 0)
|
||||
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)
|
||||
@@ -1123,12 +1098,12 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
specified_color_combo[FUNCTION_TAG] = option;
|
||||
else
|
||||
#endif
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
if (strcasecmp(rcopts[i].name, "operatingdir") == 0)
|
||||
operating_dir = option;
|
||||
else
|
||||
#endif
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
if (strcasecmp(rcopts[i].name, "fill") == 0) {
|
||||
if (!parse_num(option, &wrap_at)) {
|
||||
rcfile_error(N_("Requested fill size \"%s\" is invalid"),
|
||||
@@ -1160,7 +1135,7 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
if (strcasecmp(rcopts[i].name, "punct") == 0) {
|
||||
punct = option;
|
||||
if (has_blank_mbchars(punct)) {
|
||||
@@ -1187,7 +1162,7 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
word_chars = option;
|
||||
else
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
if (strcasecmp(rcopts[i].name, "speller") == 0)
|
||||
alt_speller = option;
|
||||
else
|
||||
@@ -1203,7 +1178,7 @@ void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
assert(FALSE);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
if (opensyntax && lastcolor == NULL)
|
||||
rcfile_error(N_("Syntax \"%s\" has no color commands"),
|
||||
live_syntax->name);
|
||||
@@ -1230,7 +1205,6 @@ void parse_one_nanorc(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Going to parse file \"%s\"\n", nanorc);
|
||||
#endif
|
||||
|
||||
rcstream = fopen(nanorc, "rb");
|
||||
|
||||
/* If opening the file succeeded, parse it. Otherwise, only
|
||||
@@ -1241,9 +1215,22 @@ void parse_one_nanorc(void)
|
||||
rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno));
|
||||
}
|
||||
|
||||
bool have_nanorc(const char *path, char *name)
|
||||
{
|
||||
if (path == NULL)
|
||||
return FALSE;
|
||||
|
||||
free(nanorc);
|
||||
nanorc = concatenate(path, name);
|
||||
|
||||
return is_good_file(nanorc);
|
||||
}
|
||||
|
||||
/* First read the system-wide rcfile, then the user's rcfile. */
|
||||
void do_rcfiles(void)
|
||||
{
|
||||
const char *xdgconfdir;
|
||||
|
||||
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
|
||||
|
||||
/* Process the system-wide nanorc. */
|
||||
@@ -1257,27 +1244,22 @@ void do_rcfiles(void)
|
||||
#endif
|
||||
|
||||
get_homedir();
|
||||
xdgconfdir = getenv("XDG_CONFIG_HOME");
|
||||
|
||||
if (homedir == NULL)
|
||||
rcfile_error(N_("I can't find my home directory! Wah!"));
|
||||
else {
|
||||
nanorc = charealloc(nanorc, strlen(homedir) + strlen(RCFILE_NAME) + 2);
|
||||
sprintf(nanorc, "%s/%s", homedir, RCFILE_NAME);
|
||||
|
||||
/* Process the current user's nanorc. */
|
||||
/* Now try the to find a nanorc file in the user's home directory
|
||||
* or in the XDG configuration directories. */
|
||||
if (have_nanorc(homedir, "/." RCFILE_NAME))
|
||||
parse_one_nanorc();
|
||||
}
|
||||
else if (have_nanorc(xdgconfdir, "/nano/" RCFILE_NAME))
|
||||
parse_one_nanorc();
|
||||
else if (have_nanorc(homedir, "/.config/nano/" RCFILE_NAME))
|
||||
parse_one_nanorc();
|
||||
else if (homedir == NULL && xdgconfdir == NULL)
|
||||
rcfile_error(N_("I can't find my home directory! Wah!"));
|
||||
|
||||
check_vitals_mapped();
|
||||
|
||||
free(nanorc);
|
||||
|
||||
if (errors && !ISSET(QUIET) && !ISSET(NO_PAUSES)) {
|
||||
errors = FALSE;
|
||||
fprintf(stderr, _("\nPress Enter to continue starting nano.\n"));
|
||||
while (getchar() != '\n')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ENABLE_NANORC */
|
||||
|
||||
354
src/search.c
354
src/search.c
@@ -2,7 +2,7 @@
|
||||
* search.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2015, 2016, 2017 Benno Schulenberg *
|
||||
* Copyright (C) 2015-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -22,18 +22,12 @@
|
||||
#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? */
|
||||
#ifndef DISABLE_HISTORIES
|
||||
static bool history_changed = FALSE;
|
||||
/* Have any of the history lists changed? */
|
||||
#endif
|
||||
static bool regexp_compiled = FALSE;
|
||||
/* Have we compiled any regular expressions? */
|
||||
|
||||
@@ -71,21 +65,14 @@ void regexp_cleanup(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Indicate on the statusbar that the string at str was not found by the
|
||||
* last search. */
|
||||
/* Report on the status bar that the given string was not found. */
|
||||
void not_found_msg(const char *str)
|
||||
{
|
||||
char *disp;
|
||||
int numchars;
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
disp = display_string(str, 0, (COLS / 2) + 1, FALSE);
|
||||
numchars = actual_x(disp, mbstrnlen(disp, COLS / 2));
|
||||
char *disp = display_string(str, 0, (COLS / 2) + 1, FALSE);
|
||||
size_t numchars = actual_x(disp, strnlenpt(disp, COLS / 2));
|
||||
|
||||
statusline(HUSH, _("\"%.*s%s\" not found"), numchars, disp,
|
||||
(disp[numchars] == '\0') ? "" : "...");
|
||||
|
||||
free(disp);
|
||||
}
|
||||
|
||||
@@ -96,7 +83,7 @@ void not_found_msg(const char *str)
|
||||
void search_replace_abort(void)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set)
|
||||
if (openfile->mark)
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
regexp_cleanup();
|
||||
@@ -144,10 +131,7 @@ int search_init(bool replacing, bool use_answer)
|
||||
/* This is now one simple call. It just does a lot. */
|
||||
i = do_prompt(FALSE, FALSE,
|
||||
inhelp ? MFINDINHELP : (replacing ? MREPLACE : MWHEREIS),
|
||||
backupstring,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
&search_history,
|
||||
#endif
|
||||
backupstring, &search_history,
|
||||
/* TRANSLATORS: This is the main search prompt. */
|
||||
edit_refresh, "%s%s%s%s%s%s", _("Search"),
|
||||
/* TRANSLATORS: The next three modify the search prompt. */
|
||||
@@ -156,7 +140,7 @@ int search_init(bool replacing, bool use_answer)
|
||||
ISSET(BACKWARDS_SEARCH) ? _(" [Backwards]") : "", replacing ?
|
||||
#ifndef NANO_TINY
|
||||
/* TRANSLATORS: The next two modify the search prompt. */
|
||||
openfile->mark_set ? _(" (to replace) in selection") :
|
||||
openfile->mark ? _(" (to replace) in selection") :
|
||||
#endif
|
||||
_(" (to replace)") : "", buf);
|
||||
|
||||
@@ -178,7 +162,7 @@ int search_init(bool replacing, bool use_answer)
|
||||
/* If an answer was given, remember it. */
|
||||
if (*answer != '\0') {
|
||||
last_search = mallocstrcpy(last_search, answer);
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
update_history(&search_history, answer);
|
||||
#endif
|
||||
}
|
||||
@@ -218,7 +202,7 @@ int search_init(bool replacing, bool use_answer)
|
||||
* where we first started searching, at column begin_x. Return 1 when we
|
||||
* found something, 0 when nothing, and -2 on cancel. When match_len is
|
||||
* not NULL, set it to the length of the found string, if any. */
|
||||
int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
int findnextstr(const char *needle, bool whole_word_only, int modus,
|
||||
size_t *match_len, bool skipone, const filestruct *begin, size_t begin_x)
|
||||
{
|
||||
size_t found_len = strlen(needle);
|
||||
@@ -289,7 +273,7 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
/* When doing a regex search, compute the length of the match. */
|
||||
if (ISSET(USE_REGEXP))
|
||||
found_len = regmatches[0].rm_eo - regmatches[0].rm_so;
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
/* When we're spell checking, a match should be a separate word;
|
||||
* if it's not, continue looking in the rest of the line. */
|
||||
if (whole_word_only && !is_separate_word(found - line->data,
|
||||
@@ -304,7 +288,6 @@ 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);
|
||||
enable_waiting();
|
||||
return 0;
|
||||
}
|
||||
@@ -318,7 +301,7 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
/* If we've reached the start or end of the buffer, wrap around;
|
||||
* but stop when spell-checking or replacing in a region. */
|
||||
if (line == NULL) {
|
||||
if (whole_word_only || have_region) {
|
||||
if (whole_word_only || modus == INREGION) {
|
||||
enable_waiting();
|
||||
return 0;
|
||||
}
|
||||
@@ -328,9 +311,11 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
else
|
||||
line = openfile->fileage;
|
||||
|
||||
statusbar(_("Search Wrapped"));
|
||||
/* Delay the "Searching..." message for at least two seconds. */
|
||||
feedback = -2;
|
||||
if (modus == JUSTFIND) {
|
||||
statusbar(_("Search Wrapped"));
|
||||
/* Delay the "Searching..." message for at least two seconds. */
|
||||
feedback = -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we've reached the original starting line, take note. */
|
||||
@@ -349,10 +334,8 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
|
||||
/* 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);
|
||||
(ISSET(BACKWARDS_SEARCH) && found_x < begin_x)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the current position to point at what we found. */
|
||||
openfile->current = line;
|
||||
@@ -365,6 +348,7 @@ int findnextstr(const char *needle, bool whole_word_only, bool have_region,
|
||||
/* Wipe the "Searching..." message and unset the suppression flag. */
|
||||
if (feedback > 0) {
|
||||
blank_statusbar();
|
||||
wrefresh(bottomwin);
|
||||
suppress_cursorpos = FALSE;
|
||||
}
|
||||
|
||||
@@ -387,35 +371,40 @@ void do_search(void)
|
||||
go_looking();
|
||||
}
|
||||
|
||||
/* Search forward for a string. */
|
||||
void do_search_forward(void)
|
||||
{
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
do_search();
|
||||
}
|
||||
|
||||
/* Search backwards for a string. */
|
||||
void do_search_backward(void)
|
||||
{
|
||||
SET(BACKWARDS_SEARCH);
|
||||
do_search();
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Search in the backward direction for the next occurrence. */
|
||||
void do_findprevious(void)
|
||||
{
|
||||
if ISSET(BACKWARDS_SEARCH)
|
||||
do_research();
|
||||
else {
|
||||
SET(BACKWARDS_SEARCH);
|
||||
do_research();
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
}
|
||||
SET(BACKWARDS_SEARCH);
|
||||
do_research();
|
||||
}
|
||||
|
||||
/* Search in the forward direction for the next occurrence. */
|
||||
void do_findnext(void)
|
||||
{
|
||||
if ISSET(BACKWARDS_SEARCH) {
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
do_research();
|
||||
SET(BACKWARDS_SEARCH);
|
||||
} else
|
||||
do_research();
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
do_research();
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Search for the last string without prompting. */
|
||||
void do_research(void)
|
||||
{
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
/* If nothing was searched for yet during this run of nano, but
|
||||
* there is a search history, take the most recent item. */
|
||||
if (*last_search == '\0' && searchbot->prev != NULL)
|
||||
@@ -448,7 +437,7 @@ void go_looking(void)
|
||||
|
||||
came_full_circle = FALSE;
|
||||
|
||||
didfind = findnextstr(last_search, FALSE, FALSE, NULL, FALSE,
|
||||
didfind = findnextstr(last_search, FALSE, JUSTFIND, NULL, FALSE,
|
||||
openfile->current, openfile->current_x);
|
||||
|
||||
/* If we found something, and we're back at the exact same spot
|
||||
@@ -456,12 +445,14 @@ void go_looking(void)
|
||||
if (didfind == 1 && openfile->current == was_current &&
|
||||
openfile->current_x == was_current_x)
|
||||
statusbar(_("This is the only occurrence"));
|
||||
else if (didfind == 0)
|
||||
not_found_msg(last_search);
|
||||
|
||||
#ifdef DEBUG
|
||||
statusline(HUSH, "Took: %.2f", (double)(clock() - start) / CLOCKS_PER_SEC);
|
||||
#endif
|
||||
|
||||
edit_redraw(was_current);
|
||||
edit_redraw(was_current, CENTERING);
|
||||
search_replace_abort();
|
||||
}
|
||||
|
||||
@@ -557,21 +548,21 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
size_t match_len;
|
||||
bool replaceall = FALSE;
|
||||
bool skipone = FALSE;
|
||||
bool mark_was_set = FALSE;
|
||||
int modus = REPLACING;
|
||||
#ifndef NANO_TINY
|
||||
filestruct *was_mark = openfile->mark;
|
||||
filestruct *top, *bot;
|
||||
size_t top_x, bot_x;
|
||||
bool right_side_up = FALSE;
|
||||
/* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
|
||||
* FALSE if (current, current_x) is. */
|
||||
|
||||
mark_was_set = openfile->mark_set;
|
||||
|
||||
/* If the mark is on, frame the region, and turn the mark off. */
|
||||
if (mark_was_set) {
|
||||
if (openfile->mark) {
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
openfile->mark_set = FALSE;
|
||||
openfile->mark = NULL;
|
||||
modus = INREGION;
|
||||
|
||||
/* Start either at the top or the bottom of the marked region. */
|
||||
if (!ISSET(BACKWARDS_SEARCH)) {
|
||||
@@ -588,7 +579,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
|
||||
while (TRUE) {
|
||||
int i = 0;
|
||||
int result = findnextstr(needle, whole_word_only, mark_was_set,
|
||||
int result = findnextstr(needle, whole_word_only, modus,
|
||||
&match_len, skipone, real_current, *real_current_x);
|
||||
|
||||
/* If nothing more was found, or the user aborted, stop looping. */
|
||||
@@ -600,7 +591,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* An occurrence outside of the marked region means we're done. */
|
||||
if (mark_was_set && (openfile->current->lineno > bot->lineno ||
|
||||
if (was_mark && (openfile->current->lineno > bot->lineno ||
|
||||
openfile->current->lineno < top->lineno ||
|
||||
(openfile->current == bot &&
|
||||
openfile->current_x + match_len > bot_x) ||
|
||||
@@ -621,9 +612,6 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
/* Refresh the edit window, scrolling it if necessary. */
|
||||
edit_refresh();
|
||||
|
||||
/* Don't show cursor, to not distract from highlighted match. */
|
||||
curs_set(0);
|
||||
|
||||
spotlight(TRUE, from_col, to_col);
|
||||
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
@@ -655,20 +643,20 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
#ifndef NANO_TINY
|
||||
/* If the mark was on and it was located after the cursor,
|
||||
* then adjust its x position for any text length changes. */
|
||||
if (mark_was_set && !right_side_up) {
|
||||
if (openfile->current == openfile->mark_begin &&
|
||||
openfile->mark_begin_x > openfile->current_x) {
|
||||
if (openfile->mark_begin_x < openfile->current_x + match_len)
|
||||
openfile->mark_begin_x = openfile->current_x;
|
||||
if (was_mark && !right_side_up) {
|
||||
if (openfile->current == was_mark &&
|
||||
openfile->mark_x > openfile->current_x) {
|
||||
if (openfile->mark_x < openfile->current_x + match_len)
|
||||
openfile->mark_x = openfile->current_x;
|
||||
else
|
||||
openfile->mark_begin_x += length_change;
|
||||
bot_x = openfile->mark_begin_x;
|
||||
openfile->mark_x += length_change;
|
||||
bot_x = openfile->mark_x;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the mark was not on or it was before the cursor, then
|
||||
* adjust the cursor's x position for any text length changes. */
|
||||
if (!mark_was_set || right_side_up) {
|
||||
if (!was_mark || right_side_up) {
|
||||
#endif
|
||||
if (openfile->current == real_current &&
|
||||
openfile->current_x < *real_current_x) {
|
||||
@@ -696,7 +684,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
openfile->current->data = copy;
|
||||
|
||||
if (!replaceall) {
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
/* When doing syntax coloring, the replacement might require
|
||||
* a change of colors, so refresh the whole edit window. */
|
||||
if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX))
|
||||
@@ -714,17 +702,15 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
|
||||
if (numreplaced == -1)
|
||||
not_found_msg(needle);
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
else if (numreplaced > 0)
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (mark_was_set)
|
||||
openfile->mark_set = TRUE;
|
||||
openfile->mark = was_mark;
|
||||
#endif
|
||||
|
||||
/* If the NO_NEWLINES flag isn't set, and text has been added to the
|
||||
/* If "automatic newline" is enabled, and text has been added to the
|
||||
* magicline, make a new magicline. */
|
||||
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
|
||||
new_magicline();
|
||||
@@ -757,14 +743,11 @@ void do_replace(void)
|
||||
if (i != 0)
|
||||
return;
|
||||
|
||||
i = do_prompt(FALSE, FALSE, MREPLACEWITH, NULL,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
&replace_history,
|
||||
#endif
|
||||
i = do_prompt(FALSE, FALSE, MREPLACEWITH, NULL, &replace_history,
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
edit_refresh, _("Replace with"));
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
#ifdef ENABLE_HISTORIES
|
||||
/* If the replace string is not "", add it to the replace history list. */
|
||||
if (i == 0)
|
||||
update_history(&replace_history, answer);
|
||||
@@ -794,9 +777,8 @@ void do_replace(void)
|
||||
refresh_needed = TRUE;
|
||||
|
||||
if (numreplaced >= 0)
|
||||
statusline(HUSH, P_("Replaced %lu occurrence",
|
||||
"Replaced %lu occurrences", (unsigned long)numreplaced),
|
||||
(unsigned long)numreplaced);
|
||||
statusline(HUSH, P_("Replaced %zd occurrence",
|
||||
"Replaced %zd occurrences", numreplaced), numreplaced);
|
||||
|
||||
search_replace_abort();
|
||||
}
|
||||
@@ -825,10 +807,7 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
|
||||
/* Ask for the line and column. */
|
||||
int i = do_prompt(FALSE, FALSE, MGOTOLINE,
|
||||
use_answer ? answer : NULL,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
NULL,
|
||||
#endif
|
||||
use_answer ? answer : NULL, NULL,
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
edit_refresh, _("Enter line number, column number"));
|
||||
|
||||
@@ -1075,8 +1054,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 {
|
||||
@@ -1090,199 +1068,3 @@ void do_find_bracket(void)
|
||||
}
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
/* Indicate whether any of the history lists have changed. */
|
||||
bool history_has_changed(void)
|
||||
{
|
||||
return history_changed;
|
||||
}
|
||||
|
||||
/* Initialize the search and replace history lists. */
|
||||
void history_init(void)
|
||||
{
|
||||
search_history = make_new_node(NULL);
|
||||
search_history->data = mallocstrcpy(NULL, "");
|
||||
searchage = search_history;
|
||||
searchbot = search_history;
|
||||
|
||||
replace_history = make_new_node(NULL);
|
||||
replace_history->data = mallocstrcpy(NULL, "");
|
||||
replaceage = replace_history;
|
||||
replacebot = replace_history;
|
||||
}
|
||||
|
||||
/* Set the current position in the history list h to the bottom. */
|
||||
void history_reset(const filestruct *h)
|
||||
{
|
||||
if (h == search_history)
|
||||
search_history = searchbot;
|
||||
else if (h == replace_history)
|
||||
replace_history = replacebot;
|
||||
}
|
||||
|
||||
/* Return the first node containing the first len characters of the
|
||||
* string s in the history list, starting at h_start and ending at
|
||||
* h_end, or NULL if there isn't one. */
|
||||
filestruct *find_history(const filestruct *h_start, const filestruct
|
||||
*h_end, const char *s, size_t len)
|
||||
{
|
||||
const filestruct *p;
|
||||
|
||||
for (p = h_start; p != h_end->prev && p != NULL; p = p->prev) {
|
||||
if (strncmp(s, p->data, len) == 0)
|
||||
return (filestruct *)p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Update a history list (the one in which h is the current position)
|
||||
* with a fresh string s. That is: add s, or move it to the end. */
|
||||
void update_history(filestruct **h, const char *s)
|
||||
{
|
||||
filestruct **hage = NULL, **hbot = NULL, *thesame;
|
||||
|
||||
assert(h != NULL && s != NULL);
|
||||
|
||||
if (*h == search_history) {
|
||||
hage = &searchage;
|
||||
hbot = &searchbot;
|
||||
} else if (*h == replace_history) {
|
||||
hage = &replaceage;
|
||||
hbot = &replacebot;
|
||||
}
|
||||
|
||||
assert(hage != NULL && hbot != NULL);
|
||||
|
||||
/* See if the string is already in the history. */
|
||||
thesame = find_history(*hbot, *hage, s, HIGHEST_POSITIVE);
|
||||
|
||||
/* If an identical string was found, delete that item. */
|
||||
if (thesame != NULL) {
|
||||
filestruct *after = thesame->next;
|
||||
|
||||
/* If the string is at the head of the list, move the head. */
|
||||
if (thesame == *hage)
|
||||
*hage = after;
|
||||
|
||||
unlink_node(thesame);
|
||||
renumber(after);
|
||||
}
|
||||
|
||||
/* If the history is full, delete the oldest item (the one at the
|
||||
* head of the list), to make room for a new item at the end. */
|
||||
if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
|
||||
filestruct *oldest = *hage;
|
||||
|
||||
*hage = (*hage)->next;
|
||||
unlink_node(oldest);
|
||||
renumber(*hage);
|
||||
}
|
||||
|
||||
/* Store the fresh string in the last item, then create a new item. */
|
||||
(*hbot)->data = mallocstrcpy((*hbot)->data, s);
|
||||
splice_node(*hbot, make_new_node(*hbot));
|
||||
*hbot = (*hbot)->next;
|
||||
(*hbot)->data = mallocstrcpy(NULL, "");
|
||||
|
||||
/* Indicate that the history needs to be saved on exit. */
|
||||
history_changed = TRUE;
|
||||
|
||||
/* Set the current position in the list to the bottom. */
|
||||
*h = *hbot;
|
||||
}
|
||||
|
||||
/* Move h to the string in the history list just before it, and return
|
||||
* that string. If there isn't one, don't move h and return NULL. */
|
||||
char *get_history_older(filestruct **h)
|
||||
{
|
||||
assert(h != NULL);
|
||||
|
||||
if ((*h)->prev == NULL)
|
||||
return NULL;
|
||||
|
||||
*h = (*h)->prev;
|
||||
|
||||
return (*h)->data;
|
||||
}
|
||||
|
||||
/* Move h to the string in the history list just after it, and return
|
||||
* that string. If there isn't one, don't move h and return NULL. */
|
||||
char *get_history_newer(filestruct **h)
|
||||
{
|
||||
assert(h != NULL);
|
||||
|
||||
if ((*h)->next == NULL)
|
||||
return NULL;
|
||||
|
||||
*h = (*h)->next;
|
||||
|
||||
return (*h)->data;
|
||||
}
|
||||
|
||||
/* More placeholders. */
|
||||
void get_history_newer_void(void)
|
||||
{
|
||||
;
|
||||
}
|
||||
void get_history_older_void(void)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TABCOMP
|
||||
/* Move h to the next string that's a tab completion of the string s,
|
||||
* looking at only the first len characters of s, and return that
|
||||
* string. If there isn't one, or if len is 0, don't move h and return
|
||||
* s. */
|
||||
char *get_history_completion(filestruct **h, char *s, size_t len)
|
||||
{
|
||||
assert(s != NULL);
|
||||
|
||||
if (len > 0) {
|
||||
filestruct *hage = NULL, *hbot = NULL, *p;
|
||||
|
||||
assert(h != NULL);
|
||||
|
||||
if (*h == search_history) {
|
||||
hage = searchage;
|
||||
hbot = searchbot;
|
||||
} else if (*h == replace_history) {
|
||||
hage = replaceage;
|
||||
hbot = replacebot;
|
||||
}
|
||||
|
||||
assert(hage != NULL && hbot != NULL);
|
||||
|
||||
/* Search the history list from the current position to the top
|
||||
* for a match of len characters. Skip over an exact match. */
|
||||
p = find_history((*h)->prev, hage, s, len);
|
||||
|
||||
while (p != NULL && strcmp(p->data, s) == 0)
|
||||
p = find_history(p->prev, hage, s, len);
|
||||
|
||||
if (p != NULL) {
|
||||
*h = p;
|
||||
return mallocstrcpy(s, (*h)->data);
|
||||
}
|
||||
|
||||
/* Search the history list from the bottom to the current position
|
||||
* for a match of len characters. Skip over an exact match. */
|
||||
p = find_history(hbot, *h, s, len);
|
||||
|
||||
while (p != NULL && strcmp(p->data, s) == 0)
|
||||
p = find_history(p->prev, *h, s, len);
|
||||
|
||||
if (p != NULL) {
|
||||
*h = p;
|
||||
return mallocstrcpy(s, (*h)->data);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're here, we didn't find a match, we didn't find an inexact
|
||||
* match, or len is 0. Return s. */
|
||||
return (char *)s;
|
||||
}
|
||||
#endif /* ENSABLE_TABCOMP */
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
|
||||
821
src/text.c
821
src/text.c
File diff suppressed because it is too large
Load Diff
82
src/utils.c
82
src/utils.c
@@ -2,7 +2,7 @@
|
||||
* utils.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* Copyright (C) 2016-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -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. */
|
||||
@@ -55,6 +53,29 @@ void get_homedir(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the filename part of the given path. */
|
||||
const char *tail(const char *path)
|
||||
{
|
||||
const char *slash = strrchr(path, '/');
|
||||
|
||||
if (slash == NULL)
|
||||
return path;
|
||||
else
|
||||
return ++slash;
|
||||
}
|
||||
|
||||
/* Return a copy of the two given strings, welded together. */
|
||||
char *concatenate(const char *path, const char *name)
|
||||
{
|
||||
size_t pathlen = strlen(path);
|
||||
char *joined = charalloc(pathlen + strlen(name) + 1);
|
||||
|
||||
strcpy(joined, path);
|
||||
strcpy(joined + pathlen, name);
|
||||
|
||||
return joined;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
/* Return the number of digits that the given integer n takes up. */
|
||||
int digits(ssize_t n)
|
||||
@@ -172,6 +193,20 @@ void sunder(char *str)
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
||||
/* Free the memory of the given array, which should contain len elements. */
|
||||
void free_chararray(char **array, size_t len)
|
||||
{
|
||||
if (array == NULL)
|
||||
return;
|
||||
|
||||
while (len > 0)
|
||||
free(array[--len]);
|
||||
|
||||
free(array);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fix the regex if we're on platforms which require an adjustment
|
||||
* from GNU-style to BSD-style word boundaries. */
|
||||
const char *fixbounds(const char *r)
|
||||
@@ -181,10 +216,6 @@ const char *fixbounds(const char *r)
|
||||
char *r2 = charalloc(strlen(r) * 5);
|
||||
char *r3;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "fixbounds(): Start string = \"%s\"\n", r);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < strlen(r); i++) {
|
||||
if (r[i] != '\0' && r[i] == '\\' && (r[i + 1] == '>' || r[i + 1] == '<')) {
|
||||
strcpy(&r2[j], "[[:");
|
||||
@@ -196,19 +227,18 @@ const char *fixbounds(const char *r)
|
||||
r2[j] = r[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
r2[j] = '\0';
|
||||
r3 = mallocstrcpy(NULL, r2);
|
||||
free(r2);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "fixbounds(): Ending string = \"%s\"\n", r3);
|
||||
#endif
|
||||
|
||||
return (const char *) r3;
|
||||
#endif /* !GNU_WORDBOUNDS */
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_SPELLER
|
||||
#ifdef ENABLE_SPELLER
|
||||
/* Is the word starting at the given position in buf and of the given length
|
||||
* a separate word? That is: is it not part of a longer word?*/
|
||||
bool is_separate_word(size_t position, size_t length, const char *buf)
|
||||
@@ -226,7 +256,7 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
|
||||
return ((position == 0 || !is_alpha_mbchar(before)) &&
|
||||
(buf[word_end] == '\0' || !is_alpha_mbchar(after)));
|
||||
}
|
||||
#endif /* !DISABLE_SPELLER */
|
||||
#endif /* ENABLE_SPELLER */
|
||||
|
||||
/* Return the position of the needle in the haystack, or NULL if not found.
|
||||
* When searching backwards, we will find the last match that starts no later
|
||||
@@ -483,18 +513,18 @@ void remove_magicline(void)
|
||||
void mark_order(const filestruct **top, size_t *top_x, const filestruct
|
||||
**bot, size_t *bot_x, bool *right_side_up)
|
||||
{
|
||||
if ((openfile->current->lineno == openfile->mark_begin->lineno &&
|
||||
openfile->current_x > openfile->mark_begin_x) ||
|
||||
openfile->current->lineno > openfile->mark_begin->lineno) {
|
||||
*top = openfile->mark_begin;
|
||||
*top_x = openfile->mark_begin_x;
|
||||
if ((openfile->current->lineno == openfile->mark->lineno &&
|
||||
openfile->current_x > openfile->mark_x) ||
|
||||
openfile->current->lineno > openfile->mark->lineno) {
|
||||
*top = openfile->mark;
|
||||
*top_x = openfile->mark_x;
|
||||
*bot = openfile->current;
|
||||
*bot_x = openfile->current_x;
|
||||
if (right_side_up != NULL)
|
||||
*right_side_up = TRUE;
|
||||
} else {
|
||||
*bot = openfile->mark_begin;
|
||||
*bot_x = openfile->mark_begin_x;
|
||||
*bot = openfile->mark;
|
||||
*bot_x = openfile->mark_x;
|
||||
*top = openfile->current;
|
||||
*top_x = openfile->current_x;
|
||||
if (right_side_up != NULL)
|
||||
@@ -515,8 +545,7 @@ filestruct *fsfromline(ssize_t lineno)
|
||||
f = f->next;
|
||||
|
||||
if (f->lineno != lineno) {
|
||||
statusline(ALERT, _("Internal error: can't match line %ld. "
|
||||
"Please save your work."), (long)lineno);
|
||||
statusline(ALERT, "Gone undo line -- please report a bug");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -554,7 +583,7 @@ void dump_filestruct(const filestruct *inptr)
|
||||
fprintf(stderr, "Dumping a buffer to stderr...\n");
|
||||
|
||||
while (inptr != NULL) {
|
||||
fprintf(stderr, "(%ld) %s\n", (long)inptr->lineno, inptr->data);
|
||||
fprintf(stderr, "(%zd) %s\n", inptr->lineno, inptr->data);
|
||||
inptr = inptr->next;
|
||||
}
|
||||
}
|
||||
@@ -565,8 +594,7 @@ void dump_filestruct_reverse(void)
|
||||
const filestruct *fileptr = openfile->filebot;
|
||||
|
||||
while (fileptr != NULL) {
|
||||
fprintf(stderr, "(%ld) %s\n", (long)fileptr->lineno,
|
||||
fileptr->data);
|
||||
fprintf(stderr, "(%zd) %s\n", fileptr->lineno, fileptr->data);
|
||||
fileptr = fileptr->prev;
|
||||
}
|
||||
}
|
||||
|
||||
421
src/winio.c
421
src/winio.c
@@ -2,7 +2,7 @@
|
||||
* winio.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2017 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014, 2015, 2016, 2017 Benno Schulenberg *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -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
|
||||
@@ -53,6 +49,71 @@ static int statusblank = 0;
|
||||
static bool seen_wide = FALSE;
|
||||
/* Whether we've seen a multicolumn character in the current line. */
|
||||
#endif
|
||||
static bool reveal_cursor = FALSE;
|
||||
/* Whether the cursor should be shown when waiting for input. */
|
||||
#ifndef NANO_TINY
|
||||
static bool recording = FALSE;
|
||||
/* Whether we are in the process of recording a macro. */
|
||||
static int *macro_buffer = NULL;
|
||||
/* A buffer where the recorded key codes are stored. */
|
||||
static size_t macro_length = 0;
|
||||
/* The current length of the macro. */
|
||||
|
||||
/* Add the given code to the macro buffer. */
|
||||
void add_to_macrobuffer(int code)
|
||||
{
|
||||
macro_length++;
|
||||
macro_buffer = (int*)nrealloc(macro_buffer, macro_length * sizeof(int));
|
||||
macro_buffer[macro_length - 1] = code;
|
||||
}
|
||||
|
||||
/* Remove the last key code plus any trailing Esc codes from macro buffer. */
|
||||
void snip_last_keystroke(void)
|
||||
{
|
||||
macro_length--;
|
||||
while (macro_length > 0 && macro_buffer[macro_length - 1] == '\x1b')
|
||||
macro_length--;
|
||||
}
|
||||
|
||||
/* Start or stop the recording of keystrokes. */
|
||||
void record_macro(void)
|
||||
{
|
||||
recording = !recording;
|
||||
|
||||
if (recording) {
|
||||
macro_length = 0;
|
||||
statusbar(_("Recording a macro..."));
|
||||
} else {
|
||||
snip_last_keystroke();
|
||||
statusbar(_("Stopped recording"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the stored sequence of codes into the regular key buffer,
|
||||
* so they will be "executed" again. */
|
||||
void run_macro(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (recording) {
|
||||
statusline(HUSH, _("Cannot run macro while recording"));
|
||||
snip_last_keystroke();
|
||||
return;
|
||||
}
|
||||
|
||||
if (macro_length == 0) {
|
||||
statusline(HUSH, _("Macro is empty"));
|
||||
return;
|
||||
}
|
||||
|
||||
free(key_buffer);
|
||||
key_buffer = (int *)nmalloc(macro_length * sizeof(int));
|
||||
key_buffer_len = macro_length;
|
||||
|
||||
for (i = 0; i < macro_length; i++)
|
||||
key_buffer[i] = macro_buffer[i];
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Control character compatibility:
|
||||
*
|
||||
@@ -113,7 +174,7 @@ static bool seen_wide = FALSE;
|
||||
* buffer is empty. */
|
||||
void get_key_buffer(WINDOW *win)
|
||||
{
|
||||
int input;
|
||||
int input = ERR;
|
||||
size_t errcount = 0;
|
||||
|
||||
/* If the keystroke buffer isn't empty, get out. */
|
||||
@@ -124,38 +185,34 @@ void get_key_buffer(WINDOW *win)
|
||||
* screen updates. */
|
||||
doupdate();
|
||||
|
||||
/* Read in the first character using whatever mode we're in. */
|
||||
input = wgetch(win);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (the_window_resized) {
|
||||
ungetch(input);
|
||||
regenerate_screen();
|
||||
input = KEY_WINCH;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (input == ERR && !waiting_mode)
|
||||
return;
|
||||
if (reveal_cursor)
|
||||
curs_set(1);
|
||||
|
||||
/* Read in the first keystroke using whatever mode we're in. */
|
||||
while (input == ERR) {
|
||||
/* If we've failed to get a character MAX_BUF_SIZE times in a row,
|
||||
* assume our input source is gone and die gracefully. We could
|
||||
* 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)
|
||||
die(_("Too many errors from stdin"));
|
||||
input = wgetch(win);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (the_window_resized) {
|
||||
regenerate_screen();
|
||||
input = KEY_WINCH;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
input = wgetch(win);
|
||||
if (input == ERR && !waiting_mode) {
|
||||
curs_set(0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we've failed to get a character MAX_BUF_SIZE times in a row,
|
||||
* assume our input source is gone and die gracefully. We could
|
||||
* check if errno is set to EIO ("Input/output error") and die in
|
||||
* that case, but it's not always set properly. Argh. */
|
||||
if (input == ERR && ++errcount == MAX_BUF_SIZE)
|
||||
die(_("Too many errors from stdin"));
|
||||
}
|
||||
|
||||
curs_set(0);
|
||||
|
||||
/* Increment the length of the keystroke buffer, and save the value
|
||||
* of the keystroke at the end of it. */
|
||||
key_buffer_len++;
|
||||
@@ -173,6 +230,10 @@ void get_key_buffer(WINDOW *win)
|
||||
nodelay(win, TRUE);
|
||||
|
||||
while (TRUE) {
|
||||
#ifndef NANO_TINY
|
||||
if (recording)
|
||||
add_to_macrobuffer(input);
|
||||
#endif
|
||||
input = wgetch(win);
|
||||
|
||||
/* If there aren't any more characters, stop reading. */
|
||||
@@ -289,10 +350,12 @@ int *get_input(WINDOW *win, size_t input_len)
|
||||
}
|
||||
|
||||
/* Read in a single keystroke, ignoring any that are invalid. */
|
||||
int get_kbinput(WINDOW *win)
|
||||
int get_kbinput(WINDOW *win, bool showcursor)
|
||||
{
|
||||
int kbinput = ERR;
|
||||
|
||||
reveal_cursor = showcursor;
|
||||
|
||||
/* Extract one keystroke from the input stream. */
|
||||
while (kbinput == ERR)
|
||||
kbinput = parse_kbinput(win);
|
||||
@@ -527,7 +590,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) {
|
||||
@@ -958,6 +1029,19 @@ int convert_sequence(const int *seq, size_t seq_len)
|
||||
}
|
||||
break;
|
||||
#ifndef NANO_TINY
|
||||
case '9': /* To accomodate iTerm2 in "xterm mode". */
|
||||
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. */
|
||||
@@ -1252,7 +1336,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);
|
||||
}
|
||||
}
|
||||
@@ -1415,11 +1499,6 @@ long get_unicode_kbinput(WINDOW *win, int kbinput)
|
||||
statusline(HUSH, _("Unicode Input: %s"), partial);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "get_unicode_kbinput(): kbinput = %d, uni_digits = %d, uni = %ld, retval = %ld\n",
|
||||
kbinput, uni_digits, uni, retval);
|
||||
#endif
|
||||
|
||||
/* If we have an end result, reset the Unicode digit counter. */
|
||||
if (retval != ERR)
|
||||
uni_digits = 0;
|
||||
@@ -1508,6 +1587,8 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *count)
|
||||
{
|
||||
int *kbinput;
|
||||
|
||||
reveal_cursor = TRUE;
|
||||
|
||||
/* Read in the first code. */
|
||||
while ((kbinput = get_input(win, 1)) == NULL)
|
||||
;
|
||||
@@ -1537,6 +1618,8 @@ int *parse_verbatim_kbinput(WINDOW *win, size_t *count)
|
||||
char *multibyte;
|
||||
int onebyte, i;
|
||||
|
||||
reveal_cursor = FALSE;
|
||||
|
||||
while (unicode == ERR) {
|
||||
free(kbinput);
|
||||
while ((kbinput = get_input(win, 1)) == NULL)
|
||||
@@ -1655,9 +1738,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)
|
||||
@@ -1675,9 +1756,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) {
|
||||
@@ -1705,12 +1783,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
|
||||
@@ -1875,7 +1951,7 @@ char *display_string(const char *buf, size_t column, size_t span, bool isdata)
|
||||
#endif
|
||||
}
|
||||
|
||||
while (*buf != '\0' && column < beyond) {
|
||||
while (*buf != '\0' && (column < beyond || mbwidth(buf) == 0)) {
|
||||
int charlength, charwidth = 1;
|
||||
|
||||
if (*buf == ' ') {
|
||||
@@ -1895,7 +1971,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])
|
||||
@@ -1966,6 +2044,19 @@ char *display_string(const char *buf, size_t column, size_t span, bool isdata)
|
||||
return converted;
|
||||
}
|
||||
|
||||
/* Determine the sequence number of the given buffer in the circular list. */
|
||||
int buffer_number(openfilestruct *buffer)
|
||||
{
|
||||
int count = 1;
|
||||
|
||||
while (buffer != firstfile) {
|
||||
buffer = buffer->prev;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* If path is NULL, we're in normal editing mode, so display the current
|
||||
* version of nano, the current filename, and whether the current file
|
||||
* has been modified on the titlebar. If path isn't NULL, we're either
|
||||
@@ -1979,21 +2070,21 @@ void titlebar(const char *path)
|
||||
/* The width that "Modified" would take up. */
|
||||
size_t offset = 0;
|
||||
/* The position at which the center part of the titlebar starts. */
|
||||
const char *branding = BRANDING;
|
||||
const char *upperleft = "";
|
||||
/* What is shown in the top left corner. */
|
||||
const char *prefix = "";
|
||||
/* What is shown before the path -- "File:", "DIR:", or "". */
|
||||
/* What is shown before the path -- "DIR:" or nothing. */
|
||||
const char *state = "";
|
||||
/* The state of the current buffer -- "Modified", "View", or "". */
|
||||
char *caption;
|
||||
/* The presentable form of the pathname. */
|
||||
char *indicator = NULL;
|
||||
/* The buffer sequence number plus buffer count. */
|
||||
|
||||
/* If the screen is too small, there is no titlebar. */
|
||||
if (topwin == NULL)
|
||||
return;
|
||||
|
||||
assert(path != NULL || openfile->filename != NULL);
|
||||
|
||||
wattron(topwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
blank_titlebar();
|
||||
@@ -2004,19 +2095,25 @@ void titlebar(const char *path)
|
||||
* then sacrifice the prefix, and only then start dottifying. */
|
||||
|
||||
/* Figure out the path, prefix and state strings. */
|
||||
if (inhelp)
|
||||
branding = "";
|
||||
#ifdef ENABLE_BROWSER
|
||||
else if (path != NULL)
|
||||
if (!inhelp && path != NULL)
|
||||
prefix = _("DIR:");
|
||||
else
|
||||
#endif
|
||||
else {
|
||||
if (!inhelp) {
|
||||
/* If there are/were multiple buffers, show which out of how many. */
|
||||
if (more_than_one) {
|
||||
indicator = charalloc(24);
|
||||
sprintf(indicator, "[%i/%i]", buffer_number(openfile),
|
||||
buffer_number(firstfile->prev));
|
||||
upperleft = indicator;
|
||||
} else
|
||||
upperleft = BRANDING;
|
||||
|
||||
if (openfile->filename[0] == '\0')
|
||||
path = _("New Buffer");
|
||||
else {
|
||||
else
|
||||
path = openfile->filename;
|
||||
prefix = _("File:");
|
||||
}
|
||||
|
||||
if (openfile->modified)
|
||||
state = _("Modified");
|
||||
@@ -2027,7 +2124,7 @@ void titlebar(const char *path)
|
||||
}
|
||||
|
||||
/* Determine the widths of the four elements, including their padding. */
|
||||
verlen = strlenpt(branding) + 3;
|
||||
verlen = strlenpt(upperleft) + 3;
|
||||
prefixlen = strlenpt(prefix);
|
||||
if (prefixlen > 0)
|
||||
prefixlen++;
|
||||
@@ -2040,7 +2137,7 @@ void titlebar(const char *path)
|
||||
|
||||
/* Only print the version message when there is room for it. */
|
||||
if (verlen + prefixlen + pathlen + pluglen + statelen <= COLS)
|
||||
mvwaddstr(topwin, 0, 2, branding);
|
||||
mvwaddstr(topwin, 0, 2, upperleft);
|
||||
else {
|
||||
verlen = 2;
|
||||
/* If things don't fit yet, give up the placeholder. */
|
||||
@@ -2053,6 +2150,8 @@ void titlebar(const char *path)
|
||||
}
|
||||
}
|
||||
|
||||
free(indicator);
|
||||
|
||||
/* If we have side spaces left, center the path name. */
|
||||
if (verlen > 0)
|
||||
offset = verlen + (COLS - (verlen + pluglen + statelen) -
|
||||
@@ -2148,14 +2247,12 @@ void statusline(message_type importance, const char *msg, ...)
|
||||
if (importance == ALERT) {
|
||||
if (++alerts > 3 && !ISSET(NO_PAUSES))
|
||||
msg = _("Further warnings were suppressed");
|
||||
beep();
|
||||
else if (alerts < 4)
|
||||
beep();
|
||||
}
|
||||
|
||||
lastmessage = importance;
|
||||
|
||||
/* Turn the cursor off while fiddling in the statusbar. */
|
||||
curs_set(0);
|
||||
|
||||
blank_statusbar();
|
||||
|
||||
/* Construct the message out of all the arguments. */
|
||||
@@ -2241,7 +2338,7 @@ void bottombars(int menu)
|
||||
|
||||
wmove(bottomwin, 1 + i % 2, (i / 2) * itemwidth);
|
||||
|
||||
onekey(s->keystr, _(f->desc), itemwidth + (COLS % itemwidth));
|
||||
post_one_key(s->keystr, _(f->desc), itemwidth + (COLS % itemwidth));
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -2250,32 +2347,29 @@ void bottombars(int menu)
|
||||
wrefresh(bottomwin);
|
||||
}
|
||||
|
||||
/* Write a shortcut key to the help area at the bottom of the window.
|
||||
* keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
|
||||
* to write at most length characters, even if length is very small and
|
||||
* keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
|
||||
* the whole string! We do not bother padding the entry with blanks. */
|
||||
void onekey(const char *keystroke, const char *desc, int length)
|
||||
/* Write a key's representation plus a minute description of its function
|
||||
* to the screen. For example, the key could be "^C" and its tag "Cancel".
|
||||
* Key plus tag may occupy at most width columns. */
|
||||
void post_one_key(const char *keystroke, const char *tag, int width)
|
||||
{
|
||||
assert(keystroke != NULL && desc != NULL);
|
||||
|
||||
wattron(bottomwin, interface_color_pair[KEY_COMBO]);
|
||||
waddnstr(bottomwin, keystroke, actual_x(keystroke, length));
|
||||
waddnstr(bottomwin, keystroke, actual_x(keystroke, width));
|
||||
wattroff(bottomwin, interface_color_pair[KEY_COMBO]);
|
||||
|
||||
length -= strlenpt(keystroke) + 1;
|
||||
/* If the remaning space is too small, skip the description. */
|
||||
width -= strlenpt(keystroke);
|
||||
if (width < 2)
|
||||
return;
|
||||
|
||||
if (length > 0) {
|
||||
waddch(bottomwin, ' ');
|
||||
wattron(bottomwin, interface_color_pair[FUNCTION_TAG]);
|
||||
waddnstr(bottomwin, desc, actual_x(desc, length));
|
||||
wattroff(bottomwin, interface_color_pair[FUNCTION_TAG]);
|
||||
}
|
||||
waddch(bottomwin, ' ');
|
||||
wattron(bottomwin, interface_color_pair[FUNCTION_TAG]);
|
||||
waddnstr(bottomwin, tag, actual_x(tag, width - 1));
|
||||
wattroff(bottomwin, interface_color_pair[FUNCTION_TAG]);
|
||||
}
|
||||
|
||||
/* 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();
|
||||
@@ -2306,8 +2400,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
|
||||
@@ -2321,7 +2414,7 @@ void place_the_cursor(bool forreal)
|
||||
void edit_draw(filestruct *fileptr, const char *converted,
|
||||
int row, size_t from_col)
|
||||
{
|
||||
#if !defined(NANO_TINY) || !defined(DISABLE_COLOR)
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_COLOR)
|
||||
size_t from_x = actual_x(fileptr->data, from_col);
|
||||
/* The position in fileptr->data of the leftmost character
|
||||
* that displays at least partially on the window. */
|
||||
@@ -2331,20 +2424,17 @@ void edit_draw(filestruct *fileptr, const char *converted,
|
||||
* might be beyond the null terminator of the string. */
|
||||
#endif
|
||||
|
||||
assert(openfile != NULL && fileptr != NULL && converted != NULL);
|
||||
assert(strlenpt(converted) <= editwincols);
|
||||
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
/* If line numbering is switched on, put a line number in front of
|
||||
* the text -- but only for the parts that are not softwrapped. */
|
||||
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
|
||||
mvwprintw(edit, row, 0, "%*ld", margin - 1, (long)fileptr->lineno);
|
||||
mvwprintw(edit, row, 0, "%*zd", margin - 1, fileptr->lineno);
|
||||
wattroff(edit, interface_color_pair[LINE_NUMBER]);
|
||||
}
|
||||
#endif
|
||||
@@ -2361,7 +2451,7 @@ void edit_draw(filestruct *fileptr, const char *converted,
|
||||
wredrawln(edit, row, 1);
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
/* If color syntaxes are available and turned on, apply them. */
|
||||
if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
|
||||
const colortype *varnish = openfile->colorstrings;
|
||||
@@ -2609,15 +2699,15 @@ void edit_draw(filestruct *fileptr, const char *converted,
|
||||
wattroff(edit, varnish->attributes);
|
||||
}
|
||||
}
|
||||
#endif /* !DISABLE_COLOR */
|
||||
#endif /* ENABLE_COLOR */
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the mark is on, and fileptr is at least partially selected, we
|
||||
* need to paint it. */
|
||||
if (openfile->mark_set &&
|
||||
(fileptr->lineno <= openfile->mark_begin->lineno ||
|
||||
if (openfile->mark &&
|
||||
(fileptr->lineno <= openfile->mark->lineno ||
|
||||
fileptr->lineno <= openfile->current->lineno) &&
|
||||
(fileptr->lineno >= openfile->mark_begin->lineno ||
|
||||
(fileptr->lineno >= openfile->mark->lineno ||
|
||||
fileptr->lineno >= openfile->current->lineno)) {
|
||||
const filestruct *top, *bot;
|
||||
/* The lines where the marked region begins and ends. */
|
||||
@@ -2654,9 +2744,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 */
|
||||
@@ -2788,7 +2878,7 @@ int update_softwrapped_line(filestruct *fileptr)
|
||||
bool line_needs_update(const size_t old_column, const size_t new_column)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set)
|
||||
if (openfile->mark)
|
||||
return TRUE;
|
||||
else
|
||||
#endif
|
||||
@@ -2803,10 +2893,6 @@ 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)) {
|
||||
/* Recede through the requested number of chunks. */
|
||||
@@ -2896,7 +2982,7 @@ bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge)
|
||||
|
||||
/* Scroll the edit window in the given direction and the given number of rows,
|
||||
* and draw new lines on the blank lines left after the scrolling. */
|
||||
void edit_scroll(scroll_dir direction, int nrows)
|
||||
void edit_scroll(bool direction, int nrows)
|
||||
{
|
||||
filestruct *line;
|
||||
size_t leftedge;
|
||||
@@ -2906,7 +2992,7 @@ void edit_scroll(scroll_dir direction, int nrows)
|
||||
|
||||
/* Move the top line of the edit window the requested number of rows up or
|
||||
* down, and reduce the number of rows with the amount we couldn't move. */
|
||||
if (direction == UPWARD)
|
||||
if (direction == BACKWARD)
|
||||
nrows -= go_back_chunks(nrows, &openfile->edittop, &openfile->firstcolumn);
|
||||
else
|
||||
nrows -= go_forward_chunks(nrows, &openfile->edittop, &openfile->firstcolumn);
|
||||
@@ -2929,7 +3015,7 @@ void edit_scroll(scroll_dir direction, int nrows)
|
||||
|
||||
/* Scroll the text of the edit window a number of rows up or down. */
|
||||
scrollok(edit, TRUE);
|
||||
wscrl(edit, (direction == UPWARD) ? -nrows : nrows);
|
||||
wscrl(edit, (direction == BACKWARD) ? -nrows : nrows);
|
||||
scrollok(edit, FALSE);
|
||||
|
||||
/* Part 2: nrows is now the number of rows in the scrolled region of the
|
||||
@@ -2945,7 +3031,7 @@ void edit_scroll(scroll_dir direction, int nrows)
|
||||
leftedge = openfile->firstcolumn;
|
||||
|
||||
/* If we scrolled forward, move down to the start of the blank region. */
|
||||
if (direction == DOWNWARD)
|
||||
if (direction == FORWARD)
|
||||
go_forward_chunks(editwinrows - nrows, &line, &leftedge);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -2976,61 +3062,55 @@ void edit_scroll(scroll_dir direction, int nrows)
|
||||
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 goal_column = leftedge + editwincols;
|
||||
/* The place at or before which text must be broken. */
|
||||
size_t breaking_col = goal_column;
|
||||
/* The column where text can be broken, when there's no better. */
|
||||
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. */
|
||||
size_t last_blank_col = 0;
|
||||
/* The column position of the last seen whitespace character. */
|
||||
const char *farthest_blank = NULL;
|
||||
/* A pointer to the last seen whitespace character in text. */
|
||||
|
||||
/* First find the place in text where the current chunk starts. */
|
||||
while (*text != '\0' && column < leftedge)
|
||||
text += parse_mbchar(text, NULL, &column);
|
||||
|
||||
/* Use a full screen row for text. */
|
||||
goal_column = column + editwincols;
|
||||
|
||||
/* Now find the place in text where this chunk should end. */
|
||||
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;
|
||||
farthest_blank = text;
|
||||
last_blank_col = column;
|
||||
}
|
||||
|
||||
prev_column = column;
|
||||
char_len = parse_mbchar(text, NULL, &column);
|
||||
text += char_len;
|
||||
index += char_len;
|
||||
breaking_col = (*text == '\t' ? goal_column : column);
|
||||
text += parse_mbchar(text, NULL, &column);
|
||||
}
|
||||
|
||||
/* If we didn't overshoot the target, we've found a breaking point. */
|
||||
/* If we didn't overshoot the limit, we've found a breaking point;
|
||||
* and we've reached EOL if we didn't even *reach* the limit. */
|
||||
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);
|
||||
return lastblank_column;
|
||||
/* If we're softwrapping at blanks and we found at least one blank, break
|
||||
* after that blank -- if it doesn't overshoot the screen's edge. */
|
||||
if (farthest_blank != NULL) {
|
||||
parse_mbchar(farthest_blank, NULL, &last_blank_col);
|
||||
|
||||
if (last_blank_col <= goal_column)
|
||||
return last_blank_col;
|
||||
|
||||
/* If it's a tab that overshoots, break at the screen's edge. */
|
||||
if (*farthest_blank == '\t')
|
||||
breaking_col = 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;
|
||||
/* Otherwise, break at the last character that doesn't overshoot. */
|
||||
return (editwincols > 1) ? breaking_col : column - 1;
|
||||
}
|
||||
|
||||
/* Get the row of the softwrapped chunk of the given line that column is on,
|
||||
@@ -3060,7 +3140,10 @@ size_t get_chunk_and_edge(size_t column, filestruct *line, size_t *leftedge)
|
||||
* relative to the first row (zero-based). */
|
||||
size_t chunk_for(size_t column, filestruct *line)
|
||||
{
|
||||
return get_chunk_and_edge(column, line, NULL);
|
||||
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
|
||||
@@ -3069,6 +3152,9 @@ 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;
|
||||
@@ -3108,7 +3194,7 @@ size_t actual_last_column(size_t leftedge, size_t column)
|
||||
|
||||
/* 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. */
|
||||
* a multi-column character, but actual_x() will fix that later. */
|
||||
if (!last_chunk)
|
||||
end_col--;
|
||||
|
||||
@@ -3167,7 +3253,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;
|
||||
|
||||
@@ -3175,14 +3261,14 @@ 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;
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the mark is on, update all lines between old_current and current. */
|
||||
if (openfile->mark_set) {
|
||||
if (openfile->mark) {
|
||||
filestruct *line = old_current;
|
||||
|
||||
while (line != openfile->current) {
|
||||
@@ -3213,24 +3299,15 @@ void edit_refresh(void)
|
||||
filestruct *line;
|
||||
int row = 0;
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
/* When needed, initialize the colors for the current syntax. */
|
||||
if (!have_palette)
|
||||
color_init();
|
||||
#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;
|
||||
|
||||
@@ -3245,7 +3322,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;
|
||||
@@ -3275,10 +3352,6 @@ void adjust_viewport(update_type manner)
|
||||
|
||||
/* 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. */
|
||||
@@ -3315,7 +3388,7 @@ void total_refresh(void)
|
||||
* portion of the window. */
|
||||
void display_main_list(void)
|
||||
{
|
||||
#ifndef DISABLE_COLOR
|
||||
#ifdef ENABLE_COLOR
|
||||
if (openfile->syntax &&
|
||||
(openfile->syntax->formatter || openfile->syntax->linter))
|
||||
set_lint_or_format_shortcuts();
|
||||
@@ -3342,9 +3415,6 @@ void do_cursorpos(bool force)
|
||||
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];
|
||||
openfile->current->data[openfile->current_x] = '\0';
|
||||
@@ -3398,7 +3468,7 @@ void spotlight(bool active, size_t from_col, size_t to_col)
|
||||
char *word;
|
||||
size_t word_span, room;
|
||||
|
||||
place_the_cursor(FALSE);
|
||||
place_the_cursor();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
@@ -3425,7 +3495,7 @@ void spotlight(bool active, size_t from_col, size_t to_col)
|
||||
room--;
|
||||
|
||||
if (active)
|
||||
wattron(edit, hilite_attribute);
|
||||
wattron(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
waddnstr(edit, word, actual_x(word, room));
|
||||
|
||||
@@ -3433,7 +3503,7 @@ void spotlight(bool active, size_t from_col, size_t to_col)
|
||||
waddch(edit, '$');
|
||||
|
||||
if (active)
|
||||
wattroff(edit, hilite_attribute);
|
||||
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
free(word);
|
||||
|
||||
@@ -3472,12 +3542,12 @@ void spotlight_softwrapped(bool active, size_t from_col, size_t to_col)
|
||||
break_col - from_col, FALSE);
|
||||
|
||||
if (active)
|
||||
wattron(edit, hilite_attribute);
|
||||
wattron(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
waddnstr(edit, word, actual_x(word, break_col));
|
||||
|
||||
if (active)
|
||||
wattroff(edit, hilite_attribute);
|
||||
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
free(word);
|
||||
|
||||
@@ -3494,7 +3564,7 @@ void spotlight_softwrapped(bool active, size_t from_col, size_t to_col)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_EXTRA
|
||||
#ifdef ENABLE_EXTRA
|
||||
#define CREDIT_LEN 54
|
||||
#define XLCREDIT_LEN 9
|
||||
|
||||
@@ -3580,7 +3650,6 @@ void do_credits(void)
|
||||
window_init();
|
||||
}
|
||||
|
||||
curs_set(0);
|
||||
nodelay(edit, TRUE);
|
||||
|
||||
blank_titlebar();
|
||||
@@ -3644,4 +3713,4 @@ void do_credits(void)
|
||||
|
||||
total_refresh();
|
||||
}
|
||||
#endif /* !DISABLE_EXTRA */
|
||||
#endif /* ENABLE_EXTRA */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Here is an example for assembler.
|
||||
|
||||
syntax "asm" "\.(S|s|asm)$"
|
||||
magic "[Aa]ssembl(y|er)"
|
||||
magic "assembler source"
|
||||
comment "//"
|
||||
|
||||
color red "\<[A-Z_]{2,}\>"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Here is an example for awk.
|
||||
|
||||
syntax "awk" "\.awk$"
|
||||
magic "awk.*script text"
|
||||
magic "awk script"
|
||||
comment "#"
|
||||
|
||||
# Records.
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
## Here is an example for C/C++.
|
||||
|
||||
syntax "c" "\.(c(c|pp|xx|\+\+)?|C)$" "\.(h(h|pp|xx)?|H)$" "\.ii?$"
|
||||
magic "(ASCII|UTF-8 Unicode) C(\+\+)? program text"
|
||||
magic "^(C|C\+\+) (source|program)"
|
||||
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)\>"
|
||||
|
||||
@@ -14,4 +14,4 @@ color ,red " + +"
|
||||
color brightred "(GNU )?nano [1-9]\.[0-9]\.[^[:space:][:punct:]]+"
|
||||
|
||||
# Email addresses.
|
||||
color yellow "<[[:alnum:].%_+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}>"
|
||||
color magenta "<[[:alnum:].%_+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}>"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## Here is an example for Emacs Lisp.
|
||||
|
||||
syntax "elisp" "\.el$"
|
||||
magic "Lisp/Scheme program"
|
||||
comment ";"
|
||||
|
||||
# Basic functions/macros
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
syntax "guile" "\.scm$"
|
||||
header "^#!.*guile"
|
||||
magic "guile"
|
||||
comment ";"
|
||||
|
||||
# Basic scheme functions
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
## Here is an example for HTML.
|
||||
|
||||
syntax "html" "\.html?$"
|
||||
magic "HTML document text"
|
||||
magic "HTML document"
|
||||
comment "<!--|-->"
|
||||
|
||||
# Tags:
|
||||
color cyan start="<[[:alpha:]/!?]" end=">"
|
||||
color cyan "<[[:alpha:]/!?][^>]*>"
|
||||
# Bold, italic, and underlined:
|
||||
color brightmagenta "</?[biu]>"
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
## Version: 2011-05-05
|
||||
|
||||
syntax "lua" "\.lua$"
|
||||
magic "Lua script"
|
||||
comment "--"
|
||||
|
||||
color brightwhite "\[\[.*\]\]"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## Here is an example for Makefiles.
|
||||
|
||||
syntax "makefile" "Makefile[^/]*$" "\.(make|mk)$"
|
||||
magic "makefile script"
|
||||
comment "#"
|
||||
|
||||
color red "[:=]"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Here is an example for manpages.
|
||||
|
||||
syntax "man" "\.[1-9]x?$"
|
||||
magic "troff or preprocessor input text"
|
||||
magic "troff or preprocessor input"
|
||||
comment ".\""
|
||||
|
||||
color green "\.(SH|SS|TH) .*$"
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
syntax "nanohelp"
|
||||
|
||||
# Key combos:
|
||||
color cyan "\^([]4-8A-Z^\_←→↑↓]|Home|End)" "[←→↑↓]"
|
||||
color cyan "\<(Tab|Enter|Home|End|Ins|Del|Bsp|PgUp|PgDn)\>"
|
||||
color cyan "\<M-." "\<F1?[0-9]" "(\^|M-)Space"
|
||||
color cyan "\^[]4-8A-Z^\_◀▶▲▼]" "[◀▶▲▼]" "(\^|M-)Space" "\<M-." "\<F1?[0-9]"
|
||||
color cyan "\<(Tab|Enter|Ins|Del|Bsp|Up|Down|Left|Right|Home|End|PgUp|PgDn)\>"
|
||||
|
||||
# Quoted indicators:
|
||||
color brightred "'(\^|M-)'"
|
||||
|
||||
@@ -8,8 +8,8 @@ icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comm
|
||||
|
||||
# Keywords
|
||||
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cutfromcursor|fill[[:space:]]+-?[[:digit:]]+|historylog|justifytrim|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[1-9][0-9]*|tabstospaces|tempfile|unix|view|wordbounds)\>"
|
||||
icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|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|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+"
|
||||
icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|selected|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>"
|
||||
icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|selectedcolor|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+"
|
||||
icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
|
||||
icolor brightgreen "^[[:space:]]*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:]]+.*$"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## Here is an example for C/C++/Obj-C.
|
||||
|
||||
syntax "m" "\.m$"
|
||||
magic "Objective-C source"
|
||||
comment "//"
|
||||
|
||||
# Stuffs,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## Syntax highlighting for OCaml.
|
||||
|
||||
syntax "ocaml" "\.mli?$"
|
||||
magic "OCaml"
|
||||
comment "(*|*)"
|
||||
|
||||
# Uid:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Here is an example for patch files.
|
||||
|
||||
syntax "patch" "\.(patch|diff|debdiff)$"
|
||||
magic "diff output text"
|
||||
magic "diff output"
|
||||
# There is no official support for comments in patch files.
|
||||
comment ""
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
syntax "perl" "\.p[lm]$"
|
||||
header "^#!.*perl[-0-9._]*"
|
||||
magic "Perl script text"
|
||||
magic "Perl script"
|
||||
comment "#"
|
||||
|
||||
color red "\<(accept|alarm|atan2|bin(d|mode)|c(aller|h(dir|mod|op|own|root)|lose(dir)?|onnect|os|rypt)|d(bm(close|open)|efined|elete|ie|o|ump)|e(ach|of|val|x(ec|ists|it|p))|f(cntl|ileno|lock|ork))\>" "\<(get(c|login|peername|pgrp|ppid|priority|pwnam|(host|net|proto|serv)byname|pwuid|grgid|(host|net)byaddr|protobynumber|servbyport)|([gs]et|end)(pw|gr|host|net|proto|serv)ent|getsock(name|opt)|gmtime|goto|grep|hex|index|int|ioctl|join)\>" "\<(keys|kill|last|length|link|listen|local(time)?|log|lstat|m|mkdir|msg(ctl|get|snd|rcv)|next|oct|open(dir)?|ord|pack|pipe|pop|printf?|push|q|qq|qx|rand|re(ad(dir|link)?|cv|do|name|quire|set|turn|verse|winddir)|rindex|rmdir|s|scalar|seek(dir)?)\>" "\<(se(lect|mctl|mget|mop|nd|tpgrp|tpriority|tsockopt)|shift|shm(ctl|get|read|write)|shutdown|sin|sleep|socket(pair)?|sort|spli(ce|t)|sprintf|sqrt|srand|stat|study|substr|symlink|sys(call|read|tem|write)|tell(dir)?|time|tr(y)?|truncate|umask)\>" "\<(un(def|link|pack|shift)|utime|values|vec|wait(pid)?|wantarray|warn|write)\>"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Here is an example for PHP.
|
||||
|
||||
syntax "php" "\.ph(p[23457s~]?|tml)$"
|
||||
magic "PHP script text"
|
||||
magic "PHP script"
|
||||
comment "//"
|
||||
|
||||
# PHP markings.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
## Here is an example for PostgreSQL.
|
||||
|
||||
syntax "sql" "\.sql[2345s~]?$"
|
||||
magic "PostgreSQL script text"
|
||||
comment "-- "
|
||||
|
||||
# Functions.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
syntax "python" "\.py$"
|
||||
header "^#!.*python[-0-9._]*"
|
||||
magic "Python script"
|
||||
linter pyflakes
|
||||
comment "#"
|
||||
|
||||
@@ -17,8 +18,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)"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
syntax "ruby" "\.rb$"
|
||||
header "^#!.*ruby[-0-9._]*"
|
||||
magic "Ruby script"
|
||||
linter ruby -w -c
|
||||
comment "#"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
syntax "sh" "\.sh$"
|
||||
header "^#!.*((ba|da|k|pdk)?sh[-0-9_]*|openrc-run|runscript)"
|
||||
magic "(POSIX|Bourne.*) shell script text"
|
||||
magic "(POSIX|Bourne-Again) shell script.*text"
|
||||
linter dash -n
|
||||
comment "#"
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## Syntax highlighting for Tcl files.
|
||||
|
||||
syntax "tcl" "\.tcl$"
|
||||
magic "Tcl(/Tk)? script"
|
||||
comment "#"
|
||||
|
||||
# Standard Tcl [info commands]:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## Here is a short example for TeX files.
|
||||
|
||||
syntax "tex" "\.tex$"
|
||||
magic "(La)?TeX document"
|
||||
linter chktex -v0 -q -I
|
||||
comment "%"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
syntax "texinfo" "\.texi$"
|
||||
header "^\\input texinfo"
|
||||
magic "Texinfo source text"
|
||||
magic "Texinfo source"
|
||||
comment "@c "
|
||||
|
||||
# Command arguments, trailing and enclosed.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
syntax "xml" "\.([jrsx]html?|jnlp|mml|pom|rng|sgml?|svg|w[as]dl|wsdd|xjb|xml|xs(d|lt?)|xul)$"
|
||||
header "<\?xml.*version=.*\?>"
|
||||
magic "(XML|SGML) (sub)?document text"
|
||||
magic "(XML|SGML) (sub)?document"
|
||||
comment "<!--|-->"
|
||||
|
||||
# The entire content of the tag:
|
||||
|
||||
Reference in New Issue
Block a user