home *** CD-ROM | disk | FTP | other *** search
- /*
- * File commands.
- */
- #include <sys/types.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include "def.h"
-
- bool load_file ();
- bool readin ();
- void makename ();
- bool writeout ();
- bool parse_f_name ();
- A32 ffseek ();
- A32 file_len();
-
- extern char MSG_rd_file[];
- extern char MSG_trash[];
- extern char MSG_ins_file[];
- extern char MSG_not_fnd[];
- extern char MSG_visit[];
- extern char MSG_view[];
- extern char MSG_buf_ex[];
- extern char MSG_old_buf[];
- extern char MSG_buf_nam[];
- extern char MSG_cnt_cr[];
- extern char MSG_reading[];
- extern char MSG_read_lx[];
- extern char MSG_no_mem_rd[];
- extern char MSG_wr_file[];
- extern char MSG_no_fn[];
- extern char MSG_bk_err[];
- extern char MSG_writing[];
- extern char MSG_wrot_n[];
- extern char MSG_fil_nam[];
- extern char MSG_null[];
- extern char ERR_parse_fn[];
- extern char ERR_addr_neg[];
- extern char ERR_f_size[];
-
- static int ughlyflag = FALSE;
-
- /*
- * 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.
- */
- bool
- fileread ()
- {
- register bool s;
- char fname[NFILEN];
- A32 start, end;
-
- if ((s = ereply (MSG_rd_file, fname, NFILEN, NULL)) != TRUE)
- return (s);
- if (parse_f_name (fname, &start, &end))
- {
- adjustcase (fname);
- return (readin (fname, start, end));
- }
- return (TRUE);
- }
-
- /* insert file into current buffer - use readin, and yank
- */
- bool
- fileinsert ()
- {
- register bool s;
- char bname[NBUFN], fname[NFILEN];
- A32 start, end;
- register char *trash = MSG_trash;
-
- strcpy (bname, curbp->b_bname); /* save current buffer */
- if ((s = _usebuffer (trash)) == 0) /* temp buffer */
- return (s);
- if ((s = ereply (MSG_ins_file, fname, NFILEN, NULL)) != TRUE)
- return (s);
- /* if file name and starting and ending addresses are good */
- if (parse_f_name (fname, &start, &end))
- {
- adjustcase (fname);
- if ((s = readin (fname, start, end)) == 0)
- {
- writ_echo (MSG_not_fnd);
- _usebuffer (bname);
- _killbuffer (trash);
- return (s);
- }
- if ((s = _usebuffer (bname)) == 0)
- {
- _killbuffer (trash);
- return (s);
- }
- if ((s = _yankbuffer (trash)) == 0)
- {
- _killbuffer (trash);
- return (s);
- }
- writ_echo (okmsg);
- }
- else
- {
- _usebuffer (bname);
- _killbuffer (trash);
- return (FALSE);
- }
- if ((s = _killbuffer (trash)) == 0)
- return (s);
- wind_on_dot (curwp);
- return (s);
- }
-
- /*
- * 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.
- *
- * also various hacked versions for auto load, and
- * file-vist with auto window split, and readonly (view-file) (jam)
- */
- bool
- file_visit (f, n, k)
- int f, n, k;
- {
- char fname[NFILEN];
- bool s;
- A32 start, end;
- if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
- return (s);
- if (!parse_f_name (fname, &start, &end))
- return (FALSE);
-
- splitwind ();
- return (load_file (fname, start, end));
- }
-
- /* like filevisit, only read only
- */
- bool
- viewfile ()
- {
- char fname[NFILEN];
- bool s;
- A32 start, end;
-
- if ((s = ereply (MSG_view, fname, NFILEN, NULL)) != TRUE)
- return (s);
- ughlyflag = TRUE;
- if (!parse_f_name (fname, &start, &end))
- return (FALSE);
-
- s = load_file (fname, start, end);
- if (s)
- curbp->b_flag |= BFVIEW;
- ughlyflag = FALSE;
- return (s);
- }
-
- bool
- filevisit ()
- {
- char fname[NFILEN];
- bool s;
- A32 start, end;
-
- if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
- return (s);
- if (!parse_f_name (fname, &start, &end))
- return (FALSE);
-
- return (load_file (fname, start, end));
- }
-
- bool
- load_file (fname, start, end) /* jam */
- char *fname;
- A32 start, end;
- {
- register BUFFER *bp;
- register WINDOW *wp;
- register LINE *lp;
- register int i;
- bool s;
- char bname[NBUFN];
- extern int initial_load; /* jam */
- static int append = 0;
-
- adjustcase (fname);
- for (bp = bheadp; bp != NULL; bp = bp->b_bufp)
- {
- if (strcmp (bp->b_fname, fname) == 0)
- {
- if (ughlyflag == TRUE)
- {
- writ_echo (MSG_buf_ex);
- return (FALSE);
- }
- if (--curbp->b_nwnd == 0)
- {
- curbp->b_type = BTFILE;
- curbp->b_dotp = curwp->w_dotp;
- curbp->b_doto = curwp->w_doto;
- curbp->b_unit_offset = curwp->w_unit_offset;
- 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_unit_offset = bp->b_unit_offset;
- 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_unit_offset = wp->w_unit_offset;
- 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;
- if (kbdmop == NULL)
- {
- writ_echo (MSG_old_buf);
- }
- return (TRUE);
- }
- }
-
- makename (bname, fname); /* New buffer name. */
- while ((bp = bfind (bname, FALSE)) != NULL)
- {
- if (initial_load) /* patch old name */
- {
- funky_name (bname, append++);
- bp = NULL;
- break;
- }
- s = ereply (MSG_buf_nam, bname, NBUFN, NULL);
- if (s == ABORT) /* ^G to just quit */
- return (s);
- if (strcmp (bp->b_bname, bname) == 0 || s == FALSE)
- {
- /* CR to clobber it */
- makename (bname, fname);
- break;
- }
- }
- if (bp == NULL && (bp = bfind (bname, TRUE)) == NULL)
- {
- err_echo (MSG_cnt_cr);
- return (FALSE);
- }
- if (--curbp->b_nwnd == 0)
- {
- /* Undisplay. */
- curbp->b_type = BTFILE;
- curbp->b_dotp = curwp->w_dotp;
- curbp->b_doto = curwp->w_doto;
- curbp->b_unit_offset = curwp->w_unit_offset;
- 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, start, end)); /* Read it in. */
- }
-
- /*
- * 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 "beav file"). 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). Return a standard status. Print a summary
- * (lines read, error message) out as well.
- */
- bool
- readin (fname, start, end)
- char fname[];
- A32 start, end;
- {
- register LINE *lp1;
- register LINE *lp2;
- register WINDOW *wp;
- register BUFFER *bp;
- register bool s, m;
- long byte_cnt;
- LPOS req_chars;
- char buf[NCOL], buf1[NCOL];
- A32 temp;
-
- m = TRUE;
- byte_cnt = 0;
- bp = curbp; /* Cheap. */
- if ((s = bclear (bp)) != TRUE) /* Might be old. */
- return (s);
- #if BACKUP
- bp->b_flag &= ~(BFCHG | BFBAK); /* No change, backup. */
- #else
- bp->b_flag &= ~BFCHG; /* No change. */
- #endif
- if ((start == 0L) && (end == MAXPOS))
- strcpy (bp->b_fname, fname);
- else
- strcpy (bp->b_fname, MSG_null);
- bp->b_file_size = 0;
- bp->b_type = BTFILE;
- if ((s = ffropen (fname)) == FIOERR || s == FIOFNF) /* jam */
- goto out;
- bp->b_file_size = file_len (); /* get the file lenth */
- sprintf (buf, MSG_reading, fname); /* jam */
- writ_echo (buf);
- temp = ffseek (start);
- if (temp != start)
- {
- sprintf (buf1, ERR_f_size, R_POS_FMT (curwp));
- sprintf (buf, buf1, temp);
- writ_echo (buf);
- return (FALSE);
- }
- /* only read the requested number of characters */
- if ((end - start) > NLINE)
- req_chars = NLINE;
- else
- req_chars = (int) (end - start);
-
- if ((lp1 = lalloc (req_chars)) == NULL)
- {
- bp->b_flag |= BFVIEW; /* if no memory set to read only mode */
-
- m = FALSE; /* flag memory allocation error */
- }
- else
- {
- while ((s = ffgetline (lp1->l_text, lp1->l_size, &lp1->l_used)) == FIOSUC)
- {
- /* this code breaks rules for knowing how lines * are stored and linked
- together, oh well */
- 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;
- lp1->l_file_offset = byte_cnt; /* file offset from begining */
- byte_cnt += (long) lp1->l_used; /* number of bytes read in */
- start += (long) lp1->l_used;
- if (end <= start)
- break;
- /* stop reading after the requested number of characters */
- if (end < start + req_chars)
- {
- req_chars = end - start;
- }
- if ((lp1 = lalloc (req_chars)) == NULL)
- {
- bp->b_flag |= BFVIEW; /* if no memory set to read only mode */
-
- m = FALSE; /* flag memory allocation error */
- break;
- }
- if ((byte_cnt & 0x7fff) == 0)
- {
- sprintf (buf1, MSG_read_lx, R_POS_FMT (curwp));
- sprintf (buf, buf1, (ulong) byte_cnt);
- writ_echo (buf);
- /* check if we should quit */
- if (ttkeyready ())
- {
- wind_on_dot_all ();
- if (ttgetc () == CTL_G) /* was it an abort key? */
- {
- s = FIOERR;
- break;
- }
- }
- }
- }
- }
- ffclose (); /* Ignore errors. */
- if (s == FIOEOF && kbdmop == NULL)
- {
- /* Don't zap an error. */
- sprintf (buf1, MSG_read_lx, R_POS_FMT (curwp));
- sprintf (buf, buf1, byte_cnt);
- writ_echo (buf);
- }
- if (m == FALSE && kbdmop == NULL)
- {
- /* Don't zap an error. */
- sprintf (buf, MSG_no_mem_rd);
- err_echo (buf);
- }
-
- #if BACKUP
- curbp->b_flag |= BFBAK; /* Need a backup. */
- #endif
- out:
- for (wp = wheadp; wp != NULL; wp = wp->w_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_unit_offset = 0;
- wp->w_markp = NULL;
- wp->w_marko = 0;
- wp->w_flag |= WFMODE | WFHARD;
- }
- }
- /* so tell yank-buffer about it */
- if ((blistp->b_nwnd != 0) &&/* update buffer display */
- (blistp->b_type == BTLIST))
- listbuffers ();
- if (s == FIOERR || s == FIOFNF) /* 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.
- * BDC1 left scan delimiter.
- * BDC2 optional second left scan delimiter.
- * BDC3 optional right scan delimiter.
- */
- void
- makename (bname, fname)
- char bname[];
- char fname[];
- {
- register char *cp1;
- register char *cp2;
-
- cp1 = &fname[0];
- while (*cp1 != 0)
- ++cp1;
- #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.
- */
- bool
- filewrite ()
- {
- register WINDOW *wp;
- register bool s;
- char fname[NFILEN];
- A32 start, end;
-
- if ((s = ereply (MSG_wr_file, fname, NFILEN, NULL)) != TRUE)
- return (s);
- if (!parse_f_name (fname, &start, &end))
- return (FALSE);
-
- adjustcase (fname);
- if ((s = writeout (fname, start, end, S_IREAD | S_IWRITE)) == TRUE)
- {
- strcpy (curbp->b_fname, fname);
- curbp->b_flag &= ~BFCHG;
- wp = wheadp; /* Update mode lines. */
- while (wp != NULL)
- {
- if (wp->w_bufp == curbp)
- wp->w_flag |= WFMODE;
- wp = wp->w_wndp;
- }
- }
-
- #if BACKUP
- curbp->b_flag &= ~BFBAK; /* No backup. */
- #endif
- return (s);
- }
-
- /*
- * Save the contents of the current buffer back 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.
- */
- bool
- filesave ()
- {
- register WINDOW *wp;
- register bool s;
- struct stat st;
-
- if ((curbp->b_flag & BFCHG) == 0) /* Return, no changes. */
- return (TRUE);
- if (curbp->b_fname[0] == 0) /* Must have a name. */
- {
- if (!(curbp->b_type == BTSAVE)) /* yanked buffer */
- {
- writ_echo (MSG_no_fn);
- }
- return (FALSE);
- }
- st.st_mode = S_IREAD | S_IWRITE; /* set default */
- #if BACKUP
- if ((curbp->b_flag & BFBAK) != 0)
- {
- /* get the mode of the file */
- stat (curbp->b_fname, &st);
-
- s = fbackupfile (curbp->b_fname);
- if (s == ABORT) /* Hard error. */
- return (s);
- if (s == FALSE /* Softer error. */
- && (s = eyesno (MSG_bk_err)) != TRUE)
- return (s);
- }
-
- #endif
- if ((s = writeout (curbp->b_fname, 0L, MAXPOS, st.st_mode)) == TRUE)
- {
- curbp->b_flag &= ~BFCHG;/* No change. */
- curbp->b_flag &= ~BFBAD;/* if it was trashed, forget it now */
- wp = wheadp; /* Update mode lines. */
- while (wp != NULL)
- {
- if (wp->w_bufp == curbp)
- wp->w_flag |= WFMODE;
- wp = wp->w_wndp;
- }
- }
-
- #if BACKUP
- curbp->b_flag &= ~BFBAK; /* No backup. */
- #endif
- 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.
- * The file permissions are set as requested.
- */
- bool
- writeout (fn, start, end, mode)
- char *fn;
- A32 start, end;
- int mode;
- {
- register int s, num_chars;
- register LINE *lp;
- register long nbytes;
- char buf[NCOL], buf1[NCOL];
- A32 temp;
-
- if ((s = ffwopen (fn, mode)) != FIOSUC) /* Open writes message. */
- return (FALSE);
- temp = ffseek (start);
- if (temp != start)
- {
- sprintf (buf1, ERR_f_size, R_POS_FMT (curwp));
- sprintf (buf, buf1, temp);
- writ_echo (buf);
- return (FALSE);
- }
- sprintf (buf, MSG_writing, fn); /* jam */
- writ_echo (buf);
-
- /* insure that the help screen reflects the latest bindings */
- if (curbp == blistp)
- wallchart (0, 0, 0);
-
- lp = lforw (curbp->b_linep);/* First line. */
- nbytes = 0; /* Number of bytes. */
- temp = end - start; /* number of bytes to write */
- while (lp != curbp->b_linep)
- {
- if (curbp == blistp)
- {
- /* special list buffer */
- num_chars = HENDCOL;/* limit line length */
- lp->l_text[num_chars - 1] = '\n';
- }
- else
- {
- /* standard buffer */
- if (nbytes + (long) llength (lp) > temp)
- num_chars = (int) (temp - nbytes);
- else
- num_chars = llength (lp);
- }
- if ((s = ffputline (&lp->l_text[0], num_chars)) != FIOSUC)
- break;
- nbytes += num_chars;
- if (temp <= nbytes)
- break;
- lp = lforw (lp);
-
- if ((nbytes & 0x7fff) == 0)
- {
- sprintf (buf1, MSG_wrot_n, R_POS_FMT (curwp));
- sprintf (buf, buf1, (ulong) nbytes);
- writ_echo (buf);
- /* check if we should quit */
- if (ttkeyready ())
- {
- wind_on_dot_all ();
- if (ttgetc () == CTL_G) /* was it an abort key? */
- {
- s = FIOERR;
- break;
- }
- }
- }
- }
- if (s == FIOSUC)
- {
- /* No write error. */
- s = ffclose ();
- if (s == FIOSUC && kbdmop == NULL)
- {
- sprintf (buf1, MSG_wrot_n, R_POS_FMT (curwp));
- sprintf (buf, buf1, (long) nbytes);
- writ_echo (buf);
- }
- }
- else /* Ignore close error */
- ffclose (); /* if a write error. */
- curbp->b_file_size = nbytes;/* update file size */
- if ((blistp->b_nwnd != 0) &&/* update buffer display */
- (blistp->b_type == BTLIST))
- listbuffers ();
- 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.
- */
- bool
- filename ()
- {
- register WINDOW *wp;
- register bool s;
- char fname[NFILEN];
- A32 start, end;
-
- if ((s = ereply (MSG_fil_nam, fname, NFILEN, NULL)) == ABORT)
- return (s);
- if (!parse_f_name (fname, &start, &end))
- return (FALSE);
-
- adjustcase (fname);
- curbp->b_flag |= BFCHG; /* jam - on name change, set modify */
- BUF_START (curwp) = start;
- l_fix_up (curbp->b_linep->l_fp); /* adjust file offsets from first line */
- strcpy (curbp->b_fname, fname); /* Fix name. */
- wp = wheadp; /* Update mode lines. */
- while (wp != NULL)
- {
- if (wp->w_bufp == curbp)
- wp->w_flag |= WFMODE;
- wp = wp->w_wndp;
- }
- #if BACKUP
- curbp->b_flag &= ~BFBAK; /* No backup. */
- #endif
- return (TRUE);
- }
-
- /*
- * Get the length parameters that were entered with the file name.
- * There can be the file name only.
- * There can be a file name and a starting position.
- * There can be a name a starting position and an ending position.
- * There can be a name a starting position and a length.
- *
- * input:
- * fn pointer to file name string to parse.
- *
- * output:
- * fn pointer to null terminated file name.
- * start pointer to the starting point in file (default = 0)
- * end pointer to the end point in file (default = -1)
- * return FALSE if file name or addresses are bad.
- */
- bool
- parse_f_name (fn, start, end)
- char *fn;
- A32 *start, *end;
- {
- char buf[NFILEN], buf1[NCOL], fmt[NCOL];
- int i_cnt;
-
- /* build up format string according to the current screen format */
- sprintf (fmt, "%s %s %s", "%s", R_POS_FMT (curwp), R_POS_FMT (curwp));
-
- *start = 0L;
- *end = MAXPOS;
- sscanf (fn, fmt, buf, start, end);
-
- if (*end != MAXPOS)
- {
- for (i_cnt = strlen (fn) - 1; i_cnt >= 0; i_cnt--)
- {
- if (fn[i_cnt] == '+')
- {
- *end += *start;
- break;
- }
- }
- }
- /* start should preceed end */
- if (*start > *end)
- {
- sprintf (buf1, ERR_parse_fn, R_POS_FMT (curwp), R_POS_FMT (curwp));
- sprintf (buf, buf1, *start, *end);
- writ_echo (buf);
- return (FALSE);
- }
-
- /* error if addresses are negative */
- if ((*start < 0) || (*end < 0))
- {
- writ_echo (ERR_addr_neg);
- return (FALSE);
- }
-
- /* deposit null terminated file name */
- strcpy (fn, buf);
- return (TRUE);
- }
-