?? editor.c
字號:
/*文本編輯器editor源代碼*/
#include <stdio.h>
#include <conio.h>
#include <bios.h>
#include <math.h>
#define LEFT 0x4b00 /*←:光標左移*/
#define RIGHT 0x4d00 /*→:光標右移*/
#define DOWN 0x5000 /*↓鍵:光標下移*/
#define UP 0x4800 /*↑鍵:光標上移*/
#define ESC 0x011b /*ESC鍵:取消菜單打開操作*/
#define ENTER 0x1c0d /*回車鍵:換行*/
#define DEL 21248 /*DEL鍵:刪除當前字符*/
#define BACK 3592 /*BackSpace鍵:刪除當前光標位置前一個字符*/
#define CL 29440 /*ctrl+←鍵:從右至左,選定文本*/
#define CR 29696 /*ctrl+→鍵:從左到右,選定文本*/
#define Cc 11779 /*ctrl+c鍵:將選定文本,復制一份到剪貼板中*/
#define Cv 12054 /*ctrl+v鍵:將剪貼板中的內容復制到當前位置*/
#define Cx 11544 /*ctrl+x鍵:對選定文本,執行剪切操作*/
#define F1 15104 /*F1鍵:打開文件菜單*/
#define F2 15360 /*F2鍵:打開編輯菜單*/
#define F3 15616 /*F3鍵:打開幫助菜單*/
#define F10 17408 /*F10鍵:進入文本快速預覽模式*/
int value,backup,NUM;
/*value保存有值數組元素的最大下標值,backup保存value的副本,NUM保存當前行中的用戶輸入的字符個數*/
typedef struct record
{
char ch; /*保存一字符*/
int col, line; /*x軸和y軸坐標*/
}record;
record r[500]; /*定義一個有500個元素的結構體數組,保存選定的文本字符的屬性*/
typedef struct node /*定義保存行中的單個字符的結構*/
{
char ch; /*數據域:保存一字符*/
struct node *next; /*指針域:指向下一個結點的指針*/
}node;/*由此類型節點構成的單鏈表,命名為:列單鏈表*/
typedef struct Hnode /*定義保存所有列單鏈表首節點的指針的結構*/
{
node *next; /*指向列單鏈表的首節點的地址*/
struct Hnode *nextl; /*指向下一個節點的指針*/
}Hnode;/*由此類型節點構成的單鏈表,命名為:行單鏈表*/
void drawmain() /*畫主窗口函數*/
{
int i,j;
gotoxy(1,1); /*在文本窗口中設置光標至(1,1)處*/
textbackground(7); /*選擇新的文本背景顏色,7為LIGHTGRAY淡灰色*/
textcolor(0); /*在文本模式中選擇新的字符顏色0為BLACK黑*/
insline(); /*在文本窗口的(1,1)位置處中插入一個空行*/
for(i=1;i<=24;i++)
{
gotoxy(1,1+i); /*(x,y)中x不變,y++*/
cprintf("%c",196); /*在窗口左邊輸出-,即畫出主窗口的左邊界 */
gotoxy(80,1+i);
cprintf("%c",196); /*在窗口右邊,輸出-,即畫出主窗口的右邊界*/
}
for(i=1;i<=79;i++)
{
gotoxy(1+i,2); /*在第2行,第2列開始*/
cprintf("%c",196); /*在窗口頂端,輸出-*/
gotoxy(1+i,25); /*在第25行,第2列開始*/
cprintf("%c",196); /*在窗口底端,輸出-*/
}
gotoxy(1,1); cprintf("%c",196); /*在窗口左上角,輸出-*/
gotoxy(1,24); cprintf("%c",196); /*在窗口左下角,輸出-*/
gotoxy(80,1); cprintf("%c",196); /*在窗口右上角,輸出-*/
gotoxy(80,24); cprintf("%c",196); /*在窗口右下角,輸出-*/
gotoxy(7,1); cprintf("%c %c File %c %c",179,17,16,179); /* | < > |*/
gotoxy(27,1); cprintf("%c %c Edit %c %c",179,17,16,179); /* | < > |*/
gotoxy(47,1); cprintf("%c %c Help %c %c",179,17,16,179); /* | < > |*/
gotoxy(5,25); /*跳至窗口底端*/
textcolor(1);
cprintf(" Row:1 Col:1");
gotoxy(68,25);
cprintf("Version 2.0");
}
void qview(Hnode *q) /*快速預覽文本:開頭:#,回車:* */
{
void view(Hnode *q); /*view()函數聲明*/
node *p;
int i;
window(1,1,80,25); /*定義文本窗口大小*/
clrscr(); /*清屏*/
/*循環讀取兩個單鏈表中的值:q是一個指向行單鏈表首節點的指針,
此單鏈表數據域的值為實際保存各行字符的列單鏈表p中的首節點地址*/
do{
p=q->next; /*p指向保存行數據的列單鏈表的首節點的地址*/
cprintf("#"); /*每行開頭,打印此字符,不管前面是否有回車符*/
while(p!=NULL) /*循環讀取單鏈表p中的值*/
{
if(p->ch==13) putch('*'); /*若為回車鍵,打印出*號*/
else
putch(p->ch); /*輸出各行中的字符到預覽窗口*/
p=p->next; /*指向下一個節點*/
}
q=q->nextl; /*指向下一個節點*/
printf("\n");/*輸出一個回車*/
}while(q!=NULL);
getch();
clrscr();
drawmain();/*按任意鍵后,回到主窗口界面*/
window(2,2,79,23);
textbackground(9);
for(i=0;i<24;i++)
insline(); /*插入24個空行*/
window(3,3,78,23);
textcolor(10);
}
void view(Hnode *q) /*按行顯示保存在單鏈表中的文本字符,q為指向行單鏈表中第一個節點的指針*/
{
node *p; /*p為保存列單鏈表節點元素地址的指針*/
clrscr(); /*清屏*/
/*雙重循環,讀取并顯示保存在單鏈表中字符*/
do{
p=q->next;
while(p!=NULL&&p->ch>=32&&p->ch<127&&p->ch!=13&&p->ch!=-1) /*指針p不能為空,且數據域必須為常規字符*/
{
putch(p->ch);/*在文本窗口中輸出該字符*/
p=p->next; /*指向下一個節點*/
}
q=q->nextl; /*指向下一個節點*/
if((p->ch==13||p->ch==-1)&&q!=NULL) gotoxy(1,wherey()+1); /*若ch為回車或EOF標記,光標跳至下行的開始處*/
}while(q!=NULL); /*逐行逐列顯示文本字符*/
}
int check(Hnode *Hhead,int m,int n) /*check():在單鏈表中檢查第m行第n列位置的字符,若為常規字符,則返回該字符*/
{
int i;
Hnode *q;
node *p;
q=Hhead;
for(i=1;i<m;i++) /*定位至行單鏈表中的第m個元素*/
q=q->nextl;
p=q->next;/*獲取第m個節點的數據域*/
for(i=1;i<n;i++) /*定位至列單鏈表中的第n個元素*/
p=p->next;
if(p->ch==13) return -1; /*若第m行,第n列的字符為回車鍵,則返回-1*/
if(p->ch>=32&&p->ch<127) return p->ch; /*若第m行,第n列的字符為常規字符,則返回該字符*/
else return 0; /*若第m行,第n列的字符既非回車符又非常規字符,則返回0*/
}
int judge(Hnode *Hhead,int m) /*judge():返回第m行中的常規字符總的個數,不包括回車符*/
{
Hnode *q;
node *p;
int i,num=0;
q=Hhead;
for(i=1;i<m;i++) /*定位至行單鏈表中的第m個元素*/
q=q->nextl;
if(q==NULL) return -1; /*返回-1,表示第m行不存在*/
p=q->next;
while(p->next!=NULL)
{
p=p->next;
num++; /*統計第m行的字符個數*/
}
/*行尾字符還沒有判斷,接下來判斷行尾字符*/
if(p->ch==13&&num==0) return 0; /*返回0,表示當前行只有一個回車字符*/
if(p->ch>=32&&p->ch<127) return num+1; /*返回num+1,表示當前行的最后一個字符為常規字符*/
if(p->ch==13&&num!=0) return num; /*返回num,表示當前行的最后一個字符為回車符,不計算在內*/
else return 1;/*返回num,表示當前行中只有一個字符,且沒有回車符*/
}
int del(Hnode *Hhead,int m,int n) /*del():刪除第m行,第n列位置的字符*/
{
Hnode *q,*q1;
node *p1,*p2,*tail;
int i,num=0,j,flag=0;
q=Hhead;
if(n==0&&m==1) return; /*第1行,第0列不存在*/
if(n==0&&m>1) /*若為第0列字符,但行必須大于1,執行向上行移處理*/
{
n=76;
m=m-1;
gotoxy(n,m);/*移至第m-1行,第76列*/
flag=1; /*移位的標志置1*/
}
for(i=1;i<m;i++) /*定位至行單鏈表中的第m個元素*/
q=q->nextl;
p1=q->next;
for(i=1;i<n-1;i++) /*定位至列單鏈表中的第n-1個元素*/
p1=p1->next;
p2=p1->next; /*p2指向列單鏈表中的第n個元素*/
if(n==1) /*若是刪除第m行第1列的字符*/
{
q->next=p1->next;
free(p1);
}
else
{
p1->next=p2->next; /*在單鏈表中刪除第m行第n列的元素*/
free(p2);
}
/*刪除掉第m行第n列的元素后,處理行單鏈表中第m個節點后的數據向前移的任務*/
while((num=judge(Hhead,m++))>0) /*執行一次judge(Head,m)后,m才加1.這里必須滿足行常規字符數不為0的條件*/
{
p1=q->next; q1=q;
if(p1!=NULL) /*若當前行非空*/
{
while(p1->next!=NULL)
p1=p1->next;
tail=p1;/*tail保存列單鏈表最后一個元素的地址*/
q=q->nextl; /*指向下一行的元素的地址*/
p1=p2=q->next;
tail->next=p1; /*tail的指針域指向下一行的第一個元素的地址*/
}
else /*若當前行的字符個數為0,即刪除該字符后,只剩下回車符,則將下一個行單鏈表中節點的數據域移至前一下節點的數據域*/
{
q=q->nextl; p1=p2=q->next;
q1->next=p1;/*q1->next指向下一行的第一個元素的地址*/
}
for(i=0;i<76-num;i++)
/*當前行還有76-num個空位沒有字符,在下一行的單鏈表中讀取字符,直至遇到回車符為止*/
{
p1=p2; /*p1指向p2的前一個節點,p2指向行單鏈表中下一個節點*/
p2=p2->next;
if(p2->ch==13) break; /*若為回車,跳出循環*/
}
q->next=p2; /*在列單鏈表中去掉移至上行的元素*/
p1->next=NULL;/*下行移至上行的最后一個元素,指針置空*/
}
return flag; /*返回0:表示沒有換位,返回1:表示有換位*/
}
/*執行insert()后,檢驗第n行及后面的數據,使其滿足規則*/
int test(Hnode *Hhead,int n)
{
int i=0,num1=1;
node *p1,*p2,*tail,*temp1,*temp2;
Hnode *q;
q=Hhead;
for(i=1;i<n;i++) /*定位至行單鏈表中的第n個元素*/
q=q->nextl;
tail=p1=q->next;
if(p1==NULL) return; /*若此行沒有任何字符,則返回*/
while(tail->next!=NULL) /*定位至列單鏈表中的最后一個元素*/
tail=tail->next;
/*若此單鏈表中沒有回車符且有超過76個節點時,則p1會指向此列單鏈表中的第76個節點*/
for(i=0;i<75;i++)
{
if(p1->ch==13||p1->next==NULL) break;
p1=p1->next;
}
p2=p1->next;
p1->next=NULL; /*在此行的最后一個字符的前一個字符處斷行,因為插入在此行插入了一個新的字符*/
if(tail->ch!=13) /*若此行行尾不是回車鍵*/
{
if(p1->ch==13&&q->nextl==NULL)/*若p1的數據域為回車符且行單鏈表中只有n個節點*/
{
q->nextl=(Hnode *)malloc(sizeof(Hnode)); /*新建一個行單鏈表節點,相當于添加一個新行*/
q->nextl->nextl=NULL;
tail->next=(node *)malloc(sizeof(node));/*在tail所指節點位置開始繼續準備添加字符*/
tail->next->ch=13; tail->next->next=NULL;
q->nextl->next=p2; /*新行單鏈表節點保存此行多出的字符*/
}
else /*若此行行尾和行中都沒有回車鍵,或者q->nextl不為空*/
{
q=q->nextl;/*q->nextl有可能為空*/
tail->next=q->next;/*將多出的字符與下一行的字符相連*/
q->next=p2;/**/
if(q!=NULL) test(Hhead,++n); /*若行單鏈表第n個節點后還有節點,繼續test()的相同處理*/
}
}
else /*若此列單鏈表最后一個元素為回車符*/
{
temp2=p2; /*p2指向第77個字符,或者為空(為空表示此行插入一個字符后,沒有超出范圍*/
while(q!=NULL&&p2!=NULL) /*q指向行列表中的第n個節點.條件:行單鏈表中第n個節點存中且有第77個字符*/
{ /*條件:在行單鏈表中只有n個節點,且字符超過了一行規定的76個,且num1標志為1*/
if((q->nextl==NULL)&&(p1!=tail||p2!=NULL)&&(num1==1))
{
num1++;
q->nextl=(Hnode *)malloc(sizeof(Hnode)); /*新建一個行單鏈表節點,準備存儲此行中多出的字符*/
q->nextl->nextl=NULL; q->nextl->next=NULL; /*初始化值*/
}
/*行單鏈表中第n+1個節點已經存在,下面為在行單鏈表中插入一個新的節點*/
q=q->nextl; /*q指向行列表中的第n+1個節點*/
temp1=q->next;
q->next=temp2; /*q的數據域為此行中多出的字符所在的列單鏈表中的節點地址*/
temp2=temp1;
}
}
}
void insert(Hnode *Hhead,int m,int n, char a) /*第m行,第n列的位置之前一個位置,插入單字符*/
{
int i;
Hnode *q;
node *p,*p1,*p2;
q=Hhead;
for(i=1;i<m;i++) /*定位至行單鏈表中的第m個元素*/
q=q->nextl;
p1=q->next;
for(i=1;i<n-1;i++) /*定位至列單鏈表中的第n-1個元素*/
p1=p1->next;
p=(node *)malloc(sizeof(node)); /*創建一個新的列單鏈表節點*/
p->ch=a; /*給此節點的數據域賦值*/
if(n==1) /*插入之前,若只有一個字符在行中,則插在此節點之前*/
{
p->next=q->next;
q->next=p;
}
else
{
p->next=p1->next; /*在第m行,第n列的字符前,插入一字符*/
p1->next=p;
}
test(Hhead,m); /*在插入新元素后,檢驗并處理單鏈表中第m行開始的元素,使其滿足規則*/
}
/*對控制鍵進行響應,A:按鍵的整數值,Hhead:行單鏈表的首地址*/
void control(int A, Hnode *Hhead)
{
void colorview(Hnode *,int,int); /*函數聲明*/
int x,y,flag=0;
x=wherex(); y=wherey(); /*得到當前光標的坐標值*/
if((A==CL)&&(x!=1)) /*ctrl+←,當前光標不是在行首,光標移動*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -