diff --git a/ChangeLog b/ChangeLog
index e143a45f3ea9894868c4a21741c1ed0772b22c82..55296e37f408fa3bf78e34dab1fa7aba6ab6a375 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,40 @@
 CVS code -
+- General:
+	- Overhaul the cutting and uncutting routines to use the
+	  partitioning code, as it greatly simplifies how they work.
+	  New functions move_to_filestruct(), copy_from_filestruct(),
+	  cut_line(), cut_marked(), and cut_to_eol(); changes to
+	  add_to_cutbuffer(), do_cut_text(), do_uncut_text(), etc.;
+	  removal of functions get_cutbottom(), add_to_cutbuffer(), and
+	  cut_marked_segment(). (DLR)
+	- Overhaul the justify-related routines to back up and restore
+	  unjustified text to use the partitioning code, as it greatly
+	  simplifies how they work, and to store such text in its own
+	  buffer rather than the cutbuffer.  Changes to backup_lines(),
+	  do_justify(), etc. (DLR)
+- cut.c:
+  do_uncut_text()
+	- No longer duplicate Pico's adding an extra magicline to the
+	  file if uncutting leaves the cursor on the current one, as
+	  it's actually a bug. (DLR)
+- global.c:
+  thanks_for_all_the_fish()
+	- Free the justify buffer if it isn't empty. (DLR)
 - nano.c:
+  handle_sigwinch()
+	- If the justify buffer isn't empty, blow it away and don't
+	  display "UnJustify" in the shortcut list anymore. (DLR)
   do_wrap()
 	- Make wrap_loc and word_back ssize_t's, to match fill. (DLR)
+  do_justify()
+	- For consistency, preserve placewewant if we didn't unjustify
+	  instead of setting it to 0. (DLR)
+- winio.c:
+  get_edit_input()
+	- Remove parameter allow_funcs, as it was only needed as a
+	  workaround for when justified text was stored in the cutbuffer
+	  and the cut shortcut was hit at the "Can now UnJustify!"
+	  prompt. (DLR)
 
 GNU nano 1.3.5 - 2004.11.22
 - General:
diff --git a/src/cut.c b/src/cut.c
index 3a7a8ab2e3051e5f839917100e247f9ed1cc2c8c..a90defa6c297b9fa99e6aa4c89c9504ffe318ab6 100644
--- a/src/cut.c
+++ b/src/cut.c
@@ -32,12 +32,6 @@
 
 static bool keep_cutbuffer = FALSE;
 	/* Should we keep the contents of the cutbuffer? */
-static cut_type marked_cut = CUT_LINE;
-	/* What type of cut is in the cutbuffer? */
-#ifndef NANO_SMALL
-static bool concatenate_cut = FALSE;
-	/* Should we add this cut string to the end of the last one? */
-#endif
 static filestruct *cutbottom = NULL;
 	/* Pointer to end of cutbuffer. */
 
@@ -46,444 +40,133 @@ void cutbuffer_reset(void)
     keep_cutbuffer = FALSE;
 }
 
-filestruct *get_cutbottom(void)
+/* If we're not on the magicline, move all the text of the current line,
+ * plus the newline at the end, to the cutbuffer. */
+void cut_line(void)
 {
-    return cutbottom;
-}
-
-void add_to_cutbuffer(filestruct *inptr, bool allow_concat)
-{
-#ifdef DEBUG
-    fprintf(stderr, "add_to_cutbuffer(): inptr->data = %s\n", inptr->data);
-#endif
-
-    if (cutbuffer == NULL)
-	cutbuffer = inptr;
-#ifndef NANO_SMALL
-    else if (allow_concat && concatenate_cut) {
-	/* If allow_concat is TRUE and we're concatenating, tack the
-	 * text in inptr onto the text in cutbottom. */
-	cutbottom->data = charealloc(cutbottom->data,
-		strlen(cutbottom->data) + strlen(inptr->data) + 1);
-	strcat(cutbottom->data, inptr->data);
-	return;
-    }
-#endif
-    else {
-	cutbottom->next = inptr;
-	inptr->prev = cutbottom;
-    }
-    cutbottom = inptr;
-    cutbottom->next = NULL;
+    if (current->next != NULL)
+	move_to_filestruct(&cutbuffer, &cutbottom, current, 0,
+		current->next, 0);
 }
 
 #ifndef NANO_SMALL
-/* Cut a marked segment instead of a whole line.
- *
- * The first cut character is top->data[top_x].  Unless top == bot, the
- * last cut line has length bot_x.  That is, if bot_x > 0 then we cut to
- * bot->data[bot_x - 1].
- *
- * We maintain totsize, totlines, filebot, the magicline, and line
- * numbers.  Also, we set current and current_x so the cursor will be on
- * the first character after what was cut.  We do not do any screen
- * updates.
- *
- * Note cutbuffer might not be NULL if cut to end is used. */
-void cut_marked_segment(void)
+/* Move all currently marked text to the cutbuffer, and set the current
+ * place we want to where the text used to start. */
+void cut_marked(void)
 {
-    filestruct *top;
-    filestruct *bot;
-    filestruct *tmp;
-    size_t top_x;
-    size_t bot_x;
-    size_t newsize;
+    filestruct *top, *bot;
+    size_t top_x, bot_x;
 
-    /* If the mark doesn't cover any text, get out. */
-    if (current == mark_beginbuf && current_x == mark_beginx)
-	return;
-    assert(current != NULL && mark_beginbuf != NULL);
-
-    /* Set up the top and bottom lines and coordinates of the marked
-     * text. */
     mark_order((const filestruct **)&top, &top_x,
-		(const filestruct **)&bot, &bot_x, NULL);
-
-    /* Make the first cut line manually.  Move the cut part of the top
-     * line into tmp, and set newsize to that partial line's length. */
-    tmp = copy_node(top);
-    newsize = (top == bot ? bot_x - top_x : strlen(top->data + top_x));
-    charmove(tmp->data, tmp->data + top_x, newsize);
-    null_at(&tmp->data, newsize);
-
-    /* Add the contents of tmp to the cutbuffer.  Note that cutbuffer
-     * might be non-NULL if we have cut to end enabled. */
-    if (cutbuffer == NULL) {
-	cutbuffer = tmp;
-	cutbottom = tmp;
-    } else {
-	if (concatenate_cut) {
-	    /* If we're concatenating, tack the text in the first line
-	     * of tmp onto the text in the bottom of the cutbuffer, and
-	     * move tmp one line down to where its next line begins. */
-	    cutbottom->data = charealloc(cutbottom->data,
-		strlen(cutbottom->data) + strlen(tmp->data) + 1);
-	    strcat(cutbottom->data, tmp->data);
-	    tmp = tmp->next;
-	}
-
-	/* Put tmp on the line after the bottom of the cutbuffer. */
-	cutbottom->next = tmp;
-
-	if (!concatenate_cut) {
-	    /* Tf we're not concatenating, attach tmp to the bottom of
-	     * the cutbuffer, and then move the bottom of the cutbuffer
-	     * one line down to where tmp is. */
-	    tmp->prev = cutbottom;
-	    cutbottom = tmp;
-	}
-    }
+	(const filestruct **)&bot, &bot_x, NULL);
 
