From 12dc8cae8070ea5a10de6d2af57bea534f45b369 Mon Sep 17 00:00:00 2001 From: Chris Allegretta Date: Thu, 31 Jul 2008 04:24:04 +0000 Subject: [PATCH] Commit back some undo/redo rewrites git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@4283 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- src/cut.c | 6 ++- src/global.c | 1 + src/nano.h | 31 ++++++++++---- src/proto.h | 1 + src/text.c | 113 +++++++++++++++++++++++++++++++++++---------------- 5 files changed, 110 insertions(+), 42 deletions(-) diff --git a/src/cut.c b/src/cut.c index 57ba5c3c..b56f6d46 100644 --- a/src/cut.c +++ b/src/cut.c @@ -28,7 +28,6 @@ static bool keep_cutbuffer = FALSE; /* Should we keep the contents of the cutbuffer? */ -static filestruct *cutbottom = NULL; /* Pointer to the end of the cutbuffer. */ /* Indicate that we should no longer keep the contents of the @@ -163,6 +162,7 @@ void do_cut_text( keep_cutbuffer = TRUE; #ifndef NANO_TINY + if (cut_till_end) { /* If cut_till_end is TRUE, move all text up to the end of the * file into the cutbuffer. */ @@ -205,11 +205,13 @@ void do_cut_text( if (!old_no_newlines) UNSET(NO_NEWLINES); } else + update_undo(CUT, openfile); #endif /* Leave the text in the cutbuffer, and mark the file as * modified. */ set_modified(); + /* Update the screen. */ edit_refresh(); @@ -221,6 +223,7 @@ void do_cut_text( /* Move text from the current filestruct into the cutbuffer. */ void do_cut_text_void(void) { + add_undo(CUT, openfile); do_cut_text( #ifndef NANO_TINY FALSE, FALSE @@ -239,6 +242,7 @@ void do_copy_text(void) /* Cut from the current cursor position to the end of the file. */ void do_cut_till_end(void) { + add_undo(CUTTOEND, openfile); do_cut_text(FALSE, TRUE); } #endif /* !NANO_TINY */ diff --git a/src/global.c b/src/global.c index 5ca7c8d9..0cece9c2 100644 --- a/src/global.c +++ b/src/global.c @@ -69,6 +69,7 @@ int editwinrows = 0; filestruct *cutbuffer = NULL; /* The buffer where we store cut text. */ +filestruct *cutbottom = NULL; #ifndef DISABLE_JUSTIFY filestruct *jusbuffer = NULL; /* The buffer where we store unjustified text. */ diff --git a/src/nano.h b/src/nano.h index f40d69d4..694acd38 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, UNCUT, OTHER + ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, CUTTOEND, UNCUT, OTHER } undo_type; /* Structure types. */ @@ -251,20 +251,37 @@ typedef struct syntaxtype { #ifndef NANO_TINY typedef struct undo { + ssize_t lineno; undo_type type; - filestruct *fs; + /* What type of undo was this */ int begin; /* Where did this action begin or end */ char *strdata; - /* Generic pointer for data regardless of what type it is */ - filestruct *fsdata; - /* Generic pointer for data regardless of what type it is */ - struct undo *next; - ssize_t lineno; + /* String type data we will use for ccopying the affected line back */ int xflags; + /* Some flag data we need */ + + /* Cut specific stuff we need */ + filestruct *cutbuffer; + /* Copy of the cutbuffer */ + filestruct *cutbottom; + /* Copy of cutbottom */ + bool mark_set; + /* was the marker set when we cut */ + bool to_end; + /* was this a cut to end */ + ssize_t mark_begin_lineno; + /* copy copy copy */ + ssize_t mark_begin_x; + /* Another shadow variable */ + + struct undo *next; } undo; + + #endif /* NANO_TINY */ + typedef struct openfilestruct { char *filename; /* The current file's name. */ diff --git a/src/proto.h b/src/proto.h index 6af1d462..2d8c34cf 100644 --- a/src/proto.h +++ b/src/proto.h @@ -47,6 +47,7 @@ extern WINDOW *bottomwin; extern int editwinrows; extern filestruct *cutbuffer; +extern filestruct *cutbottom; #ifndef DISABLE_JUSTIFY extern filestruct *jusbuffer; #endif diff --git a/src/text.c b/src/text.c index 5666015b..2c908f60 100644 --- a/src/text.c +++ b/src/text.c @@ -368,9 +368,9 @@ void do_unindent(void) void do_undo(void) { undo *u = openfile->current_undo; - filestruct *f = openfile->current, *t; + filestruct *f = openfile->current, *t, *t2; int len = 0; - char *action, *data; + char *undidmsg, *data; if (!u) { statusbar(_("Nothing in undo buffer!")); @@ -396,7 +396,7 @@ void do_undo(void) openfile->current_x = u->begin; switch(u->type) { case ADD: - action = _("text add"); + undidmsg = _("text add"); len = strlen(f->data) - strlen(u->strdata) + 1; data = charalloc(len); strncpy(data, f->data, u->begin); @@ -405,7 +405,7 @@ void do_undo(void) f->data = data; break; case DEL: - action = _("text delete"); + undidmsg = _("text delete"); len = strlen(f->data) + strlen(u->strdata) + 1; data = charalloc(len); @@ -418,7 +418,7 @@ void do_undo(void) openfile->current_x += strlen(u->strdata); break; case SPLIT: - action = _("line split"); + undidmsg = _("line split"); free(f->data); f->data = mallocstrcpy(NULL, u->strdata); if (f->next != NULL) { @@ -429,7 +429,7 @@ void do_undo(void) renumber(f); break; case UNSPLIT: - action = _("line join"); + undidmsg = _("line join"); t = make_new_node(f); t->data = mallocstrcpy(NULL, u->strdata); data = mallocstrncpy(NULL, f->data, u->begin); @@ -439,14 +439,26 @@ void do_undo(void) splice_node(f, t, f->next); renumber(f); break; + case CUT: + case CUTTOEND: + undidmsg = _("text cut"); + cutbuffer = copy_filestruct(u->cutbuffer); + for (cutbottom = cutbuffer; cutbottom->next != NULL; cutbottom = cutbottom->next) + ; + if (u->mark_set && u->mark_begin_lineno < u->lineno) + do_gotolinecolumn(u->mark_begin_lineno, u->mark_begin_x+1, FALSE, FALSE, FALSE, FALSE); + else + do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE); + do_uncut_text(); + free_filestruct(cutbuffer); + break; default: - action = _("wtf?"); + undidmsg = _("wtf?"); break; } - openfile->current = f; - edit_refresh(); - statusbar(_("Undid action (%s)"), action); + do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE); + statusbar(_("Undid action (%s)"), undidmsg); openfile->current_undo = openfile->current_undo->next; } @@ -454,9 +466,9 @@ void do_undo(void) void do_redo(void) { undo *u = openfile->undotop; - filestruct *f = openfile->current, *t; - int len = 0; - char *action, *data; + filestruct *f = openfile->current, *t, *t2; + int len = 0, i, i2; + char *undidmsg, *data; for (; u != NULL && u->next != openfile->current_undo; u = u->next) ; @@ -486,7 +498,7 @@ void do_redo(void) switch(u->type) { case ADD: - action = _("text add"); + undidmsg = _("text add"); len = strlen(f->data) + strlen(u->strdata) + 1; data = charalloc(len); strcpy(&data[u->begin], u->strdata); @@ -495,7 +507,7 @@ void do_redo(void) f->data = data; break; case DEL: - action = _("text delete"); + undidmsg = _("text delete"); len = strlen(f->data) + strlen(u->strdata) + 1; data = charalloc(len); strncpy(data, f->data, u->begin); @@ -504,7 +516,7 @@ void do_redo(void) f->data = data; break; case SPLIT: - action = _("line split"); + undidmsg = _("line split"); t = make_new_node(f); t->data = mallocstrcpy(NULL, u->strdata); data = mallocstrncpy(NULL, f->data, u->begin); @@ -515,7 +527,7 @@ void do_redo(void) renumber(f); break; case UNSPLIT: - action = _("line join"); + undidmsg = _("line join"); len = strlen(f->data) + strlen(u->strdata + 1); data = charalloc(len); strcpy(data, f->data); @@ -529,15 +541,33 @@ void do_redo(void) } renumber(f); break; + case CUT: + case CUTTOEND: + undidmsg = _("line cut"); + do_gotolinecolumn(u->lineno, u->begin+1, FALSE, FALSE, FALSE, FALSE); + openfile->mark_set = u->mark_set; + t = cutbuffer; + cutbuffer = NULL; + if (u->mark_set) { + for (i = 1, t = openfile->fileage; i != u->mark_begin_lineno; i++) + t = t->next; + openfile->mark_begin = t; + } + openfile->mark_begin_x = u->mark_begin_x; + do_cut_text(FALSE, u->to_end); + openfile->mark_set = FALSE; + openfile->mark_begin = NULL; + openfile->mark_begin_x = 0; + cutbuffer = t; + edit_refresh(); + break; default: - action = _("wtf?"); + undidmsg = _("wtf?"); break; } - openfile->current = f; - openfile->current_x = u->begin; - edit_refresh(); - statusbar(_("Redid action (%s)"), action); + do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE); + statusbar(_("Redid action (%s)"), undidmsg); openfile->current_undo = u; @@ -697,6 +727,7 @@ bool execute_command(const char *command) return TRUE; } +/* Add a new undo struct to the top of the current pile */ void add_undo(undo_type current_action, openfilestruct *fs) { undo *u = nmalloc(sizeof(undo)); @@ -713,8 +744,6 @@ void add_undo(undo_type current_action, openfilestruct *fs) u->type = current_action; u->lineno = fs->current->lineno; u->begin = fs->current_x; - u->fs = fs->current; - u->xflags = 0; u->next = fs->undotop; fs->undotop = u; fs->current_undo = u; @@ -746,27 +775,44 @@ void add_undo(undo_type current_action, openfilestruct *fs) break; case SPLIT: data = mallocstrcpy(NULL, fs->current->data); - u->strdata = data; u->begin = fs->current_x; + u->strdata = data; + break; + case CUT: + case CUTTOEND: + u->mark_set = openfile->mark_set; + if (u->mark_set) { + u->mark_begin_lineno = openfile->mark_begin->lineno; + u->mark_begin_x = openfile->mark_begin_x; + } + u->to_end = (current_action == CUTTOEND); break; } #ifdef DEBUG fprintf(stderr, "fs->current->data = \"%s\", current_x = %d, u->begin = %d, type = %d\n", fs->current->data, fs->current_x, u->begin, current_action); - fprintf(stderr, "u->strdata = \"%s\"\n", u->strdata); fprintf(stderr, "left update_add...\n"); #endif fs->last_action = current_action; } +/* Update an undo item, or determine whether a new one + is really needed and bounce the data to add_undo + 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) { undo *u; char *data; int len = 0; - if (action != fs->last_action) { + /* 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 + && openfile->current->lineno != fs->undotop->lineno)) { add_undo(action, fs); return; } @@ -774,13 +820,6 @@ void update_undo(undo_type action, openfilestruct *fs) assert(fs->undotop != NULL); u = fs->undotop; - if (u->fs->data != openfile->current->data || u->lineno != openfile->current->lineno) { - add_undo(action, fs); - return; - } - - - switch (u->type) { case ADD: #ifdef DEBUG @@ -836,6 +875,12 @@ void update_undo(undo_type action, openfilestruct *fs) fprintf(stderr, "current undo data now \"%s\"\nu->begin = %d\n", u->strdata, u->begin); #endif break; + case CUT: + case CUTTOEND: + case UNCUT: + u->cutbuffer = copy_filestruct(cutbuffer); + u->cutbottom = cutbottom; + break; case SPLIT: case UNSPLIT: /* We don't really ever update an enter key press, treat it as a new */