C语言400行实现文本编辑器

C语言400行实现文本编辑器_第1张图片

 

学校的数据结构布置的作业。处理核心采用了双链表的结构。

typedef struct Line{
    char text[1024];
    struct Line* prev;
    struct Line* next;
}line;

采用命令行操作,可完成行为单位的插入、删除、复制剪切粘贴等任务。为表对前辈的敬意,名为vimisa。读取命令的枢纽函数console()如下:

line* console(line* h){
    char str[1024],*pc;
    memset(str,0,1024);
    line* l = h,temp,clipboard;
    memset(clipboard.text,0,1024);
    int a,b; 
    COORD pos = {23,0};
    
    
    system("cls");
	printS(l);
	printf(">>>");
	gets(str);
    while(strcmp(str,"\\exit")!=0){
    	
    	if(strncasecmp(str,"\\i ",3)==0){
    		l = r_i(l,str+3);
		}
    	else if(strncasecmp(str,"\\d ",3)==0){
			a = 1;
			b = sscanf(str+2,"%d",&a);
    		if(b) l = r_d(l,a);
    		else printf("INPROPER FORMAT\n");
		}
    	else if(strncasecmp(str,"\\e ",3)==0){
    		l = r_e(l,str+3);
		}
		else if(strncasecmp(str,"\\m ",3)==0){
			a = 1;
			b = sscanf(str+2,"%d",&a);
    		if(b) l = r_m(l,a);
    		else printf("INPROPER FORMAT\n");
		}
		else if(strncasecmp(str,"\\c ",3)==0){
			l = copy(l,&clipboard);
		}
		else if(strncasecmp(str,"\\x ",3)==0){
			l = cut(l,&clipboard);
		}
		else if(strncasecmp(str,"\\v ",3)==0){
			l = paste(l,&clipboard);
		}
		else if(strncasecmp(str,"\\in ",4)==0){
			l = i_e(l);
		}
		else if(strncasecmp(str,"\\b ",3)==0){
			l->prev->text[strlen(l->prev->text)-1] = ' ';
			strcat(str,"\n");
			strcat(l->prev->text,str+3);
		}
		else if(strncasecmp(str,"\\h ",3)==0){
			system("cls");
    		printP(readF("help.txt"),999);
    		system("pause");
		}
		else{
			l = r_e(l,str);
		}
		
		
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
		memset(str,0,1024);
		system("cls");
    	printS(l);
    	printf("\n>>>");
    	gets(str);
    	
	}
    return h;
}

在程序内,也可以键入"\h "来 查看帮助文档。支持的命令入下图所示。

C语言400行实现文本编辑器_第2张图片

 

使用"\in "进入,本编辑器支持行内细节编辑,但目前对汉字仍会有bug。汉字只能稳定地支持整行操作。行内编辑界面仍然采用命令操作。

C语言400行实现文本编辑器_第3张图片

 C语言400行实现文本编辑器_第4张图片

 

 可以视作一个缺陷,本编辑器的光标移动只能采用命令而不支持方向键。用"\m 5","\m -5","\r 5","\l 3"等命令实现。

Vimisa支持终端调用,在将vimisa.exe和help.txt放入用户文件夹或配置环境变量后可以采用"vimisa [filename]" 的方式打开文本文件。

C语言400行实现文本编辑器_第5张图片

 代码全文如下。

//
// Created by Misappon on 2022/10/22.
//
#include 
#include 
#include 
#include "stdlib.h"
#include "conio.h"
#include 
#include 
#define RSHOWLINES 10


typedef struct Line{
    char text[1024];
    struct Line* prev;
    struct Line* next;
}line;
void gotoxy(short x, short y) {
    COORD coord = {x, y}; 
    //COORD是Windows API中定义的一种结构体类型,表示控制台屏幕上的坐标。
    //上面语句是定义了COORD类型的变量coord,并以形参x和y进行初始化。
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
    //GetStdHandle(STD_OUTPUT_HANDLE); 获取控制台输出句柄
    //然后用SetConsoleCursorPosition设置控制台(cmd)光标位置
}

line* i_e(line* l);
line* cnclEntr(line* l,char str[1024], char* pc);

line* initLine(){
    line* l = malloc(sizeof (line));
    l->prev = NULL;
    l->next = NULL;
    memset(l->text,0,1024);

    return l;
}

