goto_line_posx(u->mark_begin_lineno, u->mark_begin_x);
break;
#ifndef DISABLE_WRAPPING
- case SPLIT:
+ case SPLIT_END:
undidmsg = _("line wrap");
- f->data = charealloc(f->data, strlen(f->data) + strlen(u->strdata) + 1);
- strcpy(&f->data[strlen(f->data) - 1], u->strdata);
- if (u->strdata2 != NULL)
- f->next->data = mallocstrcpy(f->next->data, u->strdata2);
- else {
- filestruct *foo = openfile->current->next;
- unlink_node(foo);
- delete_node(foo);
- }
- renumber(f);
- gotolinecolumn = TRUE;
+ goto_line_posx(u->lineno, u->begin);
+ openfile->current_undo = openfile->current_undo->next;
+ openfile->last_action = OTHER;
+ while (openfile->current_undo->type != SPLIT_BEGIN)
+ do_undo();
+ u = openfile->current_undo;
+ f = openfile->current;
break;
#endif /* !DISABLE_WRAPPING */
case UNSPLIT:
do_enter(TRUE);
break;
#ifndef DISABLE_WRAPPING
- case SPLIT:
+ case SPLIT_BEGIN:
undidmsg = _("line wrap");
- if (u->xflags & UNsplit_madenew)
- prepend_wrap = TRUE;
- do_wrap(f, TRUE);
- renumber(f);
- gotolinecolumn = TRUE;
+ goto_line_posx(u->lineno, u->begin);
+ openfile->current_undo = u;
+ openfile->last_action = OTHER;
+ while (openfile->current_undo->type != SPLIT_END)
+ do_redo();
+ u = openfile->current_undo;
+ goto_line_posx(u->lineno, u->begin);
break;
#endif /* !DISABLE_WRAPPING */
case UNSPLIT:
char *data;
openfilestruct *fs = openfile;
/* Last thing we cut to set up the undo for uncut. */
- ssize_t wrap_loc;
- /* For calculating split beginning. */
if (!ISSET(UNDOABLE))
return;
u->type = current_action;
u->lineno = fs->current->lineno;
u->begin = fs->current_x;
- u->next = fs->undotop;
- fs->undotop = u;
- fs->current_undo = u;
+ if (u->type == SPLIT_BEGIN) {
+ /* Some action, most likely an ADD, was performed that invoked
+ * do_wrap(). Rearrange the undo order so that this previous
+ * action is after the SPLIT_BEGIN undo. */
+ u->next = fs->undotop->next ;
+ fs->undotop->next = u;
+ } else {
+ u->next = fs->undotop;
+ fs->undotop = u;
+ fs->current_undo = u;
+ }
u->strdata = NULL;
u->strdata2 = NULL;
u->cutbuffer = NULL;
current_action = u->type = UNSPLIT;
break;
#ifndef DISABLE_WRAPPING
- case SPLIT:
- wrap_loc = break_line(openfile->current->data, fill
-#ifndef DISABLE_HELP
- , FALSE
-#endif
- );
- u->strdata = mallocstrcpy(NULL, &openfile->current->data[wrap_loc]);
- /* Don't bother saving the next line if we're not prepending,
- * as a new line will be created. */
- if (prepend_wrap)
- u->strdata2 = mallocstrcpy(NULL, fs->current->next->data);
- u->begin = wrap_loc;
+ case SPLIT_BEGIN:
+ current_action = fs->undotop->type;
+ break;
+ case SPLIT_END:
break;
#endif /* !DISABLE_WRAPPING */
case INSERT:
/* Change to an add if we're not using the same undo struct
* that we should be using. */
if (action != fs->last_action
- || (action != ENTER && action != CUT && action != INSERT && action != SPLIT
+ || (action != ENTER && action != CUT && action != INSERT
&& openfile->current->lineno != fs->current_undo->lineno)) {
add_undo(action);
return;
u->mark_begin_x = fs->current_x;
break;
#ifndef DISABLE_WRAPPING
- case SPLIT:
- /* This will only be called if we made a completely new line,
- * and as such we should note that so we can destroy it later. */
- u->xflags = UNsplit_madenew;
+ case SPLIT_BEGIN:
+ case SPLIT_END:
break;
#endif /* !DISABLE_WRAPPING */
case UNSPLIT:
prepend_wrap = FALSE;
}
-/* We wrap the given line. Precondition: we assume the cursor has been
- * moved forward since the last typed character. Return TRUE if we
- * wrapped, and FALSE otherwise. */
-bool do_wrap(filestruct *line, bool undoing)
+/* Try wrapping the given line. Return TRUE if wrapped, FALSE otherwise. */
+bool do_wrap(filestruct *line)
{
size_t line_len;
/* The length of the line we wrap. */
/* The text after the wrap point. */
size_t after_break_len;
/* The length of after_break. */
- bool prepending = FALSE;
- /* Do we prepend to the next line? */
const char *next_line = NULL;
/* The next line, minus indentation. */
size_t next_line_len = 0;
/* The length of next_line. */
- char *new_line = NULL;
- /* The line we create. */
- size_t new_line_len = 0;
- /* The eventual length of new_line. */
/* There are three steps. First, we decide where to wrap. Then, we
* create the new wrap line. Finally, we clean up. */
return FALSE;
#ifndef NANO_TINY
- if (!undoing)
- add_undo(SPLIT);
-
/* If autoindent is turned on, and we're on the character just after
* the indentation, we don't wrap. */
if (ISSET(AUTOINDENT)) {
if (wrap_loc == indent_len)
return FALSE;
}
+
+ add_undo(SPLIT_BEGIN);
#endif
+ size_t old_x = openfile->current_x;
+ filestruct * oldLine = openfile->current;
+ openfile->current = line;
+
/* Step 2, making the new wrap line. It will consist of indentation
* followed by the text after the wrap point, optionally followed by
* a space (if the text after the wrap point doesn't end in a blank)
const char *end = after_break + move_mbleft(after_break,
after_break_len);
+ /* Go to the end of the line. */
+ openfile->current_x = line_len;
+
/* If after_break doesn't end in a blank, make sure it ends in a
* space. */
if (!is_blank_mbchar(end)) {
+ add_undo(ADD);
line_len++;
line->data = charealloc(line->data, line_len + 1);
line->data[line_len - 1] = ' ';
after_break = line->data + wrap_loc;
after_break_len++;
openfile->totsize++;
+ openfile->current_x++;
+ update_undo(ADD);
}
next_line = line->next->data;
next_line_len = strlen(next_line);
if (after_break_len + next_line_len <= fill) {
- prepending = TRUE;
- new_line_len += next_line_len;
+ /* Delete the LF to join the two lines. */
+ do_delete();
+ /* Delete any leading blanks from the joined-on line. */
+ while (is_blank_mbchar(&line->data[openfile->current_x]))
+ do_delete();
+ renumber(line);
}
}
- /* new_line_len is now the length of the text that will be wrapped
- * to the next line, plus (if we're prepending to it) the length of
- * the text of the next line. */
- new_line_len += after_break_len;
-
-#ifndef NANO_TINY
- if (ISSET(AUTOINDENT)) {
- if (prepending) {
- /* If we're prepending, the indentation will come from the
- * next line. */
- indent_string = next_line;
- indent_len = indent_length(indent_string);
- next_line += indent_len;
- } else {
- /* Otherwise, it will come from this line, in which case
- * we should increase new_line_len to make room for it. */
- new_line_len += indent_len;
- openfile->totsize += mbstrnlen(indent_string, indent_len);
- }
- }
-#endif
-
- /* Now we allocate the new line and copy the text into it. */
- new_line = charalloc(new_line_len + 1);
- new_line[0] = '\0';
-
-#ifndef NANO_TINY
- if (ISSET(AUTOINDENT)) {
- /* Copy the indentation. */
- strncpy(new_line, indent_string, indent_len);
- new_line[indent_len] = '\0';
- new_line_len += indent_len;
- }
-#endif
-
- /* Copy all the text after the wrap point of the current line. */
- strcat(new_line, after_break);
-
- /* Break the current line at the wrap point. */
- null_at(&line->data, wrap_loc);
-
- if (prepending) {
-#ifndef NANO_TINY
- if (!undoing)
- update_undo(SPLIT);
-#endif
- /* If we're prepending, copy the text from the next line, minus
- * the indentation that we already copied above. */
- strcat(new_line, next_line);
-
- free(line->next->data);
- line->next->data = new_line;
+ /* Go to the wrap location and split the line there. */
+ openfile->current_x = wrap_loc;
+ do_enter(FALSE);
- /* If the NO_NEWLINES flag isn't set, and text has been added to
- * the magicline, make a new magicline. */
- if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
- new_magicline();
+ if (old_x < wrap_loc) {
+ openfile->current_x = old_x;
+ openfile->current = oldLine;
+ prepend_wrap = TRUE;
} else {
- /* Otherwise, make a new line and copy the text after where we
- * broke this line to the beginning of the new line. */
- splice_node(openfile->current, make_new_node(openfile->current),
- openfile->current->next);
-
- /* If the current line is the last line of the file, move the
- * last line of the file down to the next line. */
- if (openfile->filebot == openfile->current)
- openfile->filebot = openfile->current->next;
-
- openfile->current->next->data = new_line;
-
- openfile->totsize++;
- }
-
- /* Step 3, clean up. Reposition the cursor and mark, and do some
- * other sundry things. */
-
- /* Set the prepend_wrap flag, so that later wraps of this line will
- * be prepended to the next line. */
- prepend_wrap = TRUE;
-
- /* Each line knows its number. We recalculate these if we inserted
- * a new line. */
- if (!prepending)
- renumber(line);
-
- /* If the cursor was after the break point, we must move it. We
- * also clear the prepend_wrap flag in this case. */
- if (openfile->current_x > wrap_loc) {
+ openfile->current_x += (old_x - wrap_loc);
prepend_wrap = FALSE;
-
- openfile->current = openfile->current->next;
- openfile->current_x -= wrap_loc
-#ifndef NANO_TINY
- - indent_len
-#endif
- ;
- openfile->placewewant = xplustabs();
}
+ openfile->placewewant = xplustabs();
+
#ifndef NANO_TINY
- /* If the mark was on this line after the wrap point, we move it
- * down. If it was on the next line and we prepended to that line,
- * we move it right. */
- if (openfile->mark_set) {
- if (openfile->mark_begin == line && openfile->mark_begin_x >
- wrap_loc) {
- openfile->mark_begin = line->next;
- openfile->mark_begin_x -= wrap_loc - indent_len + 1;
- } else if (prepending && openfile->mark_begin == line->next)
- openfile->mark_begin_x += after_break_len;
- }
+ add_undo(SPLIT_END);
#endif
return TRUE;