-    /* And make the top remainder line manually too.  Update current_x
-     * and totlines to account for all the cut text, and update totsize
-     * to account for the length of the cut part of the first line. */
-    current_x = top_x;
-    totsize -= newsize;
-    totlines -= bot->lineno - top->lineno;
-
-    /* Now set newsize to be the length of the top remainder line plus
-     * the bottom remainder line, plus one for the null terminator. */
-    newsize = top_x + strlen(bot->data + bot_x) + 1;
-
-    if (top == bot) {
-	/* In this case, we're only cutting one line or part of one
-	 * line, so the remainder line is shorter.  This means that we
-	 * must move text from the end forward first. */
-	charmove(top->data + top_x, bot->data + bot_x, newsize - top_x);
-	top->data = charealloc(top->data, newsize);
-
-	cutbottom->next = NULL;
-#ifdef DEBUG
-	dump_buffer(cutbuffer);
+    move_to_filestruct(&cutbuffer, &cutbottom, top, top_x, bot, bot_x);
+    placewewant = xplustabs();
+}
 #endif
-	return;
-    }
-
-    /* Update totsize to account for the cut part of the last line. */
-    totsize -= bot_x + 1;
-
-    /* Here, the top remainder line might get longer (if the bottom
-     * remainder line is added to the end of it), so we realloc() it
-     * first. */
-    top->data = charealloc(top->data, newsize);
-    charmove(top->data + top_x, bot->data + bot_x, newsize - top_x);
-
-    assert(cutbottom != NULL && cutbottom->next != NULL);
-    /* We're cutting multiple lines, so in particular the next line is
-     * cut too. */
-    cutbottom->next->prev = cutbottom;
-
-    /* Update totsize to account for all the complete lines that have
-     * been cut.  After this, totsize is fully up to date. */
-    for (tmp = top->next; tmp != bot; tmp = tmp->next)
-	totsize -= strlen(tmp->data) + 1;
-
-    /* Make the last cut line manually. */
-    null_at(&bot->data, bot_x);
-
-    /* Move the rest of the cut text (other than the cut part of the top
-     * line) from the buffer to the end of the cutbuffer, and fix the
-     * edit buffer to account for the cut text. */
-    top->next = bot->next;
-    cutbottom = bot;
-    cutbottom->next = NULL;
-    if (top->next != NULL)
-	top->next->prev = top;
-    renumber(top);
-    current = top;
 
