📄 vi.c
字号:
new_screen(rows, columns); // get memory for virtual screen cnt = file_size(fn); // file size size = 2 * cnt; // 200% of file size new_text(size); // get a text[] buffer screenbegin = dot = end = text; if (fn != 0) { ch= file_insert(fn, text, cnt); } if (ch < 1) { (void) char_insert(text, '\n'); // start empty buf with dummy line } file_modified = FALSE;#ifdef BB_FEATURE_VI_YANKMARK YDreg = 26; // default Yank/Delete reg Ureg = 27; // hold orig line for "U" cmd for (cnt = 0; cnt < 28; cnt++) { mark[cnt] = 0; } // init the marks mark[26] = mark[27] = text; // init "previous context"#endif /* BB_FEATURE_VI_YANKMARK */ err_method = 1; // flash last_forward_char = last_input_char = '\0'; crow = 0; ccol = 0; edit_status();#ifdef BB_FEATURE_VI_USE_SIGNALS signal(SIGHUP, catch_sig); signal(SIGINT, catch_sig); signal(SIGALRM, alarm_sig); signal(SIGTERM, catch_sig); signal(SIGQUIT, core_sig); signal(SIGILL, core_sig); signal(SIGTRAP, core_sig); signal(SIGIOT, core_sig); signal(SIGABRT, core_sig); signal(SIGFPE, core_sig); signal(SIGBUS, core_sig); signal(SIGSEGV, core_sig);#ifdef SIGSYS signal(SIGSYS, core_sig);#endif signal(SIGWINCH, winch_sig); signal(SIGTSTP, suspend_sig); sig = setjmp(restart); if (sig != 0) { msg = ""; if (sig == SIGWINCH) msg = "(window resize)"; if (sig == SIGHUP) msg = "(hangup)"; if (sig == SIGINT) msg = "(interrupt)"; if (sig == SIGTERM) msg = "(terminate)"; if (sig == SIGBUS) msg = "(bus error)"; if (sig == SIGSEGV) msg = "(I tried to touch invalid memory)"; if (sig == SIGALRM) msg = "(alarm)"; psbs("-- caught signal %d %s--", sig, msg); screenbegin = dot = text; }#endif /* BB_FEATURE_VI_USE_SIGNALS */ editing = 1; cmd_mode = 0; // 0=command 1=insert 2='R'eplace cmdcnt = 0; tabstop = 8; offset = 0; // no horizontal offset c = '\0';#ifdef BB_FEATURE_VI_DOT_CMD if (last_modifying_cmd != 0) free(last_modifying_cmd); if (ioq_start != NULL) free(ioq_start); ioq = ioq_start = last_modifying_cmd = 0; adding2q = 0;#endif /* BB_FEATURE_VI_DOT_CMD */ redraw(FALSE); // dont force every col re-draw show_status_line(); //------This is the main Vi cmd handling loop ----------------------- while (editing > 0) {#ifdef BB_FEATURE_VI_CRASHME if (crashme > 0) { if ((end - text) > 1) { crash_dummy(); // generate a random command } else { crashme = 0; dot = string_insert(text, (Byte *) "\n\n##### Ran out of text to work on. #####\n\n"); // insert the string refresh(FALSE); } }#endif /* BB_FEATURE_VI_CRASHME */ last_input_char = c = get_one_char(); // get a cmd from user#ifdef BB_FEATURE_VI_YANKMARK // save a copy of the current line- for the 'U" command if (begin_line(dot) != cur_line) { cur_line = begin_line(dot); text_yank(begin_line(dot), end_line(dot), Ureg); }#endif /* BB_FEATURE_VI_YANKMARK */#ifdef BB_FEATURE_VI_DOT_CMD // These are commands that change text[]. // Remember the input for the "." command if (!adding2q && ioq_start == 0 && strchr((char *) modifying_cmds, c) != NULL) { start_new_cmd_q(c); }#endif /* BB_FEATURE_VI_DOT_CMD */ do_cmd(c); // execute the user command // // poll to see if there is input already waiting. if we are // not able to display output fast enough to keep up, skip // the display update until we catch up with input. if (mysleep(0) == 0) { // no input pending- so update output refresh(FALSE); show_status_line(); }#ifdef BB_FEATURE_VI_CRASHME if (crashme > 0) crash_test(); // test editor variables#endif /* BB_FEATURE_VI_CRASHME */ } //------------------------------------------------------------------- place_cursor(rows, 0, FALSE); // go to bottom of screen clear_to_eol(); // Erase to end of line cookmode();}static Byte readbuffer[BUFSIZ];#ifdef BB_FEATURE_VI_CRASHMEstatic int totalcmds = 0;static int Mp = 85; // Movement command Probabilitystatic int Np = 90; // Non-movement command Probabilitystatic int Dp = 96; // Delete command Probabilitystatic int Ip = 97; // Insert command Probabilitystatic int Yp = 98; // Yank command Probabilitystatic int Pp = 99; // Put command Probabilitystatic int M = 0, N = 0, I = 0, D = 0, Y = 0, P = 0, U = 0;char chars[20] = "\t012345 abcdABCD-=.$";char *words[20] = { "this", "is", "a", "test", "broadcast", "the", "emergency", "of", "system", "quick", "brown", "fox", "jumped", "over", "lazy", "dogs", "back", "January", "Febuary", "March"};char *lines[20] = { "You should have received a copy of the GNU General Public License\n", "char c, cm, *cmd, *cmd1;\n", "generate a command by percentages\n", "Numbers may be typed as a prefix to some commands.\n", "Quit, discarding changes!\n", "Forced write, if permission originally not valid.\n", "In general, any ex or ed command (such as substitute or delete).\n", "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n", "Please get w/ me and I will go over it with you.\n", "The following is a list of scheduled, committed changes.\n", "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n", "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n", "Any question about transactions please contact Sterling Huxley.\n", "I will try to get back to you by Friday, December 31.\n", "This Change will be implemented on Friday.\n", "Let me know if you have problems accessing this;\n", "Sterling Huxley recently added you to the access list.\n", "Would you like to go to lunch?\n", "The last command will be automatically run.\n", "This is too much english for a computer geek.\n",};char *multilines[20] = { "You should have received a copy of the GNU General Public License\n", "char c, cm, *cmd, *cmd1;\n", "generate a command by percentages\n", "Numbers may be typed as a prefix to some commands.\n", "Quit, discarding changes!\n", "Forced write, if permission originally not valid.\n", "In general, any ex or ed command (such as substitute or delete).\n", "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n", "Please get w/ me and I will go over it with you.\n", "The following is a list of scheduled, committed changes.\n", "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n", "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n", "Any question about transactions please contact Sterling Huxley.\n", "I will try to get back to you by Friday, December 31.\n", "This Change will be implemented on Friday.\n", "Let me know if you have problems accessing this;\n", "Sterling Huxley recently added you to the access list.\n", "Would you like to go to lunch?\n", "The last command will be automatically run.\n", "This is too much english for a computer geek.\n",};// create a random command to executestatic void crash_dummy(){ static int sleeptime; // how long to pause between commands char c, cm, *cmd, *cmd1; int i, cnt, thing, rbi, startrbi, percent; // "dot" movement commands cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL"; // is there already a command running? if (strlen((char *) readbuffer) > 0) goto cd1; cd0: startrbi = rbi = 0; sleeptime = 0; // how long to pause between commands memset(readbuffer, '\0', BUFSIZ - 1); // clear the read buffer // generate a command by percentages percent = (int) lrand48() % 100; // get a number from 0-99 if (percent < Mp) { // Movement commands // available commands cmd = cmd1; M++; } else if (percent < Np) { // non-movement commands cmd = "mz<>\'\""; // available commands N++; } else if (percent < Dp) { // Delete commands cmd = "dx"; // available commands D++; } else if (percent < Ip) { // Inset commands cmd = "iIaAsrJ"; // available commands I++; } else if (percent < Yp) { // Yank commands cmd = "yY"; // available commands Y++; } else if (percent < Pp) { // Put commands cmd = "pP"; // available commands P++; } else { // We do not know how to handle this command, try again U++; goto cd0; } // randomly pick one of the available cmds from "cmd[]" i = (int) lrand48() % strlen(cmd); cm = cmd[i]; if (strchr(":\024", cm)) goto cd0; // dont allow colon or ctrl-T commands readbuffer[rbi++] = cm; // put cmd into input buffer // now we have the command- // there are 1, 2, and multi char commands // find out which and generate the rest of command as necessary if (strchr("dmryz<>\'\"", cm)) { // 2-char commands cmd1 = " \n\r0$^-+wWeEbBhjklHL"; if (cm == 'm' || cm == '\'' || cm == '\"') { // pick a reg[] cmd1 = "abcdefghijklmnopqrstuvwxyz"; } thing = (int) lrand48() % strlen(cmd1); // pick a movement command c = cmd1[thing]; readbuffer[rbi++] = c; // add movement to input buffer } if (strchr("iIaAsc", cm)) { // multi-char commands if (cm == 'c') { // change some thing thing = (int) lrand48() % strlen(cmd1); // pick a movement command c = cmd1[thing]; readbuffer[rbi++] = c; // add movement to input buffer } thing = (int) lrand48() % 4; // what thing to insert cnt = (int) lrand48() % 10; // how many to insert for (i = 0; i < cnt; i++) { if (thing == 0) { // insert chars readbuffer[rbi++] = chars[((int) lrand48() % strlen(chars))]; } else if (thing == 1) { // insert words strcat((char *) readbuffer, words[(int) lrand48() % 20]); strcat((char *) readbuffer, " "); sleeptime = 0; // how fast to type } else if (thing == 2) { // insert lines strcat((char *) readbuffer, lines[(int) lrand48() % 20]); sleeptime = 0; // how fast to type } else { // insert multi-lines strcat((char *) readbuffer, multilines[(int) lrand48() % 20]); sleeptime = 0; // how fast to type } } strcat((char *) readbuffer, "\033"); } cd1: totalcmds++; if (sleeptime > 0) (void) mysleep(sleeptime); // sleep 1/100 sec}// test to see if there are any errorsstatic void crash_test(){ static time_t oldtim; time_t tim; char d[2], buf[BUFSIZ], msg[BUFSIZ]; msg[0] = '\0'; if (end < text) { strcat((char *) msg, "end<text "); } if (end > textend) { strcat((char *) msg, "end>textend "); } if (dot < text) { strcat((char *) msg, "dot<text "); } if (dot > end) { strcat((char *) msg, "dot>end "); } if (screenbegin < text) { strcat((char *) msg, "screenbegin<text "); } if (screenbegin > end - 1) { strcat((char *) msg, "screenbegin>end-1 "); } if (strlen(msg) > 0) { alarm(0); sprintf(buf, "\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s", totalcmds, last_input_char, msg, SOs, SOn); write(1, buf, strlen(buf)); while (read(0, d, 1) > 0) { if (d[0] == '\n' || d[0] == '\r') break; } alarm(3); } tim = (time_t) time((time_t *) 0); if (tim >= (oldtim + 3)) { sprintf((char *) status_buffer, "Tot=%d: M=%d N=%d I=%d D=%d Y=%d P=%d U=%d size=%d", totalcmds, M, N, I, D, Y, P, U, end - text + 1); oldtim = tim; } return;}#endif /* BB_FEATURE_VI_CRASHME *///---------------------------------------------------------------------//----- the Ascii Chart -----------------------------------------------//// 00 nul 01 soh 02 stx 03 etx 04 eot 05 enq 06 ack 07 bel// 08 bs 09 ht 0a nl 0b vt 0c np 0d cr 0e so 0f si// 10 dle 11 dc1 12 dc2 13 dc3 14 dc4 15 nak 16 syn 17 etb// 18 can 19 em 1a sub 1b esc 1c fs 1d gs 1e rs 1f us// 20 sp 21 ! 22 " 23 # 24 $ 25 % 26 & 27 '// 28 ( 29 ) 2a * 2b + 2c , 2d - 2e . 2f /// 30 0 31 1 32 2 33 3 34 4 35 5 36 6 37 7// 38 8 39 9 3a : 3b ; 3c < 3d = 3e > 3f ?// 40 @ 41 A 42 B 43 C 44 D 45 E 46 F 47 G// 48 H 49 I 4a J 4b K 4c L 4d M 4e N 4f O// 50 P 51 Q 52 R 53 S 54 T 55 U 56 V 57 W// 58 X 59 Y 5a Z 5b [ 5c \ 5d ] 5e ^ 5f _// 60 ` 61 a 62 b 63 c 64 d 65 e 66 f 67 g// 68 h 69 i 6a j 6b k 6c l 6d m 6e n 6f o// 70 p 71 q 72 r 73 s 74 t 75 u 76 v 77 w// 78 x 79 y 7a z 7b { 7c | 7d } 7e ~ 7f del//---------------------------------------------------------------------//----- Execute a Vi Command -----------------------------------static void do_cmd(Byte c){ Byte c1, *p, *q, *msg, buf[9], *save_dot; int cnt, i, j, dir, yf; c1 = c; // quiet the compiler cnt = yf = dir = 0; // quiet the compiler p = q = save_dot = msg = buf; // quiet the compiler memset(buf, '\0', 9); // clear buf /* if this is a cursor key, skip these checks */ switch (c) { case VI_K_UP: case VI_K_DOWN: case VI_K_LEFT: case VI_K_RIGHT: case VI_K_HOME: case VI_K_END: case VI_K_PAGEUP: case VI_K_PAGEDOWN: goto key_cmd_mode; } if (cmd_mode == 2) { // we are 'R'eplacing the current *dot with new char if (*dot == '\n') { // don't Replace past E-o-l cmd_mode = 1; // convert to insert } else { if (1 <= c && c <= 127) { // only ASCII chars if (c != 27) dot = yank_delete(dot, dot, 0, YANKDEL); // delete char dot = char_insert(dot, c); // insert new char } goto dc1; } } if (cmd_mode == 1) { // hitting "Insert" twice means "R" replace mode if (c == VI_K_INSERT) goto dc5; // insert the char c at "dot" if (1 <= c && c <= 127) { dot = char_insert(dot, c); // only ASCII chars } goto dc1; }key_cmd_mode: switch (c) { //case 0x01: // soh
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -