diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-05-07 17:37:43 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-05-07 17:37:43 +0000 |
commit | 822c3837f95a355f90d25aaabeb2445bb5eb1bf0 (patch) | |
tree | 74a0aca850bc434a61e922d5efbd8b212603ffd1 /editors/vi.c | |
parent | 713b3987003ce61e3b1c9003f42b8490d666a850 (diff) | |
download | busybox-w32-822c3837f95a355f90d25aaabeb2445bb5eb1bf0.tar.gz busybox-w32-822c3837f95a355f90d25aaabeb2445bb5eb1bf0.tar.bz2 busybox-w32-822c3837f95a355f90d25aaabeb2445bb5eb1bf0.zip |
Another vi update from Sterling Huxley:
- All of the ESC sequences are now in variables. This should make
re-targeting for other terminals easier.
- The initial screen draw does not force out every single column.
Should be faster.
- The place_cursor() routine trys to be smarter about moving the
cursor. This is optional based on BB_FEATURE_VI_OPTIMIZE_CURSOR.
- The 't' and 'f' intra-line positioning commands were added.
They can now be used as targets in 'c' and 'd' commands, i.e.,
dfx - delete from dot to next 'x'
dtx - delete from dot to the char before next 'x'
- show_status_line() uses a static int checksum to remember what
is currently displayed on the screen and not re-draw the status
line unless it has changed.
- Some of the code in refresh() was moved out to format_line().
refresh() trys to send out the smallest segment containing
the changed chars rather than the whole line.
- Added "flash" to the :set command to specify if error indication
should be by flashing the screen or ringing the bell.
- Changed the rawmode() routine so that it turns off the
NL -> CR NL translation. On output of a NL, the OS will not add
a CR.
- If vi was started as "view", with global read-only mode,
and another file is opened, the file is opened read-only
rather than read+write.
Diffstat (limited to 'editors/vi.c')
-rw-r--r-- | editors/vi.c | 572 |
1 files changed, 348 insertions, 224 deletions
diff --git a/editors/vi.c b/editors/vi.c index 96fc96559..54f1d265c 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -19,13 +19,13 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | char *vi_Version = | 21 | char *vi_Version = |
22 | "$Id: vi.c,v 1.5 2001/04/26 15:56:47 andersen Exp $"; | 22 | "$Id: vi.c,v 1.6 2001/05/07 17:37:43 andersen Exp $"; |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * To compile for standalone use: | 25 | * To compile for standalone use: |
26 | * gcc -Wall -Os -s -DSTANDALONE -o vi vi.c | 26 | * gcc -Wall -Os -s -DSTANDALONE -o vi vi.c |
27 | * or | 27 | * or |
28 | * gcc -Wall -Os -s -DSTANDALONE -DCRASHME -o vi vi.c # include testing features | 28 | * gcc -Wall -Os -s -DSTANDALONE -DBB_FEATURE_VI_CRASHME -o vi vi.c # include testing features |
29 | * strip vi | 29 | * strip vi |
30 | */ | 30 | */ |
31 | 31 | ||
@@ -47,7 +47,7 @@ char *vi_Version = | |||
47 | 47 | ||
48 | //---- Feature -------------- Bytes to immplement | 48 | //---- Feature -------------- Bytes to immplement |
49 | #ifdef STANDALONE | 49 | #ifdef STANDALONE |
50 | #define vi_main main | 50 | #define vi_main main |
51 | #define BB_FEATURE_VI_COLON // 4288 | 51 | #define BB_FEATURE_VI_COLON // 4288 |
52 | #define BB_FEATURE_VI_YANKMARK // 1408 | 52 | #define BB_FEATURE_VI_YANKMARK // 1408 |
53 | #define BB_FEATURE_VI_SEARCH // 1088 | 53 | #define BB_FEATURE_VI_SEARCH // 1088 |
@@ -62,7 +62,7 @@ char *vi_Version = | |||
62 | // To stop testing, wait until all to text[] is deleted, or | 62 | // To stop testing, wait until all to text[] is deleted, or |
63 | // Ctrl-Z and kill -9 %1 | 63 | // Ctrl-Z and kill -9 %1 |
64 | // while in the editor Ctrl-T will toggle the crashme function on and off. | 64 | // while in the editor Ctrl-T will toggle the crashme function on and off. |
65 | //#define BB_FEATURE_VI_CRASHME // randomly pick commands to execute | 65 | //#define BB_FEATURE_VI_CRASHME // randomly pick commands to execute |
66 | #endif /* STANDALONE */ | 66 | #endif /* STANDALONE */ |
67 | 67 | ||
68 | #ifndef STANDALONE | 68 | #ifndef STANDALONE |
@@ -144,7 +144,11 @@ static struct timeval tv; // use select() for small sleeps | |||
144 | static char erase_char; // the users erase character | 144 | static char erase_char; // the users erase character |
145 | static int rows, columns; // the terminal screen is this size | 145 | static int rows, columns; // the terminal screen is this size |
146 | static int crow, ccol, offset; // cursor is on Crow x Ccol with Horz Ofset | 146 | static int crow, ccol, offset; // cursor is on Crow x Ccol with Horz Ofset |
147 | static char *SOs, *SOn; | 147 | static char *SOs, *SOn; // terminal standout start/normal ESC sequence |
148 | static char *bell; // terminal bell sequence | ||
149 | static char *Ceol, *Ceos; // Clear-end-of-line and Clear-end-of-screen ESC sequence | ||
150 | static char *CMrc; // Cursor motion arbitrary destination ESC sequence | ||
151 | static char *CMup, *CMdown; // Cursor motion up and down ESC sequence | ||
148 | static Byte *status_buffer; // mesages to the user | 152 | static Byte *status_buffer; // mesages to the user |
149 | static Byte last_input_char; // last char read from user | 153 | static Byte last_input_char; // last char read from user |
150 | static Byte last_forward_char; // last char searched for with 'f' | 154 | static Byte last_forward_char; // last char searched for with 'f' |
@@ -157,6 +161,9 @@ static Byte *dot; // where all the action takes place | |||
157 | static int tabstop; | 161 | static int tabstop; |
158 | static struct termios term_orig, term_vi; // remember what the cooked mode was | 162 | static struct termios term_orig, term_vi; // remember what the cooked mode was |
159 | 163 | ||
164 | #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR | ||
165 | static int last_row; // where the cursor was last moved to | ||
166 | #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ | ||
160 | #ifdef BB_FEATURE_VI_USE_SIGNALS | 167 | #ifdef BB_FEATURE_VI_USE_SIGNALS |
161 | static jmp_buf restart; // catch_sig() | 168 | static jmp_buf restart; // catch_sig() |
162 | #endif /* BB_FEATURE_VI_USE_SIGNALS */ | 169 | #endif /* BB_FEATURE_VI_USE_SIGNALS */ |
@@ -172,7 +179,7 @@ static Byte *ioq, *ioq_start; // pointer to string for get_one_char to "read" | |||
172 | static Byte *modifying_cmds; // cmds that modify text[] | 179 | static Byte *modifying_cmds; // cmds that modify text[] |
173 | #endif /* BB_FEATURE_VI_DOT_CMD || BB_FEATURE_VI_YANKMARK */ | 180 | #endif /* BB_FEATURE_VI_DOT_CMD || BB_FEATURE_VI_YANKMARK */ |
174 | #ifdef BB_FEATURE_VI_READONLY | 181 | #ifdef BB_FEATURE_VI_READONLY |
175 | static int readonly; | 182 | static int vi_readonly, readonly; |
176 | #endif /* BB_FEATURE_VI_READONLY */ | 183 | #endif /* BB_FEATURE_VI_READONLY */ |
177 | #ifdef BB_FEATURE_VI_SETOPTS | 184 | #ifdef BB_FEATURE_VI_SETOPTS |
178 | static int autoindent; | 185 | static int autoindent; |
@@ -234,7 +241,7 @@ static Byte get_one_char(void); // read 1 char from stdin | |||
234 | static int file_size(Byte *); // what is the byte size of "fn" | 241 | static int file_size(Byte *); // what is the byte size of "fn" |
235 | static int file_insert(Byte *, Byte *, int); | 242 | static int file_insert(Byte *, Byte *, int); |
236 | static int file_write(Byte *, Byte *, Byte *); | 243 | static int file_write(Byte *, Byte *, Byte *); |
237 | static void place_cursor(int, int); | 244 | static void place_cursor(int, int, int); |
238 | static void screen_erase(); | 245 | static void screen_erase(); |
239 | static void clear_to_eol(void); | 246 | static void clear_to_eol(void); |
240 | static void clear_to_eos(void); | 247 | static void clear_to_eos(void); |
@@ -249,6 +256,7 @@ static void psbs(char *, ...); // Print Status Buf in standout mode | |||
249 | static void ni(Byte *); // display messages | 256 | static void ni(Byte *); // display messages |
250 | static void edit_status(void); // show file status on status line | 257 | static void edit_status(void); // show file status on status line |
251 | static void redraw(int); // force a full screen refresh | 258 | static void redraw(int); // force a full screen refresh |
259 | static void format_line(Byte*, Byte*, int); | ||
252 | static void refresh(int); // update the terminal from screen[] | 260 | static void refresh(int); // update the terminal from screen[] |
253 | 261 | ||
254 | #ifdef BB_FEATURE_VI_SEARCH | 262 | #ifdef BB_FEATURE_VI_SEARCH |
@@ -261,9 +269,7 @@ static Byte *get_one_address(Byte *, int *); // get colon addr, if present | |||
261 | static Byte *get_address(Byte *, int *, int *); // get two colon addrs, if present | 269 | static Byte *get_address(Byte *, int *, int *); // get two colon addrs, if present |
262 | static void colon(Byte *); // execute the "colon" mode cmds | 270 | static void colon(Byte *); // execute the "colon" mode cmds |
263 | #endif /* BB_FEATURE_VI_COLON */ | 271 | #endif /* BB_FEATURE_VI_COLON */ |
264 | #if defined(BB_FEATURE_VI_SEARCH) || defined(BB_FEATURE_VI_COLON) | ||
265 | static Byte *get_input_line(Byte *); // get input line- use "status line" | 272 | static Byte *get_input_line(Byte *); // get input line- use "status line" |
266 | #endif /* BB_FEATURE_VI_SEARCH || BB_FEATURE_VI_COLON */ | ||
267 | #ifdef BB_FEATURE_VI_USE_SIGNALS | 273 | #ifdef BB_FEATURE_VI_USE_SIGNALS |
268 | static void winch_sig(int); // catch window size changes | 274 | static void winch_sig(int); // catch window size changes |
269 | static void suspend_sig(int); // catch ctrl-Z | 275 | static void suspend_sig(int); // catch ctrl-Z |
@@ -307,16 +313,23 @@ extern int vi_main(int argc, char **argv) | |||
307 | int i; | 313 | int i; |
308 | #endif /* BB_FEATURE_VI_YANKMARK */ | 314 | #endif /* BB_FEATURE_VI_YANKMARK */ |
309 | 315 | ||
316 | CMrc= "\033[%d;%dH"; // Terminal Crusor motion ESC sequence | ||
317 | CMup= "\033[A"; // move cursor up one line, same col | ||
318 | CMdown="\n"; // move cursor down one line, same col | ||
319 | Ceol= "\033[0K"; // Clear from cursor to end of line | ||
320 | Ceos= "\033[0J"; // Clear from cursor to end of screen | ||
310 | SOs = "\033[7m"; // Terminal standout mode on | 321 | SOs = "\033[7m"; // Terminal standout mode on |
311 | SOn = "\033[0m"; // Terminal standout mode off | 322 | SOn = "\033[0m"; // Terminal standout mode off |
323 | bell= "\007"; // Terminal bell sequence | ||
312 | #ifdef BB_FEATURE_VI_CRASHME | 324 | #ifdef BB_FEATURE_VI_CRASHME |
313 | (void) srand((long) getpid()); | 325 | (void) srand((long) getpid()); |
314 | #endif /* BB_FEATURE_VI_CRASHME */ | 326 | #endif /* BB_FEATURE_VI_CRASHME */ |
315 | status_buffer = (Byte *) malloc(200); // hold messages to user | 327 | status_buffer = (Byte *) malloc(200); // hold messages to user |
316 | #ifdef BB_FEATURE_VI_READONLY | 328 | #ifdef BB_FEATURE_VI_READONLY |
317 | readonly = FALSE; | 329 | vi_readonly = readonly = FALSE; |
318 | if (strncmp(argv[0], "view", 4) == 0) { | 330 | if (strncmp(argv[0], "view", 4) == 0) { |
319 | readonly = TRUE; | 331 | readonly = TRUE; |
332 | vi_readonly = TRUE; | ||
320 | } | 333 | } |
321 | #endif /* BB_FEATURE_VI_READONLY */ | 334 | #endif /* BB_FEATURE_VI_READONLY */ |
322 | #ifdef BB_FEATURE_VI_SETOPTS | 335 | #ifdef BB_FEATURE_VI_SETOPTS |
@@ -348,10 +361,10 @@ extern int vi_main(int argc, char **argv) | |||
348 | readonly = TRUE; | 361 | readonly = TRUE; |
349 | break; | 362 | break; |
350 | #endif /* BB_FEATURE_VI_READONLY */ | 363 | #endif /* BB_FEATURE_VI_READONLY */ |
351 | //case 'r': // recover flag- ignore- we don't use tmp file | 364 | //case 'r': // recover flag- ignore- we don't use tmp file |
352 | //case 'x': // encryption flag- ignore | 365 | //case 'x': // encryption flag- ignore |
353 | //case 'c': // execute command first | 366 | //case 'c': // execute command first |
354 | //case 'h': // help -- just use default | 367 | //case 'h': // help -- just use default |
355 | default: | 368 | default: |
356 | show_help(); | 369 | show_help(); |
357 | break; | 370 | break; |
@@ -397,12 +410,12 @@ static void edit_file(Byte * fn) | |||
397 | rawmode(); | 410 | rawmode(); |
398 | rows = 24; | 411 | rows = 24; |
399 | columns = 80; | 412 | columns = 80; |
413 | ch= -1; | ||
400 | #ifdef BB_FEATURE_VI_WIN_RESIZE | 414 | #ifdef BB_FEATURE_VI_WIN_RESIZE |
401 | window_size_get(0); | 415 | window_size_get(0); |
402 | #endif /* BB_FEATURE_VI_WIN_RESIZE */ | 416 | #endif /* BB_FEATURE_VI_WIN_RESIZE */ |
403 | new_screen(rows, columns); // get memory for virtual screen | 417 | new_screen(rows, columns); // get memory for virtual screen |
404 | 418 | ||
405 | ch= 0; | ||
406 | cnt = file_size(fn); // file size | 419 | cnt = file_size(fn); // file size |
407 | size = 2 * cnt; // 200% of file size | 420 | size = 2 * cnt; // 200% of file size |
408 | new_text(size); // get a text[] buffer | 421 | new_text(size); // get a text[] buffer |
@@ -484,7 +497,7 @@ static void edit_file(Byte * fn) | |||
484 | ioq = ioq_start = last_modifying_cmd = 0; | 497 | ioq = ioq_start = last_modifying_cmd = 0; |
485 | adding2q = 0; | 498 | adding2q = 0; |
486 | #endif /* BB_FEATURE_VI_DOT_CMD */ | 499 | #endif /* BB_FEATURE_VI_DOT_CMD */ |
487 | redraw(TRUE); | 500 | redraw(FALSE); // dont force every col re-draw |
488 | show_status_line(); | 501 | show_status_line(); |
489 | 502 | ||
490 | //------This is the main Vi cmd handling loop ----------------------- | 503 | //------This is the main Vi cmd handling loop ----------------------- |
@@ -534,7 +547,7 @@ static void edit_file(Byte * fn) | |||
534 | } | 547 | } |
535 | //------------------------------------------------------------------- | 548 | //------------------------------------------------------------------- |
536 | 549 | ||
537 | place_cursor(rows, 0); // go to bottom of screen | 550 | place_cursor(rows, 0, FALSE); // go to bottom of screen |
538 | clear_to_eol(); // Erase to end of line | 551 | clear_to_eol(); // Erase to end of line |
539 | cookmode(); | 552 | cookmode(); |
540 | } | 553 | } |
@@ -649,7 +662,7 @@ static void crash_dummy() | |||
649 | i = (int) lrand48() % strlen(cmd); | 662 | i = (int) lrand48() % strlen(cmd); |
650 | cm = cmd[i]; | 663 | cm = cmd[i]; |
651 | if (strchr(":\024", cm)) | 664 | if (strchr(":\024", cm)) |
652 | goto cd0; // dont allow these commands | 665 | goto cd0; // dont allow colon or ctrl-T commands |
653 | readbuffer[rbi++] = cm; // put cmd into input buffer | 666 | readbuffer[rbi++] = cm; // put cmd into input buffer |
654 | 667 | ||
655 | // now we have the command- | 668 | // now we have the command- |
@@ -725,11 +738,9 @@ static void crash_test() | |||
725 | 738 | ||
726 | if (strlen(msg) > 0) { | 739 | if (strlen(msg) > 0) { |
727 | alarm(0); | 740 | alarm(0); |
728 | sprintf(buf, "\n\n%d: \'%c\' ", totalcmds, last_input_char); | 741 | sprintf(buf, "\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s", |
742 | totalcmds, last_input_char, msg, SOs, SOn); | ||
729 | write(1, buf, strlen(buf)); | 743 | write(1, buf, strlen(buf)); |
730 | write(1, msg, strlen(msg)); | ||
731 | write(1, "\n\n\n", 3); | ||
732 | write(1, "\033[7m[Hit return to continue]\033[0m", 32); | ||
733 | while (read(0, d, 1) > 0) { | 744 | while (read(0, d, 1) > 0) { |
734 | if (d[0] == '\n' || d[0] == '\r') | 745 | if (d[0] == '\n' || d[0] == '\r') |
735 | break; | 746 | break; |
@@ -803,50 +814,49 @@ static void do_cmd(Byte c) | |||
803 | } | 814 | } |
804 | 815 | ||
805 | switch (c) { | 816 | switch (c) { |
806 | //case 0x01: // soh | 817 | //case 0x01: // soh |
807 | //case 0x09: // ht | 818 | //case 0x09: // ht |
808 | //case 0x0b: // vt | 819 | //case 0x0b: // vt |
809 | //case 0x0e: // so | 820 | //case 0x0e: // so |
810 | //case 0x0f: // si | 821 | //case 0x0f: // si |
811 | //case 0x10: // dle | 822 | //case 0x10: // dle |
812 | //case 0x11: // dc1 | 823 | //case 0x11: // dc1 |
813 | //case 0x13: // dc3 | 824 | //case 0x13: // dc3 |
814 | #ifdef BB_FEATURE_VI_CRASHME | 825 | #ifdef BB_FEATURE_VI_CRASHME |
815 | case 0x14: // dc4 ctrl-T | 826 | case 0x14: // dc4 ctrl-T |
816 | crashme = (crashme == 0) ? 1 : 0; | 827 | crashme = (crashme == 0) ? 1 : 0; |
817 | break; | 828 | break; |
818 | #endif /* BB_FEATURE_VI_CRASHME */ | 829 | #endif /* BB_FEATURE_VI_CRASHME */ |
819 | //case 0x16: // syn | 830 | //case 0x16: // syn |
820 | //case 0x17: // etb | 831 | //case 0x17: // etb |
821 | //case 0x18: // can | 832 | //case 0x18: // can |
822 | //case 0x1c: // fs | 833 | //case 0x1c: // fs |
823 | //case 0x1d: // gs | 834 | //case 0x1d: // gs |
824 | //case 0x1e: // rs | 835 | //case 0x1e: // rs |
825 | //case 0x1f: // us | 836 | //case 0x1f: // us |
826 | //case '!': // !- | 837 | //case '!': // !- |
827 | //case '#': // #- | 838 | //case '#': // #- |
828 | //case '&': // &- | 839 | //case '&': // &- |
829 | //case '(': // (- | 840 | //case '(': // (- |
830 | //case ')': // )- | 841 | //case ')': // )- |
831 | //case '*': // *- | 842 | //case '*': // *- |
832 | //case ',': // ,- | 843 | //case ',': // ,- |
833 | //case '=': // =- | 844 | //case '=': // =- |
834 | //case '@': // @- | 845 | //case '@': // @- |
835 | //case 'F': // F- | 846 | //case 'F': // F- |
836 | //case 'K': // K- | 847 | //case 'K': // K- |
837 | //case 'Q': // Q- | 848 | //case 'Q': // Q- |
838 | //case 'S': // S- | 849 | //case 'S': // S- |
839 | //case 'T': // T- | 850 | //case 'T': // T- |
840 | //case 'V': // V- | 851 | //case 'V': // V- |
841 | //case '[': // [- | 852 | //case '[': // [- |
842 | //case '\\': // \- | 853 | //case '\\': // \- |
843 | //case ']': // ]- | 854 | //case ']': // ]- |
844 | //case '_': // _- | 855 | //case '_': // _- |
845 | //case '`': // `- | 856 | //case '`': // `- |
846 | //case 'g': // g- | 857 | //case 'g': // g- |
847 | //case 't': // t- | ||
848 | //case 'u': // u- FIXME- there is no undo | 858 | //case 'u': // u- FIXME- there is no undo |
849 | //case 'v': // v- | 859 | //case 'v': // v- |
850 | default: // unrecognised command | 860 | default: // unrecognised command |
851 | buf[0] = c; | 861 | buf[0] = c; |
852 | buf[1] = '\0'; | 862 | buf[1] = '\0'; |
@@ -904,7 +914,7 @@ static void do_cmd(Byte c) | |||
904 | break; | 914 | break; |
905 | case 12: // ctrl-L force redraw whole screen | 915 | case 12: // ctrl-L force redraw whole screen |
906 | case 18: // ctrl-R force redraw | 916 | case 18: // ctrl-R force redraw |
907 | place_cursor(0, 0); // put cursor in correct place | 917 | place_cursor(0, 0, FALSE); // put cursor in correct place |
908 | clear_to_eos(); // tel terminal to erase display | 918 | clear_to_eos(); // tel terminal to erase display |
909 | (void) mysleep(10); | 919 | (void) mysleep(10); |
910 | screen_erase(); // erase the internal screen buffer | 920 | screen_erase(); // erase the internal screen buffer |
@@ -924,7 +934,7 @@ static void do_cmd(Byte c) | |||
924 | case 25: // ctrl-Y scroll up one line | 934 | case 25: // ctrl-Y scroll up one line |
925 | dot_scroll(1, -1); | 935 | dot_scroll(1, -1); |
926 | break; | 936 | break; |
927 | case 0x1b: // esc | 937 | case 27: // esc |
928 | if (cmd_mode == 0) | 938 | if (cmd_mode == 0) |
929 | indicate_error(c); | 939 | indicate_error(c); |
930 | cmd_mode = 0; // stop insrting | 940 | cmd_mode = 0; // stop insrting |
@@ -1053,8 +1063,9 @@ static void do_cmd(Byte c) | |||
1053 | //**** fall thru to ... 'i' | 1063 | //**** fall thru to ... 'i' |
1054 | case ';': // ;- look at rest of line for last forward char | 1064 | case ';': // ;- look at rest of line for last forward char |
1055 | if (cmdcnt-- > 1) { | 1065 | if (cmdcnt-- > 1) { |
1056 | do_cmd(c); | 1066 | do_cmd(';'); |
1057 | } // repeat cnt | 1067 | } // repeat cnt |
1068 | if (last_forward_char == 0) break; | ||
1058 | q = dot + 1; | 1069 | q = dot + 1; |
1059 | while (q < end - 1 && *q != '\n' && *q != last_forward_char) { | 1070 | while (q < end - 1 && *q != '\n' && *q != last_forward_char) { |
1060 | q++; | 1071 | q++; |
@@ -1182,41 +1193,37 @@ static void do_cmd(Byte c) | |||
1182 | } | 1193 | } |
1183 | break; | 1194 | break; |
1184 | case ':': // :- the colon mode commands | 1195 | case ':': // :- the colon mode commands |
1185 | #ifdef BB_FEATURE_VI_COLON | ||
1186 | p = get_input_line((Byte *) ":"); // get input line- use "status line" | 1196 | p = get_input_line((Byte *) ":"); // get input line- use "status line" |
1197 | #ifdef BB_FEATURE_VI_COLON | ||
1187 | colon(p); // execute the command | 1198 | colon(p); // execute the command |
1188 | #else /* BB_FEATURE_VI_COLON */ | 1199 | #else /* BB_FEATURE_VI_COLON */ |
1189 | *status_buffer = '\0'; // clear the status buffer | 1200 | if (*p == ':') |
1190 | place_cursor(rows - 1, 0); // go to Status line, bottom of screen | 1201 | p++; // move past the ':' |
1191 | clear_to_eol(); // clear the line | 1202 | cnt = strlen((char *) p); |
1192 | write(1, ":", 1); // write out the : prompt | 1203 | if (cnt <= 0) |
1193 | for (cnt = 0; cnt < 8; cnt++) { | 1204 | break; |
1194 | c1 = get_one_char(); | 1205 | if (strncasecmp((char *) p, "quit", cnt) == 0 || |
1195 | if (c1 == '\n' || c1 == '\r' || c1 == 27) { | 1206 | strncasecmp((char *) p, "q!", cnt) == 0) { // delete lines |
1196 | break; | 1207 | if (file_modified == TRUE && p[1] != '!') { |
1197 | } | ||
1198 | buf[cnt] = c1; | ||
1199 | buf[cnt + 1] = '\0'; | ||
1200 | write(1, buf + cnt, 1); // echo the char | ||
1201 | } | ||
1202 | cnt = strlen((char *) buf); | ||
1203 | if (strncasecmp((char *) buf, "quit", cnt) == 0 || | ||
1204 | strncasecmp((char *) buf, "q!", cnt) == 0) { // delete lines | ||
1205 | if (file_modified == TRUE && buf[1] != '!') { | ||
1206 | psbs("No write since last change (:quit! overrides)"); | 1208 | psbs("No write since last change (:quit! overrides)"); |
1207 | } else { | 1209 | } else { |
1208 | editing = 0; | 1210 | editing = 0; |
1209 | } | 1211 | } |
1210 | } else if (strncasecmp((char *) buf, "write", cnt) == 0 || | 1212 | } else if (strncasecmp((char *) p, "write", cnt) == 0 || |
1211 | strncasecmp((char *) buf, "wq", cnt) == 0) { | 1213 | strncasecmp((char *) p, "wq", cnt) == 0) { |
1212 | cnt = file_write(cfn, text, end - 1); | 1214 | cnt = file_write(cfn, text, end - 1); |
1213 | file_modified = FALSE; | 1215 | file_modified = FALSE; |
1214 | psb("\"%s\" %dL, %dC", cfn, count_lines(text, end - 1), cnt); | 1216 | psb("\"%s\" %dL, %dC", cfn, count_lines(text, end - 1), cnt); |
1215 | if (buf[1] == 'q') { | 1217 | if (p[1] == 'q') { |
1216 | editing = 0; | 1218 | editing = 0; |
1217 | } | 1219 | } |
1220 | } else if (strncasecmp((char *) p, "file", cnt) == 0 ) { | ||
1221 | edit_status(); // show current file status | ||
1222 | } else if (sscanf((char *) p, "%d", &j) > 0) { | ||
1223 | dot = find_line(j); // go to line # j | ||
1224 | dot_skip_over_ws(); | ||
1218 | } else { // unrecognised cmd | 1225 | } else { // unrecognised cmd |
1219 | ni((Byte *) buf); | 1226 | ni((Byte *) p); |
1220 | } | 1227 | } |
1221 | #endif /* BB_FEATURE_VI_COLON */ | 1228 | #endif /* BB_FEATURE_VI_COLON */ |
1222 | break; | 1229 | break; |
@@ -1287,10 +1294,10 @@ static void do_cmd(Byte c) | |||
1287 | end_cmd_q(); // stop adding to q | 1294 | end_cmd_q(); // stop adding to q |
1288 | #endif /* BB_FEATURE_VI_DOT_CMD */ | 1295 | #endif /* BB_FEATURE_VI_DOT_CMD */ |
1289 | break; | 1296 | break; |
1290 | case 'G': // G- goto to a line number (default= E-O-F) | 1297 | case 'G': // G- goto to a line number (default= E-O-F) |
1291 | dot = end - 1; // assume E-O-F | 1298 | dot = end - 1; // assume E-O-F |
1292 | if (cmdcnt > 0) { | 1299 | if (cmdcnt > 0) { |
1293 | dot = find_line(cmdcnt); // what line is #cmdcnt | 1300 | dot = find_line(cmdcnt); // what line is #cmdcnt |
1294 | } | 1301 | } |
1295 | dot_skip_over_ws(); | 1302 | dot_skip_over_ws(); |
1296 | break; | 1303 | break; |
@@ -1338,13 +1345,13 @@ static void do_cmd(Byte c) | |||
1338 | dot_begin(); | 1345 | dot_begin(); |
1339 | dot_skip_over_ws(); | 1346 | dot_skip_over_ws(); |
1340 | break; | 1347 | break; |
1341 | case 'M': // M- goto middle line on screen | 1348 | case 'M': // M- goto middle line on screen |
1342 | dot = screenbegin; | 1349 | dot = screenbegin; |
1343 | for (cnt = 0; cnt < (rows-1) / 2; cnt++) | 1350 | for (cnt = 0; cnt < (rows-1) / 2; cnt++) |
1344 | dot = next_line(dot); | 1351 | dot = next_line(dot); |
1345 | break; | 1352 | break; |
1346 | case 'O': // O- open a empty line above | 1353 | case 'O': // O- open a empty line above |
1347 | // 0i\n\033-i | 1354 | // 0i\n ESC -i |
1348 | p = begin_line(dot); | 1355 | p = begin_line(dot); |
1349 | if (p[-1] == '\n') { | 1356 | if (p[-1] == '\n') { |
1350 | dot_prev(); | 1357 | dot_prev(); |
@@ -1353,7 +1360,7 @@ static void do_cmd(Byte c) | |||
1353 | dot = char_insert(dot, '\n'); | 1360 | dot = char_insert(dot, '\n'); |
1354 | } else { | 1361 | } else { |
1355 | dot_begin(); // 0 | 1362 | dot_begin(); // 0 |
1356 | dot = char_insert(dot, '\n'); // i\n\033 | 1363 | dot = char_insert(dot, '\n'); // i\n ESC |
1357 | dot_prev(); // - | 1364 | dot_prev(); // - |
1358 | } | 1365 | } |
1359 | goto dc_i; | 1366 | goto dc_i; |
@@ -1390,6 +1397,7 @@ static void do_cmd(Byte c) | |||
1390 | } | 1397 | } |
1391 | if (file_modified == TRUE | 1398 | if (file_modified == TRUE |
1392 | #ifdef BB_FEATURE_VI_READONLY | 1399 | #ifdef BB_FEATURE_VI_READONLY |
1400 | && vi_readonly == FALSE | ||
1393 | && readonly == FALSE | 1401 | && readonly == FALSE |
1394 | #endif /* BB_FEATURE_VI_READONLY */ | 1402 | #endif /* BB_FEATURE_VI_READONLY */ |
1395 | ) { | 1403 | ) { |
@@ -1452,7 +1460,7 @@ static void do_cmd(Byte c) | |||
1452 | } | 1460 | } |
1453 | } | 1461 | } |
1454 | dot = yank_delete(p, q, 0, yf); // delete word | 1462 | dot = yank_delete(p, q, 0, yf); // delete word |
1455 | } else if (strchr("^0bBeE$", c1)) { | 1463 | } else if (strchr("^0bBeEft$", c1)) { |
1456 | // single line copy text into a register and delete | 1464 | // single line copy text into a register and delete |
1457 | dot = yank_delete(p, q, 0, yf); // delete word | 1465 | dot = yank_delete(p, q, 0, yf); // delete word |
1458 | } else if (strchr("cdykjHL%+-{}\r\n", c1)) { | 1466 | } else if (strchr("cdykjHL%+-{}\r\n", c1)) { |
@@ -1514,6 +1522,13 @@ static void do_cmd(Byte c) | |||
1514 | } | 1522 | } |
1515 | end_cmd_q(); // stop adding to q | 1523 | end_cmd_q(); // stop adding to q |
1516 | break; | 1524 | break; |
1525 | case 't': // t- move to char prior to next x | ||
1526 | last_forward_char = get_one_char(); | ||
1527 | do_cmd(';'); | ||
1528 | if (*dot == last_forward_char) | ||
1529 | dot_left(); | ||
1530 | last_forward_char= 0; | ||
1531 | break; | ||
1517 | case 'w': // w- forward a word | 1532 | case 'w': // w- forward a word |
1518 | if (cmdcnt-- > 1) { | 1533 | if (cmdcnt-- > 1) { |
1519 | do_cmd(c); | 1534 | do_cmd(c); |
@@ -1699,19 +1714,19 @@ static void colon(Byte * buf) | |||
1699 | int useforce, forced; | 1714 | int useforce, forced; |
1700 | struct stat st_buf; | 1715 | struct stat st_buf; |
1701 | 1716 | ||
1702 | // :3154 // if (-e line 3154) goto it else stay put | 1717 | // :3154 // if (-e line 3154) goto it else stay put |
1703 | // :4,33w! foo // write a portion of buffer to file "foo" | 1718 | // :4,33w! foo // write a portion of buffer to file "foo" |
1704 | // :w // write all of buffer to current file | 1719 | // :w // write all of buffer to current file |
1705 | // :q // quit | 1720 | // :q // quit |
1706 | // :q! // quit- dont care about modified file | 1721 | // :q! // quit- dont care about modified file |
1707 | // :'a,'z!sort -u // filter block through sort | 1722 | // :'a,'z!sort -u // filter block through sort |
1708 | // :'f // goto mark "f" | 1723 | // :'f // goto mark "f" |
1709 | // :'fl // list literal the mark "f" line | 1724 | // :'fl // list literal the mark "f" line |
1710 | // :.r bar // read file "bar" into buffer before dot | 1725 | // :.r bar // read file "bar" into buffer before dot |
1711 | // :/123/,/abc/d // delete lines from "123" line to "abc" line | 1726 | // :/123/,/abc/d // delete lines from "123" line to "abc" line |
1712 | // :/xyz/ // goto the "xyz" line | 1727 | // :/xyz/ // goto the "xyz" line |
1713 | // :s/find/replace/ // substitute pattern "find" with "replace" | 1728 | // :s/find/replace/ // substitute pattern "find" with "replace" |
1714 | // :!<cmd> // run <cmd> then return | 1729 | // :!<cmd> // run <cmd> then return |
1715 | // | 1730 | // |
1716 | if (strlen((char *) buf) <= 0) | 1731 | if (strlen((char *) buf) <= 0) |
1717 | goto vc1; | 1732 | goto vc1; |
@@ -1725,8 +1740,8 @@ static void colon(Byte * buf) | |||
1725 | r = end - 1; | 1740 | r = end - 1; |
1726 | li = count_lines(text, end - 1); | 1741 | li = count_lines(text, end - 1); |
1727 | fn = cfn; // default to current file | 1742 | fn = cfn; // default to current file |
1728 | memset(cmd, '\0', BUFSIZ); // clear cmd[] | 1743 | memset(cmd, '\0', BUFSIZ); // clear cmd[] |
1729 | memset(args, '\0', BUFSIZ); // clear args[] | 1744 | memset(args, '\0', BUFSIZ); // clear args[] |
1730 | 1745 | ||
1731 | // look for optional address(es) :. :1 :1,9 :'q,'a :% | 1746 | // look for optional address(es) :. :1 :1,9 :'q,'a :% |
1732 | buf = get_address(buf, &b, &e); | 1747 | buf = get_address(buf, &b, &e); |
@@ -1745,7 +1760,7 @@ static void colon(Byte * buf) | |||
1745 | while (isblnk(*buf)) | 1760 | while (isblnk(*buf)) |
1746 | buf++; | 1761 | buf++; |
1747 | strcpy((char *) args, (char *) buf); | 1762 | strcpy((char *) args, (char *) buf); |
1748 | if (last_char_is((char *)cmd,'!')) { | 1763 | if (last_char_is((char *)cmd, '!')) { |
1749 | useforce = TRUE; | 1764 | useforce = TRUE; |
1750 | cmd[strlen((char *) cmd) - 1] = '\0'; // get rid of ! | 1765 | cmd[strlen((char *) cmd) - 1] = '\0'; // get rid of ! |
1751 | } | 1766 | } |
@@ -1775,7 +1790,7 @@ static void colon(Byte * buf) | |||
1775 | } else if (strncmp((char *) cmd, "!", 1) == 0) { // run a cmd | 1790 | } else if (strncmp((char *) cmd, "!", 1) == 0) { // run a cmd |
1776 | // :!ls run the <cmd> | 1791 | // :!ls run the <cmd> |
1777 | (void) alarm(0); // wait for input- no alarms | 1792 | (void) alarm(0); // wait for input- no alarms |
1778 | place_cursor(rows - 1, 0); // go to Status line | 1793 | place_cursor(rows - 1, 0, FALSE); // go to Status line |
1779 | clear_to_eol(); // clear the line | 1794 | clear_to_eol(); // clear the line |
1780 | cookmode(); | 1795 | cookmode(); |
1781 | system(orig_buf+1); // run the cmd | 1796 | system(orig_buf+1); // run the cmd |
@@ -1870,14 +1885,14 @@ static void colon(Byte * buf) | |||
1870 | #endif /* BB_FEATURE_VI_YANKMARK */ | 1885 | #endif /* BB_FEATURE_VI_YANKMARK */ |
1871 | // how many lines in text[]? | 1886 | // how many lines in text[]? |
1872 | li = count_lines(text, end - 1); | 1887 | li = count_lines(text, end - 1); |
1873 | psb("\"%s\"%s" | 1888 | psb("\"%s\"%s" |
1874 | #ifdef BB_FEATURE_VI_READONLY | 1889 | #ifdef BB_FEATURE_VI_READONLY |
1875 | "%s" | 1890 | "%s" |
1876 | #endif /* BB_FEATURE_VI_READONLY */ | 1891 | #endif /* BB_FEATURE_VI_READONLY */ |
1877 | " %dL, %dC", cfn, | 1892 | " %dL, %dC", cfn, |
1878 | (sr < 0 ? " [New file]" : ""), | 1893 | (sr < 0 ? " [New file]" : ""), |
1879 | #ifdef BB_FEATURE_VI_READONLY | 1894 | #ifdef BB_FEATURE_VI_READONLY |
1880 | (readonly == TRUE ? " [Read only]" : ""), | 1895 | ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), |
1881 | #endif /* BB_FEATURE_VI_READONLY */ | 1896 | #endif /* BB_FEATURE_VI_READONLY */ |
1882 | li, ch); | 1897 | li, ch); |
1883 | } else if (strncasecmp((char *) cmd, "file", i) == 0) { // what File is this | 1898 | } else if (strncasecmp((char *) cmd, "file", i) == 0) { // what File is this |
@@ -1896,7 +1911,7 @@ static void colon(Byte * buf) | |||
1896 | } | 1911 | } |
1897 | } else if (strncasecmp((char *) cmd, "features", i) == 0) { // what features are available | 1912 | } else if (strncasecmp((char *) cmd, "features", i) == 0) { // what features are available |
1898 | // print out values of all features | 1913 | // print out values of all features |
1899 | place_cursor(rows - 1, 0); // go to Status line, bottom of screen | 1914 | place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen |
1900 | clear_to_eol(); // clear the line | 1915 | clear_to_eol(); // clear the line |
1901 | cookmode(); | 1916 | cookmode(); |
1902 | show_help(); | 1917 | show_help(); |
@@ -1907,7 +1922,7 @@ static void colon(Byte * buf) | |||
1907 | q = begin_line(dot); // assume .,. for the range | 1922 | q = begin_line(dot); // assume .,. for the range |
1908 | r = end_line(dot); | 1923 | r = end_line(dot); |
1909 | } | 1924 | } |
1910 | place_cursor(rows - 1, 0); // go to Status line, bottom of screen | 1925 | place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen |
1911 | clear_to_eol(); // clear the line | 1926 | clear_to_eol(); // clear the line |
1912 | write(1, "\r\n", 2); | 1927 | write(1, "\r\n", 2); |
1913 | for (; q <= r; q++) { | 1928 | for (; q <= r; q++) { |
@@ -1973,13 +1988,13 @@ static void colon(Byte * buf) | |||
1973 | goto vc1; // nothing was inserted | 1988 | goto vc1; // nothing was inserted |
1974 | // how many lines in text[]? | 1989 | // how many lines in text[]? |
1975 | li = count_lines(q, q + ch - 1); | 1990 | li = count_lines(q, q + ch - 1); |
1976 | psb("\"%s\"" | 1991 | psb("\"%s\"" |
1977 | #ifdef BB_FEATURE_VI_READONLY | 1992 | #ifdef BB_FEATURE_VI_READONLY |
1978 | "%s" | 1993 | "%s" |
1979 | #endif /* BB_FEATURE_VI_READONLY */ | 1994 | #endif /* BB_FEATURE_VI_READONLY */ |
1980 | " %dL, %dC", fn, | 1995 | " %dL, %dC", fn, |
1981 | #ifdef BB_FEATURE_VI_READONLY | 1996 | #ifdef BB_FEATURE_VI_READONLY |
1982 | (readonly == TRUE ? " [Read only]" : ""), | 1997 | ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), |
1983 | #endif /* BB_FEATURE_VI_READONLY */ | 1998 | #endif /* BB_FEATURE_VI_READONLY */ |
1984 | li, ch); | 1999 | li, ch); |
1985 | if (ch > 0) { | 2000 | if (ch > 0) { |
@@ -2001,13 +2016,16 @@ static void colon(Byte * buf) | |||
2001 | i = 0; // offset into args | 2016 | i = 0; // offset into args |
2002 | if (strlen((char *) args) == 0) { | 2017 | if (strlen((char *) args) == 0) { |
2003 | // print out values of all options | 2018 | // print out values of all options |
2004 | place_cursor(rows - 1, 0); // go to Status line, bottom of screen | 2019 | place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen |
2005 | clear_to_eol(); // clear the line | 2020 | clear_to_eol(); // clear the line |
2006 | printf("----------------------------------------\r\n"); | 2021 | printf("----------------------------------------\r\n"); |
2007 | #ifdef BB_FEATURE_VI_SETOPTS | 2022 | #ifdef BB_FEATURE_VI_SETOPTS |
2008 | if (!autoindent) | 2023 | if (!autoindent) |
2009 | printf("no"); | 2024 | printf("no"); |
2010 | printf("autoindent "); | 2025 | printf("autoindent "); |
2026 | if (!err_method) | ||
2027 | printf("no"); | ||
2028 | printf("flash "); | ||
2011 | if (!ignorecase) | 2029 | if (!ignorecase) |
2012 | printf("no"); | 2030 | printf("no"); |
2013 | printf("ignorecase "); | 2031 | printf("ignorecase "); |
@@ -2026,6 +2044,10 @@ static void colon(Byte * buf) | |||
2026 | strncasecmp((char *) args + i, "ai", 2) == 0) { | 2044 | strncasecmp((char *) args + i, "ai", 2) == 0) { |
2027 | autoindent = (i == 2) ? 0 : 1; | 2045 | autoindent = (i == 2) ? 0 : 1; |
2028 | } | 2046 | } |
2047 | if (strncasecmp((char *) args + i, "flash", 5) == 0 || | ||
2048 | strncasecmp((char *) args + i, "fl", 2) == 0) { | ||
2049 | err_method = (i == 2) ? 0 : 1; | ||
2050 | } | ||
2029 | if (strncasecmp((char *) args + i, "ignorecase", 10) == 0 || | 2051 | if (strncasecmp((char *) args + i, "ignorecase", 10) == 0 || |
2030 | strncasecmp((char *) args + i, "ic", 2) == 0) { | 2052 | strncasecmp((char *) args + i, "ic", 2) == 0) { |
2031 | ignorecase = (i == 2) ? 0 : 1; | 2053 | ignorecase = (i == 2) ? 0 : 1; |
@@ -2096,7 +2118,7 @@ static void colon(Byte * buf) | |||
2096 | fn = args; | 2118 | fn = args; |
2097 | } | 2119 | } |
2098 | #ifdef BB_FEATURE_VI_READONLY | 2120 | #ifdef BB_FEATURE_VI_READONLY |
2099 | if (readonly == TRUE && useforce == FALSE) { | 2121 | if ((vi_readonly == TRUE || readonly == TRUE) && useforce == FALSE) { |
2100 | psbs("\"%s\" File is read only", fn); | 2122 | psbs("\"%s\" File is read only", fn); |
2101 | goto vc3; | 2123 | goto vc3; |
2102 | } | 2124 | } |
@@ -2452,10 +2474,18 @@ static Byte *bound_dot(Byte * p) // make sure text[0] <= P < "end" | |||
2452 | 2474 | ||
2453 | static Byte *new_screen(int ro, int co) | 2475 | static Byte *new_screen(int ro, int co) |
2454 | { | 2476 | { |
2477 | int li; | ||
2478 | |||
2455 | if (screen != 0) | 2479 | if (screen != 0) |
2456 | free(screen); | 2480 | free(screen); |
2457 | screensize = ro * co + 8; | 2481 | screensize = ro * co + 8; |
2458 | screen = (Byte *) malloc(screensize); | 2482 | screen = (Byte *) malloc(screensize); |
2483 | // initialize the new screen. assume this will be a empty file. | ||
2484 | screen_erase(); | ||
2485 | // non-existant text[] lines start with a tilde (~). | ||
2486 | for (li = 1; li < ro - 1; li++) { | ||
2487 | screen[(li * co) + 0] = '~'; | ||
2488 | } | ||
2459 | return (screen); | 2489 | return (screen); |
2460 | } | 2490 | } |
2461 | 2491 | ||
@@ -2469,9 +2499,9 @@ static Byte *new_text(int size) | |||
2469 | } | 2499 | } |
2470 | text = (Byte *) malloc(size + 8); | 2500 | text = (Byte *) malloc(size + 8); |
2471 | memset(text, '\0', size); // clear new text[] | 2501 | memset(text, '\0', size); // clear new text[] |
2472 | //text += 4; // leave some room for "oops" | 2502 | //text += 4; // leave some room for "oops" |
2473 | textend = text + size - 1; | 2503 | textend = text + size - 1; |
2474 | //textend -= 4; // leave some root for "oops" | 2504 | //textend -= 4; // leave some root for "oops" |
2475 | return (text); | 2505 | return (text); |
2476 | } | 2506 | } |
2477 | 2507 | ||
@@ -2596,7 +2626,7 @@ static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p' | |||
2596 | cmd_mode = 0; | 2626 | cmd_mode = 0; |
2597 | cmdcnt = 0; | 2627 | cmdcnt = 0; |
2598 | end_cmd_q(); // stop adding to q | 2628 | end_cmd_q(); // stop adding to q |
2599 | *status_buffer = '\0'; // clear the status buffer | 2629 | strcpy((char *) status_buffer, " "); // clear the status buffer |
2600 | if (p[-1] != '\n') { | 2630 | if (p[-1] != '\n') { |
2601 | p--; | 2631 | p--; |
2602 | } | 2632 | } |
@@ -2667,7 +2697,7 @@ static Byte find_range(Byte ** start, Byte ** stop, Byte c) | |||
2667 | q = next_line(q); | 2697 | q = next_line(q); |
2668 | } | 2698 | } |
2669 | q = end_line(q); | 2699 | q = end_line(q); |
2670 | } else if (strchr("^%$0bBeE", c)) { | 2700 | } else if (strchr("^%$0bBeEft", c)) { |
2671 | // These cmds operate on char positions | 2701 | // These cmds operate on char positions |
2672 | do_cmd(c); // execute movement cmd | 2702 | do_cmd(c); // execute movement cmd |
2673 | q = dot; | 2703 | q = dot; |
@@ -2931,6 +2961,7 @@ static void show_help(void) | |||
2931 | printf("\tNamed buffers with \"x\n"); | 2961 | printf("\tNamed buffers with \"x\n"); |
2932 | #endif /* BB_FEATURE_VI_YANKMARK */ | 2962 | #endif /* BB_FEATURE_VI_YANKMARK */ |
2933 | #ifdef BB_FEATURE_VI_READONLY | 2963 | #ifdef BB_FEATURE_VI_READONLY |
2964 | printf("\tReadonly if vi is called as \"view\"\n"); | ||
2934 | printf("\tReadonly with -R command line arg\n"); | 2965 | printf("\tReadonly with -R command line arg\n"); |
2935 | #endif /* BB_FEATURE_VI_READONLY */ | 2966 | #endif /* BB_FEATURE_VI_READONLY */ |
2936 | #ifdef BB_FEATURE_VI_SET | 2967 | #ifdef BB_FEATURE_VI_SET |
@@ -3111,6 +3142,7 @@ static void rawmode(void) | |||
3111 | term_vi = term_orig; | 3142 | term_vi = term_orig; |
3112 | term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG ON- allow intr's | 3143 | term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG ON- allow intr's |
3113 | term_vi.c_iflag &= (~IXON & ~ICRNL); | 3144 | term_vi.c_iflag &= (~IXON & ~ICRNL); |
3145 | term_vi.c_oflag &= (~ONLCR); | ||
3114 | term_vi.c_cc[VMIN] = 1; | 3146 | term_vi.c_cc[VMIN] = 1; |
3115 | term_vi.c_cc[VTIME] = 0; | 3147 | term_vi.c_cc[VTIME] = 0; |
3116 | erase_char = term_vi.c_cc[VERASE]; | 3148 | erase_char = term_vi.c_cc[VERASE]; |
@@ -3172,7 +3204,7 @@ static void cont_sig(int sig) | |||
3172 | //----- Come here when we get a Suspend signal ------------------- | 3204 | //----- Come here when we get a Suspend signal ------------------- |
3173 | static void suspend_sig(int sig) | 3205 | static void suspend_sig(int sig) |
3174 | { | 3206 | { |
3175 | place_cursor(rows, 0); // go to bottom of screen | 3207 | place_cursor(rows - 1, 0, FALSE); // go to bottom of screen |
3176 | clear_to_eol(); // Erase to end of line | 3208 | clear_to_eol(); // Erase to end of line |
3177 | cookmode(); // terminal to "cooked" | 3209 | cookmode(); // terminal to "cooked" |
3178 | 3210 | ||
@@ -3181,7 +3213,7 @@ static void suspend_sig(int sig) | |||
3181 | kill(getpid(), SIGTSTP); | 3213 | kill(getpid(), SIGTSTP); |
3182 | } | 3214 | } |
3183 | 3215 | ||
3184 | //----- Come here when we get a signal -------------------- | 3216 | //----- Come here when we get a signal --------------------------- |
3185 | static void catch_sig(int sig) | 3217 | static void catch_sig(int sig) |
3186 | { | 3218 | { |
3187 | signal(SIGHUP, catch_sig); | 3219 | signal(SIGHUP, catch_sig); |
@@ -3382,7 +3414,6 @@ static Byte get_one_char() | |||
3382 | return (c); // return the char, where ever it came from | 3414 | return (c); // return the char, where ever it came from |
3383 | } | 3415 | } |
3384 | 3416 | ||
3385 | #if defined(BB_FEATURE_VI_SEARCH) || defined(BB_FEATURE_VI_COLON) | ||
3386 | static Byte *get_input_line(Byte * prompt) // get input line- use "status line" | 3417 | static Byte *get_input_line(Byte * prompt) // get input line- use "status line" |
3387 | { | 3418 | { |
3388 | Byte buf[BUFSIZ]; | 3419 | Byte buf[BUFSIZ]; |
@@ -3392,7 +3423,7 @@ static Byte *get_input_line(Byte * prompt) // get input line- use "status line" | |||
3392 | 3423 | ||
3393 | strcpy((char *) buf, (char *) prompt); | 3424 | strcpy((char *) buf, (char *) prompt); |
3394 | *status_buffer = '\0'; // clear the status buffer | 3425 | *status_buffer = '\0'; // clear the status buffer |
3395 | place_cursor(rows - 1, 0); // go to Status line, bottom of screen | 3426 | place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen |
3396 | clear_to_eol(); // clear the line | 3427 | clear_to_eol(); // clear the line |
3397 | write(1, prompt, strlen((char *) prompt)); // write out the :, /, or ? prompt | 3428 | write(1, prompt, strlen((char *) prompt)); // write out the :, /, or ? prompt |
3398 | 3429 | ||
@@ -3421,7 +3452,6 @@ static Byte *get_input_line(Byte * prompt) // get input line- use "status line" | |||
3421 | obufp = (Byte *) strdup((char *) buf); | 3452 | obufp = (Byte *) strdup((char *) buf); |
3422 | return (obufp); | 3453 | return (obufp); |
3423 | } | 3454 | } |
3424 | #endif /* BB_FEATURE_VI_SEARCH || BB_FEATURE_VI_COLON */ | ||
3425 | 3455 | ||
3426 | static int file_size(Byte * fn) // what is the byte size of "fn" | 3456 | static int file_size(Byte * fn) // what is the byte size of "fn" |
3427 | { | 3457 | { |
@@ -3465,9 +3495,15 @@ static int file_insert(Byte * fn, Byte * p, int size) | |||
3465 | } | 3495 | } |
3466 | 3496 | ||
3467 | // see if we can open the file | 3497 | // see if we can open the file |
3498 | #ifdef BB_FEATURE_VI_READONLY | ||
3499 | if (vi_readonly == TRUE) goto fi1; // do not try write-mode | ||
3500 | #endif | ||
3468 | fd = open((char *) fn, O_RDWR); // assume read & write | 3501 | fd = open((char *) fn, O_RDWR); // assume read & write |
3469 | if (fd < 0) { | 3502 | if (fd < 0) { |
3470 | // could not open for writing- maybe file is read only | 3503 | // could not open for writing- maybe file is read only |
3504 | #ifdef BB_FEATURE_VI_READONLY | ||
3505 | fi1: | ||
3506 | #endif | ||
3471 | fd = open((char *) fn, O_RDONLY); // try read-only | 3507 | fd = open((char *) fn, O_RDONLY); // try read-only |
3472 | if (fd < 0) { | 3508 | if (fd < 0) { |
3473 | psbs("\"%s\" %s", fn, "could not open file"); | 3509 | psbs("\"%s\" %s", fn, "could not open file"); |
@@ -3529,51 +3565,96 @@ static int file_write(Byte * fn, Byte * first, Byte * last) | |||
3529 | // 1,0 ... 1,79 | 3565 | // 1,0 ... 1,79 |
3530 | // . ... . | 3566 | // . ... . |
3531 | // . ... . | 3567 | // . ... . |
3532 | // 22,0 ... 22,79 | 3568 | // 22,0 ... 22,79 |
3533 | // 23,0 ... 23,79 status line | 3569 | // 23,0 ... 23,79 status line |
3534 | // | 3570 | // |
3535 | 3571 | ||
3536 | //----- Move the cursor to row x col (count from 0, not 1) ------- | 3572 | //----- Move the cursor to row x col (count from 0, not 1) ------- |
3537 | static void place_cursor(int row, int col) | 3573 | static void place_cursor(int row, int col, int opti) |
3538 | { | 3574 | { |
3539 | Byte buf[30]; | 3575 | char cm1[BUFSIZ]; |
3576 | char *cm; | ||
3540 | int l; | 3577 | int l; |
3541 | 3578 | #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR | |
3542 | if (row < 0) | 3579 | char cm2[BUFSIZ]; |
3543 | row = 0; | 3580 | Byte *screenp; |
3544 | if (row >= rows) | 3581 | // char cm3[BUFSIZ]; |
3545 | row = rows - 1; | 3582 | int Rrow= last_row; |
3546 | if (col < 0) | 3583 | #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ |
3547 | col = 0; | 3584 | |
3548 | if (col >= columns) | 3585 | memset(cm1, '\0', BUFSIZ - 1); // clear the buffer |
3549 | col = columns - 1; | 3586 | |
3550 | sprintf((char *) buf, "%c[%d;%dH", 0x1b, row + 1, col + 1); | 3587 | if (row < 0) row = 0; |
3551 | l = strlen((char *) buf); | 3588 | if (row >= rows) row = rows - 1; |
3552 | write(1, buf, l); | 3589 | if (col < 0) col = 0; |
3590 | if (col >= columns) col = columns - 1; | ||
3591 | |||
3592 | //----- 1. Try the standard terminal ESC sequence | ||
3593 | sprintf((char *) cm1, CMrc, row + 1, col + 1); | ||
3594 | cm= cm1; | ||
3595 | if (opti == FALSE) goto pc0; | ||
3596 | |||
3597 | #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR | ||
3598 | //----- find the minimum # of chars to move cursor ------------- | ||
3599 | //----- 2. Try moving with discreet chars (Newline, [back]space, ...) | ||
3600 | memset(cm2, '\0', BUFSIZ - 1); // clear the buffer | ||
3601 | |||
3602 | // move to the correct row | ||
3603 | while (row < Rrow) { | ||
3604 | // the cursor has to move up | ||
3605 | strcat(cm2, CMup); | ||
3606 | Rrow--; | ||
3607 | } | ||
3608 | while (row > Rrow) { | ||
3609 | // the cursor has to move down | ||
3610 | strcat(cm2, CMdown); | ||
3611 | Rrow++; | ||
3612 | } | ||
3613 | |||
3614 | // now move to the correct column | ||
3615 | strcat(cm2, "\r"); // start at col 0 | ||
3616 | // just send out orignal source char to get to correct place | ||
3617 | screenp = &screen[row * columns]; // start of screen line | ||
3618 | strncat(cm2, screenp, col); | ||
3619 | |||
3620 | //----- 3. Try some other way of moving cursor | ||
3621 | //--------------------------------------------- | ||
3622 | |||
3623 | // pick the shortest cursor motion to send out | ||
3624 | cm= cm1; | ||
3625 | if (strlen(cm2) < strlen(cm)) { | ||
3626 | cm= cm2; | ||
3627 | } /* else if (strlen(cm3) < strlen(cm)) { | ||
3628 | cm= cm3; | ||
3629 | } */ | ||
3630 | #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ | ||
3631 | pc0: | ||
3632 | l= strlen(cm); | ||
3633 | if (l) write(1, cm, l); // move the cursor | ||
3553 | } | 3634 | } |
3554 | 3635 | ||
3555 | //----- Erase from cursor to end of line ----------------------- | 3636 | //----- Erase from cursor to end of line ----------------------- |
3556 | static void clear_to_eol() | 3637 | static void clear_to_eol() |
3557 | { | 3638 | { |
3558 | write(1, "\033[0K", 4); // Erase from cursor to end of line | 3639 | write(1, Ceol, strlen(Ceol)); // Erase from cursor to end of line |
3559 | } | 3640 | } |
3560 | 3641 | ||
3561 | //----- Erase from cursor to end of screen ----------------------- | 3642 | //----- Erase from cursor to end of screen ----------------------- |
3562 | static void clear_to_eos() | 3643 | static void clear_to_eos() |
3563 | { | 3644 | { |
3564 | write(1, "\033[0J", 4); // Erase from cursor to end of screen | 3645 | write(1, Ceos, strlen(Ceos)); // Erase from cursor to end of screen |
3565 | } | 3646 | } |
3566 | 3647 | ||
3567 | //----- Start standout mode ------------------------------------ | 3648 | //----- Start standout mode ------------------------------------ |
3568 | static void standout_start() // send "start reverse video" sequence | 3649 | static void standout_start() // send "start reverse video" sequence |
3569 | { | 3650 | { |
3570 | write(1, "\033[7m", 4); // Start reverse video mode | 3651 | write(1, SOs, strlen(SOs)); // Start reverse video mode |
3571 | } | 3652 | } |
3572 | 3653 | ||
3573 | //----- End standout mode -------------------------------------- | 3654 | //----- End standout mode -------------------------------------- |
3574 | static void standout_end() // send "end reverse video" sequence | 3655 | static void standout_end() // send "end reverse video" sequence |
3575 | { | 3656 | { |
3576 | write(1, "\033[0m", 4); // End reverse video mode | 3657 | write(1, SOn, strlen(SOn)); // End reverse video mode |
3577 | } | 3658 | } |
3578 | 3659 | ||
3579 | //----- Flash the screen -------------------------------------- | 3660 | //----- Flash the screen -------------------------------------- |
@@ -3588,7 +3669,7 @@ static void flash(int h) | |||
3588 | 3669 | ||
3589 | static void beep() | 3670 | static void beep() |
3590 | { | 3671 | { |
3591 | write(1, "\007", 1); // send out a bell character | 3672 | write(1, bell, strlen(bell)); // send out a bell character |
3592 | } | 3673 | } |
3593 | 3674 | ||
3594 | static void indicate_error(char c) | 3675 | static void indicate_error(char c) |
@@ -3608,25 +3689,25 @@ static void indicate_error(char c) | |||
3608 | //----- Erase the Screen[] memory ------------------------------ | 3689 | //----- Erase the Screen[] memory ------------------------------ |
3609 | static void screen_erase() | 3690 | static void screen_erase() |
3610 | { | 3691 | { |
3611 | int i; | 3692 | memset(screen, ' ', screensize); // clear new screen |
3612 | |||
3613 | for (i = 0; i < screensize; i++) { | ||
3614 | screen[i] = '\0'; | ||
3615 | } | ||
3616 | } | 3693 | } |
3617 | 3694 | ||
3618 | //----- Draw the status line at bottom of the screen ------------- | 3695 | //----- Draw the status line at bottom of the screen ------------- |
3619 | static void show_status_line(void) | 3696 | static void show_status_line(void) |
3620 | { | 3697 | { |
3621 | int cnt; | 3698 | static int last_cksum; |
3699 | int l, cnt, cksum; | ||
3622 | 3700 | ||
3623 | cnt = strlen((char *) status_buffer); | 3701 | cnt = strlen((char *) status_buffer); |
3624 | place_cursor(rows - 1, 0); // put cursor on status line | 3702 | for (cksum= l= 0; l < cnt; l++) { cksum += (int)(status_buffer[l]); } |
3625 | if (cnt > 0) { | 3703 | // don't write the status line unless it changes |
3704 | if (cnt > 0 && last_cksum != cksum) { | ||
3705 | last_cksum= cksum; // remember if we have seen this line | ||
3706 | place_cursor(rows - 1, 0, FALSE); // put cursor on status line | ||
3626 | write(1, status_buffer, cnt); | 3707 | write(1, status_buffer, cnt); |
3708 | clear_to_eol(); | ||
3709 | place_cursor(crow, ccol, FALSE); // put cursor back in correct place | ||
3627 | } | 3710 | } |
3628 | clear_to_eol(); | ||
3629 | place_cursor(crow, ccol); // put cursor back in correct place | ||
3630 | } | 3711 | } |
3631 | 3712 | ||
3632 | //----- format the status buffer, the bottom line of screen ------ | 3713 | //----- format the status buffer, the bottom line of screen ------ |
@@ -3636,10 +3717,10 @@ static void psbs(char *format, ...) | |||
3636 | va_list args; | 3717 | va_list args; |
3637 | 3718 | ||
3638 | va_start(args, format); | 3719 | va_start(args, format); |
3639 | strcpy((char *) status_buffer, "\033[7m"); // Terminal standout mode on | 3720 | strcpy((char *) status_buffer, SOs); // Terminal standout mode on |
3640 | vsprintf((char *) status_buffer + strlen((char *) status_buffer), format, | 3721 | vsprintf((char *) status_buffer + strlen((char *) status_buffer), format, |
3641 | args); | 3722 | args); |
3642 | strcat((char *) status_buffer, "\033[0m"); // Terminal standout mode off | 3723 | strcat((char *) status_buffer, SOn); // Terminal standout mode off |
3643 | va_end(args); | 3724 | va_end(args); |
3644 | 3725 | ||
3645 | return; | 3726 | return; |
@@ -3686,7 +3767,7 @@ static void edit_status(void) // show file status on status line | |||
3686 | "%s line %d of %d --%d%%--", | 3767 | "%s line %d of %d --%d%%--", |
3687 | (cfn != 0 ? (char *) cfn : "No file"), | 3768 | (cfn != 0 ? (char *) cfn : "No file"), |
3688 | #ifdef BB_FEATURE_VI_READONLY | 3769 | #ifdef BB_FEATURE_VI_READONLY |
3689 | (readonly == TRUE ? " [Read only]" : ""), | 3770 | ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), |
3690 | #endif /* BB_FEATURE_VI_READONLY */ | 3771 | #endif /* BB_FEATURE_VI_READONLY */ |
3691 | (file_modified == TRUE ? " [modified]" : ""), | 3772 | (file_modified == TRUE ? " [modified]" : ""), |
3692 | cur, tot, percent); | 3773 | cur, tot, percent); |
@@ -3695,12 +3776,50 @@ static void edit_status(void) // show file status on status line | |||
3695 | //----- Force refresh of all Lines ----------------------------- | 3776 | //----- Force refresh of all Lines ----------------------------- |
3696 | static void redraw(int full_screen) | 3777 | static void redraw(int full_screen) |
3697 | { | 3778 | { |
3698 | place_cursor(0, 0); // put cursor in correct place | 3779 | place_cursor(0, 0, FALSE); // put cursor in correct place |
3699 | clear_to_eos(); // tel terminal to erase display | 3780 | clear_to_eos(); // tel terminal to erase display |
3700 | screen_erase(); // erase the internal screen buffer | 3781 | screen_erase(); // erase the internal screen buffer |
3701 | refresh(full_screen); // this will redraw the entire display | 3782 | refresh(full_screen); // this will redraw the entire display |
3702 | } | 3783 | } |
3703 | 3784 | ||
3785 | //----- Format a text[] line into a buffer --------------------- | ||
3786 | static void format_line(Byte *dest, Byte *src, int li) | ||
3787 | { | ||
3788 | int co; | ||
3789 | Byte c; | ||
3790 | |||
3791 | for (co= 0; co < MAX_SCR_COLS; co++) { | ||
3792 | c= ' '; // assume blank | ||
3793 | if (li > 0 && co == 0) { | ||
3794 | c = '~'; // not first line, assume Tilde | ||
3795 | } | ||
3796 | // are there chars in text[] and have we gone past the end | ||
3797 | if (text < end && src < end) { | ||
3798 | c = *src++; | ||
3799 | } | ||
3800 | if (c == '\n') | ||
3801 | break; | ||
3802 | if (c < ' ' || c > '~') { | ||
3803 | if (c == '\t') { | ||
3804 | c = ' '; | ||
3805 | // co % 8 != 7 | ||
3806 | for (; (co % tabstop) != (tabstop - 1); co++) { | ||
3807 | dest[co] = c; | ||
3808 | } | ||
3809 | } else { | ||
3810 | dest[co++] = '^'; | ||
3811 | c |= '@'; // make it visible | ||
3812 | c &= 0x7f; // get rid of hi bit | ||
3813 | } | ||
3814 | } | ||
3815 | // the co++ is done here so that the column will | ||
3816 | // not be overwritten when we blank-out the rest of line | ||
3817 | dest[co] = c; | ||
3818 | if (src >= end) | ||
3819 | break; | ||
3820 | } | ||
3821 | } | ||
3822 | |||
3704 | //----- Refresh the changed screen lines ----------------------- | 3823 | //----- Refresh the changed screen lines ----------------------- |
3705 | // Copy the source line from text[] into the buffer and note | 3824 | // Copy the source line from text[] into the buffer and note |
3706 | // if the current screenline is different from the new buffer. | 3825 | // if the current screenline is different from the new buffer. |
@@ -3709,97 +3828,102 @@ static void redraw(int full_screen) | |||
3709 | static void refresh(int full_screen) | 3828 | static void refresh(int full_screen) |
3710 | { | 3829 | { |
3711 | static int old_offset; | 3830 | static int old_offset; |
3712 | int li, co, changed; | 3831 | int li, changed; |
3713 | Byte c, buf[MAX_SCR_COLS]; | 3832 | Byte buf[MAX_SCR_COLS]; |
3714 | Byte *tp, *sp; // pointer into text[] and screen[] | 3833 | Byte *tp, *sp; // pointer into text[] and screen[] |
3834 | #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR | ||
3835 | int last_li= -2; // last line that changed- for optimizing cursor movement | ||
3836 | #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ | ||
3715 | 3837 | ||
3716 | #ifdef BB_FEATURE_VI_WIN_RESIZE | 3838 | #ifdef BB_FEATURE_VI_WIN_RESIZE |
3717 | window_size_get(0); | 3839 | window_size_get(0); |
3718 | #endif /* BB_FEATURE_VI_WIN_RESIZE */ | 3840 | #endif /* BB_FEATURE_VI_WIN_RESIZE */ |
3719 | sync_cursor(dot, &crow, &ccol); | 3841 | sync_cursor(dot, &crow, &ccol); // where cursor will be (on "dot") |
3720 | tp = screenbegin; // index into text[] of top line | 3842 | tp = screenbegin; // index into text[] of top line |
3843 | |||
3721 | // compare text[] to screen[] and mark screen[] lines that need updating | 3844 | // compare text[] to screen[] and mark screen[] lines that need updating |
3722 | for (li = 0; li < rows - 1; li++) { | 3845 | for (li = 0; li < rows - 1; li++) { |
3723 | // format current text line into buf with "columns" wide | 3846 | int cs, ce; // column start & end |
3724 | for (co = 0; co < columns + offset;) { | 3847 | memset(buf, ' ', MAX_SCR_COLS); // blank-out the buffer |
3725 | c = ' '; // assume blank | 3848 | buf[MAX_SCR_COLS-1] = 0; // NULL terminate the buffer |
3726 | if (li > 0 && co == 0) { | 3849 | // format current text line into buf |
3727 | c = '~'; // not first line, assume Tilde | 3850 | format_line(buf, tp, li); |
3728 | } | 3851 | |
3729 | // are there chars in text[] | 3852 | // skip to the end of the current text[] line |
3730 | // and have we gone past the end | 3853 | while (tp < end && *tp++ != '\n') /*no-op*/ ; |
3731 | if (text < end && tp < end) { | 3854 | |
3732 | c = *tp++; | 3855 | // see if there are any changes between vitual screen and buf |
3733 | } | 3856 | changed = FALSE; // assume no change |
3734 | if (c == '\n') | 3857 | cs= 0; |
3858 | ce= columns-1; | ||
3859 | sp = &screen[li * columns]; // start of screen line | ||
3860 | if (full_screen == TRUE) { | ||
3861 | // force re-draw of every single column from 0 - columns-1 | ||
3862 | goto re0; | ||
3863 | } | ||
3864 | // compare newly formatted buffer with virtual screen | ||
3865 | // look forward for first difference between buf and screen | ||
3866 | for ( ; cs <= ce; cs++) { | ||
3867 | if (buf[cs + offset] != sp[cs]) { | ||
3868 | changed = TRUE; // mark for redraw | ||
3735 | break; | 3869 | break; |
3736 | if (c < ' ' || c > '~') { | ||
3737 | if (c == '\t') { | ||
3738 | c = ' '; | ||
3739 | // co % 8 != 7 | ||
3740 | for (; (co % tabstop) != (tabstop - 1); co++) { | ||
3741 | buf[co] = c; | ||
3742 | } | ||
3743 | } else { | ||
3744 | buf[co++] = '^'; | ||
3745 | c |= '@'; // make it visible | ||
3746 | c &= 0x7f; // get rid of hi bit | ||
3747 | } | ||
3748 | } | 3870 | } |
3749 | // the co++ is done here so that the column will | ||
3750 | // not be overwritten when we blank-out the rest of line | ||
3751 | buf[co++] = c; | ||
3752 | if (tp >= end) | ||
3753 | break; | ||
3754 | } | ||
3755 | if (co >= columns + offset) { | ||
3756 | // skip to the end of the current text[] line | ||
3757 | while (tp < end && *tp++ != '\n'); | ||
3758 | } | 3871 | } |
3759 | // try to keep the cursor near it's current position | ||
3760 | // remember how many chars in this row- where the cursor sits | ||
3761 | // blank out the rest of the buffer | ||
3762 | while (co < MAX_SCR_COLS - 1) { | ||
3763 | buf[co++] = ' '; | ||
3764 | } | ||
3765 | buf[co++] = 0; // NULL terminate the buffer | ||
3766 | 3872 | ||
3767 | // if necessary, update virtual screen[] and terminal from buf[] | 3873 | // look backward for last difference between buf and screen |
3768 | changed = FALSE; // assume no change | 3874 | for ( ; ce >= cs; ce--) { |
3769 | sp = &screen[li * columns]; // start of screen line | 3875 | if (buf[ce + offset] != sp[ce]) { |
3770 | for (co = 0; co < columns; co++) { | ||
3771 | if (sp[co] != buf[co + offset]) { | ||
3772 | sp[co] = buf[co + offset]; | ||
3773 | changed = TRUE; // mark for redraw | 3876 | changed = TRUE; // mark for redraw |
3877 | break; | ||
3774 | } | 3878 | } |
3775 | } | 3879 | } |
3880 | // now, cs is index of first diff, and ce is index of last diff | ||
3881 | |||
3776 | // if horz offset has changed, force a redraw | 3882 | // if horz offset has changed, force a redraw |
3777 | if (offset != old_offset) | 3883 | if (offset != old_offset) { |
3884 | re0: | ||
3778 | changed = TRUE; | 3885 | changed = TRUE; |
3886 | } | ||
3779 | 3887 | ||
3780 | // write all marked screen lines out to terminal | 3888 | // make a sanity check of columns indexes |
3889 | if (cs < 0) cs= 0; | ||
3890 | if (ce > columns-1) ce= columns-1; | ||
3891 | if (cs > ce) { cs= 0; ce= columns-1; } | ||
3892 | // is there a change between vitual screen and buf | ||
3781 | if (changed == TRUE) { | 3893 | if (changed == TRUE) { |
3782 | place_cursor(li, 0); // put cursor in correct place | 3894 | // copy changed part of buffer to virtual screen |
3783 | clear_to_eol(); // Erase to end of line | 3895 | memmove(sp+cs, buf+(cs+offset), ce-cs+1); |
3784 | if (full_screen == FALSE) { | 3896 | |
3785 | // don't redraw every column on terminal | 3897 | // move cursor to column of first change |
3786 | // look backwards for last non-blank | 3898 | if (offset != old_offset) { |
3787 | for (co = columns + offset; co >= 0; co--) { | 3899 | // opti_cur_move is still too stupid |
3788 | // break; | 3900 | // to handle offsets correctly |
3789 | if (buf[co] != ' ') | 3901 | place_cursor(li, cs, FALSE); |
3790 | break; | ||
3791 | } | ||
3792 | co++; | ||
3793 | } else { | 3902 | } else { |
3794 | // redraw every column on terminal | 3903 | #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR |
3795 | co = columns; | 3904 | // if this just the next line |
3905 | // try to optimize cursor movement | ||
3906 | // otherwise, use standard ESC sequence | ||
3907 | place_cursor(li, cs, li == (last_li+1) ? TRUE : FALSE); | ||
3908 | last_li= li; | ||
3909 | #else /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ | ||
3910 | place_cursor(li, cs, FALSE); // use standard ESC sequence | ||
3911 | #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ | ||
3796 | } | 3912 | } |
3913 | |||
3797 | // write line out to terminal | 3914 | // write line out to terminal |
3798 | write(1, buf + offset, co); | 3915 | write(1, sp+cs, ce-cs+1); |
3916 | #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR | ||
3917 | last_row = li; | ||
3918 | #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ | ||
3799 | } | 3919 | } |
3800 | } | 3920 | } |
3801 | 3921 | ||
3802 | place_cursor(crow, ccol); | 3922 | place_cursor(crow, ccol, (crow == last_row) ? TRUE : FALSE); |
3923 | #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR | ||
3924 | last_row = crow; | ||
3925 | #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ | ||
3926 | |||
3803 | if (offset != old_offset) | 3927 | if (offset != old_offset) |
3804 | old_offset = offset; | 3928 | old_offset = offset; |
3805 | } | 3929 | } |