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, <ext(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: }