diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2014-04-03 12:47:48 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2014-04-03 12:47:48 +0200 |
commit | e7430867a8ad61bbea20d05fc2f9fc5094e211dc (patch) | |
tree | 37f07ce0e23ef16f78df1c5e1dca0bddc7ff3c2d | |
parent | 2c51202aece44d0f72b7d496ac94823e10d08d54 (diff) | |
download | busybox-w32-e7430867a8ad61bbea20d05fc2f9fc5094e211dc.tar.gz busybox-w32-e7430867a8ad61bbea20d05fc2f9fc5094e211dc.tar.bz2 busybox-w32-e7430867a8ad61bbea20d05fc2f9fc5094e211dc.zip |
vi: clear undo buffer when we change to another file
function old new delta
init_text_buffer 156 190 +34
undo_push 360 382 +22
count_lines 74 72 -2
undo_pop 246 222 -24
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/2 up/down: 56/-26) Total: 30 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 156 |
1 files changed, 87 insertions, 69 deletions
diff --git a/editors/vi.c b/editors/vi.c index 71086c901..a978e0fcb 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -306,8 +306,8 @@ struct globals { | |||
306 | smallint editing; // >0 while we are editing a file | 306 | smallint editing; // >0 while we are editing a file |
307 | // [code audit says "can be 0, 1 or 2 only"] | 307 | // [code audit says "can be 0, 1 or 2 only"] |
308 | smallint cmd_mode; // 0=command 1=insert 2=replace | 308 | smallint cmd_mode; // 0=command 1=insert 2=replace |
309 | int file_modified; // buffer contents changed (counter, not flag!) | 309 | int modified_count; // buffer contents changed if !0 |
310 | int last_file_modified; // = -1; | 310 | int last_modified_count; // = -1; |
311 | int save_argc; // how many file names on cmd line | 311 | int save_argc; // how many file names on cmd line |
312 | int cmdcnt; // repetition count | 312 | int cmdcnt; // repetition count |
313 | unsigned rows, columns; // the terminal screen is this size | 313 | unsigned rows, columns; // the terminal screen is this size |
@@ -378,37 +378,37 @@ struct globals { | |||
378 | char scr_out_buf[MAX_SCR_COLS + MAX_TABSTOP * 2]; | 378 | char scr_out_buf[MAX_SCR_COLS + MAX_TABSTOP * 2]; |
379 | #if ENABLE_FEATURE_VI_UNDO | 379 | #if ENABLE_FEATURE_VI_UNDO |
380 | // undo_push() operations | 380 | // undo_push() operations |
381 | #define UNDO_INS 0 | 381 | #define UNDO_INS 0 |
382 | #define UNDO_DEL 1 | 382 | #define UNDO_DEL 1 |
383 | #define UNDO_INS_CHAIN 2 | 383 | #define UNDO_INS_CHAIN 2 |
384 | #define UNDO_DEL_CHAIN 3 | 384 | #define UNDO_DEL_CHAIN 3 |
385 | // UNDO_*_QUEUED must be equal to UNDO_xxx ORed with UNDO_QUEUED_FLAG | 385 | // UNDO_*_QUEUED must be equal to UNDO_xxx ORed with UNDO_QUEUED_FLAG |
386 | #define UNDO_QUEUED_FLAG 4 | 386 | #define UNDO_QUEUED_FLAG 4 |
387 | #define UNDO_INS_QUEUED 4 | 387 | #define UNDO_INS_QUEUED 4 |
388 | #define UNDO_DEL_QUEUED 5 | 388 | #define UNDO_DEL_QUEUED 5 |
389 | #define UNDO_USE_SPOS 32 | 389 | #define UNDO_USE_SPOS 32 |
390 | #define UNDO_EMPTY 64 | 390 | #define UNDO_EMPTY 64 |
391 | // Pass-through flags for functions that can be undone | 391 | // Pass-through flags for functions that can be undone |
392 | #define NO_UNDO 0 | 392 | #define NO_UNDO 0 |
393 | #define ALLOW_UNDO 1 | 393 | #define ALLOW_UNDO 1 |
394 | #define ALLOW_UNDO_CHAIN 2 | 394 | #define ALLOW_UNDO_CHAIN 2 |
395 | #if ENABLE_FEATURE_VI_UNDO_QUEUE | 395 | # if ENABLE_FEATURE_VI_UNDO_QUEUE |
396 | #define ALLOW_UNDO_QUEUED 3 | 396 | #define ALLOW_UNDO_QUEUED 3 |
397 | char undo_queue_state; | 397 | char undo_queue_state; |
398 | int undo_q; | 398 | int undo_q; |
399 | char *undo_queue_spos; // Start position of queued operation | 399 | char *undo_queue_spos; // Start position of queued operation |
400 | char undo_queue[CONFIG_FEATURE_VI_UNDO_QUEUE_MAX]; | 400 | char undo_queue[CONFIG_FEATURE_VI_UNDO_QUEUE_MAX]; |
401 | #else | 401 | # else |
402 | // If undo queuing disabled, don't invoke the missing queue logic | 402 | // If undo queuing disabled, don't invoke the missing queue logic |
403 | #define ALLOW_UNDO_QUEUED 1 | 403 | #define ALLOW_UNDO_QUEUED 1 |
404 | #endif /* ENABLE_FEATURE_VI_UNDO_QUEUE */ | 404 | # endif |
405 | 405 | ||
406 | struct undo_object { | 406 | struct undo_object { |
407 | struct undo_object *prev; // Linking back avoids list traversal (LIFO) | 407 | struct undo_object *prev; // Linking back avoids list traversal (LIFO) |
408 | int u_type; // 0=deleted, 1=inserted, 2=swapped | ||
409 | int start; // Offset where the data should be restored/deleted | 408 | int start; // Offset where the data should be restored/deleted |
410 | int length; // total data size | 409 | int length; // total data size |
411 | char *undo_text; // ptr to text that will be inserted | 410 | uint8_t u_type; // 0=deleted, 1=inserted, 2=swapped |
411 | char undo_text[1]; // text that was deleted (if deletion) | ||
412 | } *undo_stack_tail; | 412 | } *undo_stack_tail; |
413 | #endif /* ENABLE_FEATURE_VI_UNDO */ | 413 | #endif /* ENABLE_FEATURE_VI_UNDO */ |
414 | 414 | ||
@@ -423,8 +423,8 @@ struct globals { | |||
423 | #define vi_setops (G.vi_setops ) | 423 | #define vi_setops (G.vi_setops ) |
424 | #define editing (G.editing ) | 424 | #define editing (G.editing ) |
425 | #define cmd_mode (G.cmd_mode ) | 425 | #define cmd_mode (G.cmd_mode ) |
426 | #define file_modified (G.file_modified ) | 426 | #define modified_count (G.modified_count ) |
427 | #define last_file_modified (G.last_file_modified ) | 427 | #define last_modified_count (G.last_modified_count) |
428 | #define save_argc (G.save_argc ) | 428 | #define save_argc (G.save_argc ) |
429 | #define cmdcnt (G.cmdcnt ) | 429 | #define cmdcnt (G.cmdcnt ) |
430 | #define rows (G.rows ) | 430 | #define rows (G.rows ) |
@@ -485,7 +485,7 @@ struct globals { | |||
485 | 485 | ||
486 | #define INIT_G() do { \ | 486 | #define INIT_G() do { \ |
487 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 487 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
488 | last_file_modified = -1; \ | 488 | last_modified_count = -1; \ |
489 | /* "" but has space for 2 chars: */ \ | 489 | /* "" but has space for 2 chars: */ \ |
490 | IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \ | 490 | IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \ |
491 | } while (0) | 491 | } while (0) |
@@ -608,6 +608,7 @@ static char what_reg(void); // what is letter of current YDreg | |||
608 | static void check_context(char); // remember context for '' command | 608 | static void check_context(char); // remember context for '' command |
609 | #endif | 609 | #endif |
610 | #if ENABLE_FEATURE_VI_UNDO | 610 | #if ENABLE_FEATURE_VI_UNDO |
611 | static void flush_undo_data(void); | ||
611 | static void undo_push(char *, unsigned int, unsigned char); // Push an operation on the undo stack | 612 | static void undo_push(char *, unsigned int, unsigned char); // Push an operation on the undo stack |
612 | static void undo_pop(void); // Undo the last operation | 613 | static void undo_pop(void); // Undo the last operation |
613 | # if ENABLE_FEATURE_VI_UNDO_QUEUE | 614 | # if ENABLE_FEATURE_VI_UNDO_QUEUE |
@@ -616,6 +617,7 @@ static void undo_queue_commit(void); // Flush any queued objects to the undo sta | |||
616 | # define undo_queue_commit() ((void)0) | 617 | # define undo_queue_commit() ((void)0) |
617 | # endif | 618 | # endif |
618 | #else | 619 | #else |
620 | #define flush_undo_data() ((void)0) | ||
619 | #define undo_queue_commit() ((void)0) | 621 | #define undo_queue_commit() ((void)0) |
620 | #endif | 622 | #endif |
621 | 623 | ||
@@ -725,6 +727,8 @@ static int init_text_buffer(char *fn) | |||
725 | int rc; | 727 | int rc; |
726 | int size = file_size(fn); // file size. -1 means does not exist. | 728 | int size = file_size(fn); // file size. -1 means does not exist. |
727 | 729 | ||
730 | flush_undo_data(); | ||
731 | |||
728 | /* allocate/reallocate text buffer */ | 732 | /* allocate/reallocate text buffer */ |
729 | free(text); | 733 | free(text); |
730 | text_size = size + 10240; | 734 | text_size = size + 10240; |
@@ -735,14 +739,14 @@ static int init_text_buffer(char *fn) | |||
735 | current_filename = xstrdup(fn); | 739 | current_filename = xstrdup(fn); |
736 | } | 740 | } |
737 | if (size < 0) { | 741 | if (size < 0) { |
738 | // file dont exist. Start empty buf with dummy line | 742 | // file doesnt exist. Start empty buf with dummy line |
739 | char_insert(text, '\n', NO_UNDO); | 743 | char_insert(text, '\n', NO_UNDO); |
740 | rc = 0; | 744 | rc = 0; |
741 | } else { | 745 | } else { |
742 | rc = file_insert(fn, text, 1); | 746 | rc = file_insert(fn, text, 1); |
743 | } | 747 | } |
744 | file_modified = 0; | 748 | modified_count = 0; |
745 | last_file_modified = -1; | 749 | last_modified_count = -1; |
746 | #if ENABLE_FEATURE_VI_YANKMARK | 750 | #if ENABLE_FEATURE_VI_YANKMARK |
747 | /* init the marks. */ | 751 | /* init the marks. */ |
748 | memset(mark, 0, sizeof(mark)); | 752 | memset(mark, 0, sizeof(mark)); |
@@ -1124,7 +1128,7 @@ static void colon(char *buf) | |||
1124 | dot_skip_over_ws(); | 1128 | dot_skip_over_ws(); |
1125 | } else if (strncmp(cmd, "edit", i) == 0) { // Edit a file | 1129 | } else if (strncmp(cmd, "edit", i) == 0) { // Edit a file |
1126 | // don't edit, if the current file has been modified | 1130 | // don't edit, if the current file has been modified |
1127 | if (file_modified && !useforce) { | 1131 | if (modified_count && !useforce) { |
1128 | status_line_bold("No write since last change (:%s! overrides)", cmd); | 1132 | status_line_bold("No write since last change (:%s! overrides)", cmd); |
1129 | goto ret; | 1133 | goto ret; |
1130 | } | 1134 | } |
@@ -1227,7 +1231,7 @@ static void colon(char *buf) | |||
1227 | goto ret; | 1231 | goto ret; |
1228 | } | 1232 | } |
1229 | // don't exit if the file been modified | 1233 | // don't exit if the file been modified |
1230 | if (file_modified) { | 1234 | if (modified_count) { |
1231 | status_line_bold("No write since last change (:%s! overrides)", cmd); | 1235 | status_line_bold("No write since last change (:%s! overrides)", cmd); |
1232 | goto ret; | 1236 | goto ret; |
1233 | } | 1237 | } |
@@ -1280,10 +1284,10 @@ static void colon(char *buf) | |||
1280 | // if the insert is before "dot" then we need to update | 1284 | // if the insert is before "dot" then we need to update |
1281 | if (q <= dot) | 1285 | if (q <= dot) |
1282 | dot += ch; | 1286 | dot += ch; |
1283 | // file_modified++; | 1287 | // modified_count++; |
1284 | } | 1288 | } |
1285 | } else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args | 1289 | } else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args |
1286 | if (file_modified && !useforce) { | 1290 | if (modified_count && !useforce) { |
1287 | status_line_bold("No write since last change (:%s! overrides)", cmd); | 1291 | status_line_bold("No write since last change (:%s! overrides)", cmd); |
1288 | } else { | 1292 | } else { |
1289 | // reset the filenames to edit | 1293 | // reset the filenames to edit |
@@ -1438,8 +1442,8 @@ static void colon(char *buf) | |||
1438 | } else { | 1442 | } else { |
1439 | status_line("'%s' %dL, %dC", fn, li, l); | 1443 | status_line("'%s' %dL, %dC", fn, li, l); |
1440 | if (q == text && r == end - 1 && l == ch) { | 1444 | if (q == text && r == end - 1 && l == ch) { |
1441 | file_modified = 0; | 1445 | modified_count = 0; |
1442 | last_file_modified = -1; | 1446 | last_modified_count = -1; |
1443 | } | 1447 | } |
1444 | if ((cmd[0] == 'x' || cmd[1] == 'q' || cmd[1] == 'n' | 1448 | if ((cmd[0] == 'x' || cmd[1] == 'q' || cmd[1] == 'n' |
1445 | || cmd[0] == 'X' || cmd[1] == 'Q' || cmd[1] == 'N' | 1449 | || cmd[0] == 'X' || cmd[1] == 'Q' || cmd[1] == 'N' |
@@ -1940,7 +1944,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | |||
1940 | # endif | 1944 | # endif |
1941 | } | 1945 | } |
1942 | #else | 1946 | #else |
1943 | file_modified++; | 1947 | modified_count++; |
1944 | #endif /* ENABLE_FEATURE_VI_UNDO */ | 1948 | #endif /* ENABLE_FEATURE_VI_UNDO */ |
1945 | p++; | 1949 | p++; |
1946 | } else if (c == 27) { // Is this an ESC? | 1950 | } else if (c == 27) { // Is this an ESC? |
@@ -1988,7 +1992,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | |||
1988 | # endif | 1992 | # endif |
1989 | } | 1993 | } |
1990 | #else | 1994 | #else |
1991 | file_modified++; | 1995 | modified_count++; |
1992 | #endif /* ENABLE_FEATURE_VI_UNDO */ | 1996 | #endif /* ENABLE_FEATURE_VI_UNDO */ |
1993 | p += 1 + stupid_insert(p, c); // insert the char | 1997 | p += 1 + stupid_insert(p, c); // insert the char |
1994 | #if ENABLE_FEATURE_VI_SETOPTS | 1998 | #if ENABLE_FEATURE_VI_SETOPTS |
@@ -2206,8 +2210,19 @@ static void showmatching(char *p) | |||
2206 | #endif /* FEATURE_VI_SETOPTS */ | 2210 | #endif /* FEATURE_VI_SETOPTS */ |
2207 | 2211 | ||
2208 | #if ENABLE_FEATURE_VI_UNDO | 2212 | #if ENABLE_FEATURE_VI_UNDO |
2213 | static void flush_undo_data(void) | ||
2214 | { | ||
2215 | struct undo_object *undo_entry; | ||
2216 | |||
2217 | while (undo_stack_tail) { | ||
2218 | undo_entry = undo_stack_tail; | ||
2219 | undo_stack_tail = undo_entry->prev; | ||
2220 | free(undo_entry); | ||
2221 | } | ||
2222 | } | ||
2223 | |||
2209 | // Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com) | 2224 | // Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com) |
2210 | static void undo_push(char *src, unsigned int length, unsigned char u_type) // Add to the undo stack | 2225 | static void undo_push(char *src, unsigned int length, uint8_t u_type) // Add to the undo stack |
2211 | { | 2226 | { |
2212 | struct undo_object *undo_entry; | 2227 | struct undo_object *undo_entry; |
2213 | 2228 | ||
@@ -2275,10 +2290,19 @@ static void undo_push(char *src, unsigned int length, unsigned char u_type) // A | |||
2275 | u_type = u_type & ~UNDO_QUEUED_FLAG; | 2290 | u_type = u_type & ~UNDO_QUEUED_FLAG; |
2276 | #endif | 2291 | #endif |
2277 | 2292 | ||
2278 | // Allocate a new undo object and use it as the stack tail | 2293 | // Allocate a new undo object |
2279 | undo_entry = xzalloc(sizeof(*undo_entry)); | 2294 | if (u_type == UNDO_DEL || u_type == UNDO_DEL_CHAIN) { |
2280 | undo_entry->prev = undo_stack_tail; | 2295 | // For UNDO_DEL objects, save deleted text |
2281 | undo_stack_tail = undo_entry; | 2296 | if ((src + length) == end) |
2297 | length--; | ||
2298 | // If this deletion empties text[], strip the newline. When the buffer becomes | ||
2299 | // zero-length, a newline is added back, which requires this to compensate. | ||
2300 | undo_entry = xzalloc(offsetof(struct undo_object, undo_text) + length); | ||
2301 | memcpy(undo_entry->undo_text, src, length); | ||
2302 | } else { | ||
2303 | undo_entry = xzalloc(sizeof(*undo_entry)); | ||
2304 | } | ||
2305 | undo_entry->length = length; | ||
2282 | #if ENABLE_FEATURE_VI_UNDO_QUEUE | 2306 | #if ENABLE_FEATURE_VI_UNDO_QUEUE |
2283 | if ((u_type & UNDO_USE_SPOS) != 0) { | 2307 | if ((u_type & UNDO_USE_SPOS) != 0) { |
2284 | undo_entry->start = undo_queue_spos - text; // use start position from queue | 2308 | undo_entry->start = undo_queue_spos - text; // use start position from queue |
@@ -2289,18 +2313,12 @@ static void undo_push(char *src, unsigned int length, unsigned char u_type) // A | |||
2289 | #else | 2313 | #else |
2290 | undo_entry->start = src - text; | 2314 | undo_entry->start = src - text; |
2291 | #endif | 2315 | #endif |
2292 | // For UNDO_DEL objects, copy the deleted text somewhere | ||
2293 | undo_entry->u_type = u_type; | 2316 | undo_entry->u_type = u_type; |
2294 | if (u_type == UNDO_DEL || u_type == UNDO_DEL_CHAIN) { | 2317 | |
2295 | if ((src + length) == end) | 2318 | // Push it on undo stack |
2296 | length--; | 2319 | undo_entry->prev = undo_stack_tail; |
2297 | // If this deletion empties text[], strip the newline. When the buffer becomes | 2320 | undo_stack_tail = undo_entry; |
2298 | // zero-length, a newline is added back, which requires this to compensate. | 2321 | modified_count++; |
2299 | undo_entry->undo_text = xmalloc(length); | ||
2300 | memcpy(undo_entry->undo_text, src, length); | ||
2301 | } | ||
2302 | undo_entry->length = length; | ||
2303 | file_modified++; | ||
2304 | } | 2322 | } |
2305 | 2323 | ||
2306 | static void undo_pop(void) // Undo the last operation | 2324 | static void undo_pop(void) // Undo the last operation |
@@ -2326,9 +2344,8 @@ static void undo_pop(void) // Undo the last operation | |||
2326 | u_start = text + undo_entry->start; | 2344 | u_start = text + undo_entry->start; |
2327 | text_hole_make(u_start, undo_entry->length); | 2345 | text_hole_make(u_start, undo_entry->length); |
2328 | memcpy(u_start, undo_entry->undo_text, undo_entry->length); | 2346 | memcpy(u_start, undo_entry->undo_text, undo_entry->length); |
2329 | free(undo_entry->undo_text); | ||
2330 | status_line("Undo [%d] %s %d chars at position %d", | 2347 | status_line("Undo [%d] %s %d chars at position %d", |
2331 | file_modified, "restored", | 2348 | modified_count, "restored", |
2332 | undo_entry->length, undo_entry->start | 2349 | undo_entry->length, undo_entry->start |
2333 | ); | 2350 | ); |
2334 | break; | 2351 | break; |
@@ -2339,7 +2356,7 @@ static void undo_pop(void) // Undo the last operation | |||
2339 | u_end = u_start - 1 + undo_entry->length; | 2356 | u_end = u_start - 1 + undo_entry->length; |
2340 | text_hole_delete(u_start, u_end, NO_UNDO); | 2357 | text_hole_delete(u_start, u_end, NO_UNDO); |
2341 | status_line("Undo [%d] %s %d chars at position %d", | 2358 | status_line("Undo [%d] %s %d chars at position %d", |
2342 | file_modified, "deleted", | 2359 | modified_count, "deleted", |
2343 | undo_entry->length, undo_entry->start | 2360 | undo_entry->length, undo_entry->start |
2344 | ); | 2361 | ); |
2345 | break; | 2362 | break; |
@@ -2360,7 +2377,7 @@ static void undo_pop(void) // Undo the last operation | |||
2360 | // Deallocate the undo object we just processed | 2377 | // Deallocate the undo object we just processed |
2361 | undo_stack_tail = undo_entry->prev; | 2378 | undo_stack_tail = undo_entry->prev; |
2362 | free(undo_entry); | 2379 | free(undo_entry); |
2363 | file_modified--; | 2380 | modified_count--; |
2364 | // For chained operations, continue popping all the way down the chain. | 2381 | // For chained operations, continue popping all the way down the chain. |
2365 | if (repeat) { | 2382 | if (repeat) { |
2366 | undo_pop(); // Follow the undo chain if one exists | 2383 | undo_pop(); // Follow the undo chain if one exists |
@@ -2452,13 +2469,13 @@ static char *text_hole_delete(char *p, char *q, int undo) // delete "p" through | |||
2452 | break; | 2469 | break; |
2453 | # endif | 2470 | # endif |
2454 | } | 2471 | } |
2455 | file_modified--; | 2472 | modified_count--; |
2456 | #endif | 2473 | #endif |
2457 | if (src < text || src > end) | 2474 | if (src < text || src > end) |
2458 | goto thd0; | 2475 | goto thd0; |
2459 | if (dest < text || dest >= end) | 2476 | if (dest < text || dest >= end) |
2460 | goto thd0; | 2477 | goto thd0; |
2461 | file_modified++; | 2478 | modified_count++; |
2462 | if (src >= end) | 2479 | if (src >= end) |
2463 | goto thd_atend; // just delete the end of the buffer | 2480 | goto thd_atend; // just delete the end of the buffer |
2464 | memmove(dest, src, cnt); | 2481 | memmove(dest, src, cnt); |
@@ -2885,7 +2902,7 @@ static int file_insert(const char *fn, char *p, int update_ro_status) | |||
2885 | status_line_bold("can't read '%s'", fn); | 2902 | status_line_bold("can't read '%s'", fn); |
2886 | } | 2903 | } |
2887 | // if (cnt >= size) | 2904 | // if (cnt >= size) |
2888 | // file_modified++; | 2905 | // modified_count++; |
2889 | close(fd); | 2906 | close(fd); |
2890 | fi0: | 2907 | fi0: |
2891 | #if ENABLE_FEATURE_VI_READONLY | 2908 | #if ENABLE_FEATURE_VI_READONLY |
@@ -2922,7 +2939,7 @@ static int file_write(char *fn, char *first, char *last) | |||
2922 | ftruncate(fd, charcnt); | 2939 | ftruncate(fd, charcnt); |
2923 | if (charcnt == cnt) { | 2940 | if (charcnt == cnt) { |
2924 | // good write | 2941 | // good write |
2925 | //file_modified = FALSE; | 2942 | //modified_count = FALSE; |
2926 | } else { | 2943 | } else { |
2927 | charcnt = 0; | 2944 | charcnt = 0; |
2928 | } | 2945 | } |
@@ -3144,7 +3161,7 @@ static int format_edit_status(void) | |||
3144 | 3161 | ||
3145 | int cur, percent, ret, trunc_at; | 3162 | int cur, percent, ret, trunc_at; |
3146 | 3163 | ||
3147 | // file_modified is now a counter rather than a flag. this | 3164 | // modified_count is now a counter rather than a flag. this |
3148 | // helps reduce the amount of line counting we need to do. | 3165 | // helps reduce the amount of line counting we need to do. |
3149 | // (this will cause a mis-reporting of modified status | 3166 | // (this will cause a mis-reporting of modified status |
3150 | // once every MAXINT editing operations.) | 3167 | // once every MAXINT editing operations.) |
@@ -3154,11 +3171,12 @@ static int format_edit_status(void) | |||
3154 | // we're on, then we shouldn't have to do this count_lines() | 3171 | // we're on, then we shouldn't have to do this count_lines() |
3155 | cur = count_lines(text, dot); | 3172 | cur = count_lines(text, dot); |
3156 | 3173 | ||
3157 | // reduce counting -- the total lines can't have | 3174 | // count_lines() is expensive. |
3158 | // changed if we haven't done any edits. | 3175 | // Call it only if something was changed since last time |
3159 | if (file_modified != last_file_modified) { | 3176 | // we were here: |
3177 | if (modified_count != last_modified_count) { | ||
3160 | tot = cur + count_lines(dot, end - 1) - 1; | 3178 | tot = cur + count_lines(dot, end - 1) - 1; |
3161 | last_file_modified = file_modified; | 3179 | last_modified_count = modified_count; |
3162 | } | 3180 | } |
3163 | 3181 | ||
3164 | // current line percent | 3182 | // current line percent |
@@ -3185,7 +3203,7 @@ static int format_edit_status(void) | |||
3185 | #if ENABLE_FEATURE_VI_READONLY | 3203 | #if ENABLE_FEATURE_VI_READONLY |
3186 | (readonly_mode ? " [Readonly]" : ""), | 3204 | (readonly_mode ? " [Readonly]" : ""), |
3187 | #endif | 3205 | #endif |
3188 | (file_modified ? " [Modified]" : ""), | 3206 | (modified_count ? " [Modified]" : ""), |
3189 | cur, tot, percent); | 3207 | cur, tot, percent); |
3190 | 3208 | ||
3191 | if (ret >= 0 && ret < trunc_at) | 3209 | if (ret >= 0 && ret < trunc_at) |
@@ -3814,7 +3832,7 @@ static void do_cmd(int c) | |||
3814 | if (strncmp(p, "quit", cnt) == 0 | 3832 | if (strncmp(p, "quit", cnt) == 0 |
3815 | || strncmp(p, "q!", cnt) == 0 // delete lines | 3833 | || strncmp(p, "q!", cnt) == 0 // delete lines |
3816 | ) { | 3834 | ) { |
3817 | if (file_modified && p[1] != '!') { | 3835 | if (modified_count && p[1] != '!') { |
3818 | status_line_bold("No write since last change (:%s! overrides)", p); | 3836 | status_line_bold("No write since last change (:%s! overrides)", p); |
3819 | } else { | 3837 | } else { |
3820 | editing = 0; | 3838 | editing = 0; |
@@ -3829,8 +3847,8 @@ static void do_cmd(int c) | |||
3829 | if (cnt == -1) | 3847 | if (cnt == -1) |
3830 | status_line_bold("Write error: %s", strerror(errno)); | 3848 | status_line_bold("Write error: %s", strerror(errno)); |
3831 | } else { | 3849 | } else { |
3832 | file_modified = 0; | 3850 | modified_count = 0; |
3833 | last_file_modified = -1; | 3851 | last_modified_count = -1; |
3834 | status_line("'%s' %dL, %dC", current_filename, count_lines(text, end - 1), cnt); | 3852 | status_line("'%s' %dL, %dC", current_filename, count_lines(text, end - 1), cnt); |
3835 | if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n' | 3853 | if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n' |
3836 | || p[0] == 'X' || p[1] == 'Q' || p[1] == 'N' | 3854 | || p[0] == 'X' || p[1] == 'Q' || p[1] == 'N' |
@@ -3963,7 +3981,7 @@ static void do_cmd(int c) | |||
3963 | undo_push((dot - 1), 1, UNDO_INS_CHAIN); | 3981 | undo_push((dot - 1), 1, UNDO_INS_CHAIN); |
3964 | #else | 3982 | #else |
3965 | *dot++ = ' '; | 3983 | *dot++ = ' '; |
3966 | file_modified++; | 3984 | modified_count++; |
3967 | #endif | 3985 | #endif |
3968 | while (isblank(*dot)) { // delete leading WS | 3986 | while (isblank(*dot)) { // delete leading WS |
3969 | text_hole_delete(dot, dot, ALLOW_UNDO_CHAIN); | 3987 | text_hole_delete(dot, dot, ALLOW_UNDO_CHAIN); |
@@ -4035,7 +4053,7 @@ static void do_cmd(int c) | |||
4035 | indicate_error(c); | 4053 | indicate_error(c); |
4036 | break; | 4054 | break; |
4037 | } | 4055 | } |
4038 | if (file_modified) { | 4056 | if (modified_count) { |
4039 | if (ENABLE_FEATURE_VI_READONLY && readonly_mode) { | 4057 | if (ENABLE_FEATURE_VI_READONLY && readonly_mode) { |
4040 | status_line_bold("'%s' is read only", current_filename); | 4058 | status_line_bold("'%s' is read only", current_filename); |
4041 | break; | 4059 | break; |
@@ -4172,7 +4190,7 @@ static void do_cmd(int c) | |||
4172 | undo_push(dot, 1, UNDO_INS_CHAIN); | 4190 | undo_push(dot, 1, UNDO_INS_CHAIN); |
4173 | #else | 4191 | #else |
4174 | *dot = c1; | 4192 | *dot = c1; |
4175 | file_modified++; | 4193 | modified_count++; |
4176 | #endif | 4194 | #endif |
4177 | } | 4195 | } |
4178 | end_cmd_q(); // stop adding to q | 4196 | end_cmd_q(); // stop adding to q |
@@ -4226,10 +4244,10 @@ static void do_cmd(int c) | |||
4226 | #else | 4244 | #else |
4227 | if (islower(*dot)) { | 4245 | if (islower(*dot)) { |
4228 | *dot = toupper(*dot); | 4246 | *dot = toupper(*dot); |
4229 | file_modified++; | 4247 | modified_count++; |
4230 | } else if (isupper(*dot)) { | 4248 | } else if (isupper(*dot)) { |
4231 | *dot = tolower(*dot); | 4249 | *dot = tolower(*dot); |
4232 | file_modified++; | 4250 | modified_count++; |
4233 | } | 4251 | } |
4234 | #endif | 4252 | #endif |
4235 | dot_right(); | 4253 | dot_right(); |