/* * The routines in this file * handle the reading and writing of * disk files. All of details about the * reading and writing of the disk are * in "fileio.c". */ #include #include "ed.h" unsigned char insflag = FALSE; /* Flag for C mode in newline() */ /* * Read a file into the current * buffer. This is really easy; all you do it * find the name of the file, and call the standard * "read a file into the current buffer" code. * Bound to "C-X C-R". */ fileread(f, n) register int f, n; { register int s; char fname[NFILEN]; if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE) return (s); return (readin(fname)); } /* * Select a file for editing. * Look around to see if you can find the * file in another buffer; if you can find it * just switch to the buffer. If you cannot find * the file, create a new buffer, read in the * text, and switch to the new buffer. * Bound to C-X C-V. */ filevisit(f, n) register int f, n; { register BUFFER *bp; register WINDOW *wp; register LINE *lp; register int i; register int s; char bname[NBUFN]; char fname[NFILEN]; if ((s=mlreply("Visit file: ", fname, NFILEN)) != TRUE) return (s); strcpy(lastbuf, curbp->b_bname); for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) { if ((bp->b_flag&BFTEMP)==0 && strcmp(bp->b_fname, fname)==0) { if (--curbp->b_nwnd == 0) { curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; } curbp = bp; curwp->w_bufp = bp; if (bp->b_nwnd++ == 0) { curwp->w_dotp = bp->b_dotp; curwp->w_doto = bp->b_doto; curwp->w_markp = bp->b_markp; curwp->w_marko = bp->b_marko; } else { wp = wheadp; while (wp != NULL) { if (wp!=curwp && wp->w_bufp==bp) { curwp->w_dotp = wp->w_dotp; curwp->w_doto = wp->w_doto; curwp->w_markp = wp->w_markp; curwp->w_marko = wp->w_marko; break; } wp = wp->w_wndp; } } lp = curwp->w_dotp; i = curwp->w_ntrows/2; while (i-- && lback(lp)!=curbp->b_linep) lp = lback(lp); curwp->w_linep = lp; curwp->w_flag |= WFMODE|WFHARD; mlwrite("[Old buffer]"); return (TRUE); } } makename(bname, fname); /* New buffer name. */ while ((bp=bfind(bname, FALSE, 0)) != NULL) { s = mlreply("Buffer name: ", bname, NBUFN); if (s == ABORT) /* ^G to just quit */ return (s); if (s == FALSE) { /* CR to clobber it */ makename(bname, fname); break; } } if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) { mlwrite("Cannot create buffer"); return (FALSE); } if (--curbp->b_nwnd == 0) { /* Undisplay. */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; } curbp = bp; /* Switch to it. */ curwp->w_bufp = bp; curbp->b_nwnd++; return (readin(fname)); /* Read it in. */ } /* * Read file "fname" into the current * buffer, blowing away any text found there. Called * by both the read and visit commands. Return the final * status of the read. Also called by the mainline, * to read in a file specified on the command line as * an argument. */ readin(fname) char fname[]; { register LINE *lp1; register LINE *lp2; register int i; register WINDOW *wp; register BUFFER *bp; register int s; register int nbytes; register int nline; char line[NLINE]; bp = curbp; /* Cheap. */ if ((s=bclear(bp)) != TRUE) /* Might be old. */ return (s); bp->b_flag &= ~(BFTEMP|BFCHG); if (fname[0] == '~') /* an alias request */ if ((s=parsefn(fname))==FALSE) s = FIOFNF; strcpy(bp->b_fname, fname); if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */ goto out; if (s == FIOFNF) { /* File not found. */ mlwrite("[New file]"); goto out; } mlwrite("[Reading %s]",fname); nline = 0; while ((s=ffgetline(line, NLINE)) == FIOSUC) { nbytes = strlen(line); if ((lp1=lalloc(nbytes)) == NULL) { s = FIOERR; /* Keep message on the */ break; /* display. */ } lp2 = lback(curbp->b_linep); lp2->l_fp = lp1; lp1->l_fp = curbp->b_linep; lp1->l_bp = lp2; curbp->b_linep->l_bp = lp1; for (i=0; iw_wndp) { if (wp->w_bufp == curbp) { wp->w_linep = lforw(curbp->b_linep); wp->w_dotp = lforw(curbp->b_linep); wp->w_doto = 0; wp->w_markp = curwp->w_dotp; wp->w_marko = 0; wp->w_flag |= WFMODE|WFHARD; } } if (s == FIOERR) /* False if error. */ return (FALSE); return (TRUE); } /* * Take a file name, and from it * fabricate a buffer name. This routine knows * about the syntax of file names on the target system. * I suppose that this information could be put in * a better place than a line of code. */ makename(bname, fname) char bname[]; char fname[]; { register char *cp1; register char *cp2; if (fname[0] == '~') parsefn(fname); cp1 = &fname[0]; while (*cp1 != 0) ++cp1; #if VMS while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']') --cp1; #endif #if CPM while (cp1!=&fname[0] && cp1[-1]!=':') --cp1; #endif #if ST while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\') --cp1; #endif #if V7 while (cp1!=&fname[0] && cp1[-1]!='/') --cp1; #endif cp2 = &bname[0]; while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') *cp2++ = *cp1++; *cp2 = 0; } /* * Ask for a file name, and write the * contents of the current buffer to that file. * Update the remembered file name and clear the * buffer changed flag. This handling of file names * is different from the earlier versions, and * is more compatable with Gosling EMACS than * with ITS EMACS. Bound to "C-X C-W". */ filewrite(f, n) register int f, n; { register int s; char fname[NFILEN]; if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE) return (s); if ((s=writeout(fname)) == TRUE) { strcpy(curbp->b_fname, fname); curbp->b_flag &= ~BFCHG; upmode(); /* Update mode lines. */ } return (s); } /* * Save the contents of the current * buffer in its associatd file. No nothing * if nothing has changed (this may be a bug, not a * feature). Error if there is no remembered file * name for the buffer. Bound to "C-X C-S". May * get called by "C-Z". */ filesave(f, n) register int f, n; { register int s; if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */ return (TRUE); if (curbp->b_fname[0] == 0) { /* Must have a name. */ filename(f,n); /* prompt user for a name */ if (curbp->b_fname[0] == 0) /* still no name */ return (FALSE); } if ((s=writeout(curbp->b_fname)) == TRUE) { curbp->b_flag &= ~BFCHG; upmode(); /* Update mode lines. */ } return (s); } /* * This function performs the details of file * writing. Uses the file management routines in the * "fileio.c" package. The number of lines written is * displayed. Sadly, it looks inside a LINE; provide * a macro for this. Most of the grief is error * checking of some sort. */ writeout(fn) char fn[]; { register int s; register LINE *lp; register int nline; if (fn[0] == '~') /* an alias request */ if ((s=parsefn(fn))==FALSE) return(FALSE); if ((s=ffwopen(fn)) != FIOSUC) /* Open writes message. */ return (FALSE); mlwrite("[Writing: %s]", fn); lp = lforw(curbp->b_linep); /* First line. */ nline = 0; /* Number of lines. */ while (lp != curbp->b_linep) { if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC) break; ++nline; lp = lforw(lp); } if (s == FIOSUC) { /* No write error. */ s = ffclose(); if (s == FIOSUC) { /* No close error. */ if (nline == 1) mlwrite("[Wrote %d line]",nline); else mlwrite("[Wrote %d lines]", nline); } } else /* Ignore close error */ ffclose(); /* if a write error. */ if (s != FIOSUC) /* Some sort of error. */ return (FALSE); return (TRUE); } /* * The command allows the user * to modify the file name associated with * the current buffer. It is like the "f" command * in UNIX "ed". The operation is simple; just zap * the name in the BUFFER structure, and mark the windows * as needing an update. You can type a blank line at the * prompt if you wish. */ filename(f, n) register int f, n; { register int s; char fname[NFILEN]; if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT) return (s); if (fname[0] == '~') /* an alias request */ s=parsefn(fname); if (s == FALSE) strcpy(curbp->b_fname, ""); else strcpy(curbp->b_fname, fname); upmode(); return (TRUE); } /* WRITEREG eXtended command Write defined region to file. Prompt * for filename. Error if any sub-function returns failure. Bound to * CTLX-R. */ writereg(f, n) register int f, n; { register int s; char buf[NLINE]; char fname[NFILEN]; n = 0; f = 0; if ((s=mlreply("Write region: ", fname, NFILEN)) == ABORT || s == FALSE) return(s); if (copyregion(NULL, NULL) != TRUE) return (FALSE); if ((s=ffwopen(fname)) != FIOSUC) return (s); while ((s=kremove(n++)) != EOF) { if (s != '\n' && f < NLINE) buf[f++] = s; else { ffputline(buf, f); f=0; } } if ((s=ffclose()) == FIOERR) return(s); else mlwrite("[Region written to %s]",fname); return(TRUE); } /* FILEINSERT eXtended command insert existing file at point. All of the * necessary updating is done by the usual insert commands. Bound to ^X-I. */ fileinsert(f, n) register int f, n; { char fname[NFILEN]; char line[NLINE]; register int c; register int nline; register int omarko; register LINE *omarkp; nline = 0; if ((f=mlreply("Insert file: ", fname, NFILEN)) == ABORT || f == FALSE) return(f); if (fname[0] == '~') if ((f=parsefn(fname))==FALSE) return(f); if (ffropen(fname) == FIOFNF) { mlwrite("File: %s not found", fname); return (FALSE); } insflag = TRUE; /* save current place in buffer */ if ((omarkp=lback(curwp->w_dotp)) == curbp->b_linep) omarkp = NULL; omarko = curwp->w_doto; mlwrite("[Mark set]"); /* the standard routines take care of update */ while ((f=ffgetline(line, NLINE)) == FIOSUC) { n = 0; ++nline; while ((c=line[n++]) !=NULL) if (linsert(1, c) == FALSE) { insflag = FALSE; return (FALSE); } if (newline(FALSE, 1) == FALSE) { insflag = FALSE; return (FALSE); } } ffclose(); if (f == FIOEOF) { if (nline == 1) mlwrite("[Inserted %d line]",nline); else mlwrite("[Inserted %d lines]", nline); } insflag = FALSE; /* The following code is needed if we want to insert a file * the way GNU does (returning to the point of insertion * when done). The problem is with files inserted when the * current point is at the end or beginning of the buffer. */ if (omarkp == NULL) /* inserted at beginning */ { curwp->w_markp = curwp->w_dotp; curwp->w_marko = curwp->w_doto; gotobob(FALSE,TRUE); curwp->w_doto = omarko; } else /* inserted at end or in the midst */ { curwp->w_markp = omarkp; curwp->w_marko = omarko; swapmark(FALSE,TRUE); forwline(NULL,1); } if (f == FIOERR) return (FALSE); return (TRUE); } parsefn(fname) char fname[]; { register char *ptr; char *index(), *alias(); char template[NFILEN]; if ((ptr=index(fname,'\\'))!=(char *)NULL) { *ptr = '\0'; /* ptr++==file; fname==alias */ if (alias(&template[0],&fname[1])==(char *)NULL) return(FALSE); strcat(template,++ptr); strcpy(fname,template); } else return(FALSE); return(TRUE); }