home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / code / microema.sit / src / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-09  |  16.8 KB  |  753 lines  |  [TEXT/Earl]

  1. /*    FILE.C:   for MicroEMACS
  2.  
  3.     The routines in this file handle the reading, writing
  4.     and lookup of disk files.  All of details about the
  5.     reading and writing of the disk are in "fileio.c".
  6.  
  7. */
  8.  
  9. #include    <stdio.h>
  10. #include    "estruct.h"
  11. #include    "edef.h"
  12. #if MAC
  13. #if LSC
  14. #include    <PackageMgr.h>
  15. #include <QuickDraw.h>
  16. #include <StdFilePkg.h>
  17. #endif
  18. #if MPW
  19. #include <QuickDraw.h>
  20. #include <Packages.h>
  21. #define PtoCstr p2cstr
  22. #define CtoPstr c2pstr
  23. #endif
  24. extern short _iovrefnum;        /* defined in fileio.c */
  25. SFTypeList    mytypelist = {'TEXT','A/UX','COBJ','OBJ '};
  26. #endif
  27. /*
  28.  * Read a file into the current
  29.  * buffer. This is really easy; all you do is
  30.  * find the name of the file, and call the standard
  31.  * "read a file into the current buffer" code.
  32.  * Bound to "C-X C-R".
  33.  */
  34. fileread(f, n)
  35. {
  36.     register int    s;
  37.     char fname[NFILEN];
  38.  
  39.     if (restflag)        /* don't allow this command if restricted */
  40.         return(resterr());
  41. #if FINDER
  42.     if(!clexec){
  43.         if ((s=xgetfile(fname) != TRUE))
  44.             return(s);
  45.     }else{
  46.         _iovrefnum = curbp->b_ioWDDirID;
  47. #endif
  48.         if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE)
  49.             return(s);
  50. #if FINDER
  51.     }
  52. #endif
  53.     s = (readin(fname, TRUE));
  54. #if FINDER
  55.     curbp->b_ioWDDirID = _iovrefnum;
  56. #endif
  57.     return(s);
  58. }
  59.  
  60. /*
  61.  * Insert a file into the current
  62.  * buffer. This is really easy; all you do it
  63.  * find the name of the file, and call the standard
  64.  * "insert a file into the current buffer" code.
  65.  * Bound to "C-X C-I".
  66.  */
  67. insfile(f, n)
  68. {
  69.     register int    s;
  70.     char fname[NFILEN];
  71.  
  72.     if (restflag)        /* don't allow this command if restricted */
  73.         return(resterr());
  74.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if  */
  75.         return(rdonly());    /* we are in read only mode    */
  76. #if FINDER
  77.     if(!clexec){
  78.         if ((s=xgetfile(fname) != TRUE))
  79.             return(s);
  80.     }else{
  81.         _iovrefnum = curbp->b_ioWDDirID;
  82. #endif
  83.         if ((s=mlreply("Insert file: ", fname, NFILEN)) != TRUE)
  84.             return(s);
  85. #if FINDER
  86.     }
  87. #endif
  88.     return(ifile(fname));
  89. }
  90.  
  91. /*
  92.  * Select a file for editing.
  93.  * Look around to see if you can find the
  94.  * fine in another buffer; if you can find it
  95.  * just switch to the buffer. If you cannot find
  96.  * the file, create a new buffer, read in the
  97.  * text, and switch to the new buffer.
  98.  * Bound to C-X C-F.
  99.  */
  100. filefind(f, n)
  101. {
  102.     char fname[NFILEN];    /* file user wishes to find */
  103.     register int s;     /* status return */
  104.  
  105.     if (restflag)        /* don't allow this command if restricted */
  106.         return(resterr());
  107. #if FINDER
  108.     if(!clexec){
  109.         if ((s=xgetfile(fname) != TRUE))
  110.             return(s);
  111.     }else{
  112.     _iovrefnum = curbp->b_ioWDDirID;
  113. #endif
  114.     if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE)
  115.         return(s);
  116. #if FINDER
  117.     }
  118. #endif
  119.     s = (getfile(fname, TRUE));
  120. #if FINDER
  121.     curbp->b_ioWDDirID = _iovrefnum;
  122. #endif
  123.     return(s);
  124. }
  125.  
  126. viewfile(f, n)    /* visit a file in VIEW mode */
  127. {
  128.     char fname[NFILEN];    /* file user wishes to find */
  129.     register int s;     /* status return */
  130.     register WINDOW *wp;    /* scan for windows that need updating */
  131.  
  132.     if (restflag)        /* don't allow this command if restricted */
  133.         return(resterr());
  134. #if FINDER
  135.     if(!clexec){
  136.         if ((s=xgetfile(fname) != TRUE))
  137.         return (s);
  138.     }else{
  139.         _iovrefnum = curbp->b_ioWDDirID;
  140. #endif
  141.         if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE)
  142.             return (s);
  143. #if FINDER
  144.     }
  145. #endif
  146.  
  147.     s = getfile(fname, FALSE);
  148.     if (s) {    /* if we succeed, put it in view mode */
  149. #if FINDER
  150.         curbp->b_ioWDDirID = _iovrefnum;
  151. #endif
  152.         curwp->w_bufp->b_mode |= MDVIEW;
  153.  
  154.         /* scan through and update mode lines of all windows */
  155.         wp = wheadp;
  156.         while (wp != NULL) {
  157.             wp->w_flag |= WFMODE;
  158.             wp = wp->w_wndp;
  159.         }
  160.     }
  161.     return(s);
  162. }
  163.  
  164. #if    CRYPT
  165. resetkey()    /* reset the encryption key if needed */
  166.  
  167. {
  168.     register int s; /* return status */
  169.  
  170.     /* turn off the encryption flag */
  171.     cryptflag = FALSE;
  172.  
  173.     /* if we are in crypt mode */
  174.     if (curbp->b_mode & MDCRYPT) {
  175.         if (curbp->b_key[0] == 0) {
  176.             s = setkey(FALSE, 0);
  177.             if (s != TRUE)
  178.                 return(s);
  179.         }
  180.  
  181.         /* let others know... */
  182.         cryptflag = TRUE;
  183.  
  184.         /* and set up the key to be used! */
  185.         /* de-encrypt it */
  186.         crypt((char *)NULL, 0);
  187.         crypt(curbp->b_key, strlen(curbp->b_key));
  188.  
  189.         /* re-encrypt it...seeding it to start */
  190.         crypt((char *)NULL, 0);
  191.         crypt(curbp->b_key, strlen(curbp->b_key));
  192.     }
  193.  
  194.     return(TRUE);
  195. }
  196. #endif
  197.  
  198. getfile(fname, lockfl)
  199.  
  200. char fname[];        /* file name to find */
  201. int lockfl;        /* check the file for locks? */
  202.  
  203. {
  204.     register BUFFER *bp;
  205.     register LINE    *lp;
  206.     register int    i;
  207.     register int    s;
  208.     char bname[NBUFN];    /* buffer name to put file */
  209.  
  210. #if    MSDOS
  211.     mklower(fname);     /* msdos isn't case sensitive */
  212. #endif
  213.     for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
  214.         if ((bp->b_flag&BFINVS)==0 && name_equal(bp->b_fname, fname)==0) {
  215.             swbuffer(bp);
  216.             lp = curwp->w_dotp;
  217.             i = curwp->w_ntrows/2;
  218.             while (i-- && lback(lp)!=curbp->b_linep)
  219.                 lp = lback(lp);
  220.             curwp->w_linep = lp;
  221.             curwp->w_flag |= WFMODE|WFHARD;
  222.             mlwrite("[Old buffer]");
  223.             return (TRUE);
  224.         }
  225.     }
  226.     makename(bname, fname);         /* New buffer name.    */
  227.     while ((bp=bfind(bname, FALSE, 0)) != NULL) {
  228.         /* old buffer name conflict code */
  229.         s = mlreply("Buffer name: ", bname, NBUFN);
  230.         if (s == ABORT)         /* ^G to just quit    */
  231.             return (s);
  232.         if (s == FALSE) {        /* CR to clobber it    */
  233.             makename(bname, fname);
  234.             break;
  235.         }
  236.     }
  237.     if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) {
  238.         mlwrite("Cannot create buffer");
  239.         return (FALSE);
  240.     }
  241.     if (--curbp->b_nwnd == 0) {        /* Undisplay.        */
  242.         curbp->b_dotp = curwp->w_dotp;
  243.         curbp->b_doto = curwp->w_doto;
  244.         curbp->b_markp = curwp->w_markp;
  245.         curbp->b_marko = curwp->w_marko;
  246.     }
  247.     curbp = bp;                /* Switch to it.    */
  248.     curwp->w_bufp = bp;
  249.     curbp->b_nwnd++;
  250.     return(readin(fname, lockfl));        /* Read it in.        */
  251. }
  252.  
  253. /*
  254.     Read file "fname" into the current buffer, blowing away any text
  255.     found there.  Called by both the read and find commands.  Return
  256.     the final status of the read.  Also called by the mainline, to
  257.     read in a file specified on the command line as an argument.
  258.     The command bound to M-FNR is called after the buffer is set up
  259.     and before it is read.
  260. */
  261.  
  262. readin(fname, lockfl)
  263.  
  264. char    fname[];    /* name of file to read */
  265. int    lockfl;     /* check for file locks? */
  266.  
  267. {
  268.     register LINE    *lp1;
  269.     register LINE    *lp2;
  270.     register int    i;
  271.     register WINDOW *wp;
  272.     register BUFFER *bp;
  273.     register int    s;
  274.     int    nbytes;
  275.     register int    nline;
  276.     int        lflag;        /* any lines longer than allowed? */
  277.     char mesg[NSTRING];
  278.     char *here;
  279.  
  280. #if    FILOCK
  281.     if (lockfl && lockchk(fname) == ABORT)
  282.         return(ABORT);
  283. #endif
  284. #if    CRYPT
  285.     s = resetkey();
  286.     if (s != TRUE)
  287.         return(s);
  288. #endif
  289.     bp = curbp;                /* Cheap.        */
  290.     if ((s=bclear(bp)) != TRUE)        /* Might be old.    */
  291.         return (s);
  292.     bp->b_flag &= ~(BFINVS|BFCHG);
  293.     strcpy(bp->b_fname, fname);
  294.  
  295.     /* let a user macro get hold of things...if he wants */
  296.     execute(META|SPEC|'R', FALSE, 1);
  297.  
  298.     /* turn off ALL keyboard translation in case we get a dos error */
  299.     TTkclose();
  300.  
  301.     if ((s=ffropen(fname)) == FIOERR)    /* Hard file open.    */
  302.         goto out;
  303.  
  304.     if (s == FIOFNF) {            /* File not found.    */
  305.         mlwrite("[New file]");
  306.         goto out;
  307.     }
  308.  
  309.     /* read the file in */
  310.     mlwrite("[Reading file]");
  311.     nline = 0;
  312.     lflag = FALSE;
  313.     while ((s=ffgetline(&nbytes)) == FIOSUC) {
  314.  
  315.         if ((lp1=lalloc(nbytes)) == NULL) {
  316.             s = FIOMEM;        /* Keep message on the    */
  317.             break;            /* display.        */
  318.         }
  319.         lp2 = lback(curbp->b_linep);
  320.         lp2->l_fp = lp1;
  321.         lp1->l_fp = curbp->b_linep;
  322.         lp1->l_bp = lp2;
  323.         curbp->b_linep->l_bp = lp1;
  324.         for (i=0; i<nbytes; ++i)
  325.             lputc(lp1, i, fline[i]);
  326.         ++nline;
  327.     }
  328.     ffclose();                /* Ignore errors.    */
  329.     strcpy(mesg, "[");
  330.     if (s==FIOERR) {
  331.         strcat(mesg, "I/O ERROR, ");
  332.         curbp->b_flag |= BFTRUNC;
  333.     }
  334.     if (s == FIOMEM) {
  335.         strcat(mesg, "OUT OF MEMORY, ");
  336.         curbp->b_flag |= BFTRUNC;
  337.     }
  338. #if FINDER    /* Avoid linking in sprintf for just 1 function call! */
  339.     strcat(&mesg[strlen(mesg)],"Read ");
  340.     NumToString( (long)nline,(here = &mesg[strlen(mesg)]));
  341.     PtoCstr(here);
  342.     strcat(&mesg[strlen(mesg)]," line");
  343. #else
  344.     sprintf(&mesg[strlen(mesg)], "Read %d line", nline);
  345. #endif
  346.     if (nline > 1)
  347.         strcat(mesg, "s");
  348.     strcat(mesg, "]");
  349.     mlwrite(mesg);
  350.  
  351. out:
  352.     TTkopen();    /* open the keyboard again */
  353.     for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  354.         if (wp->w_bufp == curbp) {
  355.             wp->w_linep = lforw(curbp->b_linep);
  356.             wp->w_dotp  = lforw(curbp->b_linep);
  357.             wp->w_doto  = 0;
  358.             wp->w_markp = NULL;
  359.             wp->w_marko = 0;
  360.             wp->w_flag |= WFMODE|WFHARD;
  361.         }
  362.     }
  363.     if (s == FIOERR || s == FIOFNF)     /* False if error.    */
  364.         return(FALSE);
  365.     return (TRUE);
  366. }
  367.  
  368. /*
  369.  * Take a file name, and from it
  370.  * fabricate a buffer name. This routine knows
  371.  * about the syntax of file names on the target system.
  372.  * I suppose that this information could be put in
  373.  * a better place than a line of code.
  374.  */
  375. makename(bname, fname)
  376. char    bname[];
  377. char    fname[];
  378. {
  379.     register char *cp1;
  380.     register char *cp2;
  381.  
  382.     cp1 = &fname[0];
  383.     while (*cp1 != 0)
  384.         ++cp1;
  385.  
  386. #if    AMIGA
  387.     while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='/')
  388.         --cp1;
  389. #endif
  390. #if    VMS
  391.     while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']')
  392.         --cp1;
  393. #endif
  394. #if    CPM
  395.     while (cp1!=&fname[0] && cp1[-1]!=':')
  396.         --cp1;
  397. #endif
  398. #if    MSDOS
  399.     while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
  400.         --cp1;
  401. #endif
  402. #if    ST520
  403.     while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\')
  404.         --cp1;
  405. #endif
  406. #if    FINDER
  407.     while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
  408.         --cp1;
  409. #endif
  410. #if    V7 | USG | BSD
  411.     while (cp1!=&fname[0] && cp1[-1]!='/')
  412.         --cp1;
  413. #endif
  414.     cp2 = &bname[0];
  415.     while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
  416.         *cp2++ = *cp1++;
  417.     *cp2 = 0;
  418. }
  419.  
  420. unqname(name)    /* make sure a buffer name is unique */
  421.  
  422. char *name;    /* name to check on */
  423.  
  424. {
  425.     register char *sp;
  426.  
  427.     /* check to see if it is in the buffer list */
  428.     while (bfind(name, 0, FALSE) != NULL) {
  429.  
  430.         /* go to the end of the name */
  431.         sp = name;
  432.         while (*sp)
  433.             ++sp;
  434.         if (sp == name || (*(sp-1) <'0' || *(sp-1) > '8')) {
  435.             *sp++ = '0';
  436.             *sp = 0;
  437.         } else
  438.             *(--sp) += 1;
  439.     }
  440. }
  441.  
  442. /*
  443.  * Ask for a file name, and write the
  444.  * contents of the current buffer to that file.
  445.  * Update the remembered file name and clear the
  446.  * buffer changed flag. This handling of file names
  447.  * is different from the earlier versions, and
  448.  * is more compatable with Gosling EMACS than
  449.  * with ITS EMACS. Bound to "C-X C-W".
  450.  */
  451. filewrite(f, n)
  452. {
  453.     register WINDOW *wp;
  454.     register int    s;
  455.     char        fname[NFILEN];
  456.  
  457.     if (restflag)        /* don't allow this command if restricted */
  458.         return(resterr());
  459. #if FINDER
  460.     if ((s=xputfile(fname,NFILEN) != TRUE))
  461.         return (s);
  462. #else
  463.     if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE)
  464.         return (s);
  465. #endif
  466.     if ((s=writeout(fname)) == TRUE) {
  467.         strcpy(curbp->b_fname, fname);
  468.         curbp->b_flag &= ~BFCHG;
  469.         wp = wheadp;            /* Update mode lines.    */
  470.         while (wp != NULL) {
  471.             if (wp->w_bufp == curbp)
  472.                 wp->w_flag |= WFMODE;
  473.             wp = wp->w_wndp;
  474.         }
  475.     }
  476.     return (s);
  477. }
  478.  
  479. /*
  480.  * Save the contents of the current
  481.  * buffer in its associatd file. No nothing
  482.  * if nothing has changed (this may be a bug, not a
  483.  * feature). Error if there is no remembered file
  484.  * name for the buffer. Bound to "C-X C-S". May
  485.  * get called by "C-Z".
  486.  */
  487. filesave(f, n)
  488. {
  489.     register WINDOW *wp;
  490.     register int    s;
  491.  
  492.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if  */
  493.         return(rdonly());    /* we are in read only mode    */
  494.     if ((curbp->b_flag&BFCHG) == 0)     /* Return, no changes.    */
  495.         return (TRUE);
  496.     if (curbp->b_fname[0] == 0) {        /* Must have a name.    */
  497.         mlwrite("No file name");
  498.         return (FALSE);
  499.     }
  500.  
  501.     /* complain about truncated files */
  502.     if ((curbp->b_flag&BFTRUNC) != 0) {
  503.         if (mlyesno("Truncated file..write it out") == FALSE) {
  504.             mlwrite("[Aborted]");
  505.             return(FALSE);
  506.         }
  507.     }
  508.  
  509.     if ((s=writeout(curbp->b_fname)) == TRUE) {
  510.         curbp->b_flag &= ~BFCHG;
  511.         wp = wheadp;            /* Update mode lines.    */
  512.         while (wp != NULL) {
  513.             if (wp->w_bufp == curbp)
  514.                 wp->w_flag |= WFMODE;
  515.             wp = wp->w_wndp;
  516.         }
  517.     }
  518.     return (s);
  519. }
  520.  
  521. /*
  522.  * This function performs the details of file
  523.  * writing. Uses the file management routines in the
  524.  * "fileio.c" package. The number of lines written is
  525.  * displayed. Sadly, it looks inside a LINE; provide
  526.  * a macro for this. Most of the grief is error
  527.  * checking of some sort.
  528.  */
  529. writeout(fn)
  530. char    *fn;
  531. {
  532.     register int    s;
  533.     register LINE    *lp;
  534.     register int    nline;
  535.  
  536. #if    CRYPT
  537.     s = resetkey();
  538.     if (s != TRUE)
  539.         return(s);
  540. #endif
  541.     /* turn off ALL keyboard translation in case we get a dos error */
  542.     TTkclose();
  543.  
  544.     if ((s=ffwopen(fn)) != FIOSUC) {    /* Open writes message. */
  545.         TTkopen();
  546.         return (FALSE);
  547.     }
  548.     mlwrite("[Writing...]");        /* tell us were writing */
  549.     lp = lforw(curbp->b_linep);        /* First line.        */
  550.     nline = 0;                /* Number of lines.    */
  551.     while (lp != curbp->b_linep) {
  552.         if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  553.             break;
  554.         ++nline;
  555.         lp = lforw(lp);
  556.     }
  557.     if (s == FIOSUC) {            /* No write error.    */
  558.         s = ffclose();
  559.         if (s == FIOSUC) {        /* No close error.    */
  560.             if (nline == 1)
  561.                 mlwrite("[Wrote 1 line]");
  562.             else
  563.                 mlwrite("[Wrote %d lines]", nline);
  564.         }
  565.     } else                    /* Ignore close error    */
  566.         ffclose();            /* if a write error.    */
  567.     TTkopen();
  568.     if (s != FIOSUC)            /* Some sort of error.    */
  569.         return (FALSE);
  570.     return (TRUE);
  571. }
  572.  
  573. /*
  574.  * The command allows the user
  575.  * to modify the file name associated with
  576.  * the current buffer. It is like the "f" command
  577.  * in UNIX "ed". The operation is simple; just zap
  578.  * the name in the BUFFER structure, and mark the windows
  579.  * as needing an update. You can type a blank line at the
  580.  * prompt if you wish.
  581.  */
  582. filename(f, n)
  583. {
  584.     register WINDOW *wp;
  585.     register int    s;
  586.     char        fname[NFILEN];
  587.  
  588.     if (restflag)        /* don't allow this command if restricted */
  589.         return(resterr());
  590. #if FINDER
  591. if(!clexec){
  592.     if ((s=xputfile(fname,NFILEN) != TRUE))
  593.         return (s);
  594. }
  595. else
  596. #endif
  597.     if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT)
  598.         return (s);
  599.     if (s == FALSE)
  600.         strcpy(curbp->b_fname, "");
  601.     else
  602.         strcpy(curbp->b_fname, fname);
  603.     wp = wheadp;                /* Update mode lines.    */
  604.     while (wp != NULL) {
  605.         if (wp->w_bufp == curbp)
  606.             wp->w_flag |= WFMODE;
  607.         wp = wp->w_wndp;
  608.     }
  609.     curbp->b_mode &= ~MDVIEW;    /* no longer read only mode */
  610.     return (TRUE);
  611. }
  612.  
  613. /*
  614.  * Insert file "fname" into the current
  615.  * buffer, Called by insert file command. Return the final
  616.  * status of the read.
  617.  */
  618. ifile(fname)
  619. char    fname[];
  620. {
  621.     register LINE    *lp0;
  622.     register LINE    *lp1;
  623.     register LINE    *lp2;
  624.     register int    i;
  625.     register BUFFER *bp;
  626.     register int    s;
  627.     int    nbytes;
  628.     register int    nline;
  629.     int        lflag;        /* any lines longer than allowed? */
  630.     char mesg[NSTRING];
  631.     char *here;
  632.  
  633.     bp = curbp;                /* Cheap.        */
  634.     bp->b_flag |= BFCHG;            /* we have changed    */
  635.     bp->b_flag &= ~BFINVS;            /* and are not temporary*/
  636.     if ((s=ffropen(fname)) == FIOERR)    /* Hard file open.    */
  637.         goto out;
  638.     if (s == FIOFNF) {            /* File not found.    */
  639.         mlwrite("[No such file]");
  640.         return(FALSE);
  641.     }
  642.     mlwrite("[Inserting file]");
  643.  
  644. #if    CRYPT
  645.     s = resetkey();
  646.     if (s != TRUE)
  647.         return(s);
  648. #endif
  649.     /* back up a line and save the mark here */
  650.     curwp->w_dotp = lback(curwp->w_dotp);
  651.     curwp->w_doto = 0;
  652.     curwp->w_markp = curwp->w_dotp;
  653.     curwp->w_marko = 0;
  654.  
  655.     nline = 0;
  656.     lflag = FALSE;
  657.     while ((s=ffgetline(&nbytes)) == FIOSUC) {
  658.  
  659.         if ((lp1=lalloc(nbytes)) == NULL) {
  660.             s = FIOMEM;        /* Keep message on the    */
  661.             break;            /* display.        */
  662.         }
  663.         lp0 = curwp->w_dotp;    /* line previous to insert */
  664.         lp2 = lp0->l_fp;    /* line after insert */
  665.  
  666.         /* re-link new line between lp0 and lp2 */
  667.         lp2->l_bp = lp1;
  668.         lp0->l_fp = lp1;
  669.         lp1->l_bp = lp0;
  670.         lp1->l_fp = lp2;
  671.  
  672.         /* and advance and write out the current line */
  673.         curwp->w_dotp = lp1;
  674.         for (i=0; i<nbytes; ++i)
  675.             lputc(lp1, i, fline[i]);
  676.         ++nline;
  677.     }
  678.     ffclose();                /* Ignore errors.    */
  679.     curwp->w_markp = lforw(curwp->w_markp);
  680.     strcpy(mesg, "[");
  681.     if (s==FIOERR) {
  682.         strcat(mesg, "I/O ERROR, ");
  683.         curbp->b_flag |= BFTRUNC;
  684.     }
  685.     if (s == FIOMEM) {
  686.         strcat(mesg, "OUT OF MEMORY, ");
  687.         curbp->b_flag |= BFTRUNC;
  688.     }
  689. #if FINDER    /* Avoid linking in sprintf for just 1 function call! */
  690.     strcat(&mesg[strlen(mesg)],"Inserted ");
  691.     NumToString( (long)nline,(here = &mesg[strlen(mesg)]));
  692.     PtoCstr(here);
  693.     strcat(&mesg[strlen(mesg)]," line");
  694. #else
  695.     sprintf(&mesg[strlen(mesg)], "Inserted %d line", nline);
  696. #endif
  697.     if (nline > 1)
  698.         strcat(mesg, "s");
  699.     strcat(mesg, "]");
  700.     mlwrite(mesg);
  701.  
  702. out:
  703.     /* advance to the next line and mark the window for changes */
  704.     curwp->w_dotp = lforw(curwp->w_dotp);
  705.     curwp->w_flag |= WFHARD | WFMODE;
  706.  
  707.     /* copy window parameters back to the buffer structure */
  708.     curbp->b_dotp = curwp->w_dotp;
  709.     curbp->b_doto = curwp->w_doto;
  710.     curbp->b_markp = curwp->w_markp;
  711.     curbp->b_marko = curwp->w_marko;
  712.  
  713.     if (s == FIOERR)            /* False if error.    */
  714.         return (FALSE);
  715.     return (TRUE);
  716. }
  717. #if LSC
  718. #define PASS(a) a
  719. #endif
  720. #if MPW
  721. #define PASS(a) &(a)            /* Yuch!!!! */
  722. #endif
  723. xgetfile (reply)
  724. char reply[];
  725. {
  726.     SFReply frommac;
  727.     SFGetFile (where, 0L, 0L, 4, mytypelist, 0L, &frommac);
  728.     if (frommac.good) {
  729.         _iovrefnum = frommac.vRefNum;
  730.         PtoCstr(PASS(frommac.fName));
  731.         strcpy(reply,PASS(frommac.fName));
  732.       return (TRUE);
  733.     }
  734.     else return (FALSE);
  735. }
  736. xputfile (reply,length)
  737. char reply[];
  738. int length;
  739. {
  740.     SFReply frommac;
  741.     CtoPstr(curbp->b_fname);
  742.     SFPutFile (where, "\009Put file:",curbp->b_fname ,0L, &frommac);
  743.     PtoCstr(curbp->b_fname);
  744.     if (frommac.good) {
  745.         _iovrefnum = frommac.vRefNum;
  746.         curbp->b_ioWDDirID = _iovrefnum;
  747.         PtoCstr(PASS(frommac.fName));
  748.         strncpy(reply,PASS(frommac.fName),length);
  749.         return (TRUE);
  750.     }
  751.     else return (FALSE);
  752. }
  753.