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. */
void do_cut_text_void(void)
{
#ifndef NANO_TINY
- add_undo(CUT, openfile);
+ add_undo(CUT);
#endif
do_cut_text(
#ifndef NANO_TINY
void do_cut_till_end(void)
{
#ifndef NANO_TINY
- add_undo(CUTTOEND, openfile);
+ add_undo(CUTTOEND);
#endif
do_cut_text(FALSE, TRUE, FALSE);
}
/* 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
/* 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 =
/* 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;
}
/* 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. */
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
/* 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. */
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)",
#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. */
/* Save the file specified in answer in the current
* buffer. */
- open_buffer(answer);
+ open_buffer(answer, TRUE);
#ifndef NANO_TINY
}
#endif
set_modified();
#ifndef NANO_TINY
- update_undo(ADD, openfile);
+ update_undo(ADD);
/* Note that current_x has not yet been incremented. */
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,
* 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);
}
} 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. */
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
#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(
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);
size_t length_change;
#ifndef NANO_TINY
- update_undo(REPLACE, openfile);
+ update_undo(REPLACE);
#endif
if (i == 2)
replaceall = TRUE;
* 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));
filestruct *f = openfile->current, *t;
int len = 0;
char *undidmsg, *data;
+ filestruct *oldcutbuffer = cutbuffer, *oldcutbottom = cutbottom;
if (!u) {
statusbar(_("Nothing in undo buffer!"));
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;
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. */
if (f == NULL)
nperror("fdopen");
- read_file(f, "stdin");
+ read_file(f, "stdin", TRUE);
if (wait(NULL) == -1)
nperror("wait");
}
/* 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 */
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:
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",
/* 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;
}
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);
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);
u->begin--;
} else {
/* They deleted something else on the line */
- add_undo(DEL, fs);
+ add_undo(DEL);
return;
}
#ifdef DEBUG
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 */
#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;
}
}
}
+/* 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)
{