home *** CD-ROM | disk | FTP | other *** search
- /*
- * File commands.
- */
- #include "no_backup.h"
- #include "makebackup.h"
-
- #include "def.h"
- #include "line.h"
- #include "buffer.h"
- #include "window.h"
-
- #ifdef ANSI
- #include <string.h>
- #include <stdlib.h>
- #endif
-
- struct buffer *findbuffer();
- VOID
- makename(), upmodes();
- static char *itos();
- #ifndef NO_PROTO
- static char *itos
- PROTO((char *bufp, unsigned int num));
- #endif
-
- /*
- * insert a file into the current buffer. Real easy - just call the
- * insertfile routine with the file name.
- */
- /* ARGSUSED */
- fileinsert(f, n)
- {
- register int s;
- char fname[NFILEN];
-
- if ((s = ereply("Insert file: ", fname, NFILEN)) != TRUE)
- return (s);
- return insertfile(adjustname(fname), (char *) NULL);
- /* don't set buffer name */
- }
-
- /*
- * Select a file for editing. Look around to see if you can find the fine 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.
- */
- /* ARGSUSED */
- filevisit(f, n)
- {
- register struct buffer *bp;
- int s;
- char fname[NFILEN];
- char *adjf;
-
- if ((s = ereply("Find file: ", fname, NFILEN)) != TRUE)
- return s;
- adjf = adjustname(fname);
- if ((bp = findbuffer(adjf)) == NULL)
- return FALSE;
- curbp = bp;
- if (showbuffer(bp, curwp, WFHARD) != TRUE)
- return FALSE;
- if (bp->b_fname[0] == 0)
- return readin(adjf); /* Read it in. */
- return TRUE;
- }
- /*
- * Pop to a file in the other window. Same as last function, just popbuf
- * instead of showbuffer.
- */
- /* ARGSUSED */
- poptofile(f, n)
- {
- register struct buffer *bp;
- register struct window *wp;
- int s;
- char fname[NFILEN];
- char *adjf;
-
- if ((s = ereply("Find file in other window: ", fname, NFILEN)) != TRUE)
- return s;
- adjf = adjustname(fname);
- if ((bp = findbuffer(adjf)) == NULL)
- return FALSE;
- if ((wp = popbuf(bp)) == NULL)
- return FALSE;
- curbp = bp;
- curwp = wp;
- if (bp->b_fname[0] == 0)
- return readin(adjf); /* Read it in. */
- return TRUE;
- }
-
- /*
- * reads the file being edited back into the buffer, throwing away changes.
- */
- revertbuffer(f, n)
- {
- int s;
- char prompt[NLINE];
-
- if (curbp->b_fname[0] == '\0') {
- ewprintf("Buffer does not seem to be associated with any file");
- return TRUE;
- }
- strcpy(prompt, "Revert buffer from file ");
- strcat(prompt, curbp->b_fname);
- if ((s = eyesno(prompt)) != TRUE)
- return s;
- curbp->b_flag &= ~BFCHG;/* Don't ask, just chung it */
- readin(curbp->b_fname);
- }
-
- /*
- * given a file name, either find the buffer it uses, or create a new empty
- * buffer to put it in.
- */
- struct buffer *
- findbuffer(fname)
- char *fname;
- {
- register struct buffer *bp;
- char bname[NBUFN], *cp;
- unsigned count = 0;
-
- for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
- if (fncmp(bp->b_fname, fname) == 0)
- return bp;
- }
- makename(bname, fname); /* New buffer name. */
- cp = bname + strlen(bname);
- while (bfind(bname, FALSE) != NULL) {
- *cp = '<'; /* add "<count>" to then name */
- (VOID) strcpy(itos(cp, count += 1) + 1, ">");
- }
- return bfind(bname, TRUE);
- }
-
- /*
- * Put the decimal representation of num into a buffer. Hacked to be faster,
- * smaller, and less general.
- */
- static char *
- itos(bufp, num)
- char *bufp;
- unsigned num;
- {
- if (num >= 10) {
- bufp = itos(bufp, num / 10);
- num %= 10;
- }
- *++bufp = '0' + num;
- return bufp;
- }
-
- /*
- * Read the file "fname" into the current buffer. Make all of the text in the
- * buffer go away, after checking for unsaved changes. This is called by the
- * "read" command, the "visit" command, and the mainline (for "uemacs file").
- */
- readin(fname)
- char *fname;
- {
- register int status;
- register struct window *wp;
-
- if (bclear(curbp) != TRUE) /* Might be old. */
- return TRUE;
- status = insertfile(fname, fname);
- #ifdef FOOB
- curbp->b_foob = getfoob(fname);
- #endif
- curbp->b_flag &= ~BFCHG;/* No change. */
- for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
- if (wp->w_bufp == curbp) {
- wp->w_dotp = wp->w_linep = lforw(curbp->b_linep);
- wp->w_doto = 0;
- wp->w_markp = NULL;
- wp->w_marko = 0;
- }
- }
- return status;
- }
- /*
- * insert a file in the current buffer, after dot. Set mark at the end of the
- * text inserted, point at the beginning. Return a standard status. Print a
- * summary (lines read, error message) out as well. If the BACKUP conditional
- * is set, then this routine also does the read end of backup processing. The
- * BFBAK flag, if set in a buffer, says that a backup should be taken. It is
- * set when a file is read in, but not on a new file (you don't need to make
- * a backup copy of nothing).
- */
- insertfile(fname, newname)
- char fname[], newname[];
- {
- register struct line *lp1;
- register struct line *lp2;
- register struct window *wp;
- int nbytes;
- struct line *olp; /* Line we started at */
- int opos; /* and offset into it */
- int s, nline;
- struct buffer *bp;
- char line[NLINE];
-
- bp = curbp; /* Cheap. */
- if (newname != (char *) NULL)
- (VOID) strcpy(bp->b_fname, newname);
- if ((s = ffropen(fname)) == FIOERR) /* Hard file open. */
- goto out;
- if (s == FIOFNF) { /* File not found. */
- if (newname != NULL)
- ewprintf("(New file)");
- else
- ewprintf("(File not found)");
- goto out;
- }
- opos = curwp->w_doto;
- /* Open a new line, at point, and start inserting after it */
- (VOID) lnewline();
- olp = lback(curwp->w_dotp);
- if (olp == curbp->b_linep) {
- /* if at end of buffer, create a line to insert before */
- (VOID) lnewline();
- curwp->w_dotp = lback(curwp->w_dotp);
- }
- nline = 0; /* Don't count fake line at end */
- while ((s = ffgetline(line, NLINE, &nbytes)) != FIOERR) {
- switch (s) {
- case FIOSUC:
- ++nline;
- /* and continue */
- case FIOEOF: /* the last line of the file */
- if ((lp1 = lalloc(nbytes)) == NULL) {
- s = FIOERR; /* Keep message on the */
- goto endoffile; /* display. */
- }
- bcopy(line, <ext(lp1)[0], nbytes);
- lineread: lp2 = lback(curwp->w_dotp);
- lp2->l_fp = lp1;
- lp1->l_fp = curwp->w_dotp;
- lp1->l_bp = lp2;
- curwp->w_dotp->l_bp = lp1;
- if (s == FIOEOF)
- goto endoffile;
- break;
- case FIOLONG:{ /* a line to long to fit in our buffer */
- char *cp;
- char *cp2 = 0; /* For lint */
- int i;
-
- nbytes = 0;
- for (;;) {
- if ((cp = (char *) malloc((unsigned) (nbytes + NLINE))) == NULL) {
- ewprintf("Could not allocate %d bytes",
- nbytes + NLINE);
- s = FIOERR;
- if (nbytes)
- free(cp2);
- goto endoffile;
- }
- if (nbytes) {
- bcopy(cp2, cp, nbytes);
- free(cp2);
- }
- bcopy(line, cp + nbytes, NLINE);
- nbytes += NLINE;
- switch (s = ffgetline(line, NLINE, &i)) {
- case FIOERR:
- free(cp);
- goto endoffile;
- case FIOLONG:
- cp2 = cp;
- break;
- case FIOEOF:
- case FIOSUC:
- if ((lp1 = lalloc(nbytes + i)) == NULL) {
- s = FIOERR;
- free(cp);
- goto endoffile;
- }
- bcopy(cp, <ext(lp1)[0], nbytes);
- bcopy(line, <ext(lp1)[nbytes], i);
- goto lineread;
- }
- }
- }
- default:
- ewprintf("Unknown code %d reading file", s);
- s = FIOERR;
- break;
- }
- }
- endoffile:
- (VOID) ffclose(); /* Ignore errors. */
- if (s == FIOEOF) { /* Don't zap an error. */
- if (nline == 1)
- ewprintf("(Read 1 line)");
- else
- ewprintf("(Read %d lines)", nline);
- }
- /* Set mark at the end of the text */
- curwp->w_dotp = curwp->w_markp = lback(curwp->w_dotp);
- curwp->w_marko = llength(curwp->w_markp);
- (VOID) ldelnewline();
- curwp->w_dotp = olp;
- curwp->w_doto = opos;
- if (olp == curbp->b_linep)
- curwp->w_dotp = lforw(olp);
- #ifndef NO_BACKUP
- if (newname != NULL)
- bp->b_flag |= BFCHG | BFBAK; /* Need a backup. */
- else
- bp->b_flag |= BFCHG;
- #else
- bp->b_flag |= BFCHG;
- #endif
- /*
- * if the insert was at the end of buffer, set lp1 to the end of
- * buffer line, and lp2 to the beginning of the newly inserted text.
- * (Otherwise lp2 is set to NULL.) This is used below to set
- * pointers in other windows correctly if they are also at the end of
- * buffer.
- */
- lp1 = bp->b_linep;
- if (curwp->w_markp == lp1) {
- lp2 = curwp->w_dotp;
- } else {
- (VOID) ldelnewline(); /* delete extranious newline */
- out: lp2 = NULL;
- }
- for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
- if (wp->w_bufp == curbp) {
- wp->w_flag |= WFMODE | WFEDIT;
- if (wp != curwp && lp2 != NULL) {
- if (wp->w_dotp == lp1)
- wp->w_dotp = lp2;
- if (wp->w_markp == lp1)
- wp->w_markp = lp2;
- if (wp->w_linep == lp1)
- wp->w_linep = lp2;
- }
- }
- }
- return s != FIOERR; /* False if error. */
- }
-
- /*
- * Take a file name, and from it fabricate a buffer name. This routine knows
- * about the syntax of file names on the target system. BDC1 left
- * scan delimiter. BDC2 optional second left scan delimiter. BDC3
- * ptional right scan delimiter.
- */
- VOID
- makename(bname, fname)
- char bname[];
- char fname[];
- {
- register char *cp1;
- register char *cp2;
-
- cp1 = &fname[0];
- while (*cp1 != 0)
- ++cp1;
- --cp1; /* insure at least 1 character ! */
- #ifdef BDC2
- while (cp1 != &fname[0] && cp1[-1] != BDC1 && cp1[-1] != BDC2)
- --cp1;
- #else
- while (cp1 != &fname[0] && cp1[-1] != BDC1)
- --cp1;
- #endif
- cp2 = &bname[0];
- #ifdef BDC3
- while (cp2 != &bname[NBUFN - 1] && *cp1 != 0 && *cp1 != BDC3)
- *cp2++ = *cp1++;
- #else
- while (cp2 != &bname[NBUFN - 1] && *cp1 != 0)
- *cp2++ = *cp1++;
- #endif
- *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.
- */
- /* ARGSUSED */
- filewrite(f, n)
- {
- register int s, count = 0;
- char fname[NFILEN], bname[NBUFN];
- register char *adjfname, *cp;
-
- if ((s = ereply("Write file: ", fname, NFILEN)) != TRUE)
- return (s);
- adjfname = adjustname(fname);
- if ((s = writeout(curbp, adjfname)) == TRUE) {
- (VOID) strcpy(curbp->b_fname, adjfname);
- makename(bname, fname);
- cp = bname + strlen(bname);
- while (bfind(bname, FALSE) != NULL) {
- *cp = '<';
- strcpy(itos(cp, count += 1) + 1, ">");
- }
- if ((cp = (char *) malloc(strlen(bname) + 1)) == NULL)
- ewprintf("Couldn't get %d bytes", strlen(bname) + 1);
- else {
- free(curbp->b_bname);
- strcpy(cp, bname);
- curbp->b_bname = cp;
- }
-
- #ifndef NO_BACKUP
- curbp->b_flag &= ~(BFBAK | BFCHG);
- #else
- curbp->b_flag &= ~BFCHG;
- #endif
- upmodes(curbp);
- }
- return s;
- }
-
- /*
- * Save the contents of the current buffer back into its associated file.
- */
- #ifndef NO_BACKUP
- static int makebackup = MAKEBACKUP;
- #endif
-
- /* ARGSUSED */
- filesave(f, n)
- {
- return buffsave(curbp);
- }
-
- /*
- * Save the contents of the buffer argument into its associated file. Do
- * nothing if there have been no changes (is this a bug, or a feature). Error
- * if there is no remembered file name. If this is the first write since the
- * read or visit, then a backup copy of the file is made. Allow user to
- * select whether or not to make backup files by looking at the value of
- * makebackup.
- */
- buffsave(bp)
- struct buffer *bp;
- {
- register int s;
-
- if ((bp->b_flag & BFCHG) == 0) { /* Return, no changes. */
- ewprintf("(No changes need to be saved)");
- return TRUE;
- }
- if (bp->b_fname[0] == '\0') { /* Must have a name. */
- ewprintf("No file name");
- return (FALSE);
- }
- #ifndef NO_BACKUP
- if (makebackup && (bp->b_flag & BFBAK)) {
- s = fbackupfile(bp->b_fname);
- if (s == ABORT) /* Hard error. */
- return FALSE;
- if (s == FALSE /* Softer error. */
- && (s = eyesno("Backup error, save anyway")) != TRUE)
- return s;
- }
- #endif
- if ((s = writeout(bp, bp->b_fname)) == TRUE) {
- #ifndef NO_BACKUP
- bp->b_flag &= ~(BFCHG | BFBAK);
- #else
- bp->b_flag &= ~BFCHG;
- #endif
- upmodes(bp);
- }
- return s;
- }
-
- #ifndef NO_BACKUP
- /*
- * Since we don't have variables (we probably should) this is a command
- * processor for changing the value of the make backup flag. If no argument
- * is given, sets makebackup to true, so backups are made. If an argument is
- * given, no backup files are made when saving a new version of a file. Only
- * used when BACKUP is #defined.
- */
- /* ARGSUSED */
- makebkfile(f, n)
- {
- if (f & FFARG)
- makebackup = n > 0;
- else
- makebackup = !makebackup;
- ewprintf("Backup files %sabled", makebackup ? "en" : "dis");
- return TRUE;
- }
- #endif
-
- /*
- * This function performs the details of file writing; writing the file in
- * buffer bp to file fn. Uses the file management routines in the "fileio.c"
- * package. Most of the grief is checking of some sort.
- */
- writeout(bp, fn)
- register struct buffer *bp;
- char *fn;
- {
- register int s;
-
- if ((s = ffwopen(fn)) != FIOSUC) /* Open writes message. */
- return (FALSE);
- s = ffputbuf(bp);
- if (s == FIOSUC) { /* No write error. */
- s = ffclose();
- if (s == FIOSUC)
- ewprintf("Wrote %s", fn);
- } else /* Ignore close error */
- (VOID) ffclose(); /* if a write error. */
- #ifdef FOOB
- putfoob(fn, bp->b_foob);
- #endif
- return s == FIOSUC;
- }
-
- /*
- * Tag all windows for bp (all windows if bp NULL) as needing their mode line
- * updated.
- */
- VOID
- upmodes(bp)
- register struct buffer *bp;
- {
- register struct window *wp;
-
- for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
- if (bp == NULL || wp->w_bufp == bp)
- wp->w_flag |= WFMODE;
- }
-