vi: undo code shrink

function                                             old     new   delta
undo_push                                            414     395     -19
do_cmd                                              4803    4761     -42

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
1_23_stable
Denys Vlasenko 2014-04-03 01:45:05 +02:00
parent a8d6f9bee4
commit 2c51202aec
1 changed files with 42 additions and 41 deletions

View File

@ -2209,7 +2209,8 @@ static void showmatching(char *p)
// Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com) // Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com)
static void undo_push(char *src, unsigned int length, unsigned char u_type) // Add to the undo stack static void undo_push(char *src, unsigned int length, unsigned char u_type) // Add to the undo stack
{ {
struct undo_object *undo_temp; struct undo_object *undo_entry;
// "u_type" values // "u_type" values
// UNDO_INS: insertion, undo will remove from buffer // UNDO_INS: insertion, undo will remove from buffer
// UNDO_DEL: deleted text, undo will restore to buffer // UNDO_DEL: deleted text, undo will restore to buffer
@ -2237,7 +2238,7 @@ static void undo_push(char *src, unsigned int length, unsigned char u_type) // A
case UNDO_DEL: case UNDO_DEL:
undo_queue_spos = src; undo_queue_spos = src;
undo_q++; undo_q++;
undo_queue[(CONFIG_FEATURE_VI_UNDO_QUEUE_MAX - undo_q)] = *src; undo_queue[CONFIG_FEATURE_VI_UNDO_QUEUE_MAX - undo_q] = *src;
// If queue is full, dump it into an object // If queue is full, dump it into an object
if (undo_q == CONFIG_FEATURE_VI_UNDO_QUEUE_MAX) if (undo_q == CONFIG_FEATURE_VI_UNDO_QUEUE_MAX)
undo_queue_commit(); undo_queue_commit();
@ -2275,80 +2276,80 @@ static void undo_push(char *src, unsigned int length, unsigned char u_type) // A
#endif #endif
// Allocate a new undo object and use it as the stack tail // Allocate a new undo object and use it as the stack tail
undo_temp = undo_stack_tail; undo_entry = xzalloc(sizeof(*undo_entry));
undo_stack_tail = xmalloc(sizeof(struct undo_object)); undo_entry->prev = undo_stack_tail;
undo_stack_tail = undo_entry;
#if ENABLE_FEATURE_VI_UNDO_QUEUE #if ENABLE_FEATURE_VI_UNDO_QUEUE
if ((u_type & UNDO_USE_SPOS) != 0) { if ((u_type & UNDO_USE_SPOS) != 0) {
undo_stack_tail->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_stack_tail->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); u_type = (u_type & ~UNDO_USE_SPOS);
#else #else
undo_stack_tail->start = src - text; undo_entry->start = src - text;
#endif /* ENABLE_FEATURE_VI_UNDO_QUEUE */ #endif
// For UNDO_DEL objects, copy the deleted text somewhere // For UNDO_DEL objects, copy the deleted text somewhere
switch (u_type) { undo_entry->u_type = u_type;
case UNDO_DEL: if (u_type == UNDO_DEL || u_type == UNDO_DEL_CHAIN) {
case UNDO_DEL_CHAIN: if ((src + length) == end)
if ((src + length) == end) length--;
length--; // If this deletion empties text[], strip the newline. When the buffer becomes
// If this deletion empties text[], strip the newline. When the buffer becomes // zero-length, a newline is added back, which requires this to compensate.
// zero-length, a newline is added back, which requires this to compensate. undo_entry->undo_text = xmalloc(length);
undo_stack_tail->undo_text = xmalloc(length); memcpy(undo_entry->undo_text, src, length);
memcpy(undo_stack_tail->undo_text, src, length);
break;
} }
undo_stack_tail->prev = undo_temp; undo_entry->length = length;
undo_stack_tail->length = length;
undo_stack_tail->u_type = u_type;
file_modified++; file_modified++;
} }
static void undo_pop(void) // Undo the last operation static void undo_pop(void) // Undo the last operation
{ {
int repeat = 0; int repeat;
char *u_start, *u_end; char *u_start, *u_end;
struct undo_object *undo_temp; struct undo_object *undo_entry;
// Commit pending undo queue before popping (should be unnecessary) // Commit pending undo queue before popping (should be unnecessary)
undo_queue_commit(); undo_queue_commit();
undo_entry = undo_stack_tail;
// Check for an empty undo stack // Check for an empty undo stack
if (undo_stack_tail == NULL) { if (!undo_entry) {
status_line("Already at oldest change"); status_line("Already at oldest change");
return; return;
} }
switch (undo_stack_tail->u_type) { switch (undo_entry->u_type) {
case UNDO_DEL: case UNDO_DEL:
case UNDO_DEL_CHAIN: case UNDO_DEL_CHAIN:
// make hole and put in text that was deleted; deallocate text // make hole and put in text that was deleted; deallocate text
u_start = text + undo_stack_tail->start; u_start = text + undo_entry->start;
text_hole_make(u_start, undo_stack_tail->length); text_hole_make(u_start, undo_entry->length);
memcpy(u_start, undo_stack_tail->undo_text, undo_stack_tail->length); memcpy(u_start, undo_entry->undo_text, undo_entry->length);
free(undo_stack_tail->undo_text); free(undo_entry->undo_text);
status_line("Undo [%d] %s %d chars at position %d", status_line("Undo [%d] %s %d chars at position %d",
file_modified, "restored", file_modified, "restored",
undo_stack_tail->length, undo_stack_tail->start); undo_entry->length, undo_entry->start
);
break; break;
case UNDO_INS: case UNDO_INS:
case UNDO_INS_CHAIN: case UNDO_INS_CHAIN:
// delete what was inserted // delete what was inserted
u_start = undo_stack_tail->start + text; u_start = undo_entry->start + text;
u_end = u_start - 1 + undo_stack_tail->length; u_end = u_start - 1 + undo_entry->length;
text_hole_delete(u_start, u_end, NO_UNDO); text_hole_delete(u_start, u_end, NO_UNDO);
status_line("Undo [%d] %s %d chars at position %d", status_line("Undo [%d] %s %d chars at position %d",
file_modified, "deleted", file_modified, "deleted",
undo_stack_tail->length, undo_stack_tail->start); undo_entry->length, undo_entry->start
);
break; break;
} }
// For chained operations, continue popping all the way down the chain. repeat = 0;
switch (undo_entry->u_type) {
// If this is the end of a chain, lower modification count and refresh display // If this is the end of a chain, lower modification count and refresh display
switch (undo_stack_tail->u_type) {
case UNDO_DEL: case UNDO_DEL:
case UNDO_INS: case UNDO_INS:
dot = (text + undo_stack_tail->start); dot = (text + undo_entry->start);
refresh(FALSE); refresh(FALSE);
break; break;
case UNDO_DEL_CHAIN: case UNDO_DEL_CHAIN:
@ -2357,11 +2358,11 @@ static void undo_pop(void) // Undo the last operation
break; break;
} }
// Deallocate the undo object we just processed // Deallocate the undo object we just processed
undo_temp = undo_stack_tail->prev; undo_stack_tail = undo_entry->prev;
free(undo_stack_tail); free(undo_entry);
undo_stack_tail = undo_temp;
file_modified--; file_modified--;
if (repeat == 1) { // For chained operations, continue popping all the way down the chain.
if (repeat) {
undo_pop(); // Follow the undo chain if one exists undo_pop(); // Follow the undo chain if one exists
} }
} }
@ -2372,7 +2373,7 @@ static void undo_queue_commit(void) // Flush any queued objects to the undo stac
// Pushes the queue object onto the undo stack // Pushes the queue object onto the undo stack
if (undo_q > 0) { if (undo_q > 0) {
// Deleted character undo events grow from the end // Deleted character undo events grow from the end
undo_push((undo_queue + CONFIG_FEATURE_VI_UNDO_QUEUE_MAX - undo_q), undo_push(undo_queue + CONFIG_FEATURE_VI_UNDO_QUEUE_MAX - undo_q,
undo_q, undo_q,
(undo_queue_state | UNDO_USE_SPOS) (undo_queue_state | UNDO_USE_SPOS)
); );