add DB's overhaul of the file loading code to increase efficiency,

remove ugly workarounds for most cases of edittop's or current's being
NULL (as those cases no longer occur due to the overhaul), and remove
detection of binary files (since it wasn't always accurate and will only
cause problems when UTF-8 support is added); also add a few minor fixes
of mine


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1928 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
master
David Lawrence Ramsey 2004-09-05 21:40:31 +00:00
parent 8bf08097ee
commit 02517e0a0f
10 changed files with 442 additions and 442 deletions

View File

@ -15,6 +15,29 @@ CVS code -
- Remove reference to @includedir@ in src/Makefile.am, as it's
unneeded and can break cross-compilation. (DLR, found by Mike
Frysinger)
- Overhaul the file opening, reading, and loading operations to
increase efficiency, avoid problems on invalid filenames
specified on the command line, and eliminate corner cases that
erroneously leave edittop or current NULL when they shouldn't
be. Also split out the code to execute a command into a
separate function, eliminate a workaround for one of the
aforementioned corner cases, handle files with a mix of DOS
and Mac format lines, and remove the code to turn on the
NO_CONVERT flag when opening a binary file, as it's not always
reliable and will cause problems with UTF-8 text files. New
functions open_file(), execute_command(), and mallocstrassn();
changes to read_line(), load_file(), read_file(), open_file(),
get_next_filename(), do_insertfile(), do_insertfile_void(),
do_alt_speller(), and edit_refresh(). (David Benbennick) DLR:
Add a few minor fixes to make sure that current is set
properly in all cases, indicate on the statusbar when the file
has a mix of DOS and Mac format lines, move the test for DOS
line endings from read_line() to read_file() to avoid
inaccurate statusbar messages and to reduce fileformat to a
local variable in read_file(), eliminate another workaround in
edit_update(), rename open_the_file() to open_file() since the
latter has been removed, and rename load_a_file() to
load_buffer().
- files.c:
do_insertfile()
- Readd the NANO_SMALL #ifdef around the start_again: label to
@ -23,14 +46,23 @@ CVS code -
shortcut_init()
- Remove redundant NANO_SMALL #ifdef. (DLR)
- nano.c:
die_save_file()
- Clarify the error message when there are too many backup files
and the current one can't be written. (DLR)
do_para_begin(), do_para_end()
- Maintain current_y's value when moving up or down lines so
that smooth scrolling works correctly. (DLR)
- nano.h:
- Add WIDTH_OF_TAB #define, containing the default width of a
tab. (DLR)
- rcfile.c:
parse_rcfile()
- Add missing brackets around an if statement block so that
parsing the numeric argument after "tabsize" works properly
again. (DLR, found by Mike Frysinger)
- Since flag values are longs, use "%ld" instead of "%d" in the
debugging messages indicating when a flag is set or unset.
(DLR)
- search.c:
findnextstr()
- Take the no_sameline parameter after can_display_wrap and
@ -56,6 +88,10 @@ CVS code -
- If there are more than MAIN_VISIBLE shortcuts available, only
register clicks on the first MAIN_VISIBLE shortcuts, since
bottombars() only shows that many shortcuts. (DLR)
reset_cursor()
- If this is called before any files have been opened, as it can
be by statusbar(), put the cursor at the top left corner of
the edit window before getting out. (DLR)
edit_refresh()
- Call edit_update() with NONE instead of CENTER when smooth
scrolling is on, for consistency with the movement routines.

View File

