[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.2

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;
1.2     ! millert    62:        register MGWIN *wp;
1.1       deraadt    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;
1.2     ! millert   129:        register MGWIN          *wp;
1.1       deraadt   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;
1.2     ! millert   169:        register MGWIN *wp;
1.1       deraadt   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; {
1.2     ! millert   478:        register MGWIN *wp;
1.1       deraadt   479:
                    480:        for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
                    481:                if (bp == NULL || curwp->w_bufp == bp) wp->w_flag |= WFMODE;
                    482: }