-    /* If the bottom line of the cut was the magicline, set filebot
-     * properly, and add a new magicline if the top remainder line
-     * (which is now the new bottom line) is non-blank. */
-    if (bot == filebot) {
-	filebot = top;
-	assert(bot_x == 0);
-	if (top_x > 0)
-	    new_magicline();
+/* If we're not at the end of the current line, move all the text from
+ * the current cursor position to the end of the current line,
+ * not counting the newline at the end, to the cutbuffer.  If we are,
+ * and we're not on the magicline, move the newline at the end to the
+ * cutbuffer, and set the current place we want to where the newline
+ * used to be. */
+void cut_to_eol(void)
+{
+    size_t data_len = strlen(current->data);
+
+    assert(current_x <= data_len);
+
+    if (current_x < data_len)
+	/* If we're not at the end of the line, move all the text from
+	 * the current position up to it, not counting the newline at
+	 * the end, to the cutbuffer. */
+	move_to_filestruct(&cutbuffer, &cutbottom, current, current_x,
+		current, data_len);
+    else if (current->next != NULL) {
+	/* If we're at the end of the line, and the next line isn't the
+	 * magicline, move all the text from the current position up to
+	 * the beginning of the next line, i.e, the newline at the
+	 * end, to the cutbuffer. */
+	move_to_filestruct(&cutbuffer, &cutbottom, current, current_x,
+		current->next, 0);
+	placewewant = xplustabs();
     }
-#ifdef DEBUG
-    dump_buffer(cutbuffer);
-#endif
 }
-#endif
 
+/* Move text from the current filestruct into the cutbuffer. */
 void do_cut_text(void)
 {
-    filestruct *fileptr;
-
     assert(current != NULL && current->data != NULL);
 
     check_statusblank();
 
+    /* If keep_cutbuffer is FALSE, blow away the text in the
+     * cutbuffer. */
     if (!keep_cutbuffer) {
 	free_filestruct(cutbuffer);
 	cutbuffer = NULL;
-	marked_cut = CUT_LINE;
-#ifndef NANO_SMALL
-	concatenate_cut = FALSE;
-#endif
 #ifdef DEBUG
 	fprintf(stderr, "Blew away cutbuffer =)\n");
 #endif
     }
 
-    /* You can't cut the magicline except with the mark.  But trying
-     * does clear the cutbuffer if keep_cutbuffer is FALSE. */
-    if (current == filebot
-#ifndef NANO_SMALL
-		&& !ISSET(MARK_ISSET)
-#endif
-		)
-	return;
-
+    /* Set keep_cutbuffer to TRUE, so that the text we're going to move
+     * into the cutbuffer will be added to the text already in the
+     * cutbuffer instead of replacing it. */
     keep_cutbuffer = TRUE;
 
 #ifndef NANO_SMALL
-    if (ISSET(CUT_TO_END) && !ISSET(MARK_ISSET)) {
-	assert(current_x <= strlen(current->data));
-
-	if (current->data[current_x] == '\0') {
-	    /* If the line is empty and we didn't just cut a non-blank
-	     * line, create a dummy blank line and add it to the
-	     * cutbuffer. */
-	    if (marked_cut != CUT_MARKED && current->next != filebot) {
-		filestruct *junk = make_new_node(current);
-
-		junk->data = mallocstrcpy(NULL, "");
-		add_to_cutbuffer(junk, TRUE);
-#ifdef DEBUG
-		dump_buffer(cutbuffer);
-#endif
-	    }
-
-	    do_delete();
-	    marked_cut = CUT_TO_EOL;
-	    return;
-	} else {
-	    SET(MARK_ISSET);
-
-	    mark_beginx = strlen(current->data);
-	    mark_beginbuf = current;
-	}
-    }
-
     if (ISSET(MARK_ISSET)) {
-	cut_marked_segment();
-
-	placewewant = xplustabs();
+	/* If the mark is on, move the marked text to the cutbuffer and
+	 * turn the mark off. */
+	cut_marked();
 	UNSET(MARK_ISSET);
-
-	marked_cut = CUT_MARKED;
-	concatenate_cut = TRUE;
-
-	edit_refresh();
-	set_modified();
-	return;
-    }
-#endif /* !NANO_SMALL */
-
-    totlines--;
-    totsize -= strlen(current->data) + 1;
-    fileptr = current;
-    current = current->next;
-    current->prev = fileptr->prev;
-    add_to_cutbuffer(fileptr, TRUE);
-#ifdef DEBUG
-    dump_buffer(cutbuffer);
+    } else
 #endif
-
-    if (fileptr == fileage)
-	fileage = current;
+    if (ISSET(CUT_TO_END))
+	/* Otherwise, if the CUT_TO_END flag is set, move all text up to
+	 * the end of the line into the cutbuffer. */
+	cut_to_eol();
     else
-	current->prev->next = current;
-
-    if (fileptr == edittop)
-	edittop = current;
+	/* Otherwise, move the entire line into the cutbuffer. */
+	cut_line();
 
-    renumber(current);
-    current_x = 0;
     edit_refresh();
     set_modified();
-    marked_cut = CUT_LINE;
-#ifndef NANO_SMALL
-    concatenate_cut = FALSE;
+
+#ifdef DEBUG
+    dump_buffer(cutbuffer);
 #endif
 }
 