@ -37,35 +37,12 @@
#include "proto.h"
#include "nano.h"
/* Set a default value for PATH_MAX, so we can use it below in lines like
path = getcwd(NULL, PATH_MAX + 1); */
/* Set a default value for PATH_MAX, so we can use it below in lines
* like "path = getcwd(NULL, PATH_MAX + 1);". */
#ifndef PATH_MAX
#define PATH_MAX -1
#endif
#ifndef NANO_SMALL
static int fileformat = 0; /* 0 = *nix, 1 = DOS, 2 = Mac */
#endif
/* Load file into edit buffer -- takes data from file struct. */
void load_file(int update)
{
current = fileage;
#ifdef ENABLE_MULTIBUFFER
/* if update is zero, add a new entry to the open_files structure;
otherwise, update the current entry (the latter is needed in the
case of the alternate spell checker) */
add_open_file(update);
#endif
#ifdef ENABLE_COLOR
update_color();
if (ISSET(COLOR_SYNTAX))
edit_refresh();
#endif
}
/* What happens when there is no file to open? aiee! */
void new_file(void)
{
@ -79,24 +56,6 @@ void new_file(void)
totlines = 1;
totsize = 0;
#ifdef ENABLE_MULTIBUFFER
/* if there aren't any entries in open_files, create the entry for
this new file; without this, if nano is started without a filename
on the command line, a new file will be created, but it will be
given no open_files entry */
if (open_files == NULL) {
add_open_file(FALSE);
/* turn off view mode in this case; this is for consistency
whether multibuffers are compiled in or not */
UNSET(VIEW_MODE);
}
#else
/* if multibuffers haven't been compiled in, turn off view mode
unconditionally; otherwise, don't turn them off (except in the
above case), so that we can view multiple files properly */
UNSET(VIEW_MODE);
#endif
#ifdef ENABLE_COLOR
update_color();
if (ISSET(COLOR_SYNTAX))
@ -104,12 +63,17 @@ void new_file(void)
#endif
}
filestruct *read_line(char *buf, filestruct *prev, int *line1ins, size_t
len)
/* We make a new line of text from buf. buf is length len. If
* first_line_ins is TRUE, then we put the new line at the top of the
* file. Otherwise, we assume prev is the last line of the file, and
* put our line after prev. */
filestruct *read_line(char *buf, filestruct *prev, bool *first_line_ins,
size_t len)
{
filestruct *fileptr = (filestruct *)nmalloc(sizeof(filestruct));
/* nulls to newlines; len is the string's real length here */
/* Convert nulls to newlines. len is the string's real length
* here. */
unsunder(buf, len);
assert(strlen(buf) == len);
@ -117,27 +81,25 @@ filestruct *read_line(char *buf, filestruct *prev, int *line1ins, size_t
fileptr->data = mallocstrcpy(NULL, buf);
#ifndef NANO_SMALL
/* If it's a DOS file (CRLF), and file conversion isn't disabled,
strip out the CR part */
/* If it's a DOS file (CR LF), and file conversion isn't disabled,
* strip out the CR part. */
if (!ISSET(NO_CONVERT) && len > 0 && buf[len - 1] == '\r') {
fileptr->data[len - 1] = '\0';
totsize--;
if (fileformat == 0)
fileformat = 1;
}
#endif
if (*line1ins != 0 || fileage == NULL) {
/* Special case, insert with cursor on 1st line. */
if (*first_line_ins || fileage == NULL) {
/* Special case: we're inserting with the cursor on the first
* line. */
fileptr->prev = NULL;
fileptr->next = fileage;
fileptr->lineno = 1;
if (*line1ins != 0) {
*line1ins = 0;
if (*first_line_ins) {
*first_line_ins = FALSE;
/* If we're inserting into the first line of the file, then
we want to make sure that our edit buffer stays on the
first line (and that fileage stays up to date!) */
* we want to make sure that our edit buffer stays on the
* first line and that fileage stays up to date. */
edittop = fileptr;
} else
filebot = fileptr;
@ -153,70 +115,105 @@ filestruct *read_line(char *buf, filestruct *prev, int *line1ins, size_t
return fileptr;
}
void read_file(FILE *f, const char *filename, int quiet)
/* Load a file into the edit buffer. This takes data from the file
* struct. */
void load_file(void)
{
int num_lines = 0, len = 0;
char input = '\0'; /* current input character */
char *buf;
long i = 0, bufx = 128;
filestruct *fileptr = current, *tmp = NULL;
#ifndef NANO_SMALL
int old_no_convert = ISSET(NO_CONVERT);
current = fileage;
#ifdef ENABLE_MULTIBUFFER
/* Add a new entry to the open_files structure. */
add_open_file(FALSE);
/* Reinitialize the shortcut list. */
shortcut_init(FALSE);
#endif
int line1ins = 0;
}
void read_file(FILE *f, const char *filename)
{
size_t num_lines = 0;
/* The number of lines in the file. */
size_t len = 0;
/* The length of the current line of the file. */
size_t i = 0;
/* The position in the current line of the file. */
size_t bufx = 128;
/* The size of each chunk of the file that we read. */
char input = '\0';
/* The current input character. */
char *buf;
/* The buffer where we store chunks of the file. */
filestruct *fileptr = current;
/* The current line of the file. */
bool first_line_ins = FALSE;
/* Whether we're inserting with the cursor on the first line. */
int input_int;
/* The current value we read from the file, whether an input
* character or EOF. */
#ifndef NANO_SMALL
int fileformat = 0;
/* 0 = *nix, 1 = DOS, 2 = Mac, 3 = both DOS and Mac. */
#endif
buf = charalloc(bufx);
buf[0] = '\0';
if (current != NULL) {
if (current == fileage)
line1ins = 1;
first_line_ins = TRUE;
else
fileptr = current->prev;
tmp = fileptr;
}
/* For the assertion in read_line(), it must be true that if current is
* NULL then so is fileage. */
/* For the assertion in read_line(), it must be true that if current
* is NULL, then so is fileage. */
assert(current != NULL || fileage == NULL);
/* Read the entire file into file struct. */
/* Read the entire file into the file struct. */
while ((input_int = getc(f)) != EOF) {
input = (char)input_int;
#ifndef NANO_SMALL
/* If the file has binary chars in it, don't stupidly
assume it's a DOS or Mac formatted file if it hasn't been
detected as one already! */
if (fileformat == 0 && !ISSET(NO_CONVERT)
&& is_cntrl_char(input) && input != '\t'
&& input != '\r' && input != '\n')
SET(NO_CONVERT);
#endif
input = (char)input_int;
/* If it's a *nix file (LF) or a DOS file (CR LF), and file
* conversion isn't disabled, handle it! */
if (input == '\n') {
/* read in the line properly */
fileptr = read_line(buf, fileptr, &line1ins, len);
#ifndef NANO_SMALL
/* If there's a CR before the LF, set fileformat to DOS if
* we currently think this is a *nix file, or to both if we
* currently think it's a Mac file. */
if (!ISSET(NO_CONVERT) && i > 0 && buf[i - 1] == '\r' &&
(fileformat == 0 || fileformat == 2))
fileformat++;
#endif
/* reset the line length, in preparation for the next line */
/* Read in the line properly. */
fileptr = read_line(buf, fileptr, &first_line_ins, len);
/* Reset the line length in preparation for the next
* line. */
len = 0;
num_lines++;
buf[0] = '\0';
i = 0;
#ifndef NANO_SMALL
/* If it's a Mac file (no LF just a CR), and file conversion
isn't disabled, handle it! */
/* If it's a Mac file (CR without an LF), and file conversion
* isn't disabled, handle it! */
} else if (!ISSET(NO_CONVERT) && i > 0 && buf[i - 1] == '\r') {
fileformat = 2;
/* read in the line properly */
fileptr = read_line(buf, fileptr, &line1ins, len);
/* If we currently think the file is a *nix file, set
* fileformat to Mac. If we currently think the file is a
* DOS file, set fileformat to both DOS and Mac. */
if (fileformat == 0 || fileformat == 1)
fileformat += 2;
/* reset the line length, in preparation for the next line;
since we've already read in the next character, reset it
to 1 instead of 0 */
/* Read in the line properly. */
fileptr = read_line(buf, fileptr, &first_line_ins, len);
/* Reset the line length in preparation for the next line.
* Since we've already read in the next character, reset it
* to 1 instead of 0. */
len = 1;
num_lines++;
@ -226,15 +223,14 @@ void read_file(FILE *f, const char *filename, int quiet)
i = 1;
#endif
} else {
/* Calculate the total length of the line; it might have
nulls in it, so we can't just use strlen(). */
/* Calculate the total length of the line. It might have
* nulls in it, so we can't just use strlen() here. */
len++;
/* Now we allocate a bigger buffer 128 characters at a time.
If we allocate a lot of space for one line, we may indeed
have to use a buffer this big later on, so we don't
decrease it at all. We do free it at the end, though. */
* If we allocate a lot of space for one line, we may indeed
* have to use a buffer this big later on, so we don't
* decrease it at all. We do free it at the end, though. */
if (i >= bufx - 1) {
bufx += 128;
buf = charealloc(buf, bufx);
@ -246,54 +242,43 @@ void read_file(FILE *f, const char *filename, int quiet)
totsize++;
}
/* This conditional duplicates previous read_byte() behavior;
perhaps this could use some better handling. */
/* This conditional duplicates previous read_byte() behavior.
* Perhaps this could use some better handling. */
if (ferror(f))
nperror(filename);
fclose(f);
/* Did we not get a newline but still have stuff to do? */
if (len > 0) {
#ifndef NANO_SMALL
/* If file conversion isn't disabled, the last character in
this file is a CR and fileformat isn't set yet, make sure
it's set to Mac format */
if (!ISSET(NO_CONVERT) && buf[len - 1] == '\r' && fileformat == 0)
fileformat = 2;
#endif
/* read in the LAST line properly */
fileptr = read_line(buf, fileptr, &line1ins, len);
num_lines++;
totsize++;
buf[0] = '\0';
}
#ifndef NANO_SMALL
else if (!ISSET(NO_CONVERT) && input == '\r') {
/* If file conversion isn't disabled and the last character in
this file is a CR, read it in properly as a (Mac format)
line */
/* If file conversion isn't disabled and the last character in this
* file is a CR, read it in properly as a Mac format line. */
if (len == 0 && !ISSET(NO_CONVERT) && input == '\r') {
buf[0] = input;
buf[1] = '\0';
len = 1;
fileptr = read_line(buf, fileptr, &line1ins, len);
num_lines++;
totsize++;
buf[0] = '\0';
}
#endif
free(buf);
/* Did we not get a newline and still have stuff to do? */
if (len > 0) {
#ifndef NANO_SMALL
/* If NO_CONVERT wasn't set before we read the file, but it is now,
unset it again. */
if (!old_no_convert && ISSET(NO_CONVERT))
UNSET(NO_CONVERT);
/* If file conversion isn't disabled and the last character in
* this file is a CR, set fileformat to Mac if we currently
* think the file is a *nix file, or to both DOS and Mac if we
* currently think the file is a DOS file. */
if (!ISSET(NO_CONVERT) && buf[len - 1] == '\r' &&
(fileformat == 0 || fileformat == 1))
fileformat += 2;
#endif
/* Did we even GET a file if we don't already have one? */
/* Read in the last line properly. */
fileptr = read_line(buf, fileptr, &first_line_ins, len);
num_lines++;
totsize++;
}
free(buf);
/* If we didn't get a file and we don't already have one, make a new
* file. */
if (totsize == 0 || fileptr == NULL)
new_file();
@ -309,93 +294,77 @@ void read_file(FILE *f, const char *filename, int quiet)
filebot = fileptr;
new_magicline();
totsize--;
load_file(quiet);
}
}
#ifndef NANO_SMALL
if (fileformat == 2)
statusbar(P_("Read %d line (Converted from Mac format)",
"Read %d lines (Converted from Mac format)",
num_lines), num_lines);
if (fileformat == 3)
statusbar(
P_("Read %lu line (Converted from DOS and Mac format)",
"Read %lu lines (Converted from DOS and Mac format)",
(unsigned long)num_lines), (unsigned long)num_lines);
else if (fileformat == 2)
statusbar(P_("Read %lu line (Converted from Mac format)",
"Read %lu lines (Converted from Mac format)",
(unsigned long)num_lines), (unsigned long)num_lines);
else if (fileformat == 1)
statusbar(P_("Read %d line (Converted from DOS format)",
"Read %d lines (Converted from DOS format)",
num_lines), num_lines);
statusbar(P_("Read %lu line (Converted from DOS format)",
"Read %lu lines (Converted from DOS format)",
(unsigned long)num_lines), (unsigned long)num_lines);
else
#endif
statusbar(P_("Read %d line", "Read %d lines", num_lines),
num_lines);
#ifndef NANO_SMALL
/* Set fileformat back to 0, now that we've read the file in and
possibly converted it from DOS/Mac format. */
fileformat = 0;
#endif
statusbar(P_("Read %lu line", "Read %lu lines",
(unsigned long) num_lines),(unsigned long)num_lines);
totlines += num_lines;
return;
}
/* Open the file (and decide if it exists). Return TRUE on success,
* FALSE on failure. */
bool open_file(const char *filename, int insert, int quiet)
/* Open the file (and decide if it exists). If newfie is TRUE, display
* "New File" if the file is missing. Otherwise, say "[filename] not
* found".
*
* Return -2 if we say "New File". Otherwise, -1 if the file isn't
* opened, 0 otherwise. The file might still have an error while
* reading with a 0 return value. *f is set to the opened file. */
int open_file(const char *filename, bool newfie, FILE **f)
{
int fd;
FILE *f;
struct stat fileinfo;
if (filename[0] == '\0' || stat(filename, &fileinfo) == -1) {
if (insert && !quiet) {
statusbar(_("\"%s\" not found"), filename);
return FALSE;
} else {
/* We have a new file */
assert(f != NULL);
if (filename == NULL || filename[0] == '\0' ||
stat(filename, &fileinfo) == -1) {
if (newfie) {
statusbar(_("New File"));
new_file();
return -2;
}
statusbar(_("\"%s\" not found"), filename);
return -1;
} else if (S_ISDIR(fileinfo.st_mode) || S_ISCHR(fileinfo.st_mode) ||
S_ISBLK(fileinfo.st_mode)) {
/* Don't open character or block files. Sorry, /dev/sndstat! */
statusbar(S_ISDIR(fileinfo.st_mode) ? _("\"%s\" is a directory") :
_("File \"%s\" is a device file"), filename);
if (!insert)
new_file();
return FALSE;
return -1;
} else if ((fd = open(filename, O_RDONLY)) == -1) {
/* If we're in multibuffer mode, don't be quiet when an error
occurs while opening a file */
if (!quiet
#ifdef ENABLE_MULTIBUFFER
|| ISSET(MULTIBUFFER)
#endif
)
statusbar("Error reading %s: %s", filename, strerror(errno));
if (!insert)
new_file();
return FALSE;
} else { /* File is A-OK */
if (!quiet)
statusbar(_("Reading File"));
f = fdopen(fd, "rb"); /* Binary for our own line-end munging */
if (f == NULL) {
nperror("fdopen");
close(fd);
return FALSE;
}
read_file(f, filename, quiet);
#ifndef NANO_SMALL
stat(filename, &originalfilestat);
#endif
}
statusbar(_("Error reading %s: %s"), filename, strerror(errno));
return -1;
} else {
/* File is A-OK. */
*f = fdopen(fd, "rb"); /* Binary for our own line-end munging */
return TRUE;
if (*f == NULL) {
statusbar(_("Error reading %s: %s"), filename, strerror(errno));
close(fd);
} else
statusbar(_("Reading File"));
}
return 0;
}
/* This function will return the name of the first available extension
* of a filename (starting with the filename.save, then filename.save.1,
* etc). Memory is allocated for the return value. If no writable
* of a filename (starting with filename.save, then filename.save.1,
* etc.). Memory is allocated for the return value. If no writable
* extension exists, we return "". */
char *get_next_filename(const char *name)
{
@ -421,77 +390,125 @@ char *get_next_filename(const char *name)
}
/* We get here only if there is no possible save file. */
buf[0] = '\0';
null_at(&buf, 0);
return buf;
}
void do_insertfile(int loading_file)
{
int i, old_current_x = current_x;
bool opened;
/* TRUE if the file opened successfully. */
char *realname = NULL;
static char *inspath = NULL;
if (inspath == NULL) {
inspath = charalloc(1);
inspath[0] = '\0';
}
#ifndef DISABLE_WRAPPING
wrap_reset();
#endif
#ifndef NANO_SMALL
start_again:
#endif
void execute_command(const char *command)
{
#ifdef ENABLE_MULTIBUFFER
if (ISSET(MULTIBUFFER)) {
/* Update the current entry in the open_files structure. */
add_open_file(TRUE);
new_file();
UNSET(MODIFIED);
UNSET(MARK_ISSET);
}
#endif /* ENABLE_MULTIBUFFER */
open_pipe(command);
#ifdef ENABLE_MULTIBUFFER
/* Add this new entry to the open_files structure. */
if (ISSET(MULTIBUFFER))
load_file();
#endif /* ENABLE_MULTIBUFFER */
}
#endif /* !NANO_SMALL */
#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE)
currshortcut = insertfile_list;
/* name is a file name to open. We make a new buffer if necessary, then
* open and read the file. */
void load_buffer(const char *name)
{
bool new_buffer = fileage == NULL
#ifdef ENABLE_MULTIBUFFER
|| ISSET(MULTIBUFFER)
#endif
;
/* new_buffer says whether we load to this buffer or a new one.
* If new_buffer is TRUE, we display "New File" if the file is
* not found, and if it is found we set filename and add a new
* open_files entry. */
FILE *f;
int rc;
/* rc == -2 means that the statusbar displayed "New File". -1
* means that the open failed. 0 means success. */
#ifndef DISABLE_OPERATINGDIR
if (operating_dir != NULL && strcmp(operating_dir, ".") != 0)
#ifdef ENABLE_MULTIBUFFER
if (ISSET(MULTIBUFFER))
i = statusq(TRUE, insertfile_list, inspath,
#ifndef NANO_SMALL
NULL,
if (check_operating_dir(name, FALSE)) {
statusbar(_("Can't insert file from outside of %s"), operating_dir);
return;
}
#endif
_("File to insert into new buffer [from %s] "),
operating_dir);
else
#endif
i = statusq(TRUE, insertfile_list, inspath,
#ifndef NANO_SMALL
NULL,
#endif
_("File to insert [from %s] "),
operating_dir);
#ifdef ENABLE_MULTIBUFFER
/* Update the current entry in the open_files structure. */
add_open_file(TRUE);
#endif
rc = open_file(name, new_buffer, &f);
#ifdef ENABLE_MULTIBUFFER
if (rc != -1 && ISSET(MULTIBUFFER)) {
UNSET(MODIFIED);
#ifndef NANO_SMALL
UNSET(MARK_ISSET);
#endif
}
#endif
if (rc != -1 && new_buffer) {
filename = mallocstrcpy(filename, name);
new_file();
}
if (rc == 0) {
read_file(f, filename);
#ifndef NANO_SMALL
stat(filename, &originalfilestat);
#endif
}
/* Add this new entry to the open_files structure if we have
* multibuffer support, or to the main filestruct if we don't. */
if (rc != -1 && new_buffer)
load_file();
}
void do_insertfile(void)
{
int i;
const char *msg;
char *inspath = mallocstrcpy(NULL, "");
/* The last answer the user typed on the statusbar. Saved for if
* they do M-F or cancel the file browser. */
wrap_reset();
#if !defined(DISABLE_BROWSER) || (!defined(NANO_SMALL) && defined(ENABLE_MULTIBUFFER))
start_again: /* Go here when the user cancels the file browser. */
#endif
#ifdef ENABLE_MULTIBUFFER
if (ISSET(MULTIBUFFER))
msg = N_("File to insert into new buffer [from %s] ");
else
#endif
#ifdef ENABLE_MULTIBUFFER
if (ISSET(MULTIBUFFER))
i = statusq(TRUE, insertfile_list, inspath,
msg = N_("File to insert [from %s] ");
i = statusq(TRUE, insertfile_list, inspath,
#ifndef NANO_SMALL
NULL,
#endif
_("File to insert into new buffer [from ./] "));
else
#endif /* ENABLE_MULTIBUFFER */
i = statusq(TRUE, insertfile_list, inspath,
#ifndef NANO_SMALL
NULL,
_(msg),
#ifndef DISABLE_OPERATINGDIR
operating_dir != NULL && strcmp(operating_dir, ".") != 0 ?
operating_dir :
#endif
_("File to insert [from ./] "));
"./");
if (i != -1) {
int old_current_x = current_x;
inspath = mallocstrcpy(inspath, answer);
#ifdef DEBUG
fprintf(stderr, "filename is %s\n", answer);
#endif
#ifndef NANO_SMALL
#ifdef ENABLE_MULTIBUFFER
@ -499,11 +516,9 @@ void do_insertfile(int loading_file)
/* Don't allow toggling if we're in view mode. */
if (!ISSET(VIEW_MODE))
TOGGLE(MULTIBUFFER);
loading_file = ISSET(MULTIBUFFER);
goto start_again;
}
#endif /* ENABLE_MULTIBUFFER */
if (i == NANO_EXTCMD_KEY) {
char *ans = mallocstrcpy(NULL, answer);
int ts = statusq(TRUE, extcmd_list, ans, NULL,
@ -511,137 +526,67 @@ void do_insertfile(int loading_file)
free(ans);
if (ts == -1 || answer == NULL || answer[0] == '\0') {
statusbar(_("Cancelled"));
display_main_list();
return;
}
if (ts == -1 || answer == NULL || answer[0] == '\0')
goto start_again;
}
#endif /* !NANO_SMALL */
#ifndef DISABLE_BROWSER
if (i == NANO_TOFILES_KEY) {
char *tmp = do_browse_from(answer);
if (tmp != NULL) {
free(answer);
answer = tmp;
resetstatuspos = 1;
} else
if (tmp == NULL)
goto start_again;
}
#endif
#ifndef DISABLE_OPERATINGDIR
if (
#ifndef NANO_SMALL
i != NANO_EXTCMD_KEY &&
#endif
check_operating_dir(answer, FALSE) != 0) {
statusbar(_("Can't insert file from outside of %s"),
operating_dir);
return;
}
#endif
#ifdef ENABLE_MULTIBUFFER
if (loading_file) {
/* update the current entry in the open_files structure */
add_open_file(TRUE);
new_file();
UNSET(MODIFIED);
#ifndef NANO_SMALL
UNSET(MARK_ISSET);
#endif
resetstatuspos = TRUE;
free(answer);
answer = tmp;
}
#endif
#ifndef NANO_SMALL
if (i == NANO_EXTCMD_KEY) {
realname = mallocstrcpy(realname, "");
opened = open_pipe(answer);
} else {
if (i == NANO_EXTCMD_KEY)
execute_command(answer);
else {
#endif
realname = real_dir_from_tilde(answer);
opened = open_file(realname, TRUE, loading_file);
answer = mallocstrassn(answer, real_dir_from_tilde(answer));
load_buffer(answer);
#ifndef NANO_SMALL
}
#endif
#ifdef ENABLE_MULTIBUFFER
if (loading_file) {
/* if there was an error opening the file, free() realname,
free() fileage (which now points to the new buffer we
created to hold the file), reload the buffer we had open
before, and skip the insertion; otherwise, save realname
in filename and continue the insertion */
if (!opened) {
free(realname);
free(fileage);
load_open_file();
goto skip_insert;
} else
filename = mallocstrcpy(filename, realname);
}
#endif
free(realname);
#ifdef DEBUG
dump_buffer(fileage);
#endif
#ifdef ENABLE_MULTIBUFFER
if (loading_file)
load_file(FALSE);
else
#endif
set_modified();
#ifdef ENABLE_MULTIBUFFER
/* If we've loaded another file, update the titlebar's contents */
if (loading_file) {
clearok(topwin, FALSE);
if (ISSET(MULTIBUFFER)) {
/* Update the titlebar. */
titlebar(NULL);
/* And re-init the shortcut list */
/* Reinitialize the shortcut list. */
shortcut_init(FALSE);
} else
} else {
#endif
/* Restore the old x-coordinate position */
/* Mark the file as modified. */
set_modified();
/* Restore the old x-coordinate position. */
current_x = old_current_x;
#ifdef ENABLE_MULTIBUFFER
}
#endif
/* If we've gone off the bottom, recenter; otherwise, just redraw */
edit_refresh();
} else {
} else
statusbar(_("Cancelled"));
i = 0;
}
#ifdef ENABLE_MULTIBUFFER
skip_insert:
#endif
free(inspath);
inspath = NULL;
display_main_list();
}
void do_insertfile_void(void)
{
#ifdef ENABLE_MULTIBUFFER
if (ISSET(VIEW_MODE)) {
if (ISSET(MULTIBUFFER))
do_insertfile(TRUE);
else
statusbar(_("Key illegal in non-multibuffer mode"));
}
if (ISSET(VIEW_MODE) && !ISSET(MULTIBUFFER))
statusbar(_("Key illegal in non-multibuffer mode"));
else
do_insertfile(ISSET(MULTIBUFFER));
#else
do_insertfile(FALSE);
#endif
do_insertfile();
display_main_list();
}
@ -1008,7 +953,7 @@ int close_open_file(void)
display_main_list();
return 0;
}
#endif /* MULTIBUFFER */
#endif /* ENABLE_MULTIBUFFER */
#if !defined(DISABLE_SPELLER) || !defined(DISABLE_OPERATINGDIR) || !defined(NANO_SMALL)
/*

View File

@ -367,7 +367,8 @@ void shortcut_init(int unjustify)
);
#ifdef ENABLE_MULTIBUFFER
if (open_files != NULL && (open_files->prev != NULL || open_files->next != NULL))
if (open_files != NULL && (open_files->prev != NULL ||
open_files->next != NULL))
/* Translators: try to keep this string under 10 characters long */
sc_init_one(&main_list, NANO_EXIT_KEY, N_("Close"),
IFHELP(nano_exit_msg, NANO_NO_KEY), NANO_EXIT_FKEY,

View File

@ -179,7 +179,7 @@ void die_save_file(const char *die_filename)
if (!failed)
fprintf(stderr, _("\nBuffer written to %s\n"), ret);
else
fprintf(stderr, _("\nNo %s written (too many backup files?)\n"), ret);
fprintf(stderr, _("\nBuffer not written to %s (too many backup files?)\n"), ret);
free(ret);
}
@ -856,7 +856,7 @@ bool open_pipe(const char *command)
if (f == NULL)
nperror("fdopen");
read_file(f, "stdin", FALSE);
read_file(f, "stdin");
/* If multibuffer mode is on, we could be here in view mode. If so,
* don't set the modification flag. */
if (!ISSET(VIEW_MODE))
@ -1406,7 +1406,7 @@ bool do_int_spell_fix(const char *word)
bool reverse_search_set = ISSET(REVERSE_SEARCH);
#ifndef NANO_SMALL
bool case_sens_set = ISSET(CASE_SENSITIVE);
bool mark_set = ISSET(MARK_ISSET);
bool old_mark_set = ISSET(MARK_ISSET);
SET(CASE_SENSITIVE);
/* Make sure the marking highlight is off during spell-check. */
@ -1475,7 +1475,7 @@ bool do_int_spell_fix(const char *word)
UNSET(CASE_SENSITIVE);
/* Restore marking highlight. */
if (mark_set)
if (old_mark_set)
SET(MARK_ISSET);
#endif
@ -1678,16 +1678,17 @@ const char *do_alt_speller(char *tempfile_name)
pid_t pid_spell;
char *ptr;
static int arglen = 3;
static char **spellargs = (char **)NULL;
static char **spellargs = NULL;
FILE *f;
#ifndef NANO_SMALL
bool mark_set = ISSET(MARK_ISSET);
bool old_mark_set = ISSET(MARK_ISSET);
int mbb_lineno_cur = 0;
/* We're going to close the current file, and open the output of
* the alternate spell command. The line that mark_beginbuf
* points to will be freed, so we save the line number and
* restore afterwards. */
if (mark_set) {
if (old_mark_set) {
mbb_lineno_cur = mark_beginbuf->lineno;
UNSET(MARK_ISSET);
}
@ -1738,7 +1739,7 @@ const char *do_alt_speller(char *tempfile_name)
refresh();
#ifndef NANO_SMALL
if (mark_set) {
if (old_mark_set) {
do_gotopos(mbb_lineno_cur, mark_beginx, y_cur, 0);
mark_beginbuf = current;
/* In case the line got shorter, assign mark_beginx. */
@ -1750,7 +1751,13 @@ const char *do_alt_speller(char *tempfile_name)
free_filestruct(fileage);
terminal_init();
global_init(TRUE);
open_file(tempfile_name, FALSE, TRUE);
/* Do what load_buffer() would do, except for making a new
* buffer for the temp file if multibuffer support is
* available. */
open_file(tempfile_name, FALSE, &f);
read_file(f, tempfile_name);
current = fileage;
#ifndef NANO_SMALL
}
#endif
@ -2564,6 +2571,7 @@ void do_justify(bool full_justify)
edit_refresh();
statusbar(_("Can now UnJustify!"));
/* Display the shortcut list with UnJustify. */
shortcut_init(TRUE);
display_main_list();
@ -2618,6 +2626,7 @@ void do_justify(bool full_justify)
cutbuffer = cutbuffer_save;
/* Note that now cutbottom is invalid, but that's okay. */
blank_statusbar();
/* Display the shortcut list with UnCut. */
shortcut_init(FALSE);
display_main_list();
@ -2940,11 +2949,19 @@ void terminal_init(void)
int main(int argc, char **argv)
{
int optchr;
int startline = 0; /* Line to try and start at */
int startline = 0;
/* Line to try and start at. */
#ifndef DISABLE_WRAPJUSTIFY
bool fill_flag_used = FALSE; /* Was the fill option used? */
bool fill_flag_used = FALSE;
/* Was the fill option used? */
#endif
int kbinput; /* Input from keyboard */
#ifdef ENABLE_MULTIBUFFER
bool old_multibuffer;
/* The old value of the multibuffer option, restored after we
* load all files on the command line. */
#endif
int kbinput;
/* Input from keyboard. */
bool meta_key;
#ifdef HAVE_GETOPT_LONG
const struct option long_options[] = {
@ -3015,8 +3032,8 @@ int main(int argc, char **argv)
#endif
#if !defined(ENABLE_NANORC) && defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING)
/* if we don't have rcfile support, we're root, and
--disable-wrapping-as-root is used, turn wrapping off */
/* If we don't have rcfile support, we're root, and
* --disable-wrapping-as-root is used, turn wrapping off. */
if (geteuid() == NANO_ROOT_UID)
SET(NO_WRAP);
#endif
@ -3190,8 +3207,8 @@ int main(int argc, char **argv)
}
/* We've read through the command line options. Now back up the flags
and values that are set, and read the rcfile(s). If the values
haven't changed afterward, restore the backed-up values. */
* and values that are set, and read the rcfile(s). If the values
* haven't changed afterward, restore the backed-up values. */
#ifdef ENABLE_NANORC
if (!ISSET(NO_RCFILE)) {
#ifndef DISABLE_OPERATINGDIR
@ -3336,43 +3353,26 @@ int main(int argc, char **argv)
#endif
#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
/* If whitespace wasn't specified, set its default value. */
if (whitespace == NULL)
whitespace = mallocstrcpy(NULL, " ");
#endif
/* If tabsize wasn't specified, set its default value. */
if (tabsize == -1)
tabsize = 8;
/* Clear the filename we'll be using */
filename = charalloc(1);
filename[0] = '\0';
tabsize = WIDTH_OF_TAB;
/* If there's a +LINE flag, it is the first non-option argument. */
if (0 < optind && optind < argc && argv[optind][0] == '+') {
startline = atoi(&argv[optind][1]);
optind++;
}
if (0 < optind && optind < argc)
filename = mallocstrcpy(filename, argv[optind]);
/* See if there's a non-option in argv (first non-option is the
filename, if +LINE is not given) */
if (argc > 1 && argc > optind) {
/* Look for the +line flag... */
if (argv[optind][0] == '+') {
startline = atoi(&argv[optind][1]);
optind++;
if (argc > optind)
filename = mallocstrcpy(filename, argv[optind]);
} else
filename = mallocstrcpy(filename, argv[optind]);
}
/* Back up the old terminal settings so that they can be restored. */
tcgetattr(0, &oldterm);
/* Curses initialization stuff: Start curses and set up the
* terminal state. */
/* Curses initialization stuff: Start curses and set up the
* terminal state. */
initscr();
terminal_init();
@ -3392,44 +3392,55 @@ int main(int argc, char **argv)
mouse_init();
#endif
#ifdef DEBUG
fprintf(stderr, "Main: top and bottom win\n");
#endif
titlebar(NULL);
display_main_list();
#ifdef DEBUG
fprintf(stderr, "Main: open file\n");
#endif
open_file(filename, FALSE, FALSE);
#ifdef ENABLE_MULTIBUFFER
/* If we're using multibuffers and more than one file is specified
on the command line, load them all and switch to the first one
afterward. */
if (optind + 1 < argc) {
bool old_multibuffer = ISSET(MULTIBUFFER), list = FALSE;
SET(MULTIBUFFER);
for (optind++; optind < argc; optind++) {
add_open_file(TRUE);
new_file();
filename = mallocstrcpy(filename, argv[optind]);
titlebar(NULL);
open_file(filename, FALSE, FALSE);
load_file(FALSE);
/* Display the main list with "Close" if we haven't
* already. */
if (!list) {
shortcut_init(FALSE);
list = TRUE;
display_main_list();
}
}
open_nextfile_void();
if (!old_multibuffer)
UNSET(MULTIBUFFER);
old_multibuffer = ISSET(MULTIBUFFER);
SET(MULTIBUFFER);
/* Read all the files after the first one on the command line into
* new buffers. */
{
int i;
for (i = optind + 1; i < argc; i++)
load_buffer(argv[i]);
}
#endif
/* Read the first file on the command line into either the current
* buffer or a new buffer, depending on whether multibuffer mode is
* enabled. */
if (optind < argc)
load_buffer(argv[optind]);
/* We didn't open any files if all the command line arguments were
* invalid files like directories or if there were no command line
* arguments given. In this case, we have to load a blank buffer.
* Also, we unset view mode to allow editing. */
if (filename == NULL) {
filename = mallocstrcpy(NULL, "");
new_file();
UNSET(VIEW_MODE);
/* Add this new entry to the open_files structure if we have
* multibuffer support, or to the main filestruct if we don't. */
load_file();
}
#ifdef ENABLE_MULTIBUFFER
if (!old_multibuffer)
UNSET(MULTIBUFFER);
#endif
#ifdef DEBUG
fprintf(stderr, "Main: top and bottom win\n");
#endif
titlebar(NULL);
display_main_list();
if (startline > 0)
do_gotoline(startline, FALSE);

View File

@ -491,6 +491,9 @@ typedef enum {
* occurs. */
#define CHARS_FROM_EOL 8
/* Default width of a tab. */
#define WIDTH_OF_TAB 8
/* Maximum number of search history strings saved, same value used for
* replace history. */
#define MAX_SEARCH_HISTORY 100

View File

@ -164,14 +164,18 @@ void do_cut_text(void);
void do_uncut_text(void);
/* Public functions in files.c */
void load_file(int update);
void new_file(void);
filestruct *read_line(char *buf, filestruct *prev, int *line1ins, size_t
len);
void read_file(FILE *f, const char *filename, int quiet);
bool open_file(const char *filename, int insert, int quiet);
filestruct *read_line(char *buf, filestruct *prev, bool *first_line_ins,
size_t len);
void load_file(void);
void read_file(FILE *f, const char *filename);
int open_file(const char *filename, bool newfie, FILE **f);
char *get_next_filename(const char *name);
void do_insertfile(int loading_file);
#ifndef NANO_SMALL
void execute_command(const char *command);
#endif
void load_buffer(const char *name);
void do_insertfile(void);
void do_insertfile_void(void);
#ifdef ENABLE_MULTIBUFFER
openfilestruct *make_new_opennode(openfilestruct *prevnode);
@ -411,7 +415,7 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
void do_replace(void);
void do_gotoline(int line, bool save_pos);
void do_gotoline_void(void);
#if defined (ENABLE_MULTIBUFFER) || !defined (DISABLE_SPELLER)
#if defined(ENABLE_MULTIBUFFER) || !defined(DISABLE_SPELLER)
void do_gotopos(int line, int pos_x, int pos_y, size_t pos_pww);
#endif
void do_find_bracket(void);
@ -479,6 +483,7 @@ void nperror(const char *s);
void *nmalloc(size_t howmuch);
void *nrealloc(void *ptr, size_t howmuch);
char *mallocstrcpy(char *dest, const char *src);
char *mallocstrassn(char *dest, char *src);
void new_magicline(void);
#ifndef NANO_SMALL
void mark_order(const filestruct **top, size_t *top_x, const filestruct

View File

@ -619,13 +619,13 @@ void parse_rcfile(FILE *rcstream)
} else
SET(rcopts[i].flag);
#ifdef DEBUG
fprintf(stderr, "set flag %d!\n",
fprintf(stderr, "set flag %ld!\n",
rcopts[i].flag);
#endif
} else {
UNSET(rcopts[i].flag);
#ifdef DEBUG
fprintf(stderr, "unset flag %d!\n",
fprintf(stderr, "unset flag %ld!\n",
rcopts[i].flag);
#endif
}

View File

@ -616,7 +616,7 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
bool begin_line = FALSE, bol_or_eol = FALSE;
#endif
#ifndef NANO_SMALL
bool old_mark_isset = ISSET(MARK_ISSET);
bool old_mark_set = ISSET(MARK_ISSET);
UNSET(MARK_ISSET);
edit_refresh();
@ -758,7 +758,7 @@ int do_replace_loop(const char *needle, const filestruct *real_current,
new_magicline();
#ifndef NANO_SMALL
if (old_mark_isset)
if (old_mark_set)
SET(MARK_ISSET);
#endif

View File

@ -396,7 +396,7 @@ void *nrealloc(void *ptr, size_t howmuch)
}
/* Copy one malloc()ed string to another pointer. Should be used as:
* dest = mallocstrcpy(dest, src); */
* "dest = mallocstrcpy(dest, src);". */
char *mallocstrcpy(char *dest, const char *src)
{
if (src == NULL)
@ -411,7 +411,16 @@ char *mallocstrcpy(char *dest, const char *src)
return dest;
}
/* Append a new magic-line to filebot. */
/* Free the malloc()ed string at dest and return the malloc()ed string
* at src. Should be used as: "answer = mallocstrassn(answer,
* real_dir_from_tilde(answer));". */
char *mallocstrassn(char *dest, char *src)
{
free(dest);
return src;
}
/* Append a new magicline to filebot. */
void new_magicline(void)
{
filebot->next = (filestruct *)nmalloc(sizeof(filestruct));

View File

@ -2385,13 +2385,15 @@ size_t get_page_start(size_t column)
}
/* Resets current_y, based on the position of current, and puts the
* cursor at (current_y, current_x). */
* cursor in the edit window at (current_y, current_x). */
void reset_cursor(void)
{
/* Yuck. This condition can be true after open_file() when opening
* the first file. */
if (edittop == NULL)
/* If we haven't opened any files yet, put the cursor in the top
* left corner of the edit window and get out. */
if (edittop == NULL || current == NULL) {
wmove(edit, 0, 0);
return;
}
current_y = current->lineno - edittop->lineno;
if (current_y < editwinrows) {
@ -2884,14 +2886,6 @@ void edit_redraw(const filestruct *old_current, size_t old_pww)
/* Refresh the screen without changing the position of lines. */
void edit_refresh(void)
{
/* Neither of these conditions should occur, but they do. edittop
* is NULL when you open an existing file on the command line, and
* ENABLE_COLOR is defined. Yuck. */
if (current == NULL)
return;
if (edittop == NULL)
edittop = current;
if (current->lineno < edittop->lineno ||
current->lineno >= edittop->lineno + editwinrows)
/* Note that edit_update() changes edittop so that it's in range
@ -2932,10 +2926,6 @@ void edit_update(topmidnone location)
{
filestruct *foo = current;
/* We shouldn't need this check. Yuck. */
if (current == NULL)
return;
if (location != TOP) {
/* If location is CENTER, we move edittop up (editwinrows / 2)
* lines. This puts current at the center of the screen. If