|
|
1.1 ! root 1: /* ! 2: * The routines in this file handle the reading and writing of disk files. ! 3: * All of details about the reading and writing of the disk are in "fileio.c". ! 4: */ ! 5: #include <stdio.h> ! 6: #include "ed.h" ! 7: ! 8: /* ! 9: * Read a file into the current buffer. ! 10: * This is really easy; all you do it find the name of the file and call ! 11: * the standard "read a file into the current buffer" code. ! 12: * Bound to "C-X C-R". ! 13: */ ! 14: fileread(f, n) ! 15: { ! 16: register int s; ! 17: uchar fname[NFILEN]; ! 18: ! 19: if ((s=mlreply("Read file: ", fname, NFILEN)) != TRUE) ! 20: return (s); ! 21: #if GEM ! 22: fixname(fname); ! 23: #endif ! 24: return (readin(fname)); ! 25: } ! 26: ! 27: /* ! 28: * Select a file for editing. ! 29: * Look around to see if you can find the file in another buffer; ! 30: * if you can find it just switch to the buffer. If you cannot find ! 31: * the file, create a new buffer, read in the text, and switch to the ! 32: * new buffer. ! 33: * Bound to C-X C-V. ! 34: */ ! 35: filevisit(f, n) ! 36: { ! 37: uchar fname[NFILEN]; ! 38: int s; ! 39: ! 40: if ((s=mlreply("Visit file: ", fname, NFILEN)) != TRUE) ! 41: return (s); ! 42: #if GEM ! 43: fixname(fname); ! 44: #endif ! 45: return visitfile(fname); ! 46: } ! 47: ! 48: /* Real file visit routine... */ ! 49: visitfile(fname) ! 50: uchar fname[]; ! 51: { ! 52: register BUFFER *bp; ! 53: register WINDOW *wp; ! 54: register LINE *lp; ! 55: register int i; ! 56: register int s; ! 57: uchar bname[NBUFN]; ! 58: ! 59: for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) { ! 60: if ((bp->b_flag&BFTEMP)==0 && strcmp(bp->b_fname, fname)==0) { ! 61: if (--curbp->b_nwnd == 0) { ! 62: curbp->b_dotp = curwp->w_dotp; ! 63: curbp->b_doto = curwp->w_doto; ! 64: curbp->b_markp = curwp->w_markp; ! 65: curbp->b_marko = curwp->w_marko; ! 66: } ! 67: curbp = bp; ! 68: curwp->w_bufp = bp; ! 69: if (bp->b_nwnd++ == 0) { ! 70: curwp->w_dotp = bp->b_dotp; ! 71: curwp->w_doto = bp->b_doto; ! 72: curwp->w_markp = bp->b_markp; ! 73: curwp->w_marko = bp->b_marko; ! 74: } else { ! 75: wp = wheadp; ! 76: while (wp != NULL) { ! 77: if (wp!=curwp && wp->w_bufp==bp) { ! 78: curwp->w_dotp = wp->w_dotp; ! 79: curwp->w_doto = wp->w_doto; ! 80: curwp->w_markp = wp->w_markp; ! 81: curwp->w_marko = wp->w_marko; ! 82: break; ! 83: } ! 84: wp = wp->w_wndp; ! 85: } ! 86: } ! 87: lp = curwp->w_dotp; ! 88: i = curwp->w_ntrows/2; ! 89: while (i-- && lback(lp)!=curbp->b_linep) ! 90: lp = lback(lp); ! 91: curwp->w_linep = lp; ! 92: curwp->w_flag |= WFMODE|WFHARD; ! 93: mlwrite("[Old buffer]"); ! 94: return (TRUE); ! 95: } ! 96: } ! 97: makename(bname, fname); /* New buffer name. */ ! 98: while ((bp=bfind(bname, FALSE, 0)) != NULL) { ! 99: s = mlreply("Buffer name: ", bname, NBUFN); ! 100: #if GEM ! 101: fixname(bname); ! 102: #endif ! 103: if (s == ABORT) /* ^G to just quit */ ! 104: return (s); ! 105: if (s == FALSE) { /* CR to clobber it */ ! 106: makename(bname, fname); ! 107: break; ! 108: } ! 109: } ! 110: if (bp==NULL && (bp=bfind(bname, TRUE, 0))==NULL) { ! 111: mlwrite("Cannot create buffer"); ! 112: return (FALSE); ! 113: } ! 114: if (--curbp->b_nwnd == 0) { /* Undisplay. */ ! 115: curbp->b_dotp = curwp->w_dotp; ! 116: curbp->b_doto = curwp->w_doto; ! 117: curbp->b_markp = curwp->w_markp; ! 118: curbp->b_marko = curwp->w_marko; ! 119: } ! 120: curbp = bp; /* Switch to it. */ ! 121: curwp->w_bufp = bp; ! 122: curbp->b_nwnd++; ! 123: return (readin(fname)); /* Read it in. */ ! 124: } ! 125: ! 126: /* ! 127: * Read file "fname" into the current buffer, blowing away any text found ! 128: * there. Called by both the read and visit commands. Return the final ! 129: * status of the read. Also called by the mainline, to read in a file ! 130: * specified on the command line as an argument. ! 131: */ ! 132: readin(fname) ! 133: uchar fname[]; ! 134: { ! 135: register LINE *lp1; ! 136: register LINE *lp2; ! 137: register int i; ! 138: register WINDOW *wp; ! 139: register BUFFER *bp; ! 140: register int s; ! 141: register int nbytes; ! 142: register int nline; ! 143: uchar line[NLINE]; ! 144: ! 145: mlwrite(" "); ! 146: bp = curbp; /* Cheap. */ ! 147: if ((s=bclear(bp)) != TRUE) /* Might be old. */ ! 148: return (s); ! 149: bp->b_flag &= ~(BFTEMP|BFCHG|BFTRUNC); ! 150: strcpy(bp->b_fname, fname); ! 151: switch (s=ffropen(fname)) { /* file open */ ! 152: case FIOERR: /* file exists but cannot read */ ! 153: mlwrite("[Cannot read %s]", fname); ! 154: goto out; ! 155: case FIOFNF: /* File not found. */ ! 156: mlwrite("[New file: %s]", fname); ! 157: goto out; ! 158: } ! 159: mlwrite("[Reading file %s]", fname); ! 160: nline = 0; ! 161: while ((s=ffgetline(line, NLINE)) == FIOSUC) { ! 162: nbytes = strlen(line); ! 163: if ((lp1=lalloc(nbytes)) == NULL) { ! 164: mlwrite("File too large for available memory!"); ! 165: bp->b_flag |= BFTRUNC; /* Mark buffer truncated */ ! 166: s = FIOERR; /* Keep message on the */ ! 167: break; /* display. */ ! 168: } ! 169: lp2 = lback(curbp->b_linep); ! 170: lforw(lp2) = lp1; ! 171: lforw(lp1) = curbp->b_linep; ! 172: lback(lp1) = lp2; ! 173: lback(curbp->b_linep) = lp1; ! 174: lp1->l_lnumber = ++nline; ! 175: #ifdef SLOW ! 176: for (i=0; i<nbytes; ++i) ! 177: lputc(lp1, i, line[i]); ! 178: #else ! 179: strncpy(lp1->l_text, line, nbytes); ! 180: #endif ! 181: } ! 182: ffclose(); /* Ignore errors. */ ! 183: if (s == FIOEOF) { /* Don't zap message! */ ! 184: if (nline == 1) ! 185: mlwrite("[Read 1 line]"); ! 186: else ! 187: mlwrite("[Read %d lines]", nline); ! 188: } ! 189: out: ! 190: for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) { ! 191: if (wp->w_bufp == curbp) { ! 192: wp->w_linep = lforw(curbp->b_linep); ! 193: wp->w_dotp = lforw(curbp->b_linep); ! 194: wp->w_doto = 0; ! 195: wp->w_markp = NULL; ! 196: wp->w_marko = 0; ! 197: wp->w_flag |= WFMODE|WFHARD; ! 198: } ! 199: } ! 200: if (s == FIOERR) /* False if error. */ ! 201: return (FALSE); ! 202: return (TRUE); ! 203: } ! 204: ! 205: /* ! 206: * Take a file name, and from it fabricate a buffer name. ! 207: * This routine knows about the syntax of file names on the target system. ! 208: * I suppose that this information could be put in a better place than a ! 209: * line of code. ! 210: */ ! 211: makename(bname, fname) ! 212: uchar bname[]; ! 213: uchar fname[]; ! 214: { ! 215: register uchar *cp1; ! 216: register uchar *cp2; ! 217: ! 218: cp1 = &fname[0]; ! 219: while (*cp1 != 0) ! 220: ++cp1; ! 221: #if VMS ! 222: while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!=']') ! 223: --cp1; ! 224: #endif ! 225: #if CPM ! 226: while (cp1!=&fname[0] && cp1[-1]!=':') ! 227: --cp1; ! 228: #endif ! 229: #if MSDOS || GEM ! 230: while (cp1!=&fname[0] && cp1[-1]!=':' && cp1[-1]!='\\') ! 231: --cp1; ! 232: #endif ! 233: #if V7 ! 234: while (cp1!=&fname[0] && cp1[-1]!='/') ! 235: --cp1; ! 236: #endif ! 237: cp2 = &bname[0]; ! 238: while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') ! 239: *cp2++ = *cp1++; ! 240: *cp2 = 0; ! 241: } ! 242: ! 243: /* ! 244: * Ask for a file name, and write the contents of the current buffer to ! 245: * that file. Update the remembered file name and clear the buffer changed ! 246: * flag. This handling of file names is different from the earlier versions, ! 247: * and is more compatable with Gosling EMACS than with ITS EMACS. ! 248: * Bound to "C-X C-W". ! 249: */ ! 250: filewrite(f, n) ! 251: { ! 252: register WINDOW *wp; ! 253: register int s; ! 254: uchar fname[NFILEN]; ! 255: ! 256: if ((s=mlreply("Write file: ", fname, NFILEN)) != TRUE) ! 257: return (s); ! 258: #if GEM ! 259: fixname(fname); ! 260: #endif ! 261: if ((s=writeout(fname)) == TRUE) { ! 262: strcpy(curbp->b_fname, fname); ! 263: curbp->b_flag &= ~BFCHG; ! 264: wp = wheadp; /* Update mode lines. */ ! 265: while (wp != NULL) { ! 266: if (wp->w_bufp == curbp) ! 267: wp->w_flag |= WFMODE; ! 268: wp = wp->w_wndp; ! 269: } ! 270: } ! 271: return (s); ! 272: } ! 273: ! 274: /* ! 275: * Save the contents of the current buffer in its associatd file. No nothing ! 276: * if nothing has changed (this may be a bug, not a feature). Error if there is ! 277: * no remembered file name for the buffer. Bound to "C-X C-S". ! 278: * May get called by "C-Z". ! 279: */ ! 280: filesave(f, n) ! 281: { ! 282: register WINDOW *wp; ! 283: register int s; ! 284: ! 285: if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */ ! 286: return (TRUE); ! 287: if (curbp->b_fname[0] == 0) { /* Must have a name. */ ! 288: mlwrite("No file name"); ! 289: return (FALSE); ! 290: } ! 291: if ((curbp->b_flag & BFTRUNC) != 0) { /* If file was truncated... */ ! 292: if (mlyesno("File was truncated -- write it anyway") != TRUE) ! 293: return (FALSE); ! 294: } ! 295: if ((s=writeout(curbp->b_fname)) == TRUE) { ! 296: curbp->b_flag &= ~(BFCHG|BFTRUNC); ! 297: wp = wheadp; /* Update mode lines. */ ! 298: while (wp != NULL) { ! 299: if (wp->w_bufp == curbp) ! 300: wp->w_flag |= WFMODE; ! 301: wp = wp->w_wndp; ! 302: } ! 303: } ! 304: return (s); ! 305: } ! 306: ! 307: /* ! 308: * This function performs the details of file writing. ! 309: * Uses the file management routines in the "fileio.c" package. ! 310: * The number of lines written is displayed. Sadly, it looks inside a LINE; ! 311: * provide a macro for this. Most of the grief is error checking of some sort. ! 312: */ ! 313: writeout(fn) ! 314: uchar *fn; ! 315: { ! 316: register int s; ! 317: register LINE *lp; ! 318: register int nline; ! 319: ! 320: if ((s=ffwopen(fn, "w")) != FIOSUC) /* Open writes message. */ ! 321: return (FALSE); ! 322: lp = lforw(curbp->b_linep); /* First line. */ ! 323: nline = 0; /* Number of lines. */ ! 324: while (lp != curbp->b_linep) { ! 325: if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC) ! 326: break; ! 327: ++nline; ! 328: lp = lforw(lp); ! 329: } ! 330: if (s == FIOSUC) { /* No write error. */ ! 331: s = ffclose(); ! 332: if (s == FIOSUC) { /* No close error. */ ! 333: curbp->b_flag |= BFWRITE; /* Written... */ ! 334: if (nline == 1) ! 335: mlwrite("[Wrote 1 line]"); ! 336: else ! 337: mlwrite("[Wrote %d lines]", nline); ! 338: } ! 339: } else /* Ignore close error */ ! 340: ffclose(); /* if a write error. */ ! 341: ! 342: sync(); /* protect filesystem */ ! 343: ! 344: if (s != FIOSUC) /* Some sort of error. */ ! 345: return (FALSE); ! 346: return (TRUE); ! 347: } ! 348: ! 349: /* ! 350: * The command allows the user to modify the file name associated with ! 351: * the current buffer. It is like the "f" command in UNIX "ed". ! 352: * The operation is simple; just zap the name in the BUFFER structure, ! 353: * and mark the windows as needing an update. You can type a blank line at ! 354: * the prompt if you wish. ! 355: */ ! 356: filename(f, n) ! 357: { ! 358: register WINDOW *wp; ! 359: register int s; ! 360: uchar fname[NFILEN]; ! 361: ! 362: if ((s=mlreply("Name: ", fname, NFILEN)) == ABORT) ! 363: return (s); ! 364: #if GEM ! 365: fixname(fname); ! 366: #endif ! 367: if (s == FALSE) ! 368: strcpy(curbp->b_fname, ""); ! 369: else ! 370: strcpy(curbp->b_fname, fname); ! 371: wp = wheadp; /* Update mode lines. */ ! 372: while (wp != NULL) { ! 373: if (wp->w_bufp == curbp) ! 374: wp->w_flag |= WFMODE; ! 375: wp = wp->w_wndp; ! 376: } ! 377: return (TRUE); ! 378: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.