+/* Copy text from the cutbuffer into the current filestruct. */
 void do_uncut_text(void)
 {
-    filestruct *tmp = current;
-    filestruct *newbuf = NULL;
-    filestruct *newend = NULL;
+    assert(current != NULL && current->data != NULL);
 
 #ifndef DISABLE_WRAPPING
     wrap_reset();
 #endif
-    check_statusblank();
-    if (cutbuffer == NULL || current == NULL)
-	return;			/* AIEEEEEEEEEEEE */
-
-    /* If we're uncutting a previously non-marked block, uncut to end if
-     * we're not at the beginning of the line.  If we are at the
-     * beginning of the line, set placewewant to 0.  Pico does both of
-     * these. */
-    if (marked_cut == CUT_LINE) {
-	if (current_x > 0)
-	    marked_cut = CUT_TO_EOL;
-	else
-	    placewewant = 0;
-    }
-
-    /* If we're going to uncut on the magicline, always make a new
-     * magicline in advance, as Pico does. */
-    if (current->next == NULL)
-	new_magicline();
-
-    if (marked_cut == CUT_LINE || cutbuffer->next != NULL) {
-	newbuf = copy_filestruct(cutbuffer);
-	for (newend = newbuf; newend->next != NULL && newend != NULL;
-		newend = newend->next)
-	    totlines++;
-    }
-
-    /* Hook newbuf in at current. */
-    if (marked_cut != CUT_LINE) {
-	filestruct *hold = current;
-
-	/* If there's only one line in the cutbuffer... */
-	if (cutbuffer->next == NULL) {
-	    size_t buf_len = strlen(cutbuffer->data);
-	    size_t cur_len = strlen(current->data);
-
-	    current->data = charealloc(current->data, cur_len +
-		buf_len + 1);
-	    charmove(current->data + current_x + buf_len,
-		current->data + current_x, cur_len - current_x + 1);
-	    strncpy(current->data + current_x, cutbuffer->data,
-		buf_len);
-		/* Use strncpy() to not copy the null terminator. */
 
-	    current_x += buf_len;
-	    totsize += buf_len;
-
-	    placewewant = xplustabs();
-	} else {		/* Yuck -- no kidding! */
-	    char *tmpstr, *tmpstr2;
-
-	    tmp = current->next;
-
-	    /* New beginning. */
-	    tmpstr = charalloc(current_x + strlen(newbuf->data) + 1);
-	    strncpy(tmpstr, current->data, current_x);
-	    strcpy(&tmpstr[current_x], newbuf->data);
-	    totsize += strlen(newbuf->data) + strlen(newend->data) + 1;
-
-	    /* New end. */
-	    tmpstr2 = charalloc(strlen(newend->data) +
-		strlen(&current->data[current_x]) + 1);
-	    strcpy(tmpstr2, newend->data);
-	    strcat(tmpstr2, &current->data[current_x]);
-
-	    free(current->data);
-	    current->data = tmpstr;
-	    current->next = newbuf->next;
-	    newbuf->next->prev = current;
-	    delete_node(newbuf);
-
-	    current_x = strlen(newend->data);
-	    placewewant = xplustabs();
-	    free(newend->data);
-	    newend->data = tmpstr2;
-
-	    newend->next = tmp;
-
-	    /* If tmp isn't NULL, we're in the middle: update the
-	     * prev pointer.  If it IS NULL, we're at the end; update
-	     * the filebot pointer. */
-	    if (tmp != NULL)
-		tmp->prev = newend;
-	    else {
-		filebot = newend;
-		new_magicline();
-	    }
-
-	    /* Recalculate current_y and totsize. */
-	    for (tmp = current->next; tmp != newend; tmp = tmp->next) {
-		current_y++;
-		totsize += strlen(tmp->data) + 1;
-	    }
-
-	    current = newend;
-	}
-
-	/* If we're doing a cut to end, we don't want anything else on
-	 * the line, so we have to screw up all the work we just did and
-	 * separate the line. */
-	if (marked_cut == CUT_TO_EOL) {
-	    tmp = make_new_node(current);
-	    tmp->data = mallocstrcpy(NULL, current->data + current_x);
-	    splice_node(current, tmp, current->next);
-	    null_at(&current->data, current_x);
-	    current = current->next;
-	    current_x = 0;
-	    placewewant = 0;
-
-	    /* Extra line added; update stuff. */
-	    totlines++;
-	    totsize++;
-	}
-
-	/* Renumber from BEFORE where we pasted ;) */
-	renumber(hold);
+    check_statusblank();
 
-#ifdef DEBUG
-	dump_buffer(fileage);
-	dump_buffer(cutbuffer);
-#endif
-	set_modified();
-	edit_refresh();
+    /* If the cutbuffer is empty, get out. */
+    if (cutbuffer == NULL)
 	return;
-    }
-
-    if (current != fileage) {
-	tmp = current->prev;
-	tmp->next = newbuf;
-	newbuf->prev = tmp;
-    } else
-	fileage = newbuf;
 
-    totlines++;		/* Unmarked uncuts don't split lines. */
+    /* Add a copy of the text in the cutbuffer to the current filestruct
+     * at the current cursor position. */
+    copy_from_filestruct(cutbuffer, cutbottom);
 
-    /* This is so uncutting at the top of the buffer will work => */
-    if (current_y == 0)
-	edittop = newbuf;
+    /* Set the current place we want to where the text from the
+     * cutbuffer ends. */
+    placewewant = xplustabs();
 
-    /* Connect the end of the buffer to the filestruct. */
-    newend->next = current;
-    current->prev = newend;
-
-    /* Recalculate current_y and totsize. */
-    for (tmp = newbuf; tmp != current; tmp = tmp->next) {
-	current_y++;
-	totsize += strlen(tmp->data) + 1;
-    }
-
-    renumber(newbuf);
     edit_refresh();
+    set_modified();
 
 #ifdef DEBUG
     dump_buffer_reverse();
 #endif
-
-    set_modified();
 }
diff --git a/src/global.c b/src/global.c
index 580d2e35d713f5d9523b9d8ae811c466a7369ab5..761d2e09691be90cafbf3b38393423abfc634399 100644
--- a/src/global.c
+++ b/src/global.c
@@ -63,6 +63,9 @@ filestruct *edittop = NULL;	/* Pointer to the top of the edit
 				   file struct */
 filestruct *filebot = NULL;	/* Last node in the file struct */
 filestruct *cutbuffer = NULL;	/* A place to store cut text */
+#ifndef DISABLE_JUSTIFY
+filestruct *jusbuffer = NULL;	/* A place to store unjustified text */
+#endif
 partition *filepart = NULL;	/* A place to store a portion of the
 				   file struct */
 
@@ -1160,7 +1163,10 @@ void thanks_for_all_the_fish(void)
 	free(answer);
     if (cutbuffer != NULL)
 	free_filestruct(cutbuffer);
-
+#ifndef DISABLE_JUSTIFY
+    if (jusbuffer != NULL)
+	free_filestruct(jusbuffer);
+#endif
     free_shortcutage(&main_list);
     free_shortcutage(&whereis_list);
     free_shortcutage(&replace_list);
diff --git a/src/nano.c b/src/nano.c
index 88c9ccb7f2aa8c518514b394d35c3a42e9e07a37..6268773a1cc07b8dc347c76109cda46d0af37a32 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -78,6 +78,11 @@ static int pid;			/* The PID of the newly forked process
 				 * it. */
 #endif
 
+#ifndef DISABLE_JUSTIFY
+static filestruct *jusbottom = NULL;
+	/* Pointer to end of justify buffer. */
+#endif
+
 /* What we do when we're all set to exit. */
 void finish(void)
 {
@@ -714,6 +719,169 @@ void unpartition_filestruct(partition **p)
     *p = NULL;
 }
 