line* readF(const char path[1024]){
    FILE* fp = fopen(path,"r");
    line *l,*h;
    l = malloc(sizeof (line));
    l->prev = NULL;
    l->next = NULL;
    memset(l->text,0,1024);
    h = l;
//    char* str = malloc(1024*sizeof (char));
    while (feof(fp) == 0){
        fgets(l->text,1024,fp);
        l->next = malloc(sizeof (line));
//        printf("%s",l->text);
        memset(l->next->text,0,1024);
        l->next->prev = l;
        l->next->next = NULL;
        l = l->next;
    }
    l->prev->next=NULL;
    free(l);
    
    fclose(fp);
    return h;
}

void printP(line* h,int n_hl){
	line* l = h;
    for(int i=0;l;i++){
    	if(i==n_hl){
    		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x70);
		}
		else{
    		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
		}
        printf("%s",l->text); // 红色字体,绿色背景
        l = l->next;
    }
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
}
void printS(line* focus){//s for section
	line* l = focus;
	int j,swi=0;
	for(j=0;jprev;j++){
		l = l->prev;
	} 
    for(int i=0;l&&i<1+j+RSHOWLINES;i++){
    	if(i==j||(swi==0&&l->next==NULL)){
    		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x70);
    		swi=1;
		}
		else{
    		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
		}
        printf("%s",l->text); 
        l = l->next;
    }
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
}

line* r_m(line* focus,int n){
	int s = abs(n)/n;
	for(int i=0;i!=n;i+=s) {
		if(n<0) {
			if(focus->prev==NULL) break;
			focus = focus->prev;
		}
		else{
			if(focus->next==NULL) break;
			focus = focus->next;
		}
	}
	
	return focus;
}

line* r_d(line* focus,int n){
	line* med,*fo=focus;
	for(int i;iprev==NULL){
			med = fo->next;
		}
		else if(focus->next==NULL){
			med = fo->prev;
		} 
		else {
			med = fo->prev;
		}
		if(fo->prev) fo->prev->next = fo->next;
		if(fo->next) fo->next->prev = fo->prev;
		free(fo);
		
		fo = fo->next;
	}
	return med;
}

line* r_e(line* focus,char text[1024]){//e for edit
	strcat(text,"\n");
	strcpy(focus->text,text);
	
	if(focus->next) focus = focus->next;
	else{
		focus->next = (line*)malloc(sizeof(line));
		focus->next->prev = focus;
		focus->next->next = NULL;
		memset(focus->next->text,0,1024); 
		focus = focus->next;
	}
	return focus;
}

line* r_i(line* focus,char text[1024]){
	line* med = malloc(sizeof(line));
	if(focus->next){
		focus->next->prev = med;
		med->next = focus->next;
	}
	else{
		focus->next = med;
		med->next = NULL;
	}
	med->prev = focus;
	focus->next = med;
	r_e(med,text);
	
	return med;
}

line* cut(line* l,line* clipboard){
	clipboard->prev = NULL;
	clipboard->next = NULL;
	strcpy(clipboard->text,l->text);
	l = r_d(l,1);
	
	return l;
}

line* copy(line* l,line* clipboard){
	clipboard->prev = NULL;
	clipboard->next = NULL;
	strcpy(clipboard->text,l->text);
	
	return l;
}

line* paste(line* desti, line* clipboard){
	strcpy(desti->text,clipboard->text);
	
	return desti;
}

