aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/undo.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:31:31 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:31:31 +0000
commit9243becbedbb6a1592208051f8fa2b090dcc5e7d (patch)
tree607c2a862ec3f4399b8766383f6f8e04c4aa43b4 /src/nvim/undo.c
parent9e40b6e9e1bc67f2d856adb837ee64dd0e25b717 (diff)
parent3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff)
downloadrneovim-usermarks.tar.gz
rneovim-usermarks.tar.bz2
rneovim-usermarks.zip
Merge remote-tracking branch 'upstream/master' into usermarksusermarks
Diffstat (limited to 'src/nvim/undo.c')
-rw-r--r--src/nvim/undo.c162
1 files changed, 90 insertions, 72 deletions
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 75a09b244c..2b0bb1d243 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -76,41 +76,56 @@
#include <assert.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <limits.h>
#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <time.h>
+#include <uv.h>
#include "auto/config.h"
+#include "klib/kvec.h"
#include "nvim/ascii.h"
+#include "nvim/autocmd.h"
#include "nvim/buffer.h"
#include "nvim/buffer_updates.h"
#include "nvim/change.h"
#include "nvim/cursor.h"
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
+#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_getln.h"
#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
-#include "nvim/lib/kvec.h"
+#include "nvim/gettext.h"
+#include "nvim/globals.h"
+#include "nvim/highlight_defs.h"
+#include "nvim/macros.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
-#include "nvim/os_unix.h"
#include "nvim/path.h"
-#include "nvim/pos.h" // MAXLNUM
+#include "nvim/pos.h"
+#include "nvim/screen.h"
#include "nvim/sha256.h"
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/types.h"
#include "nvim/undo.h"
+#include "nvim/undo_defs.h"
+#include "nvim/vim.h"
/// Structure passed around between undofile functions.
typedef struct {
@@ -558,7 +573,7 @@ int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int re
}
if (size > 0) {
- uep->ue_array = xmalloc(sizeof(char_u *) * (size_t)size);
+ uep->ue_array = xmalloc(sizeof(char *) * (size_t)size);
linenr_T lnum;
long i;
for (i = 0, lnum = top + 1; i < size; i++) {
@@ -609,20 +624,20 @@ int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int re
// extra fields for uhp
#define UHP_SAVE_NR 1
-static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
+static char e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
/// Compute the hash for a buffer text into hash[UNDO_HASH_SIZE].
///
/// @param[in] buf The buffer used to compute the hash
/// @param[in] hash Array of size UNDO_HASH_SIZE in which to store the value of
/// the hash
-void u_compute_hash(buf_T *buf, char_u *hash)
+void u_compute_hash(buf_T *buf, uint8_t *hash)
{
context_sha256_T ctx;
sha256_start(&ctx);
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
- char_u *p = ml_get_buf(buf, lnum, false);
- sha256_update(&ctx, p, (uint32_t)(STRLEN(p) + 1));
+ char *p = ml_get_buf(buf, lnum, false);
+ sha256_update(&ctx, (uint8_t *)p, strlen(p) + 1);
}
sha256_finish(&ctx, hash);
}
@@ -651,7 +666,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
char fname_buf[MAXPATHL];
// Expand symlink in the file name, so that we put the undo file with the
// actual file instead of with the symlink.
- if (resolve_symlink((const char_u *)ffname, (char_u *)fname_buf) == OK) {
+ if (resolve_symlink(ffname, fname_buf) == OK) {
ffname = fname_buf;
}
#endif
@@ -662,7 +677,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
// Loop over 'undodir'. When reading find the first file that exists.
// When not reading use the first directory that exists or ".".
- char *dirp = (char *)p_udir;
+ char *dirp = p_udir;
while (*dirp != NUL) {
size_t dir_len = copy_option_part(&dirp, dir_name, MAXPATHL, ",");
if (dir_len == 1 && dir_name[0] == '.') {
@@ -685,7 +700,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
*p-- = NUL;
}
- bool has_directory = os_isdir((char_u *)dir_name);
+ bool has_directory = os_isdir(dir_name);
if (!has_directory && *dirp == NUL && !reading) {
// Last directory in the list does not exist, create it.
int ret;
@@ -713,7 +728,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
// When reading check if the file exists.
if (undo_file_name != NULL
- && (!reading || os_path_exists((char_u *)undo_file_name))) {
+ && (!reading || os_path_exists(undo_file_name))) {
break;
}
XFREE_CLEAR(undo_file_name);
@@ -750,7 +765,7 @@ static void u_free_uhp(u_header_T *uhp)
/// @param hash The hash of the buffer contents
//
/// @returns false in case of an error.
-static bool serialize_header(bufinfo_T *bi, char_u *hash)
+static bool serialize_header(bufinfo_T *bi, uint8_t *hash)
FUNC_ATTR_NONNULL_ALL
{
buf_T *buf = bi->bi_buf;
@@ -771,9 +786,9 @@ static bool serialize_header(bufinfo_T *bi, char_u *hash)
// Write buffer-specific data.
undo_write_bytes(bi, (uintmax_t)buf->b_ml.ml_line_count, 4);
- size_t len = buf->b_u_line_ptr ? STRLEN(buf->b_u_line_ptr) : 0;
+ size_t len = buf->b_u_line_ptr ? strlen(buf->b_u_line_ptr) : 0;
undo_write_bytes(bi, len, 4);
- if (len > 0 && !undo_write(bi, buf->b_u_line_ptr, len)) {
+ if (len > 0 && !undo_write(bi, (uint8_t *)buf->b_u_line_ptr, len)) {
return false;
}
undo_write_bytes(bi, (uintmax_t)buf->b_u_line_lnum, 4);
@@ -1034,11 +1049,11 @@ static bool serialize_uep(bufinfo_T *bi, u_entry_T *uep)
undo_write_bytes(bi, (uintmax_t)uep->ue_size, 4);
for (size_t i = 0; i < (size_t)uep->ue_size; i++) {
- size_t len = STRLEN(uep->ue_array[i]);
+ size_t len = strlen(uep->ue_array[i]);
if (!undo_write_bytes(bi, len, 4)) {
return false;
}
- if (len > 0 && !undo_write(bi, uep->ue_array[i], len)) {
+ if (len > 0 && !undo_write(bi, (uint8_t *)uep->ue_array[i], len)) {
return false;
}
}
@@ -1057,18 +1072,18 @@ static u_entry_T *unserialize_uep(bufinfo_T *bi, bool *error, const char *file_n
uep->ue_lcount = undo_read_4c(bi);
uep->ue_size = undo_read_4c(bi);
- char_u **array = NULL;
+ char **array = NULL;
if (uep->ue_size > 0) {
- if ((size_t)uep->ue_size < SIZE_MAX / sizeof(char_u *)) { // -V547
- array = xmalloc(sizeof(char_u *) * (size_t)uep->ue_size);
- memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size);
+ if ((size_t)uep->ue_size < SIZE_MAX / sizeof(char *)) { // -V547
+ array = xmalloc(sizeof(char *) * (size_t)uep->ue_size);
+ memset(array, 0, sizeof(char *) * (size_t)uep->ue_size);
}
}
uep->ue_array = array;
for (size_t i = 0; i < (size_t)uep->ue_size; i++) {
int line_len = undo_read_4c(bi);
- char_u *line;
+ char *line;
if (line_len >= 0) {
line = undo_read_string(bi, (size_t)line_len);
} else {
@@ -1135,7 +1150,7 @@ static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info)
/// @param[in] buf Buffer for which undo file is written.
/// @param[in] hash Hash value of the buffer text. Must have #UNDO_HASH_SIZE
/// size.
-void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, char_u *const hash)
+void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, uint8_t *const hash)
FUNC_ATTR_NONNULL_ARG(3, 4)
{
char *file_name;
@@ -1177,7 +1192,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
// If the undo file already exists, verify that it actually is an undo
// file, and delete it.
- if (os_path_exists((char_u *)file_name)) {
+ if (os_path_exists(file_name)) {
if (name == NULL || !forceit) {
// Check we can read it and it's an undo file.
fd = os_open(file_name, O_RDONLY, 0);
@@ -1194,7 +1209,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
}
goto theend;
} else {
- char_u mbuf[UF_START_MAGIC_LEN];
+ char mbuf[UF_START_MAGIC_LEN];
ssize_t len = read_eintr(fd, mbuf, UF_START_MAGIC_LEN);
close(fd);
if (len < UF_START_MAGIC_LEN
@@ -1327,9 +1342,9 @@ write_error:
#ifdef HAVE_ACL
if (buf->b_ffname != NULL) {
// For systems that support ACL: get the ACL from the original file.
- vim_acl_T acl = mch_get_acl((char_u *)buf->b_ffname);
- mch_set_acl((char_u *)file_name, acl);
- mch_free_acl(acl);
+ vim_acl_T acl = os_get_acl(buf->b_ffname);
+ os_set_acl(file_name, acl);
+ os_free_acl(acl);
}
#endif
@@ -1344,11 +1359,11 @@ theend:
/// a bit more verbose.
/// Otherwise use curbuf->b_ffname to generate the undo file name.
/// "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
-void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_ATTR_UNUSED)
+void u_read_undo(char *name, const uint8_t *hash, const char *orig_name FUNC_ATTR_UNUSED)
FUNC_ATTR_NONNULL_ARG(2)
{
u_header_T **uhp_table = NULL;
- char_u *line_ptr = NULL;
+ char *line_ptr = NULL;
char *file_name;
if (name == NULL) {
@@ -1362,7 +1377,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
// owner of the text file or equal to the current user.
FileInfo file_info_orig;
FileInfo file_info_undo;
- if (os_fileinfo((const char *)orig_name, &file_info_orig)
+ if (os_fileinfo(orig_name, &file_info_orig)
&& os_fileinfo(file_name, &file_info_undo)
&& file_info_orig.stat.st_uid != file_info_undo.stat.st_uid
&& file_info_undo.stat.st_uid != getuid()) {
@@ -1399,7 +1414,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
};
// Read the undo file header.
- char_u magic_buf[UF_START_MAGIC_LEN];
+ char magic_buf[UF_START_MAGIC_LEN];
if (fread(magic_buf, UF_START_MAGIC_LEN, 1, fp) != 1
|| memcmp(magic_buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) {
semsg(_("E823: Not an undo file: %s"), file_name);
@@ -1411,7 +1426,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
goto error;
}
- char_u read_hash[UNDO_HASH_SIZE];
+ uint8_t read_hash[UNDO_HASH_SIZE];
if (!undo_read(&bi, read_hash, UNDO_HASH_SIZE)) {
corruption_error("hash", file_name);
goto error;
@@ -1728,10 +1743,10 @@ static bool undo_read(bufinfo_T *bi, uint8_t *buffer, size_t size)
/// @param len can be zero to allocate an empty line.
///
/// @returns a pointer to allocated memory or NULL in case of an error.
-static uint8_t *undo_read_string(bufinfo_T *bi, size_t len)
+static char *undo_read_string(bufinfo_T *bi, size_t len)
{
- uint8_t *ptr = xmallocz(len);
- if (len > 0 && !undo_read(bi, ptr, len)) {
+ char *ptr = xmallocz(len);
+ if (len > 0 && !undo_read(bi, (uint8_t *)ptr, len)) {
xfree(ptr);
return NULL;
}
@@ -1771,16 +1786,16 @@ void u_redo(int count)
/// Undo and remove the branch from the undo tree.
/// Also moves the cursor (as a "normal" undo would).
-bool u_undo_and_forget(int count)
+///
+/// @param do_buf_event If `true`, send the changedtick with the buffer updates
+bool u_undo_and_forget(int count, bool do_buf_event)
{
if (curbuf->b_u_synced == false) {
u_sync(true);
count = 1;
}
undo_undoes = true;
- u_doit(count, true,
- // Don't send nvim_buf_lines_event for u_undo_and_forget().
- false);
+ u_doit(count, true, do_buf_event);
if (curbuf->b_u_curhead == NULL) {
// nothing was undone.
@@ -2223,7 +2238,7 @@ target_zero:
/// @param do_buf_event If `true`, send buffer updates.
static void u_undoredo(int undo, bool do_buf_event)
{
- char_u **newarray = NULL;
+ char **newarray = NULL;
linenr_T newlnum = MAXLNUM;
u_entry_T *nuep;
u_entry_T *newlist = NULL;
@@ -2283,7 +2298,7 @@ static void u_undoredo(int undo, bool do_buf_event)
// line.
long i;
for (i = 0; i < newsize && i < oldsize; i++) {
- if (STRCMP(uep->ue_array[i], ml_get(top + 1 + (linenr_T)i)) != 0) {
+ if (strcmp(uep->ue_array[i], ml_get(top + 1 + (linenr_T)i)) != 0) {
break;
}
}
@@ -2301,11 +2316,11 @@ static void u_undoredo(int undo, bool do_buf_event)
// delete the lines between top and bot and save them in newarray
if (oldsize > 0) {
- newarray = xmalloc(sizeof(char_u *) * (size_t)oldsize);
+ newarray = xmalloc(sizeof(char *) * (size_t)oldsize);
// delete backwards, it goes faster in most cases
long i;
linenr_T lnum;
- for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum) {
+ for (lnum = bot - 1, i = oldsize; --i >= 0; lnum--) {
// what can we do when we run out of memory?
newarray[i] = u_save_line(lnum);
// remember we deleted the last line in the buffer, and a
@@ -2327,13 +2342,13 @@ static void u_undoredo(int undo, bool do_buf_event)
// If the file is empty, there is an empty line 1 that we
// should get rid of, by replacing it with the new line
if (empty_buffer && lnum == 0) {
- ml_replace((linenr_T)1, (char *)uep->ue_array[i], true);
+ ml_replace((linenr_T)1, uep->ue_array[i], true);
} else {
- ml_append(lnum, (char *)uep->ue_array[i], (colnr_T)0, false);
+ ml_append(lnum, uep->ue_array[i], (colnr_T)0, false);
}
xfree(uep->ue_array[i]);
}
- xfree((char_u *)uep->ue_array);
+ xfree(uep->ue_array);
}
// Adjust marks
@@ -2550,7 +2565,7 @@ static void u_undo_end(bool did_undo, bool absolute, bool quiet)
uhp = curbuf->b_u_newhead;
}
- char_u msgbuf[80];
+ char msgbuf[80];
if (uhp == NULL) {
*msgbuf = NUL;
} else {
@@ -2560,7 +2575,7 @@ static void u_undo_end(bool did_undo, bool absolute, bool quiet)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer == curbuf && wp->w_p_cole > 0) {
- redraw_later(wp, NOT_VALID);
+ redraw_later(wp, UPD_NOT_VALID);
}
}
}
@@ -2579,21 +2594,25 @@ static void u_undo_end(bool did_undo, bool absolute, bool quiet)
}
/// Put the timestamp of an undo header in "buf[buflen]" in a nice format.
-void undo_fmt_time(char_u *buf, size_t buflen, time_t tt)
+void undo_fmt_time(char *buf, size_t buflen, time_t tt)
{
if (time(NULL) - tt >= 100) {
struct tm curtime;
os_localtime_r(&tt, &curtime);
+ size_t n;
if (time(NULL) - tt < (60L * 60L * 12L)) {
// within 12 hours
- (void)strftime((char *)buf, buflen, "%H:%M:%S", &curtime);
+ n = strftime(buf, buflen, "%H:%M:%S", &curtime);
} else {
// longer ago
- (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", &curtime);
+ n = strftime(buf, buflen, "%Y/%m/%d %H:%M:%S", &curtime);
+ }
+ if (n == 0) {
+ buf[0] = NUL;
}
} else {
int64_t seconds = time(NULL) - tt;
- vim_snprintf((char *)buf, buflen,
+ vim_snprintf(buf, buflen,
NGETTEXT("%" PRId64 " second ago",
"%" PRId64 " seconds ago", (uint32_t)seconds),
seconds);
@@ -2635,15 +2654,15 @@ void ex_undolist(exarg_T *eap)
while (uhp != NULL) {
if (uhp->uh_prev.ptr == NULL && uhp->uh_walk != nomark
&& uhp->uh_walk != mark) {
- vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ", uhp->uh_seq, changes);
- undo_fmt_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), uhp->uh_time);
+ vim_snprintf(IObuff, IOSIZE, "%6ld %7d ", uhp->uh_seq, changes);
+ undo_fmt_time(IObuff + strlen(IObuff), IOSIZE - strlen(IObuff), uhp->uh_time);
if (uhp->uh_save_nr > 0) {
- while (STRLEN(IObuff) < 33) {
+ while (strlen(IObuff) < 33) {
STRCAT(IObuff, " ");
}
- vim_snprintf_add((char *)IObuff, IOSIZE, " %3ld", uhp->uh_save_nr);
+ vim_snprintf_add(IObuff, IOSIZE, " %3ld", uhp->uh_save_nr);
}
- GA_APPEND(char_u *, &ga, vim_strsave(IObuff));
+ GA_APPEND(char *, &ga, xstrdup(IObuff));
}
uhp->uh_walk = mark;
@@ -2713,9 +2732,8 @@ void ex_undojoin(exarg_T *eap)
}
if (get_undolevel(curbuf) < 0) {
return; // no entries, nothing to do
- } else {
- curbuf->b_u_synced = false; // Append next change to last entry
}
+ curbuf->b_u_synced = false; // Append next change to last entry
}
/// Called after writing or reloading the file and setting b_changed to false.
@@ -2744,7 +2762,7 @@ void u_find_first_changed(void)
linenr_T lnum;
for (lnum = 1; lnum < curbuf->b_ml.ml_line_count
&& lnum <= uep->ue_size; lnum++) {
- if (STRCMP(ml_get_buf(curbuf, lnum, false), uep->ue_array[lnum - 1]) != 0) {
+ if (strcmp(ml_get_buf(curbuf, lnum, false), uep->ue_array[lnum - 1]) != 0) {
clearpos(&(uhp->uh_cursor));
uhp->uh_cursor.lnum = lnum;
return;
@@ -2917,7 +2935,7 @@ static void u_freeentries(buf_T *buf, u_header_T *uhp, u_header_T **uhpp)
#ifdef U_DEBUG
uhp->uh_magic = 0;
#endif
- xfree((char_u *)uhp);
+ xfree(uhp);
buf->b_u_numhead--;
}
@@ -2927,11 +2945,11 @@ static void u_freeentry(u_entry_T *uep, long n)
while (n > 0) {
xfree(uep->ue_array[--n]);
}
- xfree((char_u *)uep->ue_array);
+ xfree(uep->ue_array);
#ifdef U_DEBUG
uep->ue_magic = 0;
#endif
- xfree((char_u *)uep);
+ xfree(uep);
}
/// invalidate the undo buffer; called when storage has already been released
@@ -2991,11 +3009,11 @@ void u_undoline(void)
return;
}
- char_u *oldp = u_save_line(curbuf->b_u_line_lnum);
- ml_replace(curbuf->b_u_line_lnum, (char *)curbuf->b_u_line_ptr, true);
+ char *oldp = u_save_line(curbuf->b_u_line_lnum);
+ ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true);
changed_bytes(curbuf->b_u_line_lnum, 0);
- extmark_splice_cols(curbuf, (int)curbuf->b_u_line_lnum - 1, 0, (colnr_T)STRLEN(oldp),
- (colnr_T)STRLEN(curbuf->b_u_line_ptr), kExtmarkUndo);
+ extmark_splice_cols(curbuf, (int)curbuf->b_u_line_lnum - 1, 0, (colnr_T)strlen(oldp),
+ (colnr_T)strlen(curbuf->b_u_line_ptr), kExtmarkUndo);
xfree(curbuf->b_u_line_ptr);
curbuf->b_u_line_ptr = oldp;
@@ -3025,7 +3043,7 @@ void u_blockfree(buf_T *buf)
/// Allocate memory and copy curbuf line into it.
///
/// @param lnum the line to copy
-static char_u *u_save_line(linenr_T lnum)
+static char *u_save_line(linenr_T lnum)
{
return u_save_line_buf(curbuf, lnum);
}
@@ -3034,9 +3052,9 @@ static char_u *u_save_line(linenr_T lnum)
///
/// @param lnum line to copy
/// @param buf buffer to copy from
-static char_u *u_save_line_buf(buf_T *buf, linenr_T lnum)
+static char *u_save_line_buf(buf_T *buf, linenr_T lnum)
{
- return vim_strsave(ml_get_buf(buf, lnum, false));
+ return xstrdup(ml_get_buf(buf, lnum, false));
}
/// Check if the 'modified' flag is set, or 'ff' has changed (only need to