diff options
| -rw-r--r-- | editors/vi.c | 572 | ||||
| -rw-r--r-- | vi.c | 572 |
2 files changed, 696 insertions, 448 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 | } |
| @@ -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 | } |
