home *** CD-ROM | disk | FTP | other *** search
/ Shareware 1 2 the Maxx / sw_1.zip / sw_1 / OS2 / BEAV132X.ZIP / FILE.C < prev    next >
C/C++ Source or Header  |  1992-01-06  |  20KB  |  789 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    fileread ()
  50. {
  51.     register char   s;
  52.     char    fname[NFILEN];
  53.     A32     start, end;
  54.  
  55.     if ((s = ereply (MSG_rd_file, fname, NFILEN, NULL)) != TRUE)
  56.         return (s);
  57.     if (parse_f_name (fname, &start, &end))
  58.     {
  59.         adjustcase (fname);
  60.         return (readin (fname, start, end));
  61.     }
  62.     return (TRUE);
  63. }
  64.  
  65.  
  66. /* insert file into current buffer - use readin, and yank
  67. */
  68. char    fileinsert ()
  69. {
  70.     register char   s;
  71.     char    bname[NBUFN],
  72.     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. /*
  118. * Select a file for editing.
  119. * Look around to see if you can find the
  120. * fine in another buffer; if you can find it
  121. * just switch to the buffer. If you cannot find
  122. * the file, create a new buffer, read in the
  123. * text, and switch to the new buffer.
  124. *
  125. * also various hacked versions for auto load, and
  126. * file-vist with auto window split, and readonly (view-file) (jam)
  127. */
  128. char    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.  
  144. /* like filevisit, only read only
  145. */
  146. char    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.  
  166. char    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.  
  181. char    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. /*
  296. * Read the file "fname" into the current buffer.
  297. * Make all of the text in the buffer go away, after checking
  298. * for unsaved changes. This is called by the "read" command, the
  299. * "visit" command, and the mainline (for "beav file"). If the
  300. * BACKUP conditional is set, then this routine also does the read
  301. * end of backup processing. The BFBAK flag, if set in a buffer,
  302. * says that a backup should be taken. It is set when a file is
  303. * read in, but not on a new file (you don't need to make a backup
  304. * copy of nothing). Return a standard status. Print a summary
  305. * (lines read, error message) out as well.
  306. */
  307. char    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. /*
  451. * Take a file name, and from it
  452. * fabricate a buffer name. This routine knows
  453. * about the syntax of file names on the target system.
  454. * BDC1         left scan delimiter.
  455. * BDC2         optional second left scan delimiter.
  456. * BDC3         optional right scan delimiter.
  457. */
  458. void 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. /*
  488. * Ask for a file name, and write the
  489. * contents of the current buffer to that file.
  490. * Update the remembered file name and clear the
  491. * buffer changed flag. This handling of file names
  492. * is different from the earlier versions, and
  493. * is more compatable with Gosling EMACS than
  494. * with ITS EMACS.
  495. */
  496. char    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. /*
  530. * Save the contents of the current buffer back into
  531. * its associated file. Do nothing if there have been no changes
  532. * (is this a bug, or a feature). Error if there is no remembered
  533. * file name. If this is the first write since the read or visit,
  534. * then a backup copy of the file is made.
  535. */
  536. char    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 writeout (fn, start, end, mode)
  597. char   *fn;
  598. A32     start, end;
  599. ushort    mode;
  600. {
  601.     register    int    s, num_chars;
  602.     register    LINE * lp;
  603.     register    long   nbytes;
  604.     char        buf[NCOL], buf1[NCOL];
  605.     A32         temp;
  606.  
  607.     if ((s = ffwopen (fn, mode)) != FIOSUC)/* Open writes message. */
  608.         return (FALSE);
  609.     temp = ffseek (start);
  610.     if (temp != start)
  611.     {
  612.         sprintf (buf1, ERR_f_size, R_POS_FMT(curwp));
  613.         sprintf (buf, buf1, temp);
  614.         writ_echo (buf);
  615.         return (FALSE);
  616.     }
  617.     sprintf (buf, MSG_writing, fn);/* jam */
  618.     writ_echo (buf);
  619.  
  620.     /* insure that the help screen reflects the latest bindings */
  621.     if (curbp == blistp)
  622.         wallchart (0, 0, 0);
  623.  
  624.     lp = lforw (curbp -> b_linep);/* First line. */
  625.     nbytes = 0;                  /* Number of bytes.  */
  626.     temp = end - start;         /* number of bytes to write */
  627.     while (lp != curbp -> b_linep)
  628.     {
  629.         if (curbp == blistp)
  630.         {
  631.             /* special list buffer */
  632.             num_chars = HENDCOL;    /* limit line length */
  633.             lp -> l_text[num_chars - 1] = '\n';
  634.         }
  635.         else
  636.         {
  637.             /* standard buffer */
  638.             if (nbytes + (long)llength (lp) > temp)
  639.                 num_chars = (int)(temp - nbytes);
  640.             else
  641.                 num_chars = llength (lp);
  642.         }
  643.         if ((s = ffputline (&lp -> l_text[0], num_chars)) != FIOSUC)
  644.             break;
  645.         nbytes += num_chars;
  646.         if (temp <= nbytes)
  647.             break;
  648.         lp = lforw (lp);
  649.  
  650.         if ((nbytes & 0x7fff) == 0)
  651.         {
  652.             sprintf (buf1, MSG_wrot_n, R_POS_FMT(curwp));
  653.             sprintf (buf, buf1, (ulong)nbytes);
  654.             writ_echo (buf);
  655.             /* check if we should quit */
  656.             if (ttkeyready ())
  657.             {
  658.                 wind_on_dot_all();
  659.                 if (ttgetc () == CTL_G)  /* was it an abort key? */
  660.                 {
  661.                     s = FIOERR;
  662.                     break;
  663.                 }
  664.             }
  665.         }
  666.     }
  667.     if (s == FIOSUC)
  668.     {
  669.         /* No write error. */
  670.         s = ffclose ();
  671.         if (s == FIOSUC && kbdmop == NULL)
  672.         {
  673.             sprintf (buf1, MSG_wrot_n, R_POS_FMT(curwp));
  674.             sprintf (buf, buf1, (long) nbytes);
  675.             writ_echo (buf);
  676.         }
  677.     }
  678.     else /* Ignore close error   */
  679.         ffclose ();             /* if a write error.    */
  680.     curbp -> b_file_size = nbytes;  /* update file size */
  681.     if ((blistp -> b_nwnd != 0) &&  /* update buffer display */
  682.     (blistp -> b_type == BTLIST))
  683.         listbuffers ();
  684.     if (s != FIOSUC)            /* Some sort of error.  */
  685.         return (FALSE);
  686.     return (TRUE);
  687. }
  688.  
  689. /*
  690. * The command allows the user
  691. * to modify the file name associated with
  692. * the current buffer. It is like the "f" command
  693. * in UNIX "ed". The operation is simple; just zap
  694. * the name in the BUFFER structure, and mark the windows
  695. * as needing an update. You can type a blank line at the
  696. * prompt if you wish.
  697. */
  698. char    filename ()
  699. {
  700.     register    WINDOW * wp;
  701.     register char   s;
  702.     char    fname[NFILEN];
  703.     A32     start, end;
  704.  
  705.     if ((s = ereply (MSG_fil_nam, fname, NFILEN, NULL)) == ABORT)
  706.         return (s);
  707.     if (!parse_f_name (fname, &start, &end))
  708.         return (FALSE);
  709.  
  710.     adjustcase (fname);
  711.     curbp -> b_flag |= BFCHG;   /* jam - on name change, set modify */
  712.     BUF_START(curwp) = start;
  713.     l_fix_up (curbp -> b_linep -> l_fp); /* adjust file offsets from first line */
  714.     strcpy (curbp -> b_fname, fname);/* Fix name.            */
  715.     wp = wheadp;                /* Update mode lines.   */
  716.     while (wp != NULL)
  717.     {
  718.         if (wp -> w_bufp == curbp)
  719.             wp -> w_flag |= WFMODE;
  720.         wp = wp -> w_wndp;
  721.     }
  722. #if     BACKUP
  723.     curbp -> b_flag &= ~BFBAK;  /* No backup.           */
  724. #endif
  725.     return (TRUE);
  726. }
  727.  
  728. /*
  729. *   Get the length parameters that were entered with the file name.
  730. *   There can be the file name only.
  731. *   There can be a file name and a starting position.
  732. *   There can be a name a starting position and an ending position.
  733. *   There can be a name a starting position and a length.
  734. *
  735. *   input:
  736. *       fn      pointer to file name string to parse.
  737. *
  738. *   output:
  739. *       fn      pointer to null terminated file name.
  740. *       start   pointer to the starting point in file (default = 0)
  741. *       end     pointer to the end point in file (default = -1)
  742. *       return  FALSE if file name or addresses are bad.
  743. */
  744. bool    parse_f_name (fn, start, end)
  745. char    *fn;
  746. A32     *start, *end;
  747. {
  748.     char    buf[NFILEN], buf1[NCOL], fmt[NCOL];
  749.     int     i_cnt;
  750.  
  751.     /* build up format string according to the current screen format */
  752.     sprintf (fmt, "%s %s %s", "%s", R_POS_FMT(curwp), R_POS_FMT(curwp));
  753.  
  754.     *start = 0L;
  755.     *end = MAXPOS;
  756.     sscanf (fn, fmt, buf, start, end);
  757.  
  758.     if (*end != MAXPOS)
  759.     {
  760.         for (i_cnt = strlen (fn) - 1; i_cnt >= 0; i_cnt--)
  761.         {
  762.             if (fn[i_cnt] == '+')
  763.             {
  764.                 *end += *start;
  765.                 break;
  766.             }
  767.         }
  768.     }
  769.     /* start should preceed end */
  770.     if (*start > *end)
  771.     {
  772.         sprintf (buf1, ERR_parse_fn, R_POS_FMT(curwp), R_POS_FMT(curwp));
  773.         sprintf (buf, buf1, *start, *end);
  774.         writ_echo (buf);
  775.         return (FALSE);
  776.     }
  777.  
  778.     /* error if addresses are negative */
  779.     if ((*start < 0) || (*end < 0))
  780.     {
  781.         writ_echo (ERR_addr_neg);
  782.         return (FALSE);
  783.     }
  784.  
  785.     /* deposit null terminated file name */
  786.     strcpy (fn, buf);
  787.     return (TRUE);
  788. }
  789.