[BACK]Return to file.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/file.c, Revision 1.1

1.1     ! deraadt     1: /*
        !             2:  *             File commands.
        !             3:  */
        !             4: #include       "def.h"
        !             5:
        !             6: BUFFER *findbuffer();
        !             7: VOID   makename();
        !             8: VOID   upmodes();
        !             9: static char *itos();
        !            10:
        !            11: /*
        !            12:  * insert a file into the current buffer. Real easy - just call the
        !            13:  * insertfile routine with the file name.
        !            14:  */
        !            15: /*ARGSUSED*/
        !            16: fileinsert(f, n)
        !            17: {
        !            18:        register int    s;
        !            19:        char            fname[NFILEN];
        !            20:
        !            21:        if ((s=eread("Insert file: ", fname, NFILEN, EFNEW|EFCR|EFFILE)) != TRUE)
        !            22:                return (s);
        !            23:        return insertfile(adjustname(fname), (char *) NULL, FALSE);
        !            24:                                                /* don't set buffer name */
        !            25: }
        !            26:
        !            27: /*
        !            28:  * Select a file for editing.
        !            29:  * Look around to see if you can find the
        !            30:  * fine in another buffer; if you can find it
        !            31:  * just switch to the buffer. If you cannot find
        !            32:  * the file, create a new buffer, read in the
        !            33:  * text, and switch to the new buffer.
        !            34:  */
        !            35: /*ARGSUSED*/
        !            36: filevisit(f, n)
        !            37: {
        !            38:        register BUFFER *bp;
        !            39:        int     s;
        !            40:        char    fname[NFILEN];
        !            41:        char    *adjf;
        !            42:
        !            43:        if ((s=eread("Find file: ", fname, NFILEN, EFNEW|EFCR|EFFILE)) != TRUE)
        !            44:                return s;
        !            45:        adjf = adjustname(fname);
        !            46:        if ((bp = findbuffer(adjf)) == NULL) return FALSE;
        !            47:        curbp = bp;
        !            48:        if (showbuffer(bp, curwp, WFHARD) != TRUE) return FALSE;
        !            49:        if (bp->b_fname[0] == 0)
        !            50:                return readin(adjf);            /* Read it in.          */
        !            51:        return TRUE;
        !            52: }
        !            53:
        !            54: /*
        !            55:  * Pop to a file in the other window. Same as last function, just
        !            56:  * popbuf instead of showbuffer.
        !            57:  */
        !            58: /*ARGSUSED*/
        !            59: poptofile(f, n)
        !            60: {
        !            61:        register BUFFER *bp;
        !            62:        register WINDOW *wp;
        !            63:        int     s;
        !            64:        char    fname[NFILEN];
        !            65:        char    *adjf;
        !            66:
        !            67:        if ((s=eread("Find file in other window: ", fname, NFILEN,
        !            68:                     EFNEW|EFCR|EFFILE)) != TRUE)
        !            69:                return s;
        !            70:        adjf = adjustname(fname);
        !            71:        if ((bp = findbuffer(adjf)) == NULL) return FALSE;
        !            72:        if ((wp = popbuf(bp)) == NULL) return FALSE;
        !            73:        curbp = bp;
        !            74:        curwp = wp;
        !            75:        if (bp->b_fname[0] == 0)
        !            76:                return readin(adjf);            /* Read it in.          */
        !            77:        return TRUE;
        !            78: }
        !            79:
        !            80: /*
        !            81:  * given a file name, either find the buffer it uses, or create a new
        !            82:  * empty buffer to put it in.
        !            83:  */
        !            84: BUFFER *
        !            85: findbuffer(fname)
        !            86: char *fname;
        !            87: {
        !            88:        register BUFFER *bp;
        !            89:        char    bname[NBUFN], *cp;
        !            90:        unsigned count = 1;
        !            91:
        !            92:        for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
        !            93:                if (fncmp(bp->b_fname, fname) == 0)
        !            94:                        return bp;
        !            95:        }
        !            96:        makename(bname, fname);                 /* New buffer name.     */
        !            97:        cp = bname + strlen(bname);
        !            98:        while(bfind(bname, FALSE) != NULL) {
        !            99:                *cp = '<';              /* add "<count>" to then name   */
        !           100:                (VOID) strcpy(itos(cp, ++count)+1, ">");
        !           101:        }
        !           102:        return bfind(bname, TRUE);
        !           103: }
        !           104:
        !           105: /*
        !           106:  * Put the decimal representation of num into a buffer.  Hacked to be
        !           107:  * faster, smaller, and less general.
        !           108:  */
        !           109: static char *itos(bufp, num)
        !           110: char *bufp;
        !           111: unsigned num;
        !           112: {
        !           113:        if (num >= 10) {
        !           114:                bufp = itos(bufp, num/10);
        !           115:                num %= 10;
        !           116:        }
        !           117:        *++bufp = '0' + num;
        !           118:        return bufp;
        !           119: }
        !           120:
        !           121: /*
        !           122:  * Read the file "fname" into the current buffer.
        !           123:  * Make all of the text in the buffer go away, after checking
        !           124:  * for unsaved changes. This is called by the "read" command, the
        !           125:  * "visit" command, and the mainline (for "uemacs file").
        !           126:  */
        !           127: readin(fname) char *fname; {
        !           128:        register int            status;
        !           129:        register WINDOW         *wp;
        !           130:
        !           131:        if (bclear(curbp) != TRUE)              /* Might be old.        */
        !           132:                return TRUE;
        !           133:        status = insertfile(fname, fname, TRUE) ;
        !           134:        curbp->b_flag &= ~BFCHG;                /* No change.           */
        !           135:        for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
        !           136:                if (wp->w_bufp == curbp) {
        !           137:                        wp->w_dotp  = wp->w_linep = lforw(curbp->b_linep);
        !           138:                        wp->w_doto  = 0;
        !           139:                        wp->w_markp = NULL;
        !           140:                        wp->w_marko = 0;
        !           141:                }
        !           142:        }
        !           143:        return status;
        !           144: }
        !           145: /*
        !           146:  * NB, getting file attributes is done here under control of a flag
        !           147:  * rather than in readin, which would be cleaner.  I was concerned
        !           148:  * that some operating system might require the file to be open
        !           149:  * in order to get the information.  Similarly for writing.
        !           150:  */
        !           151:
        !           152: /*
        !           153:  * insert a file in the current buffer, after dot. Set mark
        !           154:  * at the end of the text inserted, point at the beginning.
        !           155:  * Return a standard status. Print a summary (lines read,
        !           156:  * error message) out as well. If the
        !           157:  * BACKUP conditional is set, then this routine also does the read
        !           158:  * end of backup processing. The BFBAK flag, if set in a buffer,
        !           159:  * says that a backup should be taken. It is set when a file is
        !           160:  * read in, but not on a new file (you don't need to make a backup
        !           161:  * copy of nothing).
        !           162:  */
        !           163: static char *line = NULL;
        !           164: static int linesize = 0;
        !           165:
        !           166: insertfile(fname, newname, needinfo) char fname[], newname[]; {
        !           167:        register LINE   *lp1;
        !           168:        register LINE   *lp2;
        !           169:        register WINDOW *wp;
        !           170:        int             nbytes;
        !           171:        LINE            *olp;                   /* Line we started at */
        !           172:        int             opos;                   /* and offset into it */
        !           173:        int             s, nline;
        !           174:        BUFFER          *bp;
        !           175:
        !           176:        if (line == NULL) {
        !           177:                line = malloc(NLINE);
        !           178:                linesize = NLINE;
        !           179:        }
        !           180:        bp = curbp;                             /* Cheap.               */
        !           181:        if (newname != (char *) NULL)
        !           182:                (VOID) strcpy(bp->b_fname, newname);
        !           183:        /* Hard file open.      */
        !           184:        if ((s=ffropen(fname, needinfo ? bp : (BUFFER *) NULL)) == FIOERR)
        !           185:                goto out;
        !           186:        if (s == FIOFNF) {                      /* File not found.      */
        !           187:                if (newname != NULL)
        !           188:                        ewprintf("(New file)");
        !           189:                else    ewprintf("(File not found)");
        !           190:                goto out;
        !           191:        }
        !           192:        opos = curwp->w_doto;
        !           193:        /* Open a new line, at point, and start inserting after it */
        !           194:        (VOID) lnewline();
        !           195:        olp = lback(curwp->w_dotp);
        !           196:        if(olp == curbp->b_linep) {
        !           197:                /* if at end of buffer, create a line to insert before */
        !           198:                (VOID) lnewline();
        !           199:                curwp->w_dotp = lback(curwp->w_dotp);
        !           200:        }
        !           201:        nline = 0;                      /* Don't count fake line at end */
        !           202:        while ((s=ffgetline(line, linesize, &nbytes)) != FIOERR) {
        !           203: doneread:
        !           204:            switch(s) {
        !           205:            case FIOSUC:
        !           206:                ++nline;
        !           207:                /* and continue */
        !           208:            case FIOEOF:        /* the last line of the file            */
        !           209:                if ((lp1=lalloc(nbytes)) == NULL) {
        !           210:                        s = FIOERR;             /* Keep message on the  */
        !           211:                        goto endoffile;         /* display.             */
        !           212:                }
        !           213:                bcopy(line, &ltext(lp1)[0], nbytes);
        !           214:                lp2 = lback(curwp->w_dotp);
        !           215:                lp2->l_fp = lp1;
        !           216:                lp1->l_fp = curwp->w_dotp;
        !           217:                lp1->l_bp = lp2;
        !           218:                curwp->w_dotp->l_bp = lp1;
        !           219:                if(s==FIOEOF) goto endoffile;
        !           220:                break;
        !           221:            case FIOLONG: {     /* a line to long to fit in our buffer  */
        !           222:                    char *cp;
        !           223:                    int newsize;
        !           224:
        !           225:                    newsize = linesize * 2;
        !           226:                    if(newsize < 0 ||
        !           227:                       (cp = malloc((unsigned)newsize)) == NULL) {
        !           228:                            ewprintf("Could not allocate %d bytes",
        !           229:                                    newsize);
        !           230:                            s = FIOERR;
        !           231:                            goto endoffile;
        !           232:                    }
        !           233:                    bcopy(line, cp, linesize);
        !           234:                    free(line);
        !           235:                    line = cp;
        !           236:                    s=ffgetline(line+linesize, linesize, &nbytes);
        !           237:                    nbytes += linesize;
        !           238:                    linesize = newsize;
        !           239:                    if (s == FIOERR)
        !           240:                        goto endoffile;
        !           241:                    goto doneread;
        !           242:                }
        !           243:            default:
        !           244:                ewprintf("Unknown code %d reading file", s);
        !           245:                s = FIOERR;
        !           246:                break;
        !           247:            }
        !           248:        }
        !           249: endoffile:
        !           250:        (VOID) ffclose((BUFFER *) NULL);        /* Ignore errors.       */
        !           251:        if (s==FIOEOF) {                        /* Don't zap an error.  */
        !           252:                if (nline == 1) ewprintf("(Read 1 line)");
        !           253:                else            ewprintf("(Read %d lines)", nline);
        !           254:        }
        !           255:        /* Set mark at the end of the text */
        !           256:        curwp->w_dotp = curwp->w_markp = lback(curwp->w_dotp);
        !           257:        curwp->w_marko = llength(curwp->w_markp);
        !           258:        (VOID) ldelnewline();
        !           259:        curwp->w_dotp = olp;
        !           260:        curwp->w_doto = opos;
        !           261:        if(olp == curbp->b_linep) curwp->w_dotp = lforw(olp);
        !           262: #ifndef NO_BACKUP
        !           263:        if (newname != NULL)
        !           264:                bp->b_flag |= BFCHG | BFBAK;    /* Need a backup.       */
        !           265:        else    bp->b_flag |= BFCHG;
        !           266: #else
        !           267:        bp->b_flag |= BFCHG;
        !           268: #endif
        !           269:        /* if the insert was at the end of buffer, set lp1 to the end of
        !           270:         * buffer line, and lp2 to the beginning of the newly inserted
        !           271:         * text.  (Otherwise lp2 is set to NULL.)  This is
        !           272:         * used below to set pointers in other windows correctly if they
        !           273:         * are also at the end of buffer.
        !           274:         */
        !           275:        lp1 = bp->b_linep;
        !           276:        if (curwp->w_markp == lp1) {
        !           277:                lp2 = curwp->w_dotp;
        !           278:        } else {
        !           279:                (VOID) ldelnewline();           /* delete extranious newline */
        !           280: out:           lp2 = NULL;
        !           281:        }
        !           282:        for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
        !           283:                if (wp->w_bufp == curbp) {
        !           284:                        wp->w_flag |= WFMODE|WFEDIT;
        !           285:                        if (wp != curwp && lp2 != NULL) {
        !           286:                                if (wp->w_dotp == lp1)  wp->w_dotp  = lp2;
        !           287:                                if (wp->w_markp == lp1) wp->w_markp = lp2;
        !           288:                                if (wp->w_linep == lp1) wp->w_linep = lp2;
        !           289:                        }
        !           290:                }
        !           291:        }
        !           292:        return s != FIOERR;                     /* False if error.      */
        !           293: }
        !           294:
        !           295: /*
        !           296:  * Take a file name, and from it
        !           297:  * fabricate a buffer name. This routine knows
        !           298:  * about the syntax of file names on the target system.
        !           299:  * BDC1                left scan delimiter.
        !           300:  * BDC2                optional second left scan delimiter.
        !           301:  * BDC3                optional right scan delimiter.
        !           302:  */
        !           303: VOID
        !           304: makename(bname, fname) char bname[]; char fname[]; {
        !           305:        register char   *cp1;
        !           306:        register char   *cp2;
        !           307:
        !           308:        cp1 = &fname[0];
        !           309:        while (*cp1 != 0)
        !           310:                ++cp1;
        !           311:        --cp1;                  /* insure at least 1 character ! */
        !           312: #ifdef BDC2
        !           313:        while (cp1!=&fname[0] && cp1[-1]!=BDC1 && cp1[-1]!=BDC2)
        !           314:                --cp1;
        !           315: #else
        !           316:        while (cp1!=&fname[0] && cp1[-1]!=BDC1)
        !           317:                --cp1;
        !           318: #endif
        !           319:        cp2 = &bname[0];
        !           320: #ifdef BDC3
        !           321:        while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=BDC3)
        !           322:                *cp2++ = *cp1++;
        !           323: #else
        !           324:        while (cp2!=&bname[NBUFN-1] && *cp1!=0)
        !           325:                *cp2++ = *cp1++;
        !           326: #endif
        !           327:        *cp2 = 0;
        !           328: }
        !           329:
        !           330: /*
        !           331:  * Ask for a file name, and write the
        !           332:  * contents of the current buffer to that file.
        !           333:  * Update the remembered file name and clear the
        !           334:  * buffer changed flag. This handling of file names
        !           335:  * is different from the earlier versions, and
        !           336:  * is more compatable with Gosling EMACS than
        !           337:  * with ITS EMACS.
        !           338:  */
        !           339: /*ARGSUSED*/
        !           340: filewrite(f, n)
        !           341: {
        !           342:        register int    s;
        !           343:        char            fname[NFILEN];
        !           344:        char            *adjfname;
        !           345:
        !           346:        if ((s=eread("Write file: ", fname, NFILEN,
        !           347:                      EFNEW|EFCR|EFFILE)) != TRUE)
        !           348:                return (s);
        !           349:        adjfname = adjustname(fname);
        !           350:        /* old attributes are no longer current */
        !           351:        bzero(&curbp->b_fi, sizeof(curbp->b_fi));
        !           352:        if ((s=writeout(curbp, adjfname)) == TRUE) {
        !           353:                (VOID) strcpy(curbp->b_fname, adjfname);
        !           354: #ifndef NO_BACKUP
        !           355:                curbp->b_flag &= ~(BFBAK | BFCHG);
        !           356: #else
        !           357:                curbp->b_flag &= ~BFCHG;
        !           358: #endif
        !           359:                upmodes(curbp);
        !           360:        }
        !           361:        return s;
        !           362: }
        !           363:
        !           364: /*
        !           365:  * Save the contents of the current buffer back into
        !           366:  * its associated file.
        !           367:  */
        !           368: #ifndef NO_BACKUP
        !           369: #ifndef        MAKEBACKUP
        !           370: #define        MAKEBACKUP TRUE
        !           371: #endif
        !           372: static int     makebackup = MAKEBACKUP;
        !           373: #endif
        !           374:
        !           375: /*ARGSUSED*/
        !           376: filesave(f, n)
        !           377: {
        !           378:        return buffsave(curbp);
        !           379: }
        !           380:
        !           381: /*
        !           382:  * Save the contents of the buffer argument into its associated file.
        !           383:  * Do nothing if there have been no changes
        !           384:  * (is this a bug, or a feature). Error if there is no remembered
        !           385:  * file name. If this is the first write since the read or visit,
        !           386:  * then a backup copy of the file is made.
        !           387:  * Allow user to select whether or not to make backup files
        !           388:  * by looking at the value of makebackup.
        !           389:  */
        !           390: buffsave(bp) BUFFER *bp; {
        !           391:        register int    s;
        !           392:
        !           393:        if ((bp->b_flag&BFCHG) == 0)    {       /* Return, no changes.  */
        !           394:                ewprintf("(No changes need to be saved)");
        !           395:                return TRUE;
        !           396:        }
        !           397:        if (bp->b_fname[0] == '\0') {           /* Must have a name.    */
        !           398:                ewprintf("No file name");
        !           399:                return (FALSE);
        !           400:        }
        !           401: #ifndef NO_BACKUP
        !           402:        if (makebackup && (bp->b_flag&BFBAK)) {
        !           403:                s = fbackupfile(bp->b_fname);
        !           404:                if (s == ABORT)                 /* Hard error.          */
        !           405:                        return FALSE;
        !           406:                if (s == FALSE                  /* Softer error.        */
        !           407:                && (s=eyesno("Backup error, save anyway")) != TRUE)
        !           408:                        return s;
        !           409:        }
        !           410: #endif
        !           411:        if ((s=writeout(bp, bp->b_fname)) == TRUE) {
        !           412: #ifndef NO_BACKUP
        !           413:                bp->b_flag &= ~(BFCHG | BFBAK);
        !           414: #else
        !           415:                bp->b_flag &= ~BFCHG;
        !           416: #endif
        !           417:                upmodes(bp);
        !           418:        }
        !           419:        return s;
        !           420: }
        !           421:
        !           422: #ifndef NO_BACKUP
        !           423: /* Since we don't have variables (we probably should)
        !           424:  * this is a command processor for changing the value of
        !           425:  * the make backup flag.  If no argument is given,
        !           426:  * sets makebackup to true, so backups are made.  If
        !           427:  * an argument is given, no backup files are made when
        !           428:  * saving a new version of a file. Only used when BACKUP
        !           429:  * is #defined.
        !           430:  */
        !           431: /*ARGSUSED*/
        !           432: makebkfile(f, n)
        !           433: {
        !           434:        if(f & FFARG) makebackup = n > 0;
        !           435:        else makebackup = !makebackup;
        !           436:        ewprintf("Backup files %sabled", makebackup ? "en" : "dis");
        !           437:        return TRUE;
        !           438: }
        !           439: #endif
        !           440:
        !           441: /*
        !           442:  * NB: bp is passed to both ffwopen and ffclose because some
        !           443:  * attribute information may need to be updated at open time
        !           444:  * and others after the close.  This is OS-dependent.  Note
        !           445:  * that the ff routines are assumed to be able to tell whether
        !           446:  * the attribute information has been set up in this buffer
        !           447:  * or not.
        !           448:  */
        !           449:
        !           450: /*
        !           451:  * This function performs the details of file
        !           452:  * writing; writing the file in buffer bp to
        !           453:  * file fn. Uses the file management routines
        !           454:  * in the "fileio.c" package. Most of the grief
        !           455:  * is checking of some sort.
        !           456:  */
        !           457: writeout(bp, fn) register BUFFER *bp; char *fn; {
        !           458:        register int    s;
        !           459:
        !           460:        if ((s=ffwopen(fn,bp)) != FIOSUC)       /* Open writes message. */
        !           461:                return (FALSE);
        !           462:        s = ffputbuf(bp);
        !           463:        if (s == FIOSUC) {                      /* No write error.      */
        !           464:                s = ffclose(bp);
        !           465:                if (s==FIOSUC)
        !           466:                        ewprintf("Wrote %s", fn);
        !           467:        } else                                  /* Ignore close error   */
        !           468:                (VOID) ffclose(bp);             /* if a write error.    */
        !           469:        return s == FIOSUC;
        !           470: }
        !           471:
        !           472: /*
        !           473:  * Tag all windows for bp (all windows if bp NULL) as needing their
        !           474:  * mode line updated.
        !           475:  */
        !           476: VOID
        !           477: upmodes(bp) register BUFFER *bp; {
        !           478:        register WINDOW *wp;
        !           479:
        !           480:        for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
        !           481:                if (bp == NULL || curwp->w_bufp == bp) wp->w_flag |= WFMODE;
        !           482: }