Jul 16
DOS下虽然有edit编辑器和更加原始的EDLIN行编辑器,但近几天我把《THE CRAFT OF C》中关于Screen-Editor的代码全部输机,想自己再弄出个新的文本编辑器。
代码如下:(在turboc下成功编译通过,但无法正常运行)
/* A Screen Editor Subsystem*/ #define TURBOC #include <stdio.h> #include <dos.h> #include <string.h> #include <bios.h> #include <conio.h> #define BUF_SIZE 32000 #define LINE_LEN 79 #define MAX_LINES 24 #define KILL_BUF_SIZE 4*LINE_LEN char buf[BUF_SIZE]; char *curloc,*endloc; int scrnx,scrny; char killbuf[KILL_BUF_SIZE]; char *helpline= "F1:save F2:load F3:find F4:replace\ ^K:Kill line ^Y:Yank ^Z:Quit "; void edit(char *fname),help(); void gotoxy(int x,int y),clrline(int y); void edit_clr_eol(int x,int y),clrscr(); void printline(char *p),delete_char(void); void search(),kill_line(); void upline(); void downline(),left(),right(); void scrolldn (int x,int y); void scrollup(int topx,int topy,int endx,int endy); void display_scrn(int x,int y,char *p); void pagedown(),pageup(),replace(); void home(),gotoend(),yank(); int load(char *fname),save(char *fname); void edit_gets(char *str); main(int argc,char *argv[]) { if (argc==2) edit(argv[1]); clrscr(); return 0; } /* This is the editor's entry function and contains its main loop. Call it with the name of the file you want to edit. */ void edit(char *fname) { union k{ char ch[2]; unsigned i; }key; char name[80]; /*try to load the file*/ if(!load(fname)) curloc=endloc=buf; strcpy(name,fname); clrscr(); scrnx=scrny=0; display_scrn(0,0,curloc); help(); gotoxy(0,0); /*Editor main loop*/ do{ key.i=bioskey(0); if(!key.ch[0]){ switch(key.ch[1]){ case 59: /*F1 save*/ save (name); break; case 60: /*F2 load*/ clrline(MAX_LINES); gotoxy(0,MAX_LINES); printf ("Enter filename:"); edit_gets(name); if (*name) load (name); help(); display_scrn(0,0,curloc); scrnx=scrny=0; break; case 61: /*F3 search*/ search(); break; case 62: /*F4 relace*/ replace(); break; case 71: /*home*/ home(); break; case 79: /*end*/ gotoend(); break; case 75: /* left*/ left(); break; case 77: /*right*/ right(); break; case 72: /*up*/ upline(); break; case 80: /*down*/ downline(); break; case 73: /*page up*/ pageup(); break; case 81: /*page down*/ pagedown(); break; case 83: /*del*/ if(curloc<endloc) delete_char(); break; } if(curloc<buf){ scrnx=scrny=0; curloc=buf; } gotoxy(scrnx,scrny); } else{ /* enter keystroke into file*/ switch(key.ch[0]){ case '\r': /* Carriage return*/ /*see if buffer is full*/ if(endloc==buf+BUF_SIZE-2) break; /* move contents of file below current location down one byte to make room for the RETURN */ memmove(curloc+1,curloc,endloc-curloc+1); *curloc=key.ch[0]; curloc++; /*clear rest of line*/ edit_clr_eol(scrnx,scrny); scrnx=0; scrny++; /*move text on the screen down*/ if (scrny==MAX_LINES){ scrny=MAX_LINES-1; scrollup(0,0,LINE_LEN,scrny); } else scrolldn(scrnx,scrny); gotoxy(scrnx,scrny); printline(curloc); endloc++; break; case '\b': /*backspace*/ if(curloc==buf) break; left (); delete_char(); break; case 11: /*C-K:kiil line*/ kill_line(); break; case 25: /*C-Y:yank kill buffer*/ yank(); break; default: if(endloc==buf+BUF_SIZE-2) break; /*can't type past end of line*/ if(scrnx==LINE_LEN) break; memmove(curloc+1,curloc,endloc-curloc+1); *curloc=key.ch[0]; putch(*curloc); scrnx++; gotoxy(scrnx,scrny); printline(curloc+1); curloc++; endloc++; } gotoxy(scrnx,scrny); } }while(key.ch[0]!=26); } /* Display a line pointed to by P.*/ void printline(register char *p) { register int i; i=scrnx; while(*p!='\r'&& *p && i<LINE_LEN){ putch(*p); p++; i++; } } /*Insert previously killed line*/ void yank() { char *p; p=killbuf; while(*p){ memmove(curloc+1,curloc,endloc-curloc+1); *curloc=*p; if(scrnx<LINE_LEN){ putch(*curloc); scrnx++; } curloc++; endloc++; p++; } printline (curloc); } /*Delete the line at the current location*/ void kill_line() { register int i; char *p,*killbufptr; if(*curloc=='\r'){ delete_char(); return; } edit_clr_eol(scrnx,scrny); /*find out how many characters are in the line*/ p=curloc; i=0; killbufptr=killbuf; while(*p!='\r' && p<endloc){ i++; *killbufptr=*p; p++; if(killbufptr<killbuf+KILL_BUF_SIZE-2) killbufptr++; } *killbufptr='\0'; /*remove the line*/ memmove(curloc,curloc+1,endloc-curloc); endloc-=i; } /*Global search and replace*/ void replace() { register int len1; char str1[80],str2[80]; char *p,*p2; clrline(MAX_LINES); gotoxy(0,MAX_LINES); printf("enter string to replace: "); edit_gets(str1); clrline(MAX_LINES); gotoxy(0,MAX_LINES); printf ("enter replacement: "); edit_gets(str2); p=curloc; len1=strlen(str1); while(*str1){ /*search for a string*/ while(*p && strncmp(str1,p,len1)) p++; if (!p) break; /*remove old string*/ memmove(p,p+len1,endloc-p); endloc-=len1; /*insert new string*/ p2=str2; while(*p2){ memmove(p+1,p,endloc-p+1); *p=*p2; p++; endloc++; p2++; } } clrscr(); /*find location of top of screen*/ p=curloc; for(len1=scrny;len1>=0&&p>buf;){ p--; if(*p=='\r') len1--; } if(*p=='\r') p++; /*redisplay current screen*/ display_scrn(0,0,p); help(); } /*Delete character at the current location.*/ void delete_char() { gotoxy(scrnx,scrny); if(*curloc=='\r'){ scrollup(0,scrny+1,LINE_LEN,MAX_LINES-1); memmove(curloc,curloc+1,endloc-curloc); endloc--; display_scrn(scrnx,scrny,curloc); help(); } else{ memmove(curloc,curloc+1,endloc-curloc); endloc--; printline(curloc); printf(" "); } } /*Display help line*/ void help() { gotoxy(0,MAX_LINES); printf(helpline); } /*Move current location left*/ void left() { if(curloc==buf) return; scrnx--; if(scrnx<0){ scrnx=0; upline(); /*find end of line*/ while(*curloc!='\r'){ curloc++; scrnx++; } } else curloc--; } /*Move currrent position right*/ void right() { /*can't move rihgt*/ if(curloc+1>endloc) return; scrnx++; /*if at end of line,go to next one*/ if(scrnx>LINE_LEN||*curloc=='\r'){ scrnx=0; scrny++; if(scrny==MAX_LINES){ scrny=MAX_LINES-1; downline(); /*move cursor and current loc to start of new line*/ curloc--; while(*curloc!='\r') curloc--; curloc++; scrnx=0; } else curloc++; } else curloc++; } /*Find a string*/ void search() { char str[80]; register char *p; int len,i; clrline(MAX_LINES); gotoxy(0,MAX_LINES); printf("search string: "); edit_gets(str); if(!*str) return; p=curloc; len=strlen(str); /*search for the string*/ while(*p && strncmp(str,p,len)) p++; if(!*p) return; /*back up to start of line*/ i=0; while(p>buf&&*p!='\r'){ p--; i++; } p++; i--; /*reposition current location to start of match*/ curloc=p+i; scrnx=i; scrny=0; /*diplay screenof text at location of match*/ clrscr(); display_scrn(0,0,p); help(); } /*Move up one line.*/ void upline() { register int i; char *p; if(curloc==buf) return; p=curloc; if(*p=='\r') p--; /*back up loacator to start of current line.*/ for(;*p!='\r'&&p>buf;p--); if(*p!='\r') return; curloc=p; curloc--; i=scrnx; /*find start of next line*/ while(*curloc!='\r' && curloc>=buf) curloc--; scrny--;scrnx=0; curloc++; /*at top of screen,must scroll up*/ if(scrny<0){ scrolldn(0,0); scrny=0; gotoxy(0,0); printline(curloc); } /* position the cursor and current location at same scrnx position as previous line if possible*/ while(i&& *curloc!='\r'){ curloc++; scrnx++; i--; } } /* Move down one line. */ void downline() { register int i; char *p; i=scrnx; p=curloc; /* advance current location to start to next line*/ while(*p!='\r' && p<endloc) p++; if(p==endloc) return; p++; curloc=p; scrny++;scrnx=0; /*if moving down past the bottom of the screen*/ if(scrny==MAX_LINES){ scrny=MAX_LINES-1; scrollup(0,0,LINE_LEN,MAX_LINES-1); gotoxy(scrnx,scrny); printline(curloc); } /* advance to corresponding character in next line*/ while(i && *curloc!='\r' && curloc<endloc){ curloc++; scrnx++; i--; } } /* Display a screen full of text(up to 24lines) starting at the specified location. */ void display_scrn(int x,int y,char *p) { register int i; gotoxy(x,y); i=0; while(y<MAX_LINES && *p){ switch(*p){ case '\r':printf("\n"); y++; i=0; break; default:if(i<LINE_LEN) putch(*p); i++; } p++; } } /* Page down MAX_LINES lines.*/ void pagedown() { register int i; clrscr(); /*count down MAX_LINES lines.*/ for(i=0;i<MAX_LINES && curloc<endloc;){ if (*curloc=='\r') i++; curloc++; } help(); scrnx=0;scrny=0; display_scrn(0,0,curloc); } /* Page up MAX_LINES lines*/ void pageup() { register int i; clrscr(); if (*curloc=='\r' && curloc>buf) curloc--; /* go back MAX_LINES in buffer*/ for(i=0;i<MAX_LINES+1 && curloc>buf;){ if(*curloc=='\r') i++; curloc--; } if(i==MAX_LINES+1) curloc+=2; help(); scrnx=0;scrny=0; display_scrn(0,0,curloc); } /* Go to the top of the file.*/ void home() { clrscr(); curloc=buf; scrnx=scrny=0; display_scrn(0,0,curloc); help(); } /* Go to the end of the file. */ void gotoend() { clrscr(); curloc=endloc; pageup(); } /* Load a file.*/ load(char *fname) { FILE *fp; char ch,*p; if((fp=fopen(fname,"rb"))==NULL) return 0; p=buf; while(!feof(fp) && p!=buf+BUF_SIZE-2){ ch=getc(fp); if(ch!='\n' && ch!=EOF){ *p=ch; p++; } } *p='\0'; fclose (fp); curloc=buf; endloc=p; return 1; } /* Save a file.*/ save(char *fname) { FILE *fp; char *p,name[80]; if(!*fname){ printf("filename: "); gets(name); } else strcpy(name,fname); if((fp=fopen(name,"wb"))==NULL) return 0; p=buf; while(p!=endloc){ if(*p!='\r') putc(*p,fp); else{ putc('\r',fp); putc('\n',fp); } p++; } fclose(fp); return 1; } /* Read a string from the keyboard,but do not scroll the display when a RETURN is entered. */ void edit_gets(char *str) { char *p; p=str; for(;;){ *str=getch(); if(*str=='\r'){ *str='\0'; return; } if(*str=='\b'){ if(str>p){ str--; putch('\b'); putch(' '); putch('\b'); } } else{ putch(*str); str++; } } } /* Read and save cursor coordinates.*/ void cursor_pos() { union REGS i,o; i.h.bh=0; i.h.ah=3; int86(16,&i,&o); } /* Send cursor to specified X,Y (0,0 is Upper left corner. */ void gotoxy(int x,int y) { union REGS i; i.h.dh=y; i.h.dl=x; i.h.ah=2; i.h.bh=0; int86(16,&i,&i); } /* Clear entire line given its Y coordinate.*/ void clrline(int y) { register int i; gotoxy(0,y); for(i=0;i<LINE_LEN;i++) putch(' '); } /* Clear to end of specified line.*/ void edit_clr_eol(int x,int y) { char *p; p=curloc; gotoxy(x,y); for(;x<LINE_LEN && *p!='\r' && *p;x++,p++){ printf(" "); } } /* Clear the screen.*/ void clrscr() { union REGS r; r.h.ah=6; r.h.al=0; r.h.ch=0; r.h.cl=0; r.h.dh=MAX_LINES; r.h.dl=LINE_LEN; r.h.bh=7; int86(0x10,&r,&r); } /*Scroll down the screen.*/ void scrolldn(int x,int y) { union REGS r; r.h.ah=7; r.h.al=1; r.h.ch=y; r.h.cl=x; r.h.dh=MAX_LINES-1; r.h.dl=LINE_LEN; r.h.bh=7; int86(0x10,&r,&r); } /* Scroll up the screen using the specified coordinate.*/ void scrollup(int topx,int topy,int endx,int endy) { union REGS r; r.h.ah=6; r.h.al=1; r.h.ch=topy; r.h.cl=topx; r.h.dh=endy; r.h.dl=endx; r.h.bh=7; int86(0x10,&r,&r); }