Compare commits

..

65 Commits

Author SHA1 Message Date
Benno Schulenberg
9f92fb3ec4 po: update translations and regenerate POT file and PO files 2016-12-28 12:58:50 +01:00
Benno Schulenberg
293423bdda bump version numbers and add a news item for the 2.7.3 release 2016-12-28 12:24:05 +01:00
Benno Schulenberg
32719d64a1 locking: disable an annoying warning
The warning is wrong when the user has just saved a buffer under a
new name.  And when --quickblank is used, the warning most likely
gets cleared off before it is seen, and the user would just hear
the beep and be left wondering what happened.

This avoids https://savannah.gnu.org/bugs/?49875.
2016-12-28 12:04:55 +01:00
Benno Schulenberg
f4321250ef docs: clarify the difference between "Esc Esc ddd" and "M-V xxxxxx" 2016-12-28 11:54:49 +01:00
Benno Schulenberg
908663e8fc input: discard a verbatim 0x0A or 0x00 byte, depending on the mode
This disallows entering a verbatim ^J (0x0A) when typing text or
search terms, and disallows a verbatim ^@ (0x00) when typing a
filename.  Nano beeps when the disallowed code is attempted.

This addresses https://savannah.gnu.org/bugs/?49897.
2016-12-27 16:46:09 +01:00
Benno Schulenberg
1fb820386b tweaks: chuck a special case, and reduce the scope of two variables
A KEY_WINCH does not need to be separately treated since the basic
action for anything that is not recognized at the yes-no prompt is:
to continue.
2016-12-26 20:25:06 +01:00
Benno Schulenberg
9973366685 prompt: represent newlines as ^J instead of breaking the bar
Also at the yes-no prompt, a 0x0A byte should be displayed as a ^J
instead of splitting the prompt bar in two and spreading it over
two lines.

This fixes https://savannah.gnu.org/bugs/?49934.
2016-12-26 19:59:51 +01:00
Benno Schulenberg
e72db0e350 files: show newlines in filenames as ^J also in error messages
When a given file is, for example, unreadable or unwritable, the
error message should use ^J instead of ^@ in its name.
2016-12-26 12:35:50 +01:00
Benno Schulenberg
87b2df6dea utils: go on to parse the line number even if the column number is bad
This fixes https://savannah.gnu.org/bugs/?49933.
2016-12-26 11:45:38 +01:00
Benno Schulenberg
c24caf5fb8 tweaks: rename four variables, for density and aptness 2016-12-26 11:01:40 +01:00
Benno Schulenberg
8db21b68d5 tweaks: use memory on the stack instead of calling malloc() and free() 2016-12-26 10:39:48 +01:00
Benno Schulenberg
cb31e45f6c tweaks: remove pointless or obscuring asserts 2016-12-26 10:29:57 +01:00
Benno Schulenberg
588daf949e tweaks: condense the setting of three flags 2016-12-25 13:11:17 +01:00
Benno Schulenberg
d21a9c8fc3 text: discard the undo stack after formatting and after spell checking
After a call to the Formatter or the Alternate spell checker, the data
on the undo stack could refer to line positions that don't exist any
more -- the chance is small, but it is there.  So... throw the whole
undo stack away, to prevent undoing things wrongly or even crashing.

(Changes made with the internal spell checker can be undone and redone
without a problem -- nano keeps full track of those.  But the changes
made with a formatter or an external spell checker happen in another
process, so nano has no record of them.)

This fixes https://savannah.gnu.org/bugs/?49920.
2016-12-24 12:22:50 +01:00
Benno Schulenberg
edbc1e5950 text: avoid a crash when a spell-checked line has gotten shorter
When using an external spell checker or formatter, the line with
the cursor might become shorter, which might result in the stored
cursor position being beyond the end-of-line.  So, when restoring
the x position, make sure to limit it to the length of the line.

This fixes https://savannah.gnu.org/bugs/?49923.
2016-12-24 12:22:17 +01:00
Benno Schulenberg
dc18746cbd tweaks: retype, rename, and reshuffle a function 2016-12-23 13:51:58 +01:00
Benno Schulenberg
c92b9be6cd tweaks: rename three variables, to be more fitting 2016-12-23 13:01:15 +01:00
Benno Schulenberg
eef7d1047a screen: display byte value 0x0A in the right places as ^@ or as ^J
In path names and file names, 0x0A means an embedded newline and
should be shown as ^J, but in anything related to the file's data,
0x0A is an encoded NUL and should be displayed as ^@.

So... switch mode at the two main entry points into the "file system"
(reading in a file, and writing out a file), and also when drawing the
titlebar.  Switch back to the default mode in the main loop.

This fixes https://savannah.gnu.org/bugs/?49893.
2016-12-23 11:00:55 +01:00
Benno Schulenberg
d49d4f7b56 history: search items *can* contain newlines -- encoded NUL bytes
Decode 0x0A bytes to 0x00 when saving the search history, and encode
them again when reading the file back in, to prevent nano from hanging
or aborting when encountering 0x00 on a line by itself.
2016-12-23 10:54:09 +01:00
Arturo Borrero González
2fbb71d555 syntax: nftables: add two new families, and add set references
Signed-off-by: Arturo Borrero González <arturo@debian.org>
2016-12-23 09:47:44 +01:00
Benno Schulenberg
66356ec7e2 screen: draw new content immediately, to prevent color flashes
After updating the color palette, the corresponding new window content
should be drawn immediately, before some other part of the code calls
doupdate(), to prevent the old content being shown in the new colors.

This fixes https://savannah.gnu.org/bugs/?49912.
Reported-by: Mike Frysinger <vapier@gentoo.org>
2016-12-23 09:25:29 +01:00
Benno Schulenberg
4edc83c3c2 tweaks: move a setting to a better place -- it needs setting just once 2016-12-22 17:08:10 +01:00
Benno Schulenberg
e6350aaba4 prompt: do not treat a leading newline in a filename specially
This fixes https://savannah.gnu.org/bugs/?49884.
2016-12-22 13:46:53 +01:00
Benno Schulenberg
8bf8682b17 binding: use the code for the Enter directly instead of a function call
And certainly don't return zero when the key wouldn't have been found,
because that would have meant jumping a word to the right.
2016-12-22 12:13:03 +01:00
Benno Schulenberg
a9b5a0e029 tweaks: rename a function to something less abbrevy
Also, swap the logic around, to use less braces.
2016-12-22 12:04:10 +01:00
Benno Schulenberg
026393a91a binding: use plain codes instead of function calls for the jumping keys
Which is possible because those keycodes are hard-bound to the relevant
functions.
2016-12-22 11:50:24 +01:00
Benno Schulenberg
db897b574f input: detect again when both Shift and Ctrl are being held on a VT
In nano 2.7.1 and 2.7.2, pressing Shift+Ctrl+Arrow on a Linux console
would behave as if Shift wasn't held.  It got broken three months ago,
by commit 08cd197b, messing up the proper order of the checks.

This fixes https://savannah.gnu.org/bugs/?49906.
2016-12-22 11:13:39 +01:00
Benno Schulenberg
2b1bc6866a input: don't crash when receiving a KEY_CANCEL
On some systems, typing ^C apparently results in a KEY_CANCEL in
the input stream, which gets hard-bound to the do_cancel function.
But in the main menu there is no Cancel function.  So... in that
case, let it fall back to the plain old Ctrl-C code: 0x03.

Reported-by: Liam Gretton <liam.gretton@leicester.ac.uk>
2016-12-21 17:42:15 +01:00
Benno Schulenberg
90b959a677 history: avoid crashing when the positionlog file is malformed 2016-12-21 17:28:09 +01:00
Benno Schulenberg
116d9e6f01 chars: use memory on the stack instead of calling malloc() and free() 2016-12-20 10:05:09 +01:00
Benno Schulenberg
6620acbff4 tweaks: use a faster comparison 2016-12-20 10:03:53 +01:00
Benno Schulenberg
1cb6619d6a undo: there are just two forms of deletion: backspacing and deleting
A third method does not exist.
2016-12-19 21:18:43 +01:00
Benno Schulenberg
79a4bf81dc tweaks: rename five variables, for uniformity with a few others 2016-12-19 19:58:15 +01:00
Benno Schulenberg
b77e6bd99d general: simplify the detection of a SIGWINCH
There is no need for a counter, nor an old counter to compare it with.
2016-12-19 10:04:01 +01:00
Benno Schulenberg
2bcc6d7f66 tweaks: start searching at a better place
Taking the terminating newline into account, and that there is
at least one digit per number.
2016-12-19 09:57:31 +01:00
Benno Schulenberg
cd705a7c4c tweaks: elide a counter and a comparison
For clarity and a tiny bit more speed.  Also rename some variables.
2016-12-19 09:44:30 +01:00
Benno Schulenberg
ecd18c1694 history: search for the two position numbers from EOL instead of BOL
A filename might contain spaces, so we can't look for the numbers
(the second and third elements) starting from the head of the line
-- we have to start at the tail and work backward.

