Compare commits
416 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f92fb3ec4 | ||
|
|
293423bdda | ||
|
|
32719d64a1 | ||
|
|
f4321250ef | ||
|
|
908663e8fc | ||
|
|
1fb820386b | ||
|
|
9973366685 | ||
|
|
e72db0e350 | ||
|
|
87b2df6dea | ||
|
|
c24caf5fb8 | ||
|
|
8db21b68d5 | ||
|
|
cb31e45f6c | ||
|
|
588daf949e | ||
|
|
d21a9c8fc3 | ||
|
|
edbc1e5950 | ||
|
|
dc18746cbd | ||
|
|
c92b9be6cd | ||
|
|
eef7d1047a | ||
|
|
d49d4f7b56 | ||
|
|
2fbb71d555 | ||
|
|
66356ec7e2 | ||
|
|
4edc83c3c2 | ||
|
|
e6350aaba4 | ||
|
|
8bf8682b17 | ||
|
|
a9b5a0e029 | ||
|
|
026393a91a | ||
|
|
db897b574f | ||
|
|
2b1bc6866a | ||
|
|
90b959a677 | ||
|
|
116d9e6f01 | ||
|
|
6620acbff4 | ||
|
|
1cb6619d6a | ||
|
|
79a4bf81dc | ||
|
|
b77e6bd99d | ||
|
|
2bcc6d7f66 | ||
|
|
cd705a7c4c | ||
|
|
ecd18c1694 | ||
|
|
bc8a3a50a4 | ||
|
|
9b90ec877a | ||
|
|
8b483c10ba | ||
|
|
f915a28d30 | ||
|
|
cb3fc8892a | ||
|
|
06d9ee89e5 | ||
|
|
0b0b812206 | ||
|
|
eafae5d417 | ||
|
|
dfff78dffe | ||
|
|
40acb8714c | ||
|
|
d7af590c6b | ||
|
|
8c7e4f5108 | ||
|
|
1144d38316 | ||
|
|
0562d27b9c | ||
|
|
c5f49167ea | ||
|
|
9765c2faa0 | ||
|
|
85ebe971e2 | ||
|
|
fc101a6ded | ||
|
|
eb88ad980a | ||
|
|
9fa95a3680 | ||
|
|
d6cc2c40fe | ||
|
|
1df4115013 | ||
|
|
ea9f62fc0f | ||
|
|
a772194102 | ||
|
|
faf77fb1ec | ||
|
|
b0b24d9c3a | ||
|
|
c9f743f676 | ||
|
|
bd920b1f49 | ||
|
|
29e094cd21 | ||
|
|
7a8ae90dac | ||
|
|
13ec5d8ce9 | ||
|
|
30591c5e01 | ||
|
|
3f8e30efb1 | ||
|
|
e9fde7d7dc | ||
|
|
fd3423f79a | ||
|
|
a4044a7e5d | ||
|
|
2fa93ae999 | ||
|
|
c8c6340ce8 | ||
|
|
6263416355 | ||
|
|
84d6f1a5b6 | ||
|
|
ecccb8d027 | ||
|
|
173bbe11ef | ||
|
|
7531b71fa1 | ||
|
|
964c10db17 | ||
|
|
0e01080983 | ||
|
|
68a0314500 | ||
|
|
dca4ab5d8f | ||
|
|
86121cf3fc | ||
|
|
f03f5d5b51 | ||
|
|
379b1556ed | ||
|
|
bfcce57b69 | ||
|
|
4eac699df3 | ||
|
|
454f5cbdce | ||
|
|
248d7be8ef | ||
|
|
372bd0f7dd | ||
|
|
f920e0d30c | ||
|
|
0f3e303d1a | ||
|
|
c9680b8b64 | ||
|
|
656563beda | ||
|
|
8f95f9b1aa | ||
|
|
c6512a9717 | ||
|
|
07ce01c189 | ||
|
|
b5400ffe65 | ||
|
|
ac41587d4e | ||
|
|
e4b8d6fab5 | ||
|
|
72e8bcb027 | ||
|
|
7401670d58 | ||
|
|
87fbe24283 | ||
|
|
e4d452424b | ||
|
|
d48071b2b2 | ||
|
|
c1a484270b | ||
|
|
981a1d39bf | ||
|
|
925a001658 | ||
|
|
77023a749b | ||
|
|
1762920808 | ||
|
|
281a56fb74 | ||
|
|
592d0d6c9a | ||
|
|
3cc561e36e | ||
|
|
0333b87ad7 | ||
|
|
059c8efb44 | ||
|
|
eb68cd1c6b | ||
|
|
ecea413802 | ||
|
|
95253231e8 | ||
|
|
eb5968f845 | ||
|
|
f2c72bf759 | ||
|
|
e472b72565 | ||
|
|
e332d2df74 | ||
|
|
ed165827bc | ||
|
|
65bf36baa5 | ||
|
|
7598b77e75 | ||
|
|
a4132e2e64 | ||
|
|
8a66c820ab | ||
|
|
af0f81f71d | ||
|
|
ea1afac9db | ||
|
|
04aab233d0 | ||
|
|
33bc848c5b | ||
|
|
4c476bc872 | ||
|
|
9c2e270b3e | ||
|
|
0eef5610eb | ||
|
|
2a55d2b29a | ||
|
|
5416b9c09d | ||
|
|
7287300e0d | ||
|
|
ffeb0f9d4b | ||
|
|
10c9093942 | ||
|
|
b38cbfe173 | ||
|
|
702b09c859 | ||
|
|
2cd8ca4eb1 | ||
|
|
55b1403542 | ||
|
|
9d5ee16614 | ||
|
|
01bbf7e82f | ||
|
|
3ed5ddba31 | ||
|
|
6cacd1e320 | ||
|
|
d9cae81a0e | ||
|
|
83ee1feda4 | ||
|
|
c7610ba356 | ||
|
|
ae648778e2 | ||
|
|
023edffe3d | ||
|
|
2789bb0813 | ||
|
|
4d996e4c39 | ||
|
|
de2aa4f24a | ||
|
|
de95ca68f7 | ||
|
|
55878efe5d | ||
|
|
43f35fc7a9 | ||
|
|
d66ea08473 | ||
|
|
8476bf86a1 | ||
|
|
c92982d60f | ||
|
|
7a274d621a | ||
|
|
fdee0df849 | ||
|
|
00efa50385 | ||
|
|
a35803d502 | ||
|
|
7013039c3a | ||
|
|
925ad6393a | ||
|
|
3264d0c5be | ||
|
|
d9148e7b3f | ||
|
|
0a18d8912b | ||
|
|
815b326864 | ||
|
|
01bf034bb6 | ||
|
|
d716809228 | ||
|
|
8041627cc3 | ||
|
|
598e0af7af | ||
|
|
8ba57cf87b | ||
|
|
e2027aee15 | ||
|
|
97f6ae5267 | ||
|
|
fc9c7b4917 | ||
|
|
77a1a5c3e4 | ||
|
|
bc8bb7e942 | ||
|
|
08cd197bf1 | ||
|
|
4de0a5049b | ||
|
|
dc76e84657 | ||
|
|
1c2b35675e | ||
|
|
add0d698b7 | ||
|
|
09e95b2d91 | ||
|
|
03fd6f3af8 | ||
|
|
b92d35d1f2 | ||
|
|
9eeb1c8fb8 | ||
|
|
ad83ed22d9 | ||
|
|
3ddf6ff955 | ||
|
|
d04c0b7555 | ||
|
|
f13707fd1d | ||
|
|
ed9e5d7183 | ||
|
|
2fd497e3ef | ||
|
|
fd6308d6d3 | ||
|
|
1dbebbcadc | ||
|
|
57d1755d10 | ||
|
|
bace664fbc | ||
|
|
acd8809d71 | ||
|
|
7b7d2bf7c9 | ||
|
|
244de605a7 | ||
|
|
002652d263 | ||
|
|
08b770d425 | ||
|
|
2dffcf101f | ||
|
|
96fbdfbc7d | ||
|
|
272a953889 | ||
|
|
db310ac9b6 | ||
|
|
c11c688420 | ||
|
|
514cd9a099 | ||
|
|
406e5242a3 | ||
|
|
c26f58e783 | ||
|
|
5ad26f864a | ||
|
|
e7f39bc248 | ||
|
|
0242d84218 | ||
|
|
7275e11c4f | ||
|
|
77d140728d | ||
|
|
4d2ada60f5 | ||
|
|
382c9d792d | ||
|
|
aeb49a8013 | ||
|
|
c05c914eee | ||
|
|
c19f0c732e | ||
|
|
6ad3700a3d | ||
|
|
4f156aa6db | ||
|
|
6142ef87b5 | ||
|
|
da2fce90bd | ||
|
|
1e3cffbbd6 | ||
|
|
92c97c70d4 | ||
|
|
b77b1391c3 | ||
|
|
7e0c4e5726 | ||
|
|
50616148b0 | ||
|
|
3e40e5d4b5 | ||
|
|
2f9232a493 | ||
|
|
0d5fbfb91c | ||
|
|
56147434f3 | ||
|
|
21cb01e543 | ||
|
|
ea9aaee8c7 | ||
|
|
c22cd03f18 | ||
|
|
bd1c5d7c63 | ||
|
|
00b293bf70 | ||
|
|
76a960d73d | ||
|
|
97eb0e515f | ||
|
|
68010d931a | ||
|
|
c661506681 | ||
|
|
0dd2a55284 | ||
|
|
49fc528d88 | ||
|
|
928a24c204 | ||
|
|
d8031af030 | ||
|
|
f85648db68 | ||
|
|
b2e2c89b62 | ||
|
|
290d278f68 | ||
|
|
8edb096821 | ||
|
|
0a387d9d08 | ||
|
|
6c16744292 | ||
|
|
86a64b1bb5 | ||
|
|
1fd2354ad4 | ||
|
|
c8bc05b10e | ||
|
|
ee57cbfa66 | ||
|
|
bd1fcc5fe2 | ||
|
|
370406bb41 | ||
|
|
85844ee6ef | ||
|
|
e38e2c634b | ||
|
|
d80109dd5e | ||
|
|
b305911cba | ||
|
|
d60f95137e | ||
|
|
14ac47517b | ||
|
|
20058a1b63 | ||
|
|
f6dd0ad18a | ||
|
|
a7ae1766c0 | ||
|
|
faa46a3c71 | ||
|
|
03b168d0e3 | ||
|
|
2f6647687a | ||
|
|
c9e9964207 | ||
|
|
0a3a6441bc | ||
|
|
2eafe7bf58 | ||
|
|
08c51cfd45 | ||
|
|
b472f5a633 | ||
|
|
5806bf5249 | ||
|
|
90a90365a8 | ||
|
|
9cd30d4917 | ||
|
|
f33d8cae30 | ||
|
|
e471e2d462 | ||
|
|
fe38b78486 | ||
|
|
1af1f5c9f4 | ||
|
|
b9e83fe9f8 | ||
|
|
cb10b2b908 | ||
|
|
19dfd20a88 | ||
|
|
d12fdda15b | ||
|
|
3930a697e8 | ||
|
|
9322e1e6a4 | ||
|
|
b70fe38eab | ||
|
|
1c528db8da | ||
|
|
1c9ab8bf16 | ||
|
|
e295070193 | ||
|
|
91951ab22a | ||
|
|
5b0ab8be62 | ||
|
|
ecef093def | ||
|
|
6d6f5bd4a7 | ||
|
|
e3dbffc9f7 | ||
|
|
2225d54126 | ||
|
|
9115828e76 | ||
|
|
b43a72471a | ||
|
|
2b5d29b8c6 | ||
|
|
b40520b574 | ||
|
|
992533b91e | ||
|
|
f3e8991206 | ||
|
|
df7353b312 | ||
|
|
f311c0af87 | ||
|
|
c88fae3310 | ||
|
|
68cfb08888 | ||
|
|
4cff67fdde | ||
|
|
aefe26d216 | ||
|
|
8eb99e2a1d | ||
|
|
19b6f906cc | ||
|
|
c38ffdc741 | ||
|
|
a472f480a7 | ||
|
|
4416d9c941 | ||
|
|
c073c5ae54 | ||
|
|
fc0ddab349 | ||
|
|
c6dbcf91c3 | ||
|
|
8c7a38596d | ||
|
|
1c2d2a4027 | ||
|
|
1e5614b31b | ||
|
|
04b9b9c78b | ||
|
|
41ad376b70 | ||
|
|
1349c1d02c | ||
|
|
4c566c7903 | ||
|
|
73a07215cc | ||
|
|
bf091be778 | ||
|
|
103dd06347 | ||
|
|
1d4c1e0bfc | ||
|
|
b3fbb7c7ff | ||
|
|
225203d40d | ||
|
|
c2a0c78d9b | ||
|
|
97f4fe26f0 | ||
|
|
ef071255e5 | ||
|
|
afb6a5b86d | ||
|
|
a37cd9f0ef | ||
|
|
6f12992cea | ||
|
|
d88423eaae | ||
|
|
8b28de1313 | ||
|
|
8fa72fb7e7 | ||
|
|
b4babc2036 | ||
|
|
f2150d3f98 | ||
|
|
033376aec0 | ||
|
|
e33a0b6dbe | ||
|
|
0894587305 | ||
|
|
960e848cc7 | ||
|
|
b4737072a6 | ||
|
|
8507dd4bd0 | ||
|
|
62eeda3e9f | ||
|
|
06c806215e | ||
|
|
d2b25120f0 | ||
|
|
0c319f8b4b | ||
|
|
4fcc760158 | ||
|
|
0d5f918453 | ||
|
|
9c7940b599 | ||
|
|
ccfb1eb0f1 | ||
|
|
7e3a9c3aa6 | ||
|
|
a730b25ef9 | ||
|
|
500fef8314 | ||
|
|
29986e95a0 | ||
|
|
4af1da7d95 | ||
|
|
528b79b5f3 | ||
|
|
03a81aa9c5 | ||
|
|
4957c1121d | ||
|
|
d9d8eb2480 | ||
|
|
d9aad9212f | ||
|
|
8b636de1d3 | ||
|
|
aeab800490 | ||
|
|
f8c33e8630 | ||
|
|
b6efea266e | ||
|
|
8686cb3d3d | ||
|
|
91fff2a2c8 | ||
|
|
d6f43bd156 | ||
|
|
ebbe546033 | ||
|
|
cf0eed6c36 | ||
|
|
feacacc46d | ||
|
|
af53c56ec8 | ||
|
|
019d7b34ca | ||
|
|
622995fb12 | ||
|
|
03586c60da | ||
|
|
07a39e8e18 | ||
|
|
1d7c177606 | ||
|
|
2ae490cd8f | ||
|
|
6fda7a7057 | ||
|
|
1e2833e07b | ||
|
|
067b0a3367 | ||
|
|
24b10179a1 | ||
|
|
c14b581e0a | ||
|
|
bfcb4cd415 | ||
|
|
8fef94cd7d | ||
|
|
61d7ca4c41 | ||
|
|
559858a3dd | ||
|
|
ddd9c7a022 | ||
|
|
03c689c22c | ||
|
|
5270dd8b32 | ||
|
|
f33796bee1 | ||
|
|
e679c518b1 | ||
|
|
ba9214c689 | ||
|
|
68acc1dfc5 | ||
|
|
1a4ec6c2d3 | ||
|
|
6bb30978fb | ||
|
|
c0c30731c4 | ||
|
|
49eaa7c465 | ||
|
|
c2b199e926 | ||
|
|
80552aeab7 | ||
|
|
dfbabc0411 | ||
|
|
59b9b222c8 | ||
|
|
79e3eaf73c | ||
|
|
9106cc8ecc | ||
|
|
17fb6dfdc0 | ||
|
|
95f417fa9a |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -36,3 +36,4 @@ core
|
||||
|
||||
/nano.spec
|
||||
/src/nano
|
||||
/src/revision.h
|
||||
|
||||
19
AUTHORS
19
AUTHORS
@@ -1,9 +1,9 @@
|
||||
This file lists people who have made significant contributions to the
|
||||
nano editor. Please see the ChangeLog for specific changes by author.
|
||||
-------------------------------------------------------------------------
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Chris Allegretta <chrisa@asty.org>
|
||||
* Original program author, former and current maintainer.
|
||||
* Original program author and long-time maintainer.
|
||||
|
||||
David Lawrence Ramsey <pooka109@gmail.com>
|
||||
* Former stable series maintainer. Multiple buffer support,
|
||||
@@ -44,6 +44,19 @@ Mike Frysinger <vapier@gentoo.org>
|
||||
Mark Majeres <mark@engine12.com>
|
||||
* A functional undo/redo system, and coloring nano's interface.
|
||||
|
||||
Mahyar Abbaspour <mahyar.abaspour@gmail.com>
|
||||
* Improved handling of SIGWINCH.
|
||||
|
||||
Mike Scalora <mike@scalora.org>
|
||||
* The comment/uncomment feature.
|
||||
|
||||
Faissal Bensefia <faissaloo@gmail.com>
|
||||
* Line numbers.
|
||||
|
||||
Sumedh Pendurkar <sumedh.pendurkar@gmail.com>
|
||||
* The word-completion feature.
|
||||
|
||||
Benno Schulenberg <bensberg@justemail.net>
|
||||
* A bunch of small bug fixes, the cutword routines, some extra
|
||||
* An array of small bug fixes, the cut-word and block-jump
|
||||
routines, text selection by holding Shift, and some extra
|
||||
key bindings. Current maintainer.
|
||||
|
||||
@@ -2966,7 +2966,7 @@ GNU nano 2.3.0 - 2011.02.26
|
||||
by Eitan Adler <lists@eitanadler.com>.
|
||||
|
||||
2011-02-23 Kamil Dudka <kdudka@redhat.com>
|
||||
* doc/man/nanorc.5: Fix small typo.
|
||||
* doc/man/nanorc.5: Fix small typo. Report and original patch by John Bradshaw.
|
||||
|
||||
2011-02-22 Chris Allegretta <chrisa@asty.org>
|
||||
* color.c (nfreeregex): Fix that we were trying to set the pointer passed by value
|
||||
@@ -3009,7 +3009,7 @@ GNU nano 2.2.6 - 2010.11.22
|
||||
|
||||
GNU nano 2.2.5 - 2010.08.05
|
||||
|
||||
2010-08-04 Lauri Kasanen <curaga@operamail.comcuraga@operamail.com>
|
||||
2010-08-04 Lauri Kasanen <curaga@operamail.com>
|
||||
* doc/syntax/mgp.nanorc: New Magicpoint syntax highlighting definition.
|
||||
|
||||
2010-08-04 Peter <exodus@savannah>
|
||||
@@ -3028,7 +3028,7 @@ GNU nano 2.2.5 - 2010.08.05
|
||||
|
||||
GNU nano 2.2.4 - 2010.04.15
|
||||
|
||||
2010-04-07 Chris Allegretta <chrisa@asty.org>
|
||||
2010-04-14 Chris Allegretta <chrisa@asty.org>
|
||||
* doc/man/nano.1,nanorc.5: Remove the backup file warnings now
|
||||
that a sufficient security fix exists for the backup file code.
|
||||
|
||||
|
||||
17
IMPROVEMENTS
17
IMPROVEMENTS
@@ -1,5 +1,18 @@
|
||||
Improvements in nano
|
||||
====================
|
||||
Improvements in GNU nano
|
||||
========================
|
||||
|
||||
Since 2.7.0:
|
||||
- The keystroke ^] to complete a fragment to an existing full word.
|
||||
- The ability to display line numbers in front of the text (M-#).
|
||||
|
||||
Since 2.6.0:
|
||||
- Shift plus the cursor keys can be used for selecting text.
|
||||
- Ctrl+Arrow should now work also on a Linux virtual console.
|
||||
- Ctrl+Up and Ctrl+Down jump to previous or next block of text.
|
||||
- Feedback during Unicode Input (M-V followed by six digits).
|
||||
- The option 'wordchars' for specifying extra word characters.
|
||||
- Hi-bit control characters are shown in a more readable manner.
|
||||
- The ability to use negative numbers at the Go To Line prompt.
|
||||
|
||||
Noteworthy changes since 2.2
|
||||
----------------------------
|
||||
|
||||
125
NEWS
125
NEWS
@@ -1,3 +1,76 @@
|
||||
2016.12.28 - GNU nano 2.7.3 "Ontbijtkoek" wipes away a handful of bugs:
|
||||
your editor is now able to handle filenames that contain
|
||||
newlines, avoids a brief flash of color when switching
|
||||
between buffers that are governed by different syntaxes,
|
||||
makes the Shift+Ctrl+Arrow keys select text again on a
|
||||
Linux console, is more resistant against malformations
|
||||
in the positionlog file, and does not crash when ^C is
|
||||
typed on systems where it produces the code KEY_CANCEL.
|
||||
Oh, and it no longer mistakenly warns about editing an
|
||||
unlocked file just after saving a new one. That's it.
|
||||
Tastes great with thick butter.
|
||||
|
||||
2016.12.12 - GNU nano 2.7.2 "Shemesh! Shemesh!" brings another feature:
|
||||
the ability to complete with one keystroke (^] by default)
|
||||
a fragment of a word to a full word existing elsewhere in
|
||||
the current buffer. Besides, this release fixes two bugs
|
||||
related to using line numbers in softwrap mode, allows to
|
||||
use the PageUp and PageDown keys together with Shift on
|
||||
VTE-based terminals, stops the help lines from flickering
|
||||
during interactive replacing, makes a "set fill" override
|
||||
an earlier "set nowrap", properly restores the selected
|
||||
region after an external spell check, and improves a few
|
||||
other tidbits. If you should find any more bugs, please
|
||||
run 'man nano | grep bugs' and report them there.
|
||||
|
||||
2016.10.29 - GNU nano 2.7.1 "Leuven" adds an often-asked-for feature: the
|
||||
ability to display line numbers beside the text. This can
|
||||
be activated with -l or --linenumbers on the command line,
|
||||
or with 'set linenumbers' in your nanorc, or toggled with
|
||||
M-#. The coloring of these numbers can be chosen via the
|
||||
option 'set numbercolor'. This release furthermore fixes
|
||||
some bugs with scrolling in softwrap mode, is more strict
|
||||
in the parsing of key rebindings, and marks a new buffer
|
||||
as modified when the output of a command (^R ^X) has been
|
||||
read into it. Come and check it out!
|
||||
|
||||
2016.09.01 - GNU nano 2.7.0 "Suni" adds a new feature: allowing text to be
|
||||
selected by holding Shift together with the cursor keys.
|
||||
Besides that, nano now works also when run in very tiny
|
||||
terminals (down to one line, one column), and improves
|
||||
the handling of the prompt in cramped spaces. Not much,
|
||||
but it's time to get it out there.
|
||||
|
||||
|
||||
2016.08.10 - nano 2.6.3 "Marika" makes the Ctrl+Arrow keys work also on
|
||||
a Linux virtual console, takes as verbatim only the very
|
||||
first keystroke after M-V, removes any lock files that it
|
||||
holds when dying, doesn't abort when a word contains digits
|
||||
(when using the default speller), fixes a small sorting bug
|
||||
in the file browser, makes searching case-insensitively in
|
||||
a UTF-8 locale a little faster, and doesn't enter invalid
|
||||
bytes when holding down both Alt keys. Santé!
|
||||
|
||||
2016.07.28 - nano 2.6.2 "Le vent nous portera" adds two new features: the
|
||||
keystrokes Ctrl+Up and Ctrl+Down for jumping between blocks
|
||||
of text, and the option 'wordchars' for specifying which
|
||||
characters (beside alphanumeric ones) should be considered
|
||||
word-forming. Further, it provides feedback during Unicode
|
||||
input (M-V followed by a six-digit hexadecimal number which
|
||||
must start with 0 or 10), avoids a crash when resizing the
|
||||
window during Verbatim input, doesn't drop a keystroke after
|
||||
having been suspended, and replaces the beginning-of-line
|
||||
anchor (^) just once per line. There are also several tiny
|
||||
improvements in screen rendering and key handling. Come get
|
||||
your hair tousled!
|
||||
|
||||
2016.06.27 - nano 2.6.1 "Stampede" is chiefly a translation update, but also
|
||||
adds one little feature (the ability to use negative numbers
|
||||
with Go To Line: -1 meaning the first line from the bottom),
|
||||
includes syntax highlighting for Rust, and fixes three tiny
|
||||
bugs (but in such far corners of the editor that they aren't
|
||||
even worth mentioning).
|
||||
|
||||
2016.06.17 - nano 2.6.0 "Rubicon" fixes more than fifty little bugs -- and
|
||||
some of them not so little. It improves moving about in
|
||||
the file browser, corrects failings of the internal spell
|
||||
@@ -15,7 +88,7 @@
|
||||
2016.02.25 - GNU nano 2.5.3 "Alphys" is released. This release
|
||||
contains fixes for bugs like: stray cursor positioning
|
||||
errors, many many memory leaks including file reading,
|
||||
using the file browser, searching for multi-byte characters,
|
||||
using the file browser, searching for multibyte characters,
|
||||
history completion, and many other places.
|
||||
New features include the ability to trim whitespace
|
||||
from the ends of lines when justifying text, see nanorc(5)
|
||||
@@ -141,7 +214,7 @@
|
||||
|
||||
2014.06.02 - GNU nano 2.3.4 won't leave you high, won't leave you dry. This
|
||||
release contains only a small number of fixes, but in
|
||||
particular allows nano to compile on non-UTF8 curses
|
||||
particular allows nano to compile on non-UTF-8 curses
|
||||
implementations (i.e. libncursesw). Other small fixes to
|
||||
the undo implementation and the default syntax config are
|
||||
also included. As always, Share and Enjoy!
|
||||
@@ -155,7 +228,7 @@
|
||||
linter support (see the nanorc man page for details). Also
|
||||
included are much improved syntax highlighting code, and
|
||||
configurations for JSON, texinfo, Go, and a default syntax
|
||||
for catch all highlighting. Finally, nano now has the
|
||||
for catch-all highlighting. Finally, nano now has the
|
||||
ability to set the color of the title bar, status bar, and
|
||||
shortcut keys (e.g. "^X") and their descriptions. Again
|
||||
see the nanorc page for details. There's much more, too
|
||||
@@ -177,7 +250,7 @@
|
||||
release includes some fixes for the new libmagic code, as
|
||||
well as a fix for improper character counts when using
|
||||
auto-indent. Also included are new syntax highlighting
|
||||
definitions for RPM spec and lua files. Thanks for
|
||||
definitions for RPM spec and Lua files. Thanks for
|
||||
using nano and keep circulating the tapes.
|
||||
|
||||
2011.02.26 - GNU nano 2.3.0 "Septic surprise" is released. This first
|
||||
@@ -457,7 +530,7 @@
|
||||
thanks for sticking with us!
|
||||
|
||||
|
||||
2007.12.20- GNU nano 2.0.7 keeps its balance. This release fixes
|
||||
2007.12.20 - GNU nano 2.0.7 keeps its balance. This release fixes
|
||||
several bugs, among others: a segfault and several
|
||||
cursor positioning problems when uncutting text or
|
||||
inserting files into the current buffer; a problem where
|
||||
@@ -479,12 +552,12 @@
|
||||
under the GNU GPL version 3 or later and the GNU FDL
|
||||
version 1.2 or later. Have fun.
|
||||
|
||||
2007.04.26- GNU nano 2.0.6 "that was quick" is released. This release
|
||||
2007.04.26 - GNU nano 2.0.6 "that was quick" is released. This release
|
||||
fixes a potential segfault after justifying text marked
|
||||
from the bottom up. It also adds one more minor
|
||||
documentation update. Enjoy.
|
||||
|
||||
2007.04.22- GNU nano 2.0.5 braces for impact. Among other things, this
|
||||
2007.04.22 - GNU nano 2.0.5 braces for impact. Among other things, this
|
||||
release fixes various problems (including a segfault)
|
||||
when trying to open or save a file in a directory
|
||||
beginning with "~" that isn't a home directory; fixes a
|
||||
@@ -592,7 +665,7 @@
|
||||
properly at all times; lines of text containing tabs are
|
||||
now wrapped at the right place; double-column characters
|
||||
are now properly displayed when past the right edge of
|
||||
the screen; invalid multi-line color regexes are now
|
||||
the screen; invalid multiline color regexes are now
|
||||
ignored; and so on. Enjoy.
|
||||
|
||||
2006.03.30 - GNU nano 1.3.11 awakens from its fever dream. This release
|
||||
@@ -930,7 +1003,7 @@
|
||||
0.11.2 of gettext, building with automake 1.6, some new
|
||||
code for displaying control characters, browser
|
||||
improvements, a new backup file option (-B, --backup), a
|
||||
new option to ignore rc files (-I,--ignorercfiles),
|
||||
new option to ignore rc files (-I, --ignorercfiles),
|
||||
compatibility with -pedantic, handling null characters
|
||||
before EOF, a slightly sportier nanorc.sample and more.
|
||||
Fixes are included for justification,
|
||||
@@ -964,19 +1037,19 @@
|
||||
Also, the "show position" code now shows the starting
|
||||
column as 1 instead of 0. Have fun!
|
||||
|
||||
2002.03.05 - GNU nano 1.1.7 "lets change everything and see what breaks"
|
||||
is released. New features include new flags
|
||||
-N, --noconvert to stop any file format conversion and
|
||||
-Q, --quotestr for the new quoted text justification, a
|
||||
new tempnam() implementation to avoid silly warnings,
|
||||
2002.03.05 - GNU nano 1.1.7 "let's change everything and see what breaks"
|
||||
is released. New features include the new flags
|
||||
-N, --noconvert (to stop any file format conversion) and
|
||||
-Q, --quotestr (for the new quoted text justification),
|
||||
a new tempnam() implementation to avoid silly warnings,
|
||||
DOS and Mac file options in the Write File dialog,
|
||||
multiple save files (file.1) for abnormal exits, ^C now
|
||||
shows column as well as character position, and
|
||||
multibuffer allows duplicate files, even unnamed ones.
|
||||
Also, the static shortcut and toggle lengths are
|
||||
history, nano now reads SYSCONFDIR/nanorc if rc file
|
||||
support is enabled, and nano is now built with (and
|
||||
requires for rebuilding) autoconf 2.5.
|
||||
multiple save files (file.1) for abnormal exits,
|
||||
^C now showing column as well as character position, and
|
||||
multibuffer allowing duplicate files, even unnamed ones.
|
||||
Also, the static shortcut and toggle lengths are history,
|
||||
nano now reads SYSCONFDIR/nanorc if rc file support is
|
||||
enabled, and nano is now built with (and for rebuilding
|
||||
requires) autoconf 2.5.
|
||||
This release also includes fixes for some memory
|
||||
leaks, detecting DOS and Mac file format, justification,
|
||||
suspending keys, search & replace under various
|
||||
@@ -1159,7 +1232,7 @@
|
||||
nasty segfault when trying to insert one's home
|
||||
directory (~), some checks for the NumLock key making
|
||||
the keypad go awry, window size sanity checks, many
|
||||
autoconf fixes, and support for the KDE konsole keypad
|
||||
autoconf fixes, and support for the KDE Konsole keypad
|
||||
layout. Have fun.
|
||||
|
||||
2001.01.07 - Nano 0.9.25 is the "Just one more feature I swear!"
|
||||
@@ -1252,7 +1325,7 @@
|
||||
New features include better (not yet perfect) binary
|
||||
display support and toggle support for most of the
|
||||
program flags (M-c, M-i, M-z, M-x, M-p, M-w, M-m, M-k
|
||||
and M-e for -c, -i, -x, -p, -w, -k, and -R).
|
||||
and M-e for -c, -i, -z, -x, -p, -w, -m, -k, and -R).
|
||||
|
||||
2000.08.09 - Nano 0.9.16, after some struggling, is released. This
|
||||
release should fix a few of the holes that 0.9.15 dug.
|
||||
@@ -1287,8 +1360,8 @@
|
||||
other major changes, this should be the feature set for
|
||||
nano 1.0, whenever it might be released =-)
|
||||
|
||||
2000.07.07 - Nano 0.9.12 (The "lucky day" release) is bursting with new
|
||||
features, bug fixes, and yummy fruit flavor. For
|
||||
2000.07.07 - Nano 0.9.12 (the "lucky day" release) is bursting with
|
||||
new features, bug fixes, and yummy fruit flavor. For
|
||||
changes, the alternate replace keystroke ^W^T is now
|
||||
^W^R to be compatible with later versions of Pico. ^W^T
|
||||
is now goto line, again for Pico compatibility. As for
|
||||
@@ -1385,7 +1458,7 @@
|
||||
path. The bug was in the new code for checking whether
|
||||
nano is invoked as 'pico'.
|
||||
|
||||
2000.04.14 - 0.9.1 has some more Pico compatibility built-in. The
|
||||
2000.04.14 - Nano 0.9.1 has some more Pico compatibility built-in. The
|
||||
option to switch to/from Search and Search/Replace (^T)
|
||||
is now available, and nano now displays the more
|
||||
Pico-like shortcut list when invoked as 'pico' (i.e. if
|
||||
|
||||
87
README
87
README
@@ -1,72 +1,69 @@
|
||||
|
||||
nano - an enhanced clone of the Pico text editor
|
||||
GNU nano -- an enhanced clone of the Pico text editor
|
||||
|
||||
Overview
|
||||
|
||||
The nano project was started because of a few "problems" with the
|
||||
wonderfully easy-to-use and friendly Pico text editor.
|
||||
The nano project was started because of a few "problems" with the
|
||||
wonderfully easy-to-use and friendly Pico text editor.
|
||||
|
||||
First and foremost was its license: the Pine suite does not use
|
||||
the GPL or a GPL-friendly license, and has unclear restrictions on
|
||||
redistribution. Because of this, Pine and Pico are not included
|
||||
with many GNU/Linux distributions. Also, other features (like
|
||||
go-to-line-number or search-and-replace) were unavailable until
|
||||
recently or require a command-line flag. Yuck.
|
||||
First and foremost was its license: the Pine suite does not use
|
||||
the GPL or a GPL-friendly license, and has unclear restrictions on
|
||||
redistribution. Because of this, Pine and Pico are not included
|
||||
with many GNU/Linux distributions. Also, other features (like
|
||||
go-to-line-number or search-and-replace) were unavailable until
|
||||
recently or require a command-line flag. Yuck.
|
||||
|
||||
nano aims to solve these problems by emulating the functionality of
|
||||
Pico as closely as possible while addressing the problems above and
|
||||
providing other extra functionality.
|
||||
nano aims to solve these problems by emulating the functionality of
|
||||
Pico as closely as possible while addressing the problems above and
|
||||
providing other extra functionality.
|
||||
|
||||
The nano editor is an official GNU package. For more information on
|
||||
GNU and the Free Software Foundation, please see http://www.gnu.org/.
|
||||
The nano editor is an official GNU package. For more information on
|
||||
GNU and the Free Software Foundation, please see http://www.gnu.org/.
|
||||
|
||||
How to compile and install nano
|
||||
|
||||
Download the nano source code, then:
|
||||
Download the nano source code, then:
|
||||
|
||||
tar zxvf nano-x.y.z.tar.gz
|
||||
cd nano-x.y.z
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
tar xvzf nano-x.y.z.tar.gz
|
||||
cd nano-x.y.z
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
It's that simple. Use --prefix with configure to override the
|
||||
default installation directory of /usr/local.
|
||||
It's that simple. Use --prefix with configure to override the
|
||||
default installation directory of /usr/local.
|
||||
|
||||
If you haven't configured with the "--disable-nanorc" option, after
|
||||
installation you may want to copy the doc/nanorc.sample to your
|
||||
home directory, rename it to ".nanorc", and then edit it according
|
||||
to your taste.
|
||||
If you haven't configured with the --disable-nanorc option, after
|
||||
installation you may want to copy the doc/nanorc.sample file to
|
||||
your home directory, rename it to ".nanorc", and then edit it
|
||||
according to your taste.
|
||||
|
||||
Web Page
|
||||
|
||||
http://www.nano-editor.org/
|
||||
https://nano-editor.org/
|
||||
|
||||
Mailing Lists and Bug Reports
|
||||
Mailing Lists
|
||||
|
||||
Savannah hosts all the nano-related mailing-lists.
|
||||
There are three nano-related mailing-lists.
|
||||
|
||||
+ info-nano@gnu.org is a very low traffic list used to announce
|
||||
new nano versions or other important information about the
|
||||
project.
|
||||
new nano versions or other important info about the project.
|
||||
+ help-nano@gnu.org is for those seeking to get help without
|
||||
wanting to hear about the technical details of its development.
|
||||
+ nano-devel@gnu.org is the list used by the people that make
|
||||
nano and a general development discussion list, with moderate
|
||||
traffic.
|
||||
+ nano-devel@gnu.org is the list used by the people that make nano
|
||||
and a general development discussion list, with moderate traffic.
|
||||
|
||||
To subscribe, send email to <name>-request@gnu.org with a
|
||||
subject of "subscribe", where <name> is the list you want to
|
||||
subscribe to.
|
||||
To subscribe, send email to <name>-request@gnu.org with a subject
|
||||
of "subscribe", where <name> is the list you want to subscribe to.
|
||||
|
||||
For general bug reports, please file a description of the problem
|
||||
on the Savannah bug tracker page for nano
|
||||
(https://savannah.gnu.org/bugs/?group=nano). The issue may have
|
||||
already been reported, and we are better able to track the state
|
||||
of the issue and whom to notify when fixed, the more the bug
|
||||
tracker is used.
|
||||
Bug Reports
|
||||
|
||||
To report a bug, please file a description of the problem on nano's
|
||||
bug tracker (https://savannah.gnu.org/bugs/?group=nano -- hover on
|
||||
"Bugs", then click "Submit new"). The issue may have already been
|
||||
reported, so please look first.
|
||||
|
||||
Current Status
|
||||
|
||||
nano has reached its seventh milestone, 2.6.x. Since 2.5.0, it is
|
||||
a "rolling" release: bug fixing and development go hand in hand.
|
||||
GNU nano has reached its seventh milestone, 2.6.x. Since 2.5.0, it
|
||||
is a "rolling" release: bug fixing and development go hand in hand.
|
||||
|
||||
56
README.GIT
56
README.GIT
@@ -1,39 +1,42 @@
|
||||
INSTRUCTIONS TO COMPILE AND INSTALL NANO GIT VERSIONS
|
||||
=====================================================
|
||||
INSTRUCTIONS FOR COMPILING AND INSTALLING NANO FROM GIT
|
||||
=======================================================
|
||||
|
||||
The latest version of nano is available via git, but building this needs a
|
||||
bit more care than the official stable and unstable tarballs.
|
||||
The latest changes and fixes for GNU nano are available via git, but
|
||||
building this needs a bit more care than the official tarballs.
|
||||
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
To successfully compile nano from the git repo, you'll need the following
|
||||
To successfully compile GNU nano from git, you'll need the following
|
||||
packages:
|
||||
|
||||
- autoconf (version >= 2.61)
|
||||
- automake (version >= 1.7)
|
||||
- autopoint (version >= 0.11.5)
|
||||
- gettext (version >= 0.11.5)
|
||||
- git (version >= 2.7.4)
|
||||
- groff (version >= 1.12)
|
||||
- pkg-config (version >= 0.22)
|
||||
- texinfo (version >= 4.0)
|
||||
- glib 2.x (in case your system doesn't have vsnprintf(), which the
|
||||
configure script will check for)
|
||||
- make, gcc, and
|
||||
- the normal development libraries (curses or slang, etc.)
|
||||
- gcc (any version)
|
||||
- make (any version)
|
||||
|
||||
If you want UTF-8 support, you will also need libncursesw5-dev installed
|
||||
(version >= 5.7), or libslang2-dev (version >= 2.0) if you use --with-slang.
|
||||
If your system doesn't have 'snprintf' or 'vsnprintf' (which the configure
|
||||
script will check for), you will also need glib-2.x installed.
|
||||
|
||||
These should all be available in your distro's package manager or software
|
||||
center, or otherwise on any GNU mirror. Note that you'll need a version of
|
||||
curses or slang with wide character support if you want nano to use UTF-8.
|
||||
center, or otherwise on any GNU mirror.
|
||||
|
||||
|
||||
Download the source
|
||||
-------------------
|
||||
|
||||
To obtain the current nano development code (called 'master', or sometimes
|
||||
'trunk'), use the following command. It will create a copy of the files in
|
||||
a subdirectory of your current working directory called 'nano':
|
||||
To obtain the current nano development branch (called 'master'), use the
|
||||
following command. It will create in your current working directory a
|
||||
subdirectory called 'nano' containing a copy of all of the files:
|
||||
|
||||
$ git clone git://git.savannah.gnu.org/nano.git nano
|
||||
|
||||
@@ -80,5 +83,26 @@ you'll need to run that "make install" command with root privileges.
|
||||
Problems?
|
||||
---------
|
||||
|
||||
Please submit any bugs in the git repository using the Savannah project's
|
||||
bug tracker (https://savannah.gnu.org/bugs/?group=nano).
|
||||
Please submit any bugs you find in the code in git via the bug tracker
|
||||
on Savannah (https://savannah.gnu.org/bugs/?group=nano).
|
||||
|
||||
|
||||
Contributing something
|
||||
----------------------
|
||||
|
||||
If you have a fix for a bug, or the code for a new or improved feature,
|
||||
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:
|
||||
|
||||
$ git commit -as
|
||||
|
||||
Then create a patch (or patches):
|
||||
|
||||
$ git format-patch master
|
||||
|
||||
Send that patch (or patches) to <nano-devel@gnu.org>, as an attachment
|
||||
or with git send-email.
|
||||
|
||||
2
THANKS
2
THANKS
@@ -1,4 +1,4 @@
|
||||
The following people have helped nano in some way or other.
|
||||
The following people have helped GNU nano in some way or another.
|
||||
If we missed you here, let us know!
|
||||
|
||||
|
||||
|
||||
40
TODO
40
TODO
@@ -1,9 +1,8 @@
|
||||
TODO file (? means the feature may be implemented, but not definitely)
|
||||
------------------------------------------------------------------------
|
||||
A list of desired features
|
||||
--------------------------
|
||||
|
||||
For the future (no targeted version, catch-all)
|
||||
Vague musings:
|
||||
- FriBidi support?
|
||||
- Port to DJGPP?
|
||||
- Make matching bracket searches sophisticated enough to skip over
|
||||
brackets inside comments?
|
||||
- Allow indentation of marked text by spaces as well as tabs?
|
||||
@@ -12,26 +11,27 @@ For the future (no targeted version, catch-all)
|
||||
- Allow conversion between different character sets. Maybe use glib's
|
||||
iconv() if the system's iconv() is inadequate, since we already use
|
||||
glib's vsnprintf() if the system lacks vsnprintf()?
|
||||
- Allow setting marks (saved positions, not to be confused with the mark
|
||||
set via Ctrl-^) at various lines and/or columns in the buffer, and
|
||||
allow movement between them with a single keystroke?
|
||||
- Allow searching for and replacing newlines?
|
||||
See also https://savannah.gnu.org/bugs/?47053.
|
||||
- New regression framework built on expect?
|
||||
- Add the ability to move to different lines of the screen with a single
|
||||
keystroke, e.g. M-` (M-~) to go to the top line, M-& (M-7) to go to
|
||||
the center line, and M-' (M-") to go to the last line?
|
||||
|
||||
Somewhat urgent:
|
||||
- Allow text searches in the help viewer.
|
||||
See https://savannah.gnu.org/bugs/?28994.
|
||||
- Detect when text is being pasted, so that we can handle it faster.
|
||||
See https://savannah.gnu.org/bugs/?40060.
|
||||
- Allow color syntaxes to apply to more than just color, so that we can
|
||||
e.g. specify a different alternate spell checker depending on which
|
||||
file type we have open.
|
||||
- Allow setting marks (saved positions, not to be confused with the mark
|
||||
set via Ctrl-^) at various lines and/or columns in the buffer, and
|
||||
allow movement between them with a single keystroke? (We're running
|
||||
out of keystrokes, though.)
|
||||
- Allow searching for and replacing newlines.
|
||||
|
||||
For version 2.6:
|
||||
- New regression framework built on expect.
|
||||
- Allow text searches in the help viewer.
|
||||
- Add the ability to move to different lines of the screen with a single
|
||||
keystroke, e.g. M-` (M-~) to go to the top line, M-& (M-7) to go to
|
||||
the center line, and M-' (M-") to go to the last line.
|
||||
- Detect when we're pasting text, so that we can handle it differently
|
||||
(i.e. faster than currently with screen redraws).
|
||||
- Allow piping marked text to an external command and replacing it with
|
||||
the command's output (as the internal spell checker already does with
|
||||
the "spell" command)?
|
||||
the command's output -- that is: generalize the spell-check flow.
|
||||
See also https://savannah.gnu.org/bugs/?28993.
|
||||
|
||||
For version 2.4:
|
||||
- Handle window resizes better. After we've resized, we should stay
|
||||
|
||||
73
configure.ac
73
configure.ac
@@ -1,24 +1,22 @@
|
||||
# Configuration for nano - a small and user-friendly text editor
|
||||
# Configuration for GNU nano - a small and user-friendly text editor
|
||||
#
|
||||
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
# 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc.
|
||||
#
|
||||
# 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, or (at your option) any
|
||||
# later version.
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
# 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 nano; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
|
||||
# USA.
|
||||
# along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
AC_INIT([nano], [2.6.0], [nano-devel@gnu.org], [nano])
|
||||
AC_INIT([GNU nano], [2.7.3], [nano-devel@gnu.org], [nano])
|
||||
AC_CONFIG_SRCDIR([src/nano.c])
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE
|
||||
@@ -90,13 +88,12 @@ if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_comment" = xyes; then
|
||||
AC_MSG_ERROR([--enable-comment cannot work with --enable-tiny])
|
||||
else
|
||||
# Disabling nanorc silently disables comment support.
|
||||
enable_comment=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_comment" != xyes; then
|
||||
if test "x$enable_comment" != xno; then
|
||||
AC_DEFINE(ENABLE_COMMENT, 1, [Define this to disable the comment/uncomment functionality.])
|
||||
AC_DEFINE(ENABLE_COMMENT, 1, [Define this to enable the comment/uncomment function.])
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -127,6 +124,19 @@ fi
|
||||
AC_ARG_ENABLE(libmagic,
|
||||
AS_HELP_STRING([--disable-libmagic], [Disable detection of file types via libmagic]))
|
||||
|
||||
AC_ARG_ENABLE(linenumbers,
|
||||
AS_HELP_STRING([--disable-linenumbers], [Disable line numbering]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_linenumbers" != xyes; then
|
||||
enable_linenumbers=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_linenumbers" != xyes; then
|
||||
if test "x$enable_linenumbers" != xno; then
|
||||
AC_DEFINE(ENABLE_LINENUMBERS, 1, [Define this to enable line numbering.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(mouse,
|
||||
AS_HELP_STRING([--disable-mouse], [Disable mouse support (and -m flag)]))
|
||||
if test "x$enable_mouse" = xno; then
|
||||
@@ -162,7 +172,22 @@ fi
|
||||
AC_ARG_ENABLE(tabcomp,
|
||||
AS_HELP_STRING([--disable-tabcomp], [Disable tab completion functions]))
|
||||
if test "x$enable_tabcomp" = xno; then
|
||||
AC_DEFINE(DISABLE_TABCOMP, 1, [Define this to disable the tab completion functions for files and search strings.])
|
||||
AC_DEFINE(DISABLE_TABCOMP, 1, [Define this to disable the tab completion functions for filenames and search strings.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(wordcomp,
|
||||
AS_HELP_STRING([--disable-wordcomp], [Disable the word completion function]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_wordcomp" = xyes; then
|
||||
AC_MSG_ERROR([--enable-wordcomp cannot work with --enable-tiny])
|
||||
else
|
||||
enable_wordcomp=no
|
||||
fi
|
||||
fi
|
||||
if test "x$disable_wordcomp" != xyes; then
|
||||
if test "x$enable_wordcomp" != xno; then
|
||||
AC_DEFINE(ENABLE_WORDCOMPLETION, 1, [Define this to enable the word completion function.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(wrapping,
|
||||
@@ -540,8 +565,12 @@ else
|
||||
AC_MSG_RESULT([Using $CURSES_LIB_NAME as the curses library])
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([$CURSES_LIB_NAME], use_default_colors, AC_DEFINE(HAVE_USE_DEFAULT_COLORS, 1, [Define this if your curses library has the use_default_colors() command.]))
|
||||
AC_CHECK_LIB([$CURSES_LIB_NAME], key_defined, AC_DEFINE(HAVE_KEY_DEFINED, 1, [Define this if your curses library has the key_defined() command.]))
|
||||
AC_CHECK_LIB([$CURSES_LIB_NAME], [use_default_colors],
|
||||
[AC_DEFINE(HAVE_USE_DEFAULT_COLORS, 1, [Define this if your curses library has the use_default_colors() command.])],
|
||||
[], [$CURSES_LIB])
|
||||
AC_CHECK_LIB([$CURSES_LIB_NAME], [key_defined],
|
||||
[AC_DEFINE(HAVE_KEY_DEFINED, 1, [Define this if your curses library has the key_defined() command.])],
|
||||
[], [$CURSES_LIB])
|
||||
|
||||
dnl Parse any configure options.
|
||||
|
||||
@@ -708,16 +737,16 @@ AM_CONDITIONAL(GROFF_HTML, test x$groff_html_support = xyes)
|
||||
AC_CHECK_PROG(haveit, makeinfo, yes, no)
|
||||
AM_CONDITIONAL(HAVE_MAKEINFO, test x$haveit = xyes)
|
||||
|
||||
# Check whether this is a git repository.
|
||||
AC_MSG_CHECKING([whether building from git])
|
||||
if test -d .git ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_PATH_PROG([GIT], [git])
|
||||
REVISION=`($GIT rev-parse --is-inside-work-tree >/dev/null 2>&1) && ($GIT rev-parse --short HEAD)`
|
||||
AC_SUBST(REVISION)
|
||||
AC_DEFINE_UNQUOTED([REVISION],"${REVISION}","Setting REVISION in config.h.")
|
||||
from_git=yes
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
from_git=no
|
||||
fi
|
||||
AM_CONDITIONAL(BUILDING_FROM_GIT, test x$from_git = xyes)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
|
||||
50
doc/faq.html
50
doc/faq.html
@@ -1,21 +1,21 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>The nano editor FAQ</title>
|
||||
<title>The GNU nano editor FAQ</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body text="#330000" bgcolor="#ffffff" link="#0000ef" vlink="#51188e" alink="#ff0000">
|
||||
<h1>The nano editor FAQ</h1>
|
||||
<h1>The GNU nano editor FAQ</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<h2><a href="#1">1. General</a></h2>
|
||||
<blockquote><p><a href="#1.1">1.1 About this FAQ</a><br>
|
||||
<a href="#1.2">1.2. How do I contribute to it?</a><br>
|
||||
<a href="#1.3">1.3. What is nano?</a><br>
|
||||
<a href="#1.3">1.3. What is GNU nano?</a><br>
|
||||
<a href="#1.4">1.4. What is the history behind nano?</a><br>
|
||||
<a href="#1.5">1.5. Why the name change from TIP?</a><br>
|
||||
<a href="#1.6">1.6. What is the current version of nano?</a><br>
|
||||
<a href="#1.7">1.7. I want to read the manpage without having to download the program!</a></p></blockquote>
|
||||
<h2><a href="#2">2. Where to get nano.</a></h2>
|
||||
<h2><a href="#2">2. Where to get GNU nano.</a></h2>
|
||||
<blockquote><p><a href="#2.1">2.1. FTP and WWW sites that carry nano.</a><br>
|
||||
<a href="#2.2">2.2. RedHat and derivatives (.rpm) packages.</a><br>
|
||||
<a href="#2.3">2.3. Debian (.deb) packages.</a><br>
|
||||
@@ -69,8 +69,8 @@
|
||||
<blockquote><p>This FAQ was originally written and maintained by Chris Allegretta <<a href="mailto:chrisa@asty.org">chrisa@asty.org</a>>, who also happens to be the creator of nano. It was then maintained by David Lawrence Ramsey <<a href="mailto:pooka109@gmail.com">pooka109@gmail.com</a>>. Maybe someone else will volunteer to maintain this FAQ someday, who knows...</p></blockquote>
|
||||
<h2><a name="1.2"></a>1.2. How do I contribute to it?</h2>
|
||||
<blockquote><p>Your best bet is to send it to the nano email address, <a href="mailto:nano@nano-editor.org">nano@nano-editor.org</a> and if it is useful enough it will be included in future versions.</p></blockquote>
|
||||
<h2><a name="1.3"></a>1.3. What is nano?</h2>
|
||||
<blockquote><p>nano is designed to be a free replacement for the Pico text editor, part of the Pine email suite from <a href="http://www.washington.edu/pine/">The University of Washington</a>. It aims to "emulate Pico as closely as possible and perhaps include extra functionality".</p></blockquote>
|
||||
<h2><a name="1.3"></a>1.3. What is GNU nano?</h2>
|
||||
<blockquote><p>GNU nano is designed to be a free replacement for the Pico text editor, part of the Pine email suite from <a href="http://www.washington.edu/pine/">The University of Washington</a>. It aims to "emulate Pico as closely as possible and perhaps include extra functionality".</p></blockquote>
|
||||
<h2><a name="1.4"></a>1.4. What is the history behind nano?</h2>
|
||||
<blockquote><p>Funny you should ask!</p>
|
||||
<p><b>In the beginning...</b></p>
|
||||
@@ -84,25 +84,26 @@
|
||||
<h2><a name="1.5"></a>1.5. Why the name change from TIP?</h2>
|
||||
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program "establishes a full duplex terminal connection to a remote host", and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
|
||||
<h2><a name="1.6"></a>1.6. What is the current version of nano?</h2>
|
||||
<blockquote><p>The current stable version of nano *should* be 2.4.2. Of course, you should always check the <a href="http://www.nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<blockquote><p>The current version of nano *should* be 2.7.0. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<h2><a name="1.7"></a>1.7. I want to read the man page without having to download the program!</h2>
|
||||
<blockquote><p>Jeez, demanding, aren't we? Okay, look <a href="http://www.nano-editor.org/dist/v2.4/nano.1.html">here</a>.</p></blockquote>
|
||||
<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%">
|
||||
<h1><a name="2"></a>2. Where to get nano.</h1>
|
||||
<h2><a name="2.1"></a>2.1. FTP and WWW sites that carry nano.</h2>
|
||||
<blockquote><p>The nano distribution can be downloaded at the following fine web and ftp sites:</p>
|
||||
<h1><a name="2"></a>2. Where to get GNU nano.</h1>
|
||||
<h2><a name="2.1"></a>2.1. Web sites that carry nano.</h2>
|
||||
<blockquote><p>The nano source tarballs can be downloaded from the following web sites:</p>
|
||||
<ul>
|
||||
<li><a href="http://www.nano-editor.org/dist/">http://www.nano-editor.org/dist/</a></li>
|
||||
<li><a href="ftp://ftp.gnu.org/pub/gnu/nano/">ftp://ftp.gnu.org/pub/gnu/nano/</a></li>
|
||||
<li><a href="https://nano-editor.org/dist/">https://nano-editor.org/dist/</a></li>
|
||||
<li><a href="https://ftp.gnu.org/gnu/nano/">https://ftp.gnu.org/gnu/nano/</a></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h2><a name="2.2"></a>2.2. RedHat and derivatives (.rpm) packages.</h2>
|
||||
<h2><a name="2.2"></a>2.2. RPM packages (RedHat, OpenSuse, and derivatives).</h2>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><a href="http://www.nano-editor.org/dist/v2.2/RPMS/">http://www.nano-editor.org/dist/v2.2/RPMS/</a></li>
|
||||
<li><a href="https://kojipkgs.fedoraproject.org//packages/nano/">https://kojipkgs.fedoraproject.org//packages/nano/</a></li>
|
||||
<li><a href="https://software.opensuse.org/package/nano">https://software.opensuse.org/package/nano</a></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h2><a name="2.3"></a>2.3. Debian (.deb) packages.</h2>
|
||||
<h2><a name="2.3"></a>2.3. Deb packages (Debian and derivatives):</h2>
|
||||
<blockquote><p>Debian users can check out the current nano packages for:</p>
|
||||
<ul>
|
||||
<li><a href="http://packages.debian.org/stable/editors/nano">stable</a></li>
|
||||
@@ -186,7 +187,7 @@
|
||||
<h2><a name="4.6"></a>4.6. nano crashes when I type <insert keystroke here>!</h2>
|
||||
<blockquote><p>If you aren't trying some bizarre keystroke combination with some bizarre $TERM entry, chances are you have found a bug. You are welcome to submit it to the <a href="mailto:nano-devel@gnu.org">nano-devel</a> list or in the <a href="https://savannah.gnu.org/bugs/?group=nano">bug tracker</a> on Savannah.</p></blockquote>
|
||||
<h2><a name="4.7"></a>4.7. nano crashes when I resize my window. How can I fix that?</h2>
|
||||
<blockquote><p>Older versions of nano had this problem, please upgrade to a newer version (at least 0.9.9, but 2.4.2 is recommended).</p></blockquote>
|
||||
<blockquote><p>Older versions of nano had this problem. Please upgrade to version 2.7.0 or newer.</p></blockquote>
|
||||
<h2><a name="4.8"></a>4.8. [version 1.3.12 and later] I'm using glibc 2.2.3, and nano crashes when I use color support or do regular expression searches. How can I fix that?</h2>
|
||||
<blockquote><p>It's a bug in glibc 2.2.3. You should upgrade to at least glibc 2.2.4.</p></blockquote>
|
||||
<h2><a name="4.9"></a>4.9. [version 1.1.12 and earlier] Why does nano show ^\ in the shortcut list instead of ^J?</h2>
|
||||
@@ -215,14 +216,13 @@
|
||||
<h2><a name="4.14"></a>4.14. When I paste text into a document, each line gets indented further than the last. Why does nano do this, and how can I avoid it?</h2>
|
||||
<blockquote><p>You have the autoindent feature turned on. Hit Meta-I to turn it off, paste your text, and then hit Meta-I again to turn it back on.</p></blockquote>
|
||||
<h2><a name="4.15"></a>4.15. On startup I get a message that says "Detected a legacy nano history file". Now older nano versions can't find my search history!</h2>
|
||||
<blockquote><p>In nano 2.3.0, cursor-position history was introduced, and both history files now reside under a .nano directory in your home. nano was trying to move this file into the new location so it could continue to use it. This means that if you try and use an earlier version of nano, it will be unable to see your current search history. To fix this, run the following commands:<br>
|
||||
<p><b>mv ~/.nano/search_history ~/.nano_history</b><br>
|
||||
<b>ln -sf ~/.nano_history ~/.nano/search_history</b></p>
|
||||
</p></blockquote>
|
||||
<blockquote><p>In nano 2.3.0, cursor-position history was introduced, and both history files now reside in a .nano subdirectory in your home directory. A newer nano will move an existing search-history file to this new location so it can continue to be used. This means that if you then try and use an earlier version of nano, it will be unable to see your current search history. To fix this, run the following command:<br>
|
||||
<p><b>ln -sf ~/.nano/search_history ~/.nano_history</b></p>
|
||||
</p><p>The "migration service" (moving the search-history file to its new location) will be deleted from nano in early 2018.</p></blockquote>
|
||||
<hr width="100%">
|
||||
<h1><a name="5"></a>5. Internationalization</h1>
|
||||
<h2><a name="5.1"></a>5.1. There's no translation for my language!</h2>
|
||||
<blockquote><p>In June 2001, nano entered the <a href="http://translationproject.org/html/welcome.html">Translation Project</a> and since then, translations should be managed from there.</p>
|
||||
<blockquote><p>In June 2001, GNU nano entered the <a href="http://translationproject.org/html/welcome.html">Translation Project</a> and since then, translations should be managed from there.</p>
|
||||
<p>If there isn't a translation for your language, you could ask <a href="http://translationproject.org/team/">your language team</a> to translate nano, or better still, join that team and do it yourself. Joining a team is easy. You just need to ask the team leader to add you, and then send a <a href="http://translationproject.org/disclaim.txt">translation disclaimer to the FSF</a> (this is necessary as nano is an official GNU package, but it does <b>not</b> mean that you transfer the rights of your work to the FSF, it's just so the FSF can legally manage them).</p>
|
||||
<p>In any case, translating nano is very easy. Just grab the latest <b>nano.pot</b> file listed on <a href="http://translationproject.org/domain/nano.html">nano's page</a> at the TP, and translate each <b>msgid</b> line into your native language on the <b>msgstr</b> line. When you're done, you should send it to the TP's central po repository.</p></blockquote>
|
||||
<h2><a name="5.2"></a>5.2. I don't like the translation for <x> in my language. How can I fix it?</h2>
|
||||
@@ -232,9 +232,9 @@
|
||||
<hr width="100%">
|
||||
<h1><a name="6"></a>6. Advocacy and Licensing</h1>
|
||||
<h2><a name="6.1"></a>6.1. Why should I use nano instead of Pico?</h2>
|
||||
<blockquote><p>There are many reasons to use nano instead of Pico. A more complete list can be found at the <a href="http://www.nano-editor.org/">nano homepage</a>.</p></blockquote>
|
||||
<blockquote><p>There are many reasons to use nano instead of Pico. A more complete list can be found at the <a href="https://nano-editor.org/">nano homepage</a>.</p></blockquote>
|
||||
<h2><a name="6.2"></a>6.2. Why should I use Pico instead of nano?</h2>
|
||||
<blockquote><p>Again, check out the <a href="http://www.nano-editor.org/">nano homepage</a> for a good summary of reasons. It really is a matter of personal preference as to which editor you should use. If you're the type of person who likes using the original version of a program, then Pico is the editor for you. If you don't mind sacrificing mailer integration with Pine, and are looking for a few more features, as well as a 'better' license in terms of adding your own changes, nano is the way to go.</p><p>Note that the last of these no longer applies to the new version of Pine, <a href="http://www.washington.edu/alpine/">Alpine</a>, which is under the Apache License, version 2.0.</p></blockquote>
|
||||
<blockquote><p>Again, check out the <a href="https://nano-editor.org/">nano homepage</a> for a good summary of reasons. It really is a matter of personal preference as to which editor you should use. If you're the type of person who likes using the original version of a program, then Pico is the editor for you. If you don't mind sacrificing mailer integration with Pine, and are looking for a few more features, as well as a 'better' license in terms of adding your own changes, nano is the way to go.</p><p>Note that the last of these no longer applies to the new version of Pine, <a href="http://www.washington.edu/alpine/">Alpine</a>, which is under the Apache License, version 2.0.</p></blockquote>
|
||||
<h2><a name="6.3"></a>6.3. What is so bad about the older Pine license?</h2>
|
||||
<blockquote><p>The U of W license for older versions of Pine and Pico is not considered truly Free Software according to both the Free Software Foundation and the <a href="http://www.debian.org/social_contract#guidelines">Debian Free Software Guidelines</a>. The main problem regards the limitations on distributing derived works: according to UW, you can distribute their software, and you can modify it, but you can not do both, i.e. distribute modified binaries.</p></blockquote>
|
||||
<h2><a name="6.4"></a>6.4. Okay, well, what mail program should I use then?</h2>
|
||||
@@ -248,7 +248,7 @@ Of course, due to the license change you can now use the <A HREF="http://www.was
|
||||
help-nano - <a href="http://mail.gnu.org/mailman/listinfo/help-nano/">http://mail.gnu.org/mailman/listinfo/help-nano/</a><br>
|
||||
nano-devel - <a href="http://mail.gnu.org/mailman/listinfo/nano-devel/">http://mail.gnu.org/mailman/listinfo/nano-devel/</a></p></blockquote>
|
||||
<h2><a name="7.2"></a>7.2. I want to send the development team a big load of cash (or just a thank you).</h2>
|
||||
<blockquote><p>That's fine. Send it <a href="mailto:nano-devel@gnu.org">our way</a>! Better yet, fix a <a href="https://savannah.gnu.org/bugs/?group=nano">bug</a> in the program or implement a <a href="http://www.nano-editor.org/dist/v2.3/TODO">cool feature</a> and send us that instead (though cash is fine too).</p></blockquote>
|
||||
<blockquote><p>That's fine. Send it <a href="mailto:nano-devel@gnu.org">our way</a>! Better yet, fix a <a href="https://savannah.gnu.org/bugs/?group=nano">bug</a> in the program or implement a <a href="https://nano-editor.org/dist/latest/TODO">cool feature</a> and send us that instead (though cash is fine too).</p></blockquote>
|
||||
<h2><a name="7.3"></a>7.3. How do I submit a bug report or patch?</h2>
|
||||
<blockquote>
|
||||
<p>The best place to submit bugs is to the <a href="https://savannah.gnu.org/bugs/?group=nano">Savannah bug tracker</a> as you can check whether the bug you are submitting has already been submitted.
|
||||
|
||||
@@ -17,16 +17,15 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANO 1 "version 2.6.0" "June 2016"
|
||||
.TH NANO 1 "version 2.7.3" "December 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
|
||||
.SH NAME
|
||||
nano \- Nano's ANOther editor, an enhanced free Pico clone
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B nano
|
||||
.RI [ options "] [[+" line , column "]\ " file "]..."
|
||||
.RI [ options "] [[+" line [, column "]]\ " file "]..."
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBnano\fP is a small, free and friendly editor which aims to replace
|
||||
@@ -38,7 +37,7 @@ replace" and "go to line and column number".
|
||||
.SH EDITING
|
||||
Entering text and moving around in a file is straightforward: typing the
|
||||
letters and using the normal cursor movement keys. Commands are entered
|
||||
by using the Control (^) and the Alt or Meta (M-) keys.
|
||||
by using the Control (^) and the Alt or Meta (M\-) keys.
|
||||
Typing \fB^K\fR deletes the current line and puts it in the cutbuffer.
|
||||
Consecutive \fB^K\fRs will put all deleted lines together in the cutbuffer.
|
||||
Any cursor movement or executing any other command will cause the next
|
||||
@@ -47,10 +46,14 @@ contents of the cutbuffer at the current cursor position.
|
||||
.PP
|
||||
When a more precise piece of text needs to be cut or copied, one can mark
|
||||
its start with \fB^6\fR, move the cursor to its end (the marked text will be
|
||||
highlighted), and then use \fB^K\fR to cut it, or \fBM-6\fR to copy it to the
|
||||
cutbuffer. One can also save the marked text to a file with \fB^O\fR, or
|
||||
highlighted), and then use \fB^K\fR to cut it, or \fBM\-6\fR to copy it to the
|
||||
cutbuffer. One can also save the marked text to a file with \fB^O\fR, or
|
||||
spell check it with \fB^T\fR.
|
||||
.PP
|
||||
Since nano-2.7.0, text can also be selected by holding Shift and moving the
|
||||
cursor with the arrow keys. Holding down the Alt key too will increase the
|
||||
stride.
|
||||
.PP
|
||||
The two lines at the bottom of the screen show the most 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
|
||||
@@ -148,9 +151,14 @@ keystroke instead of 25. Note that \fB\-c\fP overrides this.
|
||||
Show the current version number and exit.
|
||||
.TP
|
||||
.BR \-W ", " \-\-wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as part of a word.
|
||||
.TP
|
||||
.BR "\-X ""\fIcharacters\fB""" ", " "\-\-wordchars=""" \fIcharacters """
|
||||
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
|
||||
Specify the name of the syntax highlighting to use from among the ones
|
||||
defined in the \fInanorc\fP files.
|
||||
@@ -163,6 +171,10 @@ Interpret the Delete key differently so that both Backspace and Delete
|
||||
work properly. You should only need to use this option if Backspace
|
||||
acts like Delete on your system.
|
||||
.TP
|
||||
.BR \-g ", " \-\-showcursor
|
||||
Make the cursor visible in the file browser, putting it on the
|
||||
highlighted item. Useful for braille users.
|
||||
.TP
|
||||
.BR \-h ", " \-\-help
|
||||
Show a summary of the available command-line options and exit.
|
||||
.TP
|
||||
@@ -171,9 +183,12 @@ Indent new lines to the previous line's indentation. Useful when
|
||||
editing source code.
|
||||
.TP
|
||||
.BR \-k ", " \-\-cut
|
||||
Make the 'Cut Text' command (normally ^K) cut from the current cursor
|
||||
Make the 'Cut Text' command (normally \fB^K\fR) cut from the current cursor
|
||||
position to the end of the line, instead of cutting the entire line.
|
||||
.TP
|
||||
.BR \-l ", " \-\-linenumbers
|
||||
Display line numbers to the left of the text area.
|
||||
.TP
|
||||
.BR \-m ", " \-\-mouse
|
||||
Enable mouse support, if available for your system. When enabled, mouse
|
||||
clicks can be used to place the cursor, set the mark (with a double
|
||||
@@ -205,15 +220,13 @@ 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
|
||||
.B \-w
|
||||
-- the last one given takes effect.
|
||||
\fB\-w\fR -- the last one given takes effect.
|
||||
.TP
|
||||
.BR \-s\ \fIprogram\fR ", " \-\-speller= \fIprogram
|
||||
Use this alternative spell checker command.
|
||||
.TP
|
||||
.BR \-t ", " \-\-tempfile
|
||||
Always save a changed buffer without prompting. Same as Pico's \fB\-t\fP
|
||||
option.
|
||||
Save a changed buffer without prompting (when exiting with \fB^X\fR).
|
||||
.TP
|
||||
.BR \-u ", " \-\-unix
|
||||
Save a file by default in Unix format. This overrides nano's
|
||||
@@ -221,12 +234,11 @@ default behavior of saving a file in the format that it had.
|
||||
(This option has no effect when you also use \fB\-\-noconvert\fR.)
|
||||
.TP
|
||||
.BR \-v ", " \-\-view
|
||||
View-file (read-only) mode.
|
||||
Just view the file and disallow editing: read-only mode.
|
||||
.TP
|
||||
.BR \-w ", " \-\-nowrap
|
||||
Disable the hard-wrapping of long lines. This option conflicts with
|
||||
.B \-r
|
||||
-- the last one given takes effect.
|
||||
\fB\-r\fR -- the last one given takes effect.
|
||||
.TP
|
||||
.BR \-x ", " \-\-nohelp
|
||||
Don't show the two help lines at the bottom of the screen.
|
||||
@@ -242,9 +254,17 @@ continuing it over multiple screen lines. Since
|
||||
this option last when using other options (e.g.\& 'nano \-wS$') or pass it
|
||||
separately (e.g.\& 'nano \-wS \-$').
|
||||
.TP
|
||||
.BR \-a ", " \-b ", " \-e ", " \-f ", " \-g ", " \-j
|
||||
.BR \-a ", " \-b ", " \-e ", " \-f ", " \-j
|
||||
Ignored, for compatibility with Pico.
|
||||
|
||||
.SH TOGGLES
|
||||
Several of the above options can be switched on and off also while
|
||||
\fBnano\fR is running. For example, \fBM\-L\fR toggles the
|
||||
hard-wrapping of long lines, \fBM\-$\fR toggles soft-wrapping,
|
||||
\fBM\-#\fR toggles line numbers, \fBM\-M\fR toggles the mouse,
|
||||
\fBM\-I\fR auto-indentation, and \fBM\-X\fR the help lines.
|
||||
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
|
||||
@@ -256,7 +276,7 @@ for more information on the possible contents of those files.
|
||||
If no alternative spell checker command is specified on the command
|
||||
line nor in one of the \fInanorc\fP files, \fBnano\fP will check the
|
||||
\fBSPELL\fP environment variable for one.
|
||||
|
||||
.sp
|
||||
In some cases \fBnano\fP will try to dump the buffer into an emergency
|
||||
file. This will happen mainly if \fBnano\fP receives a SIGHUP or
|
||||
SIGTERM or runs out of memory. It will write the buffer into a file
|
||||
@@ -268,27 +288,25 @@ 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) and reindentations (\fBM\-{\fR and \fBM\-}\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
|
||||
cannot be undone any more. The workaround is, of course, to exit without
|
||||
saving.
|
||||
.sp
|
||||
Please report any other bugs that you encounter via
|
||||
https://savannah.gnu.org/bugs/?group=nano.
|
||||
Please report any other bugs that you encounter via:
|
||||
.br
|
||||
\fIhttps://savannah.gnu.org/bugs/?group=nano\fR.
|
||||
|
||||
.SH HOMEPAGE
|
||||
http://www.nano-editor.org/
|
||||
https://nano-editor.org/
|
||||
|
||||
.SH SEE ALSO
|
||||
.PD 0
|
||||
.TP
|
||||
\fBnanorc\fP(5)
|
||||
.BR nanorc (5)
|
||||
.PP
|
||||
\fI/usr/share/doc/nano/\fP (or equivalent on your system)
|
||||
|
||||
.SH AUTHOR
|
||||
Chris Allegretta <chrisa@asty.org>, et al (see the files \fIAUTHORS\fP and
|
||||
Chris Allegretta and others (see the files \fIAUTHORS\fR and
|
||||
\fITHANKS\fP for details). This manual page was originally written by
|
||||
Jordi Mallach <jordi@gnu.org>, for the Debian system (but may be used by
|
||||
others).
|
||||
Jordi Mallach for the Debian system (but may be used by others).
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANORC 5 "version 2.6.0" "June 2016"
|
||||
.TH NANORC 5 "version 2.7.3" "December 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
|
||||
.SH NAME
|
||||
nanorc \- nano's rcfile
|
||||
nanorc \- GNU nano's configuration file
|
||||
|
||||
.SH DESCRIPTION
|
||||
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
|
||||
@@ -116,6 +117,9 @@ Specify the color combination to use for the shortcut key combos
|
||||
in the two help lines at the bottom of the screen.
|
||||
See \fBset titlecolor\fR for more details.
|
||||
.TP
|
||||
.B set linenumbers
|
||||
Display line numbers to the left of the text area.
|
||||
.TP
|
||||
.B set locking
|
||||
Enable vim-style lock-files for when editing files.
|
||||
.TP
|
||||
@@ -150,6 +154,10 @@ Don't automatically add a newline to the ends of files.
|
||||
.B set nowrap
|
||||
Don't hard-wrap text at all.
|
||||
.TP
|
||||
.B set numbercolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Specify the color combination to use for line numbers.
|
||||
See \fBset titlecolor\fR for more details.
|
||||
.TP
|
||||
.B set operatingdir "\fIdirectory\fP"
|
||||
\fBnano\fP will only read and write files inside \fIdirectory\fP and its
|
||||
subdirectories. Also, the current directory is changed to here, so
|
||||
@@ -200,6 +208,10 @@ won't work properly with this option enabled.
|
||||
.B set regexp
|
||||
Do extended regular expression searches by default.
|
||||
.TP
|
||||
.B set showcursor
|
||||
Put the cursor on the highlighted item in the file browser, to aid
|
||||
braille users.
|
||||
.TP
|
||||
.B set smarthome
|
||||
Make the Home key smarter. When Home is pressed anywhere but at the
|
||||
very beginning of non-whitespace characters on a line, the cursor will
|
||||
@@ -236,8 +248,9 @@ Save automatically on exit, don't prompt.
|
||||
.TP
|
||||
.B set titlecolor \fIfgcolor\fR,\fIbgcolor\fR
|
||||
Specify the color combination to use for the titlebar.
|
||||
Valid color names for foreground and background are:
|
||||
.BR white , \ black , \ red , \ blue , \ green , \ yellow , \ magenta ", and " cyan .
|
||||
Valid names for the foreground and background colors are:
|
||||
.BR white ", " black ", " blue ", " green ", " red ", " cyan ", " yellow ", and " magenta .
|
||||
The name of the foreground color may be prefixed with \fBbright\fR.
|
||||
And either "\fIfgcolor\fR" or ",\fIbgcolor\fR" may be left out.
|
||||
.TP
|
||||
.B set unix
|
||||
@@ -253,8 +266,13 @@ Set the two characters used to indicate the presence of tabs and
|
||||
spaces. They must be single-column characters.
|
||||
.TP
|
||||
.B set wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as parts of words.
|
||||
.TP
|
||||
.B set wordchars \fIstring\fP
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as parts of words. This overrides the option
|
||||
\fBwordbounds\fR.
|
||||
|
||||
.SH SYNTAX HIGHLIGHTING
|
||||
Coloring the different syntactic elements of a file
|
||||
@@ -408,6 +426,7 @@ a string in the current list in the file browser.
|
||||
.TP
|
||||
.B searchagain
|
||||
Repeats the last search command without prompting.
|
||||
(The form 'research' is deprecated.)
|
||||
.TP
|
||||
.B findprevious
|
||||
As \fBsearchagain\fR, but always in the backward direction.
|
||||
@@ -442,6 +461,7 @@ Cuts all text from the cursor position till the end of the buffer.
|
||||
.TP
|
||||
.B curpos
|
||||
Shows the current cursor position: the line, column, and character positions.
|
||||
(The form 'cursorpos' is deprecated.)
|
||||
.TP
|
||||
.B wordcount
|
||||
Counts the number of words, lines and characters in the current buffer.
|
||||
@@ -469,6 +489,10 @@ Unindents (shifts to the left) the currently marked text.
|
||||
Comments or uncomments the current line or marked lines, using the comment
|
||||
style specified in the active syntax.
|
||||
.TP
|
||||
.B complete
|
||||
Completes the fragment before the cursor to a full word found elsewhere
|
||||
in the current buffer.
|
||||
.TP
|
||||
.B left
|
||||
Goes left one position (in the editor or browser).
|
||||
.TP
|
||||
@@ -505,6 +529,13 @@ Moves the cursor to the beginning of the current paragraph.
|
||||
.B endpara
|
||||
Moves the cursor to the end of the current paragraph.
|
||||
.TP
|
||||
.B prevblock
|
||||
Moves the cursor to the beginning of the current or preceding block of text.
|
||||
(Blocks are separated by one or more blank lines.)
|
||||
.TP
|
||||
.B nextblock
|
||||
Moves the cursor to the beginning of the next block of text.
|
||||
.TP
|
||||
.B prevpage
|
||||
Goes up one screenful.
|
||||
.TP
|
||||
@@ -518,7 +549,8 @@ Goes to the first line of the file.
|
||||
Goes to the last line of the file.
|
||||
.TP
|
||||
.B gotoline
|
||||
Goes to a specific line (and column if specified).
|
||||
Goes to a specific line (and column if specified). Negative numbers count
|
||||
from the end of the file (and end of the line).
|
||||
.TP
|
||||
.B gototext
|
||||
Switches from targeting a line number to searching for text.
|
||||
@@ -534,7 +566,7 @@ Switches to editing/viewing the previous buffer when multiple buffers are open.
|
||||
Switches to editing/viewing the next buffer when multiple buffers are open.
|
||||
.TP
|
||||
.B verbatim
|
||||
Inserts the next character verbatim into the file.
|
||||
Inserts the next keystroke verbatim into the file.
|
||||
.TP
|
||||
.B tab
|
||||
Inserts a tab at the current cursor location.
|
||||
@@ -566,6 +598,7 @@ Toggles case sensitivity in searching (search/replace menus only).
|
||||
.TP
|
||||
.B regexp
|
||||
Toggles whether searching/replacing is based on literal strings or regular expressions.
|
||||
(The form 'regex' is deprecated.)
|
||||
.TP
|
||||
.B backwards
|
||||
Toggles whether searching/replacing goes forward or backward.
|
||||
@@ -578,6 +611,7 @@ Shows the next history entry in the prompt menus (e.g. search).
|
||||
.TP
|
||||
.B flipreplace
|
||||
Toggles between searching for something and replacing something.
|
||||
(The form 'dontreplace' is deprecated.)
|
||||
.TP
|
||||
.B flipexecute
|
||||
Toggles between inserting a file and executing a command.
|
||||
@@ -585,6 +619,7 @@ Toggles between inserting a file and executing a command.
|
||||
.B flipnewbuffer
|
||||
Toggles between inserting into the current buffer and into a new
|
||||
empty buffer.
|
||||
(The form 'newbuffer' is deprecated.)
|
||||
.TP
|
||||
.B dosformat
|
||||
When writing a file, switches to writing a DOS format (CR/LF).
|
||||
@@ -688,6 +723,7 @@ The 'search to replace' menu.
|
||||
.TP
|
||||
.B replacewith
|
||||
The 'replace with' menu, which comes up after 'search to replace'.
|
||||
(The form 'replace2' is deprecated.)
|
||||
.TP
|
||||
.B gotoline
|
||||
The 'goto line (and column)' menu.
|
||||
@@ -732,14 +768,11 @@ System-wide configuration file.
|
||||
.TP
|
||||
.B ~/.nanorc
|
||||
Per-user configuration file.
|
||||
|
||||
.SH SEE ALSO
|
||||
.TP
|
||||
\fBnano\fP(1)
|
||||
.PP
|
||||
\fI/usr/share/doc/nano/examples/nanorc.sample\fP (or equivalent on your
|
||||
system)
|
||||
.BR nano (1)
|
||||
|
||||
.SH AUTHOR
|
||||
Chris Allegretta <chrisa@asty.org>, et al (see \fIAUTHORS\fP and
|
||||
Chris Allegretta and others (see the files \fIAUTHORS\fP and
|
||||
\fITHANKS\fP for details). This manual page was originally written by
|
||||
Jordi Mallach <jordi@gnu.org>, for the Debian system (but may be used by
|
||||
others).
|
||||
Jordi Mallach for the Debian system (but may be used by others).
|
||||
|
||||
@@ -16,64 +16,52 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 2.6.0" "June 2016"
|
||||
.TH RNANO 1 "version 2.7.3" "December 2016"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
|
||||
.SH NAME
|
||||
rnano \- Restricted mode for Nano's ANOther editor, an enhanced free
|
||||
Pico clone
|
||||
rnano \- a restricted nano
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B rnano
|
||||
.RI [ options "] [[+" line , column "]\ " file "]..."
|
||||
.RI [ options "] [[+" line [, column "]]\ " file "]..."
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBnano\fP is a small, free and friendly editor which aims to replace
|
||||
Pico, the default editor included in the non-free Pine package. On
|
||||
top of copying Pico's look and feel, \fBnano\fP also implements some
|
||||
missing (or disabled by default) features in Pico, such as "search and
|
||||
replace" and "go to line and column number".
|
||||
\fBrnano\fR runs the \fBnano\fR editor in restricted mode. This allows
|
||||
editing only the specified file or files, and doesn't allow the user
|
||||
access to the filesystem nor to a command shell.
|
||||
.PP
|
||||
\fBrnano\fP is a restricted version of \fBnano\fP, which only edits
|
||||
specific files and doesn't allow the user access to the filesystem or a
|
||||
command shell.
|
||||
.PP
|
||||
In restricted mode, \fBnano\fP will \fInot\/\fP:
|
||||
In restricted mode, \fBnano\fR will:
|
||||
.IP \[bu] 2
|
||||
read or write to any file not specified on the command line;
|
||||
not read any nanorc files;
|
||||
.IP \[bu]
|
||||
read any nanorc files;
|
||||
not allow suspending;
|
||||
.IP \[bu]
|
||||
allow suspending;
|
||||
not read nor write any file not specified on the command line;
|
||||
.IP \[bu]
|
||||
allow a file to be appended to, prepended to, or saved under a different
|
||||
name;
|
||||
not allow saving a file under a different name;
|
||||
.IP \[bu]
|
||||
use backup files or spell checking.
|
||||
not allow appending or prepending to any file;
|
||||
.IP \[bu]
|
||||
not make backup files nor do spell checking.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR \-h ", " \-\-help
|
||||
Show a summary of command-line options and exit.
|
||||
.TP
|
||||
.BR \-V ", " \-\-version
|
||||
Show the current version number and exit.
|
||||
.PP
|
||||
See the \fBnano\fP(1) manpage for all of the possible options.
|
||||
See the \fBnano\fP(1) manpage for all available options.
|
||||
|
||||
.SH BUGS
|
||||
Please send any comments or bug reports to \fBnano@nano-editor.org\fP.
|
||||
|
||||
The \fBnano\fP mailing list is available from \fBnano-devel@gnu.org\fP.
|
||||
|
||||
To subscribe, email to \fBnano-devel-request@gnu.org\fP with a subject
|
||||
of "subscribe".
|
||||
Please report bugs via \fIhttps://savannah.gnu.org/bugs/?group=nano\fR.
|
||||
|
||||
.SH HOMEPAGE
|
||||
http://www.nano-editor.org/
|
||||
https://nano-editor.org/
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR nano (1)
|
||||
|
||||
.SH AUTHOR
|
||||
Chris Allegretta <chrisa@asty.org>, et al (see the file AUTHORS for details).
|
||||
This manual page was originally written by Thijs Kinkhorst
|
||||
<thijs@kinkhorst.com>, for the Debian system (but may be used by
|
||||
others).
|
||||
Chris Allegretta and others (see the files \fIAUTHORS\fR and \fITHANKS\fR
|
||||
for details). This manual page was originally written by Thijs Kinkhorst
|
||||
for the Debian system (but may be used by others).
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
## Sample initialization file for nano.
|
||||
## Sample initialization file for GNU nano.
|
||||
##
|
||||
## Please note that you must have configured nano with --enable-nanorc
|
||||
## for this file to be read! Also note that this file should not be in
|
||||
@@ -63,6 +63,9 @@
|
||||
## Make the justify command kill whitespace at the end of lines.
|
||||
# set justifytrim
|
||||
|
||||
## Display line numbers to the left of the text.
|
||||
# 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
|
||||
## no plans to implement vim-style undo state in these files.
|
||||
@@ -138,6 +141,10 @@
|
||||
## Do extended regular expression searches by default.
|
||||
# set regexp
|
||||
|
||||
## Put the cursor on the highlighted item in the file browser;
|
||||
## useful for people who use a braille display.
|
||||
# set showcursor
|
||||
|
||||
## Make the Home key smarter. When Home is pressed anywhere but at the
|
||||
## very beginning of non-whitespace characters on a line, the cursor
|
||||
## will jump to that beginning (either forwards or backwards). If the
|
||||
@@ -178,14 +185,20 @@
|
||||
## The default otherwise:
|
||||
# set whitespace ">."
|
||||
|
||||
## Detect word boundaries more accurately by treating punctuation
|
||||
## Detect word boundaries differently by treating punctuation
|
||||
## characters as parts of words.
|
||||
# set wordbounds
|
||||
|
||||
## The characters (besides alphanumeric ones) that should be considered
|
||||
## as parts of words. This option does not have a default value. When
|
||||
## set, it overrides option 'set wordbounds'.
|
||||
# set wordchars "<_>."
|
||||
|
||||
|
||||
## Paint the interface elements of nano.
|
||||
## This is an example; by default there are no colors.
|
||||
## These are examples; by default there are no colors.
|
||||
# set titlecolor brightwhite,blue
|
||||
# set numbercolor cyan
|
||||
# set statuscolor brightwhite,green
|
||||
# set keycolor green
|
||||
# set functioncolor yellow
|
||||
|
||||
@@ -34,6 +34,7 @@ pkgdata_DATA = asm.nanorc \
|
||||
pov.nanorc \
|
||||
python.nanorc \
|
||||
ruby.nanorc \
|
||||
rust.nanorc \
|
||||
sh.nanorc \
|
||||
spec.nanorc \
|
||||
tcl.nanorc \
|
||||
|
||||
@@ -20,7 +20,7 @@ color red "\"[^"]*\"" "\'[^']*\'"
|
||||
color green "`[^`]*`"
|
||||
|
||||
# Error lines:
|
||||
color black "^\*\*\*.*"
|
||||
color brightred "^\*\*\*.*"
|
||||
|
||||
# Brackets:
|
||||
color magenta "\[|\]|\(|\)"
|
||||
|
||||
@@ -49,19 +49,19 @@ color ,green "[[:space:]]+$"
|
||||
syntax "/etc/portage" "\.(accept_keywords|env|keywords|mask|unmask|use)(/.+)?$"
|
||||
## Base text:
|
||||
color green "^.+$"
|
||||
## Use flags:
|
||||
color brightred "[[:space:]]+\+?[a-zA-Z0-9_-]+"
|
||||
color brightblue "[[:space:]]+-[a-zA-Z0-9_-]+"
|
||||
## Likely version and slot numbers:
|
||||
color magenta "-[[:digit:]].*([[:space:]]|$)"
|
||||
color magenta "-[[:digit:].]+(_(alpha|beta|pre|rc|p)[[:digit:]]*)*(-r[[:digit:]]+)?([:[:space:]]|$)"
|
||||
color magenta ":[^[:space:]]+([[:space:]]|$)"
|
||||
## Use flags (must come after version/slot):
|
||||
color brightred "[[:space:]]+\+?[A-Za-z0-9+_@-]+"
|
||||
color brightblue "[[:space:]]+-[A-Za-z0-9+_@-]+"
|
||||
## Accepted arches:
|
||||
color white "[~-]?\<(alpha|amd64|arm|hppa|ia64|mips|ppc|ppc64|s390|sh|sparc(-fbsd)?|x86(-fbsd)?)\>"
|
||||
color white "[~-]?\<(alpha|amd64|arm(64)?|hppa|ia64|m68k|mips|nios2|ppc(64)?|riscv|s390|sh|sparc|x86)(-(aix|(f|free|net|open)bsd|cygwin|hpux|interix|linux|macos|mint|solaris|winnt))?\>"
|
||||
color white "[[:space:]][*~-]?\*"
|
||||
## Categories:
|
||||
color cyan "^[[:space:]]*.*/"
|
||||
color cyan "^[[:space:]]*[^/]*/"
|
||||
## Masking regulators:
|
||||
color brightmagenta "^[[:space:]]*(=|~|<|<=|=<|>|>=|=>)"
|
||||
color brightmagenta "^[[:space:]]*(=|~|<|<=|>|>=)"
|
||||
## Comments:
|
||||
color yellow "#.*$"
|
||||
## Trailing space is bad!
|
||||
|
||||
@@ -7,11 +7,11 @@ comment "#"
|
||||
icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|comment|magic|linter|i?color|extendsyntax).*$"
|
||||
|
||||
# Keywords
|
||||
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|autoindent|backup|backwards|boldtext|casesensitive|const(antshow)?|cut|fill|historylog|justifytrim|locking|morespace|mouse|multibuffer|noconvert|nohelp|nonewlines|nowrap|pos(ition)?log|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|smarthome|smooth|softwrap|suspend|tabsize|tabstospaces|tempfile|unix|view|wordbounds)\>"
|
||||
icolor yellow "^[[:space:]]*set[[:space:]]+(functioncolor|keycolor|statuscolor|titlecolor)[[: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|operatingdir|punct|quotestr|speller|statuscolor|titlecolor|whitespace)[[:space:]]+"
|
||||
icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^|M-)([[:alpha:]]|space|[]]|[0-9^_=+{}|;:'\",./<>\?-])|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(2|with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
|
||||
icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^|M-)([[:alpha:]]|space|[]]|[0-9^_=+{}|;:'\",./<>\?-])|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(2|with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
|
||||
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cut|fill[[:space:]]+[[:digit:]]+|historylog|justifytrim|locking|morespace|mouse|multibuffer|noconvert|nohelp|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[[:digit:]]+|tabstospaces|tempfile|unix|view|wordbounds)\>"
|
||||
icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>" "[[:space:]]+[[:digit:]]+$"
|
||||
icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+"
|
||||
icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+[[:alpha:]]+[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
|
||||
icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
|
||||
icolor brightgreen "^[[:space:]]*extendsyntax[[:space:]]+[[:alpha:]]+[[:space:]]+(i?color|header|magic|comment|linter|formatter)[[:space:]]+.*$"
|
||||
icolor green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|extendsyntax)\>"
|
||||
|
||||
@@ -20,10 +20,10 @@ icolor yellow "^[[:space:]]*i?color[[:space:]]*(bright)?(white|black|red|blue|gr
|
||||
icolor magenta "^[[:space:]]*i?color\>" "\<(start|end)="
|
||||
|
||||
# Strings
|
||||
icolor brightmagenta ""(\\.|[^"])*""
|
||||
color brightmagenta ""(\\.|[^"])*""
|
||||
# Comments
|
||||
icolor brightblue "(^|[[:space:]]+)#.*$"
|
||||
icolor cyan "^[[:space:]]*##.*$"
|
||||
color brightblue "(^|[[:space:]]+)#.*$"
|
||||
color cyan "^[[:space:]]*##.*$"
|
||||
|
||||
# Trailing whitespace
|
||||
color ,green "[[:space:]]+$"
|
||||
|
||||
@@ -10,7 +10,7 @@ color green "\<(define|include)\>"
|
||||
color red "\<(add|delete|flush|insert|remove|replace)\>"
|
||||
|
||||
# Families
|
||||
color yellow "\<(arp|bridge|inet|ip6?)\>"
|
||||
color yellow "\<(arp|bridge|inet|ingress|ip6?|netdev)\>"
|
||||
|
||||
# Terminal statements
|
||||
color red "\<(drop|reject)\>"
|
||||
@@ -27,4 +27,4 @@ color yellow ""(\\.|[^"])*"" "'(\\.|[^'])*'"
|
||||
color green "[{}():;|`$<>!=&\\]" "(\]|\[)"
|
||||
|
||||
# Basic variable names
|
||||
color brightred "\$[[:alpha:]_][[:alnum:]_.]*"
|
||||
color brightred "(\$|@)[[:alpha:]_-][[:alnum:]_.-]*"
|
||||
|
||||
@@ -14,10 +14,13 @@ color brightblue "^ .*"
|
||||
# Deleted lines.
|
||||
color brightred "^-.*"
|
||||
|
||||
# Header lines.
|
||||
color magenta "^(Index:|diff)[[:blank:]].*"
|
||||
# File names and dates.
|
||||
color red "^---.*"
|
||||
color green "^\+\+\+.*"
|
||||
# Line numbers.
|
||||
color brightyellow "^@@.*"
|
||||
# Header lines.
|
||||
color magenta "^diff.*"
|
||||
|
||||
# Statistics.
|
||||
color cyan start="^---$" end="^$"
|
||||
|
||||
@@ -7,7 +7,8 @@ comment "#"
|
||||
color green "^#.*$"
|
||||
color yellow "Copyright|\(C\)"
|
||||
# Header fields.
|
||||
color brightmagenta "\<(Project\-Id\-Version|Report\-Msgid\-Bugs\-To|Last\-Translator|Language(\-Team)?|X\-Generator|Plural\-Forms)\>"
|
||||
color brightred "^\"X-Bugs:.*\"$"
|
||||
color brightmagenta "\<(Project\-Id\-Version|Report\-Msgid\-Bugs\-To|Last\-Translator|Language(\-Team)?|X-Bugs|X-Generator|Plural\-Forms)\>"
|
||||
color cyan "\<(POT\-Creation\-Date|PO\-Revision\-Date|MIME\-Version|Content\-Type|Content\-Transfer\-Encoding)\>"
|
||||
# Encodings and numbers.
|
||||
color yellow "\<(UTF|ISO|Windows|Mac|IBM)\>\-[0-9]"
|
||||
|
||||
39
doc/syntax/rust.nanorc
Normal file
39
doc/syntax/rust.nanorc
Normal file
@@ -0,0 +1,39 @@
|
||||
## Syntax highlighting for Rust.
|
||||
## Copyright 2015 Luke Francl.
|
||||
## Licensed under GPL version 3.
|
||||
|
||||
## NOTE: Rules are applied in order: later rules re-colorize matching text.
|
||||
|
||||
syntax "rust" "\.rs"
|
||||
comment "//"
|
||||
|
||||
# Function definitions
|
||||
color magenta "fn [a-z_0-9]+"
|
||||
|
||||
# Reserved words
|
||||
color yellow "\<(abstract|alignof|as|become|box|break|const|continue|crate|do|else|enum|extern|false|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|offsetof|override|priv|pub|pure|ref|return|sizeof|static|self|struct|super|true|trait|type|typeof|unsafe|unsized|use|virtual|where|while|yield)\>"
|
||||
|
||||
# Macros
|
||||
color red "[a-z_]+!"
|
||||
|
||||
# Constants
|
||||
color magenta "[A-Z][A-Z_0-9]+"
|
||||
|
||||
# Traits/Enums/Structs/Types/...
|
||||
color magenta "[A-Z][A-Za-z0-9]+"
|
||||
|
||||
# Strings
|
||||
color green "\".*\""
|
||||
color green start="\".*\\$" end=".*\""
|
||||
## NOTE: This isn't accurate, but matching "#{0,} for the end of the string is too liberal.
|
||||
color green start="r#+\"" end="\"#+"
|
||||
|
||||
# Comments
|
||||
color blue "//.*"
|
||||
color blue start="/\*" end="\*/"
|
||||
|
||||
# Attributes
|
||||
color magenta start="#!\[" end="\]"
|
||||
|
||||
# Some common markers
|
||||
color brightcyan "(XXX|TODO|FIXME|\?\?\?)"
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
@smallbook
|
||||
@set EDITION 0.4
|
||||
@set VERSION 2.6.0
|
||||
@set UPDATED June 2016
|
||||
@set VERSION 2.7.3
|
||||
@set UPDATED December 2016
|
||||
|
||||
@dircategory Editors
|
||||
@direntry
|
||||
@@ -19,16 +19,16 @@
|
||||
@c end tex
|
||||
|
||||
@titlepage
|
||||
@title @code{nano}
|
||||
@title GNU @code{nano}
|
||||
@subtitle a small and friendly text editor.
|
||||
@subtitle version 2.6.0
|
||||
@subtitle version 2.7.3
|
||||
|
||||
@author Chris Allegretta
|
||||
@page
|
||||
|
||||
This manual documents @code{nano}, a small and friendly text editor.
|
||||
This manual documents GNU @code{nano}, a small and friendly text editor.
|
||||
|
||||
This manual is part of the @code{nano} distribution.@*
|
||||
This manual is part of the GNU @code{nano} distribution.@*
|
||||
@sp 4
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
2009, 2014, 2015 Free Software Foundation, Inc.
|
||||
@@ -55,7 +55,7 @@ e-mail: @email{chrisa@@asty.org}@*
|
||||
@node Top
|
||||
@top
|
||||
|
||||
This manual documents @code{nano}, a small and friendly text editor.
|
||||
This manual documents GNU @code{nano}, a small and friendly text editor.
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
@@ -74,7 +74,7 @@ This manual documents @code{nano}, a small and friendly text editor.
|
||||
@node Introduction
|
||||
@chapter Introduction
|
||||
|
||||
@code{nano} is a small and friendly text editor. Besides basic text
|
||||
GNU @code{nano} is a small and friendly text editor. Besides basic text
|
||||
editing, @code{nano} offers many extra features, such as an interactive
|
||||
search-and-replace, undo/redo, syntax coloring, smooth scrolling,
|
||||
auto-indentation, go-to-line-and-column-number, feature toggles,
|
||||
@@ -231,9 +231,15 @@ Show the current version number and exit.
|
||||
|
||||
@item -W
|
||||
@itemx --wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as parts of words.
|
||||
|
||||
@item -X "@var{characters}"
|
||||
@itemx --wordchars="@var{characters}"
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as parts of words. This overrides option
|
||||
@option{-W} (@option{--wordbounds}).
|
||||
|
||||
@item -Y @var{name}
|
||||
@itemx --syntax=@var{name}
|
||||
Specify a specific syntax from the nanorc files to use for highlighting.
|
||||
@@ -250,6 +256,11 @@ Interpret the Delete key differently so that both Backspace and Delete
|
||||
work properly. You should only need to use this option if Backspace
|
||||
acts like Delete on your system.
|
||||
|
||||
@item -g
|
||||
@itemx --showcursor
|
||||
Make the cursor visible in the file browser, putting it on the
|
||||
highlighted item. Useful for braille users.
|
||||
|
||||
@item -h
|
||||
@itemx --help
|
||||
Show a summary of command-line options and exit.
|
||||
@@ -264,6 +275,10 @@ the previous line.
|
||||
Make the 'Cut Text' command (normally ^K) cut from the current cursor
|
||||
position to the end of the line, instead of cutting the entire line.
|
||||
|
||||
@item -l
|
||||
@itemx --linenumbers
|
||||
Display line numbers to the left of the text area.
|
||||
|
||||
@item -m
|
||||
@itemx --mouse
|
||||
Enable mouse support, if available for your system. When enabled, mouse
|
||||
@@ -313,8 +328,8 @@ the @command{spell} program to be installed on your system.
|
||||
|
||||
@item -t
|
||||
@itemx --tempfile
|
||||
Don't ask whether or not to save the current contents of the file when
|
||||
exiting, assume yes. This is most useful when using @command{nano} as the
|
||||
Don't ask whether to save a modified buffer when exiting with ^X, but
|
||||
assume yes. This option is useful when @command{nano} is used as the
|
||||
composer of a mailer program.
|
||||
|
||||
@item -u
|
||||
@@ -362,7 +377,6 @@ separately (e.g.@: @code{nano -wS -$}).
|
||||
@itemx -b
|
||||
@itemx -e
|
||||
@itemx -f
|
||||
@itemx -g
|
||||
@itemx -j
|
||||
Ignored, for compatibility with Pico.
|
||||
|
||||
@@ -396,14 +410,19 @@ Characters not present on the keyboard can be entered in two ways:
|
||||
@item
|
||||
For characters with a single-byte code,
|
||||
pressing the Esc key twice and then typing a three-digit decimal number
|
||||
(from 000 to 255) will enter the character with the corresponding value.
|
||||
(from 000 to 255) will make @code{nano} behave as if you typed the key
|
||||
with that value.
|
||||
|
||||
@item
|
||||
For any possible character, pressing M-V (Alt+V) and then typing a
|
||||
six-digit hexadecimal number (starting with 0 or 1) will enter the
|
||||
character with the corresponding Unicode value.
|
||||
corresponding Unicode character into the buffer.
|
||||
@end itemize
|
||||
|
||||
For example, typing "Esc Esc 2 3 4" will enter the character "ê" ---
|
||||
useful when going to a French party. Typing "M-V 0 0 2 5 c 6" will
|
||||
enter the symbol "◆", a little black diamond.
|
||||
|
||||
@node Commands
|
||||
@section Commands
|
||||
|
||||
@@ -586,6 +605,9 @@ toggles the @code{-z} (@code{--suspend}) command-line option.
|
||||
@item Soft Wrapping Toggle (Meta-$)
|
||||
toggles the @code{-$} (@code{--softwrap}) command-line option.
|
||||
|
||||
@item Line Numbers Toggle (Meta-#)
|
||||
toggles the @code{-l} (@code{--linenumbers}) command-line option.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
@@ -694,6 +716,9 @@ Specify the color combination to use for the shortcut key combos
|
||||
in the two help lines at the bottom of the screen.
|
||||
See @code{set titlecolor} for more details.
|
||||
|
||||
@item set linenumbers
|
||||
Display line numbers to the left of the text area.
|
||||
|
||||
@item set locking
|
||||
Enable vim-style lock-files for when editing files.
|
||||
|
||||
@@ -725,6 +750,10 @@ Don't add newlines to the ends of files.
|
||||
@item set nowrap
|
||||
Don't hard-wrap text at all.
|
||||
|
||||
@item set numbercolor @var{fgcolor},@var{bgcolor}
|
||||
Specify the color combination to use for line numbers.
|
||||
See @code{set titlecolor} for more details.
|
||||
|
||||
@item set operatingdir "directory"
|
||||
@code{nano} will only read and write files inside "directory" and its
|
||||
subdirectories. Also, the current directory is changed to here, so
|
||||
@@ -776,6 +805,10 @@ won't work properly with this option enabled.
|
||||
@item set regexp
|
||||
Do extended regular expression searches by default.
|
||||
|
||||
@item set showcursor
|
||||
Put the cursor on the highlighted item in the file browser, to aid
|
||||
braille users.
|
||||
|
||||
@item set smarthome
|
||||
Make the Home key smarter. When Home is pressed anywhere but at the
|
||||
very beginning of non-whitespace characters on a line, the cursor will
|
||||
@@ -813,7 +846,8 @@ Save automatically on exit, don't prompt.
|
||||
@item set titlecolor @var{fgcolor},@var{bgcolor}
|
||||
Specify the color combination to use for the titlebar.
|
||||
Valid color names for foreground and background are:
|
||||
white, black, red, blue, green, yellow, magenta, and cyan.
|
||||
white, black, blue, green, red, cyan, yellow, and magenta.
|
||||
The name of the foreground color may be prefixed with 'bright'.
|
||||
And either @var{fgcolor} or @var{,bgcolor} may be left out.
|
||||
|
||||
@item set unix
|
||||
@@ -831,9 +865,14 @@ spaces. They must be single-column characters. The default pair
|
||||
for a UTF-8 locale is @t{"»·"}, and for other locales @t{">."}.
|
||||
|
||||
@item set wordbounds
|
||||
Detect word boundaries more accurately by treating punctuation
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as part of a word.
|
||||
|
||||
@item set wordchars "@var{string}"
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as parts of words. This overrides the option
|
||||
@code{wordbounds}.
|
||||
|
||||
@end table
|
||||
|
||||
@node Syntax Highlighting
|
||||
@@ -997,6 +1036,7 @@ a string in the current list in the file browser
|
||||
|
||||
@item searchagain
|
||||
Repeats the last search command without prompting.
|
||||
(The form 'research' is deprecated.)
|
||||
|
||||
@item findprevious
|
||||
As @code{searchagain}, but always in the backward direction.
|
||||
@@ -1031,6 +1071,7 @@ Cuts all text from the cursor position till the end of the buffer.
|
||||
|
||||
@item curpos
|
||||
Shows the current cursor position: the line, column, and character positions.
|
||||
(The form 'cursorpos' is deprecated.)
|
||||
|
||||
@item wordcount
|
||||
Counts the number of words, lines and characters in the current buffer.
|
||||
@@ -1055,6 +1096,10 @@ Unindents (shifts to the left) the currently marked text.
|
||||
Comments or uncomments the current line or marked lines, using the comment
|
||||
style specified in the active syntax.
|
||||
|
||||
@item complete
|
||||
Completes the fragment before the cursor to a full word found elsewhere
|
||||
in the current buffer.
|
||||
|
||||
@item left
|
||||
Goes left one position (in the editor or browser).
|
||||
|
||||
@@ -1091,6 +1136,13 @@ Moves the cursor to the beginning of the current paragraph.
|
||||
@item endpara
|
||||
Moves the cursor to the end of the current paragraph.
|
||||
|
||||
@item prevblock
|
||||
Moves the cursor to the beginning of the current or preceding block of text.
|
||||
(Blocks are separated by one or more blank lines.)
|
||||
|
||||
@item nextblock
|
||||
Moves the cursor to the beginning of the next block of text.
|
||||
|
||||
@item prevpage
|
||||
Goes up one screenful.
|
||||
|
||||
@@ -1104,7 +1156,8 @@ Goes to the first line of the file.
|
||||
Goes to the last line of the file.
|
||||
|
||||
@item gotoline
|
||||
Goes to a specific line (and column if specified).
|
||||
Goes to a specific line (and column if specified). Negative numbers count
|
||||
from the end of the file (and end of the line).
|
||||
|
||||
@item gototext
|
||||
Switches from targeting a line number to searching for text.
|
||||
@@ -1120,7 +1173,7 @@ Switches to editing/viewing the previous buffer when multiple buffers are open.
|
||||
Switches to editing/viewing the next buffer when multiple buffers are open.
|
||||
|
||||
@item verbatim
|
||||
Inserts the next character verbatim into the file.
|
||||
Inserts the next keystroke verbatim into the file.
|
||||
|
||||
@item tab
|
||||
Inserts a tab at the current cursor location.
|
||||
@@ -1152,6 +1205,7 @@ Toggles case sensitivity in searching (search/replace menus only).
|
||||
|
||||
@item regexp
|
||||
Toggles whether searching/replacing is based on literal strings or regular expressions.
|
||||
(The form 'regex' is deprecated.)
|
||||
|
||||
@item backwards
|
||||
Toggles whether searching/replacing goes forward or backward.
|
||||
@@ -1164,6 +1218,7 @@ Shows the next history entry in the prompt menus (e.g.@: search).
|
||||
|
||||
@item flipreplace
|
||||
Toggles between searching for something and replacing something.
|
||||
(The form 'dontreplace' is deprecated.)
|
||||
|
||||
@item flipexecute
|
||||
Toggles between inserting a file and executing a command.
|
||||
@@ -1171,6 +1226,7 @@ Toggles between inserting a file and executing a command.
|
||||
@item flipnewbuffer
|
||||
Toggles between inserting into the current buffer and into a new
|
||||
empty buffer.
|
||||
(The form 'newbuffer' is deprecated.)
|
||||
|
||||
@item dosformat
|
||||
When writing a file, switches to writing a DOS format (CR/LF).
|
||||
@@ -1275,6 +1331,7 @@ The 'search to replace' menu.
|
||||
|
||||
@item replacewith
|
||||
The 'replace with' menu, which comes up after 'search to replace'.
|
||||
(The form 'replace2' is deprecated.)
|
||||
|
||||
@item gotoline
|
||||
The 'goto line (and column)' menu.
|
||||
@@ -1453,18 +1510,21 @@ Disable use of the spell checker. This also eliminates the @code{-s}
|
||||
command-line option, which allows specifying an alternate spell checker.
|
||||
|
||||
@item --disable-tabcomp
|
||||
Disable the tab completion code when reading or writing files.
|
||||
Disable tab completion (when nano asks for a filename or a search string).
|
||||
|
||||
@item --disable-wordcomp
|
||||
Disable word completion.
|
||||
|
||||
@item --disable-wrapping
|
||||
Disable hard-wrapping of overlong lines. This also eliminates the @code{-w}
|
||||
command-line option, which enables long-line wrapping.
|
||||
Disable all hard-wrapping of overlong lines. This also eliminates the
|
||||
@code{-w} command-line option, which switches long-line wrapping off.
|
||||
|
||||
@item --enable-tiny
|
||||
This option disables all the above. It also disables some of the larger
|
||||
internals of the editor, like the marking code and the cut-to-end-of-line
|
||||
code. It also disables the function toggles. By using the enabling
|
||||
This option implies all of the above. It also disables some other
|
||||
internals of the editor, like the marking code, the cut-to-end-of-line
|
||||
code, and the function toggles. By using the enabling
|
||||
counterpart of the above options together with @code{--enable-tiny},
|
||||
specific features can be switched back on.
|
||||
specific features can be switched back on --- but a few cannot.
|
||||
|
||||
@item --enable-debug
|
||||
Enable support for runtime debug output. This can get pretty messy, so
|
||||
@@ -1472,7 +1532,7 @@ chances are you only want this feature when you're working on the nano source.
|
||||
|
||||
@item --disable-nls
|
||||
Disables Native Language support. This will disable the use of any
|
||||
available @code{nano} translations.
|
||||
available GNU @code{nano} translations.
|
||||
|
||||
@item --disable-wrapping-as-root
|
||||
Disable hard-wrapping of overlong lines by default when @code{nano}
|
||||
|
||||
@@ -9,8 +9,8 @@ Summary : a user-friendly editor, a Pico clone with enhancements
|
||||
|
||||
License : GPLv3+
|
||||
Group : Applications/Editors
|
||||
URL : http://www.nano-editor.org/
|
||||
Source : http://www.nano-editor.org/dist/v2.4/%{name}-%{version}.tar.gz
|
||||
URL : https://nano-editor.org/
|
||||
Source : https://nano-editor.org/dist/v2.6/%{name}-%{version}.tar.gz
|
||||
|
||||
BuildRoot : %{_tmppath}/%{name}-%{version}-root
|
||||
BuildRequires : autoconf, automake, gettext-devel, ncurses-devel, texinfo
|
||||
@@ -18,7 +18,7 @@ Requires(post) : info
|
||||
Requires(preun) : info
|
||||
|
||||
%description
|
||||
nano is a small and friendly text editor. It aims to emulate the
|
||||
GNU nano is a small and friendly text editor. It aims to emulate the
|
||||
Pico text editor while also offering several enhancements.
|
||||
|
||||
%prep
|
||||
|
||||
1146
po/nano.pot
1146
po/nano.pot
File diff suppressed because it is too large
Load Diff
1328
po/pt_BR.po
1328
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Execute this is the po/ subdir.
|
||||
# Let this be executed in the po/ subdir.
|
||||
cd "$(dirname "$0")" || exit
|
||||
|
||||
echo "Updating translations via TP"
|
||||
@@ -15,10 +15,12 @@ if [ -n "${NEWSTUFF}" ]; then
|
||||
echo $(printf '%s\n' *.po | LC_ALL=C sort | sed 's/\.po//g') >>LINGUAS
|
||||
fi
|
||||
|
||||
echo "Remerging and recompiling the PO files..."
|
||||
make
|
||||
echo "Regenerating POT file and remerging and recompiling PO files..."
|
||||
make update-po
|
||||
|
||||
#echo "Staging the files"
|
||||
#git add -v nano.pot
|
||||
#git add -v *.po
|
||||
#git add -v LINGUAS
|
||||
# Ensure that the PO files are newer than the POT.
|
||||
touch *.po
|
||||
|
||||
# If needed, fix a problem in the Makefile template.
|
||||
grep -q '^datarootdir' Makefile.in.in || \
|
||||
sed -i 's/^\(datadir.*\)/datarootdir = @datarootdir@\n\1/' Makefile.in.in
|
||||
|
||||
1163
po/zh_CN.po
1163
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1176
po/zh_TW.po
1176
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,23 @@
|
||||
AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
|
||||
CLEANFILES = revision.h
|
||||
|
||||
if BUILDING_FROM_GIT
|
||||
SOMETHING = "REVISION \"$(shell git describe --tags 2>/dev/null)\""
|
||||
else
|
||||
SOMETHING = "NOTHING \"from tarball\""
|
||||
endif
|
||||
|
||||
nano.o: revision.h
|
||||
winio.o: revision.h
|
||||
|
||||
revision.h: update_revision
|
||||
@[ -f $@ ] || touch $@
|
||||
@echo "#define $(SOMETHING)" | cmp -s $@ - || \
|
||||
echo "#define $(SOMETHING)" > $@
|
||||
|
||||
.PHONY: update_revision
|
||||
|
||||
bin_PROGRAMS = nano
|
||||
nano_SOURCES = browser.c \
|
||||
chars.c \
|
||||
|
||||
289
src/browser.c
289
src/browser.c
@@ -1,23 +1,22 @@
|
||||
/**************************************************************************
|
||||
* browser.c *
|
||||
* browser.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
|
||||
* 2010, 2011, 2013, 2014, 2015 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* 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. *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -46,7 +45,7 @@ static size_t selected = 0;
|
||||
* start browsing from. */
|
||||
char *do_browser(char *path)
|
||||
{
|
||||
char *retval = NULL, *newpath = NULL;
|
||||
char *retval = NULL;
|
||||
int kbinput;
|
||||
char *present_name = NULL;
|
||||
/* The name of the currently selected file, or of the directory we
|
||||
@@ -55,33 +54,22 @@ char *do_browser(char *path)
|
||||
/* The number of the selected file before the current selected file. */
|
||||
functionptrtype func;
|
||||
/* The function of the key the user typed in. */
|
||||
DIR *dir = opendir(path);
|
||||
|
||||
/* If we can't open the given directory, forget it. */
|
||||
if (dir == NULL) {
|
||||
beep();
|
||||
free(path);
|
||||
return NULL;
|
||||
}
|
||||
DIR *dir;
|
||||
/* The directory whose contents we are showing. */
|
||||
|
||||
/* Don't show a cursor in the file list. */
|
||||
curs_set(0);
|
||||
blank_statusbar();
|
||||
bottombars(MBROWSER);
|
||||
|
||||
read_directory_contents:
|
||||
/* We come here when we refresh or select a new directory. */
|
||||
|
||||
/* Start with no key pressed. */
|
||||
kbinput = ERR;
|
||||
path = free_and_assign(path, get_full_path(path));
|
||||
|
||||
path = mallocstrassn(path, get_full_path(newpath ? newpath : path));
|
||||
|
||||
if (path != NULL && newpath != NULL)
|
||||
if (path != NULL)
|
||||
dir = opendir(path);
|
||||
|
||||
if (path == NULL || dir == NULL) {
|
||||
statusline(ALERT, "Cannot open directory: %s", strerror(errno));
|
||||
statusline(ALERT, _("Cannot open directory: %s"), strerror(errno));
|
||||
/* If we don't have a file list yet, there is nothing to show. */
|
||||
if (filelist == NULL) {
|
||||
napms(1200);
|
||||
@@ -115,50 +103,26 @@ char *do_browser(char *path)
|
||||
|
||||
old_selected = (size_t)-1;
|
||||
|
||||
newpath = NULL;
|
||||
present_path = mallocstrcpy(present_path, path);
|
||||
|
||||
titlebar(path);
|
||||
|
||||
while (TRUE) {
|
||||
struct stat st;
|
||||
int i;
|
||||
char *new_path;
|
||||
/* The path we switch to at the "Go to Directory"
|
||||
* prompt. */
|
||||
|
||||
/* Make sure that the cursor is off. */
|
||||
curs_set(0);
|
||||
lastmessage = HUSH;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH) {
|
||||
/* Remember the selected file, to be able to reselect it. */
|
||||
present_name = strdup(filelist[selected]);
|
||||
bottombars(MBROWSER);
|
||||
|
||||
/* Reopen the current directory. */
|
||||
dir = opendir(path);
|
||||
if (dir != NULL)
|
||||
goto read_directory_contents;
|
||||
|
||||
statusline(ALERT, _("Error reading %s: %s"), path, strerror(errno));
|
||||
kbinput = ERR;
|
||||
}
|
||||
#endif
|
||||
/* Display (or redisplay) the file list if we don't have a key yet,
|
||||
* or the list has changed, or the selected file has changed. */
|
||||
if (kbinput == ERR || old_selected != selected)
|
||||
/* Display (or redisplay) the file list if the list itself or
|
||||
* the selected file has changed. */
|
||||
if (old_selected != selected)
|
||||
browser_refresh();
|
||||
|
||||
old_selected = selected;
|
||||
|
||||
kbinput = get_kbinput(edit);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_MOUSE
|
||||
if (kbinput == KEY_MOUSE) {
|
||||
int mouse_x, mouse_y;
|
||||
@@ -183,7 +147,7 @@ char *do_browser(char *path)
|
||||
/* If we selected the same filename as last time, fake a
|
||||
* press of the Enter key so that the file is read in. */
|
||||
if (old_selected == selected)
|
||||
unget_kbinput(sc_seq_or(do_enter, 0), FALSE, FALSE);
|
||||
unget_kbinput(KEY_ENTER, FALSE);
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -194,15 +158,15 @@ char *do_browser(char *path)
|
||||
|
||||
if (func == total_refresh) {
|
||||
total_redraw();
|
||||
/* Simulate a window resize to force a directory reread. */
|
||||
#ifndef NANO_TINY
|
||||
/* Simulate a window resize to force a directory reread. */
|
||||
kbinput = KEY_WINCH;
|
||||
#endif
|
||||
} else if (func == do_help_void) {
|
||||
#ifndef DISABLE_HELP
|
||||
do_help_void();
|
||||
/* The window dimensions might have changed, so act as if. */
|
||||
#ifndef NANO_TINY
|
||||
/* The window dimensions might have changed, so act as if. */
|
||||
kbinput = KEY_WINCH;
|
||||
#endif
|
||||
#else
|
||||
@@ -214,6 +178,26 @@ char *do_browser(char *path)
|
||||
} else if (func == do_research) {
|
||||
/* Search for another filename. */
|
||||
do_fileresearch();
|
||||
} else if (func == do_left) {
|
||||
if (selected > 0)
|
||||
selected--;
|
||||
} else if (func == do_right) {
|
||||
if (selected < filelist_len - 1)
|
||||
selected++;
|
||||
#ifndef NANO_TINY
|
||||
} else if (func == do_prev_word_void) {
|
||||
selected -= (selected % width);
|
||||
} else if (func == do_next_word_void) {
|
||||
selected += width - 1 - (selected % width);
|
||||
if (selected >= filelist_len)
|
||||
selected = filelist_len - 1;
|
||||
#endif
|
||||
} else if (func == do_up_void) {
|
||||
if (selected >= width)
|
||||
selected -= width;
|
||||
} else if (func == do_down_void) {
|
||||
if (selected + width <= filelist_len - 1)
|
||||
selected += width;
|
||||
} else if (func == do_page_up) {
|
||||
if (selected < width)
|
||||
selected = 0;
|
||||
@@ -235,7 +219,7 @@ char *do_browser(char *path)
|
||||
selected = filelist_len - 1;
|
||||
} else if (func == goto_dir_void) {
|
||||
/* Ask for the directory to go to. */
|
||||
i = do_prompt(TRUE,
|
||||
int i = do_prompt(TRUE,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
FALSE,
|
||||
#endif
|
||||
@@ -246,73 +230,46 @@ char *do_browser(char *path)
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
browser_refresh, _("Go To Directory"));
|
||||
|
||||
bottombars(MBROWSER);
|
||||
|
||||
/* If the directory begins with a newline (i.e. an
|
||||
* encoded null), treat it as though it's blank. */
|
||||
if (i < 0 || *answer == '\n') {
|
||||
if (i < 0) {
|
||||
statusbar(_("Cancelled"));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Convert newlines to nulls in the directory name. */
|
||||
sunder(answer);
|
||||
align(&answer);
|
||||
path = free_and_assign(path, real_dir_from_tilde(answer));
|
||||
|
||||
new_path = real_dir_from_tilde(answer);
|
||||
|
||||
if (new_path[0] != '/') {
|
||||
new_path = charealloc(new_path, strlen(path) +
|
||||
strlen(answer) + 1);
|
||||
sprintf(new_path, "%s%s", path, answer);
|
||||
/* If the given path is relative, join it with the current path. */
|
||||
if (*path != '/') {
|
||||
path = charealloc(path, strlen(present_path) +
|
||||
strlen(answer) + 1);
|
||||
sprintf(path, "%s%s", present_path, answer);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_OPERATINGDIR
|
||||
if (check_operating_dir(new_path, FALSE)) {
|
||||
/* TRANSLATORS: This refers to the option --operatingdir,
|
||||
* not to --restricted. */
|
||||
statusline(ALERT, _("Can't go outside of %s "
|
||||
"in confined mode"), full_operating_dir);
|
||||
free(new_path);
|
||||
if (check_operating_dir(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);
|
||||
path = mallocstrcpy(path, present_path);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Snip any trailing slashes, so the name can be compared. */
|
||||
while (strlen(path) > 1 && path[strlen(path) - 1] == '/')
|
||||
path[strlen(path) - 1] = '\0';
|
||||
|
||||
dir = opendir(new_path);
|
||||
if (dir == NULL) {
|
||||
/* We can't open this directory for some reason. */
|
||||
statusline(ALERT, _("Error reading %s: %s"), answer,
|
||||
strerror(errno));
|
||||
free(new_path);
|
||||
continue;
|
||||
}
|
||||
/* In case the specified directory cannot be entered, select it
|
||||
* (if it is in the current list) so it will be highlighted. */
|
||||
for (i = 0; i < filelist_len; i++)
|
||||
if (strcmp(filelist[i], path) == 0)
|
||||
selected = i;
|
||||
|
||||
/* Start over again with the new path value. */
|
||||
free(path);
|
||||
path = new_path;
|
||||
/* Try opening and reading the specified directory. */
|
||||
goto read_directory_contents;
|
||||
} else if (func == do_up_void) {
|
||||
if (selected >= width)
|
||||
selected -= width;
|
||||
} else if (func == do_down_void) {
|
||||
if (selected + width <= filelist_len - 1)
|
||||
selected += width;
|
||||
#ifndef NANO_TINY
|
||||
} else if (func == do_prev_word_void) {
|
||||
selected -= (selected % width);
|
||||
} else if (func == do_next_word_void) {
|
||||
selected += width - 1 - (selected % width);
|
||||
if (selected >= filelist_len)
|
||||
selected = filelist_len - 1;
|
||||
#endif
|
||||
} else if (func == do_left) {
|
||||
if (selected > 0)
|
||||
selected--;
|
||||
} else if (func == do_right) {
|
||||
if (selected < filelist_len - 1)
|
||||
selected++;
|
||||
} else if (func == do_enter) {
|
||||
/* We can't move up from "/". */
|
||||
struct stat st;
|
||||
|
||||
/* It isn't possible to move up from the root directory. */
|
||||
if (strcmp(filelist[selected], "/..") == 0) {
|
||||
statusline(ALERT, _("Can't move up a directory"));
|
||||
continue;
|
||||
@@ -323,21 +280,20 @@ char *do_browser(char *path)
|
||||
* 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 "
|
||||
"in confined mode"), full_operating_dir);
|
||||
statusline(ALERT, _("Can't go outside of %s"),
|
||||
full_operating_dir);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If for some reason the file is inaccessible, complain. */
|
||||
if (stat(filelist[selected], &st) == -1) {
|
||||
/* We can't open this file for some reason. Complain. */
|
||||
statusline(ALERT, _("Error reading %s: %s"),
|
||||
filelist[selected], strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If it isn't a directory, a file was selected -- we're done. */
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
/* We've successfully opened a file, so we're done. */
|
||||
retval = mallocstrcpy(NULL, filelist[selected]);
|
||||
break;
|
||||
}
|
||||
@@ -348,13 +304,27 @@ char *do_browser(char *path)
|
||||
present_name = striponedir(filelist[selected]);
|
||||
|
||||
/* Try opening and reading the selected directory. */
|
||||
newpath = filelist[selected];
|
||||
path = mallocstrcpy(path, filelist[selected]);
|
||||
goto read_directory_contents;
|
||||
} else if (func == do_exit) {
|
||||
/* Exit from the file browser. */
|
||||
break;
|
||||
#ifndef NANO_TINY
|
||||
} else if (kbinput == KEY_WINCH) {
|
||||
;
|
||||
#endif
|
||||
} else
|
||||
unbound_key(kbinput);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the window resized, refresh the file list. */
|
||||
if (kbinput == KEY_WINCH) {
|
||||
/* Remember the selected file, to be able to reselect it. */
|
||||
present_name = mallocstrcpy(NULL, filelist[selected]);
|
||||
/* Reread the contents of the current directory. */
|
||||
goto read_directory_contents;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
titlebar(NULL);
|
||||
@@ -389,7 +359,7 @@ char *do_browse_from(const char *inpath)
|
||||
* at all. If so, we'll just pass the current directory to
|
||||
* do_browser(). */
|
||||
if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
|
||||
path = mallocstrassn(path, striponedir(path));
|
||||
path = free_and_assign(path, striponedir(path));
|
||||
|
||||
if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
|
||||
char * currentdir = charalloc(PATH_MAX + 1);
|
||||
@@ -399,12 +369,11 @@ char *do_browse_from(const char *inpath)
|
||||
|
||||
if (path == NULL) {
|
||||
free(currentdir);
|
||||
statusline(MILD, "The working directory has disappeared");
|
||||
statusline(MILD, _("The working directory has disappeared"));
|
||||
beep();
|
||||
napms(1200);
|
||||
return NULL;
|
||||
} else
|
||||
align(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,6 +495,8 @@ void browser_refresh(void)
|
||||
size_t i;
|
||||
int line = 0, col = 0;
|
||||
/* The current line and column while the list is getting displayed. */
|
||||
int the_line = 0, the_column = 0;
|
||||
/* The line and column of the selected item. */
|
||||
char *info;
|
||||
/* The additional information that we'll display about a file. */
|
||||
|
||||
@@ -545,28 +516,27 @@ void browser_refresh(void)
|
||||
size_t infolen;
|
||||
/* The length of the file information in columns. */
|
||||
int infomaxlen = 7;
|
||||
/* The maximum length of the file information in
|
||||
* columns: seven for "--", "(dir)", or the file size,
|
||||
* and 12 for "(parent dir)". */
|
||||
/* The maximum length of the file information in columns:
|
||||
* normally seven, but will be twelve for "(parent dir)". */
|
||||
bool dots = (COLS >= 15 && namelen >= longest - infomaxlen);
|
||||
/* Do we put an ellipsis before the filename? Don't set
|
||||
* this to TRUE if we have fewer than 15 columns (i.e.
|
||||
* one column for padding, plus seven columns for a
|
||||
* filename other than ".."). */
|
||||
char *disp = display_string(thename, dots ? namelen -
|
||||
longest + infomaxlen + 4 : 0, longest, FALSE);
|
||||
/* If we put an ellipsis before the filename, reserve
|
||||
* one column for padding, plus seven columns for "--",
|
||||
* "(dir)", or the file size, plus three columns for the
|
||||
* ellipsis. */
|
||||
/* Whether to put an ellipsis before the filename? We don't
|
||||
* waste space on dots when there are fewer than 15 columns. */
|
||||
char *disp = display_string(thename, dots ?
|
||||
namelen + infomaxlen + 4 - longest : 0, longest, FALSE);
|
||||
/* The filename (or a fragment of it) in displayable format.
|
||||
* When a fragment, account for dots plus one space padding. */
|
||||
|
||||
/* Start highlighting the currently selected file or directory. */
|
||||
if (i == selected)
|
||||
/* 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);
|
||||
the_line = line;
|
||||
the_column = col;
|
||||
}
|
||||
|
||||
blank_line(edit, line, col, longest);
|
||||
|
||||
/* If dots is TRUE, we will display something like "...ename". */
|
||||
/* If the name is too long, we display something like "...ename". */
|
||||
if (dots)
|
||||
mvwaddstr(edit, line, col, "...");
|
||||
mvwaddstr(edit, line, dots ? col + 3 : col, disp);
|
||||
@@ -575,21 +545,16 @@ void browser_refresh(void)
|
||||
|
||||
col += longest;
|
||||
|
||||
/* Show information about the file. We don't want to report
|
||||
* file sizes for links, so we use lstat(). */
|
||||
/* Show information about the file: "--" for symlinks (except when
|
||||
* they point to a directory) and for files that have disappeared,
|
||||
* "(dir)" for directories, and the file size for normal files. */
|
||||
if (lstat(filelist[i], &st) == -1 || S_ISLNK(st.st_mode)) {
|
||||
/* If the file doesn't exist (i.e. it's been deleted while
|
||||
* the file browser is open), or it's a symlink that doesn't
|
||||
* point to a directory, display "--". */
|
||||
if (stat(filelist[i], &st) == -1 || !S_ISDIR(st.st_mode))
|
||||
info = mallocstrcpy(NULL, "--");
|
||||
/* If the file is a symlink that points to a directory,
|
||||
* display it as a directory. */
|
||||
else
|
||||
/* TRANSLATORS: Try to keep this at most 7 characters. */
|
||||
info = mallocstrcpy(NULL, _("(dir)"));
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
/* If the file is a directory, display it as such. */
|
||||
if (strcmp(thename, "..") == 0) {
|
||||
/* TRANSLATORS: Try to keep this at most 12 characters. */
|
||||
info = mallocstrcpy(NULL, _("(parent dir)"));
|
||||
@@ -602,6 +567,7 @@ void browser_refresh(void)
|
||||
|
||||
info = charalloc(infomaxlen + 1);
|
||||
|
||||
/* Massage the file size into a human-readable form. */
|
||||
if (st.st_size < (1 << 10))
|
||||
modifier = ' '; /* bytes */
|
||||
else if (st.st_size < (1 << 20)) {
|
||||
@@ -615,8 +581,7 @@ void browser_refresh(void)
|
||||
modifier = 'G'; /* gigabytes */
|
||||
}
|
||||
|
||||
/* Show the size if less than a terabyte,
|
||||
* otherwise show "(huge)". */
|
||||
/* Show the size if less than a terabyte, else show "(huge)". */
|
||||
if (result < (1 << 10))
|
||||
sprintf(info, "%4ju %cB", (intmax_t)result, modifier);
|
||||
else
|
||||
@@ -634,7 +599,7 @@ void browser_refresh(void)
|
||||
|
||||
mvwaddstr(edit, line, col - infolen, info);
|
||||
|
||||
/* Finish highlighting the currently selected file or directory. */
|
||||
/* If this is the selected item, finish its highlighting. */
|
||||
if (i == selected)
|
||||
wattroff(edit, hilite_attribute);
|
||||
|
||||
@@ -649,8 +614,12 @@ void browser_refresh(void)
|
||||
line++;
|
||||
col = 0;
|
||||
}
|
||||
}
|
||||
|
||||
wmove(edit, line, col);
|
||||
/* If requested, put the cursor on the selected item and switch it on. */
|
||||
if (ISSET(SHOW_CURSOR)) {
|
||||
wmove(edit, the_line, the_column);
|
||||
curs_set(1);
|
||||
}
|
||||
|
||||
wnoutrefresh(edit);
|
||||
@@ -703,13 +672,13 @@ int filesearch_init(void)
|
||||
/* This is now one simple call. It just does a lot. */
|
||||
input = do_prompt(FALSE,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
TRUE,
|
||||
TRUE,
|
||||
#endif
|
||||
MWHEREISFILE, NULL,
|
||||
MWHEREISFILE, NULL,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
&search_history,
|
||||
&search_history,
|
||||
#endif
|
||||
browser_refresh, "%s%s", _("Search"), buf);
|
||||
browser_refresh, "%s%s", _("Search"), buf);
|
||||
|
||||
/* Release buf now that we don't need it anymore. */
|
||||
free(buf);
|
||||
@@ -738,7 +707,7 @@ void findnextfile(const char *needle)
|
||||
/* Save the settings of all flags. */
|
||||
memcpy(stash, flags, sizeof(flags));
|
||||
|
||||
/* Search forward, case insensitive and without regexes. */
|
||||
/* Search forward, case insensitive, and without regexes. */
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
UNSET(CASE_SENSITIVE);
|
||||
UNSET(USE_REGEXP);
|
||||
@@ -782,11 +751,9 @@ void findnextfile(const char *needle)
|
||||
/* Search for a filename. */
|
||||
void do_filesearch(void)
|
||||
{
|
||||
if (filesearch_init() != 0) {
|
||||
/* Cancelled, or a blank search string, or done something. */
|
||||
bottombars(MBROWSER);
|
||||
/* If the user cancelled or jumped to first or last file, don't search. */
|
||||
if (filesearch_init() != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* If answer is now "", copy last_search into answer. */
|
||||
if (*answer == '\0')
|
||||
@@ -801,8 +768,6 @@ void do_filesearch(void)
|
||||
#endif
|
||||
|
||||
findnextfile(answer);
|
||||
|
||||
bottombars(MBROWSER);
|
||||
}
|
||||
|
||||
/* Search again for the last given filename, without prompting. */
|
||||
|
||||
452
src/chars.c
452
src/chars.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* chars.c *
|
||||
* chars.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
|
||||
* 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -35,12 +35,6 @@
|
||||
|
||||
static bool use_utf8 = FALSE;
|
||||
/* Whether we've enabled UTF-8 support. */
|
||||
static const wchar_t bad_wchar = 0xFFFD;
|
||||
/* If we get an invalid multibyte sequence, we treat it as
|
||||
* Unicode FFFD (Replacement Character), unless we're searching
|
||||
* for a match to it. */
|
||||
static const char *const bad_mbchar = "\xEF\xBF\xBD";
|
||||
static const int bad_mbchar_len = 3;
|
||||
|
||||
/* Enable UTF-8 support. */
|
||||
void utf8_init(void)
|
||||
@@ -94,9 +88,24 @@ void mbtowc_reset(void)
|
||||
IGNORE_CALL_RESULT(mbtowc(NULL, NULL, 0));
|
||||
}
|
||||
|
||||
void wctomb_reset(void)
|
||||
/* This function is equivalent to isalpha() for multibyte characters. */
|
||||
bool is_alpha_mbchar(const char *c)
|
||||
{
|
||||
IGNORE_CALL_RESULT(wctomb(NULL, 0));
|
||||
assert(c != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswalpha(wc);
|
||||
} else
|
||||
#endif
|
||||
return isalpha((unsigned char)*c);
|
||||
}
|
||||
|
||||
/* This function is equivalent to isalnum() for multibyte characters. */
|
||||
@@ -110,7 +119,7 @@ bool is_alnum_mbchar(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswalnum(wc);
|
||||
@@ -130,7 +139,7 @@ bool is_blank_mbchar(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswblank(wc);
|
||||
@@ -150,37 +159,18 @@ bool is_ascii_cntrl_char(int c)
|
||||
* handles high-bit control characters. */
|
||||
bool is_cntrl_char(int c)
|
||||
{
|
||||
return (-128 <= c && c < -96) || (0 <= c && c < 32) ||
|
||||
(127 <= c && c < 160);
|
||||
return ((c & 0x60) == 0 || c == 127);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* This function is equivalent to iscntrl() for wide characters, except
|
||||
* in that it also handles wide control characters with their high bits
|
||||
* set. */
|
||||
bool is_cntrl_wchar(wchar_t wc)
|
||||
{
|
||||
return (0 <= wc && wc < 32) || (127 <= wc && wc < 160);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function is equivalent to iscntrl() for multibyte characters,
|
||||
* except in that it also handles multibyte control characters with
|
||||
* their high bits set. */
|
||||
bool is_cntrl_mbchar(const char *c)
|
||||
{
|
||||
assert(c != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
}
|
||||
|
||||
return is_cntrl_wchar(wc);
|
||||
return ((c[0] & 0xE0) == 0 || c[0] == 127 ||
|
||||
((signed char)c[0] == -62 && (signed char)c[1] < -96));
|
||||
} else
|
||||
#endif
|
||||
return is_cntrl_char((unsigned char)*c);
|
||||
@@ -197,7 +187,7 @@ bool is_punct_mbchar(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iswpunct(wc);
|
||||
@@ -206,103 +196,91 @@ bool is_punct_mbchar(const char *c)
|
||||
return ispunct((unsigned char)*c);
|
||||
}
|
||||
|
||||
/* Return TRUE for a multibyte character found in a word (currently only
|
||||
* an alphanumeric or punctuation character, and only the latter if
|
||||
* allow_punct is TRUE) and FALSE otherwise. */
|
||||
/* Return TRUE when the given multibyte character c is a word-forming
|
||||
* character (that is: alphanumeric, or specified in wordchars, or
|
||||
* punctuation when allow_punct is TRUE), and FALSE otherwise. */
|
||||
bool is_word_mbchar(const char *c, bool allow_punct)
|
||||
{
|
||||
assert(c != NULL);
|
||||
if (*c == '\0')
|
||||
return FALSE;
|
||||
|
||||
return is_alnum_mbchar(c) || (allow_punct ? is_punct_mbchar(c) :
|
||||
FALSE);
|
||||
if (is_alnum_mbchar(c))
|
||||
return TRUE;
|
||||
|
||||
if (word_chars != NULL && *word_chars != '\0') {
|
||||
char symbol[mb_cur_max() + 1];
|
||||
int symlen = parse_mbchar(c, symbol, NULL);
|
||||
|
||||
symbol[symlen] = '\0';
|
||||
return (strstr(word_chars, symbol) != NULL);
|
||||
}
|
||||
|
||||
return (allow_punct && is_punct_mbchar(c));
|
||||
}
|
||||
|
||||
/* c is a control character. It displays as ^@, ^?, or ^[ch], where ch
|
||||
* is (c + 64). We return that character. */
|
||||
char control_rep(char c)
|
||||
/* Return the visible representation of control character c. */
|
||||
char control_rep(const signed char c)
|
||||
{
|
||||
assert(is_cntrl_char(c));
|
||||
|
||||
/* Treat newlines embedded in a line as encoded nulls. */
|
||||
if (c == '\n')
|
||||
return '@';
|
||||
else if (c == NANO_CONTROL_8)
|
||||
if (c == DEL_CODE)
|
||||
return '?';
|
||||
else if (c == -97)
|
||||
return '=';
|
||||
else if (c < 0)
|
||||
return c + 224;
|
||||
else
|
||||
return c + 64;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* c is a wide control character. It displays as ^@, ^?, or ^[ch],
|
||||
* where ch is (c + 64). We return that wide character. */
|
||||
wchar_t control_wrep(wchar_t wc)
|
||||
/* Return the visible representation of multibyte control character c. */
|
||||
char control_mbrep(const char *c, bool isdata)
|
||||
{
|
||||
assert(is_cntrl_wchar(wc));
|
||||
|
||||
/* Treat newlines embedded in a line as encoded nulls. */
|
||||
if (wc == '\n')
|
||||
/* An embedded newline is an encoded NUL if it is data. */
|
||||
if (*c == '\n' && (isdata || as_an_at))
|
||||
return '@';
|
||||
else if (wc == NANO_CONTROL_8)
|
||||
return '?';
|
||||
else
|
||||
return wc + 64;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* c is a multibyte control character. It displays as ^@, ^?, or ^[ch],
|
||||
* where ch is (c + 64). We return that multibyte character. */
|
||||
char *control_mbrep(const char *c, char *crep, int *crep_len)
|
||||
{
|
||||
assert(c != NULL && crep != NULL && crep_len != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
|
||||
IGNORE_CALL_RESULT(mbtowc(&wc, c, MB_CUR_MAX));
|
||||
*crep_len = wctomb(crep, control_wrep(wc));
|
||||
if ((unsigned char)c[0] < 128)
|
||||
return control_rep(c[0]);
|
||||
else
|
||||
return control_rep(c[1]);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
*crep_len = 1;
|
||||
*crep = control_rep(*c);
|
||||
}
|
||||
|
||||
return crep;
|
||||
return control_rep(*c);
|
||||
}
|
||||
|
||||
/* c is a multibyte non-control character. We return that multibyte
|
||||
* character. If crep is an invalid multibyte sequence, it will be
|
||||
* replaced with Unicode 0xFFFD (Replacement Character). */
|
||||
char *mbrep(const char *c, char *crep, int *crep_len)
|
||||
/* Assess how many bytes the given (multibyte) character occupies. Return -1
|
||||
* if the byte sequence is invalid, and return the number of bytes minus 8
|
||||
* when it encodes an invalid codepoint. Also, in the second parameter,
|
||||
* return the number of columns that the character occupies. */
|
||||
int length_of_char(const char *c, int *width)
|
||||
{
|
||||
assert(c != NULL && crep != NULL && crep_len != NULL);
|
||||
assert(c != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
wchar_t wc;
|
||||
int charlen = mbtowc(&wc, c, MB_CUR_MAX);
|
||||
|
||||
/* Reject invalid Unicode characters. */
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0 || !is_valid_unicode(wc)) {
|
||||
/* If the sequence is invalid... */
|
||||
if (charlen < 0) {
|
||||
mbtowc_reset();
|
||||
*crep_len = bad_mbchar_len;
|
||||
strncpy(crep, bad_mbchar, *crep_len);
|
||||
} else {
|
||||
*crep_len = wctomb(crep, wc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*crep_len < 0) {
|
||||
wctomb_reset();
|
||||
*crep_len = 0;
|
||||
}
|
||||
/* If the codepoint is invalid... */
|
||||
if (!is_valid_unicode(wc))
|
||||
return charlen - 8;
|
||||
else {
|
||||
*width = wcwidth(wc);
|
||||
/* If the codepoint is unassigned, assume a width of one. */
|
||||
if (*width < 0)
|
||||
*width = 1;
|
||||
return charlen;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
*crep_len = 1;
|
||||
*crep = *c;
|
||||
}
|
||||
|
||||
return crep;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function is equivalent to wcwidth() for multibyte characters. */
|
||||
@@ -317,15 +295,13 @@ int mbwidth(const char *c)
|
||||
|
||||
if (mbtowc(&wc, c, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc = bad_wchar;
|
||||
return 1;
|
||||
}
|
||||
|
||||
width = wcwidth(wc);
|
||||
|
||||
if (width == -1) {
|
||||
wc = bad_wchar;
|
||||
width = wcwidth(wc);
|
||||
}
|
||||
if (width == -1)
|
||||
return 1;
|
||||
|
||||
return width;
|
||||
} else
|
||||
@@ -333,27 +309,25 @@ int mbwidth(const char *c)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return the maximum width in bytes of a multibyte character. */
|
||||
/* Return the maximum length (in bytes) of a character. */
|
||||
int mb_cur_max(void)
|
||||
{
|
||||
return
|
||||
#ifdef ENABLE_UTF8
|
||||
use_utf8 ? MB_CUR_MAX :
|
||||
if (use_utf8)
|
||||
return MB_CUR_MAX;
|
||||
else
|
||||
#endif
|
||||
1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Convert the Unicode value in chr to a multibyte character with the
|
||||
* same wide character value as chr, if possible. If the conversion
|
||||
* succeeds, return the (dynamically allocated) multibyte character and
|
||||
* its length. Otherwise, return an undefined (dynamically allocated)
|
||||
* multibyte character and a length of zero. */
|
||||
/* Convert the Unicode value in chr to a multibyte character, if possible.
|
||||
* If the conversion succeeds, return the (dynamically allocated) multibyte
|
||||
* character and its length. Otherwise, return an undefined (dynamically
|
||||
* allocated) multibyte character and a length of zero. */
|
||||
char *make_mbchar(long chr, int *chr_mb_len)
|
||||
{
|
||||
char *chr_mb;
|
||||
|
||||
assert(chr_mb_len != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
chr_mb = charalloc(MB_CUR_MAX);
|
||||
@@ -361,7 +335,7 @@ char *make_mbchar(long chr, int *chr_mb_len)
|
||||
|
||||
/* Reject invalid Unicode characters. */
|
||||
if (*chr_mb_len < 0 || !is_valid_unicode((wchar_t)chr)) {
|
||||
wctomb_reset();
|
||||
IGNORE_CALL_RESULT(wctomb(NULL, 0));
|
||||
*chr_mb_len = 0;
|
||||
}
|
||||
} else
|
||||
@@ -376,37 +350,35 @@ char *make_mbchar(long chr, int *chr_mb_len)
|
||||
|
||||
/* Parse a multibyte character from buf. Return the number of bytes
|
||||
* used. If chr isn't NULL, store the multibyte character in it. If
|
||||
* col isn't NULL, store the new display width in it. If *buf is '\t',
|
||||
* we expect col to have the current display width. */
|
||||
* col isn't NULL, add the character's width (in columns) to it. */
|
||||
int parse_mbchar(const char *buf, char *chr, size_t *col)
|
||||
{
|
||||
int buf_mb_len;
|
||||
int length;
|
||||
|
||||
assert(buf != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
/* Get the number of bytes in the multibyte character. */
|
||||
buf_mb_len = mblen(buf, MB_CUR_MAX);
|
||||
length = mblen(buf, MB_CUR_MAX);
|
||||
|
||||
/* When the multibyte sequence is invalid, only take the first byte. */
|
||||
if (buf_mb_len < 0) {
|
||||
if (length <= 0) {
|
||||
IGNORE_CALL_RESULT(mblen(NULL, 0));
|
||||
buf_mb_len = 1;
|
||||
} else if (buf_mb_len == 0)
|
||||
buf_mb_len++;
|
||||
length = 1;
|
||||
}
|
||||
|
||||
/* When requested, store the multibyte character in chr. */
|
||||
if (chr != NULL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < buf_mb_len; i++)
|
||||
for (i = 0; i < length; i++)
|
||||
chr[i] = buf[i];
|
||||
}
|
||||
|
||||
/* When requested, store the width of the wide character in col. */
|
||||
/* When requested, add the width of the character to col. */
|
||||
if (col != NULL) {
|
||||
/* If we have a tab, get its width in columns using the
|
||||
/* If we have a tab, compute its width in columns based on the
|
||||
* current value of col. */
|
||||
if (*buf == '\t')
|
||||
*col += tabsize - *col % tabsize;
|
||||
@@ -414,8 +386,7 @@ int parse_mbchar(const char *buf, char *chr, size_t *col)
|
||||
* column for the "^", and one for the visible character. */
|
||||
else if (is_cntrl_mbchar(buf)) {
|
||||
*col += 2;
|
||||
/* If we have a normal character, get its width in columns
|
||||
* normally. */
|
||||
/* If we have a normal character, get its width normally. */
|
||||
} else
|
||||
*col += mbwidth(buf);
|
||||
}
|
||||
@@ -423,15 +394,15 @@ int parse_mbchar(const char *buf, char *chr, size_t *col)
|
||||
#endif
|
||||
{
|
||||
/* A byte character is one byte long. */
|
||||
buf_mb_len = 1;
|
||||
length = 1;
|
||||
|
||||
/* When requested, store the byte character in chr. */
|
||||
if (chr != NULL)
|
||||
*chr = *buf;
|
||||
|
||||
/* When requested, store the width of the wide character in col. */
|
||||
/* When requested, add the width of the character to col. */
|
||||
if (col != NULL) {
|
||||
/* If we have a tab, get its width in columns using the
|
||||
/* If we have a tab, compute its width in columns using the
|
||||
* current value of col. */
|
||||
if (*buf == '\t')
|
||||
*col += tabsize - *col % tabsize;
|
||||
@@ -445,7 +416,7 @@ int parse_mbchar(const char *buf, char *chr, size_t *col)
|
||||
}
|
||||
}
|
||||
|
||||
return buf_mb_len;
|
||||
return length;
|
||||
}
|
||||
|
||||
/* Return the index in buf of the beginning of the multibyte character
|
||||
@@ -500,8 +471,6 @@ int nstrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
if (s1 == s2)
|
||||
return 0;
|
||||
|
||||
assert(s1 != NULL && s2 != NULL);
|
||||
|
||||
for (; *s1 != '\0' && *s2 != '\0' && n > 0; s1++, s2++, n--) {
|
||||
if (tolower(*s1) != tolower(*s2))
|
||||
break;
|
||||
@@ -518,32 +487,38 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
if (use_utf8) {
|
||||
wchar_t wc1, wc2;
|
||||
|
||||
if (s1 == s2)
|
||||
return 0;
|
||||
|
||||
assert(s1 != NULL && s2 != NULL);
|
||||
|
||||
for (; *s1 != '\0' && *s2 != '\0' && n > 0;
|
||||
s1 += move_mbright(s1, 0), s2 += move_mbright(s2, 0), n--) {
|
||||
while (*s1 != '\0' && *s2 != '\0' && n > 0) {
|
||||
bool bad1 = FALSE, bad2 = FALSE;
|
||||
|
||||
if (mbtowc(&wc1, s1, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc1 = (unsigned char)*s1;
|
||||
bad1 = TRUE;
|
||||
}
|
||||
|
||||
if (mbtowc(&wc2, s2, MB_CUR_MAX) < 0) {
|
||||
mbtowc_reset();
|
||||
wc2 = (unsigned char)*s2;
|
||||
bad2 = TRUE;
|
||||
}
|
||||
|
||||
if (bad1 != bad2 || towlower(wc1) != towlower(wc2))
|
||||
break;
|
||||
if (bad1 || bad2) {
|
||||
if (*s1 != *s2)
|
||||
return (unsigned char)*s1 - (unsigned char)*s2;
|
||||
|
||||
if (bad1 != bad2)
|
||||
return (bad1 ? 1 : -1);
|
||||
} else {
|
||||
int difference = towlower(wc1) - towlower(wc2);
|
||||
|
||||
if (difference != 0)
|
||||
return difference;
|
||||
}
|
||||
|
||||
s1 += move_mbright(s1, 0);
|
||||
s2 += move_mbright(s2, 0);
|
||||
n--;
|
||||
}
|
||||
|
||||
return (n > 0) ? towlower(wc1) - towlower(wc2) : 0;
|
||||
return (n > 0) ? ((unsigned char)*s1 - (unsigned char)*s2) : 0;
|
||||
} else
|
||||
#endif
|
||||
return strncasecmp(s1, s2, n);
|
||||
@@ -553,20 +528,18 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
/* This function is equivalent to strcasestr(). */
|
||||
char *nstrcasestr(const char *haystack, const char *needle)
|
||||
{
|
||||
size_t haystack_len, needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL);
|
||||
size_t needle_len;
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)haystack;
|
||||
|
||||
haystack_len = strlen(haystack);
|
||||
needle_len = strlen(needle);
|
||||
|
||||
for (; *haystack != '\0' && haystack_len >= needle_len; haystack++,
|
||||
haystack_len--) {
|
||||
while (*haystack != '\0') {
|
||||
if (strncasecmp(haystack, needle, needle_len) == 0)
|
||||
return (char *)haystack;
|
||||
|
||||
haystack++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -578,21 +551,18 @@ char *mbstrcasestr(const char *haystack, const char *needle)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
size_t haystack_len, needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL);
|
||||
size_t needle_len;
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)haystack;
|
||||
|
||||
haystack_len = mbstrlen(haystack);
|
||||
needle_len = mbstrlen(needle);
|
||||
|
||||
for (; *haystack != '\0' && haystack_len >= needle_len;
|
||||
haystack += move_mbright(haystack, 0), haystack_len--) {
|
||||
if (mbstrncasecmp(haystack, needle, needle_len) == 0 &&
|
||||
mblen(haystack, MB_CUR_MAX) > 0)
|
||||
while (*haystack != '\0') {
|
||||
if (mbstrncasecmp(haystack, needle, needle_len) == 0)
|
||||
return (char *)haystack;
|
||||
|
||||
haystack += move_mbright(haystack, 0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -601,37 +571,32 @@ char *mbstrcasestr(const char *haystack, const char *needle)
|
||||
return (char *) strcasestr(haystack, needle);
|
||||
}
|
||||
|
||||
#if !defined(NANO_TINY) || !defined(DISABLE_TABCOMP)
|
||||
/* This function is equivalent to strstr(), except in that it scans the
|
||||
* string in reverse, starting at rev_start. */
|
||||
char *revstrstr(const char *haystack, const char *needle, const char
|
||||
*rev_start)
|
||||
char *revstrstr(const char *haystack, const char *needle,
|
||||
const char *pointer)
|
||||
{
|
||||
size_t rev_start_len, needle_len;
|
||||
size_t needle_len = strlen(needle);
|
||||
size_t tail_len = strlen(pointer);
|
||||
|
||||
assert(haystack != NULL && needle != NULL && rev_start != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)rev_start;
|
||||
|
||||
needle_len = strlen(needle);
|
||||
if (needle_len == 0)
|
||||
return (char *)pointer;
|
||||
|
||||
if (strlen(haystack) < needle_len)
|
||||
return NULL;
|
||||
|
||||
rev_start_len = strlen(rev_start);
|
||||
if (tail_len < needle_len)
|
||||
pointer += tail_len - needle_len;
|
||||
|
||||
for (; rev_start >= haystack; rev_start--, rev_start_len++) {
|
||||
if (rev_start_len >= needle_len && strncmp(rev_start, needle,
|
||||
needle_len) == 0)
|
||||
return (char *)rev_start;
|
||||
while (pointer >= haystack) {
|
||||
if (strncmp(pointer, needle, needle_len) == 0)
|
||||
return (char *)pointer;
|
||||
pointer--;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* !NANO_TINY || !DISABLE_TABCOMP */
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* This function is equivalent to strcasestr(), except in that it scans
|
||||
* the string in reverse, starting at rev_start. */
|
||||
char *revstrcasestr(const char *haystack, const char *needle, const char
|
||||
@@ -639,8 +604,6 @@ char *revstrcasestr(const char *haystack, const char *needle, const char
|
||||
{
|
||||
size_t rev_start_len, needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL && rev_start != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)rev_start;
|
||||
|
||||
@@ -667,11 +630,8 @@ char *mbrevstrcasestr(const char *haystack, const char *needle, const
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool begin_line = FALSE;
|
||||
size_t rev_start_len, needle_len;
|
||||
|
||||
assert(haystack != NULL && needle != NULL && rev_start != NULL);
|
||||
|
||||
if (*needle == '\0')
|
||||
return (char *)rev_start;
|
||||
|
||||
@@ -682,27 +642,22 @@ char *mbrevstrcasestr(const char *haystack, const char *needle, const
|
||||
|
||||
rev_start_len = mbstrlen(rev_start);
|
||||
|
||||
while (!begin_line) {
|
||||
while (TRUE) {
|
||||
if (rev_start_len >= needle_len &&
|
||||
mbstrncasecmp(rev_start, needle, needle_len) == 0 &&
|
||||
mblen(rev_start, MB_CUR_MAX) > 0)
|
||||
mbstrncasecmp(rev_start, needle, needle_len) == 0)
|
||||
return (char *)rev_start;
|
||||
|
||||
/* If we've reached the head of the haystack, we found nothing. */
|
||||
if (rev_start == haystack)
|
||||
begin_line = TRUE;
|
||||
else {
|
||||
rev_start = haystack + move_mbleft(haystack, rev_start -
|
||||
haystack);
|
||||
rev_start_len++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
rev_start = haystack + move_mbleft(haystack, rev_start - haystack);
|
||||
rev_start_len++;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
return revstrcasestr(haystack, needle, rev_start);
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* This function is equivalent to strlen() for multibyte strings. */
|
||||
size_t mbstrlen(const char *s)
|
||||
@@ -716,8 +671,6 @@ size_t nstrnlen(const char *s, size_t maxlen)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
assert(s != NULL);
|
||||
|
||||
for (; *s != '\0' && maxlen > 0; s++, maxlen--, n++)
|
||||
;
|
||||
|
||||
@@ -728,8 +681,6 @@ size_t nstrnlen(const char *s, size_t maxlen)
|
||||
/* This function is equivalent to strnlen() for multibyte strings. */
|
||||
size_t mbstrnlen(const char *s, size_t maxlen)
|
||||
{
|
||||
assert(s != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
size_t n = 0;
|
||||
@@ -753,7 +704,7 @@ char *mbstrchr(const char *s, const char *c)
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool bad_s_mb = FALSE, bad_c_mb = FALSE;
|
||||
char *s_mb = charalloc(MB_CUR_MAX);
|
||||
char symbol[MB_CUR_MAX];
|
||||
const char *q = s;
|
||||
wchar_t ws, wc;
|
||||
|
||||
@@ -764,9 +715,9 @@ char *mbstrchr(const char *s, const char *c)
|
||||
}
|
||||
|
||||
while (*s != '\0') {
|
||||
int s_mb_len = parse_mbchar(s, s_mb, NULL);
|
||||
int sym_len = parse_mbchar(s, symbol, NULL);
|
||||
|
||||
if (mbtowc(&ws, s_mb, s_mb_len) < 0) {
|
||||
if (mbtowc(&ws, symbol, sym_len) < 0) {
|
||||
mbtowc_reset();
|
||||
ws = (unsigned char)*s;
|
||||
bad_s_mb = TRUE;
|
||||
@@ -775,12 +726,10 @@ char *mbstrchr(const char *s, const char *c)
|
||||
if (bad_s_mb == bad_c_mb && ws == wc)
|
||||
break;
|
||||
|
||||
s += s_mb_len;
|
||||
q += s_mb_len;
|
||||
s += sym_len;
|
||||
q += sym_len;
|
||||
}
|
||||
|
||||
free(s_mb);
|
||||
|
||||
if (*s == '\0')
|
||||
q = NULL;
|
||||
|
||||
@@ -795,8 +744,6 @@ char *mbstrchr(const char *s, const char *c)
|
||||
/* This function is equivalent to strpbrk() for multibyte strings. */
|
||||
char *mbstrpbrk(const char *s, const char *accept)
|
||||
{
|
||||
assert(s != NULL && accept != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
for (; *s != '\0'; s += move_mbright(s, 0)) {
|
||||
@@ -817,11 +764,14 @@ char *revstrpbrk(const char *s, const char *accept, const char
|
||||
{
|
||||
assert(s != NULL && accept != NULL && rev_start != NULL);
|
||||
|
||||
for (; rev_start >= s; rev_start--) {
|
||||
const char *q = (*rev_start == '\0') ? NULL : strchr(accept,
|
||||
*rev_start);
|
||||
if (*rev_start == '\0') {
|
||||
if (rev_start == s)
|
||||
return NULL;
|
||||
rev_start--;
|
||||
}
|
||||
|
||||
if (q != NULL)
|
||||
for (; rev_start >= s; rev_start--) {
|
||||
if (strchr(accept, *rev_start) != NULL)
|
||||
return (char *)rev_start;
|
||||
}
|
||||
|
||||
@@ -837,22 +787,22 @@ char *mbrevstrpbrk(const char *s, const char *accept, const char
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool begin_line = FALSE;
|
||||
|
||||
while (!begin_line) {
|
||||
const char *q = (*rev_start == '\0') ? NULL :
|
||||
mbstrchr(accept, rev_start);
|
||||
|
||||
if (q != NULL)
|
||||
return (char *)rev_start;
|
||||
|
||||
if (*rev_start == '\0') {
|
||||
if (rev_start == s)
|
||||
begin_line = TRUE;
|
||||
else
|
||||
rev_start = s + move_mbleft(s, rev_start - s);
|
||||
return NULL;
|
||||
rev_start = s + move_mbleft(s, rev_start - s);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
while (TRUE) {
|
||||
if (mbstrchr(accept, rev_start) != NULL)
|
||||
return (char *)rev_start;
|
||||
|
||||
/* If we've reached the head of the string, we found nothing. */
|
||||
if (rev_start == s)
|
||||
return NULL;
|
||||
|
||||
rev_start = s + move_mbleft(s, rev_start - s);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
return revstrpbrk(s, accept, rev_start);
|
||||
@@ -864,8 +814,6 @@ char *mbrevstrpbrk(const char *s, const char *accept, const char
|
||||
* and FALSE otherwise. */
|
||||
bool has_blank_chars(const char *s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
|
||||
for (; *s != '\0'; s++) {
|
||||
if (isblank(*s))
|
||||
return TRUE;
|
||||
@@ -878,25 +826,18 @@ bool has_blank_chars(const char *s)
|
||||
* multibyte characters, and FALSE otherwise. */
|
||||
bool has_blank_mbchars(const char *s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
bool retval = FALSE;
|
||||
char *chr_mb = charalloc(MB_CUR_MAX);
|
||||
char symbol[MB_CUR_MAX];
|
||||
|
||||
for (; *s != '\0'; s += move_mbright(s, 0)) {
|
||||
parse_mbchar(s, chr_mb, NULL);
|
||||
parse_mbchar(s, symbol, NULL);
|
||||
|
||||
if (is_blank_mbchar(chr_mb)) {
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
if (is_blank_mbchar(symbol))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
free(chr_mb);
|
||||
|
||||
return retval;
|
||||
return FALSE;
|
||||
} else
|
||||
#endif
|
||||
return has_blank_chars(s);
|
||||
@@ -919,12 +860,11 @@ bool is_valid_unicode(wchar_t wc)
|
||||
* is, and FALSE otherwise. */
|
||||
bool is_valid_mbstring(const char *s)
|
||||
{
|
||||
assert(s != NULL);
|
||||
|
||||
return
|
||||
#ifdef ENABLE_UTF8
|
||||
use_utf8 ? (mbstowcs(NULL, s, 0) != (size_t)-1) :
|
||||
if (use_utf8)
|
||||
return (mbstowcs(NULL, s, 0) != (size_t)-1);
|
||||
else
|
||||
#endif
|
||||
TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* !DISABLE_NANORC */
|
||||
|
||||
156
src/color.c
156
src/color.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* color.c *
|
||||
* color.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
|
||||
* 2010, 2011, 2013, 2014, 2015 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
* for the colors in each syntax. */
|
||||
void set_colorpairs(void)
|
||||
{
|
||||
const syntaxtype *this_syntax = syntaxes;
|
||||
const syntaxtype *sint;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
size_t i;
|
||||
@@ -62,15 +62,14 @@ void set_colorpairs(void)
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
init_pair(i + 1, foreground, background);
|
||||
interface_color_pair[i].bright = bright;
|
||||
interface_color_pair[i].pairnum = COLOR_PAIR(i + 1);
|
||||
interface_color_pair[i] =
|
||||
COLOR_PAIR(i + 1) | (bright ? A_BOLD : A_NORMAL);
|
||||
}
|
||||
else {
|
||||
interface_color_pair[i].bright = FALSE;
|
||||
if (i != FUNCTION_TAG)
|
||||
interface_color_pair[i].pairnum = hilite_attribute;
|
||||
interface_color_pair[i] = hilite_attribute;
|
||||
else
|
||||
interface_color_pair[i].pairnum = A_NORMAL;
|
||||
interface_color_pair[i] = A_NORMAL;
|
||||
}
|
||||
|
||||
free(specified_color_combo[i]);
|
||||
@@ -79,25 +78,25 @@ void set_colorpairs(void)
|
||||
|
||||
/* For each syntax, go through its list of colors and assign each
|
||||
* its pair number, giving identical color pairs the same number. */
|
||||
for (; this_syntax != NULL; this_syntax = this_syntax->next) {
|
||||
colortype *this_color = this_syntax->color;
|
||||
int clr_pair = NUMBER_OF_ELEMENTS + 1;
|
||||
for (sint = syntaxes; sint != NULL; sint = sint->next) {
|
||||
colortype *ink;
|
||||
int new_number = NUMBER_OF_ELEMENTS + 1;
|
||||
|
||||
for (; this_color != NULL; this_color = this_color->next) {
|
||||
const colortype *beforenow = this_syntax->color;
|
||||
for (ink = sint->color; ink != NULL; ink = ink->next) {
|
||||
const colortype *beforenow = sint->color;
|
||||
|
||||
while (beforenow != this_color &&
|
||||
(beforenow->fg != this_color->fg ||
|
||||
beforenow->bg != this_color->bg ||
|
||||
beforenow->bright != this_color->bright))
|
||||
while (beforenow != ink && (beforenow->fg != ink->fg ||
|
||||
beforenow->bg != ink->bg ||
|
||||
beforenow->bright != ink->bright))
|
||||
beforenow = beforenow->next;
|
||||
|
||||
if (beforenow != this_color)
|
||||
this_color->pairnum = beforenow->pairnum;
|
||||
else {
|
||||
this_color->pairnum = clr_pair;
|
||||
clr_pair++;
|
||||
}
|
||||
if (beforenow != ink)
|
||||
ink->pairnum = beforenow->pairnum;
|
||||
else
|
||||
ink->pairnum = new_number++;
|
||||
|
||||
ink->attributes = COLOR_PAIR(ink->pairnum) |
|
||||
(ink->bright ? A_BOLD : A_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,7 +104,7 @@ void set_colorpairs(void)
|
||||
/* Initialize the color information. */
|
||||
void color_init(void)
|
||||
{
|
||||
colortype *tmpcolor = openfile->colorstrings;
|
||||
const colortype *ink;
|
||||
bool using_defaults = FALSE;
|
||||
short foreground, background;
|
||||
|
||||
@@ -121,9 +120,9 @@ void color_init(void)
|
||||
#endif
|
||||
|
||||
/* For each coloring expression, initialize the color pair. */
|
||||
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
||||
foreground = tmpcolor->fg;
|
||||
background = tmpcolor->bg;
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
foreground = ink->fg;
|
||||
background = ink->bg;
|
||||
|
||||
if (foreground == -1 && !using_defaults)
|
||||
foreground = COLOR_WHITE;
|
||||
@@ -131,7 +130,7 @@ void color_init(void)
|
||||
if (background == -1 && !using_defaults)
|
||||
background = COLOR_BLACK;
|
||||
|
||||
init_pair(tmpcolor->pairnum, foreground, background);
|
||||
init_pair(ink->pairnum, foreground, background);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "init_pair(): fg = %hd, bg = %hd\n", foreground, background);
|
||||
#endif
|
||||
@@ -340,42 +339,47 @@ void reset_multis_for_id(filestruct *fileptr, int index)
|
||||
* useful when we don't know how much screen state has changed. */
|
||||
void reset_multis(filestruct *fileptr, bool force)
|
||||
{
|
||||
int nobegin, noend;
|
||||
const colortype *ink;
|
||||
int nobegin = 0, noend = 0;
|
||||
regmatch_t startmatch, endmatch;
|
||||
const colortype *tmpcolor = openfile->colorstrings;
|
||||
|
||||
/* If there is no syntax or no multiline regex, there is nothing to do. */
|
||||
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
|
||||
return;
|
||||
|
||||
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If it's not a multi-line regex, amscray. */
|
||||
if (tmpcolor->end == NULL)
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
|
||||
alloc_multidata_if_needed(fileptr);
|
||||
|
||||
if (force == FALSE) {
|
||||
/* Check whether the multidata still matches the current situation. */
|
||||
nobegin = regexec(tmpcolor->start, fileptr->data, 1, &startmatch, 0);
|
||||
noend = regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
|
||||
if ((fileptr->multidata[tmpcolor->id] == CWHOLELINE ||
|
||||
fileptr->multidata[tmpcolor->id] == CNONE) &&
|
||||
nobegin = regexec(ink->start, fileptr->data, 1, &startmatch, 0);
|
||||
noend = regexec(ink->end, fileptr->data, 1, &endmatch, 0);
|
||||
if ((fileptr->multidata[ink->id] == CWHOLELINE ||
|
||||
fileptr->multidata[ink->id] == CNONE) &&
|
||||
nobegin && noend)
|
||||
continue;
|
||||
else if (fileptr->multidata[tmpcolor->id] == CSTARTENDHERE &&
|
||||
else if (fileptr->multidata[ink->id] == CSTARTENDHERE &&
|
||||
!nobegin && !noend && startmatch.rm_so < endmatch.rm_so)
|
||||
continue;
|
||||
else if (fileptr->multidata[tmpcolor->id] == CBEGINBEFORE &&
|
||||
else if (fileptr->multidata[ink->id] == CBEGINBEFORE &&
|
||||
nobegin && !noend)
|
||||
continue;
|
||||
else if (fileptr->multidata[tmpcolor->id] == CENDAFTER &&
|
||||
else if (fileptr->multidata[ink->id] == CENDAFTER &&
|
||||
!nobegin && noend)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we got here, things have changed. */
|
||||
reset_multis_for_id(fileptr, tmpcolor->id);
|
||||
reset_multis_for_id(fileptr, ink->id);
|
||||
|
||||
/* If start and end are the same, push the resets further. */
|
||||
if (force == FALSE && !nobegin && !noend &&
|
||||
startmatch.rm_so == endmatch.rm_so)
|
||||
reset_multis_for_id(fileptr, ink->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,23 +396,11 @@ void alloc_multidata_if_needed(filestruct *fileptr)
|
||||
}
|
||||
}
|
||||
|
||||
/* Poll the keyboard every second to see if the user starts typing. */
|
||||
bool key_was_pressed(void)
|
||||
{
|
||||
static time_t last_time = 0;
|
||||
|
||||
if (time(NULL) != last_time) {
|
||||
last_time = time(NULL);
|
||||
return (wgetch(edit) != ERR);
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Precalculate the multi-line start and end regex info so we can
|
||||
* speed up rendering (with any hope at all...). */
|
||||
void precalc_multicolorinfo(void)
|
||||
{
|
||||
const colortype *tmpcolor = openfile->colorstrings;
|
||||
const colortype *ink;
|
||||
regmatch_t startmatch, endmatch;
|
||||
filestruct *fileptr, *endptr;
|
||||
|
||||
@@ -418,32 +410,24 @@ void precalc_multicolorinfo(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Entering precalculation of multiline color info\n");
|
||||
#endif
|
||||
/* Let us get keypresses to see if the user is trying to start
|
||||
* editing. Later we may want to throw up a statusbar message
|
||||
* before starting this if it takes too long to do this routine.
|
||||
* For now silently abort if they hit a key. */
|
||||
nodelay(edit, TRUE);
|
||||
|
||||
for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
|
||||
for (ink = openfile->colorstrings; ink != NULL; ink = ink->next) {
|
||||
/* If this is not a multi-line regex, skip it. */
|
||||
if (tmpcolor->end == NULL)
|
||||
if (ink->end == NULL)
|
||||
continue;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Starting work on color id %d\n", tmpcolor->id);
|
||||
fprintf(stderr, "Starting work on color id %d\n", ink->id);
|
||||
#endif
|
||||
|
||||
for (fileptr = openfile->fileage; fileptr != NULL; fileptr = fileptr->next) {
|
||||
int startx = 0, nostart = 0;
|
||||
|
||||
if (key_was_pressed())
|
||||
goto precalc_cleanup;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "working on lineno %ld... ", (long)fileptr->lineno);
|
||||
#endif
|
||||
alloc_multidata_if_needed(fileptr);
|
||||
|
||||
while ((nostart = regexec(tmpcolor->start, &fileptr->data[startx],
|
||||
1, &startmatch, (startx == 0) ? 0 : REG_NOTBOL)) == 0) {
|
||||
while ((nostart = regexec(ink->start, &fileptr->data[startx], 1,
|
||||
&startmatch, (startx == 0) ? 0 : REG_NOTBOL)) == 0) {
|
||||
/* Look for an end, and start marking how many lines are
|
||||
* encompassed, which should speed up rendering later. */
|
||||
startx += startmatch.rm_eo;
|
||||
@@ -451,14 +435,14 @@ void precalc_multicolorinfo(void)
|
||||
fprintf(stderr, "start found at pos %lu... ", (unsigned long)startx);
|
||||
#endif
|
||||
/* Look first on this line for an end. */
|
||||
if (regexec(tmpcolor->end, &fileptr->data[startx], 1,
|
||||
if (regexec(ink->end, &fileptr->data[startx], 1,
|
||||
&endmatch, (startx == 0) ? 0 : REG_NOTBOL) == 0) {
|
||||
startx += endmatch.rm_eo;
|
||||
/* Step ahead when both start and end are mere anchors. */
|
||||
if (startmatch.rm_so == startmatch.rm_eo &&
|
||||
endmatch.rm_so == endmatch.rm_eo)
|
||||
startx += 1;
|
||||
fileptr->multidata[tmpcolor->id] = CSTARTENDHERE;
|
||||
fileptr->multidata[ink->id] = CSTARTENDHERE;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "end found on this line\n");
|
||||
#endif
|
||||
@@ -470,11 +454,7 @@ void precalc_multicolorinfo(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\nadvancing to line %ld to find end... ", (long)endptr->lineno);
|
||||
#endif
|
||||
/* Check for interrupting keyboard input again. */
|
||||
if (key_was_pressed())
|
||||
goto precalc_cleanup;
|
||||
|
||||
if (regexec(tmpcolor->end, endptr->data, 1, &endmatch, 0) == 0)
|
||||
if (regexec(ink->end, endptr->data, 1, &endmatch, 0) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -489,20 +469,20 @@ void precalc_multicolorinfo(void)
|
||||
#endif
|
||||
/* We found it, we found it, la la la la la. Mark all
|
||||
* the lines in between and the end properly. */
|
||||
fileptr->multidata[tmpcolor->id] = CENDAFTER;
|
||||
fileptr->multidata[ink->id] = CENDAFTER;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "marking line %ld as CENDAFTER\n", (long)fileptr->lineno);
|
||||
#endif
|
||||
for (fileptr = fileptr->next; fileptr != endptr; fileptr = fileptr->next) {
|
||||
alloc_multidata_if_needed(fileptr);
|
||||
fileptr->multidata[tmpcolor->id] = CWHOLELINE;
|
||||
fileptr->multidata[ink->id] = CWHOLELINE;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "marking intermediary line %ld as CWHOLELINE\n", (long)fileptr->lineno);
|
||||
#endif
|
||||
}
|
||||
|
||||
alloc_multidata_if_needed(endptr);
|
||||
fileptr->multidata[tmpcolor->id] = CBEGINBEFORE;
|
||||
fileptr->multidata[ink->id] = CBEGINBEFORE;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "marking line %ld as CBEGINBEFORE\n", (long)fileptr->lineno);
|
||||
#endif
|
||||
@@ -517,13 +497,11 @@ void precalc_multicolorinfo(void)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "no match\n");
|
||||
#endif
|
||||
fileptr->multidata[tmpcolor->id] = CNONE;
|
||||
fileptr->multidata[ink->id] = CNONE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
precalc_cleanup:
|
||||
nodelay(edit, FALSE);
|
||||
}
|
||||
|
||||
#endif /* !DISABLE_COLOR */
|
||||
|
||||
37
src/cut.c
37
src/cut.c
@@ -1,22 +1,23 @@
|
||||
/**************************************************************************
|
||||
* cut.c *
|
||||
* cut.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014 Mark Majeres *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -114,13 +115,7 @@ void cut_to_eof(void)
|
||||
* copy_text is TRUE, copy the text back into the filestruct afterward.
|
||||
* If cut_till_eof is TRUE, move all text from the current cursor
|
||||
* position to the end of the file into the cutbuffer. */
|
||||
void do_cut_text(
|
||||
#ifndef NANO_TINY
|
||||
bool copy_text, bool cut_till_eof
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
)
|
||||
void do_cut_text(bool copy_text, bool cut_till_eof)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
filestruct *cb_save = NULL;
|
||||
@@ -220,10 +215,10 @@ void do_cut_text_void(void)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
add_undo(CUT);
|
||||
#endif
|
||||
do_cut_text(FALSE, FALSE);
|
||||
#ifndef NANO_TINY
|
||||
update_undo(CUT);
|
||||
#else
|
||||
do_cut_text();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
580
src/files.c
580
src/files.c
File diff suppressed because it is too large
Load Diff
649
src/global.c
649
src/global.c
File diff suppressed because it is too large
Load Diff
42
src/help.c
42
src/help.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* help.c *
|
||||
* help.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, *
|
||||
* 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -141,6 +141,12 @@ void do_help(void)
|
||||
|
||||
if (func == total_refresh) {
|
||||
total_redraw();
|
||||
} else if (func == do_up_void) {
|
||||
if (line > 0)
|
||||
line--;
|
||||
} else if (func == do_down_void) {
|
||||
if (line + (editwinrows - 1) < last_line)
|
||||
line++;
|
||||
} else if (func == do_page_up) {
|
||||
if (line > editwinrows - 2)
|
||||
line -= editwinrows - 2;
|
||||
@@ -149,12 +155,6 @@ void do_help(void)
|
||||
} else if (func == do_page_down) {
|
||||
if (line + (editwinrows - 1) < last_line)
|
||||
line += editwinrows - 2;
|
||||
} else if (func == do_up_void) {
|
||||
if (line > 0)
|
||||
line--;
|
||||
} else if (func == do_down_void) {
|
||||
if (line + (editwinrows - 1) < last_line)
|
||||
line++;
|
||||
} else if (func == do_first_line) {
|
||||
line = 0;
|
||||
} else if (func == do_last_line) {
|
||||
@@ -419,7 +419,11 @@ void help_init(void)
|
||||
* but allow it to spill into the second, for "M-Space". */
|
||||
if (scsfound == 1) {
|
||||
sprintf(ptr, "%s ", s->keystr);
|
||||
ptr += 6;
|
||||
/* Unicode arrows take three bytes instead of one. */
|
||||
if (s->keystr[1] == '\xE2')
|
||||
ptr += 8;
|
||||
else
|
||||
ptr += 6;
|
||||
} else {
|
||||
ptr += sprintf(ptr, "(%s)\t", s->keystr);
|
||||
break;
|
||||
|
||||
303
src/move.c
303
src/move.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* move.c *
|
||||
* move.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
/* Move to the first line of the file. */
|
||||
void do_first_line(void)
|
||||
{
|
||||
openfile->current = openfile->edittop = openfile->fileage;
|
||||
openfile->current = openfile->fileage;
|
||||
openfile->current_x = 0;
|
||||
openfile->placewewant = 0;
|
||||
|
||||
@@ -41,6 +41,8 @@ void do_last_line(void)
|
||||
openfile->current = openfile->filebot;
|
||||
openfile->current_x = strlen(openfile->filebot->data);
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
/* Set the last line of the screen as the target for the cursor. */
|
||||
openfile->current_y = editwinrows - 1;
|
||||
|
||||
refresh_needed = TRUE;
|
||||
@@ -50,38 +52,32 @@ void do_last_line(void)
|
||||
/* Move up one page. */
|
||||
void do_page_up(void)
|
||||
{
|
||||
int i, skipped = 0;
|
||||
int i, mustmove, skipped = 0;
|
||||
|
||||
/* If the cursor is less than a page away from the top of the file,
|
||||
* put it at the beginning of the first line. */
|
||||
if (openfile->current->lineno == 1 || (
|
||||
#ifndef NANO_TINY
|
||||
!ISSET(SOFTWRAP) &&
|
||||
#endif
|
||||
openfile->current->lineno <= editwinrows - 2)) {
|
||||
if (openfile->current->lineno == 1 || (!ISSET(SOFTWRAP) &&
|
||||
openfile->current->lineno <= editwinrows - 2)) {
|
||||
do_first_line();
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we're not in smooth scrolling mode, put the cursor at the
|
||||
* beginning of the top line of the edit window, as Pico does. */
|
||||
#ifndef NANO_TINY
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
#endif
|
||||
openfile->current = openfile->edittop;
|
||||
openfile->placewewant = openfile->current_y = 0;
|
||||
#ifndef NANO_TINY
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = editwinrows - 2; i - skipped > 0 && openfile->current !=
|
||||
openfile->fileage; i--) {
|
||||
mustmove = (editwinrows < 3) ? 1 : editwinrows - 2;
|
||||
|
||||
for (i = mustmove; i - skipped > 0 && openfile->current != openfile->fileage; i--) {
|
||||
openfile->current = openfile->current->prev;
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP) && openfile->current) {
|
||||
skipped += strlenpt(openfile->current->data) / COLS;
|
||||
skipped += strlenpt(openfile->current->data) / editwincols;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_page_up: i = %d, skipped = %d based on line %ld len %lu\n",
|
||||
fprintf(stderr, "paging up: i = %d, skipped = %d based on line %ld len %lu\n",
|
||||
i, skipped, (long)openfile->current->lineno, (unsigned long)strlenpt(openfile->current->data));
|
||||
#endif
|
||||
}
|
||||
@@ -91,20 +87,15 @@ void do_page_up(void)
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
openfile->placewewant);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_page_up: openfile->current->lineno = %lu, skipped = %d\n",
|
||||
(unsigned long)openfile->current->lineno, skipped);
|
||||
#endif
|
||||
|
||||
/* Scroll the edit window up a page. */
|
||||
edit_update(STATIONARY);
|
||||
adjust_viewport(STATIONARY);
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
/* Move down one page. */
|
||||
void do_page_down(void)
|
||||
{
|
||||
int i;
|
||||
int i, mustmove;
|
||||
|
||||
/* If the cursor is less than a page away from the bottom of the file,
|
||||
* put it at the end of the last line. */
|
||||
@@ -115,20 +106,17 @@ void do_page_down(void)
|
||||
|
||||
/* If we're not in smooth scrolling mode, put the cursor at the
|
||||
* beginning of the top line of the edit window, as Pico does. */
|
||||
#ifndef NANO_TINY
|
||||
if (!ISSET(SMOOTH_SCROLL)) {
|
||||
#endif
|
||||
openfile->current = openfile->edittop;
|
||||
openfile->placewewant = openfile->current_y = 0;
|
||||
#ifndef NANO_TINY
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = maxrows - 2; i > 0 && openfile->current !=
|
||||
openfile->filebot; i--) {
|
||||
mustmove = (maxrows < 3) ? 1 : maxrows - 2;
|
||||
|
||||
for (i = mustmove; i > 0 && openfile->current != openfile->filebot; i--) {
|
||||
openfile->current = openfile->current->next;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "do_page_down: moving to line %lu\n", (unsigned long)openfile->current->lineno);
|
||||
fprintf(stderr, "paging down: moving to line %lu\n", (unsigned long)openfile->current->lineno);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -137,7 +125,7 @@ void do_page_down(void)
|
||||
openfile->placewewant);
|
||||
|
||||
/* Scroll the edit window down a page. */
|
||||
edit_update(STATIONARY);
|
||||
adjust_viewport(STATIONARY);
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
@@ -147,7 +135,7 @@ void do_page_down(void)
|
||||
* afterwards. */
|
||||
void do_para_begin(bool allow_update)
|
||||
{
|
||||
filestruct *current_save = openfile->current;
|
||||
filestruct *was_current = openfile->current;
|
||||
|
||||
if (openfile->current != openfile->fileage) {
|
||||
do {
|
||||
@@ -159,7 +147,7 @@ void do_para_begin(bool allow_update)
|
||||
openfile->current_x = 0;
|
||||
|
||||
if (allow_update)
|
||||
edit_redraw(current_save);
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Move up to the beginning of the last beginning-of-paragraph line
|
||||
@@ -177,7 +165,7 @@ void do_para_begin_void(void)
|
||||
* paragraph or isn't in a paragraph. */
|
||||
void do_para_end(bool allow_update)
|
||||
{
|
||||
filestruct *const current_save = openfile->current;
|
||||
filestruct *was_current = openfile->current;
|
||||
|
||||
while (openfile->current != openfile->filebot &&
|
||||
!inpar(openfile->current))
|
||||
@@ -197,7 +185,7 @@ void do_para_end(bool allow_update)
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
|
||||
if (allow_update)
|
||||
edit_redraw(current_save);
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Move down to the beginning of the last line of the current paragraph.
|
||||
@@ -209,13 +197,52 @@ void do_para_end_void(void)
|
||||
}
|
||||
#endif /* !DISABLE_JUSTIFY */
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Move to the preceding block of text in the file. */
|
||||
void do_prev_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_text = FALSE, seen_text = FALSE;
|
||||
|
||||
/* Skip backward until first blank line after some nonblank line(s). */
|
||||
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
|
||||
openfile->current = openfile->current->prev;
|
||||
is_text = !white_string(openfile->current->data);
|
||||
seen_text = seen_text || is_text;
|
||||
}
|
||||
|
||||
/* Step forward one line again if this one is blank. */
|
||||
if (openfile->current->next != NULL &&
|
||||
white_string(openfile->current->data))
|
||||
openfile->current = openfile->current->next;
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Move to the next block of text in the file. */
|
||||
void do_next_block(void)
|
||||
{
|
||||
filestruct *was_current = openfile->current;
|
||||
bool is_white = white_string(openfile->current->data);
|
||||
bool seen_white = is_white;
|
||||
|
||||
/* Skip forward until first nonblank line after some blank line(s). */
|
||||
while (openfile->current->next != NULL && (!seen_white || is_white)) {
|
||||
openfile->current = openfile->current->next;
|
||||
is_white = white_string(openfile->current->data);
|
||||
seen_white = seen_white || is_white;
|
||||
}
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Move to the previous word in the file. If allow_punct is TRUE, treat
|
||||
* punctuation as part of a word. If allow_update is TRUE, update the
|
||||
* screen afterwards. */
|
||||
void do_prev_word(bool allow_punct, bool allow_update)
|
||||
{
|
||||
filestruct *current_save = openfile->current;
|
||||
filestruct *was_current = openfile->current;
|
||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||
|
||||
assert(openfile->current != NULL && openfile->current->data != NULL);
|
||||
@@ -255,7 +282,7 @@ void do_prev_word(bool allow_punct, bool allow_update)
|
||||
/* If allow_update is TRUE, update the screen. */
|
||||
if (allow_update) {
|
||||
focusing = FALSE;
|
||||
edit_redraw(current_save);
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +299,7 @@ void do_prev_word_void(void)
|
||||
* otherwise. */
|
||||
bool do_next_word(bool allow_punct, bool allow_update)
|
||||
{
|
||||
filestruct *current_save = openfile->current;
|
||||
filestruct *was_current = openfile->current;
|
||||
bool started_on_word = is_word_mbchar(openfile->current->data +
|
||||
openfile->current_x, allow_punct);
|
||||
bool seen_space = !started_on_word;
|
||||
@@ -307,7 +334,7 @@ bool do_next_word(bool allow_punct, bool allow_update)
|
||||
/* If allow_update is TRUE, update the screen. */
|
||||
if (allow_update) {
|
||||
focusing = FALSE;
|
||||
edit_redraw(current_save);
|
||||
edit_redraw(was_current);
|
||||
}
|
||||
|
||||
/* Return whether we started on a word. */
|
||||
@@ -320,7 +347,19 @@ void do_next_word_void(void)
|
||||
{
|
||||
do_next_word(ISSET(WORD_BOUNDS), TRUE);
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Make sure that the current line, when it is partially scrolled off the
|
||||
* screen in softwrap mode, is scrolled fully into view. */
|
||||
void ensure_line_is_visible(void)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP) && strlenpt(openfile->current->data) / editwincols +
|
||||
openfile->current_y >= editwinrows) {
|
||||
adjust_viewport(ISSET(SMOOTH_SCROLL) ? FLOWING : CENTERING);
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Move to the beginning of the current line. If the SMART_HOME flag is
|
||||
* set, move to the first non-whitespace character of the current line
|
||||
@@ -328,7 +367,7 @@ void do_next_word_void(void)
|
||||
* if we are. */
|
||||
void do_home(void)
|
||||
{
|
||||
size_t pww_save = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SMART_HOME)) {
|
||||
@@ -345,39 +384,34 @@ void do_home(void)
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
if (need_screen_update(pww_save))
|
||||
if (need_horizontal_scroll(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
|
||||
/* Move to the end of the current line. */
|
||||
void do_end(void)
|
||||
{
|
||||
size_t pww_save = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
if (need_screen_update(pww_save))
|
||||
if (need_horizontal_scroll(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
|
||||
ensure_line_is_visible();
|
||||
}
|
||||
|
||||
/* If scroll_only is FALSE, move up one line. If scroll_only is TRUE,
|
||||
* scroll up one line without scrolling the cursor. */
|
||||
void do_up(
|
||||
#ifndef NANO_TINY
|
||||
bool scroll_only
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
)
|
||||
void do_up(bool scroll_only)
|
||||
{
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
/* If we're at the top of the file, or if scroll_only is TRUE and
|
||||
* the top of the file is onscreen, get out. */
|
||||
if (openfile->current == openfile->fileage
|
||||
#ifndef NANO_TINY
|
||||
|| (scroll_only && openfile->edittop == openfile->fileage)
|
||||
#endif
|
||||
)
|
||||
if (openfile->current == openfile->fileage ||
|
||||
(scroll_only && openfile->edittop == openfile->fileage))
|
||||
return;
|
||||
|
||||
assert(ISSET(SOFTWRAP) || openfile->current_y == openfile->current->lineno - openfile->edittop->lineno);
|
||||
@@ -387,63 +421,39 @@ void do_up(
|
||||
openfile->current_x = actual_x(openfile->current->data,
|
||||
openfile->placewewant);
|
||||
|
||||
/* If scroll_only is FALSE and if we're on the first line of the
|
||||
* edit window, scroll the edit window up one line if we're in
|
||||
* smooth scrolling mode, or up half a page if we're not. If
|
||||
* scroll_only is TRUE, scroll the edit window up one line
|
||||
* unconditionally. */
|
||||
if (openfile->current_y == 0
|
||||
#ifndef NANO_TINY
|
||||
|| (ISSET(SOFTWRAP) && openfile->edittop->lineno == openfile->current->next->lineno) || scroll_only
|
||||
#endif
|
||||
)
|
||||
edit_scroll(UPWARD,
|
||||
#ifndef NANO_TINY
|
||||
(ISSET(SMOOTH_SCROLL) || scroll_only) ? 1 :
|
||||
#endif
|
||||
editwinrows / 2 + 1);
|
||||
/* 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->next == openfile->edittop || scroll_only)
|
||||
edit_scroll(UPWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ?
|
||||
1 : editwinrows / 2 + 1);
|
||||
|
||||
/* If we're not on the first line of the edit window, and the target
|
||||
* column is beyond the screen or the mark is on, redraw the prior
|
||||
* and current lines. */
|
||||
if (openfile->current_y > 0 && need_screen_update(0)) {
|
||||
update_line(openfile->current->next, 0);
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
/* If the lines weren't already redrawn, see if they need to be. */
|
||||
if (openfile->current_y > 0) {
|
||||
/* Redraw the prior line if it was horizontally scrolled. */
|
||||
if (need_horizontal_scroll(was_column, 0))
|
||||
update_line(openfile->current->next, 0);
|
||||
/* Redraw the current line if it needs to be horizontally scrolled. */
|
||||
if (need_horizontal_scroll(0, xplustabs()))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move up one line. */
|
||||
void do_up_void(void)
|
||||
{
|
||||
do_up(
|
||||
#ifndef NANO_TINY
|
||||
FALSE
|
||||
#endif
|
||||
);
|
||||
do_up(FALSE);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Scroll up one line without scrolling the cursor. */
|
||||
void do_scroll_up(void)
|
||||
{
|
||||
do_up(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If scroll_only is FALSE, move down one line. If scroll_only is TRUE,
|
||||
* scroll down one line without scrolling the cursor. */
|
||||
void do_down(
|
||||
#ifndef NANO_TINY
|
||||
bool scroll_only
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
)
|
||||
void do_down(bool scroll_only)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
int amount = 0, enough;
|
||||
filestruct *topline;
|
||||
#endif
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
/* If we're at the bottom of the file, get out. */
|
||||
if (openfile->current == openfile->filebot)
|
||||
@@ -456,18 +466,20 @@ void do_down(
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
/* Compute the number of lines to scroll. */
|
||||
amount = strlenpt(openfile->current->data) / COLS - xplustabs() / COLS +
|
||||
strlenpt(openfile->current->next->data) / COLS +
|
||||
amount = strlenpt(openfile->current->data) / editwincols -
|
||||
xplustabs() / editwincols +
|
||||
strlenpt(openfile->current->next->data) / editwincols +
|
||||
openfile->current_y - editwinrows + 2;
|
||||
topline = openfile->edittop;
|
||||
/* Reduce the amount when there are overlong lines at the top. */
|
||||
for (enough = 1; enough < amount; enough++) {
|
||||
amount -= strlenpt(topline->data) / COLS;
|
||||
if (amount <= 0) {
|
||||
amount -= strlenpt(topline->data) / editwincols;
|
||||
if (amount > 0)
|
||||
topline = topline->next;
|
||||
if (amount < enough) {
|
||||
amount = enough;
|
||||
break;
|
||||
}
|
||||
topline = topline->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -482,47 +494,48 @@ void do_down(
|
||||
* smooth scrolling mode, or down half a page if we're not. If
|
||||
* scroll_only is TRUE, scroll the edit window down one line
|
||||
* unconditionally. */
|
||||
if (openfile->current_y == editwinrows - 1
|
||||
#ifndef NANO_TINY
|
||||
|| amount > 0 || scroll_only
|
||||
#endif
|
||||
) {
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->current_y == editwinrows - 1 || amount > 0 || scroll_only) {
|
||||
if (amount < 1 || scroll_only)
|
||||
amount = 1;
|
||||
#endif
|
||||
edit_scroll(DOWNWARD,
|
||||
#ifndef NANO_TINY
|
||||
(ISSET(SMOOTH_SCROLL) || scroll_only) ? amount :
|
||||
#endif
|
||||
editwinrows / 2 + 1);
|
||||
|
||||
edit_scroll(DOWNWARD, (ISSET(SMOOTH_SCROLL) || scroll_only) ?
|
||||
amount : editwinrows / 2 + 1);
|
||||
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
refresh_needed = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (openfile->current_y == editwinrows - 1)
|
||||
edit_scroll(DOWNWARD, editwinrows / 2 + 1);
|
||||
#endif
|
||||
|
||||
/* If we're not on the last line of the edit window, and the target
|
||||
* column is beyond the screen or the mark is on, redraw the prior
|
||||
* and current lines. */
|
||||
if (openfile->current_y < editwinrows - 1 && need_screen_update(0)) {
|
||||
update_line(openfile->current->prev, 0);
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
/* If the lines weren't already redrawn, see if they need to be. */
|
||||
if (openfile->current_y < editwinrows - 1) {
|
||||
/* Redraw the prior line if it was horizontally scrolled. */
|
||||
if (need_horizontal_scroll(was_column, 0))
|
||||
update_line(openfile->current->prev, 0);
|
||||
/* Redraw the current line if it needs to be horizontally scrolled. */
|
||||
if (need_horizontal_scroll(0, xplustabs()))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move down one line. */
|
||||
void do_down_void(void)
|
||||
{
|
||||
do_down(
|
||||
#ifndef NANO_TINY
|
||||
FALSE
|
||||
#endif
|
||||
);
|
||||
do_down(FALSE);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Scroll up one line without scrolling the cursor. */
|
||||
void do_scroll_up(void)
|
||||
{
|
||||
do_up(TRUE);
|
||||
}
|
||||
|
||||
/* Scroll down one line without scrolling the cursor. */
|
||||
void do_scroll_down(void)
|
||||
{
|
||||
@@ -533,7 +546,7 @@ void do_scroll_down(void)
|
||||
/* Move left one character. */
|
||||
void do_left(void)
|
||||
{
|
||||
size_t pww_save = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
if (openfile->current_x > 0)
|
||||
openfile->current_x = move_mbleft(openfile->current->data,
|
||||
@@ -545,14 +558,14 @@ void do_left(void)
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
if (need_screen_update(pww_save))
|
||||
if (need_horizontal_scroll(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
}
|
||||
|
||||
/* Move right one character. */
|
||||
void do_right(void)
|
||||
{
|
||||
size_t pww_save = openfile->placewewant;
|
||||
size_t was_column = xplustabs();
|
||||
|
||||
assert(openfile->current_x <= strlen(openfile->current->data));
|
||||
|
||||
@@ -560,12 +573,20 @@ void do_right(void)
|
||||
openfile->current_x = move_mbright(openfile->current->data,
|
||||
openfile->current_x);
|
||||
else if (openfile->current != openfile->filebot) {
|
||||
do_down_void();
|
||||
openfile->current_x = 0;
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP))
|
||||
openfile->current_y -= strlenpt(openfile->current->data) / editwincols;
|
||||
#endif
|
||||
}
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
if (need_screen_update(pww_save))
|
||||
if (need_horizontal_scroll(was_column, openfile->placewewant))
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
|
||||
if (openfile->current_x == 0)
|
||||
do_down_void();
|
||||
else
|
||||
ensure_line_is_visible();
|
||||
}
|
||||
|
||||
781
src/nano.c
781
src/nano.c
File diff suppressed because it is too large
Load Diff
117
src/nano.h
117
src/nano.h
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* nano.h *
|
||||
* nano.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
/* Macros for flags, indexing each bit in a small array. */
|
||||
#define FLAGS(flag) flags[((flag) / (sizeof(unsigned) * 8))]
|
||||
#define FLAGMASK(flag) (1 << ((flag) % (sizeof(unsigned) * 8)))
|
||||
#define FLAGMASK(flag) ((unsigned)1 << ((flag) % (sizeof(unsigned) * 8)))
|
||||
#define SET(flag) FLAGS(flag) |= FLAGMASK(flag)
|
||||
#define UNSET(flag) FLAGS(flag) &= ~FLAGMASK(flag)
|
||||
#define ISSET(flag) ((FLAGS(flag) & FLAGMASK(flag)) != 0)
|
||||
@@ -92,6 +92,10 @@
|
||||
#include <curses.h>
|
||||
#endif /* CURSES_H */
|
||||
|
||||
#if defined(NCURSES_VERSION_MAJOR) && (NCURSES_VERSION_MAJOR < 6)
|
||||
#define USING_OLD_NCURSES yes
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
/* Native language support. */
|
||||
#ifdef HAVE_LIBINTL_H
|
||||
@@ -173,7 +177,11 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
OVERWRITE, APPEND, PREPEND
|
||||
} append_type;
|
||||
} kind_of_writing_type;
|
||||
|
||||
typedef enum {
|
||||
SOFTMARK, HARDMARK
|
||||
} mark_type;
|
||||
|
||||
typedef enum {
|
||||
UPWARD, DOWNWARD
|
||||
@@ -183,10 +191,6 @@ typedef enum {
|
||||
CENTERING, FLOWING, STATIONARY
|
||||
} update_type;
|
||||
|
||||
typedef enum {
|
||||
CONTROL, META, FKEY, RAWINPUT
|
||||
} key_type;
|
||||
|
||||
typedef enum {
|
||||
ADD, DEL, BACK, CUT, CUT_EOF, REPLACE,
|
||||
#ifndef DISABLE_WRAPPING
|
||||
@@ -199,14 +203,6 @@ typedef enum {
|
||||
} undo_type;
|
||||
|
||||
/* Structure types. */
|
||||
typedef struct color_pair {
|
||||
int pairnum;
|
||||
/* The color pair number used for this foreground color and
|
||||
* background color. */
|
||||
bool bright;
|
||||
/* Is this color A_BOLD? */
|
||||
} color_pair;
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
typedef struct colortype {
|
||||
short fg;
|
||||
@@ -218,6 +214,8 @@ typedef struct colortype {
|
||||
int pairnum;
|
||||
/* The color pair number used for this foreground color and
|
||||
* background color. */
|
||||
int attributes;
|
||||
/* Pair number and brightness composed into ready-to-use attributes. */
|
||||
int rex_flags;
|
||||
/* The regex compilation flags (with or without REG_ICASE). */
|
||||
char *start_regex;
|
||||
@@ -399,6 +397,8 @@ typedef struct openfilestruct {
|
||||
/* The file's y-coordinate position. */
|
||||
bool modified;
|
||||
/* Whether the file has been modified. */
|
||||
struct stat *current_stat;
|
||||
/* The file's current stat information. */
|
||||
#ifndef NANO_TINY
|
||||
bool mark_set;
|
||||
/* Whether the mark is on in this file. */
|
||||
@@ -406,10 +406,10 @@ typedef struct openfilestruct {
|
||||
/* 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. */
|
||||
mark_type kind_of_mark;
|
||||
/* Whether this is a soft or a hard mark. */
|
||||
file_format fmt;
|
||||
/* The file's format. */
|
||||
struct stat *current_stat;
|
||||
/* The file's current stat information. */
|
||||
undo *undotop;
|
||||
/* The top of the undo list. */
|
||||
undo *current_undo;
|
||||
@@ -441,21 +441,23 @@ typedef struct rcoption {
|
||||
#endif
|
||||
|
||||
typedef struct sc {
|
||||
char *keystr;
|
||||
/* The shortcut key for a function, ASCII version. */
|
||||
key_type type;
|
||||
/* What kind of command key it is, for convenience later. */
|
||||
int seq;
|
||||
/* The actual sequence to check once the type is determined. */
|
||||
const char *keystr;
|
||||
/* The string that describes a keystroke, like "^C" or "M-R". */
|
||||
bool meta;
|
||||
/* Whether this is a Meta keystroke. */
|
||||
int keycode;
|
||||
/* The integer that, together with meta, identifies the keystroke. */
|
||||
int menus;
|
||||
/* Which menus this applies to. */
|
||||
void (*scfunc)(void);
|
||||
/* The function we're going to run. */
|
||||
#ifndef NANO_TINY
|
||||
int toggle;
|
||||
/* If a toggle, what we're toggling. */
|
||||
int ordinal;
|
||||
/* The how-manieth toggle this is, in order to be able to
|
||||
* keep them in sequence. */
|
||||
#endif
|
||||
struct sc *next;
|
||||
/* Next in the list. */
|
||||
} sc;
|
||||
@@ -482,10 +484,18 @@ typedef struct subnfunc {
|
||||
/* Next item in the list. */
|
||||
} subnfunc;
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
typedef struct completion_word {
|
||||
char *word;
|
||||
struct completion_word *next;
|
||||
} completion_word;
|
||||
#endif
|
||||
|
||||
/* The elements of the interface that can be colored differently. */
|
||||
enum
|
||||
{
|
||||
TITLE_BAR = 0,
|
||||
LINE_NUMBER,
|
||||
STATUS_BAR,
|
||||
KEY_COMBO,
|
||||
FUNCTION_TAG,
|
||||
@@ -533,7 +543,9 @@ enum
|
||||
LOCKING,
|
||||
NOREAD_MODE,
|
||||
MAKE_IT_UNIX,
|
||||
JUSTIFY_TRIM
|
||||
JUSTIFY_TRIM,
|
||||
SHOW_CURSOR,
|
||||
LINE_NUMBERS
|
||||
};
|
||||
|
||||
/* Flags for the menus in which a given function should be present. */
|
||||
@@ -556,16 +568,28 @@ enum
|
||||
#define MMOST (MMAIN|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MWRITEFILE|MINSERTFILE|\
|
||||
MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MSPELL|MLINTER)
|
||||
|
||||
/* Control key sequences. Changing these would be very, very bad. */
|
||||
#define NANO_CONTROL_SPACE 0
|
||||
#define NANO_CONTROL_I 9
|
||||
#define NANO_CONTROL_3 27
|
||||
#define NANO_CONTROL_7 31
|
||||
#define NANO_CONTROL_8 127
|
||||
/* Basic control codes. */
|
||||
#define TAB_CODE 0x09
|
||||
#define ESC_CODE 0x1B
|
||||
#define DEL_CODE 0x7F
|
||||
|
||||
/* Codes for "modified" Arrow keys, beyond KEY_MAX of ncurses. */
|
||||
#define CONTROL_LEFT 0x401
|
||||
#define CONTROL_RIGHT 0x402
|
||||
#define CONTROL_UP 0x403
|
||||
#define CONTROL_DOWN 0x404
|
||||
#define SHIFT_CONTROL_LEFT 0x405
|
||||
#define SHIFT_CONTROL_RIGHT 0x406
|
||||
#define SHIFT_CONTROL_UP 0x407
|
||||
#define SHIFT_CONTROL_DOWN 0x408
|
||||
#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
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* An imaginary key for when we get a SIGWINCH (window resize). */
|
||||
@@ -582,11 +606,6 @@ enum
|
||||
/* The maximum number of entries displayed in the main shortcut list. */
|
||||
#define MAIN_VISIBLE (((COLS + 40) / 20) * 2)
|
||||
|
||||
/* The minimum editor window columns and rows required for nano to work
|
||||
* correctly. Don't make these smaller than 4 and 1. */
|
||||
#define MIN_EDITOR_COLS 4
|
||||
#define MIN_EDITOR_ROWS 1
|
||||
|
||||
/* The default number of characters from the end of the line where
|
||||
* wrapping occurs. */
|
||||
#define CHARS_FROM_EOL 8
|
||||
@@ -604,10 +623,4 @@ enum
|
||||
/* The largest size_t number that doesn't have the high bit set. */
|
||||
#define HIGHEST_POSITIVE ((~(size_t)0) >> 1)
|
||||
|
||||
#ifdef REVISION
|
||||
#define BRANDING PACKAGE_VERSION"-git "REVISION
|
||||
#else
|
||||
#define BRANDING PACKAGE_STRING
|
||||
#endif
|
||||
|
||||
#endif /* !NANO_H */
|
||||
|
||||
519
src/prompt.c
519
src/prompt.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* prompt.c *
|
||||
* prompt.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -28,19 +28,14 @@
|
||||
|
||||
static char *prompt = NULL;
|
||||
/* The prompt string used for statusbar questions. */
|
||||
static size_t statusbar_x = (size_t)-1;
|
||||
static size_t statusbar_x = HIGHEST_POSITIVE;
|
||||
/* The cursor position in answer. */
|
||||
static size_t statusbar_pww = (size_t)-1;
|
||||
/* The place we want in answer. */
|
||||
|
||||
/* Read in a character, interpret it as a shortcut or toggle if
|
||||
* necessary, and return it.
|
||||
* Set ran_func to TRUE if we ran a function associated with a
|
||||
* shortcut key, and set finished to TRUE if we're done after running
|
||||
* or trying to run a function associated with a shortcut key.
|
||||
* refresh_func is the function we will call to refresh the edit window. */
|
||||
int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
void (*refresh_func)(void))
|
||||
/* Read in a keystroke, interpret it if it is a shortcut or toggle, and
|
||||
* return it. Set ran_func to TRUE if we ran a function associated with
|
||||
* a shortcut key, and set finished to TRUE if we're done after running
|
||||
* or trying to run a function associated with a shortcut key. */
|
||||
int do_statusbar_input(bool *ran_func, bool *finished)
|
||||
{
|
||||
int input;
|
||||
/* The character we read in. */
|
||||
@@ -66,14 +61,11 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
#ifndef DISABLE_MOUSE
|
||||
/* If we got a mouse click and it was on a shortcut, read in the
|
||||
* shortcut character. */
|
||||
if (func_key && input == KEY_MOUSE) {
|
||||
if (input == KEY_MOUSE) {
|
||||
if (do_statusbar_mouse() == 1)
|
||||
input = get_kbinput(bottomwin);
|
||||
else {
|
||||
meta_key = FALSE;
|
||||
func_key = FALSE;
|
||||
input = ERR;
|
||||
}
|
||||
else
|
||||
return ERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -87,120 +79,86 @@ int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
/* If we got a non-high-bit control key, a meta key sequence, or a
|
||||
* function key, and it's not a shortcut or toggle, throw it out. */
|
||||
if (!have_shortcut) {
|
||||
if (is_ascii_cntrl_char(input) || meta_key || func_key) {
|
||||
if (is_ascii_cntrl_char(input) || meta_key || !is_byte(input)) {
|
||||
beep();
|
||||
meta_key = FALSE;
|
||||
func_key = FALSE;
|
||||
input = ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got a character, and it isn't a shortcut or toggle,
|
||||
* it's a normal text character. Display the warning if we're
|
||||
* in view mode, or add the character to the input buffer if
|
||||
* we're not. */
|
||||
/* If the keystroke isn't a shortcut nor a toggle, it's a normal text
|
||||
* character: add the it to the input buffer, when allowed. */
|
||||
if (input != ERR && !have_shortcut) {
|
||||
/* If we're using restricted mode, the filename isn't blank,
|
||||
* and we're at the "Write File" prompt, disable text input. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE) {
|
||||
/* Only accept input when not in restricted mode, or when not at
|
||||
* the "Write File" prompt, or when there is no filename yet. */
|
||||
if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
|
||||
openfile->filename[0] == '\0') {
|
||||
kbinput_len++;
|
||||
kbinput = (int *)nrealloc(kbinput, kbinput_len * sizeof(int));
|
||||
kbinput[kbinput_len - 1] = input;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got a shortcut, or if there aren't any other characters
|
||||
* waiting after the one we read in, we need to display all the
|
||||
* characters in the input buffer if it isn't empty. */
|
||||
if (have_shortcut || get_key_buffer_len() == 0) {
|
||||
if (kbinput != NULL) {
|
||||
/* Display all the characters in the input buffer at
|
||||
* once, filtering out control characters. */
|
||||
do_statusbar_output(kbinput, kbinput_len, TRUE, NULL);
|
||||
/* If we got a shortcut, or if there aren't any other keystrokes waiting
|
||||
* after the one we read in, we need to insert all the characters in the
|
||||
* input buffer (if not empty) into the answer. */
|
||||
if ((have_shortcut || get_key_buffer_len() == 0) && kbinput != NULL) {
|
||||
/* Inject all characters in the input buffer at once, filtering out
|
||||
* control characters. */
|
||||
do_statusbar_output(kbinput, kbinput_len, TRUE);
|
||||
|
||||
/* Empty the input buffer. */
|
||||
kbinput_len = 0;
|
||||
free(kbinput);
|
||||
kbinput = NULL;
|
||||
}
|
||||
/* Empty the input buffer. */
|
||||
kbinput_len = 0;
|
||||
free(kbinput);
|
||||
kbinput = NULL;
|
||||
}
|
||||
|
||||
if (have_shortcut) {
|
||||
if (s->scfunc == do_tab || s->scfunc == do_enter)
|
||||
;
|
||||
else if (s->scfunc == total_refresh) {
|
||||
total_redraw();
|
||||
refresh_func();
|
||||
} else if (s->scfunc == do_cut_text_void) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable Cut. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE)
|
||||
do_statusbar_cut_text();
|
||||
} else if (s->scfunc == do_left)
|
||||
do_statusbar_left();
|
||||
else if (s->scfunc == do_right)
|
||||
do_statusbar_right();
|
||||
if (have_shortcut) {
|
||||
if (s->scfunc == do_tab || s->scfunc == do_enter)
|
||||
;
|
||||
else if (s->scfunc == do_left)
|
||||
do_statusbar_left();
|
||||
else if (s->scfunc == do_right)
|
||||
do_statusbar_right();
|
||||
#ifndef NANO_TINY
|
||||
else if (s->scfunc == do_prev_word_void)
|
||||
do_statusbar_prev_word();
|
||||
else if (s->scfunc == do_next_word_void)
|
||||
do_statusbar_next_word();
|
||||
else if (s->scfunc == do_prev_word_void)
|
||||
do_statusbar_prev_word();
|
||||
else if (s->scfunc == do_next_word_void)
|
||||
do_statusbar_next_word();
|
||||
#endif
|
||||
else if (s->scfunc == do_home)
|
||||
do_statusbar_home();
|
||||
else if (s->scfunc == do_end)
|
||||
do_statusbar_end();
|
||||
else if (s->scfunc == do_verbatim_input) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable verbatim input. */
|
||||
if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
|
||||
openfile->filename[0] == '\0') {
|
||||
bool got_enter = FALSE;
|
||||
/* Whether we got the Enter key. */
|
||||
|
||||
do_statusbar_verbatim_input(&got_enter);
|
||||
|
||||
/* If we got the Enter key, remove it from the input
|
||||
* buffer, set input to the key value for Enter, and
|
||||
* set finished to TRUE to indicate that we're done. */
|
||||
if (got_enter) {
|
||||
get_input(NULL, 1);
|
||||
input = sc_seq_or(do_enter, 0);
|
||||
*finished = TRUE;
|
||||
}
|
||||
}
|
||||
} else if (s->scfunc == do_delete) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable Delete. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE)
|
||||
do_statusbar_delete();
|
||||
} else if (s->scfunc == do_backspace) {
|
||||
/* If we're using restricted mode, the filename
|
||||
* isn't blank, and we're at the "Write File"
|
||||
* prompt, disable Backspace. */
|
||||
if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
|
||||
currmenu != MWRITEFILE)
|
||||
do_statusbar_backspace();
|
||||
} 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 indicate
|
||||
* that we're done after running or trying to run their
|
||||
* associated functions. */
|
||||
f = sctofunc(s);
|
||||
if (s->scfunc != NULL) {
|
||||
*ran_func = TRUE;
|
||||
if (f && (!ISSET(VIEW_MODE) || f->viewok) &&
|
||||
else if (s->scfunc == do_home)
|
||||
do_statusbar_home();
|
||||
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. */
|
||||
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE &&
|
||||
openfile->filename[0] != '\0' &&
|
||||
(s->scfunc == do_verbatim_input ||
|
||||
s->scfunc == do_cut_text_void ||
|
||||
s->scfunc == do_delete ||
|
||||
s->scfunc == do_backspace))
|
||||
;
|
||||
else if (s->scfunc == do_verbatim_input) {
|
||||
do_statusbar_verbatim_input();
|
||||
} else if (s->scfunc == do_cut_text_void)
|
||||
do_statusbar_cut_text();
|
||||
else if (s->scfunc == do_delete)
|
||||
do_statusbar_delete();
|
||||
else if (s->scfunc == do_backspace)
|
||||
do_statusbar_backspace();
|
||||
else {
|
||||
/* 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
|
||||
* running or trying to run their associated functions. */
|
||||
f = sctofunc(s);
|
||||
if (s->scfunc != NULL) {
|
||||
*ran_func = TRUE;
|
||||
if (f && (!ISSET(VIEW_MODE) || f->viewok) &&
|
||||
f->scfunc != do_gotolinecolumn_void)
|
||||
f->scfunc();
|
||||
}
|
||||
*finished = TRUE;
|
||||
f->scfunc();
|
||||
}
|
||||
*finished = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,8 +176,6 @@ int do_statusbar_mouse(void)
|
||||
if (retval == 0 && wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE)) {
|
||||
size_t start_col;
|
||||
|
||||
assert(prompt != NULL);
|
||||
|
||||
start_col = strlenpt(prompt) + 2;
|
||||
|
||||
/* Move to where the click occurred. */
|
||||
@@ -227,7 +183,7 @@ int do_statusbar_mouse(void)
|
||||
statusbar_x = actual_x(answer,
|
||||
get_statusbar_page_start(start_col, start_col +
|
||||
statusbar_xplustabs()) + mouse_x - start_col);
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,18 +191,15 @@ int do_statusbar_mouse(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The user typed input_len multibyte characters. Add them to the
|
||||
* statusbar prompt, setting got_enter to TRUE if we get a newline,
|
||||
* and filtering out ASCII control characters if filtering is TRUE. */
|
||||
/* The user typed input_len multibyte characters. Add them to the answer,
|
||||
* filtering out ASCII control characters if filtering is TRUE. */
|
||||
void do_statusbar_output(int *the_input, size_t input_len,
|
||||
bool filtering, bool *got_enter)
|
||||
bool filtering)
|
||||
{
|
||||
char *output = charalloc(input_len + 1);
|
||||
char *char_buf = charalloc(mb_cur_max());
|
||||
int i, char_len;
|
||||
|
||||
assert(answer != NULL);
|
||||
|
||||
/* Copy the typed stuff so it can be treated. */
|
||||
for (i = 0; i < input_len; i++)
|
||||
output[i] = (char)the_input[i];
|
||||
@@ -255,18 +208,9 @@ void do_statusbar_output(int *the_input, size_t input_len,
|
||||
i = 0;
|
||||
|
||||
while (i < input_len) {
|
||||
/* When not filtering, convert nulls and stop at a newline. */
|
||||
if (!filtering) {
|
||||
if (output[i] == '\0')
|
||||
output[i] = '\n';
|
||||
else if (output[i] == '\n') {
|
||||
/* Put back the rest of the characters for reparsing,
|
||||
* indicate that we got the Enter key and get out. */
|
||||
unparse_kbinput(output + i, input_len - i);
|
||||
*got_enter = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Encode any NUL byte as 0x0A. */
|
||||
if (output[i] == '\0')
|
||||
output[i] = '\n';
|
||||
|
||||
/* Interpret the next multibyte character. */
|
||||
char_len = parse_mbchar(output + i, char_buf, NULL);
|
||||
@@ -277,8 +221,6 @@ void do_statusbar_output(int *the_input, size_t input_len,
|
||||
if (filtering && is_ascii_cntrl_char(*(output + i - char_len)))
|
||||
continue;
|
||||
|
||||
assert(statusbar_x <= strlen(answer));
|
||||
|
||||
/* Insert the typed character into the existing answer string. */
|
||||
answer = charealloc(answer, strlen(answer) + char_len + 1);
|
||||
charmove(answer + statusbar_x + char_len, answer + statusbar_x,
|
||||
@@ -291,23 +233,21 @@ void do_statusbar_output(int *the_input, size_t input_len,
|
||||
free(char_buf);
|
||||
free(output);
|
||||
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Move to the beginning of the prompt text. */
|
||||
/* Move to the beginning of the answer. */
|
||||
void do_statusbar_home(void)
|
||||
{
|
||||
statusbar_x = 0;
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Move to the end of the prompt text. */
|
||||
/* Move to the end of the answer. */
|
||||
void do_statusbar_end(void)
|
||||
{
|
||||
statusbar_x = strlen(answer);
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Move left one character. */
|
||||
@@ -315,16 +255,16 @@ void do_statusbar_left(void)
|
||||
{
|
||||
if (statusbar_x > 0) {
|
||||
statusbar_x = move_mbleft(answer, statusbar_x);
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
}
|
||||
|
||||
/* Move right one character. */
|
||||
void do_statusbar_right(void)
|
||||
{
|
||||
if (statusbar_x < strlen(answer)) {
|
||||
if (answer[statusbar_x] != '\0') {
|
||||
statusbar_x = move_mbright(answer, statusbar_x);
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,48 +280,33 @@ void do_statusbar_backspace(void)
|
||||
/* Delete one character. */
|
||||
void do_statusbar_delete(void)
|
||||
{
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
|
||||
if (answer[statusbar_x] != '\0') {
|
||||
int char_len = parse_mbchar(answer + statusbar_x, NULL, NULL);
|
||||
|
||||
assert(statusbar_x < strlen(answer));
|
||||
|
||||
charmove(answer + statusbar_x, answer + statusbar_x + char_len,
|
||||
strlen(answer) - statusbar_x - char_len + 1);
|
||||
align(&answer);
|
||||
|
||||
update_the_statusbar();
|
||||
}
|
||||
}
|
||||
|
||||
/* Move text from the prompt into oblivion. */
|
||||
/* Zap some or all text from the answer. */
|
||||
void do_statusbar_cut_text(void)
|
||||
{
|
||||
assert(answer != NULL);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(CUT_TO_END))
|
||||
null_at(&answer, statusbar_x);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
null_at(&answer, 0);
|
||||
if (!ISSET(CUT_TO_END))
|
||||
statusbar_x = 0;
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
}
|
||||
|
||||
null_at(&answer, statusbar_x);
|
||||
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Move to the next word in the prompt text. */
|
||||
/* Move to the next word in the answer. */
|
||||
void do_statusbar_next_word(void)
|
||||
{
|
||||
bool seen_space = !is_word_mbchar(answer + statusbar_x, FALSE);
|
||||
|
||||
assert(answer != NULL);
|
||||
|
||||
/* Move forward until we reach the start of a word. */
|
||||
while (answer[statusbar_x] != '\0') {
|
||||
statusbar_x = move_mbright(answer, statusbar_x);
|
||||
@@ -394,16 +319,14 @@ void do_statusbar_next_word(void)
|
||||
break;
|
||||
}
|
||||
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Move to the previous word in the prompt text. */
|
||||
/* Move to the previous word in the answer. */
|
||||
void do_statusbar_prev_word(void)
|
||||
{
|
||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||
|
||||
assert(answer != NULL);
|
||||
|
||||
/* Move backward until we pass over the start of a word. */
|
||||
while (statusbar_x != 0) {
|
||||
statusbar_x = move_mbleft(answer, statusbar_x);
|
||||
@@ -421,117 +344,98 @@ void do_statusbar_prev_word(void)
|
||||
/* Move one character forward again to sit on the start of the word. */
|
||||
statusbar_x = move_mbright(answer, statusbar_x);
|
||||
|
||||
update_bar_if_needed();
|
||||
update_the_statusbar();
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Get verbatim input. Set got_enter to TRUE if we got the Enter key as
|
||||
* part of the verbatim input. */
|
||||
void do_statusbar_verbatim_input(bool *got_enter)
|
||||
/* Get verbatim input and inject it into the answer, without filtering. */
|
||||
void do_statusbar_verbatim_input(void)
|
||||
{
|
||||
int *kbinput;
|
||||
size_t kbinput_len;
|
||||
|
||||
/* Read in all the verbatim characters. */
|
||||
kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
|
||||
|
||||
/* Display all the verbatim characters at once, not filtering out
|
||||
* control characters. */
|
||||
do_statusbar_output(kbinput, kbinput_len, FALSE, got_enter);
|
||||
do_statusbar_output(kbinput, kbinput_len, FALSE);
|
||||
}
|
||||
|
||||
/* Return the placewewant associated with statusbar_x, i.e. the
|
||||
* zero-based column position of the cursor. The value will be no
|
||||
* smaller than statusbar_x. */
|
||||
/* Return the zero-based column position of the cursor in the answer. */
|
||||
size_t statusbar_xplustabs(void)
|
||||
{
|
||||
return strnlenpt(answer, statusbar_x);
|
||||
}
|
||||
|
||||
/* nano scrolls horizontally within a line in chunks. This function
|
||||
* returns the column number of the first character displayed in the
|
||||
* statusbar prompt when the cursor is at the given column with the
|
||||
* prompt ending at start_col. Note that (0 <= column -
|
||||
* get_statusbar_page_start(column) < COLS). */
|
||||
size_t get_statusbar_page_start(size_t start_col, size_t column)
|
||||
/* 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
|
||||
* (0 <= column - get_statusbar_page_start(column) < COLS). */
|
||||
size_t get_statusbar_page_start(size_t base, size_t column)
|
||||
{
|
||||
if (column == start_col || column < COLS - 1 || COLS == start_col + 1)
|
||||
if (column == base || column < COLS - 1)
|
||||
return 0;
|
||||
else if (COLS > base + 2)
|
||||
return column - base - 1 - (column - base - 1) % (COLS - base - 2);
|
||||
else
|
||||
return column - start_col - (column - start_col) % (COLS -
|
||||
start_col - 1);
|
||||
return column - 2;
|
||||
}
|
||||
|
||||
/* Reinitialize the cursor position in the status bar prompt. */
|
||||
/* Reinitialize the cursor position in the answer. */
|
||||
void reinit_statusbar_x(void)
|
||||
{
|
||||
statusbar_x = (size_t)-1;
|
||||
statusbar_pww = (size_t)-1;
|
||||
statusbar_x = HIGHEST_POSITIVE;
|
||||
}
|
||||
|
||||
/* Put the cursor in the statusbar prompt at statusbar_x. */
|
||||
/* Put the cursor in the answer at statusbar_x. */
|
||||
void reset_statusbar_cursor(void)
|
||||
{
|
||||
size_t start_col = strlenpt(prompt) + 2;
|
||||
size_t xpt = statusbar_xplustabs();
|
||||
|
||||
/* Work around a cursor-misplacement bug in VTEs. */
|
||||
wmove(bottomwin, 0, 0);
|
||||
wnoutrefresh(bottomwin);
|
||||
doupdate();
|
||||
|
||||
wmove(bottomwin, 0, start_col + xpt -
|
||||
get_statusbar_page_start(start_col, start_col + xpt));
|
||||
get_statusbar_page_start(start_col, start_col + xpt));
|
||||
|
||||
wnoutrefresh(bottomwin);
|
||||
}
|
||||
|
||||
/* Repaint the statusbar. */
|
||||
void update_the_statusbar(void)
|
||||
{
|
||||
size_t start_col, index, page_start;
|
||||
size_t base, the_page, end_page;
|
||||
char *expanded;
|
||||
|
||||
assert(prompt != NULL && statusbar_x <= strlen(answer));
|
||||
base = strlenpt(prompt) + 2;
|
||||
the_page = get_statusbar_page_start(base, base + strnlenpt(answer, statusbar_x));
|
||||
end_page = get_statusbar_page_start(base, base + strlenpt(answer) - 1);
|
||||
|
||||
start_col = strlenpt(prompt) + 2;
|
||||
index = strnlenpt(answer, statusbar_x);
|
||||
page_start = get_statusbar_page_start(start_col, start_col + index);
|
||||
|
||||
if (interface_color_pair[TITLE_BAR].bright)
|
||||
wattron(bottomwin, A_BOLD);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
blank_statusbar();
|
||||
|
||||
mvwaddnstr(bottomwin, 0, 0, prompt, actual_x(prompt, COLS - 2));
|
||||
mvwaddstr(bottomwin, 0, 0, prompt);
|
||||
waddch(bottomwin, ':');
|
||||
waddch(bottomwin, (page_start == 0) ? ' ' : '$');
|
||||
waddch(bottomwin, (the_page == 0) ? ' ' : '<');
|
||||
|
||||
expanded = display_string(answer, page_start, COLS - start_col - 1, FALSE);
|
||||
expanded = display_string(answer, the_page, COLS - base - 1, FALSE);
|
||||
waddstr(bottomwin, expanded);
|
||||
free(expanded);
|
||||
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
waddch(bottomwin, (the_page >= end_page) ? ' ' : '>');
|
||||
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
reset_statusbar_cursor();
|
||||
wnoutrefresh(bottomwin);
|
||||
}
|
||||
|
||||
/* Update the statusbar line /if/ the placewewant changes page. */
|
||||
void update_bar_if_needed(void)
|
||||
{
|
||||
size_t start_col = strlenpt(prompt) + 2;
|
||||
size_t was_pww = statusbar_pww;
|
||||
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
|
||||
if (get_statusbar_page_start(start_col, start_col + statusbar_pww) !=
|
||||
get_statusbar_page_start(start_col, start_col + was_pww))
|
||||
update_the_statusbar();
|
||||
}
|
||||
|
||||
/* Get a string of input at the statusbar prompt. */
|
||||
functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
bool allow_files, bool *listed,
|
||||
#endif
|
||||
const char *curranswer,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
filestruct **history_list,
|
||||
#endif
|
||||
@@ -559,15 +463,11 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
#endif
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
|
||||
answer = mallocstrcpy(answer, curranswer);
|
||||
|
||||
if (statusbar_x > strlen(answer)) {
|
||||
if (statusbar_x > strlen(answer))
|
||||
statusbar_x = strlen(answer);
|
||||
statusbar_pww = statusbar_xplustabs();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answer, (unsigned long) statusbar_x);
|
||||
fprintf(stderr, "acquiring: answer = \"%s\", statusbar_x = %lu\n", answer, (unsigned long) statusbar_x);
|
||||
#endif
|
||||
|
||||
update_the_statusbar();
|
||||
@@ -576,25 +476,24 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
wnoutrefresh(edit);
|
||||
wnoutrefresh(bottomwin);
|
||||
|
||||
/* If we're using restricted mode, we aren't allowed to change the
|
||||
* name of the current file once it has one, because that would
|
||||
* allow writing to files not specified on the command line. In
|
||||
* this case, disable all keys that would change the text if the
|
||||
* filename isn't blank and we're at the "Write File" prompt. */
|
||||
while (TRUE) {
|
||||
/* Ensure the cursor is on when waiting for input. */
|
||||
/* Ensure the cursor is shown when waiting for input. */
|
||||
curs_set(1);
|
||||
|
||||
kbinput = do_statusbar_input(&ran_func, &finished, refresh_func);
|
||||
assert(statusbar_x <= strlen(answer));
|
||||
kbinput = do_statusbar_input(&ran_func, &finished);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the window size changed, go reformat the prompt string. */
|
||||
if (kbinput == KEY_WINCH) {
|
||||
refresh_func();
|
||||
update_the_statusbar();
|
||||
continue;
|
||||
}
|
||||
*actual = KEY_WINCH;
|
||||
#ifndef DISABLE_HISTORIES
|
||||
free(magichistory);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
func = func_from_key(&kbinput);
|
||||
|
||||
if (func == do_cancel || func == do_enter)
|
||||
@@ -607,7 +506,7 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
if (func == do_tab) {
|
||||
#ifndef DISABLE_HISTORIES
|
||||
if (history_list != NULL) {
|
||||
if (last_kbinput != sc_seq_or(do_tab, NANO_CONTROL_I))
|
||||
if (last_kbinput != the_code_for(do_tab, TAB_CODE))
|
||||
complete_len = strlen(answer);
|
||||
|
||||
if (complete_len > 0) {
|
||||
@@ -620,8 +519,6 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
if (allow_tabs)
|
||||
answer = input_tab(answer, allow_files, &statusbar_x,
|
||||
&tabbed, refresh_func, listed);
|
||||
|
||||
update_the_statusbar();
|
||||
} else
|
||||
#endif /* !DISABLE_TABCOMP */
|
||||
#ifndef DISABLE_HISTORIES
|
||||
@@ -639,8 +536,6 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
statusbar_x = strlen(answer);
|
||||
}
|
||||
|
||||
update_the_statusbar();
|
||||
|
||||
/* This key has a shortcut-list entry when it's used to
|
||||
* move to an older search, which means that finished has
|
||||
* been set to TRUE. Set it back to FALSE here, so that
|
||||
@@ -665,8 +560,6 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
statusbar_x = strlen(answer);
|
||||
}
|
||||
|
||||
update_the_statusbar();
|
||||
|
||||
/* This key has a shortcut-list entry when it's used to
|
||||
* move to a newer search, which means that finished has
|
||||
* been set to TRUE. Set it back to FALSE here, so that
|
||||
@@ -676,8 +569,6 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
} else
|
||||
#endif /* !DISABLE_HISTORIES */
|
||||
if (func == do_help_void) {
|
||||
update_the_statusbar();
|
||||
|
||||
/* This key has a shortcut-list entry when it's used to go to
|
||||
* the help browser or display a message indicating that help
|
||||
* is disabled, which means that finished has been set to TRUE.
|
||||
@@ -691,11 +582,11 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
|
||||
if (finished)
|
||||
break;
|
||||
|
||||
update_the_statusbar();
|
||||
|
||||
#if !defined(DISABLE_HISTORIES) && !defined(DISABLE_TABCOMP)
|
||||
last_kbinput = kbinput;
|
||||
#endif
|
||||
reset_statusbar_cursor();
|
||||
wnoutrefresh(bottomwin);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
@@ -734,42 +625,48 @@ int do_prompt(bool allow_tabs,
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
functionptrtype func;
|
||||
functionptrtype func = NULL;
|
||||
#ifndef DISABLE_TABCOMP
|
||||
bool listed = FALSE;
|
||||
#endif
|
||||
/* Save a possible current statusbar x position. */
|
||||
size_t was_statusbar_x = statusbar_x;
|
||||
size_t was_pww = statusbar_pww;
|
||||
|
||||
prompt = charalloc(((COLS - 4) * mb_cur_max()) + 1);
|
||||
|
||||
bottombars(menu);
|
||||
|
||||
va_start(ap, msg);
|
||||
vsnprintf(prompt, (COLS - 4) * mb_cur_max(), msg, ap);
|
||||
va_end(ap);
|
||||
null_at(&prompt, actual_x(prompt, COLS - 4));
|
||||
answer = mallocstrcpy(answer, curranswer);
|
||||
|
||||
func = get_prompt_string(&retval, allow_tabs,
|
||||
#ifndef NANO_TINY
|
||||
redo_theprompt:
|
||||
#endif
|
||||
prompt = charalloc((COLS * mb_cur_max()) + 1);
|
||||
va_start(ap, msg);
|
||||
vsnprintf(prompt, COLS * mb_cur_max(), msg, ap);
|
||||
va_end(ap);
|
||||
/* Reserve five columns for colon plus angles plus answer, ":<aa>". */
|
||||
null_at(&prompt, actual_x(prompt, (COLS < 5) ? 0 : COLS - 5));
|
||||
|
||||
func = acquire_an_answer(&retval, allow_tabs,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
allow_files, &listed,
|
||||
#endif
|
||||
curranswer,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
history_list,
|
||||
history_list,
|
||||
#endif
|
||||
refresh_func);
|
||||
refresh_func);
|
||||
|
||||
free(prompt);
|
||||
prompt = NULL;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (retval == KEY_WINCH)
|
||||
goto redo_theprompt;
|
||||
#endif
|
||||
|
||||
/* If we're done with this prompt, restore the x position to what
|
||||
* it was at a possible previous prompt. */
|
||||
if (func == do_cancel || func == do_enter) {
|
||||
if (func == do_cancel || func == do_enter)
|
||||
statusbar_x = was_statusbar_x;
|
||||
statusbar_pww = was_pww;
|
||||
}
|
||||
|
||||
/* If we left the prompt via Cancel or Enter, set the return value
|
||||
* properly. */
|
||||
@@ -801,30 +698,22 @@ int do_prompt(bool allow_tabs,
|
||||
int do_yesno_prompt(bool all, const char *msg)
|
||||
{
|
||||
int response = -2, width = 16;
|
||||
const char *yesstr; /* String of Yes characters accepted. */
|
||||
const char *nostr; /* Same for No. */
|
||||
const char *allstr; /* And All, surprise! */
|
||||
int oldmenu = currmenu;
|
||||
char *message = display_string(msg, 0, COLS, FALSE);
|
||||
|
||||
assert(msg != NULL);
|
||||
|
||||
/* yesstr, nostr, and allstr are strings of any length. Each string
|
||||
* consists of all single-byte characters accepted as valid
|
||||
* characters for that value. The first value will be the one
|
||||
* displayed in the shortcuts. */
|
||||
/* TRANSLATORS: For the next three strings, if possible, specify
|
||||
* the single-byte shortcuts for both your language and English.
|
||||
* For example, in French: "OoYy" for "Oui". */
|
||||
yesstr = _("Yy");
|
||||
nostr = _("Nn");
|
||||
allstr = _("Aa");
|
||||
* For example, in French: "OoYy", for both "Oui" and "Yes". */
|
||||
const char *yesstr = _("Yy");
|
||||
const char *nostr = _("Nn");
|
||||
const char *allstr = _("Aa");
|
||||
|
||||
do {
|
||||
/* The above three variables consist of all the single-byte characters
|
||||
* that are accepted for the corresponding answer. Of each variable,
|
||||
* the first character is displayed in the help lines. */
|
||||
|
||||
while (response == -2) {
|
||||
int kbinput;
|
||||
functionptrtype func;
|
||||
#ifndef DISABLE_MOUSE
|
||||
int mouse_x, mouse_y;
|
||||
#endif
|
||||
|
||||
if (!ISSET(NO_HELP)) {
|
||||
char shortstr[3];
|
||||
@@ -855,34 +744,28 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
onekey("^C", _("Cancel"), width);
|
||||
}
|
||||
|
||||
if (interface_color_pair[TITLE_BAR].bright)
|
||||
wattron(bottomwin, A_BOLD);
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
|
||||
/* Color the statusbar over its full width and display the question. */
|
||||
wattron(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
blank_statusbar();
|
||||
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
|
||||
mvwaddnstr(bottomwin, 0, 0, message, actual_x(message, COLS - 1));
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR]);
|
||||
|
||||
wattroff(bottomwin, A_BOLD);
|
||||
wattroff(bottomwin, interface_color_pair[TITLE_BAR].pairnum);
|
||||
|
||||
/* Refresh edit window and statusbar before getting input. */
|
||||
wnoutrefresh(edit);
|
||||
wnoutrefresh(bottomwin);
|
||||
|
||||
/* When not replacing, show the cursor. */
|
||||
if (!all)
|
||||
curs_set(1);
|
||||
|
||||
currmenu = MYESNO;
|
||||
kbinput = get_kbinput(bottomwin);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
func = func_from_key(&kbinput);
|
||||
|
||||
if (func == do_cancel)
|
||||
response = -1;
|
||||
#ifndef DISABLE_MOUSE
|
||||
else if (kbinput == KEY_MOUSE) {
|
||||
int mouse_x, mouse_y;
|
||||
/* We can click on the Yes/No/All shortcuts to select an answer. */
|
||||
if (get_mouseinput(&mouse_x, &mouse_y, FALSE) == 0 &&
|
||||
wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE) &&
|
||||
@@ -903,10 +786,7 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
}
|
||||
}
|
||||
#endif /* !DISABLE_MOUSE */
|
||||
else if (func == total_refresh) {
|
||||
total_redraw();
|
||||
continue;
|
||||
} else {
|
||||
else {
|
||||
/* Look for the kbinput in the Yes, No (and All) strings. */
|
||||
if (strchr(yesstr, kbinput) != NULL)
|
||||
response = 1;
|
||||
@@ -915,8 +795,9 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
else if (all && strchr(allstr, kbinput) != NULL)
|
||||
response = 2;
|
||||
}
|
||||
} while (response == -2);
|
||||
}
|
||||
|
||||
free(message);
|
||||
|
||||
currmenu = oldmenu;
|
||||
return response;
|
||||
}
|
||||
|
||||
249
src/proto.h
249
src/proto.h
@@ -1,22 +1,21 @@
|
||||
/**************************************************************************
|
||||
* proto.h *
|
||||
* proto.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -27,18 +26,40 @@
|
||||
|
||||
/* All external variables. See global.c for their descriptions. */
|
||||
#ifndef NANO_TINY
|
||||
extern volatile sig_atomic_t sigwinch_counter;
|
||||
extern volatile sig_atomic_t the_window_resized;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
extern bool console;
|
||||
#endif
|
||||
|
||||
extern bool meta_key;
|
||||
extern bool func_key;
|
||||
extern bool shift_held;
|
||||
|
||||
extern bool focusing;
|
||||
|
||||
extern bool as_an_at;
|
||||
|
||||
extern int margin;
|
||||
extern int editwincols;
|
||||
|
||||
extern message_type lastmessage;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
extern filestruct *pletion_line;
|
||||
|
||||
extern int controlleft;
|
||||
extern int controlright;
|
||||
extern int controlup;
|
||||
extern int controldown;
|
||||
#ifndef NANO_TINY
|
||||
extern int shiftcontrolleft;
|
||||
extern int shiftcontrolright;
|
||||
extern int shiftcontrolup;
|
||||
extern int shiftcontroldown;
|
||||
extern int shiftaltleft;
|
||||
extern int shiftaltright;
|
||||
extern int shiftaltup;
|
||||
extern int shiftaltdown;
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WRAPJUSTIFY
|
||||
@@ -59,9 +80,6 @@ extern int maxrows;
|
||||
|
||||
extern filestruct *cutbuffer;
|
||||
extern filestruct *cutbottom;
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
extern filestruct *jusbuffer;
|
||||
#endif
|
||||
extern partition *filepart;
|
||||
extern openfilestruct *openfile;
|
||||
|
||||
@@ -91,7 +109,10 @@ extern size_t quotelen;
|
||||
#endif
|
||||
#endif /* !DISABLE_JUSTIFY */
|
||||
|
||||
extern char *word_chars;
|
||||
|
||||
extern bool nodelay_mode;
|
||||
|
||||
extern char *answer;
|
||||
|
||||
extern ssize_t tabsize;
|
||||
@@ -142,7 +163,7 @@ extern int hilite_attribute;
|
||||
#ifndef DISABLE_COLOR
|
||||
extern char* specified_color_combo[NUMBER_OF_ELEMENTS];
|
||||
#endif
|
||||
extern color_pair interface_color_pair[NUMBER_OF_ELEMENTS];
|
||||
extern int interface_color_pair[NUMBER_OF_ELEMENTS];
|
||||
|
||||
extern char *homedir;
|
||||
|
||||
@@ -179,22 +200,17 @@ bool nisblank(int c);
|
||||
bool niswblank(wchar_t wc);
|
||||
#endif
|
||||
bool is_byte(int c);
|
||||
bool is_alpha_mbchar(const char *c);
|
||||
bool is_alnum_mbchar(const char *c);
|
||||
bool is_blank_mbchar(const char *c);
|
||||
bool is_ascii_cntrl_char(int c);
|
||||
bool is_cntrl_char(int c);
|
||||
#ifdef ENABLE_UTF8
|
||||
bool is_cntrl_wchar(wchar_t wc);
|
||||
#endif
|
||||
bool is_cntrl_mbchar(const char *c);
|
||||
bool is_punct_mbchar(const char *c);
|
||||
bool is_word_mbchar(const char *c, bool allow_punct);
|
||||
char control_rep(char c);
|
||||
#ifdef ENABLE_UTF8
|
||||
wchar_t control_wrep(wchar_t wc);
|
||||
#endif
|
||||
char *control_mbrep(const char *c, char *crep, int *crep_len);
|
||||
char *mbrep(const char *c, char *crep, int *crep_len);
|
||||
char control_rep(const signed char c);
|
||||
char control_mbrep(const char *c, bool isdata);
|
||||
int length_of_char(const char *c, int *width);
|
||||
int mbwidth(const char *c);
|
||||
int mb_cur_max(void);
|
||||
char *make_mbchar(long chr, int *chr_mb_len);
|
||||
@@ -213,16 +229,12 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n);
|
||||
char *nstrcasestr(const char *haystack, const char *needle);
|
||||
#endif
|
||||
char *mbstrcasestr(const char *haystack, const char *needle);
|
||||
#if !defined(NANO_TINY) || !defined(DISABLE_TABCOMP)
|
||||
char *revstrstr(const char *haystack, const char *needle, const char
|
||||
*rev_start);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
char *revstrstr(const char *haystack, const char *needle,
|
||||
const char *pointer);
|
||||
char *revstrcasestr(const char *haystack, const char *needle, const char
|
||||
*rev_start);
|
||||
char *mbrevstrcasestr(const char *haystack, const char *needle, const
|
||||
char *rev_start);
|
||||
#endif
|
||||
size_t mbstrlen(const char *s);
|
||||
#ifndef HAVE_STRNLEN
|
||||
size_t nstrnlen(const char *s, size_t maxlen);
|
||||
@@ -268,13 +280,7 @@ void cut_marked(void);
|
||||
void cut_to_eol(void);
|
||||
void cut_to_eof(void);
|
||||
#endif
|
||||
void do_cut_text(
|
||||
#ifndef NANO_TINY
|
||||
bool copy_text, bool cut_till_eof
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
);
|
||||
void do_cut_text(bool copy_text, bool cut_till_eof);
|
||||
void do_cut_text_void(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_copy_text(void);
|
||||
@@ -299,13 +305,6 @@ filestruct *read_line(char *buf, size_t buf_len, filestruct *prevnode);
|
||||
void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkwritable);
|
||||
int open_file(const char *filename, bool newfie, bool quiet, FILE **f);
|
||||
char *get_next_filename(const char *name, const char *suffix);
|
||||
void do_insertfile(
|
||||
#ifndef NANO_TINY
|
||||
bool execute
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
);
|
||||
void do_insertfile_void(void);
|
||||
char *get_full_path(const char *origpath);
|
||||
char *check_writable_directory(const char *path);
|
||||
@@ -320,11 +319,11 @@ int delete_lockfile(const char *lockfilename);
|
||||
int write_lockfile(const char *lockfilename, const char *origfilename, bool modified);
|
||||
#endif
|
||||
int copy_file(FILE *inn, FILE *out);
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp, append_type
|
||||
append, bool nonamechange);
|
||||
bool write_file(const char *name, FILE *f_open, bool tmp,
|
||||
kind_of_writing_type method, bool nonamechange);
|
||||
#ifndef NANO_TINY
|
||||
bool write_marked_file(const char *name, FILE *f_open, bool tmp,
|
||||
append_type append);
|
||||
kind_of_writing_type method);
|
||||
#endif
|
||||
int do_writeout(bool exiting);
|
||||
void do_writeout_void(void);
|
||||
@@ -349,22 +348,21 @@ const char *tail(const char *path);
|
||||
#ifndef DISABLE_HISTORIES
|
||||
char *histfilename(void);
|
||||
void load_history(void);
|
||||
bool writehist(FILE *hist, filestruct *histhead);
|
||||
bool writehist(FILE *hist, const filestruct *histhead);
|
||||
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);
|
||||
int check_poshistory(const char *file, ssize_t *line, ssize_t *column);
|
||||
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 sc_seq_or(void (*func)(void), int defaultval);
|
||||
int the_code_for(void (*func)(void), int defaultval);
|
||||
functionptrtype func_from_key(int *kbinput);
|
||||
key_type strtokeytype(const char *str);
|
||||
void assign_keyinfo(sc *s);
|
||||
void assign_keyinfo(sc *s, const char *keystring, const int keycode);
|
||||
void print_sclist(void);
|
||||
void shortcut_init(void);
|
||||
#ifndef DISABLE_COLOR
|
||||
@@ -399,34 +397,21 @@ void do_para_begin_void(void);
|
||||
void do_para_end(bool allow_update);
|
||||
void do_para_end_void(void);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
void do_prev_block(void);
|
||||
void do_next_block(void);
|
||||
void do_prev_word(bool allow_punct, bool allow_update);
|
||||
void do_prev_word_void(void);
|
||||
bool do_next_word(bool allow_punct, bool allow_update);
|
||||
void do_next_word_void(void);
|
||||
#endif
|
||||
void ensure_line_is_visible(void);
|
||||
void do_home(void);
|
||||
void do_end(void);
|
||||
void do_up(
|
||||
#ifndef NANO_TINY
|
||||
bool scroll_only
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
);
|
||||
void do_up(bool scroll_only);
|
||||
void do_up_void(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_scroll_up(void);
|
||||
#endif
|
||||
void do_down(
|
||||
#ifndef NANO_TINY
|
||||
bool scroll_only
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
);
|
||||
void do_down(bool scroll_only);
|
||||
void do_down_void(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_scroll_up(void);
|
||||
void do_scroll_down(void);
|
||||
#endif
|
||||
void do_left(void);
|
||||
@@ -457,11 +442,7 @@ void say_there_is_no_help(void);
|
||||
#endif
|
||||
void finish(void);
|
||||
void die(const char *msg, ...);
|
||||
void die_save_file(const char *die_filename
|
||||
#ifndef NANO_TINY
|
||||
, struct stat *die_stat
|
||||
#endif
|
||||
);
|
||||
void die_save_file(const char *die_filename, struct stat *die_stat);
|
||||
void window_init(void);
|
||||
#ifndef DISABLE_MOUSE
|
||||
void disable_mouse_support(void);
|
||||
@@ -475,9 +456,6 @@ void print_opt_full(const char *shortflag
|
||||
, const char *desc);
|
||||
void usage(void);
|
||||
void version(void);
|
||||
int more_space(void);
|
||||
int no_help(void);
|
||||
void no_current_file_name_warning(void);
|
||||
void do_exit(void);
|
||||
void close_and_go(void);
|
||||
void signal_init(void);
|
||||
@@ -489,13 +467,7 @@ RETSIGTYPE handle_sigwinch(int signal);
|
||||
void regenerate_screen(void);
|
||||
void allow_sigwinch(bool allow);
|
||||
void do_toggle(int flag);
|
||||
#endif
|
||||
void do_toggle_void(void);
|
||||
void disable_extended_io(void);
|
||||
#ifdef USE_SLANG
|
||||
void disable_signals(void);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
void enable_signals(void);
|
||||
#endif
|
||||
void disable_flow_control(void);
|
||||
@@ -508,14 +480,12 @@ int do_mouse(void);
|
||||
#endif
|
||||
void do_output(char *output, size_t output_len, bool allow_cntrls);
|
||||
|
||||
/* All functions in prompt.c. */
|
||||
int do_statusbar_input(bool *ran_func, bool *finished,
|
||||
void (*refresh_func)(void));
|
||||
/* Most functions in prompt.c. */
|
||||
#ifndef DISABLE_MOUSE
|
||||
int do_statusbar_mouse(void);
|
||||
#endif
|
||||
void do_statusbar_output(int *the_input, size_t input_len,
|
||||
bool filtering, bool *got_enter);
|
||||
bool filtering);
|
||||
void do_statusbar_home(void);
|
||||
void do_statusbar_end(void);
|
||||
void do_statusbar_left(void);
|
||||
@@ -527,22 +497,12 @@ void do_statusbar_cut_text(void);
|
||||
void do_statusbar_prev_word(void);
|
||||
void do_statusbar_next_word(void);
|
||||
#endif
|
||||
void do_statusbar_verbatim_input(bool *got_enter);
|
||||
void do_statusbar_verbatim_input(void);
|
||||
size_t statusbar_xplustabs(void);
|
||||
size_t get_statusbar_page_start(size_t start_col, size_t column);
|
||||
void reinit_statusbar_x(void);
|
||||
void reset_statusbar_cursor(void);
|
||||
void update_the_statusbar(void);
|
||||
void update_bar_if_needed(void);
|
||||
functionptrtype get_prompt_string(int *value, bool allow_tabs,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
bool allow_files, bool *listed,
|
||||
#endif
|
||||
const char *curranswer,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
filestruct **history_list,
|
||||
#endif
|
||||
void (*refresh_func)(void));
|
||||
int do_prompt(bool allow_tabs,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
bool allow_files,
|
||||
@@ -559,22 +519,12 @@ int do_yesno_prompt(bool all, const char *msg);
|
||||
char *parse_next_word(char *ptr);
|
||||
#endif
|
||||
#ifndef DISABLE_NANORC
|
||||
void rcfile_error(const char *msg, ...);
|
||||
char *parse_argument(char *ptr);
|
||||
#ifndef DISABLE_COLOR
|
||||
char *parse_next_regex(char *ptr);
|
||||
void parse_syntax(char *ptr);
|
||||
void parse_includes(char *ptr);
|
||||
short color_to_short(const char *colorname, bool *bright);
|
||||
bool parse_color_names(char *combostr, short *fg, short *bg, bool *bright);
|
||||
void grab_and_store(const char *kind, char *ptr, regexlisttype **storage);
|
||||
#endif
|
||||
void parse_rcfile(FILE *rcstream
|
||||
#ifndef DISABLE_COLOR
|
||||
, bool syntax_only
|
||||
#endif
|
||||
);
|
||||
void do_rcfile(void);
|
||||
void parse_rcfile(FILE *rcstream, bool syntax_only);
|
||||
void do_rcfiles(void);
|
||||
#endif /* !DISABLE_NANORC */
|
||||
|
||||
/* All functions in search.c. */
|
||||
@@ -585,31 +535,21 @@ void regexp_cleanup(void);
|
||||
void not_found_msg(const char *str);
|
||||
void search_replace_abort(void);
|
||||
int search_init(bool replacing, bool use_answer);
|
||||
int findnextstr(
|
||||
#ifndef DISABLE_SPELLER
|
||||
bool whole_word_only,
|
||||
#endif
|
||||
const filestruct *begin, size_t begin_x,
|
||||
const char *needle, size_t *match_len);
|
||||
int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
|
||||
const filestruct *begin, size_t begin_x);
|
||||
void do_search(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_findprevious(void);
|
||||
void do_findnext(void);
|
||||
#endif
|
||||
#if !defined(NANO_TINY) || !defined(DISABLE_BROWSER)
|
||||
void do_research(void);
|
||||
#endif
|
||||
void go_looking(void);
|
||||
#ifdef HAVE_REGEX_H
|
||||
int replace_regexp(char *string, bool create);
|
||||
#endif
|
||||
char *replace_line(const char *needle);
|
||||
ssize_t do_replace_loop(
|
||||
#ifndef DISABLE_SPELLER
|
||||
bool whole_word_only,
|
||||
#endif
|
||||
const filestruct *real_current, size_t *real_current_x,
|
||||
const char *needle);
|
||||
ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
const filestruct *real_current, size_t *real_current_x);
|
||||
void do_replace(void);
|
||||
void goto_line_posx(ssize_t line, size_t pos_x);
|
||||
void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
@@ -650,17 +590,25 @@ void do_tab(void);
|
||||
void do_indent(ssize_t cols);
|
||||
void do_indent_void(void);
|
||||
void do_unindent(void);
|
||||
#endif
|
||||
bool white_string(const char *s);
|
||||
#ifdef ENABLE_COMMENT
|
||||
void do_comment(void);
|
||||
bool comment_line(undo_type action, filestruct *f, const char *comment_seq);
|
||||
#endif
|
||||
void do_undo(void);
|
||||
void do_redo(void);
|
||||
#endif
|
||||
#ifndef DISABLE_COMMENT
|
||||
void do_comment(void);
|
||||
#endif
|
||||
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 add_undo(undo_type action);
|
||||
#ifndef DISABLE_COMMENT
|
||||
void update_comment_undo(ssize_t lineno);
|
||||
#endif
|
||||
void update_undo(undo_type action);
|
||||
#endif /* !NANO_TINY */
|
||||
#ifndef DISABLE_WRAPPING
|
||||
void wrap_reset(void);
|
||||
bool do_wrap(filestruct *line);
|
||||
@@ -704,12 +652,16 @@ void do_formatter(void);
|
||||
void do_wordlinechar_count(void);
|
||||
#endif
|
||||
void do_verbatim_input(void);
|
||||
void complete_a_word(void);
|
||||
|
||||
/* All functions in utils.c. */
|
||||
void get_homedir(void);
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
int digits(ssize_t n);
|
||||
#endif
|
||||
bool parse_num(const char *str, ssize_t *val);
|
||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column);
|
||||
void align(char **str);
|
||||
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);
|
||||
@@ -734,7 +686,7 @@ void *nmalloc(size_t howmuch);
|
||||
void *nrealloc(void *ptr, size_t howmuch);
|
||||
char *mallocstrncpy(char *dest, const char *src, size_t n);
|
||||
char *mallocstrcpy(char *dest, const char *src);
|
||||
char *mallocstrassn(char *dest, 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);
|
||||
@@ -745,16 +697,11 @@ void new_magicline(void);
|
||||
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);
|
||||
void discard_until(const undo *thisitem, openfilestruct *thefile);
|
||||
void add_undo(undo_type action);
|
||||
void update_undo(undo_type action);
|
||||
#ifndef DISABLE_COMMENT
|
||||
void update_comment_undo(ssize_t lineno);
|
||||
bool comment_line(undo_type action, filestruct *f, const char *comment_seq);
|
||||
#endif
|
||||
#endif
|
||||
size_t get_totsize(const filestruct *begin, const filestruct *end);
|
||||
#ifndef NANO_TINY
|
||||
filestruct *fsfromline(ssize_t lineno);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
void dump_filestruct(const filestruct *inptr);
|
||||
void dump_filestruct_reverse(void);
|
||||
@@ -764,7 +711,7 @@ void dump_filestruct_reverse(void);
|
||||
void get_key_buffer(WINDOW *win);
|
||||
size_t get_key_buffer_len(void);
|
||||
void unget_input(int *input, size_t input_len);
|
||||
void unget_kbinput(int kbinput, bool metakey, bool funckey);
|
||||
void unget_kbinput(int kbinput, bool metakey);
|
||||
int *get_input(WINDOW *win, size_t input_len);
|
||||
int get_kbinput(WINDOW *win);
|
||||
int parse_kbinput(WINDOW *win);
|
||||
@@ -773,28 +720,28 @@ int parse_escape_sequence(WINDOW *win, int kbinput);
|
||||
int get_byte_kbinput(int kbinput);
|
||||
#ifdef ENABLE_UTF8
|
||||
long add_unicode_digit(int kbinput, long factor, long *uni);
|
||||
long get_unicode_kbinput(int kbinput);
|
||||
long get_unicode_kbinput(WINDOW *win, int kbinput);
|
||||
#endif
|
||||
int get_control_kbinput(int kbinput);
|
||||
void unparse_kbinput(char *output, size_t output_len);
|
||||
int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
|
||||
int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len);
|
||||
int *parse_verbatim_kbinput(WINDOW *win, size_t *count);
|
||||
#ifndef DISABLE_MOUSE
|
||||
int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts);
|
||||
#endif
|
||||
const sc *get_shortcut(int *kbinput);
|
||||
void blank_line(WINDOW *win, int y, int x, int n);
|
||||
void blank_titlebar(void);
|
||||
void blank_topbar(void);
|
||||
void blank_edit(void);
|
||||
void blank_statusbar(void);
|
||||
void blank_bottombars(void);
|
||||
void check_statusblank(void);
|
||||
char *display_string(const char *buf, size_t start_col, size_t len, bool
|
||||
dollars);
|
||||
char *display_string(const char *buf, size_t start_col, size_t span,
|
||||
bool dollars);
|
||||
void titlebar(const char *path);
|
||||
extern void set_modified(void);
|
||||
void statusbar(const char *msg);
|
||||
void warn_and_shortly_pause(const char *msg);
|
||||
void statusline(message_type importance, const char *msg, ...);
|
||||
void bottombars(int menu);
|
||||
void onekey(const char *keystroke, const char *desc, int length);
|
||||
@@ -802,11 +749,11 @@ void reset_cursor(void);
|
||||
void edit_draw(filestruct *fileptr, const char *converted, int
|
||||
line, size_t start);
|
||||
int update_line(filestruct *fileptr, size_t index);
|
||||
bool need_screen_update(size_t pww_save);
|
||||
bool need_horizontal_scroll(const size_t old_column, const size_t new_column);
|
||||
void edit_scroll(scroll_dir direction, ssize_t nlines);
|
||||
void edit_redraw(filestruct *old_current);
|
||||
void edit_refresh(void);
|
||||
void edit_update(update_type location);
|
||||
void adjust_viewport(update_type location);
|
||||
void total_redraw(void);
|
||||
void total_refresh(void);
|
||||
void display_main_list(void);
|
||||
|
||||
218
src/rcfile.c
218
src/rcfile.c
@@ -1,22 +1,23 @@
|
||||
/**************************************************************************
|
||||
* rcfile.c *
|
||||
* rcfile.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, *
|
||||
* 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014 Mike Frysinger *
|
||||
* Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -32,8 +33,15 @@
|
||||
|
||||
#ifndef DISABLE_NANORC
|
||||
|
||||
#ifndef RCFILE_NAME
|
||||
#define RCFILE_NAME ".nanorc"
|
||||
#endif
|
||||
|
||||
static const rcoption rcopts[] = {
|
||||
{"boldtext", BOLD_TEXT},
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
{"linenumbers", LINE_NUMBERS},
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
{"brackets", 0},
|
||||
#endif
|
||||
@@ -95,6 +103,7 @@ static const rcoption rcopts[] = {
|
||||
{"noconvert", NO_CONVERT},
|
||||
{"quickblank", QUICK_BLANK},
|
||||
{"quiet", QUIET},
|
||||
{"showcursor", SHOW_CURSOR},
|
||||
{"smarthome", SMART_HOME},
|
||||
{"smooth", SMOOTH_SCROLL},
|
||||
{"softwrap", SOFTWRAP},
|
||||
@@ -102,9 +111,11 @@ static const rcoption rcopts[] = {
|
||||
{"unix", MAKE_IT_UNIX},
|
||||
{"whitespace", 0},
|
||||
{"wordbounds", WORD_BOUNDS},
|
||||
{"wordchars", 0},
|
||||
#endif
|
||||
#ifndef DISABLE_COLOR
|
||||
{"titlecolor", 0},
|
||||
{"numbercolor", 0},
|
||||
{"statuscolor", 0},
|
||||
{"keycolor", 0},
|
||||
{"functioncolor", 0},
|
||||
@@ -341,9 +352,7 @@ bool is_universal(void (*func))
|
||||
{
|
||||
if (func == do_left || func == do_right ||
|
||||
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)
|
||||
@@ -398,7 +407,12 @@ void parse_binding(char *ptr, bool dobind)
|
||||
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] == '^' && (keycopy[1] < 64 || keycopy[1] > 127)) {
|
||||
} 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)) {
|
||||
rcfile_error(N_("Key name %s is invalid"), keycopy);
|
||||
goto free_copy;
|
||||
}
|
||||
@@ -453,9 +467,11 @@ void parse_binding(char *ptr, bool dobind)
|
||||
if (f->scfunc == newsc->scfunc)
|
||||
mask = mask | f->menus;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Handle the special case of the toggles. */
|
||||
if (newsc->scfunc == do_toggle_void)
|
||||
mask = MMAIN;
|
||||
#endif
|
||||
|
||||
/* Now limit the given menu to those where the function exists. */
|
||||
if (is_universal(newsc->scfunc))
|
||||
@@ -469,20 +485,18 @@ void parse_binding(char *ptr, bool dobind)
|
||||
goto free_copy;
|
||||
}
|
||||
|
||||
newsc->keystr = keycopy;
|
||||
newsc->menus = menu;
|
||||
newsc->type = strtokeytype(newsc->keystr);
|
||||
assign_keyinfo(newsc);
|
||||
assign_keyinfo(newsc, keycopy, 0);
|
||||
|
||||
/* Do not allow rebinding the equivalent of the Escape key. */
|
||||
if (newsc->type == META && newsc->seq == 91) {
|
||||
/* 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;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "s->keystr = \"%s\"\n", newsc->keystr);
|
||||
fprintf(stderr, "s->seq = \"%d\"\n", newsc->seq);
|
||||
fprintf(stderr, "s->keycode = \"%d\"\n", newsc->keycode);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -497,6 +511,7 @@ void parse_binding(char *ptr, bool dobind)
|
||||
}
|
||||
|
||||
if (dobind) {
|
||||
#ifndef NANO_TINY
|
||||
/* If this is a toggle, copy its sequence number. */
|
||||
if (newsc->scfunc == do_toggle_void) {
|
||||
for (s = sclist; s != NULL; s = s->next)
|
||||
@@ -504,6 +519,7 @@ void parse_binding(char *ptr, bool dobind)
|
||||
newsc->ordinal = s->ordinal;
|
||||
} else
|
||||
newsc->ordinal = 0;
|
||||
#endif
|
||||
/* Add the new shortcut at the start of the list. */
|
||||
newsc->next = sclist;
|
||||
sclist = newsc;
|
||||
@@ -514,35 +530,40 @@ void parse_binding(char *ptr, bool dobind)
|
||||
free(keycopy);
|
||||
}
|
||||
|
||||
/* Verify that the given file is not a folder nor a device. */
|
||||
bool is_good_file(char *file)
|
||||
{
|
||||
struct stat rcinfo;
|
||||
|
||||
/* 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))) {
|
||||
rcfile_error(S_ISDIR(rcinfo.st_mode) ? _("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), file);
|
||||
return FALSE;
|
||||
} else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
/* Read and parse one included syntax file. */
|
||||
static void parse_one_include(char *file)
|
||||
{
|
||||
struct stat rcinfo;
|
||||
FILE *rcstream;
|
||||
|
||||
/* Can't get the specified file's full path because it may screw up
|
||||
* our cwd depending on the parent directories' permissions (see
|
||||
* Savannah bug #25297). */
|
||||
|
||||
/* Don't open directories, character files, or block files. */
|
||||
if (stat(file, &rcinfo) != -1) {
|
||||
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
|
||||
S_ISBLK(rcinfo.st_mode)) {
|
||||
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
|
||||
_("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), file);
|
||||
}
|
||||
}
|
||||
if (!is_good_file(file))
|
||||
return;
|
||||
|
||||
/* Open the new syntax file. */
|
||||
if ((rcstream = fopen(file, "rb")) == NULL) {
|
||||
rcfile_error(_("Error reading %s: %s"), file,
|
||||
strerror(errno));
|
||||
/* Open the included syntax file. */
|
||||
rcstream = fopen(file, "rb");
|
||||
|
||||
if (rcstream == NULL) {
|
||||
rcfile_error(_("Error reading %s: %s"), file, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Use the name and line number position of the new syntax file
|
||||
/* Use the name and line number position of the included syntax file
|
||||
* while parsing it, so we can know where any errors in it are. */
|
||||
nanorc = file;
|
||||
lineno = 0;
|
||||
@@ -573,8 +594,7 @@ void parse_includes(char *ptr)
|
||||
for (i = 0; i < files.gl_pathc; ++i)
|
||||
parse_one_include(files.gl_pathv[i]);
|
||||
} else
|
||||
rcfile_error(_("Error expanding %s: %s"), option,
|
||||
strerror(errno));
|
||||
rcfile_error(_("Error expanding %s: %s"), option, strerror(errno));
|
||||
|
||||
globfree(&files);
|
||||
free(expanded);
|
||||
@@ -657,7 +677,7 @@ void parse_colors(char *ptr, int rex_flags)
|
||||
/* Now for the fun part. Start adding regexes to individual strings
|
||||
* in the colorstrings array, woo! */
|
||||
while (ptr != NULL && *ptr != '\0') {
|
||||
colortype *newcolor;
|
||||
colortype *newcolor = NULL;
|
||||
/* The container for a color plus its regexes. */
|
||||
bool goodstart;
|
||||
/* Whether the start expression was valid. */
|
||||
@@ -892,8 +912,8 @@ void pick_up_name(const char *kind, char *ptr, char **storage)
|
||||
}
|
||||
#endif /* !DISABLE_COLOR */
|
||||
|
||||
/* Check whether the user has unmapped every shortcut for a
|
||||
* sequence we consider 'vital', like the exit function. */
|
||||
/* Verify that the user has not unmapped every shortcut for a
|
||||
* function that we consider 'vital' (such as "Exit"). */
|
||||
static void check_vitals_mapped(void)
|
||||
{
|
||||
subnfunc *f;
|
||||
@@ -920,13 +940,9 @@ static void check_vitals_mapped(void)
|
||||
}
|
||||
|
||||
/* Parse the rcfile, once it has been opened successfully at rcstream,
|
||||
* and close it afterwards. If syntax_only is TRUE, only allow the file
|
||||
* to contain color syntax commands. */
|
||||
void parse_rcfile(FILE *rcstream
|
||||
#ifndef DISABLE_COLOR
|
||||
, bool syntax_only
|
||||
#endif
|
||||
)
|
||||
* and close it afterwards. If syntax_only is TRUE, allow the file to
|
||||
* to contain only color syntax commands. */
|
||||
void parse_rcfile(FILE *rcstream, bool syntax_only)
|
||||
{
|
||||
char *buf = NULL;
|
||||
ssize_t len;
|
||||
@@ -1067,7 +1083,8 @@ void parse_rcfile(FILE *rcstream
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "parse_rcfile(): option name = \"%s\"\n", rcopts[i].name);
|
||||
fprintf(stderr, " Option name = \"%s\"\n", rcopts[i].name);
|
||||
fprintf(stderr, " Flag = %ld\n", rcopts[i].flag);
|
||||
#endif
|
||||
/* First handle unsetting. */
|
||||
if (set == -1) {
|
||||
@@ -1098,17 +1115,19 @@ void parse_rcfile(FILE *rcstream
|
||||
|
||||
option = mallocstrcpy(NULL, option);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "option argument = \"%s\"\n", option);
|
||||
fprintf(stderr, " Option argument = \"%s\"\n", option);
|
||||
#endif
|
||||
/* Make sure the option argument is a valid multibyte string. */
|
||||
if (!is_valid_mbstring(option)) {
|
||||
rcfile_error(N_("Option is not a valid multibyte string"));
|
||||
rcfile_error(N_("Argument is not a valid multibyte string"));
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_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, "statuscolor") == 0)
|
||||
specified_color_combo[STATUS_BAR] = option;
|
||||
else if (strcasecmp(rcopts[i].name, "keycolor") == 0)
|
||||
@@ -1128,8 +1147,10 @@ void parse_rcfile(FILE *rcstream
|
||||
rcfile_error(N_("Requested fill size \"%s\" is invalid"),
|
||||
option);
|
||||
wrap_at = -CHARS_FROM_EOL;
|
||||
} else
|
||||
} else {
|
||||
UNSET(NO_WRAP);
|
||||
free(option);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
@@ -1176,6 +1197,9 @@ void parse_rcfile(FILE *rcstream
|
||||
if (strcasecmp(rcopts[i].name, "backupdir") == 0)
|
||||
backup_dir = option;
|
||||
else
|
||||
if (strcasecmp(rcopts[i].name, "wordchars") == 0)
|
||||
word_chars = option;
|
||||
else
|
||||
#endif
|
||||
#ifndef DISABLE_SPELLER
|
||||
if (strcasecmp(rcopts[i].name, "speller") == 0)
|
||||
@@ -1191,10 +1215,6 @@ void parse_rcfile(FILE *rcstream
|
||||
free(option);
|
||||
} else
|
||||
assert(FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "flag = %ld\n", rcopts[i].flag);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef DISABLE_COLOR
|
||||
@@ -1209,45 +1229,43 @@ void parse_rcfile(FILE *rcstream
|
||||
fclose(rcstream);
|
||||
lineno = 0;
|
||||
|
||||
check_vitals_mapped();
|
||||
return;
|
||||
}
|
||||
|
||||
/* The main rcfile function. It tries to open the system-wide rcfile,
|
||||
* followed by the current user's rcfile. */
|
||||
void do_rcfile(void)
|
||||
/* Read and interpret one of the two nanorc files. */
|
||||
void parse_one_nanorc(void)
|
||||
{
|
||||
struct stat rcinfo;
|
||||
FILE *rcstream;
|
||||
|
||||
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
|
||||
|
||||
/* Don't open directories, character files, or block files. */
|
||||
if (stat(nanorc, &rcinfo) != -1) {
|
||||
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
|
||||
S_ISBLK(rcinfo.st_mode))
|
||||
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
|
||||
_("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), nanorc);
|
||||
}
|
||||
/* Don't try to open directories nor devices. */
|
||||
if (!is_good_file(nanorc))
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Parsing file \"%s\"\n", nanorc);
|
||||
fprintf(stderr, "Going to parse file \"%s\"\n", nanorc);
|
||||
#endif
|
||||
|
||||
/* Try to open the system-wide nanorc. */
|
||||
rcstream = fopen(nanorc, "rb");
|
||||
if (rcstream != NULL)
|
||||
parse_rcfile(rcstream
|
||||
#ifndef DISABLE_COLOR
|
||||
, FALSE
|
||||
#endif
|
||||
);
|
||||
|
||||
/* If opening the file succeeded, parse it. Otherwise, only
|
||||
* complain if the file actually exists. */
|
||||
if (rcstream != NULL)
|
||||
parse_rcfile(rcstream, FALSE);
|
||||
else if (errno != ENOENT)
|
||||
rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno));
|
||||
}
|
||||
|
||||
/* First read the system-wide rcfile, then the user's rcfile. */
|
||||
void do_rcfiles(void)
|
||||
{
|
||||
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
|
||||
|
||||
/* Process the system-wide nanorc. */
|
||||
parse_one_nanorc();
|
||||
|
||||
/* When configured with --disable-wrapping-as-root, turn wrapping off
|
||||
* for root, so that only root's .nanorc or --fill can turn it on. */
|
||||
#ifdef DISABLE_ROOTWRAPPING
|
||||
/* We've already read SYSCONFDIR/nanorc, if it's there. If we're
|
||||
* root, and --disable-wrapping-as-root is used, turn wrapping off
|
||||
* now. */
|
||||
if (geteuid() == NANO_ROOT_UID)
|
||||
SET(NO_WRAP);
|
||||
#endif
|
||||
@@ -1257,38 +1275,16 @@ void do_rcfile(void)
|
||||
if (homedir == NULL)
|
||||
rcfile_error(N_("I can't find my home directory! Wah!"));
|
||||
else {
|
||||
#ifndef RCFILE_NAME
|
||||
#define RCFILE_NAME ".nanorc"
|
||||
#endif
|
||||
nanorc = charealloc(nanorc, strlen(homedir) + strlen(RCFILE_NAME) + 2);
|
||||
sprintf(nanorc, "%s/%s", homedir, RCFILE_NAME);
|
||||
|
||||
/* Don't open directories, character files, or block files. */
|
||||
if (stat(nanorc, &rcinfo) != -1) {
|
||||
if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) ||
|
||||
S_ISBLK(rcinfo.st_mode))
|
||||
rcfile_error(S_ISDIR(rcinfo.st_mode) ?
|
||||
_("\"%s\" is a directory") :
|
||||
_("\"%s\" is a device file"), nanorc);
|
||||
}
|
||||
|
||||
/* Try to open the current user's nanorc. */
|
||||
rcstream = fopen(nanorc, "rb");
|
||||
if (rcstream == NULL) {
|
||||
/* Don't complain about the file's not existing. */
|
||||
if (errno != ENOENT)
|
||||
rcfile_error(N_("Error reading %s: %s"), nanorc,
|
||||
strerror(errno));
|
||||
} else
|
||||
parse_rcfile(rcstream
|
||||
#ifndef DISABLE_COLOR
|
||||
, FALSE
|
||||
#endif
|
||||
);
|
||||
/* Process the current user's nanorc. */
|
||||
parse_one_nanorc();
|
||||
}
|
||||
|
||||
check_vitals_mapped();
|
||||
|
||||
free(nanorc);
|
||||
nanorc = NULL;
|
||||
|
||||
if (errors && !ISSET(QUIET)) {
|
||||
errors = FALSE;
|
||||
|
||||
251
src/search.c
251
src/search.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* search.c *
|
||||
* search.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2015, 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -47,11 +47,8 @@ bool regexp_init(const char *regexp)
|
||||
|
||||
assert(!regexp_compiled);
|
||||
|
||||
rc = regcomp(&search_regexp, fixbounds(regexp), NANO_REG_EXTENDED
|
||||
#ifndef NANO_TINY
|
||||
| (ISSET(CASE_SENSITIVE) ? 0 : REG_ICASE)
|
||||
#endif
|
||||
);
|
||||
rc = regcomp(&search_regexp, fixbounds(regexp),
|
||||
NANO_REG_EXTENDED | (ISSET(CASE_SENSITIVE) ? 0 : REG_ICASE));
|
||||
|
||||
if (rc != 0) {
|
||||
size_t len = regerror(rc, &search_regexp, NULL, 0);
|
||||
@@ -104,10 +101,9 @@ void not_found_msg(const char *str)
|
||||
* search, if any. */
|
||||
void search_replace_abort(void)
|
||||
{
|
||||
display_main_list();
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark_set)
|
||||
edit_refresh();
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
#ifdef HAVE_REGEX_H
|
||||
regexp_cleanup();
|
||||
@@ -156,32 +152,26 @@ int search_init(bool replacing, bool use_answer)
|
||||
/* This is now one simple call. It just does a lot. */
|
||||
i = do_prompt(FALSE,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
TRUE,
|
||||
TRUE,
|
||||
#endif
|
||||
replacing ? MREPLACE : MWHEREIS, backupstring,
|
||||
replacing ? MREPLACE : MWHEREIS, backupstring,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
&search_history,
|
||||
&search_history,
|
||||
#endif
|
||||
/* TRANSLATORS: This is the main search prompt. */
|
||||
edit_refresh, "%s%s%s%s%s%s", _("Search"),
|
||||
#ifndef NANO_TINY
|
||||
/* TRANSLATORS: The next three strings are modifiers of the search prompt. */
|
||||
ISSET(CASE_SENSITIVE) ? _(" [Case Sensitive]") :
|
||||
#endif
|
||||
"",
|
||||
/* TRANSLATORS: This is the main search prompt. */
|
||||
edit_refresh, "%s%s%s%s%s%s", _("Search"),
|
||||
/* TRANSLATORS: The next three modify the search prompt. */
|
||||
ISSET(CASE_SENSITIVE) ? _(" [Case Sensitive]") : "",
|
||||
#ifdef HAVE_REGEX_H
|
||||
ISSET(USE_REGEXP) ? _(" [Regexp]") :
|
||||
ISSET(USE_REGEXP) ? _(" [Regexp]") :
|
||||
#endif
|
||||
"",
|
||||
"",
|
||||
ISSET(BACKWARDS_SEARCH) ? _(" [Backwards]") : "", replacing ?
|
||||
#ifndef NANO_TINY
|
||||
ISSET(BACKWARDS_SEARCH) ? _(" [Backwards]") :
|
||||
/* TRANSLATORS: The next two modify the search prompt. */
|
||||
openfile->mark_set ? _(" (to replace) in selection") :
|
||||
#endif
|
||||
"", replacing ?
|
||||
#ifndef NANO_TINY
|
||||
/* TRANSLATORS: The next two strings are modifiers of the search prompt. */
|
||||
openfile->mark_set ? _(" (to replace) in selection") :
|
||||
#endif
|
||||
_(" (to replace)") : "", buf);
|
||||
_(" (to replace)") : "", buf);
|
||||
|
||||
/* Release buf now that we don't need it anymore. */
|
||||
free(buf);
|
||||
@@ -215,7 +205,6 @@ int search_init(bool replacing, bool use_answer)
|
||||
|
||||
func = func_from_key(&i);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (func == case_sens_void) {
|
||||
TOGGLE(CASE_SENSITIVE);
|
||||
backupstring = mallocstrcpy(backupstring, answer);
|
||||
@@ -225,7 +214,6 @@ int search_init(bool replacing, bool use_answer)
|
||||
backupstring = mallocstrcpy(backupstring, answer);
|
||||
return 1;
|
||||
} else
|
||||
#endif
|
||||
#ifdef HAVE_REGEX_H
|
||||
if (func == regexp_void) {
|
||||
TOGGLE(USE_REGEXP);
|
||||
@@ -249,12 +237,8 @@ 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(
|
||||
#ifndef DISABLE_SPELLER
|
||||
bool whole_word_only,
|
||||
#endif
|
||||
const filestruct *begin, size_t begin_x,
|
||||
const char *needle, size_t *match_len)
|
||||
int findnextstr(const char *needle, bool whole_word_only, size_t *match_len,
|
||||
const filestruct *begin, size_t begin_x)
|
||||
{
|
||||
size_t found_len;
|
||||
/* The length of the match we find. */
|
||||
@@ -271,12 +255,13 @@ int findnextstr(
|
||||
* will return immediately and say that no match was found, and
|
||||
* rev_start will be properly set when the search continues on the
|
||||
* previous or next line. */
|
||||
rev_start +=
|
||||
#ifndef NANO_TINY
|
||||
ISSET(BACKWARDS_SEARCH) ?
|
||||
((openfile->current_x == 0) ? -1 : move_mbleft(fileptr->data, openfile->current_x)) :
|
||||
#endif
|
||||
move_mbright(fileptr->data, openfile->current_x);
|
||||
if (ISSET(BACKWARDS_SEARCH)) {
|
||||
if (openfile->current_x == 0)
|
||||
rev_start += -1;
|
||||
else
|
||||
rev_start += move_mbleft(fileptr->data, openfile->current_x);
|
||||
} else
|
||||
rev_start += move_mbright(fileptr->data, openfile->current_x);
|
||||
|
||||
enable_nodelay();
|
||||
|
||||
@@ -302,6 +287,8 @@ int findnextstr(
|
||||
}
|
||||
|
||||
if (++feedback > 0)
|
||||
/* TRANSLATORS: This is shown when searching takes
|
||||
* more than half a second. */
|
||||
statusbar(_("Searching..."));
|
||||
}
|
||||
|
||||
@@ -342,11 +329,9 @@ int findnextstr(
|
||||
}
|
||||
|
||||
/* Move to the previous or next line in the file. */
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(BACKWARDS_SEARCH))
|
||||
fileptr = fileptr->prev;
|
||||
else
|
||||
#endif
|
||||
fileptr = fileptr->next;
|
||||
|
||||
/* If we've reached the start or end of the buffer, wrap around. */
|
||||
@@ -358,11 +343,9 @@ int findnextstr(
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(BACKWARDS_SEARCH))
|
||||
fileptr = openfile->filebot;
|
||||
else
|
||||
#endif
|
||||
fileptr = openfile->fileage;
|
||||
|
||||
statusbar(_("Search Wrapped"));
|
||||
@@ -376,23 +359,15 @@ int findnextstr(
|
||||
|
||||
/* Set the starting x to the start or end of the line. */
|
||||
rev_start = fileptr->data;
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(BACKWARDS_SEARCH))
|
||||
rev_start += strlen(fileptr->data);
|
||||
#endif
|
||||
}
|
||||
|
||||
found_x = found - fileptr->data;
|
||||
|
||||
/* Ensure that the found occurrence is not beyond the starting x. */
|
||||
if (came_full_circle &&
|
||||
#ifndef NANO_TINY
|
||||
((!ISSET(BACKWARDS_SEARCH) && found_x > begin_x) ||
|
||||
(ISSET(BACKWARDS_SEARCH) && found_x < begin_x))
|
||||
#else
|
||||
found_x > begin_x
|
||||
#endif
|
||||
) {
|
||||
if (came_full_circle && ((!ISSET(BACKWARDS_SEARCH) && found_x > begin_x) ||
|
||||
(ISSET(BACKWARDS_SEARCH) && found_x < begin_x))) {
|
||||
not_found_msg(needle);
|
||||
disable_nodelay();
|
||||
return 0;
|
||||
@@ -424,10 +399,8 @@ void do_search(void)
|
||||
search_replace_abort();
|
||||
else if (i == -2) /* Do a replace instead. */
|
||||
do_replace();
|
||||
#if !defined(NANO_TINY) || defined(HAVE_REGEX_H)
|
||||
else if (i == 1) /* Toggled something. */
|
||||
do_search();
|
||||
#endif
|
||||
|
||||
if (i == 0)
|
||||
go_looking();
|
||||
@@ -458,7 +431,6 @@ void do_findnext(void)
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#if !defined(NANO_TINY) || !defined(DISABLE_BROWSER)
|
||||
/* Search for the last string without prompting. */
|
||||
void do_research(void)
|
||||
{
|
||||
@@ -484,7 +456,6 @@ void do_research(void)
|
||||
|
||||
go_looking();
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Search for the global string 'last_search'. Inform the user when
|
||||
* the string occurs only once. */
|
||||
@@ -493,14 +464,14 @@ void go_looking(void)
|
||||
filestruct *was_current = openfile->current;
|
||||
size_t was_current_x = openfile->current_x;
|
||||
int didfind;
|
||||
#ifdef DEBUG
|
||||
clock_t start = clock();
|
||||
#endif
|
||||
|
||||
came_full_circle = FALSE;
|
||||
|
||||
didfind = findnextstr(
|
||||
#ifndef DISABLE_SPELLER
|
||||
FALSE,
|
||||
#endif
|
||||
openfile->current, openfile->current_x, last_search, NULL);
|
||||
didfind = findnextstr(last_search, FALSE, NULL,
|
||||
openfile->current, openfile->current_x);
|
||||
|
||||
/* If we found something, and we're back at the exact same spot
|
||||
* where we started searching, then this is the only occurrence. */
|
||||
@@ -508,6 +479,10 @@ void go_looking(void)
|
||||
openfile->current_x == was_current_x)
|
||||
statusbar(_("This is the only occurrence"));
|
||||
|
||||
#ifdef DEBUG
|
||||
statusline(HUSH, "Took: %.2f", (double)(clock() - start) / CLOCKS_PER_SEC);
|
||||
#endif
|
||||
|
||||
edit_redraw(was_current);
|
||||
search_replace_abort();
|
||||
}
|
||||
@@ -599,20 +574,14 @@ char *replace_line(const char *needle)
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* Step through each replace word and prompt user before replacing.
|
||||
* Parameters real_current and real_current_x are needed in order to
|
||||
/* Step through each occurrence of the search string and prompt the user
|
||||
* before replacing it. We seek for needle, and replace it with answer.
|
||||
* The parameters real_current and real_current_x are needed in order to
|
||||
* allow the cursor position to be updated when a word before the cursor
|
||||
* is replaced by a shorter word.
|
||||
*
|
||||
* needle is the string to seek. We replace it with answer. Return -1
|
||||
* if needle isn't found, else the number of replacements performed. If
|
||||
* canceled isn't NULL, set it to TRUE if we canceled. */
|
||||
ssize_t do_replace_loop(
|
||||
#ifndef DISABLE_SPELLER
|
||||
bool whole_word_only,
|
||||
#endif
|
||||
const filestruct *real_current, size_t *real_current_x,
|
||||
const char *needle)
|
||||
* is replaced by a shorter word. Return -1 if needle isn't found, -2 if
|
||||
* the seeking is aborted, else the number of replacements performed. */
|
||||
ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
const filestruct *real_current, size_t *real_current_x)
|
||||
{
|
||||
ssize_t numreplaced = -1;
|
||||
size_t match_len;
|
||||
@@ -625,10 +594,10 @@ ssize_t do_replace_loop(
|
||||
/* TRUE if (mark_begin, mark_begin_x) is the top of the mark,
|
||||
* FALSE if (current, current_x) is. */
|
||||
|
||||
/* If the mark is on, frame the region, and turn the mark off. */
|
||||
if (old_mark_set) {
|
||||
/* If the mark is on, frame the region, and turn the mark off. */
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
openfile->mark_set = FALSE;
|
||||
|
||||
/* Start either at the top or the bottom of the marked region. */
|
||||
@@ -646,11 +615,8 @@ ssize_t do_replace_loop(
|
||||
|
||||
while (TRUE) {
|
||||
int i = 0;
|
||||
int result = findnextstr(
|
||||
#ifndef DISABLE_SPELLER
|
||||
whole_word_only,
|
||||
#endif
|
||||
real_current, *real_current_x, needle, &match_len);
|
||||
int result = findnextstr(needle, whole_word_only, &match_len,
|
||||
real_current, *real_current_x);
|
||||
|
||||
/* If nothing more was found, or the user aborted, stop looping. */
|
||||
if (result < 1) {
|
||||
@@ -698,18 +664,17 @@ ssize_t do_replace_loop(
|
||||
|
||||
if (i == -1) /* The replacing was cancelled. */
|
||||
break;
|
||||
else if (i == 2)
|
||||
replaceall = TRUE;
|
||||
}
|
||||
|
||||
if (i > 0 || replaceall) { /* Yes, replace it!!!! */
|
||||
if (i == 1 || replaceall) { /* Yes, replace it. */
|
||||
char *copy;
|
||||
size_t length_change;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
add_undo(REPLACE);
|
||||
#endif
|
||||
if (i == 2)
|
||||
replaceall = TRUE;
|
||||
|
||||
copy = replace_line(needle);
|
||||
|
||||
length_change = strlen(copy) - strlen(openfile->current->data);
|
||||
@@ -744,18 +709,14 @@ ssize_t do_replace_loop(
|
||||
}
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
/* Don't find the same zero-length match again. */
|
||||
if (match_len == 0)
|
||||
/* Don't find the same zero-length or BOL match again. */
|
||||
if (match_len == 0 || (*needle == '^' && ISSET(USE_REGEXP)))
|
||||
match_len++;
|
||||
#endif
|
||||
|
||||
/* Set the cursor at the last character of the replacement
|
||||
* text, so searching will resume after the replacement
|
||||
* text. Note that current_x might be set to (size_t)-1
|
||||
* here. */
|
||||
#ifndef NANO_TINY
|
||||
* text, so that searching will continue /after/ it. Note
|
||||
* that current_x might be set to (size_t)-1 here. */
|
||||
if (!ISSET(BACKWARDS_SEARCH))
|
||||
#endif
|
||||
openfile->current_x += match_len + length_change - 1;
|
||||
|
||||
/* Update the file size, and put the changed line into place. */
|
||||
@@ -772,8 +733,8 @@ ssize_t do_replace_loop(
|
||||
|
||||
if (!replaceall) {
|
||||
#ifndef DISABLE_COLOR
|
||||
/* If color syntaxes are available and turned on, we
|
||||
* need to call edit_refresh(). */
|
||||
/* 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))
|
||||
edit_refresh();
|
||||
else
|
||||
@@ -782,6 +743,7 @@ ssize_t do_replace_loop(
|
||||
}
|
||||
|
||||
set_modified();
|
||||
as_an_at = TRUE;
|
||||
numreplaced++;
|
||||
}
|
||||
}
|
||||
@@ -812,7 +774,6 @@ void do_replace(void)
|
||||
|
||||
if (ISSET(VIEW_MODE)) {
|
||||
print_view_warning();
|
||||
search_replace_abort();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -830,14 +791,14 @@ void do_replace(void)
|
||||
|
||||
i = do_prompt(FALSE,
|
||||
#ifndef DISABLE_TABCOMP
|
||||
TRUE,
|
||||
TRUE,
|
||||
#endif
|
||||
MREPLACEWITH, NULL,
|
||||
MREPLACEWITH, NULL,
|
||||
#ifndef DISABLE_HISTORIES
|
||||
&replace_history,
|
||||
&replace_history,
|
||||
#endif
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
edit_refresh, _("Replace with"));
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
edit_refresh, _("Replace with"));
|
||||
|
||||
#ifndef DISABLE_HISTORIES
|
||||
/* If the replace string is not "", add it to the replace history list. */
|
||||
@@ -858,18 +819,13 @@ void do_replace(void)
|
||||
begin = openfile->current;
|
||||
begin_x = openfile->current_x;
|
||||
|
||||
numreplaced = do_replace_loop(
|
||||
#ifndef DISABLE_SPELLER
|
||||
FALSE,
|
||||
#endif
|
||||
begin, &begin_x, last_search);
|
||||
numreplaced = do_replace_loop(last_search, FALSE, begin, &begin_x);
|
||||
|
||||
/* Restore where we were. */
|
||||
openfile->edittop = edittop_save;
|
||||
openfile->current = begin;
|
||||
openfile->current_x = begin_x;
|
||||
|
||||
edit_refresh();
|
||||
refresh_needed = TRUE;
|
||||
|
||||
if (numreplaced >= 0)
|
||||
statusline(HUSH, P_("Replaced %lu occurrence",
|
||||
@@ -913,31 +869,27 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
edit_refresh, _("Enter line number, column number"));
|
||||
|
||||
/* Cancel, or Enter with blank string. */
|
||||
/* If the user cancelled or gave a blank answer, get out. */
|
||||
if (i < 0) {
|
||||
statusbar(_("Cancelled"));
|
||||
display_main_list();
|
||||
return;
|
||||
}
|
||||
|
||||
func = func_from_key(&i);
|
||||
|
||||
if (func == gototext_void) {
|
||||
/* Keep answer up on the statusbar. */
|
||||
/* Retain what the user typed so far and switch to searching. */
|
||||
search_init(TRUE, TRUE);
|
||||
|
||||
do_search();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do a bounds check. Display a warning on an out-of-bounds
|
||||
* line or column number only if we hit Enter at the statusbar
|
||||
* prompt. */
|
||||
if (!parse_line_column(answer, &line, &column) ||
|
||||
line < 1 || column < 1) {
|
||||
if (i == 0)
|
||||
statusbar(_("Invalid line or column number"));
|
||||
display_main_list();
|
||||
/* If a function was executed, we're done here. */
|
||||
if (i > 0)
|
||||
return;
|
||||
|
||||
/* Try to extract one or two numbers from the user's response. */
|
||||
if (!parse_line_column(answer, &line, &column)) {
|
||||
statusbar(_("Invalid line or column number"));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -948,18 +900,31 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
column = openfile->placewewant + 1;
|
||||
}
|
||||
|
||||
/* Take a negative line number to mean: from the end of the file. */
|
||||
if (line < 0)
|
||||
line = openfile->filebot->lineno + line + 1;
|
||||
if (line < 1)
|
||||
line = 1;
|
||||
|
||||
/* Iterate to the requested line. */
|
||||
for (openfile->current = openfile->fileage; line > 1 &&
|
||||
openfile->current != openfile->filebot; line--)
|
||||
openfile->current = openfile->current->next;
|
||||
|
||||
/* Take a negative column number to mean: from the end of the line. */
|
||||
if (column < 0)
|
||||
column = strlenpt(openfile->current->data) + column + 2;
|
||||
if (column < 1)
|
||||
column = 1;
|
||||
|
||||
/* Set the x position that corresponds to the requested column. */
|
||||
openfile->current_x = actual_x(openfile->current->data, column - 1);
|
||||
openfile->placewewant = column - 1;
|
||||
|
||||
/* When the position was manually given, center the target line. */
|
||||
if (interactive) {
|
||||
edit_update(CENTERING);
|
||||
edit_refresh();
|
||||
display_main_list();
|
||||
if (interactive || ISSET(SOFTWRAP)) {
|
||||
adjust_viewport(CENTERING);
|
||||
refresh_needed = TRUE;
|
||||
} else {
|
||||
/* If the target line is close to the tail of the file, put the last
|
||||
* line of the file on the bottom line of the screen; otherwise, just
|
||||
@@ -968,9 +933,9 @@ void do_gotolinecolumn(ssize_t line, ssize_t column, bool use_answer,
|
||||
editwinrows / 2) {
|
||||
openfile->current_y = editwinrows - openfile->filebot->lineno +
|
||||
openfile->current->lineno - 1;
|
||||
edit_update(STATIONARY);
|
||||
adjust_viewport(STATIONARY);
|
||||
} else
|
||||
edit_update(CENTERING);
|
||||
adjust_viewport(CENTERING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1238,10 +1203,10 @@ void update_history(filestruct **h, const char *s)
|
||||
/* 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 *foo = *hage;
|
||||
filestruct *oldest = *hage;
|
||||
|
||||
*hage = (*hage)->next;
|
||||
unlink_node(foo);
|
||||
unlink_node(oldest);
|
||||
renumber(*hage);
|
||||
}
|
||||
|
||||
|
||||
493
src/text.c
493
src/text.c
@@ -1,22 +1,25 @@
|
||||
/**************************************************************************
|
||||
* text.c *
|
||||
* text.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2014, 2015 Mark Majeres *
|
||||
* Copyright (C) 2016 Mike Scalora *
|
||||
* Copyright (C) 2015, 2016 Benno Schulenberg *
|
||||
* Copyright (C) 2016 Sumedh Pendurkar *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -40,8 +43,17 @@ static bool prepend_wrap = FALSE;
|
||||
/* Should we prepend wrapped text to the next line? */
|
||||
#endif
|
||||
#ifndef DISABLE_JUSTIFY
|
||||
static filestruct *jusbuffer = NULL;
|
||||
/* The buffer where we store unjustified text. */
|
||||
static filestruct *jusbottom = NULL;
|
||||
/* Pointer to the end of the justify buffer. */
|
||||
/* A pointer to the end of the buffer with unjustified text. */
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
static int pletion_x = 0;
|
||||
/* The x position in pletion_line of the last found completion. */
|
||||
static completion_word *list_of_completions;
|
||||
/* A linked list of the completions that have been attepmted. */
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -49,15 +61,17 @@ static filestruct *jusbottom = NULL;
|
||||
void do_mark(void)
|
||||
{
|
||||
openfile->mark_set = !openfile->mark_set;
|
||||
|
||||
if (openfile->mark_set) {
|
||||
statusbar(_("Mark Set"));
|
||||
openfile->mark_begin = openfile->current;
|
||||
openfile->mark_begin_x = openfile->current_x;
|
||||
openfile->kind_of_mark = HARDMARK;
|
||||
} else {
|
||||
statusbar(_("Mark Unset"));
|
||||
openfile->mark_begin = NULL;
|
||||
openfile->mark_begin_x = 0;
|
||||
edit_refresh();
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
@@ -88,7 +102,7 @@ void do_deletion(undo_type action)
|
||||
|
||||
if (openfile->current->data[openfile->current_x] != '\0') {
|
||||
/* We're in the middle of a line: delete the current character. */
|
||||
int char_buf_len = parse_mbchar(openfile->current->data +
|
||||
int char_len = parse_mbchar(openfile->current->data +
|
||||
openfile->current_x, NULL, NULL);
|
||||
size_t line_len = strlen(openfile->current->data +
|
||||
openfile->current_x);
|
||||
@@ -104,16 +118,16 @@ void do_deletion(undo_type action)
|
||||
|
||||
/* Move the remainder of the line "in", over the current character. */
|
||||
charmove(&openfile->current->data[openfile->current_x],
|
||||
&openfile->current->data[openfile->current_x + char_buf_len],
|
||||
line_len - char_buf_len + 1);
|
||||
&openfile->current->data[openfile->current_x + char_len],
|
||||
line_len - char_len + 1);
|
||||
null_at(&openfile->current->data, openfile->current_x +
|
||||
line_len - char_buf_len);
|
||||
line_len - char_len);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Adjust the mark if it is after the cursor on the current line. */
|
||||
if (openfile->mark_set && openfile->mark_begin == openfile->current &&
|
||||
openfile->mark_begin_x > openfile->current_x)
|
||||
openfile->mark_begin_x -= char_buf_len;
|
||||
openfile->mark_begin_x -= char_len;
|
||||
#endif
|
||||
/* Adjust the file size. */
|
||||
openfile->totsize--;
|
||||
@@ -165,8 +179,12 @@ void do_deletion(undo_type action)
|
||||
return;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
ensure_line_is_visible();
|
||||
|
||||
/* If the number of screen rows that a softwrapped line occupies
|
||||
* has changed, we need a full refresh. */
|
||||
if (ISSET(SOFTWRAP) && refresh_needed == FALSE)
|
||||
if (strlenpt(openfile->current->data) / COLS != orig_lenpt / COLS)
|
||||
if (strlenpt(openfile->current->data) / editwincols != orig_lenpt / editwincols)
|
||||
refresh_needed = TRUE;
|
||||
#endif
|
||||
|
||||
@@ -247,25 +265,18 @@ void do_tab(void)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(TABS_TO_SPACES)) {
|
||||
char *output;
|
||||
size_t output_len = 0, new_pww = xplustabs();
|
||||
char *spaces = charalloc(tabsize + 1);
|
||||
size_t length = tabsize - (xplustabs() % tabsize);
|
||||
|
||||
do {
|
||||
new_pww++;
|
||||
output_len++;
|
||||
} while (new_pww % tabsize != 0);
|
||||
charset(spaces, ' ', length);
|
||||
spaces[length] = '\0';
|
||||
|
||||
output = charalloc(output_len + 1);
|
||||
do_output(spaces, length, TRUE);
|
||||
|
||||
charset(output, ' ', output_len);
|
||||
output[output_len] = '\0';
|
||||
|
||||
do_output(output, output_len, TRUE);
|
||||
|
||||
free(output);
|
||||
free(spaces);
|
||||
} else
|
||||
#endif
|
||||
do_output((char *) "\t", 1, TRUE);
|
||||
do_output((char *)"\t", 1, TRUE);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -306,7 +317,7 @@ void do_indent(ssize_t cols)
|
||||
/* If the mark is on, use all lines covered by the mark. */
|
||||
if (openfile->mark_set)
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
/* Otherwise, use the current line. */
|
||||
else {
|
||||
top = openfile->current;
|
||||
@@ -413,7 +424,6 @@ void do_indent(ssize_t cols)
|
||||
/* Throw away the undo stack, to prevent making mistakes when
|
||||
* the user tries to undo something in the reindented text. */
|
||||
discard_until(NULL, openfile);
|
||||
openfile->current_undo = NULL;
|
||||
|
||||
/* Mark the file as modified. */
|
||||
set_modified();
|
||||
@@ -438,7 +448,6 @@ void do_unindent(void)
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#ifdef ENABLE_COMMENT
|
||||
/* Test whether the string is empty or consists of only blanks. */
|
||||
bool white_string(const char *s)
|
||||
{
|
||||
@@ -448,6 +457,7 @@ bool white_string(const char *s)
|
||||
return !*s;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_COMMENT
|
||||
/* Comment or uncomment the current line or the marked lines. */
|
||||
void do_comment()
|
||||
{
|
||||
@@ -472,8 +482,8 @@ void do_comment()
|
||||
|
||||
/* Determine which lines to work on. */
|
||||
if (openfile->mark_set)
|
||||
mark_order((const filestruct **) &top, &top_x,
|
||||
(const filestruct **) &bot, &bot_x, NULL);
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
else {
|
||||
top = openfile->current;
|
||||
bot = top;
|
||||
@@ -809,7 +819,7 @@ void do_undo(void)
|
||||
break;
|
||||
}
|
||||
|
||||
if (undidmsg)
|
||||
if (undidmsg && !pletion_line)
|
||||
statusline(HUSH, _("Undid action (%s)"), undidmsg);
|
||||
|
||||
renumber(f);
|
||||
@@ -969,8 +979,8 @@ void do_redo(void)
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Someone hits Enter *gasp!* */
|
||||
void do_enter()
|
||||
/* Break the current line at the cursor position. */
|
||||
void do_enter(void)
|
||||
{
|
||||
filestruct *newnode = make_new_node(openfile->current);
|
||||
size_t extra = 0;
|
||||
@@ -980,45 +990,48 @@ void do_enter()
|
||||
#ifndef NANO_TINY
|
||||
add_undo(ENTER);
|
||||
|
||||
/* Do auto-indenting, like the neolithic Turbo Pascal editor. */
|
||||
if (ISSET(AUTOINDENT)) {
|
||||
/* If we are breaking the line in the indentation, the new
|
||||
* indentation should have only current_x characters, and
|
||||
* current_x should not change. */
|
||||
extra = indent_length(openfile->current->data);
|
||||
|
||||
/* If we are breaking the line in the indentation, limit the new
|
||||
* indentation to the current x position. */
|
||||
if (extra > openfile->current_x)
|
||||
extra = openfile->current_x;
|
||||
}
|
||||
#endif
|
||||
newnode->data = charalloc(strlen(openfile->current->data +
|
||||
openfile->current_x) + extra + 1);
|
||||
openfile->current_x) + extra + 1);
|
||||
strcpy(&newnode->data[extra], openfile->current->data +
|
||||
openfile->current_x);
|
||||
openfile->current_x);
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(AUTOINDENT)) {
|
||||
/* Copy the whitespace from the current line to the new one. */
|
||||
strncpy(newnode->data, openfile->current->data, extra);
|
||||
openfile->totsize += extra;
|
||||
}
|
||||
#endif
|
||||
|
||||
null_at(&openfile->current->data, openfile->current_x);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Adjust the mark if it was on the current line after the cursor. */
|
||||
if (openfile->mark_set && openfile->current == openfile->mark_begin &&
|
||||
openfile->current_x < openfile->mark_begin_x) {
|
||||
openfile->mark_begin = newnode;
|
||||
openfile->mark_begin_x += extra - openfile->current_x;
|
||||
}
|
||||
#endif
|
||||
openfile->current_x = extra;
|
||||
|
||||
splice_node(openfile->current, newnode);
|
||||
openfile->current = newnode;
|
||||
renumber(newnode);
|
||||
|
||||
openfile->current = newnode;
|
||||
openfile->current_x = extra;
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
openfile->totsize++;
|
||||
set_modified();
|
||||
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
update_undo(ENTER);
|
||||
#endif
|
||||
@@ -1141,6 +1154,9 @@ void discard_until(const undo *thisitem, openfilestruct *thefile)
|
||||
dropit = thefile->undotop;
|
||||
}
|
||||
|
||||
/* Adjust the pointer to the top of the undo stack. */
|
||||
thefile->current_undo = (undo *)thisitem;
|
||||
|
||||
/* Prevent a chain of editing actions from continuing. */
|
||||
thefile->last_action = OTHER;
|
||||
}
|
||||
@@ -1202,16 +1218,18 @@ void add_undo(undo_type action)
|
||||
case BACK:
|
||||
/* If the next line is the magic line, don't ever undo this
|
||||
* backspace, as it won't actually have deleted anything. */
|
||||
if (openfile->current->next == openfile->filebot && openfile->current->data[0] != '\0')
|
||||
if (openfile->current->next == openfile->filebot &&
|
||||
openfile->current->data[0] != '\0')
|
||||
u->xflags = WAS_FINAL_BACKSPACE;
|
||||
case DEL:
|
||||
if (u->begin != strlen(openfile->current->data)) {
|
||||
if (openfile->current->data[openfile->current_x] != '\0') {
|
||||
char *char_buf = charalloc(mb_cur_max() + 1);
|
||||
int char_buf_len = parse_mbchar(&openfile->current->data[u->begin], char_buf, NULL);
|
||||
null_at(&char_buf, char_buf_len);
|
||||
int char_len = parse_mbchar(&openfile->current->data[u->begin],
|
||||
char_buf, NULL);
|
||||
null_at(&char_buf, char_len);
|
||||
u->strdata = char_buf;
|
||||
if (u->type == BACK)
|
||||
u->mark_begin_x += char_buf_len;
|
||||
u->mark_begin_x += char_len;
|
||||
break;
|
||||
}
|
||||
/* Else purposely fall into the line-joining code. */
|
||||
@@ -1339,8 +1357,8 @@ fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openf
|
||||
openfile->current->data, (unsigned long)openfile->current_x, (unsigned long)u->begin);
|
||||
#endif
|
||||
char *char_buf = charalloc(mb_cur_max());
|
||||
size_t char_buf_len = parse_mbchar(&openfile->current->data[u->mark_begin_x], char_buf, NULL);
|
||||
u->strdata = addstrings(u->strdata, u->strdata ? strlen(u->strdata) : 0, char_buf, char_buf_len);
|
||||
int char_len = parse_mbchar(&openfile->current->data[u->mark_begin_x], char_buf, NULL);
|
||||
u->strdata = addstrings(u->strdata, u->strdata ? strlen(u->strdata) : 0, char_buf, char_len);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " >> current undo data is \"%s\"\n", u->strdata);
|
||||
#endif
|
||||
@@ -1350,21 +1368,15 @@ fprintf(stderr, " >> Updating... action = %d, openfile->last_action = %d, openf
|
||||
}
|
||||
case BACK:
|
||||
case DEL: {
|
||||
/* Add the removed character after or before earlier removed stuff. */
|
||||
char *char_buf = charalloc(mb_cur_max());
|
||||
size_t char_buf_len = parse_mbchar(&openfile->current->data[openfile->current_x], char_buf, NULL);
|
||||
if (openfile->current_x == u->begin) {
|
||||
/* They're deleting. */
|
||||
u->strdata = addstrings(u->strdata, strlen(u->strdata), char_buf, char_buf_len);
|
||||
int char_len = parse_mbchar(&openfile->current->data[openfile->current_x], char_buf, NULL);
|
||||
if (action == DEL) {
|
||||
u->strdata = addstrings(u->strdata, strlen(u->strdata), char_buf, char_len);
|
||||
u->mark_begin_x = openfile->current_x;
|
||||
} else if (openfile->current_x == u->begin - char_buf_len) {
|
||||
/* They're backspacing. */
|
||||
u->strdata = addstrings(char_buf, char_buf_len, u->strdata, strlen(u->strdata));
|
||||
u->begin = openfile->current_x;
|
||||
} else {
|
||||
/* They deleted something else on the line. */
|
||||
free(char_buf);
|
||||
add_undo(u->type);
|
||||
return;
|
||||
u->strdata = addstrings(char_buf, char_len, u->strdata, strlen(u->strdata));
|
||||
u->begin = openfile->current_x;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " >> current undo data is \"%s\"\nu->begin = %lu\n", u->strdata, (unsigned long)u->begin);
|
||||
@@ -1981,12 +1993,9 @@ bool begpar(const filestruct *const foo)
|
||||
|
||||
/* Case 2) or 5) or 4). */
|
||||
if (foo->prev->data[quote_len + temp_id_len] == '\0' ||
|
||||
(quote_len == 0 && indent_len > 0
|
||||
#ifndef NANO_TINY
|
||||
&& !ISSET(AUTOINDENT)
|
||||
#endif
|
||||
) || !indents_match(foo->prev->data + quote_len, temp_id_len,
|
||||
foo->data + quote_len, indent_len))
|
||||
(quote_len == 0 && indent_len > 0 && !ISSET(AUTOINDENT)) ||
|
||||
!indents_match(foo->prev->data + quote_len, temp_id_len,
|
||||
foo->data + quote_len, indent_len))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
@@ -2037,7 +2046,7 @@ void backup_lines(filestruct *first_line, size_t par_len)
|
||||
* current and filebot if filebot is the last line in the
|
||||
* paragraph. */
|
||||
assert(par_len > 0 && openfile->current->lineno + par_len <=
|
||||
openfile->filebot->lineno + 1);
|
||||
openfile->filebot->lineno + 1);
|
||||
|
||||
/* Move bot down par_len lines to the line after the last line of
|
||||
* the paragraph, if there is one. */
|
||||
@@ -2047,7 +2056,7 @@ void backup_lines(filestruct *first_line, size_t par_len)
|
||||
/* Move the paragraph from the current buffer's filestruct to the
|
||||
* justify buffer. */
|
||||
move_to_filestruct(&jusbuffer, &jusbottom, top, 0, bot,
|
||||
(i == 1 && bot == openfile->filebot) ? strlen(bot->data) : 0);
|
||||
(i == 1 && bot == openfile->filebot) ? strlen(bot->data) : 0);
|
||||
|
||||
/* Copy the paragraph back to the current buffer's filestruct from
|
||||
* the justify buffer. */
|
||||
@@ -2281,8 +2290,7 @@ void do_justify(bool full_justify)
|
||||
if (first_par_line == NULL) {
|
||||
backup_lines(openfile->current, full_justify ?
|
||||
openfile->filebot->lineno - openfile->current->lineno +
|
||||
((openfile->filebot->data[0] != '\0') ? 1 : 0) :
|
||||
par_len);
|
||||
((openfile->filebot->data[0] != '\0') ? 1 : 0) : par_len);
|
||||
first_par_line = openfile->current;
|
||||
}
|
||||
|
||||
@@ -2336,8 +2344,7 @@ void do_justify(bool full_justify)
|
||||
|
||||
/* We're just about to tack the next line onto this one. If
|
||||
* this line isn't empty, make sure it ends in a space. */
|
||||
if (line_len > 0 &&
|
||||
openfile->current->data[line_len - 1] != ' ') {
|
||||
if (line_len > 0 && openfile->current->data[line_len - 1] != ' ') {
|
||||
line_len++;
|
||||
openfile->current->data =
|
||||
charealloc(openfile->current->data, line_len + 1);
|
||||
@@ -2352,8 +2359,7 @@ void do_justify(bool full_justify)
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If needed, adjust the coordinates of the mark. */
|
||||
if (openfile->mark_set &&
|
||||
openfile->mark_begin == next_line) {
|
||||
if (openfile->mark_set && openfile->mark_begin == next_line) {
|
||||
openfile->mark_begin = openfile->current;
|
||||
openfile->mark_begin_x += line_len - indent_len;
|
||||
}
|
||||
@@ -2405,11 +2411,7 @@ void do_justify(bool full_justify)
|
||||
/* If this paragraph is non-quoted, and autoindent isn't
|
||||
* turned on, set the indentation length to zero so that the
|
||||
* indentation is treated as part of the line. */
|
||||
if (quote_len == 0
|
||||
#ifndef NANO_TINY
|
||||
&& !ISSET(AUTOINDENT)
|
||||
#endif
|
||||
)
|
||||
if (quote_len == 0 && !ISSET(AUTOINDENT))
|
||||
indent_len = 0;
|
||||
|
||||
/* Insert a new line after the current one. */
|
||||
@@ -2465,9 +2467,8 @@ void do_justify(bool full_justify)
|
||||
} else
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
|
||||
/* Renumber the lines of the now-justified current paragraph,
|
||||
* since both find_paragraph() and edit_refresh() need the line
|
||||
* numbers to be right. */
|
||||
/* Renumber the now-justified paragraph, since both refreshing the
|
||||
* edit window and finding a paragraph need correct line numbers. */
|
||||
renumber(curr_first_par_line);
|
||||
|
||||
/* We've just finished justifying the paragraph. If we're not
|
||||
@@ -2516,35 +2517,28 @@ void do_justify(bool full_justify)
|
||||
|| func == do_undo
|
||||
#endif
|
||||
) {
|
||||
/* Splice the justify buffer back into the file, but only if we
|
||||
* actually justified something. */
|
||||
/* If we actually justified something, then splice the preserved
|
||||
* unjustified text back into the file, */
|
||||
if (first_par_line != NULL) {
|
||||
filestruct *top_save;
|
||||
|
||||
/* Partition the filestruct so that it contains only the
|
||||
* text of the justified paragraph. */
|
||||
filepart = partition_filestruct(first_par_line, 0,
|
||||
last_par_line, filebot_inpar ?
|
||||
strlen(last_par_line->data) : 0);
|
||||
last_par_line, filebot_inpar ?
|
||||
strlen(last_par_line->data) : 0);
|
||||
|
||||
/* Remove the text of the justified paragraph, and
|
||||
* replace it with the text in the justify buffer. */
|
||||
/* Throw away the justified paragraph, and replace it with
|
||||
* the preserved unjustified text. */
|
||||
free_filestruct(openfile->fileage);
|
||||
openfile->fileage = jusbuffer;
|
||||
openfile->filebot = jusbottom;
|
||||
|
||||
top_save = openfile->fileage;
|
||||
|
||||
/* Unpartition the filestruct so that it contains all the
|
||||
* text again. Note that the justified paragraph has been
|
||||
* replaced with the unjustified paragraph. */
|
||||
/* Unpartition the filestruct, to contain the entire text again. */
|
||||
unpartition_filestruct(&filepart);
|
||||
|
||||
/* Renumber, starting with the beginning line of the old
|
||||
* partition. */
|
||||
renumber(top_save);
|
||||
/* Renumber, from the beginning of the unjustified part. */
|
||||
renumber(jusbuffer);
|
||||
|
||||
/* Restore the justify we just did (ungrateful user!). */
|
||||
/* Restore the old position, the size, and the mark. */
|
||||
openfile->edittop = edittop_save;
|
||||
openfile->current = current_save;
|
||||
openfile->current_x = current_x_save;
|
||||
@@ -2556,17 +2550,14 @@ void do_justify(bool full_justify)
|
||||
}
|
||||
#endif
|
||||
openfile->modified = modified_save;
|
||||
|
||||
/* Clear the justify buffer. */
|
||||
jusbuffer = NULL;
|
||||
|
||||
if (!openfile->modified)
|
||||
titlebar(NULL);
|
||||
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
} else {
|
||||
/* Put the keystroke back into the queue. */
|
||||
unget_kbinput(kbinput, meta_key, func_key);
|
||||
unget_kbinput(kbinput, meta_key);
|
||||
|
||||
/* Set the desired screen column (always zero, except at EOF). */
|
||||
openfile->placewewant = xplustabs();
|
||||
@@ -2575,13 +2566,14 @@ void do_justify(bool full_justify)
|
||||
/* Throw away the entire undo stack, to prevent a crash when
|
||||
* the user tries to undo something in the justified text. */
|
||||
discard_until(NULL, openfile);
|
||||
openfile->current_undo = NULL;
|
||||
#endif
|
||||
/* Blow away the text in the justify buffer. */
|
||||
/* Blow away the unjustified text. */
|
||||
free_filestruct(jusbuffer);
|
||||
jusbuffer = NULL;
|
||||
}
|
||||
|
||||
/* Mark the buffer for unjustified text as empty. */
|
||||
jusbuffer = NULL;
|
||||
|
||||
blank_statusbar();
|
||||
|
||||
/* Display the shortcut list with UnCut. */
|
||||
@@ -2630,17 +2622,10 @@ bool do_int_spell_fix(const char *word)
|
||||
/* Save the settings of the global flags. */
|
||||
memcpy(stash, flags, sizeof(flags));
|
||||
|
||||
/* Make sure spell-check is case sensitive. */
|
||||
/* Do the spell checking case sensitive, forward, and without regexes. */
|
||||
SET(CASE_SENSITIVE);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Make sure spell-check goes forward only. */
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
#endif
|
||||
#ifdef HAVE_REGEX_H
|
||||
/* Make sure spell-check doesn't use regular expressions. */
|
||||
UNSET(USE_REGEXP);
|
||||
#endif
|
||||
|
||||
/* Save the current search string, then set it to the misspelled word. */
|
||||
save_search = last_search;
|
||||
@@ -2650,7 +2635,7 @@ bool do_int_spell_fix(const char *word)
|
||||
/* If the mark is on, start at the beginning of the marked region. */
|
||||
if (old_mark_set) {
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
/* If the region is marked normally, swap the end points, so that
|
||||
* (current, current_x) (where searching starts) is at the top. */
|
||||
if (right_side_up) {
|
||||
@@ -2671,16 +2656,17 @@ bool do_int_spell_fix(const char *word)
|
||||
}
|
||||
|
||||
/* Find the first whole occurrence of word. */
|
||||
result = findnextstr(TRUE, NULL, 0, word, NULL);
|
||||
result = findnextstr(word, TRUE, NULL, NULL, 0);
|
||||
|
||||
/* The word must exist; if not, something is wrong. */
|
||||
if (result == 0)
|
||||
statusline(ALERT, "Internal error: "
|
||||
"speller listed unfindable word: %s", word);
|
||||
else if (result == 1) {
|
||||
/* If the word isn't found, alert the user; if it is, allow correction. */
|
||||
if (result == 0) {
|
||||
statusline(ALERT, _("Unfindable word: %s"), word);
|
||||
lastmessage = HUSH;
|
||||
proceed = TRUE;
|
||||
napms(2800);
|
||||
} else if (result == 1) {
|
||||
exp_word = display_string(openfile->current->data, xplustabs(),
|
||||
strlenpt(word), FALSE);
|
||||
|
||||
edit_refresh();
|
||||
|
||||
spotlight(TRUE, exp_word);
|
||||
@@ -2707,7 +2693,7 @@ bool do_int_spell_fix(const char *word)
|
||||
/* Replacements should happen only in the marked region. */
|
||||
openfile->mark_set = old_mark_set;
|
||||
#endif
|
||||
do_replace_loop(TRUE, current_save, ¤t_x_save, word);
|
||||
do_replace_loop(word, TRUE, current_save, ¤t_x_save);
|
||||
|
||||
/* TRANSLATORS: Shown after fixing misspellings in one word. */
|
||||
statusbar(_("Next word..."));
|
||||
@@ -2933,6 +2919,7 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
{
|
||||
int alt_spell_status;
|
||||
size_t current_x_save = openfile->current_x;
|
||||
size_t pww_save = openfile->placewewant;
|
||||
ssize_t current_y_save = openfile->current_y;
|
||||
ssize_t lineno_save = openfile->current->lineno;
|
||||
struct stat spellfileinfo;
|
||||
@@ -3030,7 +3017,7 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
if (old_mark_set) {
|
||||
/* Trim the filestruct so that it contains only the marked text. */
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
(const filestruct **)&bot, &bot_x, &right_side_up);
|
||||
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
||||
|
||||
/* Foresay whether a magicline will be added when the
|
||||
@@ -3049,6 +3036,11 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
#ifndef NANO_TINY
|
||||
if (old_mark_set) {
|
||||
filestruct *top_save = openfile->fileage;
|
||||
|
||||
/* If a magicline was added, remove it again. */
|
||||
if (added_magicline)
|
||||
remove_magicline();
|
||||
|
||||
/* Adjust the end point of the marked region for any change in
|
||||
* length of the region's last line. */
|
||||
if (right_side_up)
|
||||
@@ -3056,10 +3048,6 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
else
|
||||
openfile->mark_begin_x = strlen(openfile->filebot->data);
|
||||
|
||||
/* If a magicline was added, remove it again. */
|
||||
if (added_magicline)
|
||||
remove_magicline();
|
||||
|
||||
/* Unpartition the filestruct so that it contains all the text
|
||||
* again. Note that we've replaced the marked text originally
|
||||
* in the partition with the spell-checked marked text in the
|
||||
@@ -3080,15 +3068,21 @@ const char *do_alt_speller(char *tempfile_name)
|
||||
|
||||
/* Go back to the old position. */
|
||||
goto_line_posx(lineno_save, current_x_save);
|
||||
if (openfile->current_x > strlen(openfile->current->data))
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
openfile->current_y = current_y_save;
|
||||
edit_update(STATIONARY);
|
||||
openfile->placewewant = pww_save;
|
||||
adjust_viewport(STATIONARY);
|
||||
|
||||
/* Stat the temporary file again, and mark the buffer as modified only
|
||||
* if this file was changed since it was written. */
|
||||
stat(tempfile_name, &spellfileinfo);
|
||||
if (spellfileinfo.st_mtime != timestamp)
|
||||
if (spellfileinfo.st_mtime != timestamp) {
|
||||
set_modified();
|
||||
|
||||
/* Flush the undo stack, to avoid making a mess when the user
|
||||
* tries to undo things in spell-corrected lines. */
|
||||
discard_until(NULL, openfile);
|
||||
}
|
||||
#ifndef NANO_TINY
|
||||
/* Unblock SIGWINCHes again. */
|
||||
allow_sigwinch(TRUE);
|
||||
@@ -3114,7 +3108,7 @@ void do_spell(void)
|
||||
temp = safe_tempfile(&temp_file);
|
||||
|
||||
if (temp == NULL) {
|
||||
statusline(HUSH, _("Error writing temp file: %s"), strerror(errno));
|
||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3126,7 +3120,7 @@ void do_spell(void)
|
||||
status = write_file(temp, temp_file, TRUE, OVERWRITE, FALSE);
|
||||
|
||||
if (!status) {
|
||||
statusline(HUSH, _("Error writing temp file: %s"), strerror(errno));
|
||||
statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
|
||||
free(temp);
|
||||
return;
|
||||
}
|
||||
@@ -3139,8 +3133,6 @@ void do_spell(void)
|
||||
unlink(temp);
|
||||
free(temp);
|
||||
|
||||
currmenu = MMAIN;
|
||||
|
||||
/* If the spell-checker printed any error messages onscreen, make
|
||||
* sure that they're cleared off. */
|
||||
total_refresh();
|
||||
@@ -3187,16 +3179,16 @@ void do_linter(void)
|
||||
|
||||
if (i == -1) {
|
||||
statusbar(_("Cancelled"));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
} else if (i == 1 && (do_writeout(FALSE) != TRUE))
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
lintcopy = mallocstrcpy(NULL, openfile->syntax->linter);
|
||||
/* Create a pipe up front. */
|
||||
if (pipe(lint_fd) == -1) {
|
||||
statusbar(_("Could not create pipe"));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
blank_bottombars();
|
||||
@@ -3244,14 +3236,14 @@ void do_linter(void)
|
||||
if (pid_lint < 0) {
|
||||
close(lint_fd[0]);
|
||||
statusbar(_("Could not fork"));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the system pipe buffer size. */
|
||||
if ((pipe_buff_size = fpathconf(lint_fd[0], _PC_PIPE_BUF)) < 1) {
|
||||
close(lint_fd[0]);
|
||||
statusbar(_("Could not get size of pipe buffer"));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read in the returned syntax errors. */
|
||||
@@ -3349,7 +3341,7 @@ void do_linter(void)
|
||||
|
||||
if (!WIFEXITED(lint_status) || WEXITSTATUS(lint_status) > 2) {
|
||||
statusbar(invocation_error(openfile->syntax->linter));
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
free(read_buff);
|
||||
@@ -3357,7 +3349,7 @@ void do_linter(void)
|
||||
if (parsesuccess == 0) {
|
||||
statusline(HUSH, _("Got 0 parsable lines from command: %s"),
|
||||
openfile->syntax->linter);
|
||||
goto exit_from_lint;
|
||||
return;
|
||||
}
|
||||
|
||||
bottombars(MLINTER);
|
||||
@@ -3388,8 +3380,6 @@ void do_linter(void)
|
||||
sprintf(msg, _("This message is for unopened file %s,"
|
||||
" open it in a new buffer?"),
|
||||
curlint->filename);
|
||||
/* Show a cursor after the question. */
|
||||
curs_set(1);
|
||||
i = do_yesno_prompt(FALSE, msg);
|
||||
free(msg);
|
||||
if (i == -1) {
|
||||
@@ -3421,8 +3411,9 @@ void do_linter(void)
|
||||
bottombars(MLINTER);
|
||||
}
|
||||
|
||||
/* Show the cursor to indicate the affected line. */
|
||||
/* Place and show the cursor to indicate the affected line. */
|
||||
reset_cursor();
|
||||
wnoutrefresh(edit);
|
||||
curs_set(1);
|
||||
|
||||
kbinput = get_kbinput(bottomwin);
|
||||
@@ -3464,9 +3455,6 @@ void do_linter(void)
|
||||
free(tmplint->filename);
|
||||
free(tmplint);
|
||||
}
|
||||
|
||||
exit_from_lint:
|
||||
display_main_list();
|
||||
}
|
||||
|
||||
#ifndef DISABLE_SPELLER
|
||||
@@ -3557,14 +3545,20 @@ void do_formatter(void)
|
||||
/* Replace the text of the current buffer with the formatted text. */
|
||||
replace_buffer(temp);
|
||||
|
||||
/* Restore the cursor position, and mark the file as modified. */
|
||||
/* Restore the cursor position. */
|
||||
goto_line_posx(lineno_save, current_x_save);
|
||||
if (openfile->current_x > strlen(openfile->current->data))
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
openfile->current_y = current_y_save;
|
||||
openfile->placewewant = pww_save;
|
||||
edit_update(STATIONARY);
|
||||
adjust_viewport(STATIONARY);
|
||||
|
||||
set_modified();
|
||||
|
||||
/* Flush the undo stack, to avoid a mess or crash when
|
||||
* the user tries to undo things in reformatted lines. */
|
||||
discard_until(NULL, openfile);
|
||||
|
||||
finalstatus = _("Finished formatting");
|
||||
}
|
||||
|
||||
@@ -3606,7 +3600,7 @@ void do_wordlinechar_count(void)
|
||||
* contains only the marked text, and turn the mark off. */
|
||||
if (old_mark_set) {
|
||||
mark_order((const filestruct **)&top, &top_x,
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
(const filestruct **)&bot, &bot_x, NULL);
|
||||
filepart = partition_filestruct(top, top_x, bot, bot_x);
|
||||
openfile->mark_set = FALSE;
|
||||
}
|
||||
@@ -3693,3 +3687,176 @@ void do_verbatim_input(void)
|
||||
|
||||
free(output);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
/* Copy the found completion candidate. */
|
||||
char *copy_completion(char *check_line, int start)
|
||||
{
|
||||
char *word;
|
||||
int position = start, len_of_word = 0, index = 0;
|
||||
|
||||
/* Find the length of the word by travelling to its end. */
|
||||
while (is_word_mbchar(&check_line[position], FALSE)) {
|
||||
int next = move_mbright(check_line, position);
|
||||
len_of_word += next - position;
|
||||
position = next;
|
||||
}
|
||||
|
||||
word = (char *)nmalloc((len_of_word + 1) * sizeof(char));
|
||||
|
||||
/* Simply copy the word. */
|
||||
while (index < len_of_word)
|
||||
word[index++] = check_line[start++];
|
||||
|
||||
word[index] = '\0';
|
||||
return word;
|
||||
}
|
||||
|
||||
/* Look at the fragment the user has typed, then search the current buffer for
|
||||
* the first word that starts with this fragment, and tentatively complete the
|
||||
* fragment. If the user types 'Complete' again, search and paste the next
|
||||
* possible completion. */
|
||||
void complete_a_word(void)
|
||||
{
|
||||
char *shard, *completion = NULL;
|
||||
int start_of_shard, shard_length = 0;
|
||||
int i = 0, j = 0;
|
||||
completion_word *some_word;
|
||||
bool was_set_wrapping = !ISSET(NO_WRAP);
|
||||
|
||||
/* If this is a fresh completion attempt... */
|
||||
if (pletion_line == NULL) {
|
||||
/* Clear the list of words of a previous completion run. */
|
||||
while (list_of_completions != NULL) {
|
||||
completion_word *dropit = list_of_completions;
|
||||
list_of_completions = list_of_completions->next;
|
||||
free(dropit->word);
|
||||
free(dropit);
|
||||
}
|
||||
|
||||
/* Prevent a completion from being merged with typed text. */
|
||||
openfile->last_action = OTHER;
|
||||
|
||||
/* Initialize the starting point for searching. */
|
||||
pletion_line = openfile->fileage;
|
||||
pletion_x = 0;
|
||||
|
||||
/* Wipe the "No further matches" message. */
|
||||
blank_statusbar();
|
||||
wnoutrefresh(bottomwin);
|
||||
} else {
|
||||
/* Remove the attempted completion from the buffer. */
|
||||
do_undo();
|
||||
}
|
||||
|
||||
/* Find the start of the fragment that the user typed. */
|
||||
start_of_shard = openfile->current_x;
|
||||
while (start_of_shard > 0) {
|
||||
int step_left = move_mbleft(openfile->current->data, start_of_shard);
|
||||
|
||||
if (!is_word_mbchar(&openfile->current->data[step_left], FALSE))
|
||||
break;
|
||||
start_of_shard = step_left;
|
||||
}
|
||||
|
||||
/* If there is no word fragment before the cursor, do nothing. */
|
||||
if (start_of_shard == openfile->current_x) {
|
||||
pletion_line = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
shard = (char *)nmalloc((openfile->current_x - start_of_shard + 1) * sizeof(char));
|
||||
|
||||
/* Copy the fragment that has to be searched for. */
|
||||
while (start_of_shard < openfile->current_x)
|
||||
shard[shard_length++] = openfile->current->data[start_of_shard++];
|
||||
shard[shard_length] = '\0';
|
||||
|
||||
/* Run through all of the lines in the buffer, looking for shard. */
|
||||
while (pletion_line != NULL) {
|
||||
int threshold = strlen(pletion_line->data) - shard_length - 1;
|
||||
/* The point where we can stop searching for shard. */
|
||||
|
||||
/* Traverse the whole line, looking for shard. */
|
||||
for (i = pletion_x; i < threshold; i++) {
|
||||
/* If the first byte doesn't match, run on. */
|
||||
if (pletion_line->data[i] != shard[0])
|
||||
continue;
|
||||
|
||||
/* Compare the rest of the bytes in shard. */
|
||||
for (j = 1; j < shard_length; j++)
|
||||
if (pletion_line->data[i + j] != shard[j])
|
||||
break;
|
||||
|
||||
/* If not all of the bytes matched, continue searching. */
|
||||
if (j < shard_length)
|
||||
continue;
|
||||
|
||||
/* If the found match is not /longer/ than shard, skip it. */
|
||||
if (!is_word_mbchar(&pletion_line->data[i + j], FALSE))
|
||||
continue;
|
||||
|
||||
/* If the match is not a separate word, skip it. */
|
||||
if (i > 0 && is_word_mbchar(&pletion_line->data[
|
||||
move_mbleft(pletion_line->data, i)], FALSE))
|
||||
continue;
|
||||
|
||||
/* If this match is the shard itself, ignore it. */
|
||||
if (pletion_line == openfile->current &&
|
||||
i == openfile->current_x - shard_length)
|
||||
continue;
|
||||
|
||||
completion = copy_completion(pletion_line->data, i);
|
||||
|
||||
/* Look among earlier attempted completions for a duplicate. */
|
||||
some_word = list_of_completions;
|
||||
while (some_word && strcmp(some_word->word, completion) != 0)
|
||||
some_word = some_word->next;
|
||||
|
||||
/* If we've already tried this word, skip it. */
|
||||
if (some_word != NULL) {
|
||||
free(completion);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add the found word to the list of completions. */
|
||||
some_word = (completion_word *)nmalloc(sizeof(completion_word));
|
||||
some_word->word = completion;
|
||||
some_word->next = list_of_completions;
|
||||
list_of_completions = some_word;
|
||||
|
||||
/* Temporarily disable wrapping so only one undo item is added. */
|
||||
SET(NO_WRAP);
|
||||
|
||||
/* Inject the completion into the buffer. */
|
||||
do_output(&completion[shard_length],
|
||||
strlen(completion) - shard_length, FALSE);
|
||||
|
||||
/* If needed, reenable wrapping and wrap the current line. */
|
||||
if (was_set_wrapping) {
|
||||
UNSET(NO_WRAP);
|
||||
do_wrap(openfile->current);
|
||||
}
|
||||
|
||||
/* Set the position for a possible next search attempt. */
|
||||
pletion_x = ++i;
|
||||
|
||||
free(shard);
|
||||
return;
|
||||
}
|
||||
|
||||
pletion_line = pletion_line->next;
|
||||
pletion_x = 0;
|
||||
}
|
||||
|
||||
/* The search has reached the end of the file. */
|
||||
if (list_of_completions != NULL) {
|
||||
statusline(ALERT, _("No further matches"));
|
||||
refresh_needed = TRUE;
|
||||
} else
|
||||
/* TRANSLATORS: Shown when there are zero possible completions. */
|
||||
statusline(ALERT, _("No matches"));
|
||||
|
||||
free(shard);
|
||||
}
|
||||
#endif /* ENABLE_WORDCOMPLETION */
|
||||
|
||||
243
src/utils.c
243
src/utils.c
@@ -1,22 +1,22 @@
|
||||
/**************************************************************************
|
||||
* utils.c *
|
||||
* utils.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
|
||||
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
|
||||
* This program 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, or (at your option) *
|
||||
* any later version. *
|
||||
* Copyright (C) 2016 Benno Schulenberg *
|
||||
* *
|
||||
* This program 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. *
|
||||
* 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, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
|
||||
* 02110-1301, USA. *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -52,6 +52,39 @@ void get_homedir(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
/* Return the number of digits that the given integer n takes up. */
|
||||
int digits(ssize_t n)
|
||||
{
|
||||
if (n < 100000) {
|
||||
if (n < 1000) {
|
||||
if (n < 100)
|
||||
return 2;
|
||||
else
|
||||
return 3;
|
||||
} else {
|
||||
if (n < 10000)
|
||||
return 4;
|
||||
else
|
||||
return 5;
|
||||
}
|
||||
} else {
|
||||
if (n < 10000000) {
|
||||
if (n < 1000000)
|
||||
return 6;
|
||||
else
|
||||
return 7;
|
||||
}
|
||||
else {
|
||||
if (n < 100000000)
|
||||
return 8;
|
||||
else
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read a ssize_t from str, and store it in *val (if val is not NULL).
|
||||
* On error, we return FALSE and don't change *val. Otherwise, we
|
||||
* return TRUE. */
|
||||
@@ -60,8 +93,6 @@ bool parse_num(const char *str, ssize_t *val)
|
||||
char *first_error;
|
||||
ssize_t j;
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
/* The manual page for strtol() says this is required, and
|
||||
* it looks like it is! */
|
||||
errno = 0;
|
||||
@@ -77,44 +108,40 @@ bool parse_num(const char *str, ssize_t *val)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read two ssize_t's, separated by a comma, from str, and store them in
|
||||
* *line and *column (if they're not both NULL). Return FALSE on error,
|
||||
* or TRUE otherwise. */
|
||||
/* Read two numbers, separated by a comma, from str, and store them in
|
||||
* *line and *column. Return FALSE on error, and TRUE otherwise. */
|
||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
|
||||
{
|
||||
bool retval = TRUE;
|
||||
bool retval;
|
||||
char *firstpart;
|
||||
const char *comma;
|
||||
|
||||
assert(str != NULL);
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
|
||||
comma = strchr(str, ',');
|
||||
comma = strpbrk(str, "m,. /;");
|
||||
|
||||
if (comma != NULL && column != NULL) {
|
||||
if (!parse_num(comma + 1, column))
|
||||
retval = FALSE;
|
||||
}
|
||||
if (comma == NULL)
|
||||
return parse_num(str, line);
|
||||
|
||||
if (line != NULL) {
|
||||
if (comma != NULL) {
|
||||
char *str_line = mallocstrncpy(NULL, str, comma - str + 1);
|
||||
str_line[comma - str] = '\0';
|
||||
retval = parse_num(comma + 1, column);
|
||||
|
||||
if (str_line[0] != '\0' && !parse_num(str_line, line))
|
||||
retval = FALSE;
|
||||
if (comma == str)
|
||||
return retval;
|
||||
|
||||
free(str_line);
|
||||
} else if (!parse_num(str, line))
|
||||
retval = FALSE;
|
||||
}
|
||||
firstpart = mallocstrcpy(NULL, str);
|
||||
firstpart[comma - str] = '\0';
|
||||
|
||||
retval = parse_num(firstpart, line);
|
||||
|
||||
free(firstpart);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Fix the memory allocation for a string. */
|
||||
void align(char **str)
|
||||
/* Reduce the memory allocation of a string to what is needed. */
|
||||
void snuggly_fit(char **str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
if (*str != NULL)
|
||||
*str = charealloc(*str, strlen(*str) + 1);
|
||||
}
|
||||
@@ -122,8 +149,6 @@ void align(char **str)
|
||||
/* Null a string at a certain index and align it. */
|
||||
void null_at(char **data, size_t index)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
*data = charealloc(*data, index + 1);
|
||||
(*data)[index] = '\0';
|
||||
}
|
||||
@@ -132,8 +157,6 @@ void null_at(char **data, size_t index)
|
||||
* normally have newlines in it, so encode its nulls as newlines. */
|
||||
void unsunder(char *str, size_t true_len)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
for (; true_len > 0; true_len--, str++) {
|
||||
if (*str == '\0')
|
||||
*str = '\n';
|
||||
@@ -144,8 +167,6 @@ void unsunder(char *str, size_t true_len)
|
||||
* normally have newlines in it, so decode its newlines as nulls. */
|
||||
void sunder(char *str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
for (; *str != '\0'; str++) {
|
||||
if (*str == '\n')
|
||||
*str = '\0';
|
||||
@@ -282,27 +303,18 @@ const char *fixbounds(const char *r)
|
||||
* a separate word? That is: is it not part of a longer word?*/
|
||||
bool is_separate_word(size_t position, size_t length, const char *buf)
|
||||
{
|
||||
char *before = charalloc(mb_cur_max()), *after = charalloc(mb_cur_max());
|
||||
char before[mb_cur_max()], after[mb_cur_max()];
|
||||
size_t word_end = position + length;
|
||||
bool retval;
|
||||
|
||||
assert(buf != NULL && position < strlen(buf) && position + length <= strlen(buf));
|
||||
|
||||
/* Get the characters before and after the word, if any. */
|
||||
parse_mbchar(buf + move_mbleft(buf, position), before, NULL);
|
||||
parse_mbchar(buf + word_end, after, NULL);
|
||||
|
||||
/* If we're at the beginning of the line or the character before the
|
||||
* word isn't a non-punctuation "word" character, and if we're at
|
||||
* the end of the line or the character after the word isn't a
|
||||
* non-punctuation "word" character, we have a whole word. */
|
||||
retval = (position == 0 || !is_word_mbchar(before, FALSE)) &&
|
||||
(word_end == strlen(buf) || !is_word_mbchar(after, FALSE));
|
||||
|
||||
free(before);
|
||||
free(after);
|
||||
|
||||
return retval;
|
||||
/* If the word starts at the beginning of the line OR the character before
|
||||
* the word isn't a letter, and if the word ends at the end of the line OR
|
||||
* the character after the word isn't a letter, we have a whole word. */
|
||||
return ((position == 0 || !is_alpha_mbchar(before)) &&
|
||||
(buf[word_end] == '\0' || !is_alpha_mbchar(after)));
|
||||
}
|
||||
#endif /* !DISABLE_SPELLER */
|
||||
|
||||
@@ -320,14 +332,11 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
if ((start > haystack && *(start - 1) == '\0') || start < haystack)
|
||||
return NULL;
|
||||
|
||||
assert(haystack != NULL && needle != NULL && start != NULL);
|
||||
|
||||
#ifdef HAVE_REGEX_H
|
||||
if (ISSET(USE_REGEXP)) {
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(BACKWARDS_SEARCH)) {
|
||||
if (regexec(&search_regexp, haystack, 1, regmatches,
|
||||
0) == 0 && haystack + regmatches[0].rm_so <= start) {
|
||||
if (regexec(&search_regexp, haystack, 1, regmatches, 0) == 0 &&
|
||||
haystack + regmatches[0].rm_so <= start) {
|
||||
const char *retval = haystack + regmatches[0].rm_so;
|
||||
|
||||
/* Search forward until there are no more matches. */
|
||||
@@ -341,10 +350,8 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
regexec(&search_regexp, retval, 10, regmatches, 0);
|
||||
return retval;
|
||||
}
|
||||
} else
|
||||
#endif /* !NANO_TINY */
|
||||
if (regexec(&search_regexp, start, 10, regmatches,
|
||||
(start > haystack) ? REG_NOTBOL : 0) == 0) {
|
||||
} else if (regexec(&search_regexp, start, 10, regmatches,
|
||||
(start > haystack) ? REG_NOTBOL : 0) == 0) {
|
||||
const char *retval = start + regmatches[0].rm_so;
|
||||
|
||||
regexec(&search_regexp, retval, 10, regmatches, 0);
|
||||
@@ -353,20 +360,14 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
return NULL;
|
||||
}
|
||||
#endif /* HAVE_REGEX_H */
|
||||
#if !defined(NANO_TINY) || !defined(DISABLE_SPELLER)
|
||||
if (ISSET(CASE_SENSITIVE)) {
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(BACKWARDS_SEARCH))
|
||||
return revstrstr(haystack, needle, start);
|
||||
else
|
||||
#endif
|
||||
return strstr(start, needle);
|
||||
}
|
||||
#endif /* !DISABLE_SPELLER || !NANO_TINY */
|
||||
#ifndef NANO_TINY
|
||||
else if (ISSET(BACKWARDS_SEARCH))
|
||||
} else if (ISSET(BACKWARDS_SEARCH))
|
||||
return mbrevstrcasestr(haystack, needle, start);
|
||||
#endif
|
||||
|
||||
return mbstrcasestr(start, needle);
|
||||
}
|
||||
|
||||
@@ -406,8 +407,8 @@ void *nrealloc(void *ptr, size_t howmuch)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Copy the first n characters of one malloc()ed string to another
|
||||
* pointer. Should be used as: "dest = mallocstrncpy(dest, src, n);". */
|
||||
/* Allocate and copy the first n characters of the given src string, after
|
||||
* freeing the destination. Usage: "dest = mallocstrncpy(dest, src, n);". */
|
||||
char *mallocstrncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
if (src == NULL)
|
||||
@@ -422,17 +423,15 @@ char *mallocstrncpy(char *dest, const char *src, size_t n)
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* Copy one malloc()ed string to another pointer. Should be used as:
|
||||
/* Free the dest string and return a malloc'ed copy of src. Should be used as:
|
||||
* "dest = mallocstrcpy(dest, src);". */
|
||||
char *mallocstrcpy(char *dest, const char *src)
|
||||
{
|
||||
return mallocstrncpy(dest, src, (src == NULL) ? 1 : strlen(src) + 1);
|
||||
}
|
||||
|
||||
/* Free the malloc()ed string at dest and return the malloc()ed string
|
||||
* at src. Should be used as: "answer = mallocstrassn(answer,
|
||||
* real_dir_from_tilde(answer));". */
|
||||
char *mallocstrassn(char *dest, char *src)
|
||||
/* Free the string at dest and return the string at src. */
|
||||
char *free_and_assign(char *dest, char *src)
|
||||
{
|
||||
free(dest);
|
||||
return src;
|
||||
@@ -444,20 +443,18 @@ char *mallocstrassn(char *dest, char *src)
|
||||
* get_page_start(column) < COLS). */
|
||||
size_t get_page_start(size_t column)
|
||||
{
|
||||
if (column == 0 || column < COLS - 1)
|
||||
if (column == 0 || column < editwincols - 1)
|
||||
return 0;
|
||||
else if (COLS > 8)
|
||||
return column - 7 - (column - 7) % (COLS - 8);
|
||||
else if (editwincols > 8)
|
||||
return column - 7 - (column - 7) % (editwincols - 8);
|
||||
else
|
||||
return column - (COLS - 2);
|
||||
return column - (editwincols - 2);
|
||||
}
|
||||
|
||||
/* Return the placewewant associated with current_x, i.e. the zero-based
|
||||
* column position of the cursor. */
|
||||
size_t xplustabs(void)
|
||||
{
|
||||
assert(openfile->current != NULL);
|
||||
|
||||
return strnlenpt(openfile->current->data, openfile->current_x);
|
||||
}
|
||||
|
||||
@@ -470,8 +467,6 @@ size_t actual_x(const char *text, size_t column)
|
||||
size_t width = 0;
|
||||
/* The screen display width to text[index], in columns. */
|
||||
|
||||
assert(text != NULL);
|
||||
|
||||
while (*text != '\0') {
|
||||
int charlen = parse_mbchar(text, NULL, &width);
|
||||
|
||||
@@ -495,8 +490,6 @@ size_t strnlenpt(const char *text, size_t maxlen)
|
||||
if (maxlen == 0)
|
||||
return 0;
|
||||
|
||||
assert(text != NULL);
|
||||
|
||||
while (*text != '\0') {
|
||||
int charlen = parse_mbchar(text, NULL, &width);
|
||||
|
||||
@@ -539,9 +532,7 @@ void new_magicline(void)
|
||||
void remove_magicline(void)
|
||||
{
|
||||
if (openfile->filebot->data[0] == '\0' &&
|
||||
openfile->filebot != openfile->fileage) {
|
||||
assert(openfile->filebot != openfile->edittop && openfile->filebot != openfile->current);
|
||||
|
||||
openfile->filebot != openfile->fileage) {
|
||||
openfile->filebot = openfile->filebot->prev;
|
||||
free_filestruct(openfile->filebot->next);
|
||||
openfile->filebot->next = NULL;
|
||||
@@ -557,11 +548,9 @@ 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)
|
||||
{
|
||||
assert(top != NULL && top_x != NULL && bot != NULL && bot_x != NULL);
|
||||
|
||||
if ((openfile->current->lineno == openfile->mark_begin->lineno &&
|
||||
openfile->current_x > openfile->mark_begin_x) ||
|
||||
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;
|
||||
*bot = openfile->current;
|
||||
@@ -577,37 +566,6 @@ void mark_order(const filestruct **top, size_t *top_x, const filestruct
|
||||
*right_side_up = FALSE;
|
||||
}
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Calculate the number of characters between begin and end, and return
|
||||
* it. */
|
||||
size_t get_totsize(const filestruct *begin, const filestruct *end)
|
||||
{
|
||||
size_t totsize = 0;
|
||||
const filestruct *f;
|
||||
|
||||
/* Go through the lines from begin to end->prev, if we can. */
|
||||
for (f = begin; f != end && f != NULL; f = f->next) {
|
||||
/* Count the number of characters on this line. */
|
||||
totsize += mbstrlen(f->data);
|
||||
|
||||
/* Count the newline if we have one. */
|
||||
if (f->next != NULL)
|
||||
totsize++;
|
||||
}
|
||||
|
||||
/* Go through the line at end, if we can. */
|
||||
if (f != NULL) {
|
||||
/* Count the number of characters on this line. */
|
||||
totsize += mbstrlen(f->data);
|
||||
|
||||
/* Count the newline if we have one. */
|
||||
if (f->next != NULL)
|
||||
totsize++;
|
||||
}
|
||||
|
||||
return totsize;
|
||||
}
|
||||
|
||||
/* Given a line number, return a pointer to the corresponding struct. */
|
||||
filestruct *fsfromline(ssize_t lineno)
|
||||
@@ -622,13 +580,32 @@ filestruct *fsfromline(ssize_t lineno)
|
||||
f = f->next;
|
||||
|
||||
if (f->lineno != lineno) {
|
||||
statusline(ALERT, _("Internal error: can't match line %d. "
|
||||
"Please save your work."), lineno);
|
||||
statusline(ALERT, _("Internal error: can't match line %ld. "
|
||||
"Please save your work."), (long)lineno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Count the number of characters from begin to end, and return it. */
|
||||
size_t get_totsize(const filestruct *begin, const filestruct *end)
|
||||
{
|
||||
const filestruct *line;
|
||||
size_t totsize = 0;
|
||||
|
||||
/* Sum the number of characters (plus a newline) in each line. */
|
||||
for (line = begin; line != end->next; line = line->next)
|
||||
totsize += mbstrlen(line->data) + 1;
|
||||
|
||||
/* The last line of a file doesn't have a newline -- otherwise it
|
||||
* wouldn't be the last line -- so subtract 1 when at EOF. */
|
||||
if (line == NULL)
|
||||
totsize--;
|
||||
|
||||
return totsize;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Dump the filestruct inptr to stderr. */
|
||||
|
||||
1898
src/winio.c
1898
src/winio.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user