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:
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. */
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(¤t->data[current_x]) + 1);
- strcpy(tmpstr2, newend->data);
- strcat(tmpstr2, ¤t->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(¤t->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();
}
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 */
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);
* 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)
{
*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;
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;
}
{
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
* get out. */
if (do_para_search("e_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();
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,
* 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;
/* 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. */
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
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)) {
#endif
/* Enumeration types. */
-typedef enum {
- CUT_LINE, CUT_MARKED, CUT_TO_EOL
-} cut_type;
-
typedef enum {
NIX_FILE, DOS_FILE, MAC_FILE
} file_format;
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;
/* 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);
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
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
#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
}
}
+/* 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
}
}
-/* 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.
}
#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;
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;
}
}
* corresponding flag. */
if (t != NULL) {
cutbuffer_reset();
- if (allow_funcs)
- do_toggle(t);
+ do_toggle(t);
keyhandled = TRUE;
}
}
/* 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 {