Logo Search packages:      
Sourcecode: beav version File versions  Download package

file.c

/*
*  File commands.
*/
#include    <sys/types.h>
#include    <fcntl.h>
#include    <sys/stat.h>
#include        "def.h"

char load_file ();
char 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.
*/
char
fileread ()
{
    register char 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
*/
char
fileinsert ()
{
    register char 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)
*/
char
file_visit (f, n, k)
    int f, n, k;
{
    char fname[NFILEN];
    char 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
*/
char
viewfile ()
{
    char fname[NFILEN];
    char 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);
}

char
filevisit ()
{
    char fname[NFILEN];
    char 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));
}

char
load_file (fname, start, end) /* jam */
    char *fname;
    A32 start, end;
{
    register BUFFER *bp;
    register WINDOW *wp;
    register LINE *lp;
    register int i;
    char 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.
*/
char
readin (fname, start, end)
    char fname[];
    A32 start, end;
{
    register LINE *lp1;
    register LINE *lp2;
    register WINDOW *wp;
    register BUFFER *bp;
    register char 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.
*/
char
filewrite ()
{
    register WINDOW *wp;
    register char 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.
*/
char
filesave ()
{
    register WINDOW *wp;
    register char 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;
    ushort 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.
*/
char
filename ()
{
    register WINDOW *wp;
    register char 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);
}

Generated by  Doxygen 1.6.0   Back to index