/* edit.c */ #include "config.h" #include "object.h" #include "interface.h" #include "construct.h" #include "globals.h" #include "file.h" struct edit_s *find_buf(struct object *obj) { struct edit_s *curr; curr=edit_list; while (curr) { if (curr->obj==obj) return curr; curr=curr->next; } return NULL; } void delete_line(struct edit_s *buf, unsigned long line) { struct edit_buf *curr,*next; unsigned int num_bufs,index,count; count=buf->num_lines-line; --(buf->num_lines); num_bufs=(line-1)/NUM_ELINES; index=(line-1)%NUM_ELINES; curr=buf->buf; while (num_bufs--) curr=curr->next; if (curr->buf[index]) FREE(curr->buf[index]); while (count--) { if (index==NUM_ELINES-1) { curr->buf[index]=curr->next->buf[0]; index=0; curr=curr->next; } else curr->buf[index]=curr->buf[++index]; } } void insert_line(struct edit_s *buf, unsigned long line, char *new_line) { struct edit_buf *curr; unsigned long index,count,num_bufs; char *tmp,*tmp2; count=buf->num_lines-line; ++(buf->num_lines); curr=buf->buf; if (!curr) { buf->buf=MALLOC(sizeof(struct edit_buf)); buf->buf->next=NULL; curr=buf->buf; } index=(line)%NUM_ELINES; num_bufs=(line)/NUM_ELINES; while (num_bufs--) { if (!(curr->next)) { curr->next=MALLOC(sizeof(struct edit_buf)); curr->next->next=NULL; } curr=curr->next; } tmp=curr->buf[index]; curr->buf[index]=copy_string(new_line); while (count--) { if (index==NUM_ELINES-1) { if (!(curr->next)) { curr->next=MALLOC(sizeof(struct edit_buf)); curr->next->next=NULL; } tmp2=curr->next->buf[0]; curr->next->buf[0]=tmp; tmp=tmp2; index=0; curr=curr->next; } else { tmp2=curr->buf[++index]; curr->buf[index]=tmp; tmp=tmp2; } } } void empty_buf(struct edit_s *buf) { struct edit_buf *curr,*next; unsigned long count; count=buf->num_lines; curr=buf->buf; if (buf->path) { FREE(buf->path); buf->path=NULL; } while (count) delete_line(buf,count--); curr=buf->buf; while (curr) { next=curr->next; FREE(curr); curr=next; } buf->buf=NULL; buf->num_lines=0; buf->is_changed=0; buf->curr_line=0; } void read_into_buf(struct edit_s *buf, char *filename) { FILE *f; unsigned long count,index; struct edit_buf *curr; char sbuf[MAX_STR_LEN]; int len; if (!(f=open_file(filename,"r",buf->obj))) { send_device(buf->obj,"couldn't read "); send_device(buf->obj,filename); send_device(buf->obj,"\n"); return; } count=0; empty_buf(buf); buf->buf=MALLOC(sizeof(struct edit_buf)); curr=buf->buf; curr->next=NULL; index=0; while (fgets(sbuf,MAX_STR_LEN,f)) { count++; len=strlen(sbuf); if (len) if (sbuf[len-1]=='\n') sbuf[len-1]='\0'; curr->buf[index]=copy_string(sbuf); index++; if (index==NUM_ELINES) { index=0; curr->next=MALLOC(sizeof(struct edit_buf)); curr->next->next=NULL; curr=curr->next; } } buf->num_lines=count; buf->path=copy_string(filename); buf->curr_line=0; buf->is_changed=0; buf->inserting=0; close_file(f); send_device(buf->obj,"read "); send_device(buf->obj,filename); send_device(buf->obj,"\n"); } void write_to_buf(struct edit_s *buf, char *filename) { FILE *f; unsigned long count,index; struct edit_buf *curr; if (!(f=open_file(filename,"w",buf->obj))) { send_device(buf->obj,"couldn't write "); send_device(buf->obj,filename); send_device(buf->obj,"\n"); return; } count=0; index=0; curr=buf->buf; while (count++<buf->num_lines) { fputs(curr->buf[index],f); fputc('\n',f); index++; if (index==NUM_ELINES) { index=0; curr=curr->next; } } buf->is_changed=0; close_file(f); send_device(buf->obj,"wrote "); send_device(buf->obj,filename); send_device(buf->obj,"\n"); } void add_to_edit(struct object *obj, char *file) { struct edit_s *curr; if (obj->flags & IN_EDITOR) return; if (!(obj->flags & CONNECTED)) return; obj->flags|=IN_EDITOR; curr=MALLOC(sizeof(struct edit_s)); curr->obj=obj; curr->num_lines=0; curr->buf=NULL; curr->path=NULL; curr->curr_line=0; curr->inserting=0; curr->is_changed=0; curr->next=edit_list; edit_list=curr; send_device(obj,"entering editor\n"); if (file) read_into_buf(curr,file); } void remove_from_edit(struct object *obj) { struct edit_s *prev,*curr; if (!(obj->flags & IN_EDITOR)) return; obj->flags&=~IN_EDITOR; curr=edit_list; prev=NULL; while (curr) { if (curr->obj==obj) { if (prev) prev->next=curr->next; else edit_list=curr->next; break; } curr=curr->next; } if (!curr) return; empty_buf(curr); FREE(curr); } void split_arg(struct edit_s *buf, unsigned long *arg1, unsigned long *arg2, char *arg) { int count,len,has_hyphen; char *a1,*a2; count=0; a1=arg; a2=""; has_hyphen=0; len=strlen(arg); while (count<len) { if (arg[count]=='-') { arg[count]='\0'; has_hyphen=1; a2=&(arg[count+1]); break; } count++; } if (has_hyphen) { if (*a1) *arg1=atol(a1); else *arg1=1; if (*a2) *arg2=atol(a2); else *arg2=buf->num_lines; } else if (*arg) { *arg1=atol(arg); *arg2=*arg1; } else { *arg1=buf->curr_line; *arg2=*arg1; } } void do_edit_command(struct object *obj, char *s) { char *cmd,*arg; unsigned long line1,line2; int loop,len,index,num_bufs,count; struct edit_s *buf; struct edit_buf *curr; char sbuf[ITOA_BUFSIZ+3]; buf=find_buf(obj); if (!buf) return; if (buf->curr_line>buf->num_lines) buf->curr_line=buf->num_lines; if (buf->inserting) { if (!strcmp(s,".")) { buf->inserting=0; send_device(buf->obj,"exiting insertion mode\n"); } else { insert_line(buf,buf->curr_line,s); ++(buf->curr_line); } return; } loop=0; len=strlen(s); cmd=s; arg=""; while (loop<len) { if (s[loop]==' ') { s[loop]='\0'; arg=&(s[loop+1]); break; } loop++; } if (!strcmp(cmd,"l") || !strcmp(cmd,"list")) { split_arg(buf,&line1,&line2,arg); if (!line1) return; if (line1<1) line1=1; if (line2>buf->num_lines) line2=buf->num_lines; count=line2-line1+1; if (count<1) return; index=(line1-1)%NUM_ELINES; num_bufs=(line1-1)/NUM_ELINES; curr=buf->buf; while (num_bufs--) curr=curr->next; while (count--) { sprintf(sbuf,"%ld: ",(long) line1++); send_device(buf->obj,sbuf); send_device(buf->obj,curr->buf[index]); send_device(buf->obj,"\n"); index++; if (index==NUM_ELINES) { index=0; curr=curr->next; } } return; } if (!strcmp(cmd,"q") || !strcmp(cmd,"quit")) { if (buf->is_changed) { send_device(buf->obj,"file has been modified\n"); return; } send_device(buf->obj,"exiting editor\n"); remove_from_edit(buf->obj); return; } if (!strcmp(cmd,"i") || !strcmp(cmd,"insert")) { if (*arg) { line1=atol(arg); if (line1<0 || line1>buf->num_lines) { send_device(buf->obj,"line number out of range\n"); return; } buf->curr_line=line1; } buf->is_changed=1; buf->inserting=1; send_device(buf->obj,"entering insertion mode\n"); return; } if (!strcmp(cmd,"r") || !strcmp(cmd,"read")) { if (!arg) { send_device(buf->obj,"no filename specified\n"); return; } empty_buf(buf); read_into_buf(buf,arg); return; } if (!strcmp(cmd,"w") || !strcmp(cmd,"write")) { if (!*arg && !buf->path) { send_device(buf->obj,"no filename specified\n"); return; } if (*arg) buf->path=copy_string(arg); write_to_buf(buf,buf->path); return; } if (!strcmp(cmd,"x") || !strcmp(cmd,"exit")) { empty_buf(buf); send_device(buf->obj,"exiting editor\n"); remove_from_edit(buf->obj); return; } if (!strcmp(cmd,"d") || !strcmp(cmd,"delete")) { split_arg(buf,&line1,&line2,arg); if (line1>buf->num_lines || line1<line2 || line1==0) return; count=line2-line1+1; while (count--) delete_line(buf,line1); send_device(buf->obj,"deleted\n"); return; } if (!strcmp(cmd,"?") || !strcmp(cmd,"h") || !strcmp(cmd,"help")) { send_device(buf->obj,"list <#>-<#> lists file. line #'s " "optional\n"); send_device(buf->obj,"quit quit editor unless file " "not saved\n"); send_device(buf->obj,"insert <#> insert line at directly " "after specified #\n"); send_device(buf->obj,"delete <#>-<#> deletes lines. #'s " "optional\n"); send_device(buf->obj,"read filename reads a file\n"); send_device(buf->obj,"write <filename> writes a file\n"); send_device(buf->obj,"exit quit editor\n"); send_device(buf->obj,"help this help screen\n"); send_device(buf->obj,"status editor status\n"); return; } if (!strcmp(cmd,"s") || !strcmp(cmd,"status")) { send_device(buf->obj,"file being edited: "); if (buf->path) send_device(buf->obj,buf->path); else send_device(buf->obj,"<unknown>"); send_device(buf->obj,"\nnumber of lines: "); sprintf(sbuf,"%ld",(long) buf->num_lines); send_device(buf->obj,sbuf); send_device(buf->obj,"\ncurrent line: "); sprintf(sbuf,"%ld",(long) buf->curr_line); send_device(buf->obj,sbuf); if (buf->is_changed) send_device(buf->obj,"\nfile has been modified\n"); else send_device(buf->obj,"\nfile has not been modified\n"); return; } send_device(buf->obj,"syntax error. type 'help' for help\n"); }