/*
============================================================================
Name : myvi.c
Author :
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
/* vi: set sw=8 ts=8: */
/*
* tiny vi.c: A small 'vi' clone
* Copyright (C) 2000, 2001 Sterling Huxley <sterling@europa.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
static const char vi_Version[] =
"$Id: vi.c,v 1.18 2002/04/26 08:06:31 andersen Exp $";
/*
* To compile for standalone use:
* gcc -Wall -Os -s -DSTANDALONE -o vi vi.c
* or
* gcc -Wall -Os -s -DSTANDALONE -DBB_FEATURE_VI_CRASHME -o vi vi.c # include testing features
* strip vi
*/
/*
* Things To Do:
* EXINIT
* $HOME/.exrc and ./.exrc
* add magic to search /foo.*bar
* add :help command
* :map macros
* how about mode lines: vi: set sw=8 ts=8:
* if mark[] values were line numbers rather than pointers
* it would be easier to change the mark when add/delete lines
* More intelligence in refresh()
* ":r !cmd" and "!cmd" to filter text through an external command
* A true "undo" facility
* An "ex" line oriented mode- maybe using "cmdedit"
*/
#define STANDALONE
//---- Feature -------------- Bytes to immplement
#ifdef STANDALONE
#define vi_main main
// To test editor using CRASHME:
// vi -C filename
// To stop testing, wait until all to text[] is deleted, or
// Ctrl-Z and kill -9 %1
// while in the editor Ctrl-T will toggle the crashme function on and off.
#endif /* STANDALONE */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <regex.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/select.h>
#include <sys/time.h>
#ifndef TRUE
#define TRUE ((int)1)
#define FALSE ((int)0)
#endif /* TRUE */
#define MAX_SCR_COLS BUFSIZ
// Misc. non-Ascii keys that report an escape sequence
#define VI_K_UP 128 // cursor key Up
#define VI_K_DOWN 129 // cursor key Down
#define VI_K_RIGHT 130 // Cursor Key Right
#define VI_K_LEFT 131 // cursor key Left
#define VI_K_HOME 132 // Cursor Key Home
#define VI_K_END 133 // Cursor Key End
#define VI_K_INSERT 134 // Cursor Key Insert
#define VI_K_PAGEUP 135 // Cursor Key Page Up
#define VI_K_PAGEDOWN 136 // Cursor Key Page Down
#define VI_K_FUN1 137 // Function Key F1
#define VI_K_FUN2 138 // Function Key F2
#define VI_K_FUN3 139 // Function Key F3
#define VI_K_FUN4 140 // Function Key F4
#define VI_K_FUN5 141 // Function Key F5
#define VI_K_FUN6 142 // Function Key F6
#define VI_K_FUN7 143 // Function Key F7
#define VI_K_FUN8 144 // Function Key F8
#define VI_K_FUN9 145 // Function Key F9
#define VI_K_FUN10 146 // Function Key F10
#define VI_K_FUN11 147 // Function Key F11
#define VI_K_FUN12 148 // Function Key F12
static const int YANKONLY = FALSE;
static const int YANKDEL = TRUE;
static const int FORWARD = 1; // code depends on "1" for array index
static const int BACK = -1; // code depends on "-1" for array index
static const int LIMITED = 0; // how much of text[] in char_search
static const int FULL = 1; // how much of text[] in char_search
static const int S_BEFORE_WS = 1; // used in skip_thing() for moving "dot"
static const int S_TO_WS = 2; // used in skip_thing() for moving "dot"
static const int S_OVER_WS = 3; // used in skip_thing() for moving "dot"
static const int S_END_PUNCT = 4; // used in skip_thing() for moving "dot"
static const int S_END_ALNUM = 5; // used in skip_thing() for moving "dot"
typedef unsigned char Byte;
static int editing; // >0 while we are editing a file
static int cmd_mode; // 0=command 1=insert
static int file_modified; // buffer contents changed
static int err_method; // indicate error with beep or flash
static int fn_start; // index of first cmd line file name
static int save_argc; // how many file names on cmd line
static int cmdcnt; // repetition count
static fd_set rfds; // use select() for small sleeps
static struct timeval tv; // use select() for small sleeps
static char erase_char; // the users erase character
static int rows, columns; // the terminal screen is this size
static int crow, ccol, offset; // cursor is on Crow x Ccol with Horz Ofset
static char *SOs, *SOn; // terminal standout start/normal ESC sequence
static char *bell; // terminal bell sequence
static char *Ceol, *Ceos; // Clear-end-of-line and Clear-end-of-screen ESC sequence
static char *CMrc; // Cursor motion arbitrary destination ESC sequence
static char *CMup, *CMdown; // Cursor motion up and down ESC sequence
static Byte *status_buffer; // mesages to the user
static Byte last_input_char; // last char read from user
static Byte last_forward_char; // last char searched for with 'f'
static Byte *cfn; // previous, current, and next file name
static Byte *text, *end, *textend; // pointers to the user data in memory
static Byte *screen; // pointer to the virtual screen buffer
static int screensize; // and its size
static Byte *screenbegin; // index into text[], of top line on the screen
static Byte *dot; // where all the action takes place
static int tabstop;
static struct termios term_orig, term_vi; // remember what the cooked mode was
static void edit_file(Byte *); // edit one file
static void do_cmd(Byte); // execute a command
static void sync_cursor(Byte *, int *, int *); // synchronize the screen cursor to dot
static Byte *begin_line(Byte *); // return pointer to cur line B-o-l
static Byte *end_line(Byte *); // return pointer to cur line E-o-l
static Byte *dollar_line(Byte *); // return pointer to just before NL
static Byte *prev_line(Byte *); // return pointer to prev line B-o-l
static Byte *next_line(Byte *); // return pointer to next line B-o-l
static Byte *end_screen(void); // get pointer to last char on screen
static int count_lines(Byte *, Byte *); // count line from start to stop
static Byte *find_line(int); // find begining of line #li
static Byte *move_to_col(Byte *, int); // move "p" to column l
static int isblnk(Byte); // is the char a blank or tab
static void dot_left(void); // move dot left- dont leave line
static void dot_right(void); // move dot right- dont leave line
static void dot_begin(void); // move dot to B-o-l
static void dot_end(void); // move dot to E-o-l
static void dot_next(void); // move dot to next line B-o-l
static void dot_prev(void); // move dot to prev line B-o-l
static void dot_scroll(int, int); // move the screen up or down
static void dot_skip_over_ws(void); // move dot pat WS
static void dot_delete(void); // delete the char at 'dot'
static Byte *bound_dot(Byte *); // make sure text[0] <= P < "end"
static Byte *new_screen(int, int); // malloc virtual screen memory
static Byte *new_text(int); // malloc memory for text[] buffer
static Byte *char_insert(Byte *, Byte); // insert the char c at 'p'
static Byte *stupid_insert(Byte *, Byte); // stupidly insert the char c at 'p'
static Byte find_range(Byte **, Byte **, Byte); // return pointers for an object
static int st_test(Byte *, int, int, Byte *); // helper for skip_thing()
static Byte *skip_thing(Byte *, int, int, int); // skip some object
static Byte *find_pair(Byte *, Byte); // find matching pair () [] {}
static Byte *text_hole_delete(Byte *, Byte *); // at "p", delete a 'size' byte hole
static Byte *text_hole_make(Byte *, int); // at "p", make a 'size' byte hole
static Byte *yank_delete(Byte *, Byte *, int, int); // yank text[] into register then delete
static void show_help(void); // display some help info
static void print_literal(Byte *, Byte *); // copy s to buf, convert unprintable
static void rawmode(void); // set "raw" mode on tty
static void cookmode(void); // return to "cooked" mode on tty
static int mysleep(int); // sleep for 'h' 1/100 seconds
static Byte readit(void); // read (maybe cursor) key from stdin
static Byte get_one_char(void); // read 1 char from stdin
static int file_size(Byte *); // what is the byte size of "fn"
static int file_insert(Byte *, Byte *, int);
static int file_write(Byte *, Byte *, Byte *);
static void place_cursor(int, int, int);
static void screen_erase();
static void clear_to_eol(void);
static void clear_to_eos(void);
static void standout_start(void); // send "start reverse video" sequence
static void standout_end(void); // send "end reverse video" sequence
static void flash(int); // flash the terminal screen
static void beep(void); // beep the terminal
static void indicate_error(char); // use flash or beep to indicate error
static void show_status_line(void); // put a message on the bottom line
static void psb(char *, ...); // Print Status Buf
static void psbs(char *, ...); // Print Status Buf in standout mode
static void ni(Byte *); // display messages
static void edit_status(void); // show file status on status line
static void redraw(int); // force a full screen refresh
static void format_line(Byte*, Byte*, int);
static void refresh(int); // update the terminal from screen[]
/* BB_FEATURE_VI_COLON */
static Byte *get_input_line(Byte *); // get input line- use "status line" /* BB_FEATURE_VI_DOT_CMD */
#define end_cmd_q() /* BB_FEATURE_VI_CRASHME */
/* Find out if the last character of a string matches the one given Don't
* underrun the buffer if the string length is 0. Also avoids a possible
* space-hogging inline of strlen() per usage.
*/
char * last_char_is(const char *s, int c)
{
char *sret;
if (!s)
return NULL;
sret = (char *)s+strlen(s)-1;
if (sret>=s && *sret == c) {
return sret;
} else {
return NULL;
}
}
extern int vi_main(int argc, char **argv)
{
int c;
//这些都该是常量吧
CMrc= "\033[%d;%dH"; // Terminal Crusor motion ESC sequence
CMup= "\033[A"; // move cursor up one line, same col
CMdown="\n"; // move cursor down one line, same col
Ceol= "\033[0K"; // Clear from cursor to end of line
Ceos= "\033[0J"; // Clear from cursor to end of screen
SOs = "\033[7m"; // Terminal standout mode on
SOn = "\033[0m"; // Terminal standout mode off
bell= "\007"; // Terminal bell sequence
status_buffer = (Byte *) malloc(200); // hold messages to user
// 1- process $HOME/.exrc file
// 2- process EXINIT variable from environment
// 3- process command line args
while ((c = getopt(argc, argv, "hCR")) != -1) {
switch (c) {
//case 'r': // recover flag- ignore- we don't use tmp file
//case 'x': // encryption flag- ignore
//case 'c': // execute command first
//case 'h': // help -- just use default
default:
show_help();
return 1;
}
}
// The argv array can be used by the ":next" and ":rewind" commands
// save optind.
fn_start = optind; // remember first file name for :next and :rew
save_argc = argc;
//----- This is the main file handling loop --------------
if (optind >= argc) { //如果没有参数,则编辑个新文件
editing = 1; // 0= exit, 1= one file, 2= multiple files
edit_file(NULL);
} else {
//cnf=当前文件名称
for (; optind < argc; optind++) {
editing = 1; // 0=exit, 1=one file, 2+ =many files
if (cfn != 0)
free(cfn);
cfn = (Byte *) strdup(argv[optind]);
edit_file(cfn);
}
}
//-----------------------------------------------------------
return (0);
}
static void edit_file(Byte * fn)
{
char c;
int cnt, size, ch;
rawmode();
rows = 24;
columns = 80;
ch= -1;
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;
err_method = 1; // flash
last_forward_char = last_input_char = '\0';
crow = 0;
ccol = 0;
edit_status();
editing = 1;
cmd_mode = 0; // 0=command 1=insert 2='R'eplace
cmdcnt = 0;
tabstop = 8;
offset = 0; // no hor
网友给的一个vi代码
最新推荐文章于 2024-06-14 09:31:30 发布
这是一个小型的C语言实现的vi编辑器源代码,包含了基本的编辑、搜索、撤销等功能。代码中定义了各种键盘快捷键和操作命令,如上下左右移动光标、插入删除文本等。此外,还提供了错误处理和屏幕刷新机制。
摘要由CSDN通过智能技术生成