📄 vi.c
字号:
/* SC A Spreadsheet Calculator * * One line vi emulation * $Revision: 6.8 $ */#include <signal.h>#include <curses.h>#ifdef BSD42#include <strings.h>#else#ifndef SYSIII#include <string.h>#endif#endif#if !defined(strchr) && !defined(UPORT)#define strchr index#endifextern char *strchr();#include <stdio.h>#include <ctype.h>#include "sc.h"#define istext(a) (isalnum(a) || ((a) == '_'))extern int showrange;extern char mode_ind; /* Mode indicator *//* values for mode below */#define INSERT_MODE 0 /* Insert mode */#define EDIT_MODE 1 /* Edit mode */#define REP_MODE 2 /* Replace mode */#define SEARCH_MODE 3 /* Get arguments for '/' command */ static int mode = INSERT_MODE;static char *history[HISTLEN];static int histp = -1;static char *last_search;static char *undo_line;static int undo_lim;static char dotb[100];static int doti = 0;static int do_dot = 0;voidwrite_line(c)int c;{ if (mode == EDIT_MODE) { switch(c) { case (ctl('h')): linelim = back_line(); break; case (ctl('m')): cr_line(); break; case ESC: stop_edit(); break; case '+': for_hist(); break; case '-': back_hist(); break; case '$': last_col(); break; case '.': dotcmd(); break; case '/': search_mode(); break; case '0': col_0(); break; case 'D': u_save(c);del_to_end(); break; case 'I': u_save(c);col_0();insert_mode();break; case 'R': replace_mode(); break; case 'X': u_save(c); back_space(); break; case 'a': u_save(c); append_line(); break; case 'b': linelim = back_word(); break; case 'c': u_save(c); change_cmd(); break; case 'd': u_save(c); delete_cmd(); break; case 'f': linelim = find_char(); break; case 'h': linelim = back_line(); break; case 'i': u_save(c); insert_mode(); break; case 'j': for_hist(); break; case 'k': back_hist(); break; case 'l': linelim = for_line(0); break; case 'n': search_again(); break; case 'q': stop_edit(); break; case 'r': u_save(c); rep_char(); break; case 't': linelim = to_char(); break; case 'u': restore_it(); break; case 'w': linelim = for_word(0); break; case 'x': u_save(c); del_in_line(); break; default: break; } } else if (mode == INSERT_MODE) { savedot(c); switch(c) { case (ctl('h')): back_space(); break; case (ctl('m')): cr_line(); break; case ESC: edit_mode(); break; default: ins_in_line(c); break; } } else if (mode == SEARCH_MODE) { switch(c) { case (ctl('h')): back_space(); break; case (ctl('m')): search_hist(); break; case ESC: edit_mode(); break; default: ins_in_line(c); break; } } else if (mode == REP_MODE) { savedot(c); switch(c) { case (ctl('h')): back_space(); break; case (ctl('m')): cr_line(); break; case ESC: edit_mode(); break; default: replace_in_line(c); break; } }}edit_mode(){ mode = EDIT_MODE; mode_ind = 'e'; histp = -1; if (line[linelim] == '\0') linelim = back_line();}voidinsert_mode(){ mode_ind = 'i'; mode = INSERT_MODE;}search_mode(){ line[0] = '/'; line[1] = 0; linelim = 1; histp = -1; mode_ind = '/'; mode = SEARCH_MODE;}replace_mode(){ mode_ind = 'R'; mode = REP_MODE;}/* dot command functions. Saves info so we can redo on a '.' command */savedot(c)int c;{ if (do_dot) return; dotb[doti++] = c; dotb[doti] = 0;}dotcmd(){ int c; do_dot = 1; doti = 0; while(dotb[doti] != 0) { c = dotb[doti++]; write_line(c); } do_dot = 0; doti = 0;}vigetch(){ int c; if(do_dot) { if (dotb[doti] != 0) { return(dotb[doti++]); } else { do_dot = 0; doti = 0; return(nmgetch()); } } c = nmgetch(); savedot(c); return(c);}/* saves the current line for possible use by an undo cmd */u_save(c)int c;{ if (undo_line) { xfree(undo_line); undo_line = 0; } undo_line = strcpy(xmalloc((unsigned)(strlen(line)+1)), line); undo_lim = linelim; /* reset dot command if not processing it. */ if (!do_dot) { doti = 0; savedot(c); }}/* Restores the current line saved by u_save() */restore_it(){ register char *tempc; register int tempi; if (!undo_line) return; tempc = strcpy(xmalloc((unsigned)(strlen(line)+1)), line); tempi = linelim; strcpy(line, undo_line); linelim = undo_lim; xfree(undo_line); undo_line = tempc; undo_lim = tempi;}/* This command stops the editing process. */stop_edit(){ showrange = 0; linelim = -1; (void) move(1, 0); (void) clrtoeol();}/* * Motion commands. Forward motion commands take an argument * which, when set, cause the forward motion to continue onto * the null at the end of the line instead of stopping at the * the last character of the line. */for_line(stop_null)int stop_null;{ if (linelim >= 0 && line[linelim] != 0 && (line[linelim+1] != 0 || stop_null)) return(linelim+1); else return(linelim);}for_word(stop_null)int stop_null;{ register int c; register int cpos; cpos = linelim; if (line[cpos] == ' ') { while (line[cpos] == ' ') cpos++; if (cpos > 0 && line[cpos] == 0) --cpos; return(cpos); } if (istext(line[cpos])) { while ((c = line[cpos]) && istext(c)) cpos++; } else { while ((c = line[cpos]) && !istext(c) && c != ' ') cpos++; } while (line[cpos] == ' ') cpos++; if (cpos > 0 && line[cpos] == 0 && !stop_null) --cpos; return(cpos);}back_line(){ if (linelim) return(linelim-1); else return(0);}back_word(){ register int c; register int cpos; cpos = linelim; if (line[cpos] == ' ') { /* Skip white space */ while (cpos > 0 && line[cpos] == ' ') --cpos; } else if (cpos > 0 && (line[cpos-1] == ' ' || istext(line[cpos]) && !istext(line[cpos-1]) || !istext(line[cpos]) && istext(line[cpos-1]))) { /* Started on the first char of a word - back up to prev. word */ --cpos; while (cpos > 0 && line[cpos] == ' ') --cpos; } /* Skip across the word - goes 1 too far */ if (istext(line[cpos])) { while (cpos > 0 && (c = line[cpos]) && istext(c)) --cpos; } else { while (cpos > 0 && (c = line[cpos]) && !istext(c) && c != ' ') --cpos; } /* We are done - fix up the one too far */ if (cpos > 0 && line[cpos] && line[cpos+1]) cpos++; return(cpos);}/* Text manipulation commands */del_in_line(){ register int len, i; if (linelim >= 0) { len = strlen(line); if (linelim == len && linelim > 0) linelim--; for (i = linelim; i < len; i++) line[i] = line[i+1]; } if (linelim > 0 && line[linelim] == 0) --linelim;}ins_in_line(c)int c;{ register int i, len; len = strlen(line); for (i = len; i >= linelim; --i) line[i+1] = line[i]; line[linelim++] = c; line[len+1] = 0;}voidins_string(s)char *s;{ while (*s) ins_in_line(*s++);}append_line(){ register int i; i = linelim; if (i >= 0 && line[i]) linelim++; insert_mode();}rep_char(){ int c; c = vigetch(); if (line[linelim] != 0) { line[linelim] = c; } else { line[linelim] = c; line[linelim+1] = 0; }}replace_in_line(c){ register int len; len = strlen(line); line[linelim++] = c; if (linelim > len) line[linelim] = 0;} back_space(){ if (linelim == 0) return; if (line[linelim] == 0) { linelim = back_line(); del_in_line(); linelim = strlen(line); } else { linelim = back_line(); del_in_line(); }}get_motion(){ int c; c = vigetch(); switch (c) { case 'b': return(back_word()); case 'f': return(find_char()+1); case 'h': return(back_line()); case 'l': return(for_line(1)); case 't': return(to_char()+1); case 'w': return(for_word(1)); default: return(linelim); }}delete_cmd(){ int cpos; cpos = get_motion(); del_chars(cpos, linelim);}change_cmd(){ delete_cmd(); insert_mode();}del_chars(first, last)register int first, last;{ int temp; if (first == last) return; if (last < first) { temp = last; last = first; first = temp; } linelim = first; while(first < last) { del_in_line(); --last; }}del_to_end(){ if (linelim < 0) return; line[linelim] = 0; linelim = back_line();}cr_line(){ showrange = 0; insert_mode(); save_hist(); linelim = 0; (void) yyparse (); linelim = -1;}/* History functions */save_hist(){ register int i; /* free the oldest one */ if (history[HISTLEN-1]) { xfree(history[HISTLEN-1]); history[HISTLEN-1] = 0; } /* Move the others back */ for (i = HISTLEN-1; i > 0; --i) history[i] = history[i-1]; history[0] = xmalloc((unsigned) strlen(line)+1); strcpy(history[0], line);}back_hist(){ if (histp == -1 || histp < HISTLEN-1 && history[histp + 1]) histp++; if (history[histp]) { strcpy(line, history[histp]); linelim = 0; } else line[linelim = 0] = 0;}search_hist(){ if (last_search) { xfree(last_search); last_search = 0; } if(linelim < 1) { linelim = 0; edit_mode(); return; } last_search = strcpy(xmalloc((unsigned)(strlen(line+1)+1)), line+1); search_again(); mode = EDIT_MODE;}search_again(){ int found_it; int do_next; int prev_histp; char *look_here; prev_histp = histp; if (!last_search) return; do { back_hist(); if (prev_histp == histp) break; prev_histp = histp; look_here = line; found_it = do_next = 0; while ((look_here = strchr(look_here, last_search[0])) && !found_it && !do_next) { if (strncmp(look_here, last_search, strlen(last_search)) == 0) found_it++; else if (look_here < line + strlen(line) - 1) look_here++; else do_next++; } } while (!found_it);}for_hist(){ if (histp > 0) histp--; if (histp >= 0 && history[histp]) { strcpy(line, history[histp]); linelim = 0; } else line[linelim = 0] = 0;}col_0(){ linelim = 0;}last_col(){ linelim = strlen(line); if (linelim > 0) --linelim;}find_char(){ register int c; register int i; c = vigetch(); i = linelim; while(line[i] && line[i] != c) i++; if (!line[i]) i = linelim; return(i);}to_char(){ register int i; i = find_char(); if (i > 0 && i != linelim) --i; return(i);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -