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").