网友给的一个vi代码

/*
 ============================================================================
 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 <[email protected]>
 *
 *  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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值