+/* Move all the text between (top, top_x) and (bot, bot_x) in the
+ * current filestruct to a filestruct beginning with file_top and ending
+ * with file_bot.  If no text is between (top, top_x) and (bot, bot_x),
+ * don't do anything. */
+void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
+	filestruct *top, size_t top_x, filestruct *bot, size_t bot_x)
+{
+    filestruct *top_save;
+    long part_totsize;
+    bool at_edittop;
+#ifndef NANO_SMALL
+    bool mark_inside = FALSE;
+#endif
+
+    assert(file_top != NULL && file_bot != NULL && top != NULL && bot != NULL);
+
+    /* If (top, top_x)-(bot, bot_x) doesn't cover any text, get out. */
+    if (top == bot && top_x == bot_x)
+	return;
+
+    /* Partition the filestruct so that it contains only the text from
+     * (top, top_x) to (bot, bot_x), keep track of whether the top of
+     * the partition is the top of the edit window, and keep track of
+     * whether the mark begins inside the partition. */
+    filepart = partition_filestruct(top, top_x, bot, bot_x);
+    at_edittop = (fileage == edittop);
+#ifndef NANO_SMALL
+    if (ISSET(MARK_ISSET))
+	mark_inside = (mark_beginbuf->lineno >= fileage->lineno &&
+		mark_beginbuf->lineno <= filebot->lineno &&
+		(mark_beginbuf != fileage || mark_beginx >= top_x) &&
+		(mark_beginbuf != filebot || mark_beginx <= bot_x));
+#endif
+
+    /* Get the number of characters in the text, and subtract it from
+     * totsize. */
+    get_totals(top, bot, NULL, &part_totsize);
+    totsize -= part_totsize;
+
+    if (*file_top == NULL) {
+	/* If file_top is empty, just move all the text directly into
+	 * it.  This is equivalent to tacking the text in top onto the
+	 * (lack of) text at the end of file_top. */
+	*file_top = fileage;
+	*file_bot = filebot;
+    } else {
+	/* Otherwise, tack the text in top onto the text at the end of
+	 * file_bot. */
+	(*file_bot)->data = charealloc((*file_bot)->data,
+		strlen((*file_bot)->data) + strlen(fileage->data) + 1);
+	strcat((*file_bot)->data, fileage->data);
+
+	/* Attach the line after top to the line after file_bot.  Then,
+	 * if there's more than one line after top, move file_bot down
+	 * to bot. */
+	(*file_bot)->next = fileage->next;
+	if ((*file_bot)->next != NULL) {
+	    (*file_bot)->next->prev = *file_bot;
+	    *file_bot = filebot;
+	}
+    }
+
+    /* Since the text has now been saved, remove it from the filestruct.
+     * If the top of the partition was the top of the edit window, set
+     * edittop to where the text used to start.  If the mark began
+     * inside the partition, set the beginning of the mark to where the
+     * text used to start. */
+    fileage = (filestruct *)nmalloc(sizeof(filestruct));
+    fileage->data = mallocstrcpy(NULL, "");
+    filebot = fileage;
+    if (at_edittop)
+	edittop = fileage;
+#ifndef NANO_SMALL
+    if (mark_inside) {
+	mark_beginbuf = fileage;
+	mark_beginx = top_x;
+    }
+#endif
+
+    /* Restore the current line and cursor position. */
+    current = fileage;
+    current_x = top_x;
+
+    top_save = fileage;
+
+    /* Unpartition the filestruct so that it contains all the text
+     * again, minus the saved text. */
+    unpartition_filestruct(&filepart);
+
+    /* Renumber starting with the beginning line of the old
+     * partition. */
+    renumber(top_save);
+
+    if (filebot->data[0] != '\0')
+	new_magicline();
+
+    /* Set totlines to the new number of lines in the file. */
+    totlines = filebot->lineno;
+}
+
+/* Copy all the text from the filestruct beginning with file_top and
+ * ending with file_bot to the current filestruct at the current cursor
+ * position. */
+void copy_from_filestruct(filestruct *file_top, filestruct *file_bot)
+{
+    filestruct *top_save;
+    int part_totlines;
+    long part_totsize;
+    bool at_edittop;
+
+    assert(file_top != NULL && file_bot != NULL);
+
+    /* Partition the filestruct so that it contains no text, and keep
+     * track of whether the top of the partition is the top of the edit
+     * window. */
+    filepart = partition_filestruct(current, current_x, current,
+	current_x);
+    at_edittop = (fileage == edittop);
+
+    /* Put the top and bottom of the filestruct at copies of file_top
+     * and file_bot. */
+    fileage = copy_filestruct(file_top);
+    filebot = fileage;
+    while (filebot->next != NULL)
+	filebot = filebot->next;
+
+    /* Restore the current line and cursor position. */
+    current = filebot;
+    current_x = strlen(filebot->data);
+    if (fileage == filebot)
+	current_x += strlen(filepart->top_data);
+
+    /* Get the number of lines and the number of characters in the saved
+     * text, and add the latter to totsize. */
+    get_totals(fileage, filebot, &part_totlines, &part_totsize);
+    totsize += part_totsize;
+
+    /* If the top of the partition was the top of the edit window, set
+     * edittop to where the saved text now starts, and update the
+     * current y-coordinate to account for the number of lines it
+     * has, less one since the first line will be tacked onto the
+     * current line. */
+    if (at_edittop)
+	edittop = fileage;
+    current_y += part_totlines - 1;
+
+    top_save = fileage;
+
+    /* Unpartition the filestruct so that it contains all the text
+     * again, minus the saved text. */
+    unpartition_filestruct(&filepart);
+
+    /* Renumber starting with the beginning line of the old
+     * partition. */
+    renumber(top_save);
+
+    if (filebot->data[0] != '\0')
+	new_magicline();
+
+    /* Set totlines to the new number of lines in the file. */
+    totlines = filebot->lineno;
+}
+
 void renumber_all(void)
 {
     filestruct *temp;
@@ -2342,39 +2510,69 @@ void do_para_end(void)
     edit_redraw(old_current, old_pww);
 }
 