line* console(line* h){
    char str[1024],*pc;
    memset(str,0,1024);
    line* l = h,temp,clipboard;
    memset(clipboard.text,0,1024);
    int a,b; 
    COORD pos = {23,0};
    
    
    system("cls");
	printS(l);
	printf(">>>");
	gets(str);
    while(strcmp(str,"\\exit")!=0){
    	
    	if(strncasecmp(str,"\\i ",3)==0){
    		l = r_i(l,str+3);
		}
    	else if(strncasecmp(str,"\\d ",3)==0){
			a = 1;
			b = sscanf(str+2,"%d",&a);
    		if(b) l = r_d(l,a);
    		else printf("INPROPER FORMAT\n");
		}
    	else if(strncasecmp(str,"\\e ",3)==0){
    		l = r_e(l,str+3);
		}
		else if(strncasecmp(str,"\\m ",3)==0){
			a = 1;
			b = sscanf(str+2,"%d",&a);
    		if(b) l = r_m(l,a);
    		else printf("INPROPER FORMAT\n");
		}
		else if(strncasecmp(str,"\\c ",3)==0){
			l = copy(l,&clipboard);
		}
		else if(strncasecmp(str,"\\x ",3)==0){
			l = cut(l,&clipboard);
		}
		else if(strncasecmp(str,"\\v ",3)==0){
			l = paste(l,&clipboard);
		}
		else if(strncasecmp(str,"\\in ",4)==0){
			l = i_e(l);
		}
		else if(strncasecmp(str,"\\b ",3)==0){
			l->prev->text[strlen(l->prev->text)-1] = ' ';
			strcat(str,"\n");
			strcat(l->prev->text,str+3);
		}
		else if(strncasecmp(str,"\\h ",3)==0){
			system("cls");
    		printP(readF("help.txt"),999);
    		system("pause");
		}
		else{
			l = r_e(l,str);
		}
		
		
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
		memset(str,0,1024);
		system("cls");
    	printS(l);
    	printf("\n>>>");
    	gets(str);
    	
	}
    return h;
}

void saveF(char path[1024],line* head){
	FILE* fp = fopen(path,"w");
	line* l = head;
	while(l){
		fprintf(fp,"%s",l->text);
		l = l->next;
	}
}

line* cnclEntr(line* l,char str[1024], char* pc){
	l = r_e(l,str);
	return l; 
}

line* i_e(line* l){//Line Internal Edit
	int a=1,b,n=0,i,m=strlen(l->text),swi=1;
	char str[1024],str1[1024],c;
	line* temp;
	memset(str,0,1024);
	while(1){
		system("cls");
		for(i=0;l->text[i];i++){
			if(i == n) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x70);
			else SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
			putchar(l->text[i]);
		}
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
		printf("\n                                          \r>>>");
		memset(str,0,1024);
		c = getche();
		if(c == '\\'){
			gets(str);
			if(strncasecmp(str,"r ",2)==0){
				b = sscanf(str+2,"%d",&a);
				for(int i=0;l->text[n+1]&&i=0?n-a:0;
			}
			else if(strncasecmp(str,"d ",2)==0){
				sscanf(str+2,"%d",&a); 
				strncpy(l->text+n,l->text+n+a,strlen(l->text));
			}
			else if(strncasecmp(str,"i ",2)==0){
				swi = 0;
				memset(str1,0,1024);
				strcpy(str1,l->text+n);
				strcpy(l->text+n,str+2);
				strcat(l->text,str1);
			}
			else if(strncasecmp(str,"h ",2)==0){
				temp = readF("help.txt");
				printP(temp,0);
				system("pause");
			}
			else if(strncasecmp(str," ",1)==0){//q for quit
				break;
			}
			else{
	//			strcpy(l->text+n,str);
				b = strlen(str);
				for(i=n;itext[i] = str[i-n];
				n += b;
			}
		}
		else{
			l->text[n++] = c;
		}
	}
	if(strlen(l->text)>m && swi) strcat(l->text,"\n");
	return l;
}

int main(int argc,char *argv[]){
	FILE* fp;
	char str[1024] = {0},str1[1024] = {0};
	
	if(argc<2){
		printf("FILE NAME\n>>>");
		gets(str);
		fp = fopen(str,"r");
		if(!fp) fopen(str,"w");
		fclose(fp);
		line *h = readF(str);
		h = console(h);
		printf("SAVE AS\n>>>");
		memset(str1,0,1024);
		gets(str1);
		if(strcmp(str1,"")==0);
		else if(strcmp(str1,"-")==0) saveF(str,h);
		else saveF(str1,h);
	}
	else{
		fp = fopen(argv[1],"r");
		if(!fp) fopen(argv[1],"w");
		fclose(fp);
	    line *h = readF(argv[1]);
		h = console(h);
		printf("SAVE AS\n>>>");
		memset(str,0,1024);
		gets(str1);
		if(strcmp(str1,"")==0);
		else if(strcmp(str1,"-")==0) saveF(argv[1],h);
		else saveF(str1,h);
	}
	
    return 0;
}

你可能感兴趣的:(1024程序员节)