This fixes https://savannah.gnu.org/bugs/?49879.
2016-12-18 19:57:33 +01:00
Benno Schulenberg
bc8a3a50a4 tweaks: rename three variables, for visibility
(I don't /see/ single-letter variables -- they are too small.)
2016-12-18 19:31:11 +01:00
Benno Schulenberg
9b90ec877a tweaks: drive closer to the edge 2016-12-18 17:56:18 +01:00
Benno Schulenberg
8b483c10ba history: don't bother encoding search items -- they cannot contain newlines 2016-12-18 17:55:39 +01:00
Benno Schulenberg
f915a28d30 tweaks: don't bother trimming the final newline from a position item
It is irrelevant -- the line is discarded as soon as the data has been
extracted.
2016-12-18 16:44:39 +01:00
Benno Schulenberg
cb3fc8892a tweaks: rename a variable and rewrap two lines 2016-12-18 16:34:19 +01:00
Benno Schulenberg
06d9ee89e5 history: encode newlines in filenames as nulls
So they will not break a line in the positionlog file in two.

(Strangely, the reading in of such a log file already decodes
nulls back into newlines.)

This fixes https://savannah.gnu.org/bugs/?49877.
2016-12-18 12:27:55 +01:00
Benno Schulenberg
0b0b812206 files: don't change embedded newlines into nulls in filenames
Because changing anything to a null effectively means to truncate
the name.

This fixes https://savannah.gnu.org/bugs/?49868
and fixes https://savannah.gnu.org/bugs/?49874.
2016-12-18 11:37:57 +01:00
Benno Schulenberg
eafae5d417 screen: show an embedded newline in filenames as ^J instead of ^@
The byte 0x0A means 0x00 *only* when it is found in nano's internal
representation of a file's data, not when it occurs in a file name.

This fixes the second part of https://savannah.gnu.org/bugs/?49867.
2016-12-18 11:13:50 +01:00
Benno Schulenberg
dfff78dffe titlebar: always pass a pathname through display_string()
So that embedded control characters will be represented
instead of acted upon.

This fixes the first part of https://savannah.gnu.org/bugs/?49867.
2016-12-18 11:13:49 +01:00
Benno Schulenberg
40acb8714c oops: forgot to add and amend this to the previous commit 2016-12-18 11:12:04 +01:00
Benno Schulenberg
d7af590c6b memory: don't bother making a snug fit for things that will be freed soon
Most full paths are needed only temporarily and will be freed within
milliseconds.  Only 'full_operating_dir' and 'backup_dir' continue to
exist for the whole current session.  Any partition, too, will soon be
unpartitioned, so the extra reallocation is just a waste of time.
2016-12-18 10:33:30 +01:00
Benno Schulenberg
8c7e4f5108 tweaks: rename a function to describe what it does
It doesn't align anything -- any allocations are already aligned to
whatever multiple is required -- it just shrinks the allocated space.
2016-12-18 10:30:35 +01:00
Benno Schulenberg
1144d38316 tweaks: don't bother reallocating a string of which there is only one
And which normally is just some ten or twenty characters long, and
never gets wildly overallocated.
2016-12-18 10:28:30 +01:00
Benno Schulenberg
0562d27b9c tweaks: delete a bunch of unneeded asserts
Nano would crash straight afterward if any of these asserts would fail,
so they don't add anything.  A few others are simply superfluous.
2016-12-15 21:15:32 +01:00
Benno Schulenberg
c5f49167ea tweaks: write two pieces of conditionalized code like all others
Also trim or improve a few comments.
2016-12-15 19:48:09 +01:00
Benno Schulenberg
9765c2faa0 tweaks: elide a function that is called just once 2016-12-15 19:28:43 +01:00
Benno Schulenberg
85ebe971e2 chars: optimize for the most common case
That is: elide a second test from the most travelled path: a valid
character.  This adds a second call of mblen() when parse_mbchar()
is called on a terminating zero, but that should never happen.
2016-12-15 17:44:18 +01:00
Benno Schulenberg
fc101a6ded tweaks: rename a variable to be shorter and clearer 2016-12-15 15:50:07 +01:00
Benno Schulenberg
eb88ad980a tweaks: use a slightly faster comparison 2016-12-15 13:15:46 +01:00
Benno Schulenberg
9fa95a3680 tweaks: put some prototypes in the proper order, and move a bit of code 2016-12-15 13:04:52 +01:00
Benno Schulenberg
d6cc2c40fe tweaks: conditionalize a function that is not used in the tiny version
The fsfromline() function is mostly used by the undo functions, which
are not present in the tiny version.  It is also used by the comment/
uncomment feature, but this feature cannot be enabled when --enable-tiny
is in effect.
2016-12-15 12:45:02 +01:00
Benno Schulenberg
1df4115013 version: properly mention --disable-wordcomp if it was used 2016-12-15 12:38:47 +01:00
Benno Schulenberg
ea9f62fc0f tweaks: adjust some comments and indentation and ordering 2016-12-13 19:27:33 +01:00
Benno Schulenberg
a772194102 tweaks: rename two variables, for self-documentation 2016-12-13 17:13:38 +01:00
Benno Schulenberg
faf77fb1ec tweaks: don't bother making the next line of an end point NULL 2016-12-13 17:12:52 +01:00
Benno Schulenberg
b0b24d9c3a utils: slightly speed up the calculation of the size of a buffer
Achieve this by eliding two conditions from the inner loop,
which is possible because 'end' will never be NULL.
2016-12-13 17:11:08 +01:00
David Lawrence Ramsey
c9f743f676 tweaks: elide two unneeded variables from line numbering mode
Instead compute directly whether we're at a softwrapped part or not.
2016-12-13 17:01:39 +01:00
David Lawrence Ramsey
bd920b1f49 tweaks: adjust the type of two arguments
Convert digits() to take a ssize_t instead of an int, since it's
used on ssize_t line numbers.  And properly use the long modifier
when displaying a line number.

Also, conditionalize the digits() prototype.
2016-12-13 13:06:20 +01:00
52 changed files with 15312 additions and 15576 deletions

12
NEWS
View File

@@ -1,3 +1,15 @@
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

View File

@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/.
AC_INIT([GNU nano], [2.7.2], [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

View File

@@ -17,7 +17,7 @@
.\" Documentation License along with this program. If not, see
.\" <http://www.gnu.org/licenses/>.
.\"
.TH NANO 1 "version 2.7.2" "December 2016"
.TH NANO 1 "version 2.7.3" "December 2016"
.\" Please adjust this date whenever revising the manpage.
.SH NAME

View File

@@ -17,7 +17,7 @@
.\" Documentation License along with this program. If not, see
.\" <http://www.gnu.org/licenses/>.
.\"
.TH NANORC 5 "version 2.7.2" "December 2016"
.TH NANORC 5 "version 2.7.3" "December 2016"
.\" Please adjust this date whenever revising the manpage.
.SH NAME

View File

@@ -16,7 +16,7 @@
.\" Documentation License along with this program. If not, see
.\" <http://www.gnu.org/licenses/>.
.\"
.TH RNANO 1 "version 2.7.2" "December 2016"
.TH RNANO 1 "version 2.7.3" "December 2016"
.\" Please adjust this date whenever revising the manpage.
.SH NAME

View File

@@ -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:]_.-]*"

View File

@@ -6,7 +6,7 @@
@smallbook
@set EDITION 0.4
@set VERSION 2.7.2
@set VERSION 2.7.3
@set UPDATED December 2016
@dircategory Editors
@@ -21,7 +21,7 @@
@titlepage
@title GNU @code{nano}
@subtitle a small and friendly text editor.
@subtitle version 2.7.2
@subtitle version 2.7.3
@author Chris Allegretta
@page
@@ -410,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

870
po/bg.po

File diff suppressed because it is too large Load Diff

877
po/ca.po

File diff suppressed because it is too large Load Diff

931
po/cs.po

File diff suppressed because it is too large Load Diff

875
po/da.po

File diff suppressed because it is too large Load Diff

913
po/de.po

File diff suppressed because it is too large Load Diff

876
po/eo.po

File diff suppressed because it is too large Load Diff

876
po/es.po

File diff suppressed because it is too large Load Diff

870
po/eu.po

File diff suppressed because it is too large Load Diff

878
po/fi.po

File diff suppressed because it is too large Load Diff

878
po/fr.po

File diff suppressed because it is too large Load Diff

870
po/ga.po

File diff suppressed because it is too large Load Diff

878
po/gl.po

File diff suppressed because it is too large Load Diff

876
po/hr.po

File diff suppressed because it is too large Load Diff

878
po/hu.po

File diff suppressed because it is too large Load Diff

870
po/id.po

File diff suppressed because it is too large Load Diff

878
po/it.po

File diff suppressed because it is too large Load Diff

878
po/ja.po

File diff suppressed because it is too large Load Diff

870
po/ms.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

907
po/nb.po

File diff suppressed because it is too large Load Diff

878
po/nl.po

File diff suppressed because it is too large Load Diff

870
po/nn.po

File diff suppressed because it is too large Load Diff

876
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

878
po/ro.po

File diff suppressed because it is too large Load Diff

877
po/ru.po

File diff suppressed because it is too large Load Diff

878
po/sl.po

File diff suppressed because it is too large Load Diff

878
po/sr.po

File diff suppressed because it is too large Load Diff

874
po/sv.po

File diff suppressed because it is too large Load Diff

870
po/tr.po

File diff suppressed because it is too large Load Diff

878
po/uk.po

File diff suppressed because it is too large Load Diff

876
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -147,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);
unget_kbinput(KEY_ENTER, FALSE);
}
continue;
@@ -230,17 +230,11 @@ char *do_browser(char *path)
/* TRANSLATORS: This is a prompt. */
browser_refresh, _("Go To Directory"));
/* 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));
/* If the given path is relative, join it with the current path. */
@@ -379,8 +373,7 @@ char *do_browse_from(const char *inpath)
beep();
napms(1200);
return NULL;
} else
align(&path);
}
}
}
@@ -714,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);