-/* Put the next par_len lines, starting with first_line, in the
- * cutbuffer, not allowing them to be concatenated.  We assume there
- * are enough lines after first_line.  We leave copies of the lines in
- * place, too.  We return the new copy of first_line. */
+/* Put the next par_len lines, starting with first_line, into the
+ * justify buffer, leaving copies of those lines in place.  Assume there
+ * are enough lines after first_line.  Return the new copy of
+ * first_line. */
 filestruct *backup_lines(filestruct *first_line, size_t par_len, size_t
 	quote_len)
 {
-    /* We put the original lines, not copies, into the cutbuffer, just
-     * out of a misguided sense of consistency, so if you uncut, you get
-     * the actual same paragraph back, not a copy. */
-    filestruct *alice = first_line;
+    filestruct *top = first_line;
+	/* The top of the paragraph we're backing up. */
+    filestruct *bot = first_line;
+	/* The bottom of the paragraph we're backing up. */
+    size_t i;
+	/* Generic loop variable. */
+    size_t current_x_save = current_x;
+    int fl_lineno_save = first_line->lineno;
+    int edittop_lineno_save = edittop->lineno;
+    int current_lineno_save = current->lineno;
+#ifndef NANO_SMALL
+    bool old_mark_set = ISSET(MARK_ISSET);
+    int mbb_lineno_save = 0;
 
-    set_modified();
-    cutbuffer = NULL;
-    for (; par_len > 0; par_len--) {
-	filestruct *bob = copy_node(alice);
+    if (old_mark_set)
+	mbb_lineno_save = mark_beginbuf->lineno;
+#endif
+
+    /* Move bot down par_len lines to the newline after the last line of
+     * the paragraph. */
+    for (i = par_len; i > 0; i--)
+	bot = bot->next;
+
+    /* Move the paragraph from the main filestruct to the justify
+     * buffer. */
+    move_to_filestruct(&jusbuffer, &jusbottom, top, 0, bot, 0);
+
+    /* Copy the paragraph from the justify buffer to the main
+     * filestruct. */
+    copy_from_filestruct(jusbuffer, jusbottom);
 
-	if (alice == first_line)
-	    first_line = bob;
-	if (alice == current)
-	    current = bob;
-	if (alice == edittop)
-	    edittop = bob;
+    /* Move upward from the last line of the paragraph to the first
+     * line, putting first_line, edittop, current, and mark_beginbuf at
+     * the same lines in the copied paragraph that they had in the
+     * original paragraph. */
+    top = current->prev;
+    for (i = par_len; i > 0; i--) {
+	if (top->lineno == fl_lineno_save)
+	    first_line = top;
+	if (top->lineno == edittop_lineno_save)
+	    edittop = top;
+	if (top->lineno == current_lineno_save)
+	    current = top;
 #ifndef NANO_SMALL
-	if (alice == mark_beginbuf)
-	    mark_beginbuf = bob;
+	if (old_mark_set && top->lineno == mbb_lineno_save)
+	    mark_beginbuf = top;
 #endif
-
-	assert(alice != NULL && bob != NULL);
-	add_to_cutbuffer(alice, FALSE);
-	splice_node(bob->prev, bob, bob->next);
-	alice = bob->next;
+	top = top->prev;
     }
+
+    /* Put current_x at the same place in the copied paragraph that it
+     * had in the original paragraph. */
+    current_x = current_x_save;
+
+    set_modified();
+
     return first_line;
 }
 
@@ -2561,13 +2759,10 @@ void do_justify(bool full_justify)
 {
     filestruct *first_par_line = NULL;
 	/* Will be the first line of the resulting justified paragraph.
-	 * For restoring after uncut. */
+	 * For restoring after unjustify. */
     filestruct *last_par_line;
-	/* Will be the last line of the result, also for uncut. */
-    filestruct *cutbuffer_save = cutbuffer;
-	/* When the paragraph gets modified, all lines from the changed
-	 * one down are stored in the cutbuffer.  We back up the
-	 * original to restore it later. */
+	/* Will be the line containing the newline after the last line
+	 * of the result.  Also for restoring after unjustify. */
     bool allow_respacing;
 	/* Whether we should change the spacing at the end of a line
 	 * after justifying it.  This should be TRUE whenever we move
@@ -2611,10 +2806,7 @@ void do_justify(bool full_justify)
 	 * get out. */
 	if (do_para_search(&quote_len, &par_len)) {
 	    if (full_justify) {
-		/* This should be safe in the event of filebot->prev's
-		 * being NULL, since only last_par_line->next is used if
-		 * we eventually unjustify. */
-		last_par_line = filebot->prev;
+		last_par_line = filebot;
 		break;
 	    } else {
 		edit_refresh();
@@ -2641,7 +2833,7 @@ void do_justify(bool full_justify)
 		quote_len);
 
 	    /* If we haven't already done it, copy the original
-	     * paragraph to the cutbuffer for unjustification. */
+	     * paragraph to the justify buffer. */
 	    if (first_par_line == NULL)
 		first_par_line = backup_lines(current, full_justify ?
 			filebot->lineno - current->lineno : par_len,
@@ -2829,7 +3021,7 @@ void do_justify(bool full_justify)
      * fileage, and renumber() since edit_refresh() needs the line
      * numbers to be right (but only do the last two if we actually
      * justified something). */
-    last_par_line = current->prev;
+    last_par_line = current;
     if (first_par_line != NULL) {
 	if (first_par_line->prev == NULL)
 	    fileage = first_par_line;
@@ -2846,53 +3038,65 @@ void do_justify(bool full_justify)
 
     /* Now get a keystroke and see if it's unjustify; if not, unget the
      * keystroke and return. */
-    kbinput = get_edit_input(&meta_key, &func_key, FALSE);
+    kbinput = get_edit_input(&meta_key, &func_key);
 
     if (!meta_key && !func_key && kbinput == NANO_UNJUSTIFY_KEY) {
 	/* Restore the justify we just did (ungrateful user!). */
-	filestruct *cutbottom = get_cutbottom();
-
 	current = current_save;
 	current_x = current_x_save;
 	current_y = current_y_save;
 	edittop = edittop_save;
 
-	/* Splice the cutbuffer back into the file, but only if we
+	/* Splice the justify buffer back into the file, but only if we
 	 * actually justified something. */
 	if (first_par_line != NULL) {
-	    cutbottom->next = last_par_line->next;
-	    cutbottom->next->prev = cutbottom;
-	    /* The line numbers after the end of the paragraph have been
-	     * changed, so we change them back. */
-	    renumber(cutbottom->next);
-	    if (first_par_line->prev != NULL) {
-		cutbuffer->prev = first_par_line->prev;
-		cutbuffer->prev->next = cutbuffer;
-	    } else
-		fileage = cutbuffer;
+	    filestruct *bot_save;
 
-	    last_par_line->next = NULL;
-	    free_filestruct(first_par_line);
-	}
+	    /* Partition the filestruct so that it contains only the
+	     * text of the justified paragraph. */
+	    filepart = partition_filestruct(first_par_line, 0,
+		last_par_line, 0);
 
-	/* Restore global variables from before the justify. */
-	totsize = totsize_save;
-	totlines = filebot->lineno;
+	    /* Remove the text of the justified paragraph, and
+	     * put the text in the justify buffer in its place. */
+	    free_filestruct(fileage);
+	    fileage = jusbuffer;
+	    filebot = jusbottom;
+
+	    bot_save = filebot;
+
+	    /* Unpartition the filestruct so that it contains all the
+	     * text again.  Note that the justified paragraph has been
+	     * replaced with the unjustified paragraph. */
+	    unpartition_filestruct(&filepart);
+
+	     /* Renumber starting with the ending line of the old
+	      * partition. */
+	    if (bot_save->next != NULL)
+		renumber(bot_save->next);
+
+	    /* Restore global variables from before the justify. */
+	    totsize = totsize_save;
+	    totlines = filebot->lineno;
 #ifndef NANO_SMALL
-	mark_beginbuf = mark_beginbuf_save;
-	mark_beginx = mark_beginx_save;
+	    mark_beginbuf = mark_beginbuf_save;
+	    mark_beginx = mark_beginx_save;
 #endif
-	flags = flags_save;
-	if (!ISSET(MODIFIED))
-	    titlebar(NULL);
-	edit_refresh();
+	    flags = flags_save;
+
+	    /* Clear the justify buffer. */
+	    jusbuffer = NULL;
+
+	    if (!ISSET(MODIFIED))
+		titlebar(NULL);
+	    edit_refresh();
+	}
     } else {
-	placewewant = 0;
-	unget_kbinput(kbinput, meta_key, func_key);
+	/* Blow away the justify buffer.*/
+	free_filestruct(jusbuffer);
+	jusbuffer = NULL;
     }
 
-    cutbuffer = cutbuffer_save;
-    /* Note that now cutbottom is invalid, but that's okay. */
     blank_statusbar();
 
     /* Display the shortcut list with UnCut. */
@@ -3060,6 +3264,16 @@ void handle_sigwinch(int s)
     if (filepart != NULL)
 	unpartition_filestruct(&filepart);
 
+#ifndef DISABLE_JUSTIFY
+    /* If the justify buffer isn't empty, blow it away and display the
+     * shortcut list with UnCut. */
+    if (jusbuffer != NULL) {
+	free_filestruct(jusbuffer);
+	jusbuffer = NULL;
+	shortcut_init(FALSE);
+    }
+#endif
+
 #ifdef USE_SLANG
     /* Slang curses emulation brain damage, part 1: If we just do what
      * curses does here, it'll only work properly if the resize made the
@@ -3741,7 +3955,7 @@ int main(int argc, char **argv)
 	currshortcut = main_list;
 #endif
 
-	kbinput = get_edit_input(&meta_key, &func_key, TRUE);
+	kbinput = get_edit_input(&meta_key, &func_key);
 
 	/* Last gasp, stuff that's not in the main lists. */
 	if (kbinput != ERR && !is_cntrl_char(kbinput)) {
diff --git a/src/nano.h b/src/nano.h
index d2d55e18d35abff4843cb6e8508b6e9ce0386395..7e79053b5bf1fb1e5064b177ed19018afa78c7bc 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -145,10 +145,6 @@
 #endif
 
 /* Enumeration types. */
-typedef enum {
-    CUT_LINE, CUT_MARKED, CUT_TO_EOL
-} cut_type;
-
 typedef enum {
     NIX_FILE, DOS_FILE, MAC_FILE
 } file_format;
diff --git a/src/proto.h b/src/proto.h
index 094af605711311222514fa437ea5da7b752667db..4065da18581fccf89167560a5ba3bf902fc63c27 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -86,6 +86,9 @@ extern char *alt_speller;
 extern struct stat fileinfo;
 extern filestruct *current, *fileage, *edittop, *filebot;
 extern filestruct *cutbuffer;
+#ifndef DISABLE_JUSTIFY
+extern filestruct *jusbuffer;
+#endif
 extern partition *filepart;
 #ifndef NANO_SMALL
 extern filestruct *mark_beginbuf;
@@ -158,11 +161,11 @@ void update_color(void);
 
 /* Public functions in cut.c. */
 void cutbuffer_reset(void);
-filestruct *get_cutbottom(void);
-void add_to_cutbuffer(filestruct *inptr, bool allow_concat);
+void cut_line(void);
 #ifndef NANO_SMALL
-void cut_marked_segment(void);
+void cut_marked(void);
 #endif
+void cut_to_eol(void);
 void do_cut_text(void);
 void do_uncut_text(void);
 
@@ -308,6 +311,9 @@ void free_filestruct(filestruct *src);
 partition *partition_filestruct(filestruct *top, size_t top_x,
 	filestruct *bot, size_t bot_x);
 void unpartition_filestruct(partition **p);
+void move_to_filestruct(filestruct **file_top, filestruct **file_bot,
+	filestruct *top, size_t top_x, filestruct *bot, size_t bot_x);
+void copy_from_filestruct(filestruct *file_top, filestruct *file_bot);
 void renumber_all(void);
 void renumber(filestruct *fileptr);
 void print1opt(const char *shortflag, const char *longflag, const char
@@ -504,11 +510,11 @@ char *mallocstrassn(char *dest, char *src);
 void new_magicline(void);
 #ifndef NANO_SMALL
 void remove_magicline(void);
-void get_totals(const filestruct *begin, const filestruct *end, int
-	*lines, long *size);
 void mark_order(const filestruct **top, size_t *top_x, const filestruct
 	**bot, size_t *bot_x, bool *right_side_up);
 #endif
+void get_totals(const filestruct *begin, const filestruct *end, int
+	*lines, long *size);
 #ifndef DISABLE_TABCOMP
 int check_wildcard_match(const char *text, const char *pattern);
 #endif
@@ -549,7 +555,7 @@ const shortcut *get_shortcut(const shortcut *s_list, int kbinput, bool
 #ifndef NANO_SMALL
 const toggle *get_toggle(int kbinput, bool meta_key);
 #endif
-int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs);
+int get_edit_input(bool *meta_key, bool *func_key);
 #ifndef DISABLE_MOUSE
 bool get_edit_mouse(void);
 #endif
diff --git a/src/utils.c b/src/utils.c
index 463bce99b62a7921b4282278f87af20a0d71175a..7ee72f1bb56954aaf42250a2cda46d6b835320ab 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -456,6 +456,35 @@ void remove_magicline(void)
     }
 }
 
+/* Set top_x and bot_x to the top and bottom x-coordinates of the mark,
+ * respectively, based on the locations of top and bot.  If
+ * right_side_up isn't NULL, set it to TRUE If the mark begins with
+ * (mark_beginbuf, mark_beginx) and ends with (current, current_x), or
+ * FALSE otherwise. */
+void mark_order(const filestruct **top, size_t *top_x, const filestruct
+	**bot, size_t *bot_x, bool *right_side_up)
+{
+    assert(top != NULL && top_x != NULL && bot != NULL && bot_x != NULL);
+
+    if ((current->lineno == mark_beginbuf->lineno && current_x >
+	 mark_beginx) || current->lineno > mark_beginbuf->lineno) {
+	*top = mark_beginbuf;
+	*top_x = mark_beginx;
+	*bot = current;
+	*bot_x = current_x;
+	if (right_side_up != NULL)
+	    *right_side_up = TRUE;
+    } else {
+	*bot = mark_beginbuf;
+	*bot_x = mark_beginx;
+	*top = current;
+	*top_x = current_x;
+	if (right_side_up != NULL)
+	    *right_side_up = FALSE;
+    }
+}
+#endif
+
 /* Calculate the number of lines and the number of characters between
  * begin and end, and return them in lines and size, respectively. */
 void get_totals(const filestruct *begin, const filestruct *end, int
@@ -501,35 +530,6 @@ void get_totals(const filestruct *begin, const filestruct *end, int
     }
 }
 
-/* Set top_x and bot_x to the top and bottom x-coordinates of the mark,
- * respectively, based on the locations of top and bot.  If
- * right_side_up isn't NULL, set it to TRUE If the mark begins with
- * (mark_beginbuf, mark_beginx) and ends with (current, current_x), or
- * FALSE otherwise. */
-void mark_order(const filestruct **top, size_t *top_x, const filestruct
-	**bot, size_t *bot_x, bool *right_side_up)
-{
-    assert(top != NULL && top_x != NULL && bot != NULL && bot_x != NULL);
-
-    if ((current->lineno == mark_beginbuf->lineno && current_x >
-	 mark_beginx) || current->lineno > mark_beginbuf->lineno) {
-	*top = mark_beginbuf;
-	*top_x = mark_beginx;
-	*bot = current;
-	*bot_x = current_x;
-	if (right_side_up != NULL)
-	    *right_side_up = TRUE;
-    } else {
-	*bot = mark_beginbuf;
-	*bot_x = mark_beginx;
-	*top = current;
-	*top_x = current_x;
-	if (right_side_up != NULL)
-	    *right_side_up = FALSE;
-    }
-}
-#endif
-
 #ifndef DISABLE_TABCOMP
 /*
  * Routine to see if a text string is matched by a wildcard pattern.
diff --git a/src/winio.c b/src/winio.c
index 7c8be1445e8e7eae102a541449dc943d2d02ee79..47b636f6b002c419f8cc66504e9e5b4b4de92eed 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -1491,7 +1491,7 @@ const toggle *get_toggle(int kbinput, bool meta_key)
 }
 #endif /* !NANO_SMALL */
 
-int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs)
+int get_edit_input(bool *meta_key, bool *func_key)
 {
     bool keyhandled = FALSE;
     int kbinput, retval;
@@ -1536,12 +1536,10 @@ int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs)
 	if (s->func != do_cut_text)
 	    cutbuffer_reset();
 	if (s->func != NULL) {
-	    if (allow_funcs) {
-		if (ISSET(VIEW_MODE) && !s->viewok)
-		    print_view_warning();
-		else
-		    s->func();
-	    }
+	    if (ISSET(VIEW_MODE) && !s->viewok)
+		print_view_warning();
+	    else
+		s->func();
 	    keyhandled = TRUE;
 	}
     }
@@ -1555,8 +1553,7 @@ int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs)
 	 * corresponding flag. */
 	if (t != NULL) {
 	    cutbuffer_reset();
-	    if (allow_funcs)
-		do_toggle(t);
+	    do_toggle(t);
 	    keyhandled = TRUE;
 	}
     }
@@ -1565,7 +1562,7 @@ int get_edit_input(bool *meta_key, bool *func_key, bool allow_funcs)
     /* If we got a shortcut with a corresponding function or a toggle,
      * reset meta_key and retval.  If we didn't, keep the value of
      * meta_key and return the key we got in retval. */
-    if (allow_funcs && keyhandled) {
+    if (keyhandled) {
 	*meta_key = FALSE;
 	retval = ERR;
     } else {