A LINE EDITOR : MYWORD
ÀÛ¼º: ±èÁøÈ«
1Çг⠻õ³»±â¶§ C·Î óÀ½ ¸¸µé¾îº» ÇÁ·Î±×·¥ÀÓ. µµ½ºÀÇ edline°ú À¯»çÇÑ ±â´ÉÀ» ±¸ÇöÇÑ´Ù.
»ç¿ë¹ýÀº ¹Ù·Î ¾Æ·¡ comment¿¡ ÀÖÀ½.
/*
MYWORD4
COMMANDS:
L : display the list
Q : quit
C [# or '.'] : change one line
P [# or '.'] : set current position
I [# or '.'] : insert oneline
D [# or '.'] : delete oneline
S [# or '.'] : substitute
Ex) "How can I help you? s ."
"abc/defg"
result: The string "abc" in line
of the current position is
replaced with "defg".
# means a number from 1 to NBRLINES
'.' means current position
*/
#include <stdio.h>
#define NBRLINES 200
#define LINELENGTH 100
#define TRUE 1
#define FALSE 0
/* defines command messages */
#define MSG_NONE 0
#define MSG_LIST 1
#define MSG_QUIT 2
#define MSG_CHANGE 3
#define MSG_DESTROY 4 /* MSG_DESTROY informs to exit the program */
#define MSG_SETPOS 5
#define MSG_INSERT 6
#define MSG_DELETE 7
#define MSG_SUBSTITUTE 8
/* defines error messages */
#define MSG_UNKNOWN 100 /* MSG_UNKNOWN means unknown command */
#define MSG_OUTOFRANGE 101
struct TextStruct {
char line[LINELENGTH];
int used; /* mark the line if occupied */
};
struct TextStruct Text[NBRLINES];
struct TextStruct *LineP[NBRLINES]; /* Line Pointers */
int TLines = 0; /* Total lines */
int TChars = 0; /* Total chars */
int MESSAGE = MSG_NONE;
int POSITION = 0;
void readfile(char *fname);
int getoneline(char *buf);
char upcase(char c);
void getcommand(char *buf);
void list(void);
void quit(char *fname);
void savefile(char *fname);
void changeline(char *buf);
void postmessage(int msg);
int val(char *str);
int power10(int num);
void clearline(char *);
void setposition(char *buf);
int getposition(char *buf);
void insertline(char *buf);
void deleteline(char *buf);
void process_error(void); /* process error messages */
int findemptyline();
int str_cmp(char *src1, char *src2);
int str_len(char *str);
void str_cpy(char *dst, char *src);
int getpara(int idx, char *argvs, char *out);
void readsomestr(char *src, char *buf, int idx, int cnt);
void substitute(char *buf);
void main(int argc, char **argv)
{
char buf[LINELENGTH]; /* temporary line-buffer */
if (argc != 2) {
printf("Usage: %s filename\n", argv[0]);
return;
}
readfile(argv[1]); /* read file into the Text[] */
while (MESSAGE != MSG_DESTROY) {
printf("How can I help you? "); /* the PROMPT */
getoneline(buf); /* read one line from console */
getcommand(buf); /* distinguish commands */
switch(MESSAGE) {
case MSG_LIST:list(); break;
case MSG_QUIT:quit(argv[1]); break;
case MSG_CHANGE:changeline(buf); break;
case MSG_SETPOS:setposition(buf); break;
case MSG_INSERT:insertline(buf); break;
case MSG_DELETE:deleteline(buf); break;
case MSG_SUBSTITUTE:substitute(buf); break;
}
process_error();
clearline(buf); /* clear the 'buf' */
}
}
/* read data from a file into the 'Text' array. */
void readfile(char *fname)
{
FILE *handle;
char c;
int cnt;
/* initialize the line pointers */
for (cnt=0; cnt<NBRLINES; cnt++) {
LineP[cnt]=&Text[cnt]; /* pointers indicate each line of the Text */
LineP[cnt]->used=FALSE;
}
/* if the file is not exist, create new file */
if ((handle=fopen(fname, "rt")) == NULL) {
printf("\"%s\" new file.\n", fname);
return;
}
cnt=0;
while ((c=fgetc(handle)) != EOF) {
if (c != '\n' && cnt < LINELENGTH-1) {
LineP[TLines]->line[cnt]=c; /* read a character */
cnt++;
TChars++;
} else {
LineP[TLines]->line[cnt]='\0'; /* make a string */
LineP[TLines]->used=TRUE;
cnt=0;
if (TLines < NBRLINES) TLines++;
}
if (TLines == NBRLINES) break;
}
printf("\"%s\" opened %d chars / %d lines.\n", fname, TChars, TLines);
POSITION=TLines; /* default position value */
fclose(handle);
}
int getoneline(char *buf)
{
char c;
int cnt=0;
while((c=getchar()) != '\n') {
if (cnt < LINELENGTH-1) cnt++;
else break;
*buf++ = c;
}
*buf='\0'; /* make a string */
return cnt;
}
char upcase(char c) /* changes lowercase letters to capital letters */
{
if (c >= 'a' && c <= 'z') return c-32;
else return c;
}
/* make a message for main function */
void postmessage(int msg)
{
MESSAGE=msg;
}
/* retrieve a command */
void getcommand(char *buf)
{
switch (upcase(*buf)) {
case 'L':postmessage(MSG_LIST); break;
case 'Q':postmessage(MSG_QUIT); break;
case 'C':postmessage(MSG_CHANGE); break;
case '\0':postmessage(MSG_NONE); break;
case 'P':postmessage(MSG_SETPOS); break;
case 'I':postmessage(MSG_INSERT); break;
case 'D':postmessage(MSG_DELETE); break;
case 'S':postmessage(MSG_SUBSTITUTE); break;
default :postmessage(MSG_UNKNOWN); break;
}
}
/* display all of the list */
void list()
{
int t;
for (t=0; t<TLines; t++)
printf("%d: %s\n", t+1, LineP[t]->line);
}
void quit(char *fname)
{
char c;
printf("save changes(y/n) ");
c=upcase(getchar());
if (c == 'Y') {
savefile(fname);
printf("write\n");
postmessage(MSG_DESTROY); /* ends program */
} else
if (c == 'N') {
printf("exit\n");
postmessage(MSG_DESTROY);
}
/* clear the key buffer */
if (c != '\n') while ((c=getchar()) != '\n');
}
void savefile(char *fname)
{
FILE *handle;
int t, i;
handle=fopen(fname, "wt"); /* create a file(overwrite) */
for (t=0; t<TLines; t++) {
for (i=0; LineP[t]->line[i] != '\0'; i++)
fputc(LineP[t]->line[i], handle);
fputc('\n', handle); /* make a newline */
}
fclose(handle);
}
/* return a parameter(number) */
int getposition(char *buf)
{
if (*(buf+2) == '.') return(POSITION); /* current position number */
else return(val(buf+2)); /* read number */
}
void changeline(char *buf)
{
char tmp[LINELENGTH];
int theline;
theline=getposition(buf);
if (theline < 1 || (TLines == 0 && theline > TLines+1) ||
(TLines != 0 && theline > TLines)) {
if (theline == -1) postmessage(MSG_UNKNOWN); /* NO PARAMETER!! */
else postmessage(MSG_OUTOFRANGE); /* OUT OF RANGE!! */
return;
}
printf("%d ", theline);
if (getoneline(tmp) == 0) return; /* if nothing is input */
str_cpy(LineP[theline-1]->line, tmp);
LineP[theline-1]->used=TRUE;
if (theline == 1 && TLines == 0) {
POSITION++;
if (TLines < NBRLINES) TLines++; /* correct the total line(TLines) */
}
}
void str_cpy(char *dst, char *src)
{
while (*dst++=*src++);
}
/* translate a string to number */
int val(char *str)
{
char numstr[5];
int cnt=0, t;
int theval=0;
while(*str >= '0' && *str <='9' && cnt<4) {
numstr[cnt]=*str;
str++;
cnt++;
}
if (cnt==0) return -1; /* number wasn't input */
numstr[cnt]='\0'; /* make it a string */
for(t=0; t<cnt; t++)
theval += (numstr[t]-'0')*power10(cnt-t-1);
return theval;
}
/* make the power of 10 */
int power10(int num)
{
int t;
int theval=1;
for (t=0; t<num; t++) theval *= 10;
return theval;
}
/* clear the line buffer */
void clearline(char *buf)
{
int t;
for(t=0; t<LINELENGTH; t++) *(buf+t)='\0';
}
void setposition(char *buf)
{
int theline;
if (*(buf+2) == '.') {
printf("current line number = %d\n", POSITION);
return;
}
theline=val(buf+2); /* read number */
if (theline < 1 || theline > TLines) {
if (theline == -1) postmessage(MSG_UNKNOWN);
else postmessage(MSG_OUTOFRANGE);
return;
}
POSITION=theline;
printf("moved to line number %d\n", POSITION);
}
void deleteline(char *buf)
{
int t, theline;
theline=getposition(buf);
if (theline < 1 || theline > TLines) {
if (theline == -1) postmessage(MSG_UNKNOWN);
else postmessage(MSG_OUTOFRANGE);
return;
}
/* mark it to NOT-USED */
LineP[theline-1]->used=FALSE;
/* move up line pointers */
for (t=theline-1; t<TLines-1; t++) LineP[t]=LineP[t+1];
if (TLines > 0) TLines--;
if (POSITION > TLines) POSITION=TLines; /* correct POSITION */
}
void insertline(char *buf)
{
char tmp[LINELENGTH];
int t, emptyline;
int theline;
theline=getposition(buf);
if (theline < 1 || theline > TLines) {
if (theline == -1) postmessage(MSG_UNKNOWN);
else postmessage(MSG_OUTOFRANGE);
return;
}
if (theline == NBRLINES) printf("%d ", theline);
else printf("%d ", theline+1);
if (getoneline(tmp) == 0) return; /* if nothing is input */
if (TLines < NBRLINES) TLines++;
/* move down line pointers */
for (t=TLines; t>theline; t--) LineP[t-1]=LineP[t-2];
if ((emptyline=findemptyline()) == -1) emptyline=NBRLINES-1;
str_cpy(Text[emptyline].line, tmp);
LineP[theline]=&Text[emptyline];
LineP[theline]->used=TRUE;
}
int findemptyline()
{
int t;
/* find a empty line */
for (t=0; t<NBRLINES; t++)
if (Text[t].used == FALSE) return t;
return -1; /* no empty line found */
}
void process_error()
{
switch (MESSAGE) {
case MSG_OUTOFRANGE:
printf("requested line number out of range!\n");
break;
case MSG_UNKNOWN:
printf("error\n");
break;
}
}
int getpara(int idx, char *argvs, char *out)
{
int t=0, i=0;
int cnt=0;
char c;
if (*argvs == '\0') return 0; /* if nothing is input */
*out='\0'; /* clean up */
while (*(argvs+t)) {
if (*(argvs+t) == '/') cnt++;
if (cnt == idx) {
if (idx > 0) t++;
while (1) {
c=*(argvs+t+i);
if (c == '/' || c == '\0') break;
*(out+i)=c;
i++;
}
*(out+i)='\0';
return 1;
}
t++;
}
return 0;
}
void readsomestr(char *src, char *buf, int idx, int cnt)
{
int t;
for (t=0; t<cnt; t++) *(buf+t)=*(src+t+idx);
*(buf+t)='\0'; /* make it a string */
}
int str_cmp(char *src1, char *src2)
{
int t=0;
while(1) {
if (*(src1+t) != *(src2+t)) return 0;
if (*(src1+t) == '\0' && *(src2+t) == '\0') break;
t++;
}
return 1;
}
int str_len(char *str)
{
int t=0;
while(*(str+t)) t++;
return(t);
}
void substitute(char *buf)
{
char tmp[LINELENGTH];
char src1[30], src2[30], tmp2[30];
int theline, len1, len2;
int pos1=0, pos2=0, cnt=0, found=FALSE;
theline=getposition(buf);
if (theline < 1 || theline > TLines) {
if (theline == -1) postmessage(MSG_UNKNOWN);
else postmessage(MSG_OUTOFRANGE);
return;
}
if (getoneline(tmp) == 0) { /* if nothing is input */
postmessage(MSG_UNKNOWN);
return;
}
/* if nothing is input for 1st parameter, make error */
if (getpara(0, tmp, src1) == FALSE) {
postmessage(MSG_UNKNOWN);
return;
}
/* if nothing is input for 2nd parameter, make error */
if (getpara(1, tmp, src2) == FALSE) {
postmessage(MSG_UNKNOWN);
return;
}
/* if the first and the second parameter are same... */
if (str_cmp(src1, src2)) return;
len1=str_len(src1);
len2=str_len(src2);
while(1) {
if ((found == FALSE) && (LineP[theline-1]->line[pos1] == *src1)) {
readsomestr(LineP[theline-1]->line, tmp2, pos1, len1);
if (str_cmp(src1, tmp2)) {
cnt=len2;
pos1+=len1;
found=TRUE;
}
}
if (found == FALSE) tmp[pos2] = LineP[theline-1]->line[pos1];
else {
if (pos2 == 100) break;
if (*src2 != '\0') {
tmp[pos2] = *(src2+(len2-cnt));
cnt--;
pos2++;
}
if (cnt == 0) found=FALSE;
continue;
}
pos1++;
pos2++;
if (LineP[theline-1]->line[pos1] == '\0') break;
}
tmp[pos2]='\0'; /* make a string */
/* copy the completed temporary block 'tmp' to original block of 'Text' */
str_cpy(LineP[theline-1]->line, tmp);
}