Mercurial > vim
comparison src/undo.c @ 15361:58b125df3e9b v8.1.0688
patch 8.1.0688: text properties are not restored by undo
commit https://github.com/vim/vim/commit/ccae4672fd622f2feac8322be71b6e43e68dc4fc
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Jan 4 15:09:57 2019 +0100
patch 8.1.0688: text properties are not restored by undo
Problem: Text properties are not restored by undo.
Solution: Also save text properties for undo.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 04 Jan 2019 15:15:06 +0100 |
parents | 27b9a84395b5 |
children | 00aa76a735e7 |
comparison
equal
deleted
inserted
replaced
15360:4a4212c844d6 | 15361:58b125df3e9b |
---|---|
123 static void serialize_visualinfo(bufinfo_T *bi, visualinfo_T *info); | 123 static void serialize_visualinfo(bufinfo_T *bi, visualinfo_T *info); |
124 static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info); | 124 static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info); |
125 #endif | 125 #endif |
126 | 126 |
127 #define U_ALLOC_LINE(size) lalloc((long_u)(size), FALSE) | 127 #define U_ALLOC_LINE(size) lalloc((long_u)(size), FALSE) |
128 static char_u *u_save_line(linenr_T); | |
129 | 128 |
130 /* used in undo_end() to report number of added and deleted lines */ | 129 /* used in undo_end() to report number of added and deleted lines */ |
131 static long u_newcount, u_oldcount; | 130 static long u_newcount, u_oldcount; |
132 | 131 |
133 /* | 132 /* |
348 get_undolevel(void) | 347 get_undolevel(void) |
349 { | 348 { |
350 if (curbuf->b_p_ul == NO_LOCAL_UNDOLEVEL) | 349 if (curbuf->b_p_ul == NO_LOCAL_UNDOLEVEL) |
351 return p_ul; | 350 return p_ul; |
352 return curbuf->b_p_ul; | 351 return curbuf->b_p_ul; |
352 } | |
353 | |
354 /* | |
355 * u_save_line(): save an allocated copy of line "lnum" into "ul". | |
356 * Returns FAIL when out of memory. | |
357 */ | |
358 static int | |
359 u_save_line(undoline_T *ul, linenr_T lnum) | |
360 { | |
361 char_u *line = ml_get(lnum); | |
362 | |
363 if (curbuf->b_ml.ml_line_len == 0) | |
364 { | |
365 ul->ul_len = 1; | |
366 ul->ul_line = vim_strsave((char_u *)""); | |
367 } | |
368 else | |
369 { | |
370 ul->ul_len = curbuf->b_ml.ml_line_len; | |
371 ul->ul_line = vim_memsave(line, ul->ul_len); | |
372 } | |
373 return ul->ul_line == NULL ? FAIL : OK; | |
353 } | 374 } |
354 | 375 |
355 /* | 376 /* |
356 * Common code for various ways to save text before a change. | 377 * Common code for various ways to save text before a change. |
357 * "top" is the line above the first changed line. | 378 * "top" is the line above the first changed line. |
662 curbuf->b_u_newhead->uh_getbot_entry = uep; | 683 curbuf->b_u_newhead->uh_getbot_entry = uep; |
663 } | 684 } |
664 | 685 |
665 if (size > 0) | 686 if (size > 0) |
666 { | 687 { |
667 if ((uep->ue_array = (char_u **)U_ALLOC_LINE( | 688 if ((uep->ue_array = (undoline_T *)U_ALLOC_LINE( |
668 sizeof(char_u *) * size)) == NULL) | 689 sizeof(undoline_T) * size)) == NULL) |
669 { | 690 { |
670 u_freeentry(uep, 0L); | 691 u_freeentry(uep, 0L); |
671 goto nomem; | 692 goto nomem; |
672 } | 693 } |
673 for (i = 0, lnum = top + 1; i < size; ++i) | 694 for (i = 0, lnum = top + 1; i < size; ++i) |
676 if (got_int) | 697 if (got_int) |
677 { | 698 { |
678 u_freeentry(uep, i); | 699 u_freeentry(uep, i); |
679 return FAIL; | 700 return FAIL; |
680 } | 701 } |
681 if ((uep->ue_array[i] = u_save_line(lnum++)) == NULL) | 702 if (u_save_line(&uep->ue_array[i], lnum++) == FAIL) |
682 { | 703 { |
683 u_freeentry(uep, i); | 704 u_freeentry(uep, i); |
684 goto nomem; | 705 goto nomem; |
685 } | 706 } |
686 } | 707 } |
1109 if (len > 0 && undo_read(bi, ptr, len) == FAIL) | 1130 if (len > 0 && undo_read(bi, ptr, len) == FAIL) |
1110 { | 1131 { |
1111 vim_free(ptr); | 1132 vim_free(ptr); |
1112 return NULL; | 1133 return NULL; |
1113 } | 1134 } |
1135 // In case there are text properties there already is a NUL, but | |
1136 // checking for that is more expensive than just adding a dummy byte. | |
1114 ptr[len] = NUL; | 1137 ptr[len] = NUL; |
1115 #ifdef FEAT_CRYPT | 1138 #ifdef FEAT_CRYPT |
1116 if (bi->bi_state != NULL && bi->bi_buffer == NULL) | 1139 if (bi->bi_state != NULL && bi->bi_buffer == NULL) |
1117 crypt_decode_inplace(bi->bi_state, ptr, len); | 1140 crypt_decode_inplace(bi->bi_state, ptr, len); |
1118 #endif | 1141 #endif |
1124 * Writes the (not encrypted) header and initializes encryption if needed. | 1147 * Writes the (not encrypted) header and initializes encryption if needed. |
1125 */ | 1148 */ |
1126 static int | 1149 static int |
1127 serialize_header(bufinfo_T *bi, char_u *hash) | 1150 serialize_header(bufinfo_T *bi, char_u *hash) |
1128 { | 1151 { |
1129 int len; | 1152 long len; |
1130 buf_T *buf = bi->bi_buf; | 1153 buf_T *buf = bi->bi_buf; |
1131 FILE *fp = bi->bi_fp; | 1154 FILE *fp = bi->bi_fp; |
1132 char_u time_buf[8]; | 1155 char_u time_buf[8]; |
1133 | 1156 |
1134 /* Start writing, first the magic marker and undo info version. */ | 1157 /* Start writing, first the magic marker and undo info version. */ |
1146 undo_write_bytes(bi, (long_u)UF_VERSION_CRYPT, 2); | 1169 undo_write_bytes(bi, (long_u)UF_VERSION_CRYPT, 2); |
1147 bi->bi_state = crypt_create_for_writing(crypt_get_method_nr(buf), | 1170 bi->bi_state = crypt_create_for_writing(crypt_get_method_nr(buf), |
1148 buf->b_p_key, &header, &header_len); | 1171 buf->b_p_key, &header, &header_len); |
1149 if (bi->bi_state == NULL) | 1172 if (bi->bi_state == NULL) |
1150 return FAIL; | 1173 return FAIL; |
1151 len = (int)fwrite(header, (size_t)header_len, (size_t)1, fp); | 1174 len = (long)fwrite(header, (size_t)header_len, (size_t)1, fp); |
1152 vim_free(header); | 1175 vim_free(header); |
1153 if (len != 1) | 1176 if (len != 1) |
1154 { | 1177 { |
1155 crypt_free_state(bi->bi_state); | 1178 crypt_free_state(bi->bi_state); |
1156 bi->bi_state = NULL; | 1179 bi->bi_state = NULL; |
1179 if (undo_write(bi, hash, (size_t)UNDO_HASH_SIZE) == FAIL) | 1202 if (undo_write(bi, hash, (size_t)UNDO_HASH_SIZE) == FAIL) |
1180 return FAIL; | 1203 return FAIL; |
1181 | 1204 |
1182 /* buffer-specific data */ | 1205 /* buffer-specific data */ |
1183 undo_write_bytes(bi, (long_u)buf->b_ml.ml_line_count, 4); | 1206 undo_write_bytes(bi, (long_u)buf->b_ml.ml_line_count, 4); |
1184 len = buf->b_u_line_ptr != NULL ? (int)STRLEN(buf->b_u_line_ptr) : 0; | 1207 len = buf->b_u_line_ptr.ul_line == NULL |
1208 ? 0 : STRLEN(buf->b_u_line_ptr.ul_line); | |
1185 undo_write_bytes(bi, (long_u)len, 4); | 1209 undo_write_bytes(bi, (long_u)len, 4); |
1186 if (len > 0 && fwrite_crypt(bi, buf->b_u_line_ptr, (size_t)len) == FAIL) | 1210 if (len > 0 && fwrite_crypt(bi, buf->b_u_line_ptr.ul_line, (size_t)len) == FAIL) |
1187 return FAIL; | 1211 return FAIL; |
1188 undo_write_bytes(bi, (long_u)buf->b_u_line_lnum, 4); | 1212 undo_write_bytes(bi, (long_u)buf->b_u_line_lnum, 4); |
1189 undo_write_bytes(bi, (long_u)buf->b_u_line_colnr, 4); | 1213 undo_write_bytes(bi, (long_u)buf->b_u_line_colnr, 4); |
1190 | 1214 |
1191 /* Undo structures header data */ | 1215 /* Undo structures header data */ |
1358 undo_write_bytes(bi, (long_u)uep->ue_bot, 4); | 1382 undo_write_bytes(bi, (long_u)uep->ue_bot, 4); |
1359 undo_write_bytes(bi, (long_u)uep->ue_lcount, 4); | 1383 undo_write_bytes(bi, (long_u)uep->ue_lcount, 4); |
1360 undo_write_bytes(bi, (long_u)uep->ue_size, 4); | 1384 undo_write_bytes(bi, (long_u)uep->ue_size, 4); |
1361 for (i = 0; i < uep->ue_size; ++i) | 1385 for (i = 0; i < uep->ue_size; ++i) |
1362 { | 1386 { |
1363 len = STRLEN(uep->ue_array[i]); | 1387 // Text is written without the text properties, since we cannot restore |
1388 // the text property types. | |
1389 len = STRLEN(uep->ue_array[i].ul_line); | |
1364 if (undo_write_bytes(bi, (long_u)len, 4) == FAIL) | 1390 if (undo_write_bytes(bi, (long_u)len, 4) == FAIL) |
1365 return FAIL; | 1391 return FAIL; |
1366 if (len > 0 && fwrite_crypt(bi, uep->ue_array[i], len) == FAIL) | 1392 if (len > 0 && fwrite_crypt(bi, uep->ue_array[i].ul_line, len) == FAIL) |
1367 return FAIL; | 1393 return FAIL; |
1368 } | 1394 } |
1369 return OK; | 1395 return OK; |
1370 } | 1396 } |
1371 | 1397 |
1372 static u_entry_T * | 1398 static u_entry_T * |
1373 unserialize_uep(bufinfo_T *bi, int *error, char_u *file_name) | 1399 unserialize_uep(bufinfo_T *bi, int *error, char_u *file_name) |
1374 { | 1400 { |
1375 int i; | 1401 int i; |
1376 u_entry_T *uep; | 1402 u_entry_T *uep; |
1377 char_u **array = NULL; | 1403 undoline_T *array = NULL; |
1378 char_u *line; | 1404 char_u *line; |
1379 int line_len; | 1405 int line_len; |
1380 | 1406 |
1381 uep = (u_entry_T *)U_ALLOC_LINE(sizeof(u_entry_T)); | 1407 uep = (u_entry_T *)U_ALLOC_LINE(sizeof(u_entry_T)); |
1382 if (uep == NULL) | 1408 if (uep == NULL) |
1390 uep->ue_lcount = undo_read_4c(bi); | 1416 uep->ue_lcount = undo_read_4c(bi); |
1391 uep->ue_size = undo_read_4c(bi); | 1417 uep->ue_size = undo_read_4c(bi); |
1392 if (uep->ue_size > 0) | 1418 if (uep->ue_size > 0) |
1393 { | 1419 { |
1394 if (uep->ue_size < LONG_MAX / (int)sizeof(char_u *)) | 1420 if (uep->ue_size < LONG_MAX / (int)sizeof(char_u *)) |
1395 array = (char_u **)U_ALLOC_LINE(sizeof(char_u *) * uep->ue_size); | 1421 array = (undoline_T *)U_ALLOC_LINE(sizeof(undoline_T) * uep->ue_size); |
1396 if (array == NULL) | 1422 if (array == NULL) |
1397 { | 1423 { |
1398 *error = TRUE; | 1424 *error = TRUE; |
1399 return uep; | 1425 return uep; |
1400 } | 1426 } |
1401 vim_memset(array, 0, sizeof(char_u *) * uep->ue_size); | 1427 vim_memset(array, 0, sizeof(undoline_T) * uep->ue_size); |
1402 } | 1428 } |
1403 uep->ue_array = array; | 1429 uep->ue_array = array; |
1404 | 1430 |
1405 for (i = 0; i < uep->ue_size; ++i) | 1431 for (i = 0; i < uep->ue_size; ++i) |
1406 { | 1432 { |
1415 if (line == NULL) | 1441 if (line == NULL) |
1416 { | 1442 { |
1417 *error = TRUE; | 1443 *error = TRUE; |
1418 return uep; | 1444 return uep; |
1419 } | 1445 } |
1420 array[i] = line; | 1446 array[i].ul_line = line; |
1447 array[i].ul_len = line_len + 1; | |
1421 } | 1448 } |
1422 return uep; | 1449 return uep; |
1423 } | 1450 } |
1424 | 1451 |
1425 /* | 1452 /* |
1608 mch_remove(file_name); | 1635 mch_remove(file_name); |
1609 } | 1636 } |
1610 | 1637 |
1611 /* If there is no undo information at all, quit here after deleting any | 1638 /* If there is no undo information at all, quit here after deleting any |
1612 * existing undo file. */ | 1639 * existing undo file. */ |
1613 if (buf->b_u_numhead == 0 && buf->b_u_line_ptr == NULL) | 1640 if (buf->b_u_numhead == 0 && buf->b_u_line_ptr.ul_line == NULL) |
1614 { | 1641 { |
1615 if (p_verbose > 0) | 1642 if (p_verbose > 0) |
1616 verb_msg((char_u *)_("Skipping undo file write, nothing to undo")); | 1643 verb_msg((char_u *)_("Skipping undo file write, nothing to undo")); |
1617 goto theend; | 1644 goto theend; |
1618 } | 1645 } |
1769 u_read_undo(char_u *name, char_u *hash, char_u *orig_name) | 1796 u_read_undo(char_u *name, char_u *hash, char_u *orig_name) |
1770 { | 1797 { |
1771 char_u *file_name; | 1798 char_u *file_name; |
1772 FILE *fp; | 1799 FILE *fp; |
1773 long version, str_len; | 1800 long version, str_len; |
1774 char_u *line_ptr = NULL; | 1801 undoline_T line_ptr; |
1775 linenr_T line_lnum; | 1802 linenr_T line_lnum; |
1776 colnr_T line_colnr; | 1803 colnr_T line_colnr; |
1777 linenr_T line_count; | 1804 linenr_T line_count; |
1778 long num_head = 0; | 1805 long num_head = 0; |
1779 long old_header_seq, new_header_seq, cur_header_seq; | 1806 long old_header_seq, new_header_seq, cur_header_seq; |
1796 stat_T st_undo; | 1823 stat_T st_undo; |
1797 #endif | 1824 #endif |
1798 bufinfo_T bi; | 1825 bufinfo_T bi; |
1799 | 1826 |
1800 vim_memset(&bi, 0, sizeof(bi)); | 1827 vim_memset(&bi, 0, sizeof(bi)); |
1828 line_ptr.ul_len = 0; | |
1829 line_ptr.ul_line = NULL; | |
1830 | |
1801 if (name == NULL) | 1831 if (name == NULL) |
1802 { | 1832 { |
1803 file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE); | 1833 file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE); |
1804 if (file_name == NULL) | 1834 if (file_name == NULL) |
1805 return; | 1835 return; |
1915 /* Read undo data for "U" command. */ | 1945 /* Read undo data for "U" command. */ |
1916 str_len = undo_read_4c(&bi); | 1946 str_len = undo_read_4c(&bi); |
1917 if (str_len < 0) | 1947 if (str_len < 0) |
1918 goto error; | 1948 goto error; |
1919 if (str_len > 0) | 1949 if (str_len > 0) |
1920 line_ptr = read_string_decrypt(&bi, str_len); | 1950 { |
1951 line_ptr.ul_line = read_string_decrypt(&bi, str_len); | |
1952 line_ptr.ul_len = str_len + 1; | |
1953 } | |
1921 line_lnum = (linenr_T)undo_read_4c(&bi); | 1954 line_lnum = (linenr_T)undo_read_4c(&bi); |
1922 line_colnr = (colnr_T)undo_read_4c(&bi); | 1955 line_colnr = (colnr_T)undo_read_4c(&bi); |
1923 if (line_lnum < 0 || line_colnr < 0) | 1956 if (line_lnum < 0 || line_colnr < 0) |
1924 { | 1957 { |
1925 corruption_error("line lnum/col", file_name); | 1958 corruption_error("line lnum/col", file_name); |
2096 if (name != NULL) | 2129 if (name != NULL) |
2097 smsg((char_u *)_("Finished reading undo file %s"), file_name); | 2130 smsg((char_u *)_("Finished reading undo file %s"), file_name); |
2098 goto theend; | 2131 goto theend; |
2099 | 2132 |
2100 error: | 2133 error: |
2101 vim_free(line_ptr); | 2134 vim_free(line_ptr.ul_line); |
2102 if (uhp_table != NULL) | 2135 if (uhp_table != NULL) |
2103 { | 2136 { |
2104 for (i = 0; i < num_read_uhps; i++) | 2137 for (i = 0; i < num_read_uhps; i++) |
2105 if (uhp_table[i] != NULL) | 2138 if (uhp_table[i] != NULL) |
2106 u_free_uhp(uhp_table[i]); | 2139 u_free_uhp(uhp_table[i]); |
2594 * When "undo" is TRUE we go up in the tree, when FALSE we go down. | 2627 * When "undo" is TRUE we go up in the tree, when FALSE we go down. |
2595 */ | 2628 */ |
2596 static void | 2629 static void |
2597 u_undoredo(int undo) | 2630 u_undoredo(int undo) |
2598 { | 2631 { |
2599 char_u **newarray = NULL; | 2632 undoline_T *newarray = NULL; |
2600 linenr_T oldsize; | 2633 linenr_T oldsize; |
2601 linenr_T newsize; | 2634 linenr_T newsize; |
2602 linenr_T top, bot; | 2635 linenr_T top, bot; |
2603 linenr_T lnum; | 2636 linenr_T lnum; |
2604 linenr_T newlnum = MAXLNUM; | 2637 linenr_T newlnum = MAXLNUM; |
2667 { | 2700 { |
2668 /* Use the first line that actually changed. Avoids that | 2701 /* Use the first line that actually changed. Avoids that |
2669 * undoing auto-formatting puts the cursor in the previous | 2702 * undoing auto-formatting puts the cursor in the previous |
2670 * line. */ | 2703 * line. */ |
2671 for (i = 0; i < newsize && i < oldsize; ++i) | 2704 for (i = 0; i < newsize && i < oldsize; ++i) |
2672 if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0) | 2705 { |
2706 char_u *p = ml_get(top + 1 + i); | |
2707 | |
2708 if (curbuf->b_ml.ml_line_len != uep->ue_array[i].ul_len | |
2709 || memcmp(uep->ue_array[i].ul_line, p, curbuf->b_ml.ml_line_len) != 0) | |
2673 break; | 2710 break; |
2711 } | |
2674 if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL) | 2712 if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL) |
2675 { | 2713 { |
2676 newlnum = top; | 2714 newlnum = top; |
2677 curwin->w_cursor.lnum = newlnum + 1; | 2715 curwin->w_cursor.lnum = newlnum + 1; |
2678 } | 2716 } |
2687 empty_buffer = FALSE; | 2725 empty_buffer = FALSE; |
2688 | 2726 |
2689 /* delete the lines between top and bot and save them in newarray */ | 2727 /* delete the lines between top and bot and save them in newarray */ |
2690 if (oldsize > 0) | 2728 if (oldsize > 0) |
2691 { | 2729 { |
2692 if ((newarray = (char_u **)U_ALLOC_LINE( | 2730 if ((newarray = (undoline_T *)U_ALLOC_LINE( |
2693 sizeof(char_u *) * oldsize)) == NULL) | 2731 sizeof(undoline_T) * oldsize)) == NULL) |
2694 { | 2732 { |
2695 do_outofmem_msg((long_u)(sizeof(char_u *) * oldsize)); | 2733 do_outofmem_msg((long_u)(sizeof(undoline_T) * oldsize)); |
2696 /* | 2734 /* |
2697 * We have messed up the entry list, repair is impossible. | 2735 * We have messed up the entry list, repair is impossible. |
2698 * we have to free the rest of the list. | 2736 * we have to free the rest of the list. |
2699 */ | 2737 */ |
2700 while (uep != NULL) | 2738 while (uep != NULL) |
2707 } | 2745 } |
2708 /* delete backwards, it goes faster in most cases */ | 2746 /* delete backwards, it goes faster in most cases */ |
2709 for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum) | 2747 for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum) |
2710 { | 2748 { |
2711 /* what can we do when we run out of memory? */ | 2749 /* what can we do when we run out of memory? */ |
2712 if ((newarray[i] = u_save_line(lnum)) == NULL) | 2750 if (u_save_line(&newarray[i], lnum) == FAIL) |
2713 do_outofmem_msg((long_u)0); | 2751 do_outofmem_msg((long_u)0); |
2714 /* remember we deleted the last line in the buffer, and a | 2752 /* remember we deleted the last line in the buffer, and a |
2715 * dummy empty line will be inserted */ | 2753 * dummy empty line will be inserted */ |
2716 if (curbuf->b_ml.ml_line_count == 1) | 2754 if (curbuf->b_ml.ml_line_count == 1) |
2717 empty_buffer = TRUE; | 2755 empty_buffer = TRUE; |
2724 /* insert the lines in u_array between top and bot */ | 2762 /* insert the lines in u_array between top and bot */ |
2725 if (newsize) | 2763 if (newsize) |
2726 { | 2764 { |
2727 for (lnum = top, i = 0; i < newsize; ++i, ++lnum) | 2765 for (lnum = top, i = 0; i < newsize; ++i, ++lnum) |
2728 { | 2766 { |
2729 /* | 2767 // If the file is empty, there is an empty line 1 that we |
2730 * If the file is empty, there is an empty line 1 that we | 2768 // should get rid of, by replacing it with the new line. |
2731 * should get rid of, by replacing it with the new line | |
2732 */ | |
2733 if (empty_buffer && lnum == 0) | 2769 if (empty_buffer && lnum == 0) |
2734 ml_replace((linenr_T)1, uep->ue_array[i], TRUE); | 2770 ml_replace_len((linenr_T)1, uep->ue_array[i].ul_line, uep->ue_array[i].ul_len, TRUE, TRUE); |
2735 else | 2771 else |
2736 ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE); | 2772 ml_append(lnum, uep->ue_array[i].ul_line, (colnr_T)uep->ue_array[i].ul_len, FALSE); |
2737 vim_free(uep->ue_array[i]); | 2773 vim_free(uep->ue_array[i].ul_line); |
2738 } | 2774 } |
2739 vim_free((char_u *)uep->ue_array); | 2775 vim_free((char_u *)uep->ue_array); |
2740 } | 2776 } |
2741 | 2777 |
2742 /* adjust marks */ | 2778 /* adjust marks */ |
3170 if (uep->ue_top != 0 || uep->ue_bot != 0) | 3206 if (uep->ue_top != 0 || uep->ue_bot != 0) |
3171 return; | 3207 return; |
3172 | 3208 |
3173 for (lnum = 1; lnum < curbuf->b_ml.ml_line_count | 3209 for (lnum = 1; lnum < curbuf->b_ml.ml_line_count |
3174 && lnum <= uep->ue_size; ++lnum) | 3210 && lnum <= uep->ue_size; ++lnum) |
3175 if (STRCMP(ml_get_buf(curbuf, lnum, FALSE), | 3211 { |
3176 uep->ue_array[lnum - 1]) != 0) | 3212 char_u *p = ml_get_buf(curbuf, lnum, FALSE); |
3213 | |
3214 if (uep->ue_array[lnum - 1].ul_len != curbuf->b_ml.ml_line_len | |
3215 || memcmp(p, uep->ue_array[lnum - 1].ul_line, uep->ue_array[lnum - 1].ul_len) != 0) | |
3177 { | 3216 { |
3178 CLEAR_POS(&(uhp->uh_cursor)); | 3217 CLEAR_POS(&(uhp->uh_cursor)); |
3179 uhp->uh_cursor.lnum = lnum; | 3218 uhp->uh_cursor.lnum = lnum; |
3180 return; | 3219 return; |
3181 } | 3220 } |
3221 } | |
3182 if (curbuf->b_ml.ml_line_count != uep->ue_size) | 3222 if (curbuf->b_ml.ml_line_count != uep->ue_size) |
3183 { | 3223 { |
3184 /* lines added or deleted at the end, put the cursor there */ | 3224 /* lines added or deleted at the end, put the cursor there */ |
3185 CLEAR_POS(&(uhp->uh_cursor)); | 3225 CLEAR_POS(&(uhp->uh_cursor)); |
3186 uhp->uh_cursor.lnum = lnum; | 3226 uhp->uh_cursor.lnum = lnum; |
3381 */ | 3421 */ |
3382 static void | 3422 static void |
3383 u_freeentry(u_entry_T *uep, long n) | 3423 u_freeentry(u_entry_T *uep, long n) |
3384 { | 3424 { |
3385 while (n > 0) | 3425 while (n > 0) |
3386 vim_free(uep->ue_array[--n]); | 3426 vim_free(uep->ue_array[--n].ul_line); |
3387 vim_free((char_u *)uep->ue_array); | 3427 vim_free((char_u *)uep->ue_array); |
3388 #ifdef U_DEBUG | 3428 #ifdef U_DEBUG |
3389 uep->ue_magic = 0; | 3429 uep->ue_magic = 0; |
3390 #endif | 3430 #endif |
3391 vim_free((char_u *)uep); | 3431 vim_free((char_u *)uep); |
3398 u_clearall(buf_T *buf) | 3438 u_clearall(buf_T *buf) |
3399 { | 3439 { |
3400 buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL; | 3440 buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL; |
3401 buf->b_u_synced = TRUE; | 3441 buf->b_u_synced = TRUE; |
3402 buf->b_u_numhead = 0; | 3442 buf->b_u_numhead = 0; |
3403 buf->b_u_line_ptr = NULL; | 3443 buf->b_u_line_ptr.ul_line = NULL; |
3444 buf->b_u_line_ptr.ul_len = 0; | |
3404 buf->b_u_line_lnum = 0; | 3445 buf->b_u_line_lnum = 0; |
3405 } | 3446 } |
3406 | 3447 |
3407 /* | 3448 /* |
3408 * save the line "lnum" for the "U" command | 3449 * Save the line "lnum" for the "U" command. |
3409 */ | 3450 */ |
3410 void | 3451 void |
3411 u_saveline(linenr_T lnum) | 3452 u_saveline(linenr_T lnum) |
3412 { | 3453 { |
3413 if (lnum == curbuf->b_u_line_lnum) /* line is already saved */ | 3454 if (lnum == curbuf->b_u_line_lnum) /* line is already saved */ |
3418 curbuf->b_u_line_lnum = lnum; | 3459 curbuf->b_u_line_lnum = lnum; |
3419 if (curwin->w_cursor.lnum == lnum) | 3460 if (curwin->w_cursor.lnum == lnum) |
3420 curbuf->b_u_line_colnr = curwin->w_cursor.col; | 3461 curbuf->b_u_line_colnr = curwin->w_cursor.col; |
3421 else | 3462 else |
3422 curbuf->b_u_line_colnr = 0; | 3463 curbuf->b_u_line_colnr = 0; |
3423 if ((curbuf->b_u_line_ptr = u_save_line(lnum)) == NULL) | 3464 if (u_save_line(&curbuf->b_u_line_ptr, lnum) == FAIL) |
3424 do_outofmem_msg((long_u)0); | 3465 do_outofmem_msg((long_u)0); |
3425 } | 3466 } |
3426 | 3467 |
3427 /* | 3468 /* |
3428 * clear the line saved for the "U" command | 3469 * clear the line saved for the "U" command |
3429 * (this is used externally for crossing a line while in insert mode) | 3470 * (this is used externally for crossing a line while in insert mode) |
3430 */ | 3471 */ |
3431 void | 3472 void |
3432 u_clearline(void) | 3473 u_clearline(void) |
3433 { | 3474 { |
3434 if (curbuf->b_u_line_ptr != NULL) | 3475 if (curbuf->b_u_line_ptr.ul_line != NULL) |
3435 { | 3476 { |
3436 VIM_CLEAR(curbuf->b_u_line_ptr); | 3477 VIM_CLEAR(curbuf->b_u_line_ptr.ul_line); |
3478 curbuf->b_u_line_ptr.ul_len = 0; | |
3437 curbuf->b_u_line_lnum = 0; | 3479 curbuf->b_u_line_lnum = 0; |
3438 } | 3480 } |
3439 } | 3481 } |
3440 | 3482 |
3441 /* | 3483 /* |
3445 * Careful: may trigger autocommands that reload the buffer. | 3487 * Careful: may trigger autocommands that reload the buffer. |
3446 */ | 3488 */ |
3447 void | 3489 void |
3448 u_undoline(void) | 3490 u_undoline(void) |
3449 { | 3491 { |
3450 colnr_T t; | 3492 colnr_T t; |
3451 char_u *oldp; | 3493 undoline_T oldp; |
3452 | 3494 |
3453 if (undo_off) | 3495 if (undo_off) |
3454 return; | 3496 return; |
3455 | 3497 |
3456 if (curbuf->b_u_line_ptr == NULL | 3498 if (curbuf->b_u_line_ptr.ul_line == NULL |
3457 || curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count) | 3499 || curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count) |
3458 { | 3500 { |
3459 beep_flush(); | 3501 beep_flush(); |
3460 return; | 3502 return; |
3461 } | 3503 } |
3462 | 3504 |
3463 /* first save the line for the 'u' command */ | 3505 // first save the line for the 'u' command |
3464 if (u_savecommon(curbuf->b_u_line_lnum - 1, | 3506 if (u_savecommon(curbuf->b_u_line_lnum - 1, |
3465 curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL) | 3507 curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL) |
3466 return; | 3508 return; |
3467 oldp = u_save_line(curbuf->b_u_line_lnum); | 3509 if (u_save_line(&oldp, curbuf->b_u_line_lnum) == FAIL) |
3468 if (oldp == NULL) | |
3469 { | 3510 { |
3470 do_outofmem_msg((long_u)0); | 3511 do_outofmem_msg((long_u)0); |
3471 return; | 3512 return; |
3472 } | 3513 } |
3473 ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE); | 3514 ml_replace_len(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr.ul_line, curbuf->b_u_line_ptr.ul_len, TRUE, FALSE); |
3474 changed_bytes(curbuf->b_u_line_lnum, 0); | 3515 changed_bytes(curbuf->b_u_line_lnum, 0); |
3475 vim_free(curbuf->b_u_line_ptr); | |
3476 curbuf->b_u_line_ptr = oldp; | 3516 curbuf->b_u_line_ptr = oldp; |
3477 | 3517 |
3478 t = curbuf->b_u_line_colnr; | 3518 t = curbuf->b_u_line_colnr; |
3479 if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum) | 3519 if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum) |
3480 curbuf->b_u_line_colnr = curwin->w_cursor.col; | 3520 curbuf->b_u_line_colnr = curwin->w_cursor.col; |
3489 void | 3529 void |
3490 u_blockfree(buf_T *buf) | 3530 u_blockfree(buf_T *buf) |
3491 { | 3531 { |
3492 while (buf->b_u_oldhead != NULL) | 3532 while (buf->b_u_oldhead != NULL) |
3493 u_freeheader(buf, buf->b_u_oldhead, NULL); | 3533 u_freeheader(buf, buf->b_u_oldhead, NULL); |
3494 vim_free(buf->b_u_line_ptr); | 3534 vim_free(buf->b_u_line_ptr.ul_line); |
3495 } | |
3496 | |
3497 /* | |
3498 * u_save_line(): allocate memory and copy line 'lnum' into it. | |
3499 * Returns NULL when out of memory. | |
3500 */ | |
3501 static char_u * | |
3502 u_save_line(linenr_T lnum) | |
3503 { | |
3504 return vim_strsave(ml_get(lnum)); | |
3505 } | 3535 } |
3506 | 3536 |
3507 /* | 3537 /* |
3508 * Check if the 'modified' flag is set, or 'ff' has changed (only need to | 3538 * Check if the 'modified' flag is set, or 'ff' has changed (only need to |
3509 * check the first character, because it can only be "dos", "unix" or "mac"). | 3539 * check the first character, because it can only be "dos", "unix" or "mac"). |