commit 12dc8cae8070ea5a10de6d2af57bea534f45b369
parent 0b499d465bca356b52a4cb8cdf9b780f1dbb4e6a
Author: Chris Allegretta <chrisa@asty.org>
Date: Thu, 31 Jul 2008 04:24:04 +0000
Commit back some undo/redo rewrites
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@4283 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
Diffstat:
5 files changed, 110 insertions(+), 42 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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 */