Commit 86f7bc18 authored by David Lawrence Ramsey's avatar David Lawrence Ramsey Committed by Benno Schulenberg
Browse files

files: revamp the insertion of a file, to be more like pasting text

Move buffer handling and '\r' stripping from read_line() to read_file(),
so that the file gets its format determined and gets stored in its own
buffer entirely in one function.  Then use ingraft_buffer() to insert
this new buffer into the current one.

In addition to pasting the file at current[current_x], ingraft_buffer()
also deals with renumbering, the updating of totsize, and the handling
of a magicline, so read_file() doesn't need to do those anymore.

Note that all this makes read_file() depend on the position of
current[current_x] to know where to insert the file.  Accordingly,
set current_x to zero in initialize_buffer_text() instead of in
make_new_buffer(), so that replace_buffer() keeps working properly.
No related merge requests found
Showing with 69 additions and 120 deletions
+69 -120
...@@ -91,7 +91,6 @@ void make_new_buffer(void) ...@@ -91,7 +91,6 @@ void make_new_buffer(void)
initialize_buffer_text(); initialize_buffer_text();
openfile->current_x = 0;
openfile->placewewant = 0; openfile->placewewant = 0;
openfile->current_y = 0; openfile->current_y = 0;
...@@ -129,6 +128,7 @@ void initialize_buffer_text(void) ...@@ -129,6 +128,7 @@ void initialize_buffer_text(void)
openfile->edittop = openfile->fileage; openfile->edittop = openfile->fileage;
openfile->current = openfile->fileage; openfile->current = openfile->fileage;
openfile->current_x = 0;
openfile->totsize = 0; openfile->totsize = 0;
} }
...@@ -683,44 +683,14 @@ int is_file_writable(const char *filename) ...@@ -683,44 +683,14 @@ int is_file_writable(const char *filename)
return result; return result;
} }
/* Make a new line of text from the given buf, which is of length buf_len. /* Encode any NUL bytes in the given line of text, which is of length buf_len,
* Then attach this line after prevnode. */ * and return a dynamically allocated copy of the resultant string. */
filestruct *read_line(char *buf, size_t buf_len, filestruct *prevnode) char *encode_data(char *buf, size_t buf_len)
{ {
filestruct *freshline = (filestruct *)nmalloc(sizeof(filestruct));
/* Convert nulls to newlines. buf_len is the string's real length. */
unsunder(buf, buf_len); unsunder(buf, buf_len);
buf[buf_len] = '\0'; buf[buf_len] = '\0';
assert(openfile->fileage != NULL && strlen(buf) == buf_len); return mallocstrcpy(NULL, buf);
#ifndef NANO_TINY
/* If file conversion isn't disabled, strip a '\r' from the line. */
if (buf_len > 0 && buf[buf_len - 1] == '\r' && !ISSET(NO_CONVERT))
buf[buf_len - 1] = '\0';
#endif
freshline->data = mallocstrcpy(NULL, buf);
#ifndef DISABLE_COLOR
freshline->multidata = NULL;
#endif
freshline->prev = prevnode;
if (prevnode == NULL) {
/* Special case: we're inserting into the first line. */
freshline->next = openfile->fileage;
openfile->fileage = freshline;
freshline->lineno = 1;
} else {
prevnode->next = freshline;
freshline->next = NULL;
freshline->lineno = prevnode->lineno + 1;
}
return freshline;
} }
/* Read an open file into the current buffer. f should be set to the /* Read an open file into the current buffer. f should be set to the
...@@ -731,6 +701,8 @@ filestruct *read_line(char *buf, size_t buf_len, filestruct *prevnode) ...@@ -731,6 +701,8 @@ filestruct *read_line(char *buf, size_t buf_len, filestruct *prevnode)
void read_file(FILE *f, int fd, const char *filename, bool undoable, void read_file(FILE *f, int fd, const char *filename, bool undoable,
bool checkwritable) bool checkwritable)
{ {
ssize_t was_lineno = openfile->current->lineno;
/* The line number where we start the insertion. */
size_t num_lines = 0; size_t num_lines = 0;
/* The number of lines in the file. */ /* The number of lines in the file. */
size_t len = 0; size_t len = 0;
...@@ -741,8 +713,10 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, ...@@ -741,8 +713,10 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
/* The buffer in which we assemble each line of the file. */ /* The buffer in which we assemble each line of the file. */
size_t bufx = MAX_BUF_SIZE; size_t bufx = MAX_BUF_SIZE;
/* The allocated size of the line buffer; increased as needed. */ /* The allocated size of the line buffer; increased as needed. */
filestruct *fileptr = openfile->current->prev; filestruct *topline;
/* The line after which to start inserting. */ /* The top of the new buffer where we store the read file. */
filestruct *bottomline;
/* The bottom of the new buffer. */
int input_int; int input_int;
/* The current value we read from the file, whether an input /* The current value we read from the file, whether an input
* character or EOF. */ * character or EOF. */
...@@ -760,7 +734,11 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, ...@@ -760,7 +734,11 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
add_undo(INSERT); add_undo(INSERT);
#endif #endif
/* Read the entire file into the filestruct. */ /* Create an empty buffer. */
topline = make_new_node(NULL);
bottomline = topline;
/* Read the entire file into the new buffer. */
while ((input_int = getc(f)) != EOF) { while ((input_int = getc(f)) != EOF) {
input = (char)input_int; input = (char)input_int;
...@@ -777,14 +755,6 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, ...@@ -777,14 +755,6 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
if (format == 0 || format == 2) if (format == 0 || format == 2)
format++; format++;
} }
#endif
/* Read in the line properly. */
fileptr = read_line(buf, len, fileptr);
num_lines++;
/* Reset the length in preparation for the next line. */
len = 0;
#ifndef NANO_TINY
/* If it's a Mac file ('\r' without '\n' on the first line if we /* If it's a Mac file ('\r' without '\n' on the first line if we
* think it's a *nix file, or on any line otherwise), and file * think it's a *nix file, or on any line otherwise), and file
* conversion isn't disabled, handle it! */ * conversion isn't disabled, handle it! */
...@@ -795,15 +765,6 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, ...@@ -795,15 +765,6 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
* set format to both DOS and Mac. */ * set format to both DOS and Mac. */
if (format == 0 || format == 1) if (format == 0 || format == 1)
format += 2; format += 2;
/* Read in the line properly. */
fileptr = read_line(buf, len, fileptr);
num_lines++;
/* Store the character after the \r as the first character
* of the next line. */
buf[0] = input;
len = 1;
#endif #endif
} else { } else {
/* Store the character. */ /* Store the character. */
...@@ -819,7 +780,30 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, ...@@ -819,7 +780,30 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
bufx += MAX_BUF_SIZE; bufx += MAX_BUF_SIZE;
buf = charealloc(buf, bufx); buf = charealloc(buf, bufx);
} }
continue;
} }
#ifndef NANO_TINY
/* If it's a DOS or Mac line, strip the '\r' from it. */
if (len > 0 && buf[len - 1] == '\r' && !ISSET(NO_CONVERT))
buf[--len] = '\0';
#endif
/* Store the data and make a new line. */
bottomline->data = encode_data(buf, len);
bottomline->next = make_new_node(bottomline);
bottomline = bottomline->next;
num_lines++;
/* Reset the length in preparation for the next line. */
len = 0;
#ifndef NANO_TINY
/* If it happens to be a Mac line, store the character after the \r
* as the first character of the next line. */
if (input != '\n')
buf[len++] = input;
#endif
} }
/* Perhaps this could use some better handling. */ /* Perhaps this could use some better handling. */
...@@ -831,78 +815,43 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, ...@@ -831,78 +815,43 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
writable = is_file_writable(filename); writable = is_file_writable(filename);
} }
/* Did we not get a newline and still have stuff to do? */ /* If the file ended with newline, or it was entirely empty, make the
if (len > 0) { * last line blank. Otherwise, put the last read data in. */
if (len == 0)
bottomline->data = mallocstrcpy(NULL, "");
else {
bool mac_line_needs_newline = FALSE;
#ifndef NANO_TINY #ifndef NANO_TINY
/* If file conversion isn't disabled and the last character in /* If the final character is '\r', and file conversion isn't disabled,
* this file is '\r', set format to Mac if we currently think * set format to Mac if we currently think the file is a *nix file, or
* the file is a *nix file, or to both DOS and Mac if we * to DOS-and-Mac if we currently think it is a DOS file. */
* currently think the file is a DOS file. */ if (buf[len - 1] == '\r' && !ISSET(NO_CONVERT)) {
if (buf[len - 1] == '\r' && !ISSET(NO_CONVERT) && format < 2) if (format < 2)
format += 2; format += 2;
#endif
/* Read in the last line properly. */
fileptr = read_line(buf, len, fileptr);
num_lines++;
}
free(buf); /* Strip the carriage return. */
buf[--len] = '\0';
/* Attach the file we got to the filestruct. If we got a file of /* Indicate we need to put a blank line in after this one. */
* zero bytes, don't do anything. */ mac_line_needs_newline = TRUE;
if (num_lines > 0) {
/* If the file we got doesn't end in a newline (nor in a Mac return),
* tack its last line onto the beginning of the line at current. */
if (len > 0 && (input != '\r' || ISSET(NO_CONVERT))) {
filestruct *dropline = fileptr;
size_t current_len = strlen(openfile->current->data);
/* Adjust the current x-coordinate to compensate for the
* change in the current line. */
if (num_lines == 1)
openfile->current_x += len;
else
openfile->current_x = len;
/* Tack the text at fileptr onto the beginning of the text
* at current. */
openfile->current->data = charealloc(openfile->current->data,
len + current_len + 1);
charmove(openfile->current->data + len, openfile->current->data,
current_len + 1);
strncpy(openfile->current->data, fileptr->data, len);
/* Step back one line, and blow away the unterminated line,
* since its text has been copied into current. */
fileptr = fileptr->prev;
delete_node(dropline);
}
if (fileptr == NULL)
/* After inserting a single unterminated line at the top,
* readjust the top-of-file pointer. */
openfile->fileage = openfile->current;
else {
/* Attach the line at current after the line at fileptr. */
fileptr->next = openfile->current;
openfile->current->prev = fileptr;
} }
#endif
/* Store the data of the final line. */
bottomline->data = encode_data(buf, len);
num_lines++;
/* Renumber, starting with the last line of the file we inserted. */ if (mac_line_needs_newline) {
renumber(openfile->current); bottomline->next = make_new_node(bottomline);
bottomline = bottomline->next;
bottomline->data = mallocstrcpy(NULL, "");
}
} }
openfile->totsize += get_totsize(openfile->fileage, openfile->filebot); free(buf);
/* If the NO_NEWLINES flag isn't set, and text has been added to /* Insert the just read buffer into the current one. */
* the magicline (i.e. a file that doesn't end in a newline has been ingraft_buffer(topline);
* inserted at the end of the current buffer), add a new magicline,
* and move the current line down to it. */
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0') {
new_magicline();
openfile->current = openfile->filebot;
openfile->current_x = 0;
}
/* Set the desired x position at the end of what was inserted. */ /* Set the desired x position at the end of what was inserted. */
openfile->placewewant = xplustabs(); openfile->placewewant = xplustabs();
...@@ -931,7 +880,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, ...@@ -931,7 +880,7 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable,
statusline(HUSH, P_("Read %lu line", "Read %lu lines", statusline(HUSH, P_("Read %lu line", "Read %lu lines",
(unsigned long)num_lines), (unsigned long)num_lines); (unsigned long)num_lines), (unsigned long)num_lines);
if (num_lines < editwinrows) if (openfile->current->lineno - was_lineno < editwinrows)
focusing = FALSE; focusing = FALSE;
#ifndef NANO_TINY #ifndef NANO_TINY
......
...@@ -301,7 +301,7 @@ void switch_to_prev_buffer_void(void); ...@@ -301,7 +301,7 @@ void switch_to_prev_buffer_void(void);
void switch_to_next_buffer_void(void); void switch_to_next_buffer_void(void);
bool close_buffer(void); bool close_buffer(void);
#endif #endif
filestruct *read_line(char *buf, size_t buf_len, filestruct *prevnode); char *encode_data(char *buf, size_t buf_len);
void read_file(FILE *f, int fd, const char *filename, bool undoable, void read_file(FILE *f, int fd, const char *filename, bool undoable,
bool checkwritable); bool checkwritable);
int open_file(const char *filename, bool newfie, bool quiet, FILE **f); int open_file(const char *filename, bool newfie, bool quiet, FILE **f);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment