Index: src/chars.c =================================================================== --- src/chars.c (revision 4906) +++ src/chars.c (working copy) @@ -43,6 +43,17 @@ static const char *const bad_mbchar = "\xEF\xBF\xBD"; static const int bad_mbchar_len = 3; +/*add two allocated strings*/ +char* addstrings(char* str1, size_t len1, char* str2, size_t len2) +{ + size_t len = len1 + len2 + 1; + str1 = charealloc(str1, len); + str1[len1] = '\0'; + strncat(&str1[len1], str2, len2); + free(str2); + return str1; +} + /* Enable UTF-8 support. */ void utf8_init(void) { Index: src/cut.c =================================================================== --- src/cut.c (revision 4906) +++ src/cut.c (working copy) @@ -274,6 +274,10 @@ * at the current cursor position. */ copy_from_filestruct(cutbuffer); +#ifndef NANO_TINY + update_undo(PASTE); +#endif + /* Set the current place we want to where the text from the * cutbuffer ends. */ openfile->placewewant = xplustabs(); Index: src/nano.h =================================================================== --- src/nano.h (revision 4906) +++ src/nano.h (working copy) @@ -187,7 +187,7 @@ } function_type; typedef enum { - ADD, DEL, REPLACE, SPLIT, UNSPLIT, CUT, CUT_EOF, PASTE, ENTER, INSERT, OTHER + ADD, DEL, REPLACE, UNSPLIT, CUT, CUT_EOF, PASTE, ENTER, INSERT, OTHER } undo_type; typedef struct color_pair { @@ -572,6 +572,7 @@ #define UNdel_del (1<<0) #define UNdel_backspace (1<<1) #define UNsplit_madenew (1<<2) +#define UNcut_cutline (1<<3) #endif /* !NANO_TINY */ #define VIEW TRUE Index: src/proto.h =================================================================== --- src/proto.h (revision 4906) +++ src/proto.h (working copy) @@ -162,6 +162,7 @@ void utf8_init(void); bool using_utf8(void); #endif +char *addstrings(char* str1, size_t len1, char* str2, size_t len2); #ifndef HAVE_ISBLANK bool nisblank(int c); #endif Index: src/text.c =================================================================== --- src/text.c (revision 4906) +++ src/text.c (working copy) @@ -374,12 +374,17 @@ for (cutbottom = cutbuffer; cutbottom->next != NULL; cutbottom = cutbottom->next) ; + size_t posx = (u->xflags == UNcut_cutline)?0:u->mark_begin_x; + /* Get to where we need to uncut from. */ - goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); + goto_line_posx(u->mark_begin_lineno, posx); copy_from_filestruct(cutbuffer); free_filestruct(cutbuffer); cutbuffer = NULL; + + if(u->xflags == UNcut_cutline) + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x); } /* Redo a cut, or undo an uncut. */ @@ -406,7 +411,7 @@ if (!ISSET(CUT_TO_END)) openfile->mark_set = TRUE; - openfile->mark_begin_x = u->mark_begin_x; + openfile->mark_begin_x = (u->xflags == UNcut_cutline)?0:u->mark_begin_x; do_cut_text(FALSE, u->to_end, TRUE); openfile->mark_set = FALSE; openfile->mark_begin = NULL; @@ -417,7 +422,6 @@ /* Undo the last thing(s) we did. */ void do_undo(void) { - bool gotolinecolumn = FALSE; undo *u = openfile->current_undo; filestruct *t = 0; size_t len = 0; @@ -460,26 +464,8 @@ strcpy(&data[u->begin + strlen(u->strdata)], &f->data[u->begin]); free(f->data); f->data = data; - if (u->xflags == UNdel_backspace) - openfile->current_x += strlen(u->strdata); - goto_line_posx(u->mark_begin_lineno, u->mark_begin_x + 1); + goto_line_posx(u->mark_begin_lineno, u->mark_begin_x ); break; -#ifndef DISABLE_WRAPPING - case SPLIT: - undidmsg = _("line wrap"); - f->data = (char *) nrealloc(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; - break; -#endif /* !DISABLE_WRAPPING */ case UNSPLIT: undidmsg = _("line join"); t = make_new_node(f); @@ -489,7 +475,7 @@ free(f->data); f->data = data; splice_node(f, t, f->next); - gotolinecolumn = TRUE; + goto_line_posx(u->lineno, u->begin); break; case CUT_EOF: case CUT: @@ -504,8 +490,8 @@ undidmsg = _("line break"); if (f->next) { filestruct *foo = f->next; - f->data = (char *) nrealloc(f->data, strlen(f->data) + strlen(f->next->data) + 1); - strcat(f->data, f->next->data); + f->data = (char *) nrealloc(f->data, strlen(f->data) + strlen(&f->next->data[u->mark_begin_x]) + 1); + strcat(f->data, &f->next->data[u->mark_begin_x]); unlink_node(foo); delete_node(foo); } @@ -542,8 +528,6 @@ } renumber(f); - if (gotolinecolumn) - do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE); statusbar(_("Undid action (%s)"), undidmsg); openfile->current_undo = openfile->current_undo->next; openfile->last_action = OTHER; @@ -553,7 +537,6 @@ /* Redo the last thing(s) we undid. */ void do_redo(void) { - bool gotolinecolumn = FALSE; undo *u = openfile->undotop; size_t len = 0; char *undidmsg, *data; @@ -608,16 +591,6 @@ goto_line_posx(u->lineno, u->begin); do_enter(TRUE); break; -#ifndef DISABLE_WRAPPING - case SPLIT: - undidmsg = _("line wrap"); - if (u->xflags & UNsplit_madenew) - prepend_wrap = TRUE; - do_wrap(f, TRUE); - renumber(f); - gotolinecolumn = TRUE; - break; -#endif /* !DISABLE_WRAPPING */ case UNSPLIT: undidmsg = _("line join"); len = strlen(f->data) + strlen(u->strdata) + 1; @@ -629,7 +602,7 @@ delete_node(tmp); } renumber(f); - gotolinecolumn = TRUE; + goto_line_posx(u->lineno, u->begin); break; case CUT_EOF: case CUT: @@ -657,8 +630,6 @@ break; } - if (gotolinecolumn) - do_gotolinecolumn(u->lineno, u->begin, FALSE, FALSE, FALSE, TRUE); statusbar(_("Redid action (%s)"), undidmsg); openfile->current_undo = u; @@ -723,6 +694,11 @@ openfile->placewewant = xplustabs(); +#ifndef NANO_TINY + if (!undoing) + update_undo(ENTER); +#endif + edit_refresh_needed = TRUE; } @@ -832,8 +808,6 @@ 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; @@ -879,15 +853,14 @@ /* We need to start copying data into the undo buffer * or we won't be able to restore it later. */ case ADD: - data = charalloc(2); - data[0] = '\0'; - u->strdata = data; break; case DEL: if (u->begin != strlen(fs->current->data)) { - data = mallocstrncpy(NULL, &fs->current->data[u->begin], 2); - data[1] = '\0'; - u->strdata = data; + char *char_buf = charalloc(mb_cur_max()+1); + int char_buf_len = parse_mbchar(&fs->current->data[u->begin], char_buf, NULL); + char_buf[char_buf_len] = '\0'; + u->strdata = char_buf;//Note: there is likely more memory allocated than necessary + u->mark_begin_x += char_buf_len; break; } /* Else purposely fall into unsplit code. */ @@ -898,21 +871,6 @@ u->strdata = data; } 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; - break; -#endif /* !DISABLE_WRAPPING */ case INSERT: case REPLACE: data = mallocstrcpy(NULL, fs->current->data); @@ -929,7 +887,7 @@ else if (!ISSET(CUT_TO_END) && !u->to_end) { /* The entire line is being cut regardless of the cursor position. */ u->begin = 0; - u->mark_begin_x = 0; + u->xflags = UNcut_cutline; } break; case PASTE: @@ -942,18 +900,6 @@ u->mark_begin_lineno = fs->current->lineno; u->mark_begin_x = fs->current_x; u->lineno = fs->current->lineno + cutbottom->lineno - cutbuffer->lineno; - - filestruct *fs_buff = cutbuffer; - if (fs_buff->lineno == cutbottom->lineno) - u->begin = fs->current_x + get_totsize(fs_buff, cutbottom); - else { - /* Advance fs_buff to the last line in the cutbuffer. */ - while (fs_buff->lineno != cutbottom->lineno && fs_buff->next != NULL) - fs_buff = fs_buff->next; - assert(fs_buff->next != NULL); - u->begin = get_totsize(fs_buff, cutbottom); - } - u->mark_set = TRUE; } break; @@ -979,8 +925,6 @@ void update_undo(undo_type action) { undo *u; - char *data; - int len = 0; openfilestruct *fs = openfile; if (!ISSET(UNDOABLE)) @@ -998,7 +942,7 @@ /* 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 != INSERT && action != SPLIT + || (action != ENTER && action != CUT && action != INSERT && openfile->current->lineno != fs->current_undo->lineno)) { add_undo(action); return; @@ -1008,61 +952,42 @@ u = fs->undotop; switch (u->type) { - case ADD: + case ADD:{ #ifdef DEBUG fprintf(stderr, "fs->current->data = \"%s\", current_x = %lu, u->begin = %d\n", fs->current->data, (unsigned long) fs->current_x, u->begin); #endif - len = strlen(u->strdata) + 2; - data = (char *) nrealloc((void *) u->strdata, len * sizeof(char *)); - data[len-2] = fs->current->data[fs->current_x - 1]; - data[len-1] = '\0'; - u->strdata = (char *) data; + char *char_buf = charalloc(mb_cur_max()); + size_t char_buf_len = parse_mbchar( &fs->current->data[u->mark_begin_x], char_buf, NULL); + u->strdata = addstrings(u->strdata, u->strdata?strlen(u->strdata):0, char_buf, char_buf_len); #ifdef DEBUG fprintf(stderr, "current undo data now \"%s\"\n", u->strdata); #endif u->mark_begin_lineno = fs->current->lineno; u->mark_begin_x = fs->current_x; + } break; - case DEL: - len = strlen(u->strdata) + 2; - assert(len > 2); + case DEL:{ + char *char_buf = charalloc(mb_cur_max()); + size_t char_buf_len = parse_mbchar( &fs->current->data[fs->current_x], char_buf, NULL); if (fs->current_x == u->begin) { /* They're deleting. */ - if (!u->xflags) - u->xflags = UNdel_del; - else if (u->xflags != UNdel_del) { - add_undo(action); - return; - } - data = charalloc(len); - strcpy(data, u->strdata); - data[len-2] = fs->current->data[fs->current_x]; - data[len-1] = '\0'; - free(u->strdata); - u->strdata = data; - } else if (fs->current_x == u->begin - 1) { + u->strdata = addstrings(u->strdata, strlen(u->strdata), char_buf, char_buf_len); + u->mark_begin_x = fs->current_x; + } else if (fs->current_x == u->begin - char_buf_len){ /* They're backspacing. */ - if (!u->xflags) - u->xflags = UNdel_backspace; - else if (u->xflags != UNdel_backspace) { - add_undo(action); - return; - } - data = charalloc(len); - data[0] = fs->current->data[fs->current_x]; - strcpy(&data[1], u->strdata); - free(u->strdata); - u->strdata = data; - u->begin--; + u->strdata = addstrings(char_buf, char_buf_len, u->strdata, strlen(u->strdata) ); + u->begin = fs->current_x; } else { /* They deleted something else on the line. */ + free(char_buf); add_undo(DEL); return; } #ifdef DEBUG fprintf(stderr, "current undo data now \"%s\"\nu->begin = %d\n", u->strdata, u->begin); #endif + } break; case CUT_EOF: case CUT: @@ -1095,21 +1020,17 @@ break; case REPLACE: case PASTE: - add_undo(action); + u->begin = fs->current_x; + u->lineno = openfile->current->lineno; break; case INSERT: u->mark_begin_lineno = openfile->current->lineno; 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 ENTER: + u->mark_begin_x = fs->current_x; break; -#endif /* !DISABLE_WRAPPING */ case UNSPLIT: /* These cases are handled by the earlier check for a new line and action. */ - case ENTER: case OTHER: break; } @@ -1198,9 +1119,6 @@ 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)) { @@ -1295,10 +1213,6 @@ 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);