|
|
1.1 ! root 1: /* ! 2: * Buffer management. ! 3: * Some of the functions are internal and some are actually attached to user ! 4: * keys. Like everyone else, they set hints for the display system. ! 5: */ ! 6: #include <stdio.h> ! 7: #include "ed.h" ! 8: ! 9: /* ! 10: * Attach a buffer to a window. The values of dot and mark come from the buffer ! 11: * if the use count is 0. Otherwise, they come from some other window. ! 12: */ ! 13: usebuffer(f, n) ! 14: { ! 15: register BUFFER *bp; ! 16: register WINDOW *wp; ! 17: register int s; ! 18: uchar bufn[NBUFN]; ! 19: ! 20: if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE) ! 21: return (s); ! 22: #if GEM ! 23: fixname(bufn); ! 24: #endif ! 25: if ((bp=bfind(bufn, TRUE, 0)) == NULL) ! 26: return (FALSE); ! 27: if (--curbp->b_nwnd == 0) { /* Last use. */ ! 28: curbp->b_dotp = curwp->w_dotp; ! 29: curbp->b_doto = curwp->w_doto; ! 30: curbp->b_markp = curwp->w_markp; ! 31: curbp->b_marko = curwp->w_marko; ! 32: } ! 33: curbp = bp; /* Switch. */ ! 34: curwp->w_bufp = bp; ! 35: curwp->w_linep = bp->b_linep; /* For macros, ignored. */ ! 36: curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */ ! 37: if (bp->b_nwnd++ == 0) { /* First use. */ ! 38: curwp->w_dotp = bp->b_dotp; ! 39: curwp->w_doto = bp->b_doto; ! 40: curwp->w_markp = bp->b_markp; ! 41: curwp->w_marko = bp->b_marko; ! 42: return (TRUE); ! 43: } ! 44: wp = wheadp; /* Look for old. */ ! 45: while (wp != NULL) { ! 46: if (wp!=curwp && wp->w_bufp==bp) { ! 47: curwp->w_dotp = wp->w_dotp; ! 48: curwp->w_doto = wp->w_doto; ! 49: curwp->w_markp = wp->w_markp; ! 50: curwp->w_marko = wp->w_marko; ! 51: break; ! 52: } ! 53: wp = wp->w_wndp; ! 54: } ! 55: return (TRUE); ! 56: } ! 57: ! 58: /* ! 59: * Dispose of a buffer, by name. ! 60: * Ask for the name. Look it up (don't get too upset if it isn't there at ! 61: * all!). Get quite upset if the buffer is the current buffer. If it is ! 62: * displayed, make sure the user wants it gone, and if (s)he does, delete ! 63: * the windows associated with it as well. ! 64: * Clear the buffer (ask if the buffer has been changed). Then free the header ! 65: * line and the buffer header. Bound to "C-X K". ! 66: */ ! 67: killbuffer(f, n) ! 68: { ! 69: register BUFFER *bp; ! 70: register BUFFER *bp1; ! 71: register BUFFER *bp2; ! 72: register int s; ! 73: uchar bufn[NBUFN]; ! 74: ! 75: if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE) ! 76: return (s); ! 77: #if GEM ! 78: fixname(bufn); ! 79: #endif ! 80: if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */ ! 81: return (TRUE); ! 82: if (bp->b_nwnd != 0) { /* If on screen. */ ! 83: if (curbp == bp) { ! 84: mlwrite("Buffer is current buffer"); ! 85: return (FALSE); ! 86: } else { ! 87: if ((s = mlyesno("Buffer is displayed: Really kill")) ! 88: != TRUE) ! 89: return (FALSE); ! 90: } ! 91: } ! 92: if ((s=bclear(bp)) != TRUE) /* Blow text away. */ ! 93: return (s); ! 94: while (bp->b_nwnd != 0) /* Blow windows away. */ ! 95: zapbwind(bp); ! 96: free((char *) bp->b_linep); /* Release header line. */ ! 97: bp1 = NULL; /* Find the header. */ ! 98: bp2 = bheadp; ! 99: while (bp2 != bp) { ! 100: bp1 = bp2; ! 101: bp2 = bp2->b_bufp; ! 102: } ! 103: bp2 = bp2->b_bufp; /* Next one in chain. */ ! 104: if (bp1 == NULL) /* Unlink it. */ ! 105: bheadp = bp2; ! 106: else ! 107: bp1->b_bufp = bp2; ! 108: free((char *) bp); /* Release buffer block */ ! 109: return (TRUE); ! 110: } ! 111: ! 112: /* ! 113: * List all of the active buffers. First update the special buffer that ! 114: * holds the list. Next make sure at least 1 window is displaying the ! 115: * buffer list, splitting the screen if this is what it takes. ! 116: * Lastly, repaint all of the windows that are displaying the list. ! 117: * Bound to "C-X C-B". ! 118: */ ! 119: listbuffers(f, n) ! 120: { ! 121: register WINDOW *wp; ! 122: register BUFFER *bp; ! 123: register int s; ! 124: ! 125: if ((s=makelist()) != TRUE) ! 126: return (s); ! 127: if (blistp->b_nwnd == 0) { /* Not on screen yet. */ ! 128: if ((wp=wpopup()) == NULL) ! 129: return (FALSE); ! 130: bp = wp->w_bufp; ! 131: if (--bp->b_nwnd == 0) { ! 132: bp->b_dotp = wp->w_dotp; ! 133: bp->b_doto = wp->w_doto; ! 134: bp->b_markp = wp->w_markp; ! 135: bp->b_marko = wp->w_marko; ! 136: } ! 137: wp->w_bufp = blistp; ! 138: ++blistp->b_nwnd; ! 139: } ! 140: wp = wheadp; ! 141: while (wp != NULL) { ! 142: if (wp->w_bufp == blistp) { ! 143: wp->w_linep = lforw(blistp->b_linep); ! 144: wp->w_dotp = lforw(blistp->b_linep); ! 145: wp->w_doto = 0; ! 146: wp->w_markp = NULL; ! 147: wp->w_marko = 0; ! 148: wp->w_flag |= WFMODE|WFHARD; ! 149: } ! 150: wp = wp->w_wndp; ! 151: } ! 152: return (TRUE); ! 153: } ! 154: ! 155: /* ! 156: * This routine rebuilds the text in the special secret buffer that holds ! 157: * the buffer list. It is called by the list buffers command. Return TRUE ! 158: * if everything works. Return FALSE if there is an error ! 159: * (if there is no memory). ! 160: */ ! 161: makelist() ! 162: { ! 163: register uchar *cp1; ! 164: register uchar *cp2; ! 165: register BUFFER *bp; ! 166: register LINE *lp; ! 167: register long nlines; ! 168: register long nbytes; ! 169: register int c; ! 170: uchar b[6+1]; ! 171: uchar line[128]; ! 172: ! 173: blistp->b_flag &= ~BFCHG; /* Don't complain! */ ! 174: if ((c=bclear(blistp)) != TRUE) /* Blow old text away */ ! 175: return (c); ! 176: strcpy(blistp->b_fname, ""); ! 177: if (addline(blistp, "C Size Lines Buffer File") == FALSE ! 178: || addline(blistp,"- ---- ----- ------ ----") == FALSE) ! 179: return (FALSE); ! 180: bp = bheadp; /* For all buffers */ ! 181: while (bp != NULL) { ! 182: if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones. */ ! 183: bp = bp->b_bufp; ! 184: continue; ! 185: } ! 186: cp1 = &line[0]; /* Start at left edge */ ! 187: if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */ ! 188: *cp1++ = '*'; ! 189: else ! 190: *cp1++ = ' '; ! 191: *cp1++ = ' '; /* Gap. */ ! 192: nbytes = 0; /* Count bytes in buf. */ ! 193: nlines = 0; /* Count lines in buf. */ ! 194: lp = lforw(bp->b_linep); ! 195: while (lp != bp->b_linep) { ! 196: nlines++; ! 197: nbytes += llength(lp)+1; ! 198: lp = lforw(lp); ! 199: } ! 200: ltoa(b, 6, nbytes); /* 6 digit buffer size. */ ! 201: cp2 = &b[0]; ! 202: while ((c = *cp2++) != 0) ! 203: *cp1++ = c; ! 204: *cp1++ = ' '; /* Gap. */ ! 205: ltoa(b, 6, nlines); /* 6 digit # of lines */ ! 206: cp2 = &b[0]; ! 207: while ((c = *cp2++) != 0) ! 208: *cp1++ = c; ! 209: *cp1++ = ' '; /* Gap. */ ! 210: cp2 = &bp->b_bname[0]; /* Buffer name */ ! 211: while ((c = *cp2++) != 0) ! 212: *cp1++ = c; ! 213: cp2 = &bp->b_fname[0]; /* File name */ ! 214: if (*cp2 != 0) { ! 215: while (cp1 < &line[1+1+6+1+6+1+NBUFN+1]) ! 216: *cp1++ = ' '; ! 217: while ((c = *cp2++) != 0) { ! 218: if (cp1 < &line[128-1]) ! 219: *cp1++ = c; ! 220: } ! 221: } ! 222: *cp1 = 0; /* Add to the buffer. */ ! 223: if (addline(blistp,line) == FALSE) ! 224: return (FALSE); ! 225: bp = bp->b_bufp; ! 226: } ! 227: return (TRUE); /* All done */ ! 228: } ! 229: ! 230: ltoa(buf, width, num) ! 231: register uchar buf[]; ! 232: register int width; ! 233: register long num; ! 234: { ! 235: buf[width] = 0; /* End of string. */ ! 236: while (num >= 10) { /* Conditional digits. */ ! 237: buf[--width] = (num%10) + '0'; ! 238: num /= 10; ! 239: } ! 240: buf[--width] = num + '0'; /* Always 1 digit. */ ! 241: while (width != 0) /* Pad with blanks. */ ! 242: buf[--width] = ' '; ! 243: } ! 244: ! 245: /* ! 246: * The argument "text" points to a string. Append this line to the buffer ! 247: * specified. Handcraft the EOL on the end. Return TRUE if it worked and ! 248: * FALSE if you ran out of room. ! 249: */ ! 250: addline(bp, text) ! 251: register BUFFER *bp; ! 252: uchar *text; ! 253: { ! 254: register LINE *lp; ! 255: register int i; ! 256: register int ntext; ! 257: ! 258: ntext = strlen(text); ! 259: if ((lp=lalloc(ntext)) == NULL) ! 260: return (FALSE); ! 261: for (i=0; i<ntext; ++i) ! 262: lputc(lp, i, text[i]); ! 263: lforw(lback(bp->b_linep)) = lp; /* Hook onto the end */ ! 264: lp->l_bp = bp->b_linep->l_bp; ! 265: bp->b_linep->l_bp = lp; ! 266: lforw(lp) = bp->b_linep; ! 267: if (bp->b_dotp == bp->b_linep) /* If "." is at the end */ ! 268: bp->b_dotp = lp; /* move it to new line */ ! 269: return (TRUE); ! 270: } ! 271: ! 272: /* ! 273: * Look through the list of buffers. Return TRUE if there are any changed ! 274: * buffers. Buffers that hold magic internal stuff are not considered; ! 275: * who cares if the list of buffer names is hacked. ! 276: * Return FALSE if no buffers have been changed. ! 277: */ ! 278: anycb() ! 279: { ! 280: register BUFFER *bp; ! 281: ! 282: bp = bheadp; ! 283: while (bp != NULL) { ! 284: if ((bp->b_flag&(BFTEMP|BFNOWRT|BFERROR))==0 ! 285: && (bp->b_flag&BFCHG)!=0) ! 286: return (TRUE); ! 287: bp = bp->b_bufp; ! 288: } ! 289: return (FALSE); ! 290: } ! 291: ! 292: /* ! 293: * Find a buffer, by name. Return a pointer to the BUFFER structure ! 294: * associated with it. If the named buffer is found, but is a TEMP buffer ! 295: * (like the buffer list) conplain. If the buffer is not found and the "cflag" ! 296: * is TRUE, create it. The "bflag" is the settings for the flags in in buffer. ! 297: */ ! 298: BUFFER *bfind(bname, cflag, bflag) ! 299: register uchar *bname; ! 300: { ! 301: register BUFFER *bp; ! 302: register LINE *lp; ! 303: ! 304: bp = bheadp; ! 305: while (bp != NULL) { ! 306: if (strcmp(bname, bp->b_bname) == 0) { ! 307: if ((bp->b_flag&BFTEMP) != 0) { ! 308: mlwrite("Cannot select builtin buffer"); ! 309: return (NULL); ! 310: } ! 311: return (bp); ! 312: } ! 313: bp = bp->b_bufp; ! 314: } ! 315: if (cflag != FALSE) { ! 316: if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) ! 317: return (NULL); ! 318: if ((lp=lalloc(0)) == NULL) { ! 319: free((char *) bp); ! 320: return (NULL); ! 321: } ! 322: bp->b_bufp = bheadp; ! 323: bheadp = bp; ! 324: bp->b_dotp = lp; ! 325: bp->b_doto = 0; ! 326: bp->b_markp = NULL; ! 327: bp->b_marko = 0; ! 328: bp->b_flag = bflag; ! 329: bp->b_nwnd = 0; ! 330: bp->b_linep = lp; ! 331: strcpy(bp->b_fname, ""); ! 332: strcpy(bp->b_bname, bname); ! 333: lforw(lp) = lp; ! 334: lp->l_bp = lp; ! 335: } ! 336: return (bp); ! 337: } ! 338: ! 339: /* ! 340: * This routine blows away all of the text in a buffer. If the buffer is ! 341: * marked as changed then we ask if it is ok to blow it away; this is ! 342: * to save the user the grief of losing text. The window chain is nearly ! 343: * always wrong if this gets called; the caller must arrange for the updates ! 344: * that are required. Return TRUE if everything looks good. ! 345: */ ! 346: bclear(bp) ! 347: register BUFFER *bp; ! 348: { ! 349: register LINE *lp; ! 350: register int s; ! 351: ! 352: if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */ ! 353: && (bp->b_flag&BFCHG) != 0 /* Something changed */ ! 354: && (s=mlyesno("Discard changes")) != TRUE) ! 355: return (s); ! 356: bp->b_flag &= ~BFCHG; /* Not changed */ ! 357: while ((lp=lforw(bp->b_linep)) != bp->b_linep) ! 358: lfree(lp); ! 359: bp->b_dotp = bp->b_linep; /* Fix "." */ ! 360: bp->b_doto = 0; ! 361: bp->b_markp = NULL; /* Invalidate "mark" */ ! 362: bp->b_marko = 0; ! 363: return (TRUE); ! 364: } ! 365: ! 366: #if LIBHELP ! 367: /* ! 368: * Put up a help window with the text pointed to by txt. ! 369: */ ! 370: helpwindow(tag) ! 371: uchar *tag; ! 372: { ! 373: register WINDOW *wp; ! 374: register BUFFER *bp; ! 375: register int s; ! 376: ! 377: if ((s=makehelp(tag)) != TRUE) { ! 378: while (helpbp->b_nwnd != 0) /* If on screen */ ! 379: zaphelp(0, 0); /* Delete windows */ ! 380: return (s); ! 381: } ! 382: if (helpbp->b_nwnd == 0) { /* Not on screen yet. */ ! 383: if ((wp=wpopup(helpbp)) == NULL) ! 384: return (FALSE); ! 385: bp = wp->w_bufp; ! 386: if (--bp->b_nwnd == 0) { ! 387: bp->b_dotp = wp->w_dotp; ! 388: bp->b_doto = wp->w_doto; ! 389: bp->b_markp = wp->w_markp; ! 390: bp->b_marko = wp->w_marko; ! 391: } ! 392: wp->w_bufp = helpbp; ! 393: ++helpbp->b_nwnd; ! 394: } ! 395: wp = wheadp; ! 396: while (wp != NULL) { ! 397: if (wp->w_bufp == helpbp) { ! 398: wp->w_linep = lforw(helpbp->b_linep); ! 399: wp->w_dotp = lforw(helpbp->b_linep); ! 400: wp->w_doto = 0; ! 401: wp->w_markp = NULL; ! 402: wp->w_marko = 0; ! 403: wp->w_flag |= WFMODE|WFHARD; ! 404: } ! 405: wp = wp->w_wndp; ! 406: } ! 407: return (TRUE); ! 408: } ! 409: ! 410: /* ! 411: * Service routine for help... ! 412: */ ! 413: addhelp(str) ! 414: uchar *str; ! 415: { ! 416: addline(helpbp, str); ! 417: } ! 418: ! 419: /* ! 420: * This routine rebuilds the text in the special secret buffer that holds ! 421: * the help. It is called by the help command. Return TRUE if ! 422: * everything works. Return FALSE if there is an error (if there is no memory ! 423: * or no help for the topic or file not found.) ! 424: */ ! 425: makehelp(tag) ! 426: uchar *tag; ! 427: { ! 428: extern uchar *helpfile; ! 429: register int c; ! 430: ! 431: helpbp->b_flag &= ~BFCHG; /* Don't complain! */ ! 432: if ((c=bclear(helpbp)) != TRUE) /* Blow old text away */ ! 433: return (c); ! 434: strcpy(helpbp->b_fname, tag); ! 435: ! 436: if ((c = help(tag, addhelp)) < 0) ! 437: mlwrite("[Can't open help file %s]", helpfile); ! 438: else if (c > 0) ! 439: mlwrite("[No help available for topic \"%s\"]", tag); ! 440: ! 441: return (c == 0); /* All done */ ! 442: } ! 443: ! 444: /* ! 445: * Put up a help window with an index of matching topics ! 446: */ ! 447: topicwindow(tag) ! 448: uchar *tag; ! 449: { ! 450: register WINDOW *wp; ! 451: register BUFFER *bp; ! 452: register int s; ! 453: ! 454: if ((s=makeindex(tag)) != TRUE) { ! 455: while (helpbp->b_nwnd != 0) /* If on screen */ ! 456: zaphelp(0, 0); /* Delete windows */ ! 457: return (s); ! 458: } ! 459: if (helpbp->b_nwnd == 0) { /* Not on screen yet. */ ! 460: if ((wp=wpopup(helpbp)) == NULL) ! 461: return (FALSE); ! 462: bp = wp->w_bufp; ! 463: if (--bp->b_nwnd == 0) { ! 464: bp->b_dotp = wp->w_dotp; ! 465: bp->b_doto = wp->w_doto; ! 466: bp->b_markp = wp->w_markp; ! 467: bp->b_marko = wp->w_marko; ! 468: } ! 469: wp->w_bufp = helpbp; ! 470: ++helpbp->b_nwnd; ! 471: } ! 472: wp = wheadp; ! 473: while (wp != NULL) { ! 474: if (wp->w_bufp == helpbp) { ! 475: wp->w_linep = lforw(helpbp->b_linep); ! 476: wp->w_dotp = lforw(helpbp->b_linep); ! 477: wp->w_doto = 0; ! 478: wp->w_markp = NULL; ! 479: wp->w_marko = 0; ! 480: wp->w_flag |= WFMODE|WFHARD; ! 481: } ! 482: wp = wp->w_wndp; ! 483: } ! 484: return (TRUE); ! 485: } ! 486: ! 487: /* ! 488: * This routine rebuilds the text in the special secret buffer that holds ! 489: * the help. It is called by the help command. Return TRUE if ! 490: * everything works. Return FALSE if there is an error (if there is no memory ! 491: * or no help for the topic or file not found.) ! 492: */ ! 493: makeindex(tag) ! 494: uchar *tag; ! 495: { ! 496: extern uchar *helpfile; ! 497: register int c; ! 498: ! 499: helpbp->b_flag &= ~BFCHG; /* Don't complain! */ ! 500: if ((c=bclear(helpbp)) != TRUE) /* Blow old text away */ ! 501: return (c); ! 502: strcpy(helpbp->b_fname, "index for "); ! 503: strcat(helpbp->b_fname, tag); ! 504: ! 505: if ((c = indexhelp(tag, addhelp)) < 0) ! 506: mlwrite("[Can't open help file %s]", helpfile); ! 507: else if (c > 0) ! 508: mlwrite("[No entries matching \"%s\"]", tag); ! 509: ! 510: return (c == 0); /* All done */ ! 511: } ! 512: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.