View File

@@ -88,11 +88,6 @@ void mbtowc_reset(void)
IGNORE_CALL_RESULT(mbtowc(NULL, NULL, 0));
}
void wctomb_reset(void)
{
IGNORE_CALL_RESULT(wctomb(NULL, 0));
}
/* This function is equivalent to isalpha() for multibyte characters. */
bool is_alpha_mbchar(const char *c)
{
@@ -172,8 +167,6 @@ bool is_cntrl_char(int c)
* their high bits set. */
bool is_cntrl_mbchar(const char *c)
{
assert(c != NULL);
#ifdef ENABLE_UTF8
if (use_utf8) {
return ((c[0] & 0xE0) == 0 || c[0] == 127 ||
@@ -208,8 +201,6 @@ bool is_punct_mbchar(const char *c)
* 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;
@@ -217,15 +208,11 @@ bool is_word_mbchar(const char *c, bool allow_punct)
return TRUE;
if (word_chars != NULL && *word_chars != '\0') {
bool wordforming;
char *symbol = charalloc(MB_CUR_MAX + 1);
char symbol[mb_cur_max() + 1];
int symlen = parse_mbchar(c, symbol, NULL);
symbol[symlen] = '\0';
wordforming = (strstr(word_chars, symbol) != NULL);
free(symbol);
return wordforming;
return (strstr(word_chars, symbol) != NULL);
}
return (allow_punct && is_punct_mbchar(c));
@@ -234,12 +221,7 @@ bool is_word_mbchar(const char *c, bool allow_punct)
/* Return the visible representation of control character c. */
char control_rep(const signed char c)
{
assert(is_cntrl_char(c));
/* An embedded newline is an encoded null. */
if (c == '\n')
return '@';
else if (c == DEL_CODE)
if (c == DEL_CODE)
return '?';
else if (c == -97)
return '=';
@@ -250,9 +232,11 @@ char control_rep(const signed char c)
}
/* Return the visible representation of multibyte control character c. */
char control_mbrep(const char *c)
char control_mbrep(const char *c, bool isdata)
{
assert(c != NULL);
/* An embedded newline is an encoded NUL if it is data. */
if (*c == '\n' && (isdata || as_an_at))
return '@';
#ifdef ENABLE_UTF8
if (use_utf8) {
@@ -325,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);
@@ -353,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
@@ -368,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;
@@ -406,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);
}
@@ -415,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;
@@ -437,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
@@ -492,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;
@@ -510,8 +487,6 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
if (use_utf8) {
wchar_t wc1, wc2;
assert(s1 != NULL && s2 != NULL);
while (*s1 != '\0' && *s2 != '\0' && n > 0) {
bool bad1 = FALSE, bad2 = FALSE;
@@ -555,8 +530,6 @@ char *nstrcasestr(const char *haystack, const char *needle)
{
size_t needle_len;
assert(haystack != NULL && needle != NULL);
if (*needle == '\0')
return (char *)haystack;
@@ -580,8 +553,6 @@ char *mbstrcasestr(const char *haystack, const char *needle)
if (use_utf8) {
size_t needle_len;
assert(haystack != NULL && needle != NULL);
if (*needle == '\0')
return (char *)haystack;
@@ -602,27 +573,25 @@ char *mbstrcasestr(const char *haystack, const char *needle)
/* 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;
@@ -635,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;
@@ -665,8 +632,6 @@ char *mbrevstrcasestr(const char *haystack, const char *needle, const
if (use_utf8) {
size_t rev_start_len, needle_len;
assert(haystack != NULL && needle != NULL && rev_start != NULL);
if (*needle == '\0')
return (char *)rev_start;
@@ -706,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++)
;
@@ -718,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;
@@ -743,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;
@@ -754,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;
@@ -765,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;
@@ -785,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)) {
@@ -857,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;
@@ -871,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);
@@ -912,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 */

View File

@@ -148,8 +148,9 @@ void set_modified(void)
if (openfile->lock_filename == NULL) {
/* TRANSLATORS: Keep the next ten messages at most 76 characters. */
statusline(ALERT, _("Warning: Modifying a file which is not locked,"
" check directory permission?"));
// statusline(ALERT, _("Warning: Modifying a file which is not locked,"
// " check directory permission?"));
;
} else {
char *fullname = get_full_path(openfile->filename);
write_lockfile(openfile->lock_filename, fullname, TRUE);
@@ -433,6 +434,9 @@ bool open_buffer(const char *filename, bool undoable)
assert(filename != NULL);
/* Display newlines in filenames as ^J. */
as_an_at = FALSE;
#ifndef DISABLE_OPERATINGDIR
if (check_operating_dir(filename, FALSE)) {
statusline(ALERT, _("Can't insert file from outside of %s"),
@@ -563,7 +567,8 @@ void display_buffer(void)
precalc_multicolorinfo();
#endif
refresh_needed = TRUE;
/* Update the content of the edit window straightaway. */
edit_refresh();
}
#ifndef DISABLE_MULTIBUFFER
@@ -750,8 +755,6 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw
/* 0 = *nix, 1 = DOS, 2 = Mac, 3 = both DOS and Mac. */
#endif
assert(openfile->fileage != NULL && openfile->current != NULL);
buf = charalloc(bufx);
#ifndef NANO_TINY
@@ -1059,6 +1062,9 @@ void do_insertfile(void)
bool execute = FALSE, right_side_up = FALSE, single_line = FALSE;
#endif
/* Display newlines in filenames as ^J. */
as_an_at = FALSE;
while (TRUE) {
#ifndef NANO_TINY
if (execute) {
@@ -1100,10 +1106,8 @@ void do_insertfile(void)
"./");
/* If we're in multibuffer mode and the filename or command is
* blank, open a new buffer instead of canceling. If the
* filename or command begins with a newline (i.e. an encoded
* null), treat it as though it's blank. */
if (i == -1 || (!ISSET(MULTIBUFFER) && (i == -2 || *answer == '\n'))) {
* blank, open a new buffer instead of canceling. */
if (i == -1 || (i == -2 && !ISSET(MULTIBUFFER))) {
statusbar(_("Cancelled"));
break;
} else {
@@ -1175,10 +1179,6 @@ void do_insertfile(void)
current_was_at_top = (openfile->edittop == openfile->fileage);
}
/* Convert newlines to nulls in the given filename. */
sunder(answer);
align(&answer);
#ifndef NANO_TINY
if (execute) {
#ifndef DISABLE_MULTIBUFFER
@@ -1218,7 +1218,7 @@ void do_insertfile(void)
#ifndef NANO_TINY
if (!execute)
#endif
if (check_poshistory(answer, &priorline, &priorcol))
if (has_old_position(answer, &priorline, &priorcol))
do_gotolinecolumn(priorline, priorcol, FALSE, FALSE);
}
#endif /* !DISABLE_HISTORIES */
@@ -1346,8 +1346,6 @@ char *get_full_path(const char *origpath)
/* If we succeeded, canonicalize it in d_here. */
if (d_here != NULL) {
align(&d_here);
/* If the current directory isn't "/", tack a slash onto the end
* of it. */
if (strcmp(d_here, "/") != 0) {
@@ -1409,8 +1407,6 @@ char *get_full_path(const char *origpath)
/* If we succeeded, canonicalize it in d_there. */
if (d_there != NULL) {
align(&d_there);
/* If the current directory isn't "/", tack a slash onto
* the end of it. */
if (strcmp(d_there, "/") != 0) {
@@ -1533,6 +1529,8 @@ void init_operating_dir(void)
/* If the operating directory is inaccessible, fail. */
if (full_operating_dir == NULL || chdir(full_operating_dir) == -1)
die("Invalid operating directory\n");
snuggly_fit(&full_operating_dir);
}
/* Check to see if we're inside the operating directory. Return FALSE
@@ -1623,6 +1621,7 @@ void init_backup_dir(void)
} else {
free(backup_dir);
backup_dir = full_backup_dir;
snuggly_fit(&backup_dir);
}
}
#endif /* !NANO_TINY */
@@ -1700,8 +1699,6 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
char *tempname = NULL;
/* The name of the temporary file we write to on prepend. */
assert(name != NULL);
if (*name == '\0')
return -1;
@@ -1994,10 +1991,6 @@ bool write_file(const char *name, FILE *f_open, bool tmp,
}
}
/* There might not be a magicline. There won't be when writing out
* a selection. */
assert(openfile->fileage != NULL && openfile->filebot != NULL);
while (fileptr != NULL) {
size_t data_len = strlen(fileptr->data), size;
@@ -2145,8 +2138,6 @@ bool write_marked_file(const char *name, FILE *f_open, bool tmp,
filestruct *top, *bot;
size_t top_x, bot_x;
assert(openfile->mark_set);
/* Partition the filestruct so that it contains only the marked text. */
mark_order((const filestruct **)&top, &top_x,
(const filestruct **)&bot, &bot_x, NULL);
@@ -2194,6 +2185,9 @@ int do_writeout(bool exiting)
static bool did_credits = FALSE;
#endif
/* Display newlines in filenames as ^J. */
as_an_at = FALSE;
if (exiting && ISSET(TEMP_FILE) && openfile->filename[0] != '\0') {
if (write_file(openfile->filename, NULL, FALSE, OVERWRITE, FALSE))
return 1;
@@ -2251,9 +2245,7 @@ int do_writeout(bool exiting)
#endif
);
/* If the filename or command 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"));
break;
} else {
@@ -2332,15 +2324,10 @@ int do_writeout(bool exiting)
#endif
if (method == OVERWRITE) {
size_t answer_len = strlen(answer);
bool name_exists, do_warning;
char *full_answer, *full_filename;
struct stat st;
/* Convert newlines to nulls, just before we get the
* full path. */
sunder(answer);
full_answer = get_full_path(answer);
full_filename = get_full_path(openfile->filename);
name_exists = (stat((full_answer == NULL) ?
@@ -2352,10 +2339,6 @@ int do_writeout(bool exiting)
answer : full_answer, (full_filename == NULL) ?
openfile->filename : full_filename) != 0);
/* Convert nulls to newlines. answer_len is the
* string's real length. */
unsunder(answer, answer_len);
free(full_filename);
free(full_answer);
@@ -2411,10 +2394,6 @@ int do_writeout(bool exiting)
#endif
}
/* Convert newlines to nulls, just before we save the file. */
sunder(answer);
align(&answer);
/* Here's where we allow the selected text to be written to
* a separate file. If we're using restricted mode, this
* function is disabled, since it allows reading from or
@@ -2460,8 +2439,6 @@ char *real_dir_from_tilde(const char *buf)
{
char *retval;
assert(buf != NULL);
if (*buf == '~') {
size_t i = 1;
char *tilde_dir;
@@ -2544,8 +2521,6 @@ bool is_dir(const char *buf)
struct stat fileinfo;
bool retval;
assert(buf != NULL);
dirptr = real_dir_from_tilde(buf);
retval = (stat(dirptr, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode));
@@ -2742,31 +2717,26 @@ char *input_tab(char *buf, bool allow_files, size_t *place,
char *mzero, *glued;
const char *lastslash = revstrstr(buf, "/", buf + *place);
size_t lastslash_len = (lastslash == NULL) ? 0 : lastslash - buf + 1;
char *match1 = charalloc(mb_cur_max());
char *match2 = charalloc(mb_cur_max());
int match1_len, match2_len;
char char1[mb_cur_max()], char2[mb_cur_max()];
int len1, len2;
/* Get the number of characters that all matches have in common. */
while (TRUE) {
match1_len = parse_mbchar(matches[0] + common_len, match1, NULL);
len1 = parse_mbchar(matches[0] + common_len, char1, NULL);
for (match = 1; match < num_matches; match++) {
match2_len = parse_mbchar(matches[match] + common_len,
match2, NULL);
if (match1_len != match2_len ||
strncmp(match1, match2, match2_len) != 0)
len2 = parse_mbchar(matches[match] + common_len, char2, NULL);
if (len1 != len2 || strncmp(char1, char2, len2) != 0)
break;
}
if (match < num_matches || matches[0][common_len] == '\0')
break;
common_len += match1_len;
common_len += len1;
}
free(match1);
free(match2);
mzero = charalloc(lastslash_len + common_len + 1);
strncpy(mzero, buf, lastslash_len);
@@ -2994,10 +2964,10 @@ void load_history(void)
size_t buf_len = 0;
ssize_t read;
while ((read = getline(&line, &buf_len, hist)) >= 0) {
if (read > 0 && line[read - 1] == '\n')
line[--read] = '\0';
while ((read = getline(&line, &buf_len, hist)) > 0) {
line[--read] = '\0';
if (read > 0) {
/* Encode any embedded NUL as 0x0A. */
unsunder(line, read);
update_history(history, line);
} else
@@ -3012,22 +2982,23 @@ void load_history(void)
}
}
/* Write the lines of a history list, starting with the line at h, to
/* Write the lines of a history list, starting with the line at head, to
* the open file at hist. Return TRUE if the write succeeded, and FALSE
* otherwise. */
bool writehist(FILE *hist, filestruct *h)
bool writehist(FILE *hist, const filestruct *head)
{
filestruct *p;
const filestruct *item;
/* Write a history list from the oldest entry to the newest. Assume
* the last history entry is a blank line. */
for (p = h; p != NULL; p = p->next) {
size_t p_len = strlen(p->data);
/* Write a history list from the oldest entry to the newest. */
for (item = head; item != NULL; item = item->next) {
size_t length = strlen(item->data);
sunder(p->data);
/* Decode 0x0A bytes as embedded NULs. */
sunder(item->data);
if (fwrite(p->data, sizeof(char), p_len, hist) < p_len ||
putc('\n', hist) == EOF)
if (fwrite(item->data, sizeof(char), length, hist) < length)
return FALSE;
if (putc('\n', hist) == EOF)
return FALSE;
}
@@ -3072,7 +3043,6 @@ void save_history(void)
void save_poshistory(void)
{
char *poshist = poshistfilename();
char *statusstr = NULL;
poshiststruct *posptr;
FILE *hist;
@@ -3088,14 +3058,25 @@ void save_poshistory(void)
chmod(poshist, S_IRUSR | S_IWUSR);
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
char *path_and_place;
size_t length;
/* Assume 20 decimal positions each for line and column number,
* plus two spaces, plus the line feed, plus the null byte. */
statusstr = charalloc(strlen(posptr->filename) + 44);
sprintf(statusstr, "%s %ld %ld\n", posptr->filename, (long)posptr->lineno,
(long)posptr->xno);
if (fwrite(statusstr, sizeof(char), strlen(statusstr), hist) < strlen(statusstr))
fprintf(stderr, _("Error writing %s: %s\n"), poshist, strerror(errno));
free(statusstr);
path_and_place = charalloc(strlen(posptr->filename) + 44);
sprintf(path_and_place, "%s %ld %ld\n", posptr->filename,
(long)posptr->lineno, (long)posptr->xno);
length = strlen(path_and_place);
/* Encode newlines in filenames as nulls. */
sunder(path_and_place);
/* Restore the terminating newline. */
path_and_place[length - 1] = '\n';
if (fwrite(path_and_place, sizeof(char), length, hist) < length)
fprintf(stderr, _("Error writing %s: %s\n"),
poshist, strerror(errno));
free(path_and_place);
}
fclose(hist);
}
@@ -3164,27 +3145,28 @@ void update_poshistory(char *filename, ssize_t lineno, ssize_t xpos)
free(fullpath);
}
/* Check the recorded last file positions to see if the given file
* matches an existing entry. If so, return 1 and set line and column
* to the retrieved values. Otherwise, return 0. */
int check_poshistory(const char *file, ssize_t *line, ssize_t *column)
/* Check whether the given file matches an existing entry in the recorded
* last file positions. If not, return FALSE. If yes, return TRUE and
* set line and column to the retrieved values. */
bool has_old_position(const char *file, ssize_t *line, ssize_t *column)
{
poshiststruct *posptr;
poshiststruct *posptr = position_history;
char *fullpath = get_full_path(file);
if (fullpath == NULL)
return 0;
return FALSE;
while (posptr != NULL && strcmp(posptr->filename, fullpath) != 0)
posptr = posptr->next;
for (posptr = position_history; posptr != NULL; posptr = posptr->next) {
if (!strcmp(posptr->filename, fullpath)) {
*line = posptr->lineno;
*column = posptr->xno;
free(fullpath);
return 1;
}
}
free(fullpath);
return 0;
if (posptr == NULL)
return FALSE;
*line = posptr->lineno;
*column = posptr->xno;
return TRUE;
}
/* Load the recorded file positions from ~/.nano/filepos_history. */
@@ -3212,13 +3194,21 @@ void load_poshistory(void)
poshiststruct *record_ptr = NULL, *newrecord;
/* Read and parse each line, and store the extracted data. */
while ((read = getline(&line, &buf_len, hist)) > 2) {
if (line[read - 1] == '\n')
line[--read] = '\0';
while ((read = getline(&line, &buf_len, hist)) > 5) {
/* Decode nulls as embedded newlines. */
unsunder(line, read);
lineptr = parse_next_word(line);
xptr = parse_next_word(lineptr);
/* Find where the x index and line number are in the line. */
xptr = revstrstr(line, " ", line + read - 3);
if (xptr == NULL)
continue;
lineptr = revstrstr(line, " ", xptr - 2);
if (lineptr == NULL)
continue;
/* Now separate the three elements of the line. */
*(xptr++) = '\0';
*(lineptr++) = '\0';
/* Create a new position record. */
newrecord = (poshiststruct *)nmalloc(sizeof(poshiststruct));

View File

@@ -29,8 +29,8 @@
/* Global variables. */
#ifndef NANO_TINY
volatile sig_atomic_t sigwinch_counter = 0;
/* Is incremented by the handler whenever a SIGWINCH occurs. */
volatile sig_atomic_t the_window_resized = FALSE;
/* Set to TRUE by the handler whenever a SIGWINCH occurs. */
#endif
#ifdef __linux__
@@ -45,16 +45,13 @@ bool shift_held;
bool focusing = TRUE;
/* Whether an update of the edit window should center the cursor. */
bool as_an_at = TRUE;
/* Whether a 0x0A byte should be shown as a ^@ instead of a ^J. */
int margin = 0;
/* The amount of space reserved at the left for line numbers. */
int editwincols = -1;
/* The number of usable columns in the edit window: COLS - margin. */
#ifdef ENABLE_LINENUMBERS
int last_drawn_line = 0;
/* The line number of the last drawn line. */
int last_line_y;
/* The y coordinate of the last drawn line. */
#endif
message_type lastmessage = HUSH;
/* Messages of type HUSH should not overwrite type MILD nor ALERT. */
@@ -391,18 +388,17 @@ const sc *first_sc_for(int menu, void (*func)(void))
return NULL;
}
/* Return the given menu's first shortcut sequence, or the default value
* (2nd arg). Assumes currmenu for the menu to check. */
int sc_seq_or(void (*func)(void), int defaultval)
/* Return the first keycode that is bound to the given function in the
* current menu, if any; otherwise, return the given default value. */
int the_code_for(void (*func)(void), int defaultval)
{
const sc *s = first_sc_for(currmenu, func);
if (s) {
meta_key = s->meta;
return s->keycode;
}
/* else */
return defaultval;
if (s == NULL)
return defaultval;
meta_key = s->meta;
return s->keycode;
}
/* Return a pointer to the function that is bound to the given key. */

View File

@@ -78,8 +78,6 @@ filestruct *copy_node(const filestruct *src)
{
filestruct *dst;
assert(src != NULL);
dst = (filestruct *)nmalloc(sizeof(filestruct));
dst->data = mallocstrcpy(NULL, src->data);
@@ -96,8 +94,6 @@ filestruct *copy_node(const filestruct *src)
/* Splice a new node into an existing linked list of filestructs. */
void splice_node(filestruct *afterthis, filestruct *newnode)
{
assert(afterthis != NULL && newnode != NULL);
newnode->next = afterthis->next;
newnode->prev = afterthis;
if (afterthis->next != NULL)
@@ -112,8 +108,6 @@ void splice_node(filestruct *afterthis, filestruct *newnode)
/* Disconnect a node from a linked list of filestructs and delete it. */
void unlink_node(filestruct *fileptr)
{
assert(fileptr != NULL);
if (fileptr->prev != NULL)
fileptr->prev->next = fileptr->next;
if (fileptr->next != NULL)
@@ -129,8 +123,6 @@ void unlink_node(filestruct *fileptr)
/* Free the data structures in the given node. */
void delete_node(filestruct *fileptr)
{
assert(fileptr != NULL && fileptr->data != NULL);
free(fileptr->data);
#ifndef DISABLE_COLOR
free(fileptr->multidata);
@@ -143,8 +135,6 @@ filestruct *copy_filestruct(const filestruct *src)
{
filestruct *head, *copy;
assert(src != NULL);
copy = copy_node(src);
copy->prev = NULL;
head = copy;
@@ -237,7 +227,6 @@ partition *partition_filestruct(filestruct *top, size_t top_x,
/* Remove all text before top_x at the top of the partition. */
charmove(top->data, top->data + top_x, strlen(top->data) - top_x + 1);
align(&top->data);
/* Return the partition. */
return p;
@@ -513,8 +502,7 @@ openfilestruct *make_new_opennode(void)
/* Unlink a node from the rest of the openfilestruct, and delete it. */
void unlink_opennode(openfilestruct *fileptr)
{
assert(fileptr != NULL && fileptr->prev != NULL && fileptr->next != NULL &&
fileptr != fileptr->prev && fileptr != fileptr->next);
assert(fileptr != fileptr->prev && fileptr != fileptr->next);
fileptr->prev->next = fileptr->next;
fileptr->next->prev = fileptr->prev;
@@ -525,8 +513,6 @@ void unlink_opennode(openfilestruct *fileptr)
/* Free all the memory in the given open-file node. */
void delete_opennode(openfilestruct *fileptr)
{
assert(fileptr != NULL && fileptr->filename != NULL && fileptr->fileage != NULL);
free(fileptr->filename);
free_filestruct(fileptr->fileage);
#ifndef NANO_TINY
@@ -1033,6 +1019,9 @@ void version(void)
#ifdef DISABLE_TABCOMP
printf(" --disable-tabcomp");
#endif
#ifndef ENABLE_WORDCOMPLETION
printf(" --disable-wordcomp");
#endif
#ifdef DISABLE_WRAPPING
printf(" --disable-wrapping");
#endif
@@ -1300,7 +1289,7 @@ RETSIGTYPE do_continue(int signal)
RETSIGTYPE handle_sigwinch(int signal)
{
/* Let the input routine know that a SIGWINCH has occurred. */
sigwinch_counter++;
the_window_resized = TRUE;
}
/* Reinitialize and redraw the screen completely. */
@@ -1310,6 +1299,9 @@ void regenerate_screen(void)
int fd, result = 0;
struct winsize win;
/* Reset the trigger. */
the_window_resized = FALSE;
if (tty == NULL)
return;
fd = open(tty, O_RDWR);
@@ -1821,11 +1813,8 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
#ifndef NANO_TINY
size_t orig_lenpt = 0;
#endif
char *char_buf = charalloc(mb_cur_max());
int char_buf_len;
assert(openfile->current != NULL && openfile->current->data != NULL);
int char_len;
current_len = strlen(openfile->current->data);
@@ -1835,25 +1824,17 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
#endif
while (i < output_len) {
/* If control codes are allowed, encode a verbatim null as a newline,
* and let a verbatim ^J create a whole new line. */
if (allow_cntrls) {
if (output[i] == '\0')
output[i] = '\n';
else if (output[i] == '\n') {
do_enter();
i++;
continue;
}
}
/* Encode an embedded NUL byte as 0x0A. */
if (output[i] == '\0')
output[i] = '\n';
/* Get the next multibyte character. */
char_buf_len = parse_mbchar(output + i, char_buf, NULL);
char_len = parse_mbchar(output + i, char_buf, NULL);
i += char_buf_len;
i += char_len;
/* If controls are not allowed, ignore an ASCII control character. */
if (!allow_cntrls && is_ascii_cntrl_char(*(output + i - char_buf_len)))
if (!allow_cntrls && is_ascii_cntrl_char(*(output + i - char_len)))
continue;
/* If we're adding to the magicline, create a new magicline. */
@@ -1867,13 +1848,13 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
/* Make room for the new character and copy it into the line. */
openfile->current->data = charealloc(openfile->current->data,
current_len + char_buf_len + 1);
charmove(openfile->current->data + openfile->current_x + char_buf_len,
current_len + char_len + 1);
charmove(openfile->current->data + openfile->current_x + char_len,
openfile->current->data + openfile->current_x,
current_len - openfile->current_x + 1);
strncpy(openfile->current->data + openfile->current_x, char_buf,
char_buf_len);
current_len += char_buf_len;
char_len);
current_len += char_len;
openfile->totsize++;
set_modified();
@@ -1883,10 +1864,10 @@ void do_output(char *output, size_t output_len, bool allow_cntrls)
/* Note that current_x has not yet been incremented. */
if (openfile->mark_set && openfile->current == openfile->mark_begin &&
openfile->current_x < openfile->mark_begin_x)
openfile->mark_begin_x += char_buf_len;
openfile->mark_begin_x += char_len;
#endif
openfile->current_x += char_buf_len;
openfile->current_x += char_len;
#ifndef NANO_TINY
update_undo(ADD);
@@ -2617,7 +2598,7 @@ int main(int argc, char **argv)
else if (ISSET(POS_HISTORY)) {
ssize_t savedposline, savedposcol;
/* If edited before, restore the last cursor position. */
if (check_poshistory(argv[i], &savedposline, &savedposcol))
if (has_old_position(argv[i], &savedposline, &savedposcol))
do_gotolinecolumn(savedposline, savedposcol,
FALSE, FALSE);
}
@@ -2651,7 +2632,7 @@ int main(int argc, char **argv)
else if (ISSET(POS_HISTORY)) {
ssize_t savedposline, savedposcol;
/* If the file was edited before, restore the last cursor position. */
if (check_poshistory(argv[optind], &savedposline, &savedposcol))
if (has_old_position(argv[optind], &savedposline, &savedposcol))
do_gotolinecolumn(savedposline, savedposcol, FALSE, FALSE);
}
#endif
@@ -2685,6 +2666,7 @@ int main(int argc, char **argv)
display_main_list();
lastmessage = HUSH;
as_an_at = TRUE;
/* Update the displayed current cursor position only when there
* are no keys waiting in the input buffer. */

View File

@@ -104,7 +104,7 @@ int do_statusbar_input(bool *ran_func, bool *finished)
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, NULL);
do_statusbar_output(kbinput, kbinput_len, TRUE);
/* Empty the input buffer. */
kbinput_len = 0;
@@ -139,18 +139,7 @@ int do_statusbar_input(bool *ran_func, bool *finished)
s->scfunc == do_backspace))
;
else if (s->scfunc == do_verbatim_input) {
bool got_newline = FALSE;
/* Whether we got a verbatim ^J. */
do_statusbar_verbatim_input(&got_newline);
/* If we got a verbatim ^J, remove it from the input buffer,
* fake a press of Enter, and indicate that we're done. */
if (got_newline) {
get_input(NULL, 1);
input = sc_seq_or(do_enter, 0);
*finished = TRUE;
}
do_statusbar_verbatim_input();
} else if (s->scfunc == do_cut_text_void)
do_statusbar_cut_text();
else if (s->scfunc == do_delete)
@@ -202,11 +191,10 @@ int do_statusbar_mouse(void)
}
#endif
/* The user typed input_len multibyte characters. Add them to the
* statusbar prompt, setting got_newline to TRUE if we got a verbatim ^J,
* 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_newline)
bool filtering)
{
char *output = charalloc(input_len + 1);
char *char_buf = charalloc(mb_cur_max());
@@ -220,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 a ^J and get out. */
unparse_kbinput(output + i, input_len - i);
*got_newline = 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);
@@ -306,7 +285,6 @@ void do_statusbar_delete(void)
charmove(answer + statusbar_x, answer + statusbar_x + char_len,
strlen(answer) - statusbar_x - char_len + 1);
align(&answer);
update_the_statusbar();
}
@@ -370,19 +348,15 @@ void do_statusbar_prev_word(void)
}
#endif /* !NANO_TINY */
/* Get verbatim input, setting got_newline to TRUE if we get a ^J as
* part of the verbatim input. */
void do_statusbar_verbatim_input(bool *got_newline)
/* 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_newline);
do_statusbar_output(kbinput, kbinput_len, FALSE);
}
/* Return the zero-based column position of the cursor in the answer. */
@@ -532,7 +506,7 @@ functionptrtype acquire_an_answer(int *actual, bool allow_tabs,
if (func == do_tab) {
#ifndef DISABLE_HISTORIES
if (history_list != NULL) {
if (last_kbinput != sc_seq_or(do_tab, TAB_CODE))
if (last_kbinput != the_code_for(do_tab, TAB_CODE))
complete_len = strlen(answer);
if (complete_len > 0) {
@@ -724,6 +698,8 @@ int do_prompt(bool allow_tabs,
int do_yesno_prompt(bool all, const char *msg)
{
int response = -2, width = 16;
char *message = display_string(msg, 0, COLS, FALSE);
/* TRANSLATORS: For the next three strings, if possible, specify
* the single-byte shortcuts for both your language and English.
* For example, in French: "OoYy", for both "Oui" and "Yes". */
@@ -735,12 +711,9 @@ int do_yesno_prompt(bool all, const char *msg)
* that are accepted for the corresponding answer. Of each variable,
* the first character is displayed in the help lines. */
do {
while (response == -2) {
int kbinput;
functionptrtype func;
#ifndef DISABLE_MOUSE
int mouse_x, mouse_y;
#endif
if (!ISSET(NO_HELP)) {
char shortstr[3];
@@ -774,7 +747,7 @@ int do_yesno_prompt(bool all, const char *msg)
/* 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]);
wnoutrefresh(bottomwin);
@@ -786,17 +759,13 @@ int do_yesno_prompt(bool all, const char *msg)
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) &&
@@ -826,7 +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);
return response;
}

View File

@@ -26,7 +26,7 @@
/* 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__
@@ -38,12 +38,10 @@ extern bool shift_held;
extern bool focusing;
extern bool as_an_at;
extern int margin;
extern int editwincols;
#ifdef ENABLE_LINENUMBERS
extern int last_drawn_line;
extern int last_line_y;
#endif
extern message_type lastmessage;
@@ -211,7 +209,7 @@ 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(const signed char c);
char control_mbrep(const 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);
@@ -231,8 +229,8 @@ 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);
char *revstrstr(const char *haystack, const char *needle, const char
*rev_start);
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
@@ -350,19 +348,19 @@ 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);
void assign_keyinfo(sc *s, const char *keystring, const int keycode);
void print_sclist(void);
@@ -487,7 +485,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls);
int do_statusbar_mouse(void);
#endif
void do_statusbar_output(int *the_input, size_t input_len,
bool filtering, bool *got_newline);
bool filtering);
void do_statusbar_home(void);
void do_statusbar_end(void);
void do_statusbar_left(void);
@@ -499,7 +497,7 @@ 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_newline);
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);
@@ -592,18 +590,25 @@ void do_tab(void);
void do_indent(ssize_t cols);
void do_indent_void(void);
void do_unindent(void);
void do_undo(void);
void do_redo(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);
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);
@@ -651,10 +656,12 @@ void complete_a_word(void);
/* All functions in utils.c. */
void get_homedir(void);
int digits(int n);
#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);
@@ -690,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);

View File

@@ -664,18 +664,17 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
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,6 +743,7 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
}
set_modified();
as_an_at = TRUE;
numreplaced++;
}
}
@@ -1203,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);
}

View File

@@ -102,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);
@@ -118,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--;
@@ -424,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();
@@ -980,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;
@@ -991,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
@@ -1152,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;
}
@@ -1217,14 +1222,14 @@ void add_undo(undo_type action)
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],
int char_len = parse_mbchar(&openfile->current->data[u->begin],
char_buf, NULL);
null_at(&char_buf, char_buf_len);
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. */
@@ -1352,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
@@ -1363,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);
@@ -2567,7 +2566,6 @@ 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 unjustified text. */
free_filestruct(jusbuffer);
@@ -2624,16 +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);
/* Make sure spell-check goes forward only. */
UNSET(BACKWARDS_SEARCH);
#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;
@@ -3076,6 +3068,8 @@ 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;
openfile->placewewant = pww_save;
adjust_viewport(STATIONARY);
@@ -3083,9 +3077,12 @@ const char *do_alt_speller(char *tempfile_name)
/* 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);
@@ -3548,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;
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");
}

View File

@@ -54,7 +54,7 @@ void get_homedir(void)
#ifdef ENABLE_LINENUMBERS
/* Return the number of digits that the given integer n takes up. */
int digits(int n)
int digits(ssize_t n)
{
if (n < 100000) {
if (n < 1000) {
@@ -93,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;
@@ -126,26 +124,24 @@ bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
if (comma == NULL)
return parse_num(str, line);
if (!parse_num(comma + 1, column))
return FALSE;
retval = parse_num(comma + 1, column);
if (comma == str)
return TRUE;
return retval;
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);
}
@@ -153,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';
}
@@ -163,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';
@@ -175,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';
@@ -313,11 +303,8 @@ 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);
@@ -326,13 +313,8 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
/* 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. */
retval = (position == 0 || !is_alpha_mbchar(before)) &&
(word_end == strlen(buf) || !is_alpha_mbchar(after));
free(before);
free(after);
return retval;
return ((position == 0 || !is_alpha_mbchar(before)) &&
(buf[word_end] == '\0' || !is_alpha_mbchar(after)));
}
#endif /* !DISABLE_SPELLER */
@@ -350,8 +332,6 @@ 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)) {
if (ISSET(BACKWARDS_SEARCH)) {
@@ -475,8 +455,6 @@ size_t get_page_start(size_t column)
* column position of the cursor. */
size_t xplustabs(void)
{
assert(openfile->current != NULL);
return strnlenpt(openfile->current->data, openfile->current_x);
}
@@ -489,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);
@@ -514,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);
@@ -559,9 +533,6 @@ 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->filebot->prev;
free_filestruct(openfile->filebot->next);
openfile->filebot->next = NULL;
@@ -577,8 +548,6 @@ 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) {
@@ -597,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)
@@ -649,6 +587,25 @@ filestruct *fsfromline(ssize_t lineno)
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. */

View File

@@ -55,21 +55,6 @@ static bool seen_wide = FALSE;
/* Whether we've seen a multicolumn character in the current line. */
#endif
#ifndef NANO_TINY
static sig_atomic_t last_sigwinch_counter = 0;
/* Did we receive a SIGWINCH since we were last called? */
bool the_window_resized(void)
{
if (sigwinch_counter == last_sigwinch_counter)
return FALSE;
last_sigwinch_counter = sigwinch_counter;
regenerate_screen();
return TRUE;
}
#endif
/* Control character compatibility:
*
* - Ctrl-H is Backspace under ASCII, ANSI, VT100, and VT220.
@@ -144,8 +129,9 @@ void get_key_buffer(WINDOW *win)
input = wgetch(win);
#ifndef NANO_TINY
if (the_window_resized()) {
if (the_window_resized) {
ungetch(input);
regenerate_screen();
input = KEY_WINCH;
}
#endif
@@ -162,7 +148,8 @@ void get_key_buffer(WINDOW *win)
handle_hupterm(0);
#ifndef NANO_TINY
if (the_window_resized()) {
if (the_window_resized) {
regenerate_screen();
input = KEY_WINCH;
break;
}
@@ -521,28 +508,28 @@ int parse_kbinput(WINDOW *win)
#ifndef NANO_TINY
else if (retval == shiftcontrolleft) {
shift_held = TRUE;
return sc_seq_or(do_prev_word_void, shiftcontrolleft);
return CONTROL_LEFT;
} else if (retval == shiftcontrolright) {
shift_held = TRUE;
return sc_seq_or(do_next_word_void, shiftcontrolright);
return CONTROL_RIGHT;
} else if (retval == shiftcontrolup) {
shift_held = TRUE;
return sc_seq_or(do_prev_block, shiftcontrolup);
return CONTROL_UP;
} else if (retval == shiftcontroldown) {
shift_held = TRUE;
return sc_seq_or(do_next_block, shiftcontroldown);
return CONTROL_DOWN;
} else if (retval == shiftaltleft) {
shift_held = TRUE;
return sc_seq_or(do_home, shiftaltleft);
return KEY_HOME;
} else if (retval == shiftaltright) {
shift_held = TRUE;
return sc_seq_or(do_end, shiftaltright);
return KEY_END;
} else if (retval == shiftaltup) {
shift_held = TRUE;
return sc_seq_or(do_page_up, shiftaltup);
return KEY_PPAGE;
} else if (retval == shiftaltdown) {
shift_held = TRUE;
return sc_seq_or(do_page_down, shiftaltdown);
return KEY_NPAGE;
}
#endif
@@ -552,33 +539,33 @@ int parse_kbinput(WINDOW *win)
unsigned char modifiers = 6;
if (console && ioctl(0, TIOCLINUX, &modifiers) >= 0) {
/* Is Ctrl being held? */
if (modifiers & 0x04) {
if (retval == KEY_UP)
return sc_seq_or(do_prev_block, controlup);
else if (retval == KEY_DOWN)
return sc_seq_or(do_next_block, controldown);
else if (retval == KEY_LEFT)
return sc_seq_or(do_prev_word_void, controlleft);
else if (retval == KEY_RIGHT)
return sc_seq_or(do_next_word_void, controlright);
}
#ifndef NANO_TINY
/* Is Shift being held? */
if (modifiers & 0x01)
shift_held =TRUE;
shift_held = TRUE;
#endif
/* Is Ctrl being held? */
if (modifiers & 0x04) {
if (retval == KEY_UP)
return CONTROL_UP;
else if (retval == KEY_DOWN)
return CONTROL_DOWN;
else if (retval == KEY_LEFT)
return CONTROL_LEFT;
else if (retval == KEY_RIGHT)
return CONTROL_RIGHT;
}
#ifndef NANO_TINY
/* Are both Shift and Alt being held? */
if ((modifiers & 0x09) == 0x09) {
if (retval == KEY_UP)
return sc_seq_or(do_page_up, shiftaltup);
return KEY_PPAGE;
else if (retval == KEY_DOWN)
return sc_seq_or(do_page_down, shiftaltdown);
return KEY_NPAGE;
else if (retval == KEY_LEFT)
return sc_seq_or(do_home, shiftaltleft);
return KEY_HOME;
else if (retval == KEY_RIGHT)
return sc_seq_or(do_end, shiftaltright);
return KEY_END;
}
#endif
}
@@ -655,13 +642,13 @@ int parse_kbinput(WINDOW *win)
#endif
case DEL_CODE:
if (ISSET(REBIND_DELETE))
return sc_seq_or(do_delete, KEY_DC);
return the_code_for(do_delete, KEY_DC);
else
return KEY_BACKSPACE;
#ifdef KEY_SIC
/* Slang doesn't support KEY_SIC. */
case KEY_SIC:
return sc_seq_or(do_insertfile_void, KEY_IC);
return the_code_for(do_insertfile_void, KEY_IC);
#endif
#ifdef KEY_SBEG
/* Slang doesn't support KEY_SBEG. */
@@ -680,7 +667,7 @@ int parse_kbinput(WINDOW *win)
#endif
/* Slang doesn't support KEY_CANCEL. */
case KEY_CANCEL:
return first_sc_for(currmenu, do_cancel)->keycode;
return the_code_for(do_cancel, 0x03);
#endif
#ifdef KEY_SUSPEND
#ifdef KEY_SSUSPEND
@@ -689,7 +676,7 @@ int parse_kbinput(WINDOW *win)
#endif
/* Slang doesn't support KEY_SUSPEND. */
case KEY_SUSPEND:
return sc_seq_or(do_suspend_void, KEY_SUSPEND);
return the_code_for(do_suspend_void, KEY_SUSPEND);
#endif
#ifdef PDCURSES
case KEY_SHIFT_L:
@@ -1455,9 +1442,15 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
if (!ISSET(REBIND_KEYPAD))
keypad(win, FALSE);
/* Read in a stream of characters and interpret it if possible. */
/* Read in one keycode, or one or two escapes. */
retval = parse_verbatim_kbinput(win, kbinput_len);
/* If the code is invalid in the current mode, discard it. */
if ((*retval == '\n' && as_an_at) || (*retval == '\0' && !as_an_at)) {
*kbinput_len = 0;
beep();
}
/* Turn flow control characters back on if necessary and turn the
* keypad back on if necessary now that we're done. */
if (ISSET(PRESERVE))
@@ -1803,11 +1796,11 @@ void check_statusblank(void)
* caller wants to display buf starting with column start_col, and
* extending for at most span columns. start_col is zero-based. span
* is one-based, so span == 0 means you get "" returned. The returned
* string is dynamically allocated, and should be freed. If dollars is
* string is dynamically allocated, and should be freed. If isdata is
* TRUE, the caller might put "$" at the beginning or end of the line if
* it's too long. */
char *display_string(const char *buf, size_t start_col, size_t span,
bool dollars)
bool isdata)
{
size_t start_index;
/* Index in buf of the first character shown. */
@@ -1818,9 +1811,8 @@ char *display_string(const char *buf, size_t start_col, size_t span,
size_t index;
/* Current position in converted. */
/* If dollars is TRUE, make room for the "$" at the end of the
* line. */
if (dollars && span > 0 && strlenpt(buf) > start_col + span)
/* If this is data, make room for the "$" at the end of the line. */
if (isdata && !ISSET(SOFTWRAP) && strlenpt(buf) > start_col + span)
span--;
if (span == 0)
@@ -1841,12 +1833,12 @@ char *display_string(const char *buf, size_t start_col, size_t span,
buf += start_index;
if (*buf != '\0' && *buf != '\t' &&
(column < start_col || (dollars && column > 0))) {
(column < start_col || (isdata && column > 0))) {
/* We don't display the complete first character as it starts to
* the left of the screen. */
if (is_cntrl_mbchar(buf)) {
if (column < start_col) {
converted[index++] = control_mbrep(buf);
converted[index++] = control_mbrep(buf, isdata);
start_col++;
buf += parse_mbchar(buf, NULL, NULL);
}
@@ -1909,7 +1901,7 @@ char *display_string(const char *buf, size_t start_col, size_t span,
/* If buf contains a control character, represent it. */
if (is_cntrl_mbchar(buf)) {
converted[index++] = '^';
converted[index++] = control_mbrep(buf);
converted[index++] = control_mbrep(buf, isdata);
start_col += 2;
buf += charlength;
continue;
@@ -1969,8 +1961,8 @@ void titlebar(const char *path)
/* What is shown before the path -- "File:", "DIR:", or "". */
const char *state = "";
/* The state of the current buffer -- "Modified", "View", or "". */
char *fragment;
/* The tail part of the pathname when dottified. */
char *caption;
/* The presentable form of the pathname. */
/* If the screen is too small, there is no titlebar. */
if (topwin == NULL)
@@ -1981,6 +1973,7 @@ void titlebar(const char *path)
wattron(topwin, interface_color_pair[TITLE_BAR]);
blank_titlebar();
as_an_at = FALSE;
/* Do as Pico: if there is not enough width available for all items,
* first sacrifice the version string, then eat up the side spaces,
@@ -2049,14 +2042,16 @@ void titlebar(const char *path)
wmove(topwin, 0, offset);
/* Print the full path if there's room; otherwise, dottify it. */
if (pathlen + pluglen + statelen <= COLS)
waddstr(topwin, path);
else if (5 + statelen <= COLS) {
if (pathlen + pluglen + statelen <= COLS) {
caption = display_string(path, 0, pathlen, FALSE);
waddstr(topwin, caption);
free(caption);
} else if (5 + statelen <= COLS) {
waddstr(topwin, "...");
fragment = display_string(path, 3 + pathlen - COLS + statelen,
caption = display_string(path, 3 + pathlen - COLS + statelen,
COLS - statelen, FALSE);
waddstr(topwin, fragment);
free(fragment);
waddstr(topwin, caption);
free(caption);
}
/* Right-align the state if there's room; otherwise, trim it. */
@@ -2322,10 +2317,12 @@ void edit_draw(filestruct *fileptr, const char *converted, int
* the text -- but only for the parts that are not softwrapped. */
if (margin > 0) {
wattron(edit, interface_color_pair[LINE_NUMBER]);
if (last_drawn_line != fileptr->lineno || last_line_y >= line)
mvwprintw(edit, line, 0, "%*i", margin - 1, fileptr->lineno);
else
#ifndef NANO_TINY
if (ISSET(SOFTWRAP) && startpos >= editwincols)
mvwprintw(edit, line, 0, "%*s", margin - 1, " ");
else
#endif
mvwprintw(edit, line, 0, "%*ld", margin - 1, (long)fileptr->lineno);
wattroff(edit, interface_color_pair[LINE_NUMBER]);
}
#endif
@@ -2693,10 +2690,6 @@ void edit_draw(filestruct *fileptr, const char *converted, int
}
}
#endif /* !NANO_TINY */
#ifdef ENABLE_LINENUMBERS
last_drawn_line = fileptr->lineno;
last_line_y = line;
#endif
}
/* Just update one line in the edit buffer. This is basically a wrapper
@@ -2743,15 +2736,11 @@ int update_line(filestruct *fileptr, size_t index)
/* Expand the line, replacing tabs with spaces, and control
* characters with their displayed forms. */
#ifdef NANO_TINY
converted = display_string(fileptr->data, page_start, editwincols, TRUE);
#else
converted = display_string(fileptr->data, page_start, editwincols, !ISSET(SOFTWRAP));
#ifdef DEBUG
if (ISSET(SOFTWRAP) && strlen(converted) >= editwincols - 2)
fprintf(stderr, "update_line(): converted(1) line = %s\n", converted);
#endif
#endif /* !NANO_TINY */
/* Paint the line. */
edit_draw(fileptr, converted, line, page_start);
@@ -2776,7 +2765,7 @@ int update_line(filestruct *fileptr, size_t index)
/* Expand the line, replacing tabs with spaces, and control
* characters with their displayed forms. */
converted = display_string(fileptr->data, index, editwincols, !ISSET(SOFTWRAP));
converted = display_string(fileptr->data, index, editwincols, TRUE);
#ifdef DEBUG
if (ISSET(SOFTWRAP) && strlen(converted) >= editwincols - 2)
fprintf(stderr, "update_line(): converted(2) line = %s\n", converted);
@@ -2984,8 +2973,8 @@ void edit_redraw(filestruct *old_current)
* if we've moved and changed text. */
void edit_refresh(void)
{
filestruct *foo;
int nlines;
filestruct *line;
int row = 0;
/* Figure out what maxrows should really be. */
compute_maxrows();
@@ -3000,20 +2989,22 @@ void edit_refresh(void)
adjust_viewport((focusing || !ISSET(SMOOTH_SCROLL)) ? CENTERING : STATIONARY);
}
foo = openfile->edittop;
#ifdef DEBUG
fprintf(stderr, "edit-refresh: now edittop = %ld\n", (long)openfile->edittop->lineno);
#endif
for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
nlines += update_line(foo, (foo == openfile->current) ?
openfile->current_x : 0);
foo = foo->next;
line = openfile->edittop;
while (row < editwinrows && line != NULL) {
if (line == openfile->current)
row += update_line(line, openfile->current_x) + 1;
else
row += update_line(line, 0) + 1;
line = line->next;
}
for (; nlines < editwinrows; nlines++)
blank_line(edit, nlines, 0, COLS);
while (row < editwinrows)
blank_line(edit, row++, 0, COLS);
reset_cursor();
wnoutrefresh(edit);
@@ -3119,25 +3110,24 @@ void display_main_list(void)
* position always. In any case we reset suppress_cursorpos to FALSE. */
void do_cursorpos(bool constant)
{
filestruct *f;
char c;
size_t i, cur_xpt = xplustabs() + 1;
char saved_byte;
size_t sum, cur_xpt = xplustabs() + 1;
size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
int linepct, colpct, charpct;
assert(openfile->fileage != NULL && openfile->current != NULL);
/* Determine the size of the file up to the cursor. */
f = openfile->current->next;
c = openfile->current->data[openfile->current_x];
openfile->current->next = NULL;
saved_byte = openfile->current->data[openfile->current_x];
openfile->current->data[openfile->current_x] = '\0';
i = get_totsize(openfile->fileage, openfile->current);
sum = get_totsize(openfile->fileage, openfile->current);
openfile->current->data[openfile->current_x] = c;
openfile->current->next = f;
openfile->current->data[openfile->current_x] = saved_byte;
/* When not at EOF, subtract 1 for an overcounted newline. */
if (openfile->current != openfile->filebot)
sum--;
/* If the position needs to be suppressed, don't suppress it next time. */
if (suppress_cursorpos && constant) {
@@ -3148,14 +3138,14 @@ void do_cursorpos(bool constant)
/* Display the current cursor position on the statusbar. */
linepct = 100 * openfile->current->lineno / openfile->filebot->lineno;
colpct = 100 * cur_xpt / cur_lenpt;
charpct = (openfile->totsize == 0) ? 0 : 100 * i / openfile->totsize;
charpct = (openfile->totsize == 0) ? 0 : 100 * sum / openfile->totsize;
statusline(HUSH,
_("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
(long)openfile->current->lineno,
(long)openfile->filebot->lineno, linepct,
(unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
(unsigned long)i, (unsigned long)openfile->totsize, charpct);
(unsigned long)sum, (unsigned long)openfile->totsize, charpct);
/* Displaying the cursor position should not suppress it next time. */
suppress_cursorpos = FALSE;