diff --git a/src/cut.c b/src/cut.c index 6fda848c..72148e13 100644 --- a/src/cut.c +++ b/src/cut.c @@ -205,7 +205,7 @@ void do_cut_text( if (!old_no_newlines) UNSET(NO_NEWLINES); } else if (!undoing) - update_undo(CUT, openfile); + update_undo(CUT); #endif /* Leave the text in the cutbuffer, and mark the file as * modified. */ @@ -224,7 +224,7 @@ void do_cut_text( void do_cut_text_void(void) { #ifndef NANO_TINY - add_undo(CUT, openfile); + add_undo(CUT); #endif do_cut_text( #ifndef NANO_TINY @@ -245,7 +245,7 @@ void do_copy_text(void) void do_cut_till_end(void) { #ifndef NANO_TINY - add_undo(CUTTOEND, openfile); + add_undo(CUTTOEND); #endif do_cut_text(FALSE, TRUE, FALSE); } diff --git a/src/files.c b/src/files.c index 10b8a3e1..a5607dd2 100644 --- a/src/files.c +++ b/src/files.c @@ -101,7 +101,7 @@ void initialize_buffer_text(void) /* If it's not "", filename is a file to open. We make a new buffer, if * necessary, and then open and read the file, if applicable. */ -void open_buffer(const char *filename) +void open_buffer(const char *filename, bool undoable) { bool new_buffer = (openfile == NULL #ifdef ENABLE_MULTIBUFFER @@ -142,7 +142,7 @@ void open_buffer(const char *filename) /* If we have a non-new file, read it in. Then, if the buffer has * no stat, update the stat, if applicable. */ if (rc == 0) { - read_file(f, filename); + read_file(f, filename, undoable); #ifndef NANO_TINY if (openfile->current_stat == NULL) { openfile->current_stat = @@ -192,7 +192,7 @@ void replace_buffer(const char *filename) /* If we have a non-new file, read it in. */ if (rc == 0) - read_file(f, filename); + read_file(f, filename, FALSE); /* Move back to the beginning of the first line of the buffer. */ openfile->current = openfile->fileage; @@ -339,8 +339,9 @@ filestruct *read_line(char *buf, filestruct *prevnode, bool } /* Read an open file into the current buffer. f should be set to the - * open file, and filename should be set to the name of the file. */ -void read_file(FILE *f, const char *filename) + * open file, and filename should be set to the name of the file. + undoable means do we want to create undo records to try and undo this */ +void read_file(FILE *f, const char *filename, bool undoable) { size_t num_lines = 0; /* The number of lines in the file. */ @@ -371,6 +372,11 @@ void read_file(FILE *f, const char *filename) buf = charalloc(bufx); buf[0] = '\0'; +#ifndef NANO_TINY + if (undoable) + add_undo(INSERT); +#endif + if (openfile->current == openfile->fileage) first_line_ins = TRUE; else @@ -489,7 +495,7 @@ void read_file(FILE *f, const char *filename) /* If we didn't get a file and we don't already have one, open a * blank buffer. */ if (fileptr == NULL) - open_buffer(""); + open_buffer("", FALSE); /* Attach the file we got to the filestruct. If we got a file of * zero bytes, don't do anything. */ @@ -561,6 +567,9 @@ void read_file(FILE *f, const char *filename) openfile->placewewant = xplustabs(); #ifndef NANO_TINY + if (undoable) + update_undo(INSERT); + if (format == 3) statusbar( P_("Read %lu line (Converted from DOS and Mac format)", @@ -853,7 +862,7 @@ void do_insertfile( #ifdef ENABLE_MULTIBUFFER if (ISSET(MULTIBUFFER)) /* Open a blank buffer. */ - open_buffer(""); + open_buffer("", FALSE); #endif /* Save the command's output in the current buffer. */ @@ -877,7 +886,7 @@ void do_insertfile( /* Save the file specified in answer in the current * buffer. */ - open_buffer(answer); + open_buffer(answer, TRUE); #ifndef NANO_TINY } #endif diff --git a/src/nano.c b/src/nano.c index 14be3388..eb8678a1 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1647,7 +1647,7 @@ void do_output(char *output, size_t output_len, bool allow_cntrls) set_modified(); #ifndef NANO_TINY - update_undo(ADD, openfile); + update_undo(ADD); /* Note that current_x has not yet been incremented. */ @@ -2232,7 +2232,7 @@ int main(int argc, char **argv) icol == 1) parse_line_column(&argv[i][1], &iline, &icol); else { - open_buffer(argv[i]); + open_buffer(argv[i], FALSE); if (iline > 1 || icol > 1) { do_gotolinecolumn(iline, icol, FALSE, FALSE, FALSE, @@ -2249,14 +2249,14 @@ int main(int argc, char **argv) * buffer or a new buffer, depending on whether multibuffer mode is * enabled. */ if (optind < argc) - open_buffer(argv[optind]); + open_buffer(argv[optind], FALSE); /* 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 (openfile == NULL) { - open_buffer(""); + open_buffer("", FALSE); UNSET(VIEW_MODE); } diff --git a/src/nano.h b/src/nano.h index a1bb6720..b286f0d0 100644 --- a/src/nano.h +++ b/src/nano.h @@ -170,7 +170,7 @@ typedef enum { } function_type; typedef enum { - ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, CUTTOEND, UNCUT, OTHER + ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, CUTTOEND, UNCUT, INSERT, OTHER } undo_type; /* Structure types. */ diff --git a/src/proto.h b/src/proto.h index 0c8d3575..2a40dda2 100644 --- a/src/proto.h +++ b/src/proto.h @@ -255,7 +255,7 @@ void do_uncut_text(void); void make_new_buffer(void); void initialize_buffer(void); void initialize_buffer_text(void); -void open_buffer(const char *filename); +void open_buffer(const char *filename, bool undoable); #ifndef DISABLE_SPELLER void replace_buffer(const char *filename); #endif @@ -268,7 +268,7 @@ bool close_buffer(void); #endif filestruct *read_line(char *buf, filestruct *prevnode, bool *first_line_ins, size_t buf_len); -void read_file(FILE *f, const char *filename); +void read_file(FILE *f, const char *filename, bool undoable); int open_file(const char *filename, bool newfie, FILE **f); char *get_next_filename(const char *name, const char *suffix); void do_insertfile( @@ -707,10 +707,11 @@ void new_magicline(void); void remove_magicline(void); void mark_order(const filestruct **top, size_t *top_x, const filestruct **bot, size_t *bot_x, bool *right_side_up); -void add_undo(undo_type current_action, openfilestruct *fs); -void update_undo(undo_type action, openfilestruct *fs); +void add_undo(undo_type current_action); +void update_undo(undo_type action); #endif size_t get_totsize(const filestruct *begin, const filestruct *end); +filestruct *fsfromline(ssize_t lineno); #ifdef DEBUG void dump_filestruct(const filestruct *inptr); void dump_filestruct_reverse(void); diff --git a/src/search.c b/src/search.c index 35d3d135..64ff953d 100644 --- a/src/search.c +++ b/src/search.c @@ -789,7 +789,7 @@ ssize_t do_replace_loop( size_t length_change; #ifndef NANO_TINY - update_undo(REPLACE, openfile); + update_undo(REPLACE); #endif if (i == 2) replaceall = TRUE; diff --git a/src/text.c b/src/text.c index 7bd3a7db..0564cb9c 100644 --- a/src/text.c +++ b/src/text.c @@ -71,7 +71,7 @@ void do_delete(void) * just update_line()? */ #ifndef NANO_TINY - update_undo(DEL, openfile); + update_undo(DEL); #endif assert(openfile->current != NULL && openfile->current->data != NULL && openfile->current_x <= strlen(openfile->current->data)); @@ -371,6 +371,7 @@ void do_undo(void) filestruct *f = openfile->current, *t; int len = 0; char *undidmsg, *data; + filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom; if (!u) { statusbar(_("Nothing in undo buffer!")); @@ -458,6 +459,24 @@ void do_undo(void) free_filestruct(cutbuffer); cutbuffer = NULL; break; + case INSERT: + undidmsg = _("text insert"); + cutbuffer = NULL; + cutbottom = NULL; + /* When we updated mark_begin_lineno in update_undo, it was effectively how many line + were inserted due to being partitioned before read_file was called. So we + add its value here */ + openfile->mark_begin = fsfromline(u->lineno + u->mark_begin_lineno - 1); + openfile->mark_begin_x = 0; + openfile->mark_set = TRUE; + do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE); + cut_marked(); + u->cutbuffer = cutbuffer; + u->cutbottom = cutbottom; + cutbuffer = oldcutbuffer; + cutbottom = oldcutbottom; + openfile->mark_set = FALSE; + break; case REPLACE: undidmsg = _("text replace"); data = u->strdata; @@ -622,7 +641,7 @@ void do_enter(void) assert(openfile->current != NULL && xopenfile->current->data != NULL); #ifndef NANO_TINY - update_undo(SPLIT, openfile); + update_undo(SPLIT); /* Do auto-indenting, like the neolithic Turbo Pascal editor. */ @@ -750,7 +769,7 @@ bool execute_command(const char *command) if (f == NULL) nperror("fdopen"); - read_file(f, "stdin"); + read_file(f, "stdin", TRUE); if (wait(NULL) == -1) nperror("wait"); @@ -767,10 +786,11 @@ bool execute_command(const char *command) } /* Add a new undo struct to the top of the current pile */ -void add_undo(undo_type current_action, openfilestruct *fs) +void add_undo(undo_type current_action) { undo *u; char *data; + openfilestruct *fs = openfile; /* Ugh, if we were called while cutting not-to-end, non-marked and on the same lineno, we need to abort here */ @@ -831,12 +851,11 @@ void add_undo(undo_type current_action, openfilestruct *fs) data = mallocstrcpy(NULL, fs->current->next->data); u->strdata = data; } - u->begin = fs->current_x; break; + case INSERT: case SPLIT: case REPLACE: data = mallocstrcpy(NULL, fs->current->data); - u->begin = fs->current_x; u->strdata = data; break; case CUT: @@ -868,12 +887,12 @@ void add_undo(undo_type current_action, openfilestruct *fs) instead. The latter functionality just feels gimmicky and may just be more hassle than it's worth, so it should be axed if needed. */ -void update_undo(undo_type action, openfilestruct *fs) +void update_undo(undo_type action) { undo *u; char *data; int len = 0; - + openfilestruct *fs = openfile; #ifdef DEBUG fprintf(stderr, "action = %d, fs->last_action = %d, openfile->current->lineno = %d", @@ -887,9 +906,9 @@ void update_undo(undo_type action, openfilestruct *fs) /* Change to an add if we're not using the same undo struct that we should be using */ if (action != fs->last_action - || (action != CUT && action != CUTTOEND + || (action != CUT && action != CUTTOEND && action != INSERT && openfile->current->lineno != fs->current_undo->lineno)) { - add_undo(action, fs); + add_undo(action); return; } @@ -919,7 +938,7 @@ void update_undo(undo_type action, openfilestruct *fs) if (!u->xflags) u->xflags = UNDO_DEL_DEL; else if (u->xflags != UNDO_DEL_DEL) { - add_undo(action, fs); + add_undo(action); return; } data = charalloc(len); @@ -933,7 +952,7 @@ void update_undo(undo_type action, openfilestruct *fs) if (!u->xflags) u->xflags = UNDO_DEL_BACKSPACE; else if (u->xflags != UNDO_DEL_BACKSPACE) { - add_undo(action, fs); + add_undo(action); return; } data = charalloc(len); @@ -944,7 +963,7 @@ void update_undo(undo_type action, openfilestruct *fs) u->begin--; } else { /* They deleted something else on the line */ - add_undo(DEL, fs); + add_undo(DEL); return; } #ifdef DEBUG @@ -961,8 +980,10 @@ void update_undo(undo_type action, openfilestruct *fs) u->linescut++; break; case REPLACE: - add_undo(action, fs); + add_undo(action); break; + case INSERT: + u->mark_begin_lineno = openfile->current->lineno; case SPLIT: case UNSPLIT: /* These cases are handled by the earlier check for a new line and action */ @@ -977,7 +998,7 @@ void update_undo(undo_type action, openfilestruct *fs) #ifdef DEBUG fprintf(stderr, "Starting add_undo for new action as it does not match last_action\n"); #endif - add_undo(action, openfile); + add_undo(action); } fs->last_action = action; } diff --git a/src/utils.c b/src/utils.c index 658e418b..d09118fa 100644 --- a/src/utils.c +++ b/src/utils.c @@ -603,6 +603,24 @@ void dump_filestruct(const filestruct *inptr) } } +/* Get back a pointer given a line number in the current openfilestruct */ +filestruct *fsfromline(ssize_t lineno) +{ + filestruct *f = openfile->current; + + if (lineno <= openfile->current->lineno) + for (; f->lineno != lineno && f != openfile->fileage; f = f->prev) + ; + else + for (; f->lineno != lineno && f->next != NULL; f = f->next) + + if (f->lineno != lineno) + return NULL; + + return f; +} + + /* Dump the current buffer's filestruct to stderr in reverse. */ void dump_filestruct_reverse(void) {