DLR and DB fixes mega-merge

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1235 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
master
Chris Allegretta 2002-07-19 01:08:59 +00:00
parent cf2f6563ca
commit 6df90f5787
22 changed files with 2610 additions and 2722 deletions

2
BUGS
View File

@ -105,7 +105,7 @@
higuita@cadernoverde.com) (54) [FIXED].
- When using autoindent (-i), wrapped text does not get autoindented
(55, discovered by Mark Senior) [FIXED].
- When using -R (regex) and -p (pico mode), subsequent searches after
- When using -R (regex) and -p (Pico mode), subsequent searches after
the first fail if no string is entered (56) [FIXED].
- Page down on a file of editwinrows fails (again). Reported by Ryan
Krebs (57) [FIXED].

143
ChangeLog
View File

@ -14,8 +14,9 @@ CVS Code -
- Many fixes to the help browser and shortcut lists: efficiency
updates, consistency fixes, help text fixes and improvements,
and spacing improvements. (David Benbennick)
- Make more functions use const variables when possible. (David
Benbennick)
- Make some functions use const variables when possible, and
also make them static when necessary. (David Benbennick,
necessary redefined by Chris ;-)
- Add Carl Drinkwater's backup file option (-B or --backup on the
command line, M-B in nano's global shortcuts). If the original
file is unchanged from when it was loaded, it is backed up to
@ -33,20 +34,57 @@ CVS Code -
--regexp as an alternative for -R; they were listed in nano's
usage information, but weren't actually in nano. Also, display
"-?" as an alternative for "-h" in nano's usage information,
put the command line options in a more consistent (i. e. mostly
put the command line options in a more consistent (i.e. mostly
alphabetical) order in nano, put the long options in a more
consistent order in rcfile.c and nanorc.sample, don't include
rcfile options if their equivalent command line options are
disabled, and remove obsolete relative option from
nanorc.sample. (DLR)
- Removed much unnecessary parts to the color code and reworks
some of the color display (David Benbennick).
- Change "File Name to Append/Prepend" to "File Name to
Append/Prepend to". The original prompt could confusingly
imply that we are appending/prepending another file to the
current file, when we are actually appending/prepending the
current file to another file. (DLR)
- Put nano.1, nano.1.html, and nano.texi up to date. (DLR)
- Typo fixes for the ChangeLog. (David Benbennick)
- Put nano.1, nano.1.html, and nano.texi up to date, and fix a
few inconsistencies in them. (DLR)
- Typo fixes for the ChangeLog. (David Benbennick and DLR)
- Complete rewrite of justification code to fix some bugs and
improve its functionality. (David Benbennick)
- If a variable isn't going to be used in tiny mode, #define it
out when possible. (David Benbennick)
- Major reworking of the cutting/screen-updating code in cut.c,
some functions in utils.c, the cursor placement code in
winio.c, and many, many other areas to increase efficiency.
(David Benbennick)
- Rework handling of prompts when there's a list of partial
filename matches on the screen: remove kludgy case-by-case
handling (which didn't even handle every case), and have
statusq() handle it directly for all cases. (David Benbennick
and DLR)
- Fix some warnings and errors that show up when using gcc's
-pedantic option. (DLR)
- Add a comment to nanorc.sample warning that an out-of-range
negative value for fill can make nano die complaining that
the screen is too small (which may not be immediately
obvious. (DLR)
- There were some opendir() calls in files.c without
corresponding closedir() calls; add them. (DLR)
- Move align() and null_at() from nano.c to utils.c, and move
the openfilestruct handling functions from nano.c to files.c.
(DLR)
- In color.c, start the "#ifdef ENABLE_COLOR" block after
including all the header files, as rcfile.c does; this fixes
a warning about ANSI C'S inability to handle blank files.
(DLR)
- Add command line option -I/--ignorercfiles to ignore
/etc/nanorc and ~/.nanorc. (Carl Drinkwater)
- files.c:
new_file():
- Make sure current_x is zero; this fixes a problem where the
current cursor position wasn't reset when reading in a file in
multibuffer mode. (David Benbennick)
read_file(), read_line():
- Rework to properly handle nulls in the input file, fix
detection of binary files to properly mark a file as binary if
@ -66,8 +104,19 @@ CVS Code -
--enable-tiny is used. Since formatstr isn't ever used in tiny
mode, don't bother even creating the variable. (David
Benbennick and DLR)
do_insertfile():
- Memory leak fix. (David Benbennick)
get_full_path():
- Memory leak fix. Also, make it properly interpret ~/ notation
so, among other things, the option "--operatingdir ~" works.
(David Benbennick)
check_operating_dir():
- Memory leak fix. (David Benbennick)
cwd_tab_completion():
- Changed a variable name: dirName -> dirname. (DLR)
append_slash_if_dir(), input_tab():
- Changed a variable name: lastWasTab -> lastwastab. (DLR)
- Changed variable names: lastWasTab -> lastwastab, matchBuf ->
matchbuf. (DLR)
- global.c:
free_toggles():
- Only include if we're not using tiny mode. (David Benbennick)
@ -79,6 +128,8 @@ CVS Code -
do_toggle() if Pico emulation mode is the toggle in question.
Don't free the toggles here, either; it's unnecessary after the
above change. (David Benbennick)
- If wrapping is disabled, don't include the toggle for it.
(DLR)
shortcut_init():
- Rework IFHELP macro (David Benbennick).
- move.c:
@ -90,6 +141,26 @@ CVS Code -
- nanorc.sample:
- Put in much less crappy example regex rules for c-file.
- nano.c:
do_char():
- Fix a problem where, if ENABLE_COLOR wasn't used, typing
characters on a marked line before the beginning of the mark
would make the highlight short by one. (David Benbennick)
die():
- Rework slightly to remove redundant printing of last message
and print all messages after resetting the terminal. (DLR)
global_init():
- Call die_too_small() when fill is 0. (DLR)
usage():
- List the options that are ignored for the purpose of Pico
compatibility, and make some minor consistency fixes. (DLR)
do_next_word(), do_prev_word():
- Fix a problem where highlighting isn't done properly after
calling either of these, and another problem where the cursor
would move back too far in certain cases with do_prev_word().
(David Benbennick)
do_backspace():
- Make sure placewewant is set properly, and that the mark is
moved backwards. (David Benbennick)
clear_filename():
- Remove this function, as it has unneeded functionality, is
short enough to be inlined, and is only called in two spots
@ -97,6 +168,16 @@ CVS Code -
do_int_spell(), do_alt_spell():
- Rework to save the marked selection before doing spell checking
and restore it afterward. (DLR)
do_cont():
- Handle the case where the window was resized while we were
stopped. (David Benbennick)
handle_sigwinch():
- Make sure we adjust fill when the window is resized. (David
Benbennick)
- Call die_too_small() when fill is 0. (DLR)
help_init():
- Since the return value of snprintf() isn't well defined, use
sprintf() instead. (David Benbennick)
do_toggle():
- Since the search mode toggles aren't global anymore, we don't
need to explicitly block them here anymore (which will end up
@ -109,8 +190,23 @@ CVS Code -
hold a line number. (DLR)
- Properly handle multiple -r settings on the command line. (Carl
Drinkwater)
- Fix a bug that prevented file insertion via the Insert key
from working at all when --enable-multibuffer wasn't used
(oops). (DLR)
- Adapt David Benbennick's fix to get fill to accept negative
numbers properly in parse_rcfile() (see below) to the
handlers for the -r and -T options as well, so that -r/-T 0
can be treated separately from -r/-T string. (DLR)
- proto.h:
- Remove external declaration of the global int fill, since
it's now static. (DLR)
- rcfile.c:
colortoint():
parse_rcfile():
- Add David Benbennick's fix that allows fill to accept
negative numbers properly. Specifically, use strtol() there
instead of atoi() so that errors can be detected. Also
adapted for tabsize by DLR.
parse_next_regex(), colortoint():
- Only include if ENABLE_COLOR is defined. (DLR)
- search.c:
search_init():
@ -118,6 +214,9 @@ CVS Code -
part of this function referencing them so that they still work.
(DLR)
- Remove unneeded toggles variable. (David Benbennick)
- Fix a problem where the first character of buf was overwritten
if the last search string was one third the number of columns
plus one. (David Benbennick)
findnextstr():
- Update the current line at current_x if we don't find a match.
Also, pass current_x_find to strstrwrapper() so we know whether
@ -134,10 +233,16 @@ CVS Code -
other than the terminating null in strings to newlines and
back; they're used to handle null characters in files properly.
(DLR)
lowercase():
- Remove, since it isn't actually used anywhere. (David
Benbennick)
strstrwrapper(): Set REG_NOTBOL when we're not at the beginning of a
string, to avoid false positives when searching for regular
expressions prefixed with ^. Make it take a new parameter,
line_pos, to determine where we are in the string. (DLR)
check_wildcard_match():
- Changed variable names: retryPat -> retrypat, retryText ->
retrytext. (DLR)
- winio.c:
actual_x_from_start():
- Overhaul to make cursor placement more like that of Pico: add
@ -158,16 +263,28 @@ CVS Code -
(which should never occur under normal circumstances; they will
only be there if the line had nulls in it and was unsunder()ed
beforehand) as ^@'s. (DLR)
- Display ASCII 0x80-0x9f as backslashes followed by 3-digit
octal values to keep xterm from screwing up the display when
some of them are printed as-is. (David Benbennick)
statusbar():
- Limit statusbar display to the number of columns less four, and
don't allow it to go over its original row. (David Benbennick)
do_help():
- Add support for the handled keyboard escape sequences in the
help menu, as they are needed with some terminals (e.g. xterm
with TERM=ansi). (DLR)
do_replace_highlight():
- When using regexps, make sure the highlight is the length of
the search result and not the regexp string. (DLR)
- configure.ac:
- Added ms to ALL_LINGUAS (Jordi).
- Merged acconfig.h in (Jordi).
- Fixed so that --enable-debug defines DEBUG and undefines
NDEBUG. (Carl Drinkwater)
- THANKS:
- Completed a bit (Jordi).
- Fixed David Benbennick's email address (David Benbennick).
- Fixed David Benbennick's email address. (David Benbennick)
- Typo fix. (DLR)
GNU nano 1.1.9 - 05/12/2002
- General:
- Typos n misspellings all over the place (David Benbennick).
@ -963,7 +1080,7 @@ nano-1.1.0 - 07/15/2001
- Moved extension functions (Case Sensitive, Regexp, and Backwards
Search, Append key in write file function) to Meta keys, as
people are complaining loudly about nano not being control-key
compatible with Pico, which is a Bag Thing (TM). Changes to
compatible with Pico, which is a Bad Thing (TM). Changes to
shortcut_init, toggle_init, new toggles for backwards and regexp
(and you can now toggle all search options including regexp at
the Search: prompt!) Changes to nanogetstr to enable Meta
@ -1420,7 +1537,7 @@ General
by Rocco Corsi.
help_init()
- Fix off by one error that was making ^G help in normal mode and
^_ in pico mode not be displayed in the help (bug discovered by
^_ in Pico mode not be displayed in the help (bug discovered by
Rocco Corsi).
do_toggle()
- Added fix_editbot() call to fix improper redisplay of edit
@ -2248,10 +2365,10 @@ nano-0.9.3 - 04/29/2000
nano-0.9.2 - 04/15/2000
- This release just fixes the serious segfault problem if nano is
invoked any way other than using the absolute path. The bug was
in the new code for checking whether nano is invoked as pico.
in the new code for checking whether nano is invoked as 'pico'.
nano-0.9.1 - 04/14/2000
- Added pico compatibility for ^T when in search or switch to switch
- Added Pico compatibility for ^T when in search or switch to switch
to the opposite function. Added one to REPLACE_LIST_LEN and
WHEREIS_LIST_LEN in nano.h, new args to sc_init_one in global.c and
new strings that will have to be gettext()ed. New argument 'replacing'
@ -2373,7 +2490,7 @@ nano-0.8.4 - 02/11/2000
- README: Updated my email address and the nano web page.
nano-0.8.3 - 02/08/2000
- New pico mode (-p, --pico), toggles (more) compatibility with the
- New Pico mode (-p, --pico), toggles (more) compatibility with the
Pico messages displayed in the shortcut list. Note that there are still
small differences in this mode.
- nano.h: New shortcut struct format, for the benefit of i18n and

6
NEWS
View File

@ -221,7 +221,7 @@
The --nofollow option also works again for those who
are real security nuts. There are also some display and
search fixes, and the --disable-spell function was renamed
to --disable-speller to be in line with nano and pico's
to --disable-speller to be in line with nano and Pico's
"speller" term.
12/02/2000 - Nano 0.9.22 is released, with many more changes and
@ -416,13 +416,13 @@
04/15/2000 - Nano 0.9.2 just fixes the serious segfault problem if
nano is invoked any way other than using the absolute
path. The bug was in the new code for checking whether
nano is invoked as pico.
nano is invoked as 'pico'.
04/14/2000 - 0.9.1 has some more Pico compatibility built-in. The
option to switch to/from Search and Search/Replace
(^T) is now available, and nano now displays the
more Pico-like shortcut list when invoked as 'pico'
(i.e. if pico is a symlink to nano). There is an
(i.e. if 'pico' is a symlink to nano). There is an
important change to the handling of symbolic links
as well. Now, nano does the "correct" thing and
automatically writes to the object of the symlink,

2
THANKS
View File

@ -1,5 +1,5 @@
The following people have helped GNU nano in some way or another.
If we missed you here, let us now!
If we missed you here, let us know!
Sharuzzaman Ahmat Raslan <sharuzzaman@excite.com>
Bahasa Melayu Translator

94
color.c
View File

@ -21,8 +21,6 @@
#include "config.h"
#ifdef ENABLE_COLOR
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -33,6 +31,8 @@
#include "proto.h"
#include "nano.h"
#ifdef ENABLE_COLOR
#ifdef ENABLE_NLS
#include <libintl.h>
#define _(string) gettext(string)
@ -40,62 +40,7 @@
#define _(string) (string)
#endif
void color_on(WINDOW *win, int whatever)
{
/* Temporary fallback, if the color value hasn't been set,
turn on highlighting */
if (!colors[whatever - FIRST_COLORNUM].set) {
wattron(win, A_REVERSE);
return;
}
if (colors[whatever - FIRST_COLORNUM].bold)
wattron(win, A_BOLD);
/* If the foreground color is black, we've switched fg and bg (see
the comment in colorinit_one() about this) so turn on reverse so
it looks like it's supposed to */
if (colors[whatever - FIRST_COLORNUM].fg == COLOR_BLACK)
wattron(win, A_REVERSE);
wattron(win, COLOR_PAIR(whatever));
}
void color_off(WINDOW *win, int whatever)
{
if (!colors[whatever - FIRST_COLORNUM].set) {
wattroff(win, A_REVERSE);
return;
}
wattroff(win, COLOR_PAIR(whatever));
if (colors[whatever - FIRST_COLORNUM].fg == COLOR_BLACK)
wattroff(win, A_REVERSE);
if (colors[whatever - FIRST_COLORNUM].bold)
wattroff(win, A_BOLD);
}
void colorinit_one(int colortoset, short fg, short bg, int bold)
{
colors[colortoset - FIRST_COLORNUM].fg = fg;
colors[colortoset - FIRST_COLORNUM].bg = bg;
colors[colortoset - FIRST_COLORNUM].bold = bold;
colors[colortoset - FIRST_COLORNUM].set = 1;
/* Okay, so if they want a black foreground, do a switch on the fg
and bg, because specifying black as the foreground color gives
this ugly grey color. Then in color_on we will turn A_REVERSE
which is probably what they want it to look like... */
if (fg == COLOR_BLACK)
init_pair(colortoset, bg, fg);
else
init_pair(colortoset, fg, bg);
}
int do_colorinit(void)
void do_colorinit(void)
{
int i;
colortype *tmpcolor = NULL, *beforenow = NULL;
@ -142,38 +87,7 @@ int do_colorinit(void)
}
}
/*
if (use_default_colors() != ERR) {
init_pair(COLOR_BLACK, -1, -1);
init_pair(COLOR_GREEN, COLOR_GREEN, -1);
init_pair(COLOR_WHITE, COLOR_WHITE, -1);
init_pair(COLOR_RED, COLOR_RED, -1);
init_pair(COLOR_CYAN, COLOR_CYAN, -1);
init_pair(COLOR_MAGENTA, COLOR_MAGENTA, -1);
init_pair(COLOR_BLUE, COLOR_BLUE, -1);
init_pair(COLOR_YELLOW, COLOR_YELLOW, -1);
} else {
init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
}
*/
/* Okay I'll be nice and comment these out for the commit =)
colorinit_one(COLOR_TITLEBAR, COLOR_GREEN, COLOR_BLUE, 1);
colorinit_one(COLOR_BOTTOMBARS, COLOR_GREEN, COLOR_BLUE, 1);
colorinit_one(COLOR_STATUSBAR, COLOR_BLACK, COLOR_CYAN, 0);
colorinit_one(COLOR_TEXT, COLOR_WHITE, COLOR_BLACK, 0);
colorinit_one(COLOR_MARKER, COLOR_BLACK, COLOR_CYAN, 0);
}
*/
return 0;
return;
}
/* Update the color information based on the current filename */

View File

@ -17,10 +17,18 @@ dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h unistd.h malloc.h termios.h termio.h limits.h getopt.h regex.h)
dnl Turn off assert statements.
AC_DEFINE(NDEBUG, 1, [Shut up the assert warnings :-)])
dnl options
AC_ARG_ENABLE(debug,
[ --enable-debug Enable debugging (disabled by default)],
[if test x$enableval = xyes; then
AC_DEFINE(DEBUG, 1, [Define this to enable nano debug messages and assert warnings.])
debug_support=yes
fi])
if test "$debug_support" != "yes"; then
AC_DEFINE(NDEBUG, 1, [Shut up the assert warnings :-)])
fi
AC_ARG_ENABLE(tiny,
[ --enable-tiny Disable features for the sake of size
(currently disables detailed help and i18n)],
@ -31,8 +39,8 @@ AC_ARG_ENABLE(tiny,
AC_DEFINE(DISABLE_HELP, 1, [Define this to disable the ^G help menu.])
AC_DEFINE(DISABLE_JUSTIFY, 1, [Define this to disable the justify routine.])
AC_DEFINE(DISABLE_BROWSER, 1, [Define this to disable the built-in (crappy) file browser.])
AC_DEFINE(DISABLE_MOUSE, 1, [Define this to disable the mouse functions.])
AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable setting of the operating directory (chroot of sorts).])
AC_DEFINE(DISABLE_MOUSE, 1, [Define this to disable the mouse functions.])
AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable setting of the operating directory (chroot of sorts).])
fi])
AC_ARG_ENABLE(extra,
@ -118,7 +126,7 @@ AC_ARG_ENABLE(mouse,
fi])
AC_ARG_ENABLE(operatingdir,
[ --disable-operatingdir Disable setting of operating directory (chroot of sorts)],
[ --disable-operatingdir Disable setting of operating directory (chroot of sorts)],
[if test x$enableval != xyes; then
AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable setting of the operating directory (chroot of sorts).])
fi])
@ -296,8 +304,6 @@ dnl Parse any configure options
LIBS="$LIBS $CURSES_LIB"
AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging (def disabled)],)
AC_SUBST(CURSES_LIB)
if test "x$glib_cflags" != "x"

439
cut.c
View File

@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "proto.h"
#include "nano.h"
@ -34,17 +35,21 @@
#define _(string) (string)
#endif
static int marked_cut; /* Is the cutbuffer from a mark */
static filestruct *cutbottom = NULL; /* Pointer to end of cutbuffer */
static int marked_cut; /* Is the cutbuffer from a mark? */
static filestruct *cutbottom = NULL; /* Pointer to end of cutbuffer */
void add_to_cutbuffer(filestruct * inptr)
filestruct *get_cutbottom(void)
{
return cutbottom;
}
void add_to_cutbuffer(filestruct *inptr)
{
#ifdef DEBUG
fprintf(stderr, _("add_to_cutbuffer called with inptr->data = %s\n"),
inptr->data);
#endif
totsize -= strlen(inptr->data);
if (cutbuffer == NULL) {
cutbuffer = inptr;
inptr->prev = NULL;
@ -58,186 +63,168 @@ void add_to_cutbuffer(filestruct * inptr)
}
#ifndef NANO_SMALL
/* Cut a marked segment instead of a whole line. Only called from
do_cut_text().
destructive is whether to actually modify the file structure, if not then
just copy the buffer into cutbuffer and don't pull it from the file */
void cut_marked_segment(filestruct * top, int top_x, filestruct * bot,
int bot_x, int destructive)
/* Cut a marked segment instead of a whole line.
* The first cut character is top->data[top_x]. Unless top == bot, the
* last cut line has length bot_x. That is, if bot_x > 0 then we cut to
* bot->data[bot_x - 1].
*
* destructive is whether to actually modify the file structure, if not
* then just copy the buffer into cutbuffer and don't pull it from the
* file.
*
* If destructive, then we maintain totsize, totlines, filebot, the
* magic line, and line numbers. Also, we set current and current_x so
* the cursor will be on the first character after what was cut. We do
* not do any screen updates. */
void cut_marked_segment(filestruct *top, size_t top_x, filestruct *bot,
size_t bot_x, int destructive)
{
filestruct *tmp, *next, *botcopy;
char *tmpstr;
int newsize;
filestruct *tmp, *next;
size_t newsize;
if (top == bot && top_x == bot_x)
return;
assert(top != NULL && bot != NULL);
/* Make top be no later than bot. */
if (top->lineno > bot->lineno) {
filestruct *swap = top;
int swap2 = top_x;
top = bot;
bot = swap;
top_x = bot_x;
bot_x = swap2;
} else if (top == bot && top_x > bot_x) {
/* And bot_x can't be an earlier character than top_x. */
int swap = top_x;
top_x = bot_x;
bot_x = swap;
}
/* Make the first cut line manually. */
tmp = copy_node(top);
newsize = (top == bot ? bot_x - top_x : strlen(top->data + top_x));
memmove(tmp->data, top->data + top_x, newsize);
null_at(&tmp->data, newsize);
add_to_cutbuffer(tmp);
/* And make the remainder line manually too. */
if (destructive) {
current_x = top_x;
totsize -= newsize;
totlines -= bot->lineno - top->lineno;
newsize = top_x + strlen(bot->data + bot_x) + 1;
if (top == bot) {
/* In this case, the remainder line is shorter, so we must
move text from the end forward first. */
memmove(top->data + top_x, bot->data + bot_x,
newsize - top_x);
top->data = (char *)nrealloc(top->data,
sizeof(char) * newsize);
} else {
totsize -= bot_x;
/* Here, the remainder line might get longer, so we realloc
it first. */
top->data = (char *)nrealloc(top->data,
sizeof(char) * newsize);
memmove(top->data + top_x, bot->data + bot_x,
newsize - top_x);
}
}
/* Special case for cutting part of one line */
if (top == bot) {
int swap;
tmp = copy_node(top);
newsize = abs(bot_x - top_x) + 1;
tmpstr = charalloc(newsize + 1);
/* Make top_x always be before bot_x */
if (top_x > bot_x) {
swap = top_x;
top_x = bot_x;
bot_x = swap;
}
strncpy(tmpstr, &top->data[top_x], newsize);
if (destructive) {
memmove(&top->data[top_x], &top->data[bot_x],
strlen(&top->data[bot_x]) + 1);
align(&top->data);
current_x = top_x;
update_cursor();
}
tmpstr[newsize - 1] = '\0';
tmp->data = tmpstr;
add_to_cutbuffer(tmp);
#ifdef DEBUG
dump_buffer(cutbuffer);
#endif
return;
}
/* Set up the beginning of the cutbuffer */
tmp = copy_node(top);
tmpstr = charalloc(strlen(&top->data[top_x]) + 1);
strcpy(tmpstr, &top->data[top_x]);
free(tmp->data);
tmp->data = tmpstr;
/* Chop off the end of the first line */
tmpstr = charalloc(top_x + 1);
strncpy(tmpstr, top->data, top_x);
if (destructive) {
free(top->data);
top->data = tmpstr;
}
do {
tmp = top->next;
while (tmp != bot) {
next = tmp->next;
if (destructive)
add_to_cutbuffer(tmp);
else {
filestruct *tmpcopy = NULL;
tmpcopy = copy_node(tmp);
add_to_cutbuffer(tmpcopy);
}
totlines--;
totsize--; /* newline (add_to_cutbuffer doesn't count newlines) */
if (!destructive)
tmp = copy_node(tmp);
else
totsize -= strlen(tmp->data);
add_to_cutbuffer(tmp);
tmp = next;
}
while (next != bot && next != NULL);
/* Make the last cut line manually. */
tmp = copy_node(bot);
null_at(&tmp->data, bot_x);
add_to_cutbuffer(tmp);
#ifdef DEBUG
dump_buffer(cutbuffer);
if (next == NULL)
return;
/* Now, paste bot[bot_x] into top[top_x] */
if (destructive) {
tmpstr = charalloc(top_x + strlen(&bot->data[bot_x]) + 1);
strncpy(tmpstr, top->data, top_x);
strcpy(&tmpstr[top_x], &bot->data[bot_x]);
free(top->data);
top->data = tmpstr;
/* We explicitly don't decrement totlines here because we don't snarf
* up a newline when we're grabbing the last line of the mark. For
* the same reason, we don't do an extra totsize decrement. */
}
/* I honestly do not know why this is needed. After many hours of
using gdb on an OpenBSD box, I can honestly say something is
screwed somewhere. Not doing this causes update_line to annihilate
the last line copied into the cutbuffer when the mark is set ?!?!? */
botcopy = copy_node(bot);
null_at(&botcopy->data, bot_x);
next = botcopy->next;
add_to_cutbuffer(botcopy);
#endif
if (destructive) {
free(bot);
top->next = next;
if (next != NULL)
next->prev = top;
dump_buffer(cutbuffer);
top->next = bot->next;
if (top->next != NULL)
top->next->prev = top;
delete_node(bot);
renumber(top);
current = top;
current_x = top_x;
/* If we're hitting the end of the buffer, we should clean that up. */
if (bot == filebot) {
if (next != NULL) {
filebot = next;
} else {
filebot = top;
if (top_x > 0)
new_magicline();
}
filebot = top;
assert(bot_x == 0);
if (top_x > 0)
new_magicline();
}
if (top->lineno < edittop->lineno)
edit_update(top, CENTER);
}
}
#endif
int do_cut_text(void)
{
filestruct *tmp, *fileptr = current;
filestruct *fileptr;
#ifndef NANO_SMALL
int dontupdate = 0;
int cuttingtoend = 0;
#endif
assert(current != NULL && current->data != NULL);
check_statblank();
if (fileptr == NULL || fileptr->data == NULL)
return 0;
tmp = fileptr->next;
if (!ISSET(KEEP_CUTBUFFER)) {
free_filestruct(cutbuffer);
cutbuffer = NULL;
marked_cut = 0;
#ifdef DEBUG
fprintf(stderr, _("Blew away cutbuffer =)\n"));
#endif
}
/* Must let cutbuffer get blown away first before we do this... */
if (fileptr == filebot && !ISSET(MARK_ISSET))
/* You can't cut the magic line except with the mark. But
trying does clear the cutbuffer if KEEP_CUTBUFFER is not set. */
if (current == filebot
#ifndef NANO_SMALL
&& !ISSET(MARK_ISSET)
#endif
)
return 0;
#ifndef NANO_SMALL
if (ISSET(CUT_TO_END) && !ISSET(MARK_ISSET)) {
if (current_x == strlen(current->data)) {
assert(current_x >= 0 && current_x <= strlen(current->data));
/* If the line is empty and we didn't just cut a non-blank
line, create a dummy line and add it to the cutbuffer */
if (current->data[current_x] == '\0') {
/* If the line is empty and we didn't just cut a non-blank
line, create a dummy line and add it to the cutbuffer */
if (marked_cut != 1 && current->next != filebot) {
filestruct *junk = make_new_node(current);
filestruct *junk;
junk = NULL;
junk = make_new_node(current);
junk->data = charalloc(1);
junk->data[0] = '\0';
add_to_cutbuffer(junk);
#ifdef DEBUG
dump_buffer(cutbuffer);
#endif
}
do_delete();
@ -250,104 +237,69 @@ int do_cut_text(void)
mark_beginx = strlen(current->data);
mark_beginbuf = current;
cuttingtoend = 1;
dontupdate = 1;
}
}
if (ISSET(MARK_ISSET)) {
if (current->lineno <= mark_beginbuf->lineno) {
/* Don't do_update and move the screen position if the marked
area lies entirely within the screen buffer */
if (current->lineno == mark_beginbuf->lineno
|| (current->lineno >= edittop->lineno
&& mark_beginbuf->lineno <= editbot->lineno))
dontupdate = 1;
cut_marked_segment(current, current_x, mark_beginbuf,
mark_beginx, 1);
}
else {
/* Same as above, easier logic since we know it's a multi-line
cut and mark_beginbuf is before current */
if (mark_beginbuf->lineno >= edittop->lineno
&& current->lineno <= editbot->lineno)
dontupdate = 1;
cut_marked_segment(mark_beginbuf, mark_beginx, current,
current_x, 1);
}
/* Don't do_update() and move the screen position if the marked
area lies entirely within the screen buffer */
dontupdate |= current->lineno >= edittop->lineno &&
current->lineno <= editbot->lineno &&
mark_beginbuf->lineno >= edittop->lineno &&
mark_beginbuf->lineno <= editbot->lineno;
cut_marked_segment(current, current_x, mark_beginbuf,
mark_beginx, 1);
placewewant = xplustabs();
UNSET(MARK_ISSET);
marked_cut = 1;
set_modified();
if (dontupdate || cuttingtoend) {
if (dontupdate) {
fix_editbot();
edit_refresh();
} else
edit_update(current, CENTER);
return 1;
#else
if (0) {
#endif
} else if (fileptr == fileage) {
/* we're cutting the first line */
if (fileptr->next != NULL) {
fileptr = fileptr->next;
tmp = fileptr;
fileage = fileptr;
add_to_cutbuffer(fileptr->prev);
totsize--; /* get the newline */
totlines--;
fileptr->prev = NULL;
current = fileptr;
edit_update(fileage, CENTER);
} else {
add_to_cutbuffer(fileptr);
fileage = make_new_node(NULL);
fileage->data = charalloc(1);
fileage->data[0] = '\0';
current = fileage;
}
} else {
if (fileptr->prev != NULL)
fileptr->prev->next = fileptr->next;
if (fileptr->next != NULL) {
(fileptr->next)->prev = fileptr->prev;
current = fileptr->next;
totlines--;
totsize--; /* get the newline */
}
/* No longer an else here, because we never get here anymore...
No need to cut the magic line, as it's empty */
add_to_cutbuffer(fileptr);
}
#endif /* !NANO_SMALL */
totlines--;
totsize -= strlen(current->data) + 1;
fileptr = current;
current = current->next;
current->prev = fileptr->prev;
add_to_cutbuffer(fileptr);
#ifdef DEBUG
dump_buffer(cutbuffer);
#endif
if (fileptr == fileage)
fileage = current;
else
current->prev->next = current;
if (fileptr == edittop)
edittop = current;
renumber(current);
edit_refresh();
dump_buffer(cutbuffer);
reset_cursor();
set_modified();
marked_cut = 0;
current_x = 0;
placewewant = 0;
update_cursor();
renumber(tmp);
reset_cursor();
SET(KEEP_CUTBUFFER);
return 1;
}
int do_uncut_text(void)
{
filestruct *tmp = current, *fileptr = current, *newbuf, *newend;
filestruct *tmp = current, *fileptr = current;
filestruct *newbuf = NULL;
filestruct *newend = NULL;
#ifndef NANO_SMALL
char *tmpstr, *tmpstr2;
filestruct *hold = current;
@ -359,29 +311,35 @@ int do_uncut_text(void)
if (cutbuffer == NULL || fileptr == NULL)
return 0; /* AIEEEEEEEEEEEE */
newbuf = copy_filestruct(cutbuffer);
for (newend = newbuf; newend->next != NULL && newend != NULL;
newend = newend->next) {
totlines++;
#ifndef NANO_SMALL
if (!marked_cut || cutbuffer->next != NULL)
#endif
{
newbuf = copy_filestruct(cutbuffer);
for (newend = newbuf; newend->next != NULL && newend != NULL;
newend = newend->next)
totlines++;
}
/* Hook newbuf into fileptr */
#ifndef NANO_SMALL
if (marked_cut) {
int recenter_me = 0;
/* Should we eventually use edit_update(CENTER)? */
/* If there's only one line in the cutbuffer */
if (cutbuffer->next == NULL) {
tmpstr =
charalloc(strlen(current->data) + strlen(cutbuffer->data) +
1);
strncpy(tmpstr, current->data, current_x);
strcpy(&tmpstr[current_x], cutbuffer->data);
strcat(tmpstr, &current->data[current_x]);
free(current->data);
current->data = tmpstr;
current_x += strlen(cutbuffer->data);
totsize += strlen(cutbuffer->data);
if (strlen(cutbuffer->data) == 0)
totlines++;
size_t buf_len = strlen(cutbuffer->data);
size_t cur_len = strlen(current->data);
current->data = nrealloc(current->data, cur_len + buf_len + 1);
memmove(current->data + current_x + buf_len,
current->data + current_x, cur_len - current_x + 1);
strncpy(current->data + current_x, cutbuffer->data, buf_len);
/* Use strncpy to not copy the terminal '\0'. */
current_x += buf_len;
totsize += buf_len;
/* If we've uncut a line, make sure there's a magicline after
it */
if (current->next == NULL)
@ -417,8 +375,8 @@ int do_uncut_text(void)
newend->next = tmp;
/* If tmp isn't null, we're in the middle: update the
* prev pointer. If it IS null, we're at the end; update
* the filebot pointer */
prev pointer. If it IS null, we're at the end; update
the filebot pointer */
if (tmp != NULL)
tmp->prev = newend;
@ -434,21 +392,16 @@ int do_uncut_text(void)
for (tmp = current->next; tmp != newend; tmp = tmp->next)
totsize += strlen(tmp->data) + 1;
i = editbot->lineno;
current = newend;
if (i < newend->lineno) {
edit_update(current, CENTER);
}
else {
edit_refresh();
}
if (editbot->lineno < newend->lineno)
recenter_me = 1;
}
/* If marked cut == 2, that means that we're doing a cut to end
and we don't want anything else on the line, so we have to
screw up all the work we just did and separate the line. There
must be a better way to do this, but not at 1AM on a work night. */
screw up all the work we just did and separate the line.
There must be a better way to do this, but not at 1AM on a
work night. */
if (marked_cut == 2) {
tmp = make_new_node(current);
@ -467,24 +420,27 @@ int do_uncut_text(void)
/* Renumber from BEFORE where we pasted ;) */
renumber(hold);
#ifdef DEBUG
dump_buffer(fileage);
dump_buffer(cutbuffer);
#endif
set_modified();
edit_refresh();
if (recenter_me)
edit_update(current, CENTER);
else
edit_refresh();
UNSET(KEEP_CUTBUFFER);
return 0;
#else
if (0) {
}
#endif
} else if (fileptr != fileage) {
if (fileptr != fileage) {
tmp = fileptr->prev;
tmp->next = newbuf;
newbuf->prev = tmp;
totlines++; /* Unmarked uncuts don't split lines */
} else {
} else
fileage = newbuf;
totlines++; /* Unmarked uncuts don't split lines */
}
totlines++; /* Unmarked uncuts don't split lines */
/* This is so uncutting at the top of the buffer will work => */
if (current_y == 0)
@ -494,23 +450,22 @@ int do_uncut_text(void)
newend->next = fileptr;
fileptr->prev = newend;
/* recalculate size *sigh* */
/* Recalculate size *sigh* */
for (tmp = newbuf; tmp != fileptr; tmp = tmp->next)
totsize += strlen(tmp->data) + 1;
i = editbot->lineno;
renumber(newbuf);
if (i < newend->lineno) {
if (i < newend->lineno)
edit_update(fileptr, CENTER);
}
else {
else
edit_refresh();
}
dump_buffer_reverse(fileptr);
#ifdef DEBUG
dump_buffer_reverse();
#endif
set_modified();
UNSET(KEEP_CUTBUFFER);
edit_refresh();
return 1;
}

View File

@ -474,7 +474,7 @@ to have a completely consistent user interface across all user input
functions. This means that regardless of whether you're being asked for
a filename to insert or write, or a string to search for, the
previous value is already inserted before the cursor. If you prefer the
old behavior, use the pico emulation mode (-p or --pico) or just hit
old behavior, use the Pico emulation mode (-p or --pico) or just hit
Meta-P while in nano (see the ^G help text for more
details).</font></blockquote>

83
files.c
View File

@ -33,6 +33,7 @@
#include <errno.h>
#include <ctype.h>
#include <dirent.h>
#include <assert.h>
#include <pwd.h>
#include "proto.h"
#include "nano.h"
@ -501,7 +502,9 @@ int do_insertfile(int loading_file)
free(realname);
#ifdef DEBUG
dump_buffer(fileage);
#endif
#ifdef ENABLE_MULTIBUFFER
if (loading_file)
@ -578,6 +581,75 @@ int do_insertfile_void(void)
}
#ifdef ENABLE_MULTIBUFFER
/* Create a new openfilestruct node. */
openfilestruct *make_new_opennode(openfilestruct *prevnode)
{
openfilestruct *newnode = nmalloc(sizeof(openfilestruct));
newnode->filename = NULL;
newnode->fileage = NULL;
newnode->filebot = NULL;
newnode->prev = prevnode;
newnode->next = NULL;
return newnode;
}
/* Splice a node into an existing openfilestruct. */
void splice_opennode(openfilestruct *begin, openfilestruct *newnode,
openfilestruct *end)
{
newnode->next = end;
newnode->prev = begin;
begin->next = newnode;
if (end != NULL)
end->prev = newnode;
}
/* Unlink a node from the rest of the openfilestruct. */
void unlink_opennode(const openfilestruct *fileptr)
{
assert(fileptr != NULL);
if (fileptr->prev != NULL)
fileptr->prev->next = fileptr->next;
if (fileptr->next != NULL)
fileptr->next->prev = fileptr->prev;
}
/* Delete a node from the openfilestruct. */
void delete_opennode(openfilestruct *fileptr)
{
if (fileptr != NULL) {
if (fileptr->filename != NULL)
free(fileptr->filename);
if (fileptr->fileage != NULL)
free_filestruct(fileptr->fileage);
free(fileptr);
}
}
/* Deallocate all memory associated with this and later files,
* including the lines of text. */
void free_openfilestruct(openfilestruct *src)
{
if (src != NULL) {
while (src->next != NULL) {
src = src->next;
delete_opennode(src->prev);
#ifdef DEBUG
fprintf(stderr, _("delete_opennode(): free'd a node, YAY!\n"));
#endif
}
delete_opennode(src);
#ifdef DEBUG
fprintf(stderr, _("delete_opennode(): free'd last node.\n"));
#endif
}
}
/*
* Add/update an entry to the open_files openfilestruct. If update is
* zero, a new entry is created; otherwise, the current entry is updated.
@ -1414,7 +1486,9 @@ int write_file(char *name, int tmp, int append, int nonamechange)
}
}
#ifdef DEBUG
dump_buffer(fileage);
#endif
f = fdopen(fd, append == 1 ? "ab" : "wb");
if (!f) {
@ -2742,20 +2816,11 @@ char *do_browser(char *inpath)
/* Hilight the currently selected file/dir */
if (j == selected) {
#ifdef ENABLE_COLOR
color_on(edit, COLOR_STATUSBAR);
#else
wattron(edit, A_REVERSE);
#endif
}
waddnstr(edit, foo, strlen(foo));
if (j == selected) {
#ifdef ENABLE_COLOR
color_off(edit, COLOR_STATUSBAR);
#else
wattroff(edit, A_REVERSE);
#endif
}
/* And add some space between the cols */

119
global.c
View File

@ -37,6 +37,12 @@
* Global variables
*/
/* wrap_at might be set in rcfile.c or nano.c */
int wrap_at = -CHARS_FROM_EOL;/* Right justified fill value, allows resize */
char *last_search = NULL; /* Last string we searched for */
char *last_replace = NULL; /* Last replacement string */
int search_last_line; /* Is this the last search line? */
int flags = 0; /* Our new flag containing many options */
WINDOW *edit; /* The file portion of the editor */
WINDOW *topwin; /* Top line of screen */
@ -66,10 +72,14 @@ openfilestruct *open_files = NULL; /* The list of open files */
#endif
#ifndef DISABLE_JUSTIFY
#ifdef HAVE_REGEX_H
char *quotestr = "^([ \t]*[|>:}#])+";
#else
char *quotestr = "> "; /* Quote string */
#endif
#endif
char *answer = NULL; /* Answer str to many questions */
char *answer = NULL; /* Answer str to many questions */
int totlines = 0; /* Total number of lines in the file */
long totsize = 0; /* Total number of bytes in the file */
int placewewant = 0; /* The column we'd like the cursor
@ -79,7 +89,9 @@ int placewewant = 0; /* The column we'd like the cursor
int tabsize = 8; /* Our internal tabsize variable */
char *hblank; /* A horizontal blank line */
#ifndef DISABLE_HELP
char *help_text; /* The text in the help window */
#endif
/* More stuff for the marker select */
@ -113,14 +125,13 @@ shortcut *browser_list = NULL;
#endif
#ifdef ENABLE_COLOR
colorstruct colors[NUM_NCOLORS];
colortype *colorstrings = NULL;
syntaxtype *syntaxes = NULL;
char *syntaxstr = NULL;
#endif
#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) || !defined(DISABLE_HELP)
shortcut *currshortcut; /* Current shortcut list we're using */
const shortcut *currshortcut; /* Current shortcut list we're using */
#endif
#ifndef NANO_SMALL
@ -133,23 +144,21 @@ toggle *toggles = NULL;
regex_t search_regexp; /* Global to store compiled search regexp */
regmatch_t regmatches[10]; /* Match positions for parenthetical
subexpressions, max of 10 */
#endif
#ifdef ENABLE_COLOR
regex_t color_regexp; /* Global to store compiled search regexp */
regmatch_t colormatches[1]; /* Match positions for parenthetical */
regex_t color_regexp; /* Global to store compiled search regexp */
regmatch_t colormatches[1]; /* Match positions for parenthetical */
regex_t syntaxfile_regexp; /* Global to store compiled search regexp */
regmatch_t synfilematches[1]; /* Match positions for parenthetical */
regex_t syntaxfile_regexp; /* Global to store compiled search regexp */
regmatch_t synfilematches[1]; /* Match positions for parenthetical */
#endif /* ENABLE_COLOR */
#endif
int length_of_list(const shortcut *s)
{
int i = 0;
for (; s != NULL; s = s->next)
i++;
return i;
}
@ -211,17 +220,15 @@ static void toggle_init_one(int val, const char *desc, int flag)
}
#ifdef DEBUG
/* Deallocate all of the toggles */
/* Deallocate all of the toggles. */
static void free_toggles(void)
{
toggle *pt; /* Think "previous toggle" */
while (toggles != NULL) {
pt = toggles;
toggle *pt = toggles; /* Think "previous toggle" */
toggles = toggles->next;
free(pt);
}
toggles = NULL;
}
#endif
@ -229,10 +236,11 @@ static void toggle_init(void)
{
char *toggle_const_msg, *toggle_autoindent_msg, *toggle_suspend_msg,
*toggle_nohelp_msg, *toggle_picomode_msg, *toggle_mouse_msg,
*toggle_cuttoend_msg, *toggle_wrap_msg, *toggle_noconvert_msg,
*toggle_dos_msg, *toggle_mac_msg, *toggle_backup_msg,
*toggle_smooth_msg;
*toggle_cuttoend_msg, *toggle_noconvert_msg, *toggle_dos_msg,
*toggle_mac_msg, *toggle_backup_msg, *toggle_smooth_msg;
#ifndef DISABLE_WRAPPING
char *toggle_wrap_msg;
#endif
#ifdef ENABLE_MULTIBUFFER
char *toggle_load_msg;
#endif
@ -256,7 +264,9 @@ static void toggle_init(void)
toggle_mac_msg = _("Writing file in Mac format");
toggle_backup_msg = _("Backing up file");
toggle_smooth_msg = _("Smooth scrolling");
#ifndef DISABLE_WRAPPING
toggle_wrap_msg = _("Auto wrap");
#endif
#ifdef ENABLE_MULTIBUFFER
toggle_load_msg = _("Multiple file buffers");
#endif
@ -266,7 +276,9 @@ static void toggle_init(void)
toggle_init_one(TOGGLE_SUSPEND_KEY, toggle_suspend_msg, SUSPEND);
toggle_init_one(TOGGLE_NOHELP_KEY, toggle_nohelp_msg, NO_HELP);
toggle_init_one(TOGGLE_PICOMODE_KEY, toggle_picomode_msg, PICO_MODE);
#ifndef DISABLE_WRAPPING
toggle_init_one(TOGGLE_WRAP_KEY, toggle_wrap_msg, NO_WRAP);
#endif
toggle_init_one(TOGGLE_MOUSE_KEY, toggle_mouse_msg, USE_MOUSE);
toggle_init_one(TOGGLE_CUTTOEND_KEY, toggle_cuttoend_msg, CUT_TO_END);
#ifdef ENABLE_MULTIBUFFER
@ -283,16 +295,12 @@ static void toggle_init(void)
/* Deallocate the given shortcut. */
static void free_shortcutage(shortcut **shortcutage)
{
shortcut *s, *ps;
assert(shortcutage != NULL);
s = *shortcutage;
while (s != NULL) {
ps = s;
s = s->next;
while (*shortcutage != NULL) {
shortcut *ps = *shortcutage;
*shortcutage = (*shortcutage)->next;
free(ps);
}
*shortcutage = NULL;
}
void shortcut_init(int unjustify)
@ -432,7 +440,6 @@ void shortcut_init(int unjustify)
#endif
if (ISSET(PICO_MODE))
#ifdef ENABLE_MULTIBUFFER
/* this is so we can view multiple files */
sc_init_one(&main_list, NANO_INSERTFILE_KEY, _("Read File"),
@ -535,7 +542,7 @@ void shortcut_init(int unjustify)
sc_init_one(&main_list, NANO_ENTER_KEY, _("Enter"),
IFHELP(nano_enter_msg, 0),
KEY_ENTER, NANO_CONTROL_M, NOVIEW, do_enter_void);
KEY_ENTER, NANO_CONTROL_M, NOVIEW, do_enter);
sc_init_one(&main_list, NANO_GOTO_KEY, _("Go To Line"),
IFHELP(nano_goto_msg, NANO_ALT_GOTO_KEY),
@ -544,11 +551,11 @@ void shortcut_init(int unjustify)
#ifndef NANO_SMALL
sc_init_one(&main_list, NANO_NEXTWORD_KEY, _("Next Word"),
IFHELP(_("Move forward one word"), 0),
0, 0, VIEW, do_next_word_void);
0, 0, VIEW, do_next_word);
sc_init_one(&main_list, -9, _("Prev Word"),
IFHELP(_("Move backward one word"), NANO_PREVWORD_KEY), 0, 0,
VIEW, do_prev_word_void);
VIEW, do_prev_word);
#endif
#if !defined(NANO_SMALL) && defined(HAVE_REGEX_H)
sc_init_one(&main_list, -9, _("Find Other Bracket"),
@ -654,10 +661,10 @@ void shortcut_init(int unjustify)
IFHELP(nano_cancel_msg, 0), 0, 0, VIEW, 0);
sc_init_one(&goto_list, NANO_FIRSTLINE_KEY, _("First Line"),
IFHELP(nano_firstline_msg, 0), 0, 0, VIEW, &do_first_line);
IFHELP(nano_firstline_msg, 0), 0, 0, VIEW, do_first_line);
sc_init_one(&goto_list, NANO_LASTLINE_KEY, _("Last Line"),
IFHELP(nano_lastline_msg, 0), 0, 0, VIEW, &do_last_line);
IFHELP(nano_lastline_msg, 0), 0, 0, VIEW, do_last_line);
free_shortcutage(&help_list);
@ -781,11 +788,10 @@ void shortcut_init(int unjustify)
/* This function is called just before calling exit(). Practically, the
* only effect is to cause a segmentation fault if the various data
* structures got bolloxed earlier. Thus, we don't bother having this
* function unless debugging is turned on.
*/
* function unless debugging is turned on. */
#ifdef DEBUG
/* added by SPK for memory cleanup, gracefully return our malloc()s */
void thanks_for_all_the_fish(void)
void thanks_for_all_the_fish(void)
{
#ifndef DISABLE_OPERATINGDIR
if (operating_dir != NULL)
@ -816,15 +822,18 @@ void thanks_for_all_the_fish(void)
free_shortcutage(&whereis_list);
free_shortcutage(&replace_list);
free_shortcutage(&replace_list_2);
free_shortcutage(&help_list);
free_shortcutage(&goto_list);
free_shortcutage(&gotodir_list);
free_shortcutage(&writefile_list);
free_shortcutage(&insertfile_list);
free_shortcutage(&help_list);
free_shortcutage(&spell_list);
#ifndef NANO_SMALL
free_shortcutage(&extcmd_list);
#endif
#ifndef DISABLE_BROWSER
free_shortcutage(&browser_list);
#endif
free_shortcutage(&gotodir_list);
free_shortcutage(&goto_list);
#ifndef NANO_SMALL
free_toggles();
@ -833,19 +842,39 @@ void thanks_for_all_the_fish(void)
#ifdef ENABLE_MULTIBUFFER
if (open_files != NULL) {
/* We free the memory associated with each open file. */
openfilestruct *next;
while (open_files->prev != NULL)
open_files = open_files->prev;
do {
next = open_files->next;
free_openfilestruct(open_files);
open_files = next;
} while (open_files != NULL);
free_openfilestruct(open_files);
}
#else
if (fileage != NULL)
free_filestruct(fileage);
#endif
#ifdef ENABLE_COLOR
free(syntaxstr);
while (syntaxes != NULL) {
syntaxtype *bill = syntaxes;
free(syntaxes->desc);
while (syntaxes->extensions != NULL) {
exttype *bob = syntaxes->extensions;
syntaxes->extensions = bob->next;
free(bob->val);
free(bob);
}
while (syntaxes->color != NULL) {
colortype *bob = syntaxes->color;
syntaxes->color = bob->next;
free(bob->start);
free(bob->end);
free(bob);
}
syntaxes = syntaxes->next;
free(bill);
}
#endif /* ENABLE_COLOR */
}
#endif /* DEBUG */

136
move.c
View File

@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "proto.h"
#include "nano.h"
@ -34,23 +35,6 @@
#define _(string) (string)
#endif
void page_down(void)
{
if (!ISSET(SMOOTHSCROLL)) {
if (editbot != filebot) {
edit_update(editbot->next, CENTER);
center_cursor();
} else {
while (current != filebot)
current = current->next;
edit_update(current, CENTER);
}
} else {
edit_update(editbot, NONE);
}
update_cursor();
}
int do_page_down(void)
{
wrap_reset();
@ -61,7 +45,7 @@ int do_page_down(void)
return 0;
/* AHEM, if we only have a screen or less of text, DON'T do an
edit_update, just move the cursor to editbot! */
edit_update, just move the cursor to editbot! */
if (edittop == fileage && editbot == filebot && totlines < editwinrows) {
current = editbot;
reset_cursor();
@ -103,42 +87,18 @@ int do_end(void)
current_x = strlen(current->data);
placewewant = xplustabs();
update_line(current, current_x);
return 1;
}
/* What happens when we want to go past the bottom of the buffer */
int do_down(void)
{
wrap_reset();
if (current->next != NULL) {
if (placewewant > 0)
current_x = actual_x(current->next, placewewant);
else if (current_x > strlen(current->next->data))
current_x = strlen(current->next->data);
} else {
UNSET(KEEP_CUTBUFFER);
check_statblank();
return 0;
}
if (current_y < editwinrows - 1 && current != editbot)
current_y++;
else
page_down();
update_cursor();
update_line(current->prev, 0);
update_line(current, current_x);
UNSET(KEEP_CUTBUFFER);
check_statblank();
return 1;
}
void page_up(void)
{
if (edittop != fileage) {
if (!ISSET(SMOOTHSCROLL)) {
#ifndef NANO_SMALL
if (ISSET(SMOOTHSCROLL))
edit_update(edittop->prev, TOP);
else
#endif
{
edit_update(edittop, CENTER);
/* Now that we've updated the edit window, edittop might be
at the top of the file; if so, just move the cursor up one
@ -149,8 +109,6 @@ void page_up(void)
current = current->prev;
reset_cursor();
}
} else {
edit_update(edittop->prev, NONE);
}
} else
current_y = 0;
@ -186,35 +144,72 @@ int do_up(void)
{
wrap_reset();
if (current->prev != NULL) {
if (placewewant > 0)
current_x = actual_x(current->prev, placewewant);
else if (current_x > strlen(current->prev->data))
current_x = strlen(current->prev->data);
current_x = actual_x(current->prev, placewewant);
current = current->prev;
if (current_y > 0) {
update_line(current->next, 0);
/* It is necessary to change current first, so the mark
display will change! */
current_y--;
update_line(current, current_x);
} else
page_up();
UNSET(KEEP_CUTBUFFER);
check_statblank();
}
if (current_y > 0)
current_y--;
else
page_up();
return 1;
}
update_cursor();
update_line(current->next, 0);
update_line(current, current_x);
/* Return value 1 means we moved down, 0 means we were already at the
* bottom. */
int do_down(void) {
wrap_reset();
UNSET(KEEP_CUTBUFFER);
check_statblank();
if (current->next == NULL)
return 0;
current = current->next;
current_x = actual_x(current, placewewant);
/* Note current_y is zero-based. This test checks for the cursor
* being on the last row of the edit window. */
if (current_y == editwinrows - 1) {
#ifndef NANO_SMALL
if (ISSET(SMOOTHSCROLL)) {
/* In this case current_y does not change. The cursor
* remains at the bottom of the edit window. */
edittop = edittop->next;
editbot = editbot->next;
edit_refresh();
} else
#endif
{
edit_update(editbot->next, CENTER);
/* sets edittop so editbot->next is centered */
center_cursor();
/* sets current_y = editwinrows / 2 */
}
} else {
update_line(current->prev, 0);
update_line(current, current_x);
current_y++;
}
return 1;
}
int do_right(void)
{
if (current_x < strlen(current->data)) {
current_x++;
} else {
if (do_down())
current_x = 0;
}
assert(current_x <= strlen(current->data));
if (current->data[current_x] != '\0')
current_x++;
else if (current->next) {
do_down();
current_x = 0;
}
placewewant = xplustabs();
update_cursor();
update_line(current, current_x);
UNSET(KEEP_CUTBUFFER);
check_statblank();
@ -226,13 +221,10 @@ int do_left(void)
if (current_x > 0)
current_x--;
else if (current != fileage) {
placewewant = 0;
current_x = strlen(current->prev->data);
do_up();
current_x = strlen(current->data);
}
placewewant = xplustabs();
update_cursor();
update_line(current, current_x);
UNSET(KEEP_CUTBUFFER);
check_statblank();

55
nano.1
View File

@ -6,31 +6,31 @@
.\" Public License for copying conditions. There is NO warranty.
.\"
.\" $Id$
.TH NANO 1 "June 27, 2002"
.TH NANO 1 "July 6, 2002"
.\" Please adjust this date whenever revising the manpage.
.\"
.SH NAME
nano \- Nano's ANOther editor, an enhanced free Pico Clone
.SH SYNOPSIS
.B nano
.RI [options]\ [+LINE] " file"
.I [\+LINE]\ [options]\ [file]
.br
.SH DESCRIPTION
This manual page documents briefly the
.B nano
command.
This manual page documents briefly the \fBnano\fP command.
.PP
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
.\" \fI<whatever>\fP escape sequences to invoke bold face and italics,
.\" respectively.
\fBnano\fP is a small, free and friendly editor which aims to replace
Pico, the default editor included in the non-free Pine package. Rather
than just copying Pico's look and feel,
.B nano
also implements some missing (or disabled by default) features in Pico,
such as "search and replace" and "goto line number".
than just copying Pico's look and feel, \fBnano\fP also implements some
missing (or disabled by default) features in Pico, such as "search and
replace" and "go to line number".
.SH OPTIONS
.TP
.B \+\fILINE\fP
Places cursor at \fILINE\fP on startup.
.TP
.B \-B (\-\-backup)
When saving a file, back up the previous version of it to the current
filename suffixed with a ~.
@ -52,7 +52,7 @@ Write file in Mac format.
.B \-N (\-\-noconvert)
Disable automatic conversion of files from DOS/Mac format.
.TP
.B \-Q [str] (\-\-quotestr=[str])
.B \-Q \fI[str]\fP (\-\-quotestr=\fI[str]\fP)
Set the quoting string for justifying. The default is "> ".
.TP
.B \-R (\-\-regexp)
@ -61,15 +61,15 @@ Enable regular expression matching for search strings, as well as
.TP
.B \-S (\-\-smooth)
Enable smooth scrolling. Text will scroll line-by-line, instead of the
usual chunk-by-chunk behaviour.
usual chunk-by-chunk behavior.
.TP
.B \-T [num] (\-\-tabsize=[num])
.B \-T \fI[num]\fP (\-\-tabsize=\fI[num]\fP)
Set the size (width) of a tab.
.TP
.B \-V (\-\-version)
Show the current version number and author.
.TP
.B \-Y (\-\-syntax=[str])
.B \-Y \fI[str]\fP (\-\-syntax=\fI[str]\fP)
Specify a specific syntax highlighting from the .nanorc to use, if
available.
.TP
@ -93,7 +93,7 @@ a new file, do not follow it. Good for editing files in /tmp, perhaps?
.B \-m (\-\-mouse)
Enable mouse support (if available for your system).
.TP
.B \-o [dir] (\-\-operatingdir=[dir])
.B \-o \fI[dir]\fP (\-\-operatingdir=\fI[dir]\fP)
Set operating directory. Makes nano set up something similar to a
chroot.
.TP
@ -102,13 +102,13 @@ Emulate Pico as closely as possible. This affects both the "shortcut
list" at the bottom of the screen, as well as the display and entry of
previous search and replace strings.
.TP
.B \-r [#cols] (\-\-fill=[#cols])
.B \-r \fI[#cols]\fP (\-\-fill=\fI[#cols]\fP)
Wrap lines at column #cols. By default, this is the width of the
screen, less eight. If this value is negative, wrapping will occur at
#cols from the right of the screen, allowing it to vary along with the
screen width if the screen is resized.
.TP
.B \-s [prog] (\-\-speller=[prog])
.B \-s \fI[prog]\fP (\-\-speller=\fI[prog]\fP)
Enable alternative spell checker command.
.TP
.B \-t (\-\-tempfile)
@ -128,25 +128,22 @@ Enable suspend ability.
.TP
.B \-a, \-b, \-e, \-f, \-g, \-j
Ignored, for compatibility with Pico.
.TP
.B \+LINE
Places cursor at LINE on startup.
.SH NOTES
Nano will try to dump the buffer into an emergency file in some cases.
Mainly, this will happen if Nano receives a SIGHUP or runs out of
memory, when it will write the buffer into a file named "nano.save" if
the buffer didn't have a name already, or will add a ".save" suffix to
the current filename. If an emergency file with that name already exists
in the current directory, ".save" and a number (e.g. ".save.1") will be
suffixed to the current filename in order to make it unique. In
multibuffer mode, nano will write all the open buffers to the respective
emergency files.
\fBnano\fP will try to dump the buffer into an emergency file in some
cases. Mainly, this will happen if \fBnano\fP receives a SIGHUP or runs
out of memory, when it will write the buffer into a file named
"nano.save" if the buffer didn't have a name already, or will add a
".save" suffix to the current filename. If an emergency file with that
name already exists in the current directory, ".save" and a number (e.g.
".save.1") will be suffixed to the current filename in order to make it
unique. In multibuffer mode, \fBnano\fP will write all the open buffers
to the respective emergency files.
.SH BUGS
Please send any comments or bug reports to
.br
.B nano@nano-editor.org.
.br
The nano mailing list is available from
The \fBnano\fP mailing list is available from
.br
.B nano-devel@gnu.org.
To subscribe, email to nano-devel-request@gnu.org with a

View File

@ -3,7 +3,7 @@ Content-type: text/html
<HTML><HEAD><TITLE>Manpage of NANO</TITLE>
</HEAD><BODY>
<H1>NANO</H1>
Section: User Commands (1)<BR>Updated: June 27, 2002<BR><A HREF="#index">Index</A>
Section: User Commands (1)<BR>Updated: July 5, 2002<BR><A HREF="#index">Index</A>
<A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
@ -17,17 +17,14 @@ nano - Nano's ANOther editor, an enhanced free Pico Clone
<B>nano</B>
[options]&nbsp;[+LINE]<I> file</I>
<I>[+LINE]&nbsp;[options]&nbsp;[file]</I>
<BR>
<A NAME="lbAD">&nbsp;</A>
<H2>DESCRIPTION</H2>
This manual page documents briefly the
<B>nano</B>
command.
This manual page documents briefly the <B>nano</B> command.
<P>
@ -35,15 +32,17 @@ command.
<B>nano</B> is a small, free and friendly editor which aims to replace
Pico, the default editor included in the non-free Pine package. Rather
than just copying Pico's look and feel,
<B>nano</B>
also implements some missing (or disabled by default) features in Pico,
such as &quot;search and replace&quot; and &quot;goto line number&quot;.
than just copying Pico's look and feel, <B>nano</B> also implements some
missing (or disabled by default) features in Pico, such as &quot;search and
replace&quot; and &quot;go to line number&quot;.
<A NAME="lbAE">&nbsp;</A>
<H2>OPTIONS</H2>
<DL COMPACT>
<DT><B>+</B><I>LINE</I>
<DD>
Places cursor at <I>LINE</I> on startup.
<DT><B>-B (--backup)</B>
<DD>
@ -71,7 +70,7 @@ Write file in Mac format.
<DD>
Disable automatic conversion of files from DOS/Mac format.
<DT><B>-Q [str] (--quotestr=[str])</B>
<DT><B>-Q </B><I>[str]</I> (--quotestr=<I>[str]</I>)
<DD>
Set the quoting string for justifying. The default is &quot;&gt; &quot;.
@ -84,8 +83,8 @@ Enable regular expression matching for search strings, as well as
<DD>
Enable smooth scrolling. Text will scroll line-by-line, instead of the
usual chunk-by-chunk behaviour.
<DT><B>-T [num] (--tabsize=[num])</B>
usual chunk-by-chunk behavior.
<DT><B>-T </B><I>[num]</I> (--tabsize=<I>[num]</I>)
<DD>
Set the size (width) of a tab.
@ -93,7 +92,7 @@ Set the size (width) of a tab.
<DD>
Show the current version number and author.
<DT><B>-Y (--syntax=[str])</B>
<DT><B>-Y </B><I>[str]</I> (--syntax=<I>[str]</I>)
<DD>
Specify a specific syntax highlighting from the .nanorc to use, if
@ -124,7 +123,7 @@ a new file, do not follow it. Good for editing files in /tmp, perhaps?
<DD>
Enable mouse support (if available for your system).
<DT><B>-o [dir] (--operatingdir=[dir])</B>
<DT><B>-o </B><I>[dir]</I> (--operatingdir=<I>[dir]</I>)
<DD>
Set operating directory. Makes nano set up something similar to a
@ -135,14 +134,14 @@ chroot.
Emulate Pico as closely as possible. This affects both the &quot;shortcut
list&quot; at the bottom of the screen, as well as the display and entry of
previous search and replace strings.
<DT><B>-r [#cols] (--fill=[#cols])</B>
<DT><B>-r </B><I>[#cols]</I> (--fill=<I>[#cols]</I>)
<DD>
Wrap lines at column #cols. By default, this is the width of the
screen, less eight. If this value is negative, wrapping will occur at
#cols from the right of the screen, allowing it to vary along with the
screen width if the screen is resized.
<DT><B>-s [prog] (--speller=[prog])</B>
<DT><B>-s </B><I>[prog]</I> (--speller=<I>[prog]</I>)
<DD>
Enable alternative spell checker command.
@ -170,23 +169,19 @@ Enable suspend ability.
<DD>
Ignored, for compatibility with Pico.
<DT><B>+LINE</B>
<DD>
Places cursor at LINE on startup.
</DL>
<A NAME="lbAF">&nbsp;</A>
<H2>NOTES</H2>
Nano will try to dump the buffer into an emergency file in some cases.
Mainly, this will happen if Nano receives a SIGHUP or runs out of
memory, when it will write the buffer into a file named &quot;nano.save&quot; if
the buffer didn't have a name already, or will add a &quot;.save&quot; suffix to
the current filename. If an emergency file with that name already exists
in the current directory, &quot;.save&quot; and a number (e.g. &quot;.save.1&quot;) will be
suffixed to the current filename in order to make it unique. In
multibuffer mode, nano will write all the open buffers to the respective
emergency files.
<B>nano</B> will try to dump the buffer into an emergency file in some
cases. Mainly, this will happen if <B>nano</B> receives a SIGHUP or runs
out of memory, when it will write the buffer into a file named
&quot;nano.save&quot; if the buffer didn't have a name already, or will add a
&quot;.save&quot; suffix to the current filename. If an emergency file with that
name already exists in the current directory, &quot;.save&quot; and a number (e.g.
&quot;.save.1&quot;) will be suffixed to the current filename in order to make it
unique. In multibuffer mode, <B>nano</B> will write all the open buffers
to the respective emergency files.
<A NAME="lbAG">&nbsp;</A>
<H2>BUGS</H2>
@ -197,7 +192,7 @@ Please send any comments or bug reports to
<BR>
The nano mailing list is available from
The <B>nano</B> mailing list is available from
<BR>
<B><A HREF="mailto:nano-devel@gnu.org">nano-devel@gnu.org</A>.</B>
@ -234,6 +229,6 @@ used by others).
This document was created by
<A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
using the manual pages.<BR>
Time: 21:45:15 GMT, June 27, 2002
Time: 03:38:25 GMT, July 06, 2002
</BODY>
</HTML>

2007
nano.c

File diff suppressed because it is too large Load Diff

48
nano.h
View File

@ -124,6 +124,7 @@ typedef struct shortcut {
struct shortcut *next;
} shortcut;
#ifndef NANO_SMALL
typedef struct toggle {
int val; /* Sequence to toggle the key. Should only need 1 */
const char *desc; /* Description for when toggle is, uh, toggled,
@ -132,19 +133,17 @@ typedef struct toggle {
int flag; /* What flag actually gets toggled */
struct toggle *next;
} toggle;
#endif /* !NANO_SMALL */
#ifdef ENABLE_NANORC
typedef struct rcoption {
char *name;
int flag;
} rcoption;
#endif /* ENABLE_NANORC */
#ifdef ENABLE_COLOR
#define COLORSTRNUM 16
typedef struct colortype {
int fg; /* fg color */
int bg; /* bg color */
@ -162,9 +161,10 @@ typedef struct exttype {
typedef struct syntaxtype {
char *desc; /* Name of this syntax type */
struct exttype *extensions; /* List of extensions that this applies to */
exttype *extensions; /* List of extensions that this applies to */
colortype *color; /* color struct for this syntax */
struct syntaxtype *next;
} syntaxtype;
#endif /* ENABLE_COLOR */
@ -200,12 +200,11 @@ typedef struct syntaxtype {
#define ALT_KEYPAD (1<<25)
#define NO_CONVERT (1<<26)
#define BACKUP_FILE (1<<27)
#define NO_RCFILE (1<<28)
/* Control key sequences, changing these would be very very bad */
#ifndef NANO_SMALL
# define NANO_CONTROL_SPACE 0
#endif
#define NANO_CONTROL_SPACE 0
#define NANO_CONTROL_A 1
#define NANO_CONTROL_B 2
#define NANO_CONTROL_C 3
@ -336,6 +335,8 @@ know what you're doing */
#define NANO_NEXTWORD_KEY NANO_CONTROL_SPACE
#define NANO_PREVWORD_KEY NANO_ALT_SPACE
#ifndef NANO_SMALL
/* Toggles do not exist with NANO_SMALL. */
#define TOGGLE_CONST_KEY NANO_ALT_C
#define TOGGLE_AUTOINDENT_KEY NANO_ALT_I
#define TOGGLE_SUSPEND_KEY NANO_ALT_Z
@ -353,18 +354,18 @@ know what you're doing */
#define TOGGLE_SMOOTH_KEY NANO_ALT_S
#define TOGGLE_NOCONVERT_KEY NANO_ALT_N
#define TOGGLE_BACKUP_KEY NANO_ALT_B
#endif /* !NANO_SMALL */
#define MAIN_VISIBLE 12
#define VIEW 1
#define NOVIEW 0
#define NONE 3
#define TOP 2
#define CENTER 1
#define BOTTOM 0
typedef enum {
CENTER, TOP, NONE
} topmidbotnone;
/* Minimum editor window rows required for Nano to work correctly */
/* Minimum editor window rows required for nano to work correctly */
#define MIN_EDITOR_ROWS 3
/* Default number of characters from end-of-line where text wrapping occurs */
@ -373,25 +374,4 @@ know what you're doing */
/* Minimum fill length (space available for text before wrapping occurs) */
#define MIN_FILL_LENGTH 10
/* Color specific defines */
#ifdef ENABLE_COLOR
typedef struct colorstruct {
int fg;
int bg;
int bold;
int set;
} colorstruct;
#define FIRST_COLORNUM 16
#define COLOR_TITLEBAR 16
#define COLOR_BOTTOMBARS 17
#define COLOR_STATUSBAR 18
#define COLOR_TEXT 19
#define COLOR_MARKER 20
#define NUM_NCOLORS 5
#endif /* ENABLE_COLOR */
#endif /* ifndef NANO_H */
#endif /* !NANO_H */

View File

@ -13,7 +13,7 @@
@dircategory Editors
@direntry
* Nano: (nano). Small and friendly text editor.
* nano: (nano). Small and friendly text editor.
@end direntry
@c tex
@ -35,26 +35,26 @@ This manual is part of the GNU @code{nano} distribution.@*
@sp4
Copyright (C) 1999, 2000, 2001, 2002 Chris Allegretta.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.
@iftex
Permission is granted to process this file through TeX and print the
results, provided the printed document carries copying permission
notice identical to this one except for the removal of this paragraph
(this paragraph not being relevant to the printed manual).
results, provided the printed document carries copying permission notice
identical to this one except for the removal of this paragraph (this
paragraph not being relevant to the printed manual).
@end iftex
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
manual under the conditions for verbatim copying, provided that the
entire resulting derived work is distributed under the terms of a
permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation approved
by the Foundation.
except that this permission notice may be stated in a translation
approved by the Foundation.
You may contact the author by:
e-mail: @email{chrisa@@asty.org}@*
@ -62,7 +62,8 @@ e-mail: @email{chrisa@@asty.org}@*
@node Top, Introduction, (dir), (dir)
This manual documents GNU nano, a small and friendly text editor.
This manual documents GNU @code{nano}, a small and friendly text
editor.
@menu
* Introduction::
@ -77,11 +78,10 @@ This manual documents GNU nano, a small and friendly text editor.
@node Introduction, Editor Basics, Top, Top
@chapter Introduction
GNU @code{nano} is a small and friendly text editor. Besides basic
text editing, @code{nano} offers many extra features like an
interactive search and replace, goto line number, auto-indentation,
feature toggles, internationalization support, and filename tab
completion.
GNU @code{nano} is a small and friendly text editor. Besides basic text
editing, @code{nano} offers many extra features like an interactive
search and replace, goto line number, auto-indentation, feature toggles,
internationalization support, and filename tab completion.
@menu
* Overview::
@ -94,7 +94,7 @@ completion.
@code{nano} [GNU long option] [option] +LINE [ @var{ file ...} ]
The original goal for @code{nano} was a complete bug-for-bug compatible
emulation of Pico, but consistency is now a slightly higher priority.
emulation of Pico, but consistency is now a slightly higher priority.
There is a flag to implement (nearly) complete Pico emulation, (option -p
or GNU long option --pico). This can also be toggled from within
@code{nano} by typing Meta-P. @xref{Pico Compatibility}, for more
@ -122,7 +122,7 @@ Enable multiple file buffers, if available.
@item -K, --keypad
Do not use the ncurses keypad() call unless necessary. Try this flag if
you find that the arrow keys on the numeric keypad do not work for you
under nano.
under @code{nano}.
@item -M, --mac
Write file in Mac format.
@ -172,7 +172,8 @@ Enables the use of the mouse to select text (currently only useful for
running under the X window system).
@item -o [dir], --operatingdir=[dir]
Set operating directory. Makes nano set up something similar to a chroot.
Set operating directory. Makes @code{nano} set up something similar to a
chroot.
@item -p, --pico
Emulate Pico as closely as possible, sacrificing consistency for correct
@ -272,8 +273,8 @@ current file name, or "New Buffer" if the file has not yet been named.
The section on the right will display "Modified" if the file has been
modified since it was last saved or opened.
Special modes: When nano is in "File browser" mode, the center section
will display the current directory instead of the filename.
Special modes: When @code{nano} is in "File browser" mode, the center
section will display the current directory instead of the filename.
@xref{The File Browser}.
@node The Statusbar, Shortcut Lists, The Titlebar, Editor Basics
@ -378,7 +379,7 @@ statusbar and the file browser is exited.
@node Pico Compatibility, Building and Configure Options, The File Browser, Top
@chapter Pico Compatibility
Nano does not completely emulate Pico by default. The following
nano does not completely emulate Pico by default. The following
differences apply to the default mode and Pico Compatibility mode:
@table @code
@ -423,17 +424,17 @@ to force these functions to behave in the Pico fashion.
@node Building and Configure Options, , Pico Compatibility, Top
@chapter Building and Configure Options
Building nano from source is fairly straightforward if you are familiar
Building @code{nano} from source is fairly straightforward if you are familiar
with compiling programs with autoconf support:
tar xvfz nano-x.y.z.tar.gz (where x.y.z is the version of nano)
tar xvfz nano-x.y.z.tar.gz (where x.y.z is the version of @code{nano})
cd nano-x.y.z/
./configure
make
make install
if you are looking to optimize nano for size, you may want to consider
the following command line options:
if you are looking to optimize @code{nano} for size, you may want to
consider the following command line options:
@table @code
@ -448,38 +449,39 @@ Disable the justify (^J)/unjustify (^U) functions in the editor.
Disables spell checker ability.
@item --disable-help
Disables the help function (^G). Disabling this option makes the
binary much smaller, but makes it difficult for new users
to learn more than very basic things about using the editor.
Disables the help function (^G). Disabling this option makes the binary
much smaller, but makes it difficult for new users to learn more than
very basic things about using the editor.
@item --disable-browser
Disables the mini file browser (^O) when reading or writing files.
@item --enable-tiny
This options disables all the above. It also disables some of
the larger internals of the editor, like the marker code (^^) and
the cut to line (-k) option which it depends on to work properly.
It also disables the function toggles and mouse support.
This options disables all the above. It also disables some of the larger
internals of the editor, like the marker code (^^) and the cut to line
(-k) option which it depends on to work properly. It also disables the
function toggles and mouse support.
@item --disable-wrapping
Disables all word wrapping in the editor. This also eliminates the
-w command line flag, as nonwrapping is then the default behavior.
Disables all word wrapping in the editor. This also eliminates the -w
command line flag, as nonwrapping is then the default behavior.
@item --disable-mouse
Disables all mouse functionality. This also disables the -m command line
flag which enables the mouse functions.
Disables all mouse functionality. This also disables the -m command
line flag which enables the mouse functions.
@item --disable-operatingdir
Disables setting of operating directory. This also disables the -o
command line flag.
@item --disable-nls
Disables Native Language support. This will make the available GNU nano
translations unusable.
Disables Native Language support. This will make the available GNU
@code{nano} translations unusable.
@item --with-slang
Compiling GNU nano with Slang is supported, and will make the binary
notably smaller than if compiled with ncurses or other curses libraries.
Compiling GNU @code{nano} with Slang is supported, and will make the
binary notably smaller than if compiled with ncurses or other curses
libraries.
@end table

View File

@ -17,6 +17,8 @@
# set cut
# Use this value instead of the default
# An out-of-range negative value can make nano die complaining that the
# screen is too small
# set fill -8
# Use alternate keypad routines
@ -46,9 +48,12 @@
# Use Pico Compatibility mode for the shortcut lists and search text
# set pico
# Use this as the quoting string. You shouldn't need to change this,
# but...... default "> "
# set quotestr "// "
# The email-quote string. This is a "regular expression" if your
# system supports them, otherwise a literal string. Default
# set quotestr "^([ \t]*[|>:}#])+" if you have regexps, otherwise
# set quotestr "> ".
# You can get old nano quoted-justify behavior via:
# set quotestr "(> )+"
# Do regular expression searches by default
# set regexp
@ -62,7 +67,7 @@
# Allow nano to be suspended with ^Z
# set suspend
# Use this tab size instead of the default
# Use this tab size instead of the default; it must be greater than 0
# set tabsize 4
# Save automatically on exit, don't prompt
@ -85,7 +90,7 @@
# color will use a transparent color. If you don't want this, be sure
# to set the background color to black or white.
# syntax "c-file" ".*\.c" ".*\.h"
# syntax "c-file" ".*\.c$" ".*\.h$"
# color red "\<[A-Z_]\{2,\}\>"
# color green "\<float\>" "\<char\>" "\<int\>" "\<void\>"
# color green "\<static\>" "\<const\>" "\<struct\>"
@ -99,7 +104,7 @@
# color brightyellow "<[^= ]*>" "\"[^"]*\""
# color brightblue "//.*"
# color brightblue start="/\*.*" end="\*/"
# color brightblue start="/\*" end="\*/"
# For this you will probably want to set your editor to "nano -Y mutt"

372
proto.h
View File

@ -29,13 +29,14 @@
#include "nano.h"
extern int wrap_at;
extern int editwinrows;
extern int current_x, current_y, totlines;
extern int placewewant;
extern int mark_beginx, samelinewrap;
extern int mark_beginx;
extern long totsize;
extern int temp_opt;
extern int fill, wrap_at, flags,tabsize;
extern int wrap_at, flags, tabsize;
extern int search_last_line;
extern int currslen;
@ -47,7 +48,10 @@ extern WINDOW *edit, *topwin, *bottomwin;
extern char *filename;
extern struct stat originalfilestat;
extern char *answer;
extern char *hblank, *help_text;
extern char *hblank;
#ifndef DISABLE_HELP
extern char *help_text;
#endif
extern char *last_search;
extern char *last_replace;
#ifndef DISABLE_OPERATINGDIR
@ -57,6 +61,13 @@ extern char *full_operating_dir;
#ifndef DISABLE_SPELLER
extern char *alt_speller;
#endif
#ifndef DISABLE_TABCOMP
char *real_dir_from_tilde(char *buf);
#endif
#ifndef DISABLE_BROWSER
char *do_browse_from(char *inpath);
#endif
extern struct stat fileinfo;
extern filestruct *current, *fileage, *edittop, *editbot, *filebot;
extern filestruct *cutbuffer, *mark_beginbuf;
@ -69,6 +80,8 @@ extern openfilestruct *open_files;
extern colortype *colorstrings;
extern syntaxtype *syntaxes;
extern char *syntaxstr;
extern regex_t color_regexp;
extern regmatch_t colormatches[1];
#endif
extern shortcut *shortcut_list;
@ -83,235 +96,200 @@ extern shortcut *help_list;
#ifndef DISABLE_BROWSER
extern shortcut *browser_list, *gotodir_list;
#endif
extern shortcut *currshortcut;
extern const shortcut *currshortcut;
#ifdef HAVE_REGEX_H
extern int use_regexp, regexp_compiled;
extern regex_t search_regexp;
extern regmatch_t regmatches[10];
#ifdef ENABLE_COLOR
extern regex_t color_regexp;
extern regmatch_t colormatches[1];
extern regex_t syntaxfile_regexp;
extern regmatch_t synfilematches[1];
#endif /* ENABLE_COLOR */
#endif /* HAVE_REGEX_H */
#ifndef NANO_SMALL
extern toggle *toggles;
#endif
extern toggle *toggles;
/* Functions we want available */
/* Programs we want available */
/* Public functions in color.c */
#ifdef ENABLE_COLOR
void set_colorpairs(void);
void do_colorinit(void);
void update_color(void);
#endif /* ENABLE_COLOR */
/* public functions in global.c */
/* Public functions in cut.c */
int do_cut_text(void);
int do_uncut_text(void);
filestruct *get_cutbottom(void);
void add_to_cutbuffer(filestruct *inptr);
void cut_marked_segment(filestruct *top, size_t top_x, filestruct *bot,
size_t bot_x, int destructive);
/* Public functions in files.c */
int write_file(char *name, int tmpfile, int append, int nonamechange);
int open_file(const char *filename, int insert, int quiet);
int read_file(FILE *f, const char *filename, int quiet);
#ifdef ENABLE_MULTIBUFFER
openfilestruct *make_new_opennode(openfilestruct *prevnode);
void splice_opennode(openfilestruct *begin, openfilestruct *newnode, openfilestruct *end);
void unlink_opennode(const openfilestruct *fileptr);
void delete_opennode(openfilestruct *fileptr);
void free_openfilestruct(openfilestruct *src);
int add_open_file(int update);
int close_open_file(void);
int open_prevfile_void(void);
int open_nextfile_void(void);
#endif
#ifndef DISABLE_OPERATINGDIR
int check_operating_dir(char *currpath, int allow_tabcomp);
#endif
int do_writeout(char *path, int exiting, int append);
char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list);
void new_file(void);
int do_writeout_void(void);
int do_insertfile_void(void);
char *get_next_filename(const char *name);
#ifndef DISABLE_SPELLER
char *safe_tempnam(const char *dirname, const char *filename_prefix);
#endif
/* Public functions in global.c */
int length_of_list(const shortcut *s);
void shortcut_init(int unjustify);
#ifdef DEBUG
void thanks_for_all_the_fish(void);
#endif
char *revstrstr(char *haystack, char *needle, char *rev_start);
char *stristr(char *haystack, char *needle);
char *revstristr(char *haystack, char *needle, char *rev_start);
char *strstrwrapper(char *haystack, char *needle, char *rev_start, int line_pos);
int search_init(int replacing);
int renumber(filestruct * fileptr);
int free_filestruct(filestruct * src);
#ifdef ENABLE_MULTIBUFFER
int free_openfilestruct(openfilestruct * src);
#endif
int xplustabs(void);
int do_yesno(int all, int leavecursor, char *msg, ...);
int actual_x(filestruct * fileptr, int xplus);
int strnlenpt(char *buf, int size);
int strlenpt(char *buf);
int statusq(int allowtabs, shortcut s[], char *def, char *msg, ...);
int write_file(char *name, int tmpfile, int append, int nonamechange);
int do_cut_text(void);
int do_uncut_text(void);
int no_help(void);
int renumber_all(void);
int open_file(const char *filename, int insert, int quiet);
int do_insertfile(int loading_file);
int num_of_digits(int n);
int open_pipe(char *command);
int read_file(FILE *f, const char *filename, int quiet);
#ifdef ENABLE_MULTIBUFFER
int add_open_file(int update);
#endif
#ifndef DISABLE_OPERATINGDIR
int check_operating_dir(char *currpath, int allow_tabcomp);
#endif
#ifndef NANO_SMALL
int do_next_word_void(void);
int do_prev_word_void(void);
#endif /* !NANO_SMALL */
int do_writeout(char *path, int exiting, int append);
int do_gotoline(int line, int save_pos);
int is_whole_word(int curr_pos, filestruct *fileptr, char *searchword);
int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx,
int wholewords, int *i);
int do_find_bracket(void);
#if defined (ENABLE_MULTIBUFFER) || !defined (DISABLE_SPELLER)
void do_gotopos(int line, int pos_x, int pos_y, int pos_placewewant);
#endif
/* Now in move.c */
/* Public functions in move.c */
int do_first_line(void);
int do_last_line(void);
size_t xplustabs(void);
size_t actual_x(const filestruct *fileptr, size_t xplus);
size_t strnlenpt(const char *buf, size_t size);
size_t strlenpt(const char *buf);
void reset_cursor(void);
void blank_bottombars(void);
void blank_edit(void);
void blank_statusbar(void);
void blank_statusbar_refresh(void);
void check_statblank(void);
void titlebar(const char *path);
void bottombars(const shortcut *s);
void set_modified(void);
int do_up(void);
int do_down(void);
int do_left(void);
int do_right(void);
int check_wildcard_match(const char *text, const char *pattern);
char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list);
char *real_dir_from_tilde(char *buf);
void signal_init(void);
void unsunder(char *str, int true_len);
void sunder(char *str);
void lowercase(char *src);
void blank_bottombars(void);
void check_wrap(filestruct * inptr);
void dump_buffer(filestruct * inptr);
void align(char **strp);
void edit_refresh(void), edit_refresh_clearok(void);
void edit_update(filestruct * fileptr, int topmidbotnone);
void update_cursor(void);
void delete_node(filestruct * fileptr);
#ifdef ENABLE_MULTIBUFFER
void delete_opennode(openfilestruct * fileptr);
#endif
void set_modified(void);
void dump_buffer_reverse(filestruct * inptr);
void reset_cursor(void);
void check_statblank(void);
void update_line(filestruct * fileptr, int index);
void fix_editbot(void);
void statusbar(char *msg, ...);
void blank_statusbar(void);
void titlebar(char *path);
void previous_line(void);
void center_cursor(void);
void bottombars(const shortcut *s);
void blank_statusbar_refresh(void);
void nperror(const char *s);
void *mallocstrcpy(char *dest, char *src);
void wrap_reset(void);
void display_main_list(void);
void nano_small_msg(void);
void nano_disable_msg(void);
void do_early_abort(void);
void *nmalloc(size_t howmuch);
void *nrealloc(void *ptr, size_t howmuch);
void die(char *msg, ...);
void die_save_file(char *die_filename);
void new_file(void);
void new_magicline(void);
void splice_node(filestruct *begin, filestruct *newnode, filestruct *end);
#ifdef ENABLE_MULTIBUFFER
void splice_opennode(openfilestruct *begin, openfilestruct *newnode, openfilestruct *end);
#endif
void null_at(char **data, int index);
void page_up(void);
void blank_edit(void);
void search_init_globals(void);
void replace_abort(void);
void add_to_cutbuffer(filestruct * inptr);
void do_replace_highlight(int highlight_flag, char *word);
int do_page_up(void);
int do_page_down(void);
int do_home(void);
int do_end(void);
/* Public functions in nano.c */
void renumber(filestruct *fileptr);
void free_filestruct(filestruct *src);
int no_help(void);
void renumber_all(void);
int open_pipe(const char *command);
int do_prev_word(void);
int do_next_word(void);
void delete_node(filestruct *fileptr);
void wrap_reset(void);
void do_early_abort(void);
void die(const char *msg, ...);
void splice_node(filestruct *begin, filestruct *newnode, filestruct *end);
void nano_disabled_msg(void);
void window_init(void);
void do_mouse(void);
void print_view_warning(void);
void unlink_node(filestruct * fileptr);
int do_exit(void);
int do_spell(void);
int do_mark(void);
int do_delete(void);
int do_backspace(void);
int do_tab(void);
int do_justify(void);
int do_enter(void);
int do_wrap(filestruct *inptr);
void signal_init(void);
void handle_sigwinch(int s);
void die_save_file(const char *die_filename);
size_t indent_length(const char *line);
#ifdef ENABLE_MULTIBUFFER
void unlink_opennode(openfilestruct * fileptr);
filestruct *copy_node(const filestruct *src);
filestruct *copy_filestruct(const filestruct *src);
filestruct *make_new_node(filestruct *prevnode);
#ifndef DISABLE_HELP
void help_init(void);
#endif
void cut_marked_segment(filestruct * top, int top_x, filestruct * bot,
int bot_x, int destructive);
/* Public functions in rcfile.c */
#ifdef ENABLE_NANORC
void do_rcfile(void);
#endif
/* Public functions in search.c */
int do_gotoline(int line, int save_pos);
int is_whole_word(int curr_pos, const char *datastr, const char *searchword);
int do_replace_loop(const char *prevanswer, const filestruct *begin,
int *beginx, int wholewords, int *i);
int do_find_bracket(void);
#if defined (ENABLE_MULTIBUFFER) || !defined (DISABLE_SPELLER)
void do_gotopos(int line, int pos_x, int pos_y, int pos_placewewant);
#endif
void search_init_globals(void);
void replace_abort(void);
int do_gotoline_void(void);
int do_search(void);
int do_replace(void);
filestruct *findnextstr(int quiet, int bracket_mode, const filestruct *begin,
int beginx, const char *needle);
/* Public functions in utils.c */
const char *stristr(const char *haystack, const char *needle);
const char *strstrwrapper(const char *haystack, const char *needle,
const char *rev_start, int line_pos);
int num_of_digits(int n);
int check_wildcard_match(const char *text, const char *pattern);
void align(char **strp);
void null_at(char **data, size_t index);
void unsunder(char *str, size_t true_len);
void sunder(char *str);
void nperror(const char *s);
char *mallocstrcpy(char *dest, const char *src);
void *nmalloc(size_t howmuch);
void *nrealloc(void *ptr, size_t howmuch);
void new_magicline(void);
char *charalloc(size_t howmuch);
/* Public functions in winio.c */
int do_yesno(int all, int leavecursor, const char *msg, ...);
int statusq(int allowtabs, const shortcut *s, const char *def,
const char *msg, ...);
void do_replace_highlight(int highlight_flag, const char *word);
void edit_refresh(void);
void edit_refresh_clearok(void);
void edit_update(filestruct *fileptr, topmidbotnone location);
void update_cursor(void);
#ifdef DEBUG
void dump_buffer(const filestruct *inptr);
void dump_buffer_reverse(void);
#endif
void update_line(filestruct *fileptr, int index);
void fix_editbot(void);
void statusbar(const char *msg, ...);
void center_cursor(void);
void display_main_list(void);
#ifdef NANO_EXTRA
void do_credits(void);
#endif
int do_writeout_void(void), do_exit(void), do_gotoline_void(void);
int do_insertfile_void(void), do_search(void);
#ifdef ENABLE_MULTIBUFFER
int load_open_file(void), close_open_file(void);
#endif
int do_page_up(void), do_page_down(void);
int do_cursorpos(int constant), do_cursorpos_void(void), do_spell(void);
int do_home(void), do_end(void), total_refresh(void), do_mark(void);
int do_delete(void), do_backspace(void), do_tab(void), do_justify(void);
int do_first_line(void), do_last_line(void);
int do_replace(void), do_help(void), do_enter_void(void);
int keypad_on(WINDOW * win, int newval);
#ifdef ENABLE_MULTIBUFFER
int open_prevfile(int closing_file), open_nextfile(int closing_file);
int open_prevfile_void(void), open_nextfile_void(void);
#endif
char *charalloc (size_t howmuch);
char *get_next_filename(const char *name);
#if !defined (DISABLE_SPELLER) || !defined (DISABLE_OPERATINGDIR)
char *get_full_path(const char *origpath);
#endif
#ifndef DISABLE_SPELLER
char *check_writable_directory(const char *path);
char *safe_tempnam(const char *dirname, const char *filename_prefix);
#endif
#ifndef DISABLE_BROWSER
char *do_browser(char *path);
struct stat filestat(const char *path);
char *do_browse_from(char *inpath);
#endif
#ifdef ENABLE_COLOR
int do_colorinit(void);
void color_on(WINDOW *win, int whatever);
void color_off(WINDOW *win, int whatever);
void update_color(void);
extern colorstruct colors[NUM_NCOLORS];
#endif /* ENABLE_COLOR */
RETSIGTYPE main_loop (int junk);
filestruct *copy_node(filestruct * src);
filestruct *copy_filestruct(filestruct * src);
filestruct *make_new_node(filestruct * prevnode);
#ifdef ENABLE_MULTIBUFFER
openfilestruct *make_new_opennode(openfilestruct * prevnode);
#endif
filestruct *findnextstr(int quiet, int bracket_mode, filestruct * begin,
int beginx, char *needle);
#ifndef DISABLE_HELP
void help_init(void);
#endif
int do_cursorpos(int constant);
int do_cursorpos_void(void);
int total_refresh(void);
int do_help(void);
int keypad_on(WINDOW *win, int newval);

387
rcfile.c
View File

@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include "config.h"
#include "proto.h"
#include "nano.h"
@ -43,7 +44,7 @@
#endif
/* Static stuff for the nanorc file */
rcoption rcopts[] = {
static rcoption rcopts[] = {
#ifndef NANO_SMALL
{"autoindent", AUTOINDENT},
{"backup", BACKUP_FILE},
@ -52,7 +53,9 @@ rcoption rcopts[] = {
#ifndef NANO_SMALL
{"cut", CUT_TO_END},
#endif
#ifndef DISABLE_WRAPJUSTIFY
{"fill", 0},
#endif
{"keypad", ALT_KEYPAD},
#ifndef DISABLE_MOUSE
{"mouse", USE_MOUSE},
@ -65,7 +68,9 @@ rcoption rcopts[] = {
#endif
{"nofollow", FOLLOW_SYMLINKS},
{"nohelp", NO_HELP},
#ifndef DISABLE_WRAPPING
{"nowrap", NO_WRAP},
#endif
#ifndef DISABLE_OPERATINGDIR
{"operatingdir", 0},
#endif
@ -94,8 +99,8 @@ static int lineno = 0;
static char *nanorc;
/* We have an error in some part of the rcfile; put it on stderr and
make the user hit return to continue starting up nano */
void rcfile_error(char *msg, ...)
make the user hit return to continue starting up nano. */
static void rcfile_error(const char *msg, ...)
{
va_list ap;
@ -109,11 +114,10 @@ void rcfile_error(char *msg, ...)
fprintf(stderr, _("\nPress return to continue starting nano\n"));
while (getchar() != '\n');
}
/* Just print the error (one of many, perhaps) but don't abort, yet */
void rcfile_msg(char *msg, ...)
/* Just print the error (one of many, perhaps) but don't abort, yet. */
static void rcfile_msg(const char *msg, ...)
{
va_list ap;
@ -125,11 +129,10 @@ void rcfile_msg(char *msg, ...)
vfprintf(stderr, msg, ap);
va_end(ap);
fprintf(stderr, "\n");
}
/* Parse the next word from the string. Returns NULL if we hit EOL */
char *parse_next_word(char *ptr)
/* Parse the next word from the string. Returns NULL if we hit EOL. */
static char *parse_next_word(char *ptr)
{
while (*ptr != ' ' && *ptr != '\t' && *ptr != '\n' && *ptr != '\0')
ptr++;
@ -140,15 +143,54 @@ char *parse_next_word(char *ptr)
/* Null terminate and advance ptr */
*ptr++ = 0;
while ((*ptr == ' ' || *ptr == '\t') && *ptr != '\0')
while (*ptr == ' ' || *ptr == '\t')
ptr++;
return ptr;
}
char *parse_next_regex(char *ptr)
/* The keywords operatingdir, fill, tabsize, speller, and quotestr take
* an argument when set. Among these, operatingdir, speller, and
* quotestr have to allow tabs and spaces in the argument. Thus, if the
* next word starts with a ", we say it ends with the last " of the line.
* Otherwise, the word is interpreted as usual. That is so the arguments
* can contain "s too. */
static char *parse_argument(char *ptr) {
const char *ptr_bak = ptr;
char *last_quote = NULL;
assert(ptr != NULL);
if (*ptr != '"')
return parse_next_word(ptr);
do {
ptr++;
if (*ptr == '"')
last_quote = ptr;
} while (*ptr != '\n' && *ptr != '\0');
if (last_quote == NULL) {
if (*ptr == '\0')
ptr = NULL;
else
*ptr++ = '\0';
rcfile_error(_("argument %s has unterminated \""), ptr_bak);
} else {
*last_quote = '\0';
ptr = last_quote + 1;
}
if (ptr != NULL)
while (*ptr == ' ' || *ptr == '\t')
ptr++;
return ptr;
}
#ifdef ENABLE_COLOR
static char *parse_next_regex(char *ptr)
{
while ((*ptr != '"' || (*(ptr+1) != ' ' && *(ptr+1) != '\n'))
while ((*ptr != '"' || (*(ptr + 1) != ' ' && *(ptr + 1) != '\n'))
&& *ptr != '\n' && *ptr != '\0')
ptr++;
@ -156,45 +198,42 @@ char *parse_next_regex(char *ptr)
return NULL;
/* Null terminate and advance ptr */
*ptr++ = 0;
*ptr++ = '\0';
while ((*ptr == ' ' || *ptr == '\t') && *ptr != '\0')
while (*ptr == ' ' || *ptr == '\t')
ptr++;
return ptr;
}
#ifdef ENABLE_COLOR
int colortoint(char *colorname, int *bright)
static int colortoint(const char *colorname, int *bright)
{
int mcolor = 0;
if (colorname == NULL)
return -1;
if (stristr(colorname, "bright")) {
if (!strncasecmp(colorname, "bright", 6)) {
*bright = 1;
colorname += 6;
}
if (!strcasecmp(colorname, "green"))
mcolor += COLOR_GREEN;
mcolor = COLOR_GREEN;
else if (!strcasecmp(colorname, "red"))
mcolor += COLOR_RED;
mcolor = COLOR_RED;
else if (!strcasecmp(colorname, "blue"))
mcolor += COLOR_BLUE;
mcolor = COLOR_BLUE;
else if (!strcasecmp(colorname, "white"))
mcolor += COLOR_WHITE;
mcolor = COLOR_WHITE;
else if (!strcasecmp(colorname, "yellow"))
mcolor += COLOR_YELLOW;
mcolor = COLOR_YELLOW;
else if (!strcasecmp(colorname, "cyan"))
mcolor += COLOR_CYAN;
mcolor = COLOR_CYAN;
else if (!strcasecmp(colorname, "magenta"))
mcolor += COLOR_MAGENTA;
mcolor = COLOR_MAGENTA;
else if (!strcasecmp(colorname, "black"))
mcolor += COLOR_BLACK;
mcolor = COLOR_BLACK;
else {
rcfile_error(_("color %s not understood.\n"
"Valid colors are \"green\", \"red\", \"blue\", \n"
@ -206,10 +245,10 @@ int colortoint(char *colorname, int *bright)
return mcolor;
}
void parse_syntax(FILE * rcstream, char *buf, char *ptr)
static void parse_syntax(char *ptr)
{
syntaxtype *tmpsyntax = NULL;
char *fileregptr = NULL, *nameptr = NULL;
const char *fileregptr = NULL, *nameptr = NULL;
exttype *exttmp = NULL;
while (*ptr == ' ')
@ -232,39 +271,30 @@ void parse_syntax(FILE * rcstream, char *buf, char *ptr)
return;
}
if (syntaxes == NULL) {
syntaxes = nmalloc(sizeof(syntaxtype));
syntaxes->desc = NULL;
syntaxes->desc = mallocstrcpy(syntaxes->desc, nameptr);
syntaxes->color = NULL;
syntaxes->extensions = NULL;
syntaxes->next = NULL;
tmpsyntax = syntaxes;
if (syntaxes == NULL) {
syntaxes = (syntaxtype *)nmalloc(sizeof(syntaxtype));
tmpsyntax = syntaxes;
} else {
for (tmpsyntax = syntaxes; tmpsyntax->next != NULL;
tmpsyntax = tmpsyntax->next)
;
tmpsyntax->next = (syntaxtype *)nmalloc(sizeof(syntaxtype));
tmpsyntax = tmpsyntax->next;
#ifdef DEBUG
fprintf(stderr,
_("Starting a new syntax type\n"));
fprintf(stderr, "string val=%s\n", nameptr);
fprintf(stderr, _("Adding new syntax after 1st\n"));
#endif
} else {
for (tmpsyntax = syntaxes;
tmpsyntax->next != NULL; tmpsyntax = tmpsyntax->next);
}
tmpsyntax->desc = mallocstrcpy(NULL, nameptr);
tmpsyntax->color = NULL;
tmpsyntax->extensions = NULL;
tmpsyntax->next = NULL;
#ifdef DEBUG
fprintf(stderr, _("Adding new syntax after 1st\n"));
fprintf(stderr, _("Starting a new syntax type\n"));
fprintf(stderr, "string val=%s\n", nameptr);
#endif
tmpsyntax->next = nmalloc(sizeof(syntaxtype));
tmpsyntax->next->desc = NULL;
tmpsyntax->next->desc = mallocstrcpy(tmpsyntax->next->desc, nameptr);
tmpsyntax->next->color = NULL;
tmpsyntax->next->extensions = NULL;
tmpsyntax->next->next = NULL;
tmpsyntax = tmpsyntax->next;
}
/* Now load in the extensions to their part of the struct */
while (*ptr != '\n' && *ptr != '\0') {
while (*ptr != '"' && *ptr != '\n' && *ptr != '\0')
ptr++;
@ -276,28 +306,25 @@ void parse_syntax(FILE * rcstream, char *buf, char *ptr)
ptr = parse_next_regex(ptr);
if (tmpsyntax->extensions == NULL) {
tmpsyntax->extensions = nmalloc(sizeof(exttype));
tmpsyntax->extensions->val = NULL;
tmpsyntax->extensions->val = mallocstrcpy(tmpsyntax->extensions->val, fileregptr);
tmpsyntax->extensions->next = NULL;
}
else {
tmpsyntax->extensions = (exttype *)nmalloc(sizeof(exttype));
exttmp = tmpsyntax->extensions;
} else {
for (exttmp = tmpsyntax->extensions; exttmp->next != NULL;
exttmp = exttmp->next);
exttmp->next = nmalloc(sizeof(exttype));
exttmp->next->val = NULL;
exttmp->next->val = mallocstrcpy(exttmp->next->val, fileregptr);
exttmp->next->next = NULL;
exttmp->next = (exttype *)nmalloc(sizeof(exttype));
exttmp = exttmp->next;
}
exttmp->val = mallocstrcpy(NULL, fileregptr);
exttmp->next = NULL;
}
}
/* Parse the color stuff into the colorstrings array */
void parse_colors(FILE * rcstream, char *buf, char *ptr)
static void parse_colors(char *ptr)
{
int fg, bg, bright = 0;
int expectend = 0; /* Do we expect an end= line? */
char *tmp = NULL, *beginning, *fgstr, *bgstr;
char *fgstr;
colortype *tmpcolor = NULL;
syntaxtype *tmpsyntax = NULL;
@ -311,12 +338,11 @@ void parse_colors(FILE * rcstream, char *buf, char *ptr)
if (strstr(fgstr, ",")) {
strtok(fgstr, ",");
bgstr = strtok(NULL, ",");
bg = colortoint(strtok(NULL, ","), &bright);
} else
bgstr = NULL;
bg = -1;
fg = colortoint(fgstr, &bright);
bg = colortoint(bgstr, &bright);
if (syntaxes == NULL) {
rcfile_error(_("Cannot add a color directive without a syntax line"));
@ -331,7 +357,6 @@ void parse_colors(FILE * rcstream, char *buf, char *ptr)
in the colorstrings array, woo! */
while (*ptr != '\0') {
while (*ptr == ' ')
ptr++;
@ -349,45 +374,37 @@ void parse_colors(FILE * rcstream, char *buf, char *ptr)
}
ptr++;
beginning = ptr;
ptr = parse_next_regex(ptr);
tmp = NULL;
tmp = mallocstrcpy(tmp, beginning);
if (tmpsyntax->color == NULL) {
tmpsyntax->color = nmalloc(sizeof(colortype));
tmpsyntax->color->fg = fg;
tmpsyntax->color->bg = bg;
tmpsyntax->color->bright = bright;
tmpsyntax->color->start = tmp;
tmpsyntax->color->next = NULL;
tmpcolor = tmpsyntax->color;
#ifdef DEBUG
fprintf(stderr,
_("Starting a new colorstring for fg %d bg %d\n"),
fprintf(stderr, _("Starting a new colorstring for fg %d bg %d\n"),
fg, bg);
fprintf(stderr, _("string val=%s\n"), tmp);
#endif
} else {
for (tmpcolor = tmpsyntax->color;
tmpcolor->next != NULL; tmpcolor = tmpcolor->next);
#ifdef DEBUG
fprintf(stderr, _("Adding new entry for fg %d bg %d\n"), fg, bg);
fprintf(stderr, _("string val=%s\n"), tmp);
#endif
tmpcolor->next = nmalloc(sizeof(colortype));
tmpcolor->next->fg = fg;
tmpcolor->next->bg = bg;
tmpcolor->next->bright = bright;
tmpcolor->next->start = tmp;
tmpcolor->next->next = NULL;
tmpcolor = tmpcolor->next;
}
tmpcolor->fg = fg;
tmpcolor->bg = bg;
tmpcolor->bright = bright;
tmpcolor->next = NULL;
if (expectend) {
tmpcolor->start = ptr;
ptr = parse_next_regex(ptr);
tmpcolor->start = mallocstrcpy(NULL, tmpcolor->start);
#ifdef DEBUG
fprintf(stderr, _("string val=%s\n"), tmpcolor->start);
#endif
if (!expectend)
tmpcolor->end = NULL;
else {
if (ptr == NULL || strncasecmp(ptr, "end=", 4)) {
rcfile_error(_
("\n\t\"start=\" requires a corresponding \"end=\""));
@ -403,37 +420,30 @@ void parse_colors(FILE * rcstream, char *buf, char *ptr)
}
ptr++;
beginning = ptr;
tmpcolor->end = ptr;
ptr = parse_next_regex(ptr);
tmpcolor->end = mallocstrcpy(NULL, tmpcolor->end);
#ifdef DEBUG
fprintf(stderr, _("For end part, beginning = \"%s\"\n"),
beginning);
tmpcolor->end);
#endif
tmp = NULL;
tmp = mallocstrcpy(tmp, beginning);
tmpcolor->end = tmp;
} else
tmpcolor->end = NULL;
}
}
}
#endif /* ENABLE_COLOR */
/* Parse the RC file, once it has been opened successfully */
void parse_rcfile(FILE * rcstream)
static void parse_rcfile(FILE *rcstream)
{
char *buf, *ptr, *keyword, *option;
int set = 0, i, j;
buf = charalloc(1024);
while (fgets(buf, 1023, rcstream) > 0) {
while (fgets(buf, 1023, rcstream) != 0) {
lineno++;
ptr = buf;
while ((*ptr == ' ' || *ptr == '\t') &&
(*ptr != '\n' && *ptr != '\0'))
while (*ptr == ' ' || *ptr == '\t')
ptr++;
if (*ptr == '\n' || *ptr == '\0')
@ -459,9 +469,9 @@ void parse_rcfile(FILE * rcstream)
set = -1;
#ifdef ENABLE_COLOR
else if (!strcasecmp(keyword, "syntax"))
parse_syntax(rcstream, buf, ptr);
parse_syntax(ptr);
else if (!strcasecmp(keyword, "color"))
parse_colors(rcstream, buf, ptr);
parse_colors(ptr);
#endif /* ENABLE_COLOR */
else {
rcfile_msg(_("command %s not understood"), keyword);
@ -480,21 +490,20 @@ void parse_rcfile(FILE * rcstream)
rcopts[i].name);
#endif
if (set == 1 || rcopts[i].flag == FOLLOW_SYMLINKS) {
if (!strcasecmp(rcopts[i].name, "operatingdir") ||
!strcasecmp(rcopts[i].name, "tabsize") ||
if (!strcasecmp(rcopts[i].name, "tabsize")
#ifndef DISABLE_OPERATINGDIR
|| !strcasecmp(rcopts[i].name, "operatingdir")
#endif
#ifndef DISABLE_WRAPJUSTIFY
!strcasecmp(rcopts[i].name, "fill") ||
|| !strcasecmp(rcopts[i].name, "fill")
#endif
#ifndef DISABLE_JUSTIFY
!strcasecmp(rcopts[i].name, "quotestr") ||
|| !strcasecmp(rcopts[i].name, "quotestr")
#endif
#ifndef DISABLE_SPELLER
!strcasecmp(rcopts[i].name, "speller")
#else
0
|| !strcasecmp(rcopts[i].name, "speller")
#endif
) {
) {
if (*ptr == '\n' || *ptr == '\0') {
rcfile_error(_
("option %s requires an argument"),
@ -502,42 +511,54 @@ void parse_rcfile(FILE * rcstream)
continue;
}
option = ptr;
ptr = parse_next_word(ptr);
if (!strcasecmp(rcopts[i].name, "fill")) {
if (*option == '"')
option++;
ptr = parse_argument(ptr);
#ifdef DEBUG
fprintf(stderr, "option = %s\n", option);
#endif
#ifndef DISABLE_OPERATINGDIR
if (!strcasecmp(rcopts[i].name, "operatingdir"))
operating_dir = mallocstrcpy(NULL, option);
else
#endif
#ifndef DISABLE_WRAPJUSTIFY
if (!strcasecmp(rcopts[i].name, "fill")) {
char *first_error;
if ((j = atoi(option)) < MIN_FILL_LENGTH) {
rcfile_error(_
("requested fill size %d too small"),
/* Using strtol instead of atoi lets us
* accept 0 while checking other
* errors. */
j = (int)strtol(option, &first_error, 10);
if (errno == ERANGE || *option == '\0' || *first_error != '\0')
rcfile_error(_("requested fill size %d invalid"),
j);
} else
fill = j;
#endif
else
wrap_at = j;
} else
if (!strcasecmp(rcopts[i].name, "tabsize"))
{
if ((j = atoi(option)) <= 0) {
rcfile_error(_
("requested tab size %d too small"),
j);
} else {
tabsize = j;
}
#endif
#ifndef DISABLE_JUSTIFY
} else
if (!strcasecmp(rcopts[i].name, "quotestr"))
{
quotestr = NULL;
quotestr =
charalloc(strlen(option) + 1);
strcpy(quotestr, option);
if (!strcasecmp(rcopts[i].name, "quotestr"))
quotestr = mallocstrcpy(NULL, option);
else
#endif
} else {
#ifndef DISABLE_SPELLER
alt_speller =
charalloc(strlen(option) + 1);
strcpy(alt_speller, option);
if (!strcasecmp(rcopts[i].name, "speller"))
alt_speller = mallocstrcpy(NULL, option);
else
#endif
{
char *first_error;
/* Using strtol instead of atoi lets us
* accept 0 while checking other
* errors. */
j = (int)strtol(option, &first_error, 10);
if (errno == ERANGE || *option == '\0' || *first_error != '\0')
rcfile_error(_("requested tab size %d invalid"),
j);
else
tabsize = j;
}
} else
SET(rcopts[i].flag);
@ -555,8 +576,8 @@ void parse_rcfile(FILE * rcstream)
}
}
}
}
free(buf);
if (errors)
rcfile_error(_("Errors found in .nanorc file"));
@ -566,56 +587,48 @@ void parse_rcfile(FILE * rcstream)
/* The main rc file function, tries to open the rc file */
void do_rcfile(void)
{
char *unable = _("Unable to open ~/.nanorc file, %s");
struct stat fileinfo;
FILE *rcstream;
struct passwd *userage;
const struct passwd *userage;
uid_t euid = geteuid();
nanorc = charalloc(strlen(SYSCONFDIR) + 10);
#ifdef SYSCONFDIR
assert(sizeof(SYSCONFDIR) == strlen(SYSCONFDIR) + 1);
nanorc = charalloc(sizeof(SYSCONFDIR) + 7);
sprintf(nanorc, "%s/nanorc", SYSCONFDIR);
/* Try to open system nanorc */
if (stat(nanorc, &fileinfo) != -1)
if ((rcstream = fopen(nanorc, "r")) != NULL) {
if ((rcstream = fopen(nanorc, "r")) != NULL) {
/* Parse it! */
parse_rcfile(rcstream);
fclose(rcstream);
}
#endif
/* Parse it! */
parse_rcfile(rcstream);
fclose(rcstream);
}
/* Determine home directory using getpwent(), don't rely on $HOME */
do {
userage = getpwent();
} while (userage != NULL && userage->pw_uid != euid);
endpwent();
lineno = 0;
/* Determine home directory using getpwent(), don't rely on $HOME */
for (userage = getpwent(); userage != NULL
&& userage->pw_uid != geteuid(); userage = getpwent())
;
if (userage == NULL) {
if (userage == NULL)
rcfile_error(_("I can't find my home directory! Wah!"));
return;
else {
nanorc = nrealloc(nanorc, strlen(userage->pw_dir) + 9);
sprintf(nanorc, "%s/.nanorc", userage->pw_dir);
if ((rcstream = fopen(nanorc, "r")) == NULL) {
/* Don't complain about the file not existing */
if (errno != ENOENT)
rcfile_error(_("Unable to open ~/.nanorc file, %s"),
strerror(errno));
} else {
parse_rcfile(rcstream);
fclose(rcstream);
}
}
nanorc = charalloc(strlen(userage->pw_dir) + 10);
sprintf(nanorc, "%s/.nanorc", userage->pw_dir);
if (stat(nanorc, &fileinfo) == -1) {
/* Abort if the file doesn't exist and there's some other kind
of error stat()ing it */
if (errno != ENOENT)
rcfile_error(unable, strerror(errno));
return;
}
if ((rcstream = fopen(nanorc, "r")) == NULL) {
rcfile_error(unable, strerror(errno));
return;
}
parse_rcfile(rcstream);
fclose(rcstream);
free(nanorc);
}
#endif /* ENABLE_NANORC */

303
search.c
View File

@ -26,6 +26,7 @@
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include "proto.h"
#include "nano.h"
@ -70,7 +71,7 @@ void search_init_globals(void)
replacing = 1 if we call from do_replace, 0 if called from do_search func.
*/
int search_init(int replacing)
static int search_init(int replacing)
{
int i = 0;
char *buf;
@ -78,10 +79,6 @@ int search_init(int replacing)
search_init_globals();
buf = charalloc(strlen(last_search) + 5);
buf[0] = '\0';
/* Clear the backupstring if we've changed from Pico mode to regular
mode */
if (ISSET(CLEAR_BACKUPSTRING)) {
@ -96,7 +93,7 @@ int search_init(int replacing)
old string back up as editable if it's not the same as last_search.
Otherwise, if we don't already have a backupstring, set it to
last_search. */
last_search. */
if (ISSET(PICO_MODE)) {
if (backupstring == NULL || !strcmp(backupstring, last_search))
@ -106,21 +103,20 @@ int search_init(int replacing)
backupstring = mallocstrcpy(backupstring, last_search);
/* If using Pico messages, we do things the old fashioned way... */
if (ISSET(PICO_MODE)) {
if (last_search[0]) {
if (ISSET(PICO_MODE) && last_search[0]) {
size_t last_search_len = strlen(last_search);
/* We use COLS / 3 here because we need to see more on the line */
if (strlen(last_search) > COLS / 3) {
snprintf(buf, COLS / 3 + 3, " [%s", last_search);
sprintf(&buf[COLS / 3 + 2], "...]");
} else
sprintf(buf, " [%s]", last_search);
} else {
buf[0] = '\0';
}
}
else
buf = charalloc(last_search_len > COLS / 3 ?
COLS / 3 + 7 : last_search_len + 4);
/* We use COLS / 3 here because we need to see more on the line */
if (last_search_len > COLS / 3)
snprintf(buf, COLS / 3 + 7, " [%s...]", last_search);
else
sprintf(buf, " [%s]", last_search);
} else {
buf = charalloc(1);
buf[0] = '\0';
}
/* This is now one simple call. It just does a lot */
i = statusq(0, replacing ? replace_list : whereis_list, backupstring,
@ -146,120 +142,107 @@ int search_init(int replacing)
free(buf);
/* Cancel any search, or just return with no previous search */
if ((i == -1) || (i < 0 && !last_search[0])) {
if (i == -1 || (i < 0 && last_search[0] == '\0')) {
statusbar(_("Search Cancelled"));
reset_cursor();
free(backupstring);
backupstring = NULL;
return -1;
} else
switch (i) {
case -2: /* Same string */
} else {
switch (i) {
case -2: /* Same string */
#ifdef HAVE_REGEX_H
if (ISSET(USE_REGEXP)) {
/* If we're in pico mode, answer is "", use last_search! */
if (ISSET(PICO_MODE))
regexp_init(last_search);
else
if (ISSET(USE_REGEXP))
/* If we're in Pico mode, and answer is "", use
last_search! */
regexp_init(ISSET(PICO_MODE) ? last_search : answer);
#endif
break;
case 0: /* They entered something new */
#ifdef HAVE_REGEX_H
if (ISSET(USE_REGEXP))
regexp_init(answer);
#endif
free(backupstring);
backupstring = NULL;
last_replace[0] = '\0';
break;
#ifndef NANO_SMALL
case TOGGLE_CASE_KEY:
TOGGLE(CASE_SENSITIVE);
backupstring = mallocstrcpy(backupstring, answer);
return 1;
case TOGGLE_BACKWARDS_KEY:
TOGGLE(REVERSE_SEARCH);
backupstring = mallocstrcpy(backupstring, answer);
return 1;
#ifdef HAVE_REGEX_H
case TOGGLE_REGEXP_KEY:
TOGGLE(USE_REGEXP);
backupstring = mallocstrcpy(backupstring, answer);
return 1;
#endif
#endif /* !NANO_SMALL */
case NANO_OTHERSEARCH_KEY:
backupstring = mallocstrcpy(backupstring, answer);
return -2; /* Call the opposite search function */
case NANO_FROMSEARCHTOGOTO_KEY:
free(backupstring);
backupstring = NULL;
do_gotoline_void();
return -3;
default:
do_early_abort();
free(backupstring);
backupstring = NULL;
return -3;
}
#endif
break;
case 0: /* They entered something new */
#ifdef HAVE_REGEX_H
if (ISSET(USE_REGEXP))
regexp_init(answer);
#endif
free(backupstring);
backupstring = NULL;
last_replace[0] = '\0';
break;
case TOGGLE_CASE_KEY:
TOGGLE(CASE_SENSITIVE);
goto string_reinit;
case TOGGLE_BACKWARDS_KEY:
TOGGLE(REVERSE_SEARCH);
goto string_reinit;
#ifdef HAVE_REGEX_H
case TOGGLE_REGEXP_KEY:
TOGGLE(USE_REGEXP);
#endif
string_reinit:
free(backupstring);
backupstring = NULL;
backupstring = mallocstrcpy(backupstring, answer);
return 1;
case NANO_OTHERSEARCH_KEY:
backupstring = mallocstrcpy(backupstring, answer);
return -2; /* Call the opposite search function */
case NANO_FROMSEARCHTOGOTO_KEY:
free(backupstring);
backupstring = NULL;
do_gotoline_void();
return -3;
default:
do_early_abort();
free(backupstring);
backupstring = NULL;
return -3;
}
return 0;
}
void not_found_msg(char *str)
void not_found_msg(const char *str)
{
if (strlen(str) <= COLS / 2)
statusbar(_("\"%s\" not found"), str);
else {
char *foo = NULL;
char *foo = mallocstrcpy(NULL, str);
foo = mallocstrcpy(foo, str);
foo[COLS / 2] = '\0';
statusbar(_("\"%s...\" not found"), foo);
free(foo);
}
}
int is_whole_word(int curr_pos, filestruct *fileptr, char *searchword)
int is_whole_word(int curr_pos, const char *datastr, const char *searchword)
{
/* start of line or previous character not a letter */
if ((curr_pos < 1) || (!isalpha((int) fileptr->data[curr_pos-1])))
size_t sln = curr_pos + strlen(searchword);
/* end of line or next character not a letter */
if (((curr_pos + strlen(searchword)) == strlen(fileptr->data))
|| (!isalpha((int) fileptr->data[curr_pos + strlen(searchword)])))
return TRUE;
return FALSE;
/* start of line or previous character not a letter and end of line
* or next character not a letter */
return (curr_pos < 1 || !isalpha((int) datastr[curr_pos - 1])) &&
(sln == strlen(datastr) || !isalpha((int) datastr[sln]));
}
int past_editbuff; /* findnextstr() is now searching lines not displayed */
static int past_editbuff;
/* findnextstr() is now searching lines not displayed */
filestruct *findnextstr(int quiet, int bracket_mode, filestruct * begin, int beginx,
char *needle)
filestruct *findnextstr(int quiet, int bracket_mode,
const filestruct *begin, int beginx, const char *needle)
{
filestruct *fileptr = current;
char *searchstr, *rev_start = NULL, *found = NULL;
const char *searchstr, *rev_start = NULL, *found = NULL;
int current_x_find = 0;
past_editbuff = 0;
if (!ISSET(REVERSE_SEARCH)) { /* forward search */
current_x_find = current_x + 1;
#if 0
/* Are we now back to the place where the search started) */
if ((fileptr == begin) && (beginx > current_x_find))
search_last_line = 1;
#endif
/* Make sure we haven't passed the end of the string */
if (strlen(fileptr->data) < current_x_find)
current_x_find--;
/* Argh, current_x is set to -1 by nano.c:do_int_spell_fix(), and
* strlen returns size_t, which is unsigned. */
assert(current_x < 0 || current_x <= strlen(fileptr->data));
current_x_find = current_x;
if (current_x_find < 0 || fileptr->data[current_x_find] != '\0')
current_x_find++;
searchstr = &fileptr->data[current_x_find];
@ -306,35 +289,22 @@ filestruct *findnextstr(int quiet, int bracket_mode, filestruct * begin, int beg
/* We found an instance */
current_x_find = found - fileptr->data;
#if 1
/* Ensure we haven't wrapped around again! */
if ((search_last_line) && (current_x_find > beginx)) {
if (!quiet)
not_found_msg(needle);
return NULL;
}
#endif
}
#ifndef NANO_SMALL
else { /* reverse search */
current_x_find = current_x - 1;
#if 0
/* Are we now back to the place where the search started) */
if ((fileptr == begin) && (current_x_find > beginx))
search_last_line = 1;
#endif
/* Make sure we haven't passed the begining of the string */
#if 0 /* Is this required here ? */
if (!(&fileptr->data[current_x_find] - fileptr->data))
current_x_find++;
#endif
rev_start = &fileptr->data[current_x_find];
searchstr = fileptr->data;
/* Look for needle in searchstr */
while ((found = strstrwrapper(searchstr, needle, rev_start, current_x_find)) == NULL) {
/* finished processing file, get out */
if (search_last_line) {
if (!quiet)
@ -363,7 +333,6 @@ filestruct *findnextstr(int quiet, int bracket_mode, filestruct * begin, int beg
SET(DISABLE_CURPOS);
}
}
/* Original start line reached */
if (fileptr == begin)
search_last_line = 1;
@ -374,16 +343,14 @@ filestruct *findnextstr(int quiet, int bracket_mode, filestruct * begin, int beg
/* We found an instance */
current_x_find = found - fileptr->data;
#if 1
/* Ensure we haven't wrapped around again! */
if ((search_last_line) && (current_x_find < beginx)) {
if (!quiet)
not_found_msg(needle);
return NULL;
}
#endif
}
#endif /* NANO_SMALL */
#endif /* !NANO_SMALL */
/* Set globals now that we are sure we found something */
current = fileptr;
@ -398,7 +365,6 @@ filestruct *findnextstr(int quiet, int bracket_mode, filestruct * begin, int beg
placewewant = xplustabs();
reset_cursor();
}
return fileptr;
}
@ -416,7 +382,7 @@ void search_abort(void)
#endif
}
/* Search for a string */
/* Search for a string. */
int do_search(void)
{
int i;
@ -499,8 +465,8 @@ int replace_regexp(char *string, int create_flag)
new_size -= search_match_count;
/* Iterate through the replacement text to handle
* subexpression replacement using \1, \2, \3, etc */
/* Iterate through the replacement text to handle subexpression
* replacement using \1, \2, \3, etc. */
c = last_replace;
while (*c) {
@ -517,7 +483,7 @@ int replace_regexp(char *string, int create_flag)
if (num > search_regexp.re_nsub) {
/* Ugh, they specified a subexpression that doesn't
exist. */
exist. */
return -1;
}
@ -588,12 +554,12 @@ char *replace_line(void)
#endif
/* The tail of the original line */
/* This may expose other bugs, because it no longer
goes through each character in the string
and tests for string goodness. But because
we can assume the invariant that current->data
is less than current_x + strlen(last_search) long,
this should be safe. Or it will expose bugs ;-) */
/* This may expose other bugs, because it no longer goes through
* each character in the string and tests for string goodness. But
* because we can assume the invariant that current->data is less
* than current_x + strlen(last_search) long, this should be safe.
* Or it will expose bugs ;-) */
tmp = current->data + current_x + search_match_count;
strcat(copy, tmp);
@ -601,8 +567,8 @@ char *replace_line(void)
}
/* step through each replace word and prompt user before replacing word */
int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx,
int wholewords, int *i)
int do_replace_loop(const char *prevanswer, const filestruct *begin,
int *beginx, int wholewords, int *i)
{
int replaceall = 0, numreplaced = 0;
@ -610,7 +576,7 @@ int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx,
char *copy;
switch (*i) {
case -1: /* Aborted enter */
case -1: /* Aborted enter */
if (last_replace[0] != '\0')
answer = mallocstrcpy(answer, last_replace);
statusbar(_("Replace Cancelled"));
@ -619,8 +585,8 @@ int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx,
case 0: /* They actually entered something */
break;
default:
if (*i != -2) { /* First page, last page, for example
could get here */
if (*i != -2) { /* First page, last page, for example, could
get here */
do_early_abort();
replace_abort();
return 0;
@ -632,28 +598,20 @@ int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx,
last_replace = mallocstrcpy(last_replace, answer);
while (1) {
/* Sweet optimization by Rocco here */
#if 0
fileptr = findnextstr(replaceall, FALSE, begin, *beginx, prevanswer);
#else
if (fileptr != 0)
fileptr = findnextstr(1, FALSE, begin, *beginx, prevanswer);
else
fileptr = findnextstr(replaceall || (search_last_line ? 1 : 0), FALSE, begin, *beginx, prevanswer);
#endif
fileptr = findnextstr(fileptr || replaceall || search_last_line,
FALSE, begin, *beginx, prevanswer);
/* No more matches. Done! */
if (!fileptr)
break;
/* Make sure only whole words are found */
if ((wholewords) && (!is_whole_word(current_x, fileptr, prevanswer)))
if (wholewords && !is_whole_word(current_x, fileptr->data, prevanswer))
continue;
/* If we're here, we've found the search string */
if (!replaceall) {
curs_set(0);
do_replace_highlight(TRUE, prevanswer);
@ -681,7 +639,8 @@ int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx,
totsize += strlen(current->data);
if (!ISSET(REVERSE_SEARCH)) {
/* Stop bug where we replace a substring of the replacement text */
/* Stop bug where we replace a substring of the
replacement text */
current_x += strlen(last_replace) - 1;
/* Adjust the original cursor position - COULD BE IMPROVED */
@ -689,6 +648,7 @@ int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx,
*beginx += strlen(last_replace) - strlen(last_search);
/* For strings that cross the search start/end boundary */
/* Don't go outside of allocated memory */
if (*beginx < 1)
*beginx = 1;
@ -708,7 +668,8 @@ int do_replace_loop(char *prevanswer, filestruct *begin, int *beginx,
edit_refresh();
set_modified();
numreplaced++;
} else if (*i == -1) /* Abort, else do nothing and continue loop */
} else if (*i == -1) /* Abort, else do nothing and continue
loop */
break;
}
@ -720,7 +681,7 @@ int do_replace(void)
{
int i, numreplaced, beginx;
filestruct *begin;
char *prevanswer = NULL, *buf = NULL;
char *prevanswer = NULL;
if (ISSET(VIEW_MODE)) {
print_view_warning();
@ -754,53 +715,37 @@ int do_replace(void)
/* If answer is now == "", then PICO_MODE is set. So, copy
last_search into answer (and prevanswer)... */
if (answer[0] == '\0') {
if (answer[0] == '\0')
answer = mallocstrcpy(answer, last_search);
prevanswer = mallocstrcpy(prevanswer, last_search);
} else {
last_search = mallocstrcpy(last_search, answer);
prevanswer = mallocstrcpy(prevanswer, answer);
}
if (ISSET(PICO_MODE)) {
buf = charalloc(strlen(last_replace) + 5);
if (last_replace[0] != '\0') {
if (strlen(last_replace) > (COLS / 3)) {
strncpy(buf, last_replace, COLS / 3);
sprintf(&buf[COLS / 3 - 1], "...");
} else
sprintf(buf, "%s", last_replace);
i = statusq(0, replace_list_2, "",
_("Replace with [%s]"), buf);
}
else
i = statusq(0, replace_list_2, "",
_("Replace with"));
}
else
i = statusq(0, replace_list_2, last_replace,
_("Replace with"));
last_search = mallocstrcpy(last_search, answer);
prevanswer = mallocstrcpy(prevanswer, last_search);
if (ISSET(PICO_MODE) && last_replace[0] != '\0') {
if (strlen(last_replace) > COLS / 3) {
char *buf = charalloc(COLS / 3 + 3);
strncpy(buf, last_replace, COLS / 3 - 1);
strcpy(buf + COLS / 3 - 1, "...");
i = statusq(0, replace_list_2, "", _("Replace with [%s]"),
buf);
free(buf);
} else
i = statusq(0, replace_list_2, "", _("Replace with [%s]"),
last_replace);
} else
i = statusq(0, replace_list_2, last_replace, _("Replace with"));
/* save where we are */
begin = current;
#if 0
/* why + 1 ? isn't this taken care of in findnextstr() ? */
beginx = current_x + 1;
#else
beginx = current_x;
#endif
search_last_line = 0;
numreplaced = do_replace_loop(prevanswer, begin, &beginx, FALSE, &i);
/* restore where we were */
current = begin;
#if 0
current_x = beginx - 1;
#else
current_x = beginx;
#endif
renumber_all();
edit_update(current, CENTER);
print_replaced(numreplaced);

164
utils.c
View File

@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "config.h"
#include "proto.h"
#include "nano.h"
@ -50,75 +51,75 @@ int num_of_digits(int n)
return i;
}
/* For non-null-terminated lines. A line, by definition, shouldn't
normally have newlines in it, so encode its nulls as newlines. */
void unsunder(char *str, int true_len)
/* Fix the memory allocation for a string. */
void align(char **strp)
{
int i;
if (strlen(str) < true_len) {
for (i = 0; i < true_len; i++) {
if (str[i] == '\0')
str[i] = '\n';
}
}
assert(strp != NULL);
*strp = nrealloc(*strp, strlen(*strp) + 1);
}
/* Null a string at a certain index and align it. */
void null_at(char **data, size_t index)
{
assert(data != NULL);
*data = (char *)nrealloc(*data, sizeof(char) * (index + 1));
(*data)[index] = '\0';
}
/* For non-null-terminated lines. A line, by definition, shouldn't
normally have newlines in it, so decode its newlines into nulls. */
* 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';
}
/* For non-null-terminated lines. A line, by definition, shouldn't
* normally have newlines in it, so decode its newlines into nulls. */
void sunder(char *str)
{
int i, true_len = strlen(str);
if (strchr(str, '\n')) {
for (i = 0; i < true_len; i++) {
if (str[i] == '\n')
str[i] = '\0';
}
}
}
/* Lower case a string - must be null terminated */
void lowercase(char *src)
{
long i = 0;
while (src[i] != 0) {
src[i] = (char) tolower(src[i]);
i++;
}
assert(str != NULL);
for(; *str != '\0'; str++)
if (*str == '\n')
*str = '\0';
}
/* None of this is needed if we're using NANO_SMALL! */
#ifndef NANO_SMALL
char *revstrstr(char *haystack, char *needle, char *rev_start)
static const char *revstrstr(const char *haystack, const char *needle,
const char *rev_start)
{
char *p, *q, *r;
for(; rev_start >= haystack ; rev_start--) {
const char *r, *q;
for(p = rev_start ; p >= haystack ; --p) {
for (r = p, q = needle ; (*q == *r) && (*q != '\0') ; r++, q++)
for (r = rev_start, q = needle ; *q == *r && *q != '\0'; r++, q++)
;
if (*q == '\0')
return p;
return rev_start;
}
return 0;
return NULL;
}
char *revstristr(char *haystack, char *needle, char *rev_start)
static const char *revstristr(const char *haystack, const char *needle,
const char *rev_start)
{
char *p, *q, *r;
for (; rev_start >= haystack; rev_start--) {
const char *r = rev_start, *q = needle;
for(p = rev_start ; p >= haystack ; --p) {
for (r = p, q = needle ; (tolower(*q) == tolower(*r)) && (*q != '\0') ; r++, q++)
for (; (tolower(*q) == tolower(*r)) && (*q != '\0') ; r++, q++)
;
if (*q == '\0')
return p;
return rev_start;
}
return 0;
return NULL;
}
#endif /* NANO_SMALL */
#endif /* !NANO_SMALL */
/* This is now mutt's version (called mutt_stristr) because it doesn't
use memory allocation to do a simple search (yuck). */
char *stristr(char *haystack, char *needle)
const char *stristr(const char *haystack, const char *needle)
{
const char *p, *q;
@ -128,43 +129,41 @@ char *stristr(char *haystack, char *needle)
return (haystack);
while (*(p = haystack)) {
for (q = needle; *p && *q && tolower (*p) == tolower (*q); p++, q++)
for (q = needle; *p && *q && tolower(*p) == tolower(*q); p++, q++)
;
if (!*q)
return (haystack);
return haystack;
haystack++;
}
return NULL;
}
char *strstrwrapper(char *haystack, char *needle, char *rev_start, int line_pos)
const char *strstrwrapper(const char *haystack, const char *needle,
const char *rev_start, int line_pos)
{
#ifdef HAVE_REGEX_H
int result;
if (ISSET(USE_REGEXP)) {
if (!ISSET(REVERSE_SEARCH)) {
result = regexec(&search_regexp, haystack, 10, regmatches, (line_pos > 0) ? REG_NOTBOL : 0);
if (!result)
if (!regexec(&search_regexp, haystack, 10, regmatches, (line_pos > 0) ? REG_NOTBOL : 0))
return haystack + regmatches[0].rm_so;
}
#ifndef NANO_SMALL
} else {
char *i, *j;
else {
const char *i, *j;
/* do a quick search forward first */
if (!(regexec(&search_regexp, haystack, 10, regmatches, 0))) {
if (!regexec(&search_regexp, haystack, 10, regmatches, 0)) {
/* there's a match somewhere in the line - now search for it backwards, much slower */
for (i = rev_start; i >= haystack; --i) {
if (!(result = regexec(&search_regexp, i, 10, regmatches, (i > haystack) ? REG_NOTBOL : 0))) {
if (!regexec(&search_regexp, i, 10, regmatches, (i > haystack) ? REG_NOTBOL : 0)) {
j = i + regmatches[0].rm_so;
if (j <= rev_start)
return j;
}
}
}
#endif
}
#endif
return 0;
}
#endif
@ -174,7 +173,6 @@ char *strstrwrapper(char *haystack, char *needle, char *rev_start, int line_pos)
return revstrstr(haystack, needle, rev_start);
else
return strstr(haystack, needle);
} else {
if (ISSET(REVERSE_SEARCH))
return revstristr(haystack, needle, rev_start);
@ -188,8 +186,7 @@ char *strstrwrapper(char *haystack, char *needle, char *rev_start, int line_pos)
/* This is a wrapper for the perror function. The wrapper takes care of
* ncurses, calls perror (which writes to STDERR), then refreshes the
* screen. Note that nperror causes the window to flicker once.
*/
* screen. Note that nperror causes the window to flicker once. */
void nperror(const char *s) {
/* leave ncurses mode, go to the terminal */
if (endwin() != ERR) {
@ -212,17 +209,17 @@ void *nmalloc(size_t howmuch)
}
/* We're going to need this too - Hopefully this will minimize
the transition cost of moving to the apropriate function. */
the transition cost of moving to the appropriate function. */
char *charalloc(size_t howmuch)
{
void *r;
char *r;
/* Panic save? */
if (!(r = calloc(howmuch, sizeof (char))))
if (!(r = (char *)calloc(howmuch, sizeof (char))))
die(_("nano: calloc: out of memory!"));
return (char *) r;
return r;
}
void *nrealloc(void *ptr, size_t howmuch)
@ -235,24 +232,18 @@ void *nrealloc(void *ptr, size_t howmuch)
return r;
}
/* Copy one malloc()ed string to another pointer.
Should be used as dest = mallocstrcpy(dest, src);
*/
void *mallocstrcpy(char *dest, char *src)
/* Copy one malloc()ed string to another pointer. Should be used as:
* dest = mallocstrcpy(dest, src); */
char *mallocstrcpy(char *dest, const char *src)
{
if (src == dest)
return src;
return dest;
if (dest != NULL)
if (dest)
free(dest);
if (src == NULL) {
dest = NULL;
return(dest);
}
if (!src)
return NULL;
dest = charalloc(strlen(src) + 1);
strcpy(dest, src);
@ -260,8 +251,7 @@ void *mallocstrcpy(char *dest, char *src)
return dest;
}
/* Append a new magic-line to filebot */
/* Append a new magic-line to filebot. */
void new_magicline(void)
{
filebot->next = nmalloc(sizeof(filestruct));
@ -292,22 +282,22 @@ void new_magicline(void)
*/
int check_wildcard_match(const char *text, const char *pattern)
{
const char *retryPat;
const char *retryText;
const char *retrypat;
const char *retrytext;
int ch;
int found;
int len;
retryPat = NULL;
retryText = NULL;
retrypat = NULL;
retrytext = NULL;
while (*text || *pattern) {
ch = *pattern++;
switch (ch) {
case '*':
retryPat = pattern;
retryText = text;
retrypat = pattern;
retrytext = text;
break;
case '[':
@ -361,15 +351,15 @@ int check_wildcard_match(const char *text, const char *pattern)
}
if (*text) {
pattern = retryPat;
text = ++retryText;
pattern = retrypat;
text = ++retrytext;
break;
}
return FALSE;
}
if (pattern == NULL)
if (!pattern)
return FALSE;
}

782
winio.c

File diff suppressed because it is too large Load Diff