diff --git a/src/cut.c b/src/cut.c
index 57ba5c3c2331f48f2ed9d0f27f64af4a389f97d1..b56f6d4653711a9fc147472515d6c7f91c8a5a84 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 5ca7c8d9af9ea8900bdecd62bb2ee74bef795c9c..0cece9c282b0d8f35c40beb79056379bbadd7067 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 f40d69d4ba32d723e2c3093fb86e5caf0318b1c3..694acd38f191fb7f8da905777697fcf20a72dc19 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 6af1d46207c7c6c2331b0c9079baaff4b0095328..2d8c34cf7b0ac13af50de6908e3a661767096bd0 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 5666015b0b09a8fa5d51176e833378e7ed978612..2c908f6099a863c1ea683b8e6a00b853019ce66b 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 */