diff options
author | Ron Yorston <rmy@pobox.com> | 2021-04-15 12:00:50 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-04-15 13:09:12 +0200 |
commit | 9b2a3895eedb3c46179b1ed923b0f1214da04c5b (patch) | |
tree | e6ef6bdf04d1e1aa46e426bcf50b6fd29ad3c5e7 | |
parent | c0943ac451051b734711b0c95731ae7c515dbb31 (diff) | |
download | busybox-w32-9b2a3895eedb3c46179b1ed923b0f1214da04c5b.tar.gz busybox-w32-9b2a3895eedb3c46179b1ed923b0f1214da04c5b.tar.bz2 busybox-w32-9b2a3895eedb3c46179b1ed923b0f1214da04c5b.zip |
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>
-rw-r--r-- | editors/vi.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/editors/vi.c b/editors/vi.c index 31b5d3e8a..fef328117 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -399,26 +399,31 @@ struct globals { | |||
399 | #define UNDO_DEL 1 | 399 | #define UNDO_DEL 1 |
400 | #define UNDO_INS_CHAIN 2 | 400 | #define UNDO_INS_CHAIN 2 |
401 | #define UNDO_DEL_CHAIN 3 | 401 | #define UNDO_DEL_CHAIN 3 |
402 | // UNDO_*_QUEUED must be equal to UNDO_xxx ORed with UNDO_QUEUED_FLAG | 402 | # if ENABLE_FEATURE_VI_UNDO_QUEUE |
403 | #define UNDO_QUEUED_FLAG 4 | ||
404 | #define UNDO_INS_QUEUED 4 | 403 | #define UNDO_INS_QUEUED 4 |
405 | #define UNDO_DEL_QUEUED 5 | 404 | #define UNDO_DEL_QUEUED 5 |
406 | #define UNDO_USE_SPOS 32 | 405 | # endif |
407 | #define UNDO_EMPTY 64 | 406 | |
408 | // Pass-through flags for functions that can be undone | 407 | // Pass-through flags for functions that can be undone |
409 | #define NO_UNDO 0 | 408 | #define NO_UNDO 0 |
410 | #define ALLOW_UNDO 1 | 409 | #define ALLOW_UNDO 1 |
411 | #define ALLOW_UNDO_CHAIN 2 | 410 | #define ALLOW_UNDO_CHAIN 2 |
412 | # if ENABLE_FEATURE_VI_UNDO_QUEUE | 411 | # if ENABLE_FEATURE_VI_UNDO_QUEUE |
413 | #define ALLOW_UNDO_QUEUED 3 | 412 | #define ALLOW_UNDO_QUEUED 3 |
414 | char undo_queue_state; | 413 | # else |
414 | // If undo queuing disabled, don't invoke the missing queue logic | ||
415 | #define ALLOW_UNDO_QUEUED ALLOW_UNDO | ||
416 | # endif | ||
417 | |||
418 | # if ENABLE_FEATURE_VI_UNDO_QUEUE | ||
419 | #define UNDO_USE_SPOS 32 | ||
420 | #define UNDO_EMPTY 64 | ||
421 | char undo_queue_state; // One of UNDO_INS, UNDO_DEL, UNDO_EMPTY | ||
415 | int undo_q; | 422 | int undo_q; |
416 | char *undo_queue_spos; // Start position of queued operation | 423 | char *undo_queue_spos; // Start position of queued operation |
417 | char undo_queue[CONFIG_FEATURE_VI_UNDO_QUEUE_MAX]; | 424 | char undo_queue[CONFIG_FEATURE_VI_UNDO_QUEUE_MAX]; |
418 | # else | ||
419 | // If undo queuing disabled, don't invoke the missing queue logic | ||
420 | #define ALLOW_UNDO_QUEUED 1 | ||
421 | # endif | 425 | # endif |
426 | |||
422 | struct undo_object { | 427 | struct undo_object { |
423 | struct undo_object *prev; // Linking back avoids list traversal (LIFO) | 428 | struct undo_object *prev; // Linking back avoids list traversal (LIFO) |
424 | int start; // Offset where the data should be restored/deleted | 429 | 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) | |||
1445 | #endif /* FEATURE_VI_YANKMARK */ | 1450 | #endif /* FEATURE_VI_YANKMARK */ |
1446 | 1451 | ||
1447 | #if ENABLE_FEATURE_VI_UNDO | 1452 | #if ENABLE_FEATURE_VI_UNDO |
1448 | static void undo_push(char *, unsigned, unsigned char); | 1453 | static void undo_push(char *, unsigned, int); |
1449 | #endif | 1454 | #endif |
1450 | 1455 | ||
1451 | // open a hole in text[] | 1456 | // open a hole in text[] |
@@ -1572,9 +1577,12 @@ static void flush_undo_data(void) | |||
1572 | 1577 | ||
1573 | // Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com) | 1578 | // Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com) |
1574 | // Add to the undo stack | 1579 | // Add to the undo stack |
1575 | static void undo_push(char *src, unsigned length, uint8_t u_type) | 1580 | static void undo_push(char *src, unsigned length, int u_type) |
1576 | { | 1581 | { |
1577 | struct undo_object *undo_entry; | 1582 | struct undo_object *undo_entry; |
1583 | # if ENABLE_FEATURE_VI_UNDO_QUEUE | ||
1584 | int use_spos = u_type & UNDO_USE_SPOS; | ||
1585 | # endif | ||
1578 | 1586 | ||
1579 | // "u_type" values | 1587 | // "u_type" values |
1580 | // UNDO_INS: insertion, undo will remove from buffer | 1588 | // UNDO_INS: insertion, undo will remove from buffer |
@@ -1583,8 +1591,8 @@ static void undo_push(char *src, unsigned length, uint8_t u_type) | |||
1583 | // The CHAIN operations are for handling multiple operations that the user | 1591 | // The CHAIN operations are for handling multiple operations that the user |
1584 | // performs with a single action, i.e. REPLACE mode or find-and-replace commands | 1592 | // performs with a single action, i.e. REPLACE mode or find-and-replace commands |
1585 | // UNDO_{INS,DEL}_QUEUED: If queuing feature is enabled, allow use of the queue | 1593 | // UNDO_{INS,DEL}_QUEUED: If queuing feature is enabled, allow use of the queue |
1586 | // for the INS/DEL operation. The raw values should be equal to the values of | 1594 | // for the INS/DEL operation. |
1587 | // UNDO_{INS,DEL} ORed with UNDO_QUEUED_FLAG | 1595 | // UNDO_{INS,DEL} ORed with UNDO_USE_SPOS: commit the undo queue |
1588 | 1596 | ||
1589 | # if ENABLE_FEATURE_VI_UNDO_QUEUE | 1597 | # if ENABLE_FEATURE_VI_UNDO_QUEUE |
1590 | // This undo queuing functionality groups multiple character typing or backspaces | 1598 | // 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) | |||
1637 | } | 1645 | } |
1638 | break; | 1646 | break; |
1639 | } | 1647 | } |
1640 | # else | 1648 | u_type &= ~UNDO_USE_SPOS; |
1641 | // If undo queuing is disabled, ignore the queuing flag entirely | ||
1642 | u_type = u_type & ~UNDO_QUEUED_FLAG; | ||
1643 | # endif | 1649 | # endif |
1644 | 1650 | ||
1645 | // Allocate a new undo object | 1651 | // Allocate a new undo object |
@@ -1656,12 +1662,11 @@ static void undo_push(char *src, unsigned length, uint8_t u_type) | |||
1656 | } | 1662 | } |
1657 | undo_entry->length = length; | 1663 | undo_entry->length = length; |
1658 | # if ENABLE_FEATURE_VI_UNDO_QUEUE | 1664 | # if ENABLE_FEATURE_VI_UNDO_QUEUE |
1659 | if ((u_type & UNDO_USE_SPOS) != 0) { | 1665 | if (use_spos) { |
1660 | undo_entry->start = undo_queue_spos - text; // use start position from queue | 1666 | undo_entry->start = undo_queue_spos - text; // use start position from queue |
1661 | } else { | 1667 | } else { |
1662 | undo_entry->start = src - text; // use offset from start of text buffer | 1668 | undo_entry->start = src - text; // use offset from start of text buffer |
1663 | } | 1669 | } |
1664 | u_type = (u_type & ~UNDO_USE_SPOS); | ||
1665 | # else | 1670 | # else |
1666 | undo_entry->start = src - text; | 1671 | undo_entry->start = src - text; |
1667 | # endif | 1672 | # endif |