diff options
-rw-r--r-- | editors/vi.c | 182 |
1 files changed, 58 insertions, 124 deletions
diff --git a/editors/vi.c b/editors/vi.c index a07b68714..459f374f7 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -136,14 +136,6 @@ | |||
136 | //config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. | 136 | //config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. |
137 | //config: | 137 | //config: |
138 | //config: This is not clean but helps a lot on serial lines and such. | 138 | //config: This is not clean but helps a lot on serial lines and such. |
139 | //config: | ||
140 | //config:config FEATURE_VI_OPTIMIZE_CURSOR | ||
141 | //config: bool "Optimize cursor movement" | ||
142 | //config: default y | ||
143 | //config: depends on VI | ||
144 | //config: help | ||
145 | //config: This will make the cursor movement faster, but requires more memory | ||
146 | //config: and it makes the applet a tiny bit larger. | ||
147 | 139 | ||
148 | //applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP)) | 140 | //applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP)) |
149 | 141 | ||
@@ -202,20 +194,29 @@ enum { | |||
202 | MAX_SCR_ROWS = CONFIG_FEATURE_VI_MAX_LEN, | 194 | MAX_SCR_ROWS = CONFIG_FEATURE_VI_MAX_LEN, |
203 | }; | 195 | }; |
204 | 196 | ||
205 | /* vt102 typical ESC sequence */ | 197 | /* VT102 ESC sequences. |
206 | /* terminal standout start/normal ESC sequence */ | 198 | * See "Xterm Control Sequences" |
207 | #define SOs "\033[7m" | 199 | * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html |
208 | #define SOn "\033[0m" | 200 | */ |
209 | /* terminal bell sequence */ | 201 | /* Inverse/Normal text */ |
210 | #define bell "\007" | 202 | #define ESC_BOLD_TEXT "\033[7m" |
211 | /* Clear-end-of-line and Clear-end-of-screen ESC sequence */ | 203 | #define ESC_NORM_TEXT "\033[0m" |
212 | #define Ceol "\033[K" | 204 | /* Bell */ |
213 | #define Ceos "\033[J" | 205 | #define ESC_BELL "\007" |
214 | /* Cursor motion arbitrary destination ESC sequence */ | 206 | /* Clear-to-end-of-line */ |
215 | #define CMrc "\033[%u;%uH" | 207 | #define ESC_CLEAR2EOL "\033[K" |
216 | /* Cursor motion up and down ESC sequence */ | 208 | /* Clear-to-end-of-screen. |
217 | #define CMup "\033[A" | 209 | * (We use default param here. |
218 | #define CMdown "\n" | 210 | * Full sequence is "ESC [ <num> J", |
211 | * <num> is 0/1/2 = "erase below/above/all".) | ||
212 | */ | ||
213 | #define ESC_CLEAR2EOS "\033[J" | ||
214 | /* Cursor to given coordinate (1,1: top left) */ | ||
215 | #define ESC_SET_CURSOR_POS "\033[%u;%uH" | ||
216 | //UNUSED | ||
217 | ///* Cursor up and down */ | ||
218 | //#define ESC_CURSOR_UP "\033[A" | ||
219 | //#define ESC_CURSOR_DOWN "\n" | ||
219 | 220 | ||
220 | #if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK | 221 | #if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK |
221 | // cmds modifying text[] | 222 | // cmds modifying text[] |
@@ -303,9 +304,6 @@ struct globals { | |||
303 | int lmc_len; // length of last_modifying_cmd | 304 | int lmc_len; // length of last_modifying_cmd |
304 | char *ioq, *ioq_start; // pointer to string for get_one_char to "read" | 305 | char *ioq, *ioq_start; // pointer to string for get_one_char to "read" |
305 | #endif | 306 | #endif |
306 | #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR | ||
307 | int last_row; // where the cursor was last moved to | ||
308 | #endif | ||
309 | #if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME | 307 | #if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME |
310 | int my_pid; | 308 | int my_pid; |
311 | #endif | 309 | #endif |
@@ -389,7 +387,6 @@ struct globals { | |||
389 | #define lmc_len (G.lmc_len ) | 387 | #define lmc_len (G.lmc_len ) |
390 | #define ioq (G.ioq ) | 388 | #define ioq (G.ioq ) |
391 | #define ioq_start (G.ioq_start ) | 389 | #define ioq_start (G.ioq_start ) |
392 | #define last_row (G.last_row ) | ||
393 | #define my_pid (G.my_pid ) | 390 | #define my_pid (G.my_pid ) |
394 | #define last_search_pattern (G.last_search_pattern) | 391 | #define last_search_pattern (G.last_search_pattern) |
395 | 392 | ||
@@ -470,10 +467,7 @@ static int file_size(const char *); // what is the byte size of "fn" | |||
470 | // file_insert might reallocate text[]! | 467 | // file_insert might reallocate text[]! |
471 | static int file_insert(const char *, char *, int); | 468 | static int file_insert(const char *, char *, int); |
472 | static int file_write(char *, char *, char *); | 469 | static int file_write(char *, char *, char *); |
473 | #if !ENABLE_FEATURE_VI_OPTIMIZE_CURSOR | 470 | static void place_cursor(int, int); |
474 | #define place_cursor(a, b, optimize) place_cursor(a, b) | ||
475 | #endif | ||
476 | static void place_cursor(int, int, int); | ||
477 | static void screen_erase(void); | 471 | static void screen_erase(void); |
478 | static void clear_to_eol(void); | 472 | static void clear_to_eol(void); |
479 | static void clear_to_eos(void); | 473 | static void clear_to_eos(void); |
@@ -600,10 +594,10 @@ int vi_main(int argc, char **argv) | |||
600 | // The argv array can be used by the ":next" and ":rewind" commands | 594 | // The argv array can be used by the ":next" and ":rewind" commands |
601 | argv += optind; | 595 | argv += optind; |
602 | argc -= optind; | 596 | argc -= optind; |
603 | save_argc = argc; | ||
604 | optind = 0; | ||
605 | 597 | ||
606 | //----- This is the main file handling loop -------------- | 598 | //----- This is the main file handling loop -------------- |
599 | save_argc = argc; | ||
600 | optind = 0; | ||
607 | while (1) { | 601 | while (1) { |
608 | edit_file(argv[optind]); /* param might be NULL */ | 602 | edit_file(argv[optind]); /* param might be NULL */ |
609 | if (++optind >= argc) | 603 | if (++optind >= argc) |
@@ -2593,107 +2587,56 @@ static int file_write(char *fn, char *first, char *last) | |||
2593 | // 23,0 ... 23,79 <- status line | 2587 | // 23,0 ... 23,79 <- status line |
2594 | 2588 | ||
2595 | //----- Move the cursor to row x col (count from 0, not 1) ------- | 2589 | //----- Move the cursor to row x col (count from 0, not 1) ------- |
2596 | static void place_cursor(int row, int col, int optimize) | 2590 | static void place_cursor(int row, int col) |
2597 | { | 2591 | { |
2598 | char cm1[sizeof(CMrc) + sizeof(int)*3 * 2]; | 2592 | char cm1[sizeof(ESC_SET_CURSOR_POS) + sizeof(int)*3 * 2]; |
2599 | #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR | ||
2600 | enum { | ||
2601 | SZ_UP = sizeof(CMup), | ||
2602 | SZ_DN = sizeof(CMdown), | ||
2603 | SEQ_SIZE = SZ_UP > SZ_DN ? SZ_UP : SZ_DN, | ||
2604 | }; | ||
2605 | char cm2[SEQ_SIZE * 5 + 32]; // bigger than worst case size | ||
2606 | #endif | ||
2607 | char *cm; | ||
2608 | 2593 | ||
2609 | if (row < 0) row = 0; | 2594 | if (row < 0) row = 0; |
2610 | if (row >= rows) row = rows - 1; | 2595 | if (row >= rows) row = rows - 1; |
2611 | if (col < 0) col = 0; | 2596 | if (col < 0) col = 0; |
2612 | if (col >= columns) col = columns - 1; | 2597 | if (col >= columns) col = columns - 1; |
2613 | 2598 | ||
2614 | //----- 1. Try the standard terminal ESC sequence | 2599 | sprintf(cm1, ESC_SET_CURSOR_POS, row + 1, col + 1); |
2615 | sprintf(cm1, CMrc, row + 1, col + 1); | 2600 | write1(cm1); |
2616 | cm = cm1; | ||
2617 | |||
2618 | #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR | ||
2619 | if (optimize && col < 16) { | ||
2620 | char *screenp; | ||
2621 | int Rrow = last_row; | ||
2622 | int diff = Rrow - row; | ||
2623 | |||
2624 | if (diff < -5 || diff > 5) | ||
2625 | goto skip; | ||
2626 | |||
2627 | //----- find the minimum # of chars to move cursor ------------- | ||
2628 | //----- 2. Try moving with discreet chars (Newline, [back]space, ...) | ||
2629 | cm2[0] = '\0'; | ||
2630 | |||
2631 | // move to the correct row | ||
2632 | while (row < Rrow) { | ||
2633 | // the cursor has to move up | ||
2634 | strcat(cm2, CMup); | ||
2635 | Rrow--; | ||
2636 | } | ||
2637 | while (row > Rrow) { | ||
2638 | // the cursor has to move down | ||
2639 | strcat(cm2, CMdown); | ||
2640 | Rrow++; | ||
2641 | } | ||
2642 | |||
2643 | // now move to the correct column | ||
2644 | strcat(cm2, "\r"); // start at col 0 | ||
2645 | // just send out orignal source char to get to correct place | ||
2646 | screenp = &screen[row * columns]; // start of screen line | ||
2647 | strncat(cm2, screenp, col); | ||
2648 | |||
2649 | // pick the shortest cursor motion to send out | ||
2650 | if (strlen(cm2) < strlen(cm)) { | ||
2651 | cm = cm2; | ||
2652 | } | ||
2653 | skip: ; | ||
2654 | } | ||
2655 | last_row = row; | ||
2656 | #endif /* FEATURE_VI_OPTIMIZE_CURSOR */ | ||
2657 | write1(cm); | ||
2658 | } | 2601 | } |
2659 | 2602 | ||
2660 | //----- Erase from cursor to end of line ----------------------- | 2603 | //----- Erase from cursor to end of line ----------------------- |
2661 | static void clear_to_eol(void) | 2604 | static void clear_to_eol(void) |
2662 | { | 2605 | { |
2663 | write1(Ceol); // Erase from cursor to end of line | 2606 | write1(ESC_CLEAR2EOL); |
2664 | } | 2607 | } |
2665 | 2608 | ||
2666 | static void go_bottom_and_clear_to_eol(void) | 2609 | static void go_bottom_and_clear_to_eol(void) |
2667 | { | 2610 | { |
2668 | place_cursor(rows - 1, 0, FALSE); // go to bottom of screen | 2611 | place_cursor(rows - 1, 0); |
2669 | clear_to_eol(); // erase to end of line | 2612 | clear_to_eol(); |
2670 | } | 2613 | } |
2671 | 2614 | ||
2672 | //----- Erase from cursor to end of screen ----------------------- | 2615 | //----- Erase from cursor to end of screen ----------------------- |
2673 | static void clear_to_eos(void) | 2616 | static void clear_to_eos(void) |
2674 | { | 2617 | { |
2675 | write1(Ceos); // Erase from cursor to end of screen | 2618 | write1(ESC_CLEAR2EOS); |
2676 | } | 2619 | } |
2677 | 2620 | ||
2678 | //----- Start standout mode ------------------------------------ | 2621 | //----- Start standout mode ------------------------------------ |
2679 | static void standout_start(void) // send "start reverse video" sequence | 2622 | static void standout_start(void) |
2680 | { | 2623 | { |
2681 | write1(SOs); // Start reverse video mode | 2624 | write1(ESC_BOLD_TEXT); |
2682 | } | 2625 | } |
2683 | 2626 | ||
2684 | //----- End standout mode -------------------------------------- | 2627 | //----- End standout mode -------------------------------------- |
2685 | static void standout_end(void) // send "end reverse video" sequence | 2628 | static void standout_end(void) |
2686 | { | 2629 | { |
2687 | write1(SOn); // End reverse video mode | 2630 | write1(ESC_NORM_TEXT); |
2688 | } | 2631 | } |
2689 | 2632 | ||
2690 | //----- Flash the screen -------------------------------------- | 2633 | //----- Flash the screen -------------------------------------- |
2691 | static void flash(int h) | 2634 | static void flash(int h) |
2692 | { | 2635 | { |
2693 | standout_start(); // send "start reverse video" sequence | 2636 | standout_start(); |
2694 | redraw(TRUE); | 2637 | redraw(TRUE); |
2695 | mysleep(h); | 2638 | mysleep(h); |
2696 | standout_end(); // send "end reverse video" sequence | 2639 | standout_end(); |
2697 | redraw(TRUE); | 2640 | redraw(TRUE); |
2698 | } | 2641 | } |
2699 | 2642 | ||
@@ -2704,7 +2647,7 @@ static void Indicate_Error(void) | |||
2704 | return; // generate a random command | 2647 | return; // generate a random command |
2705 | #endif | 2648 | #endif |
2706 | if (!err_method) { | 2649 | if (!err_method) { |
2707 | write1(bell); // send out a bell character | 2650 | write1(ESC_BELL); |
2708 | } else { | 2651 | } else { |
2709 | flash(10); | 2652 | flash(10); |
2710 | } | 2653 | } |
@@ -2750,7 +2693,7 @@ static void show_status_line(void) | |||
2750 | } | 2693 | } |
2751 | have_status_msg = 0; | 2694 | have_status_msg = 0; |
2752 | } | 2695 | } |
2753 | place_cursor(crow, ccol, FALSE); // put cursor back in correct place | 2696 | place_cursor(crow, ccol); // put cursor back in correct place |
2754 | } | 2697 | } |
2755 | fflush_all(); | 2698 | fflush_all(); |
2756 | } | 2699 | } |
@@ -2762,12 +2705,12 @@ static void status_line_bold(const char *format, ...) | |||
2762 | va_list args; | 2705 | va_list args; |
2763 | 2706 | ||
2764 | va_start(args, format); | 2707 | va_start(args, format); |
2765 | strcpy(status_buffer, SOs); // Terminal standout mode on | 2708 | strcpy(status_buffer, ESC_BOLD_TEXT); |
2766 | vsprintf(status_buffer + sizeof(SOs)-1, format, args); | 2709 | vsprintf(status_buffer + sizeof(ESC_BOLD_TEXT)-1, format, args); |
2767 | strcat(status_buffer, SOn); // Terminal standout mode off | 2710 | strcat(status_buffer, ESC_NORM_TEXT); |
2768 | va_end(args); | 2711 | va_end(args); |
2769 | 2712 | ||
2770 | have_status_msg = 1 + sizeof(SOs) + sizeof(SOn) - 2; | 2713 | have_status_msg = 1 + sizeof(ESC_BOLD_TEXT) + sizeof(ESC_NORM_TEXT) - 2; |
2771 | } | 2714 | } |
2772 | 2715 | ||
2773 | // format status buffer | 2716 | // format status buffer |
@@ -2799,8 +2742,8 @@ static void print_literal(char *buf, const char *s) | |||
2799 | c = *s; | 2742 | c = *s; |
2800 | c_is_no_print = (c & 0x80) && !Isprint(c); | 2743 | c_is_no_print = (c & 0x80) && !Isprint(c); |
2801 | if (c_is_no_print) { | 2744 | if (c_is_no_print) { |
2802 | strcpy(d, SOn); | 2745 | strcpy(d, ESC_NORM_TEXT); |
2803 | d += sizeof(SOn)-1; | 2746 | d += sizeof(ESC_NORM_TEXT)-1; |
2804 | c = '.'; | 2747 | c = '.'; |
2805 | } | 2748 | } |
2806 | if (c < ' ' || c == 0x7f) { | 2749 | if (c < ' ' || c == 0x7f) { |
@@ -2812,8 +2755,8 @@ static void print_literal(char *buf, const char *s) | |||
2812 | *d++ = c; | 2755 | *d++ = c; |
2813 | *d = '\0'; | 2756 | *d = '\0'; |
2814 | if (c_is_no_print) { | 2757 | if (c_is_no_print) { |
2815 | strcpy(d, SOs); | 2758 | strcpy(d, ESC_BOLD_TEXT); |
2816 | d += sizeof(SOs)-1; | 2759 | d += sizeof(ESC_BOLD_TEXT)-1; |
2817 | } | 2760 | } |
2818 | if (*s == '\n') { | 2761 | if (*s == '\n') { |
2819 | *d++ = '$'; | 2762 | *d++ = '$'; |
@@ -2895,8 +2838,8 @@ static int format_edit_status(void) | |||
2895 | //----- Force refresh of all Lines ----------------------------- | 2838 | //----- Force refresh of all Lines ----------------------------- |
2896 | static void redraw(int full_screen) | 2839 | static void redraw(int full_screen) |
2897 | { | 2840 | { |
2898 | place_cursor(0, 0, FALSE); // put cursor in correct place | 2841 | place_cursor(0, 0); |
2899 | clear_to_eos(); // tell terminal to erase display | 2842 | clear_to_eos(); |
2900 | screen_erase(); // erase the internal screen buffer | 2843 | screen_erase(); // erase the internal screen buffer |
2901 | last_status_cksum = 0; // force status update | 2844 | last_status_cksum = 0; // force status update |
2902 | refresh(full_screen); // this will redraw the entire display | 2845 | refresh(full_screen); // this will redraw the entire display |
@@ -3036,22 +2979,13 @@ static void refresh(int full_screen) | |||
3036 | if (changed) { | 2979 | if (changed) { |
3037 | // copy changed part of buffer to virtual screen | 2980 | // copy changed part of buffer to virtual screen |
3038 | memcpy(sp+cs, out_buf+cs, ce-cs+1); | 2981 | memcpy(sp+cs, out_buf+cs, ce-cs+1); |
3039 | 2982 | place_cursor(li, cs); | |
3040 | // move cursor to column of first change | ||
3041 | //if (offset != old_offset) { | ||
3042 | // // place_cursor is still too stupid | ||
3043 | // // to handle offsets correctly | ||
3044 | // place_cursor(li, cs, FALSE); | ||
3045 | //} else { | ||
3046 | place_cursor(li, cs, TRUE); | ||
3047 | //} | ||
3048 | |||
3049 | // write line out to terminal | 2983 | // write line out to terminal |
3050 | fwrite(&sp[cs], ce - cs + 1, 1, stdout); | 2984 | fwrite(&sp[cs], ce - cs + 1, 1, stdout); |
3051 | } | 2985 | } |
3052 | } | 2986 | } |
3053 | 2987 | ||
3054 | place_cursor(crow, ccol, TRUE); | 2988 | place_cursor(crow, ccol); |
3055 | 2989 | ||
3056 | old_offset = offset; | 2990 | old_offset = offset; |
3057 | #undef old_offset | 2991 | #undef old_offset |
@@ -3221,9 +3155,9 @@ static void do_cmd(int c) | |||
3221 | break; | 3155 | break; |
3222 | case 12: // ctrl-L force redraw whole screen | 3156 | case 12: // ctrl-L force redraw whole screen |
3223 | case 18: // ctrl-R force redraw | 3157 | case 18: // ctrl-R force redraw |
3224 | place_cursor(0, 0, FALSE); // put cursor in correct place | 3158 | place_cursor(0, 0); |
3225 | clear_to_eos(); // tel terminal to erase display | 3159 | clear_to_eos(); |
3226 | mysleep(10); | 3160 | //mysleep(10); // why??? |
3227 | screen_erase(); // erase the internal screen buffer | 3161 | screen_erase(); // erase the internal screen buffer |
3228 | last_status_cksum = 0; // force status update | 3162 | last_status_cksum = 0; // force status update |
3229 | refresh(TRUE); // this will redraw the entire display | 3163 | refresh(TRUE); // this will redraw the entire display |
@@ -4142,7 +4076,7 @@ static void crash_test() | |||
4142 | 4076 | ||
4143 | if (msg[0]) { | 4077 | if (msg[0]) { |
4144 | printf("\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s", | 4078 | printf("\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s", |
4145 | totalcmds, last_input_char, msg, SOs, SOn); | 4079 | totalcmds, last_input_char, msg, ESC_BOLD_TEXT, ESC_NORM_TEXT); |
4146 | fflush_all(); | 4080 | fflush_all(); |
4147 | while (safe_read(STDIN_FILENO, d, 1) > 0) { | 4081 | while (safe_read(STDIN_FILENO, d, 1) > 0) { |
4148 | if (d[0] == '\n' || d[0] == '\r') | 4082 | if (d[0] == '\n' || d[0] == '\r') |