vi: correctly record deleted characters

The undo queue didn't record deleted characters properly.  For
example, insert some text, backspace over a couple of characters
then exit insert mode.  At this point undo will restore two nulls
instead of the deleted characters.

The fix is in undo_push():  record the state of the UNDO_USE_SPOS
flag and clear it before using 'u_type'.

Also, update the comments to reflect the fact that UNDO_QUEUED_FLAG
isn't actually used.

function                                             old     new   delta
undo_push                                            443     435      -8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-8)               Total: -8 bytes

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Ron Yorston 2021-04-15 12:00:50 +01:00 committed by Denys Vlasenko
parent c0943ac451
commit 9b2a3895ee

View File

@ -399,26 +399,31 @@ struct globals {
#define UNDO_DEL 1 #define UNDO_DEL 1
#define UNDO_INS_CHAIN 2 #define UNDO_INS_CHAIN 2
#define UNDO_DEL_CHAIN 3 #define UNDO_DEL_CHAIN 3
// UNDO_*_QUEUED must be equal to UNDO_xxx ORed with UNDO_QUEUED_FLAG # if ENABLE_FEATURE_VI_UNDO_QUEUE
#define UNDO_QUEUED_FLAG 4
#define UNDO_INS_QUEUED 4 #define UNDO_INS_QUEUED 4
#define UNDO_DEL_QUEUED 5 #define UNDO_DEL_QUEUED 5
#define UNDO_USE_SPOS 32 # endif
#define UNDO_EMPTY 64
// Pass-through flags for functions that can be undone // Pass-through flags for functions that can be undone
#define NO_UNDO 0 #define NO_UNDO 0
#define ALLOW_UNDO 1 #define ALLOW_UNDO 1
#define ALLOW_UNDO_CHAIN 2 #define ALLOW_UNDO_CHAIN 2
# if ENABLE_FEATURE_VI_UNDO_QUEUE # if ENABLE_FEATURE_VI_UNDO_QUEUE
#define ALLOW_UNDO_QUEUED 3 #define ALLOW_UNDO_QUEUED 3
char undo_queue_state; # else
// If undo queuing disabled, don't invoke the missing queue logic
#define ALLOW_UNDO_QUEUED ALLOW_UNDO
# endif
# if ENABLE_FEATURE_VI_UNDO_QUEUE
#define UNDO_USE_SPOS 32
#define UNDO_EMPTY 64
char undo_queue_state; // One of UNDO_INS, UNDO_DEL, UNDO_EMPTY
int undo_q; int undo_q;
char *undo_queue_spos; // Start position of queued operation char *undo_queue_spos; // Start position of queued operation
char undo_queue[CONFIG_FEATURE_VI_UNDO_QUEUE_MAX]; char undo_queue[CONFIG_FEATURE_VI_UNDO_QUEUE_MAX];
# else
// If undo queuing disabled, don't invoke the missing queue logic
#define ALLOW_UNDO_QUEUED 1
# endif # endif
struct undo_object { struct undo_object {
struct undo_object *prev; // Linking back avoids list traversal (LIFO) struct undo_object *prev; // Linking back avoids list traversal (LIFO)
int start; // Offset where the data should be restored/deleted int start; // Offset where the data should be restored/deleted
@ -1445,7 +1450,7 @@ static void yank_status(const char *op, const char *p, int cnt)
#endif /* FEATURE_VI_YANKMARK */ #endif /* FEATURE_VI_YANKMARK */
#if ENABLE_FEATURE_VI_UNDO #if ENABLE_FEATURE_VI_UNDO
static void undo_push(char *, unsigned, unsigned char); static void undo_push(char *, unsigned, int);
#endif #endif
// open a hole in text[] // open a hole in text[]
@ -1572,9 +1577,12 @@ static void flush_undo_data(void)
// Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com) // Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com)
// Add to the undo stack // Add to the undo stack
static void undo_push(char *src, unsigned length, uint8_t u_type) static void undo_push(char *src, unsigned length, int u_type)
{ {
struct undo_object *undo_entry; struct undo_object *undo_entry;
# if ENABLE_FEATURE_VI_UNDO_QUEUE
int use_spos = u_type & UNDO_USE_SPOS;
# endif
// "u_type" values // "u_type" values
// UNDO_INS: insertion, undo will remove from buffer // UNDO_INS: insertion, undo will remove from buffer
@ -1583,8 +1591,8 @@ static void undo_push(char *src, unsigned length, uint8_t u_type)
// The CHAIN operations are for handling multiple operations that the user // The CHAIN operations are for handling multiple operations that the user
// performs with a single action, i.e. REPLACE mode or find-and-replace commands // performs with a single action, i.e. REPLACE mode or find-and-replace commands
// UNDO_{INS,DEL}_QUEUED: If queuing feature is enabled, allow use of the queue // UNDO_{INS,DEL}_QUEUED: If queuing feature is enabled, allow use of the queue
// for the INS/DEL operation. The raw values should be equal to the values of // for the INS/DEL operation.
// UNDO_{INS,DEL} ORed with UNDO_QUEUED_FLAG // UNDO_{INS,DEL} ORed with UNDO_USE_SPOS: commit the undo queue
# if ENABLE_FEATURE_VI_UNDO_QUEUE # if ENABLE_FEATURE_VI_UNDO_QUEUE
// This undo queuing functionality groups multiple character typing or backspaces // This undo queuing functionality groups multiple character typing or backspaces
@ -1637,9 +1645,7 @@ static void undo_push(char *src, unsigned length, uint8_t u_type)
} }
break; break;
} }
# else u_type &= ~UNDO_USE_SPOS;
// If undo queuing is disabled, ignore the queuing flag entirely
u_type = u_type & ~UNDO_QUEUED_FLAG;
# endif # endif
// Allocate a new undo object // Allocate a new undo object
@ -1656,12 +1662,11 @@ static void undo_push(char *src, unsigned length, uint8_t u_type)
} }
undo_entry->length = length; undo_entry->length = length;
# if ENABLE_FEATURE_VI_UNDO_QUEUE # if ENABLE_FEATURE_VI_UNDO_QUEUE
if ((u_type & UNDO_USE_SPOS) != 0) { if (use_spos) {
undo_entry->start = undo_queue_spos - text; // use start position from queue undo_entry->start = undo_queue_spos - text; // use start position from queue
} else { } else {
undo_entry->start = src - text; // use offset from start of text buffer undo_entry->start = src - text; // use offset from start of text buffer
} }
u_type = (u_type & ~UNDO_USE_SPOS);
# else # else
undo_entry->start = src - text; undo_entry->start = src - text;
# endif # endif