home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / beav1402.zip / file.c < prev    next >
Text File  |  1993-04-16  |  20KB  |  792 lines

  1. /*
  2. *  File commands.
  3. */
  4. #include    <sys/types.h>
  5. #include    <fcntl.h>
  6. #include    <sys/stat.h>
  7. #include        "def.h"
  8.  
  9. char load_file ();
  10. char readin ();
  11. void makename ();
  12. bool writeout ();
  13. bool parse_f_name ();
  14. A32 ffseek ();
  15. A32 file_len ();
  16.  
  17. extern char MSG_rd_file[];
  18. extern char MSG_trash[];
  19. extern char MSG_ins_file[];
  20. extern char MSG_not_fnd[];
  21. extern char MSG_visit[];
  22. extern char MSG_view[];
  23. extern char MSG_buf_ex[];
  24. extern char MSG_old_buf[];
  25. extern char MSG_buf_nam[];
  26. extern char MSG_cnt_cr[];
  27. extern char MSG_reading[];
  28. extern char MSG_read_lx[];
  29. extern char MSG_no_mem_rd[];
  30. extern char MSG_wr_file[];
  31. extern char MSG_no_fn[];
  32. extern char MSG_bk_err[];
  33. extern char MSG_writing[];
  34. extern char MSG_wrot_n[];
  35. extern char MSG_fil_nam[];
  36. extern char MSG_null[];
  37. extern char ERR_parse_fn[];
  38. extern char ERR_addr_neg[];
  39. extern char ERR_f_size[];
  40.  
  41. static int ughlyflag = FALSE;
  42.  
  43. /*
  44. * Read a file into the current
  45. * buffer. This is really easy; all you do it
  46. * find the name of the file, and call the standard
  47. * "read a file into the current buffer" code.
  48. */
  49. char
  50. fileread ()
  51. {
  52.     register char s;
  53.     char fname[NFILEN];
  54.     A32 start, end;
  55.  
  56.     if ((s = ereply (MSG_rd_file, fname, NFILEN, NULL)) != TRUE)
  57.     return (s);
  58.     if (parse_f_name (fname, &start, &end))
  59.     {
  60.     adjustcase (fname);
  61.     return (readin (fname, start, end));
  62.     }
  63.     return (TRUE);
  64. }
  65.  
  66. /* insert file into current buffer - use readin, and yank
  67. */
  68. char
  69. fileinsert ()
  70. {
  71.     register char s;
  72.     char bname[NBUFN], fname[NFILEN];
  73.     A32 start, end;
  74.     register char *trash = MSG_trash;
  75.  
  76.     strcpy (bname, curbp->b_bname);    /* save current buffer */
  77.     if ((s = _usebuffer (trash)) == 0)    /* temp buffer */
  78.     return (s);
  79.     if ((s = ereply (MSG_ins_file, fname, NFILEN, NULL)) != TRUE)
  80.     return (s);
  81.     /* if file name and starting and ending addresses are good */
  82.     if (parse_f_name (fname, &start, &end))
  83.     {
  84.     adjustcase (fname);
  85.     if ((s = readin (fname, start, end)) == 0)
  86.     {
  87.         writ_echo (MSG_not_fnd);
  88.         _usebuffer (bname);
  89.         _killbuffer (trash);
  90.         return (s);
  91.     }
  92.     if ((s = _usebuffer (bname)) == 0)
  93.     {
  94.         _killbuffer (trash);
  95.         return (s);
  96.     }
  97.     if ((s = _yankbuffer (trash)) == 0)
  98.     {
  99.         _killbuffer (trash);
  100.         return (s);
  101.     }
  102.     writ_echo (okmsg);
  103.     }
  104.     else
  105.     {
  106.     _usebuffer (bname);
  107.     _killbuffer (trash);
  108.     return (FALSE);
  109.     }
  110.     if ((s = _killbuffer (trash)) == 0)
  111.     return (s);
  112.     wind_on_dot (curwp);
  113.     return (s);
  114. }
  115.  
  116. /*
  117. * Select a file for editing.
  118. * Look around to see if you can find the
  119. * fine in another buffer; if you can find it
  120. * just switch to the buffer. If you cannot find
  121. * the file, create a new buffer, read in the
  122. * text, and switch to the new buffer.
  123. *
  124. * also various hacked versions for auto load, and
  125. * file-vist with auto window split, and readonly (view-file) (jam)
  126. */
  127. char
  128. file_visit (f, n, k)
  129.     int f, n, k;
  130. {
  131.     char fname[NFILEN];
  132.     char s;
  133.     A32 start, end;
  134.     if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
  135.     return (s);
  136.     if (!parse_f_name (fname, &start, &end))
  137.     return (FALSE);
  138.  
  139.     splitwind ();
  140.     return (load_file (fname, start, end));
  141. }
  142.  
  143. /* like filevisit, only read only
  144. */
  145. char
  146. viewfile ()
  147. {
  148.     char fname[NFILEN];
  149.     char s;
  150.     A32 start, end;
  151.  
  152.     if ((s = ereply (MSG_view, fname, NFILEN, NULL)) != TRUE)
  153.     return (s);
  154.     ughlyflag = TRUE;
  155.     if (!parse_f_name (fname, &start, &end))
  156.     return (FALSE);
  157.  
  158.     s = load_file (fname, start, end);
  159.     if (s)
  160.     curbp->b_flag |= BFVIEW;
  161.     ughlyflag = FALSE;
  162.     return (s);
  163. }
  164.  
  165. char
  166. filevisit ()
  167. {
  168.     char fname[NFILEN];
  169.     char s;
  170.     A32 start, end;
  171.  
  172.     if ((s = ereply (MSG_visit, fname, NFILEN, NULL)) != TRUE)
  173.     return (s);
  174.     if (!parse_f_name (fname, &start, &end))
  175.     return (FALSE);
  176.  
  177.     return (load_file (fname, start, end));
  178. }
  179.  
  180. char
  181. load_file (fname, start, end)    /* jam */
  182.     char *fname;
  183.     A32 start, end;
  184. {
  185.     register BUFFER *bp;
  186.     register WINDOW *wp;
  187.     register LINE *lp;
  188.     register int i;
  189.     char s;
  190.     char bname[NBUFN];
  191.     extern int initial_load;    /* jam */
  192.     static int append = 0;
  193.  
  194.     adjustcase (fname);
  195.     for (bp = bheadp; bp != NULL; bp = bp->b_bufp)
  196.     {
  197.     if (strcmp (bp->b_fname, fname) == 0)
  198.     {
  199.         if (ughlyflag == TRUE)
  200.         {
  201.         writ_echo (MSG_buf_ex);
  202.         return (FALSE);
  203.         }
  204.         if (--curbp->b_nwnd == 0)
  205.         {
  206.         curbp->b_type = BTFILE;
  207.         curbp->b_dotp = curwp->w_dotp;
  208.         curbp->b_doto = curwp->w_doto;
  209.         curbp->b_unit_offset = curwp->w_unit_offset;
  210.         curbp->b_markp = curwp->w_markp;
  211.         curbp->b_marko = curwp->w_marko;
  212.         }
  213.         curbp = bp;
  214.         curwp->w_bufp = bp;
  215.         if (bp->b_nwnd++ == 0)
  216.         {
  217.         curwp->w_dotp = bp->b_dotp;
  218.         curwp->w_doto = bp->b_doto;
  219.         curwp->w_unit_offset = bp->b_unit_offset;
  220.         curwp->w_markp = bp->b_markp;
  221.         curwp->w_marko = bp->b_marko;
  222.         }
  223.         else
  224.         {
  225.         wp = wheadp;
  226.         while (wp != NULL)
  227.         {
  228.             if (wp != curwp && wp->w_bufp == bp)
  229.             {
  230.             curwp->w_dotp = wp->w_dotp;
  231.             curwp->w_doto = wp->w_doto;
  232.             curwp->w_unit_offset = wp->w_unit_offset;
  233.             curwp->w_markp = wp->w_markp;
  234.             curwp->w_marko = wp->w_marko;
  235.             break;
  236.             }
  237.             wp = wp->w_wndp;
  238.         }
  239.         }
  240.         lp = curwp->w_dotp;
  241.         i = curwp->w_ntrows / 2;
  242.         while (i-- && lback (lp) != curbp->b_linep)
  243.         lp = lback (lp);
  244.         curwp->w_linep = lp;
  245.         curwp->w_flag |= WFMODE | WFHARD;
  246.         if (kbdmop == NULL)
  247.         {
  248.         writ_echo (MSG_old_buf);
  249.         }
  250.         return (TRUE);
  251.     }
  252.     }
  253.  
  254.     makename (bname, fname);    /* New buffer name.     */
  255.     while ((bp = bfind (bname, FALSE)) != NULL)
  256.     {
  257.     if (initial_load)    /* patch old name */
  258.     {
  259.         funky_name (bname, append++);
  260.         bp = NULL;
  261.         break;
  262.     }
  263.     s = ereply (MSG_buf_nam, bname, NBUFN, NULL);
  264.     if (s == ABORT)        /* ^G to just quit      */
  265.         return (s);
  266.     if (strcmp (bp->b_bname, bname) == 0 || s == FALSE)
  267.     {
  268.         /* CR to clobber it     */
  269.         makename (bname, fname);
  270.         break;
  271.     }
  272.     }
  273.     if (bp == NULL && (bp = bfind (bname, TRUE)) == NULL)
  274.     {
  275.     err_echo (MSG_cnt_cr);
  276.     return (FALSE);
  277.     }
  278.     if (--curbp->b_nwnd == 0)
  279.     {
  280.     /* Undisplay.           */
  281.     curbp->b_type = BTFILE;
  282.     curbp->b_dotp = curwp->w_dotp;
  283.     curbp->b_doto = curwp->w_doto;
  284.     curbp->b_unit_offset = curwp->w_unit_offset;
  285.     curbp->b_markp = curwp->w_markp;
  286.     curbp->b_marko = curwp->w_marko;
  287.     }
  288.     curbp = bp;            /* Switch to it.        */
  289.     curwp->w_bufp = bp;
  290.     curbp->b_nwnd++;
  291.     return (readin (fname, start, end));    /* Read it in.          */
  292. }
  293.  
  294. /*
  295. * Read the file "fname" into the current buffer.
  296. * Make all of the text in the buffer go away, after checking
  297. * for unsaved changes. This is called by the "read" command, the
  298. * "visit" command, and the mainline (for "beav file"). If the
  299. * BACKUP conditional is set, then this routine also does the read
  300. * end of backup processing. The BFBAK flag, if set in a buffer,
  301. * says that a backup should be taken. It is set when a file is
  302. * read in, but not on a new file (you don't need to make a backup
  303. * copy of nothing). Return a standard status. Print a summary
  304. * (lines read, error message) out as well.
  305. */
  306. char
  307. readin (fname, start, end)
  308.     char fname[];
  309.     A32 start, end;
  310. {
  311.     register LINE *lp1;
  312.     register LINE *lp2;
  313.     register WINDOW *wp;
  314.     register BUFFER *bp;
  315.     register char s, m;
  316.     long byte_cnt;
  317.     LPOS req_chars;
  318.     char buf[NCOL], buf1[NCOL];
  319.     A32 temp;
  320.  
  321.     m = TRUE;
  322.     byte_cnt = 0;
  323.     bp = curbp;            /* Cheap.               */
  324.     if ((s = bclear (bp)) != TRUE)    /* Might be old.        */
  325.     return (s);
  326. #if     BACKUP
  327.     bp->b_flag &= ~(BFCHG | BFBAK);    /* No change, backup.   */
  328. #else
  329.     bp->b_flag &= ~BFCHG;    /* No change.           */
  330. #endif
  331.     if ((start == 0L) && (end == MAXPOS))
  332.     strcpy (bp->b_fname, fname);
  333.     else
  334.     strcpy (bp->b_fname, MSG_null);
  335.     bp->b_file_size = 0;
  336.     bp->b_type = BTFILE;
  337.     if ((s = ffropen (fname)) == FIOERR || s == FIOFNF)    /* jam */
  338.     goto out;
  339.     bp->b_file_size = file_len ();    /* get the file lenth */
  340.     sprintf (buf, MSG_reading, fname);    /* jam */
  341.     writ_echo (buf);
  342.     temp = ffseek (start);
  343.     if (temp != start)
  344.     {
  345.     sprintf (buf1, ERR_f_size, R_POS_FMT (curwp));
  346.     sprintf (buf, buf1, temp);
  347.     writ_echo (buf);
  348.     return (FALSE);
  349.     }
  350.     /* only read the requested number of characters */
  351.     if ((end - start) > NLINE)
  352.     req_chars = NLINE;
  353.     else
  354.     req_chars = (int) (end - start);
  355.  
  356.     if ((lp1 = lalloc (req_chars)) == NULL)
  357.     {
  358.     bp->b_flag |= BFVIEW;    /* if no memory set to read only mode */
  359.  
  360.     m = FALSE;        /* flag memory allocation error */
  361.     }
  362.     else
  363.     {
  364.     while ((s = ffgetline (lp1->l_text, lp1->l_size, &lp1->l_used)) == FIOSUC)
  365.     {
  366.         /* this code breaks rules for knowing how lines * are stored and linked
  367.       together, oh well */
  368.         lp2 = lback (curbp->b_linep);
  369.         lp2->l_fp = lp1;
  370.         lp1->l_fp = curbp->b_linep;
  371.         lp1->l_bp = lp2;
  372.         curbp->b_linep->l_bp = lp1;
  373.         lp1->l_file_offset = byte_cnt;    /* file offset from begining */
  374.         byte_cnt += (long) lp1->l_used;    /* number of bytes read in    */
  375.         start += (long) lp1->l_used;
  376.         if (end <= start)
  377.         break;
  378.         /* stop reading after the requested number of characters */
  379.         if (end < start + req_chars)
  380.         {
  381.         req_chars = end - start;
  382.         }
  383.         if ((lp1 = lalloc (req_chars)) == NULL)
  384.         {
  385.         bp->b_flag |= BFVIEW;    /* if no memory set to read only mode */
  386.  
  387.         m = FALSE;    /* flag memory allocation error */
  388.         break;
  389.         }
  390.         if ((byte_cnt & 0x7fff) == 0)
  391.         {
  392.         sprintf (buf1, MSG_read_lx, R_POS_FMT (curwp));
  393.         sprintf (buf, buf1, (ulong) byte_cnt);
  394.         writ_echo (buf);
  395.         /* check if we should quit */
  396.         if (ttkeyready ())
  397.         {
  398.             wind_on_dot_all ();
  399.             if (ttgetc () == CTL_G)    /* was it an abort key? */
  400.             {
  401.             s = FIOERR;
  402.             break;
  403.             }
  404.         }
  405.         }
  406.     }
  407.     }
  408.     ffclose ();            /* Ignore errors.       */
  409.     if (s == FIOEOF && kbdmop == NULL)
  410.     {
  411.     /* Don't zap an error.   */
  412.     sprintf (buf1, MSG_read_lx, R_POS_FMT (curwp));
  413.     sprintf (buf, buf1, byte_cnt);
  414.     writ_echo (buf);
  415.     }
  416.     if (m == FALSE && kbdmop == NULL)
  417.     {
  418.     /* Don't zap an error.   */
  419.     sprintf (buf, MSG_no_mem_rd);
  420.     err_echo (buf);
  421.     }
  422.  
  423. #if     BACKUP
  424.     curbp->b_flag |= BFBAK;    /* Need a backup.       */
  425. #endif
  426.   out:
  427.     for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  428.     {
  429.     if (wp->w_bufp == curbp)
  430.     {
  431.         wp->w_linep = lforw (curbp->b_linep);
  432.         wp->w_dotp = lforw (curbp->b_linep);
  433.         wp->w_doto = 0;
  434.         wp->w_unit_offset = 0;
  435.         wp->w_markp = NULL;
  436.         wp->w_marko = 0;
  437.         wp->w_flag |= WFMODE | WFHARD;
  438.     }
  439.     }
  440.     /* so tell yank-buffer about it */
  441.     if ((blistp->b_nwnd != 0) &&/* update buffer display */
  442.     (blistp->b_type == BTLIST))
  443.     listbuffers ();
  444.     if (s == FIOERR || s == FIOFNF)    /* False if error.      */
  445.     return (FALSE);
  446.     return (TRUE);
  447. }
  448.  
  449. /*
  450. * Take a file name, and from it
  451. * fabricate a buffer name. This routine knows
  452. * about the syntax of file names on the target system.
  453. * BDC1         left scan delimiter.
  454. * BDC2         optional second left scan delimiter.
  455. * BDC3         optional right scan delimiter.
  456. */
  457. void
  458. makename (bname, fname)
  459.     char bname[];
  460.     char fname[];
  461. {
  462.     register char *cp1;
  463.     register char *cp2;
  464.  
  465.     cp1 = &fname[0];
  466.     while (*cp1 != 0)
  467.     ++cp1;
  468. #ifdef  BDC2
  469.     while (cp1 != &fname[0] && cp1[-1] != BDC1 && cp1[-1] != BDC2)
  470.     --cp1;
  471. #else
  472.     while (cp1 != &fname[0] && cp1[-1] != BDC1)
  473.     --cp1;
  474. #endif
  475.     cp2 = &bname[0];
  476. #ifdef  BDC3
  477.     while (cp2 != &bname[NBUFN - 1] && *cp1 != 0 && *cp1 != BDC3)
  478.     *cp2++ = *cp1++;
  479. #else
  480.     while (cp2 != &bname[NBUFN - 1] && *cp1 != 0)
  481.     *cp2++ = *cp1++;
  482. #endif
  483.     *cp2 = 0;
  484. }
  485.  
  486. /*
  487. * Ask for a file name, and write the
  488. * contents of the current buffer to that file.
  489. * Update the remembered file name and clear the
  490. * buffer changed flag. This handling of file names
  491. * is different from the earlier versions, and
  492. * is more compatable with Gosling EMACS than
  493. * with ITS EMACS.
  494. */
  495. char
  496. filewrite ()
  497. {
  498.     register WINDOW *wp;
  499.     register char s;
  500.     char fname[NFILEN];
  501.     A32 start, end;
  502.  
  503.     if ((s = ereply (MSG_wr_file, fname, NFILEN, NULL)) != TRUE)
  504.     return (s);
  505.     if (!parse_f_name (fname, &start, &end))
  506.     return (FALSE);
  507.  
  508.     adjustcase (fname);
  509.     if ((s = writeout (fname, start, end, S_IREAD | S_IWRITE)) == TRUE)
  510.     {
  511.     strcpy (curbp->b_fname, fname);
  512.     curbp->b_flag &= ~BFCHG;
  513.     wp = wheadp;        /* Update mode lines.   */
  514.     while (wp != NULL)
  515.     {
  516.         if (wp->w_bufp == curbp)
  517.         wp->w_flag |= WFMODE;
  518.         wp = wp->w_wndp;
  519.     }
  520.     }
  521.  
  522. #if     BACKUP
  523.     curbp->b_flag &= ~BFBAK;    /* No backup.           */
  524. #endif
  525.     return (s);
  526. }
  527.  
  528. /*
  529. * Save the contents of the current buffer back into
  530. * its associated file. Do nothing if there have been no changes
  531. * (is this a bug, or a feature). Error if there is no remembered
  532. * file name. If this is the first write since the read or visit,
  533. * then a backup copy of the file is made.
  534. */
  535. char
  536. filesave ()
  537. {
  538.     register WINDOW *wp;
  539.     register char s;
  540.     struct stat st;
  541.  
  542.     if ((curbp->b_flag & BFCHG) == 0)    /* Return, no changes.  */
  543.     return (TRUE);
  544.     if (curbp->b_fname[0] == 0)    /* Must have a name.    */
  545.     {
  546.     if (!(curbp->b_type == BTSAVE))    /* yanked buffer */
  547.     {
  548.         writ_echo (MSG_no_fn);
  549.     }
  550.     return (FALSE);
  551.     }
  552.     st.st_mode = S_IREAD | S_IWRITE;    /* set default */
  553. #if     BACKUP
  554.     if ((curbp->b_flag & BFBAK) != 0)
  555.     {
  556.     /* get the mode of the file */
  557.     stat (curbp->b_fname, &st);
  558.  
  559.     s = fbackupfile (curbp->b_fname);
  560.     if (s == ABORT)        /* Hard error.          */
  561.         return (s);
  562.     if (s == FALSE        /* Softer error.        */
  563.         && (s = eyesno (MSG_bk_err)) != TRUE)
  564.         return (s);
  565.     }
  566.  
  567. #endif
  568.     if ((s = writeout (curbp->b_fname, 0L, MAXPOS, st.st_mode)) == TRUE)
  569.     {
  570.     curbp->b_flag &= ~BFCHG;/* No change.           */
  571.     curbp->b_flag &= ~BFBAD;/* if it was trashed, forget it now */
  572.     wp = wheadp;        /* Update mode lines.   */
  573.     while (wp != NULL)
  574.     {
  575.         if (wp->w_bufp == curbp)
  576.         wp->w_flag |= WFMODE;
  577.         wp = wp->w_wndp;
  578.     }
  579.     }
  580.  
  581. #if     BACKUP
  582.     curbp->b_flag &= ~BFBAK;    /* No backup.           */
  583. #endif
  584.     return (s);
  585. }
  586.  
  587. /*
  588. * This function performs the details of file
  589. * writing. Uses the file management routines in the
  590. * "fileio.c" package. The number of lines written is
  591. * displayed. Sadly, it looks inside a LINE; provide
  592. * a macro for this. Most of the grief is error
  593. * checking of some sort.
  594. * The file permissions are set as requested.
  595. */
  596. bool
  597. writeout (fn, start, end, mode)
  598.     char *fn;
  599.     A32 start, end;
  600.     ushort mode;
  601. {
  602.     register int s, num_chars;
  603.     register LINE *lp;
  604.     register long nbytes;
  605.     char buf[NCOL], buf1[NCOL];
  606.     A32 temp;
  607.  
  608.     if ((s = ffwopen (fn, mode)) != FIOSUC)    /* Open writes message. */
  609.     return (FALSE);
  610.     temp = ffseek (start);
  611.     if (temp != start)
  612.     {
  613.     sprintf (buf1, ERR_f_size, R_POS_FMT (curwp));
  614.     sprintf (buf, buf1, temp);
  615.     writ_echo (buf);
  616.     return (FALSE);
  617.     }
  618.     sprintf (buf, MSG_writing, fn);    /* jam */
  619.     writ_echo (buf);
  620.  
  621.     /* insure that the help screen reflects the latest bindings */
  622.     if (curbp == blistp)
  623.     wallchart (0, 0, 0);
  624.  
  625.     lp = lforw (curbp->b_linep);/* First line. */
  626.     nbytes = 0;            /* Number of bytes.  */
  627.     temp = end - start;        /* number of bytes to write */
  628.     while (lp != curbp->b_linep)
  629.     {
  630.     if (curbp == blistp)
  631.     {
  632.         /* special list buffer */
  633.         num_chars = HENDCOL;/* limit line length */
  634.         lp->l_text[num_chars - 1] = '\n';
  635.     }
  636.     else
  637.     {
  638.         /* standard buffer */
  639.         if (nbytes + (long) llength (lp) > temp)
  640.         num_chars = (int) (temp - nbytes);
  641.         else
  642.         num_chars = llength (lp);
  643.     }
  644.     if ((s = ffputline (&lp->l_text[0], num_chars)) != FIOSUC)
  645.         break;
  646.     nbytes += num_chars;
  647.     if (temp <= nbytes)
  648.         break;
  649.     lp = lforw (lp);
  650.  
  651.     if ((nbytes & 0x7fff) == 0)
  652.     {
  653.         sprintf (buf1, MSG_wrot_n, R_POS_FMT (curwp));
  654.         sprintf (buf, buf1, (ulong) nbytes);
  655.         writ_echo (buf);
  656.         /* check if we should quit */
  657.         if (ttkeyready ())
  658.         {
  659.         wind_on_dot_all ();
  660.         if (ttgetc () == CTL_G)    /* was it an abort key? */
  661.         {
  662.             s = FIOERR;
  663.             break;
  664.         }
  665.         }
  666.     }
  667.     }
  668.     if (s == FIOSUC)
  669.     {
  670.     /* No write error. */
  671.     s = ffclose ();
  672.     if (s == FIOSUC && kbdmop == NULL)
  673.     {
  674.         sprintf (buf1, MSG_wrot_n, R_POS_FMT (curwp));
  675.         sprintf (buf, buf1, (long) nbytes);
  676.         writ_echo (buf);
  677.     }
  678.     }
  679.     else            /* Ignore close error   */
  680.     ffclose ();        /* if a write error.    */
  681.     curbp->b_file_size = nbytes;/* update file size */
  682.     if ((blistp->b_nwnd != 0) &&/* update buffer display */
  683.     (blistp->b_type == BTLIST))
  684.     listbuffers ();
  685.     if (s != FIOSUC)        /* Some sort of error.  */
  686.     return (FALSE);
  687.     return (TRUE);
  688. }
  689.  
  690. /*
  691. * The command allows the user
  692. * to modify the file name associated with
  693. * the current buffer. It is like the "f" command
  694. * in UNIX "ed". The operation is simple; just zap
  695. * the name in the BUFFER structure, and mark the windows
  696. * as needing an update. You can type a blank line at the
  697. * prompt if you wish.
  698. */
  699. char
  700. filename ()
  701. {
  702.     register WINDOW *wp;
  703.     register char s;
  704.     char fname[NFILEN];
  705.     A32 start, end;
  706.  
  707.     if ((s = ereply (MSG_fil_nam, fname, NFILEN, NULL)) == ABORT)
  708.     return (s);
  709.     if (!parse_f_name (fname, &start, &end))
  710.     return (FALSE);
  711.  
  712.     adjustcase (fname);
  713.     curbp->b_flag |= BFCHG;    /* jam - on name change, set modify */
  714.     BUF_START (curwp) = start;
  715.     l_fix_up (curbp->b_linep->l_fp);    /* adjust file offsets from first line */
  716.     strcpy (curbp->b_fname, fname);    /* Fix name.            */
  717.     wp = wheadp;        /* Update mode lines.   */
  718.     while (wp != NULL)
  719.     {
  720.     if (wp->w_bufp == curbp)
  721.         wp->w_flag |= WFMODE;
  722.     wp = wp->w_wndp;
  723.     }
  724. #if     BACKUP
  725.     curbp->b_flag &= ~BFBAK;    /* No backup.           */
  726. #endif
  727.     return (TRUE);
  728. }
  729.  
  730. /*
  731. *   Get the length parameters that were entered with the file name.
  732. *   There can be the file name only.
  733. *   There can be a file name and a starting position.
  734. *   There can be a name a starting position and an ending position.
  735. *   There can be a name a starting position and a length.
  736. *
  737. *   input:
  738. *       fn      pointer to file name string to parse.
  739. *
  740. *   output:
  741. *       fn      pointer to null terminated file name.
  742. *       start   pointer to the starting point in file (default = 0)
  743. *       end     pointer to the end point in file (default = -1)
  744. *       return  FALSE if file name or addresses are bad.
  745. */
  746. bool
  747. parse_f_name (fn, start, end)
  748.     char *fn;
  749.     A32 *start, *end;
  750. {
  751.     char buf[NFILEN], buf1[NCOL], fmt[NCOL];
  752.     int i_cnt;
  753.  
  754.     /* build up format string according to the current screen format */
  755.     sprintf (fmt, "%s %s %s", "%s", R_POS_FMT (curwp), R_POS_FMT (curwp));
  756.  
  757.     *start = 0L;
  758.     *end = MAXPOS;
  759.     sscanf (fn, fmt, buf, start, end);
  760.  
  761.     if (*end != MAXPOS)
  762.     {
  763.     for (i_cnt = strlen (fn) - 1; i_cnt >= 0; i_cnt--)
  764.     {
  765.         if (fn[i_cnt] == '+')
  766.         {
  767.         *end += *start;
  768.         break;
  769.         }
  770.     }
  771.     }
  772.     /* start should preceed end */
  773.     if (*start > *end)
  774.     {
  775.     sprintf (buf1, ERR_parse_fn, R_POS_FMT (curwp), R_POS_FMT (curwp));
  776.     sprintf (buf, buf1, *start, *end);
  777.     writ_echo (buf);
  778.     return (FALSE);
  779.     }
  780.  
  781.     /* error if addresses are negative */
  782.     if ((*start < 0) || (*end < 0))
  783.     {
  784.     writ_echo (ERR_addr_neg);
  785.     return (FALSE);
  786.     }
  787.  
  788.     /* deposit null terminated file name */
  789.     strcpy (fn, buf);
  790.     return (TRUE);
  791. }
  792.