This is buffer.c in view mode; [Download] [Up]
/* BUFFER.C: buffer mgmt. routines MicroEMACS 3.10 * Buffer management. * Some of the functions are internal, * and some are actually attached to user * keys. Like everyone else, they set hints * for the display system. */ #include <stdio.h> #include "estruct.h" #include "etype.h" #include "edef.h" #include "elang.h" /* * Attach a buffer to a window. The * values of dot and mark come from the buffer * if the use count is 0. Otherwise, they come * from some other window. */ PASCAL NEAR usebuffer(f, n) { register BUFFER *bp; /* temporary buffer pointer */ /* get the buffer name to switch to */ bp = getdefb(); bp = getcbuf(TEXT24, bp ? bp->b_bname : "main", TRUE); /* "Use buffer" */ if (!bp) return(ABORT); /* make it invisable if there is an argument */ if (f == TRUE) bp->b_flag |= BFINVS; /* switch to it in any case */ return(swbuffer(bp)); } PASCAL NEAR nextbuffer(f, n) /* switch to the next buffer in the buffer list */ int f, n; /* default flag, numeric argument */ { register BUFFER *bp; /* current eligable buffer */ register int status; /* make sure the arg is legit */ if (f == FALSE) n = 1; if (n < 1) return(FALSE); /* cycle thru buffers until n runs out */ while (n-- > 0) { bp = getdefb(); if (bp == NULL) return(FALSE); status = swbuffer(bp); if (status != TRUE) return(status); } return(status); } PASCAL NEAR swbuffer(bp) /* make buffer BP current */ BUFFER *bp; { register WINDOW *wp; register int cmark; /* current mark */ /* let a user macro get hold of things...if he wants */ execkey(&exbhook, FALSE, 1); if (--curbp->b_nwnd == 0) { /* Last use. */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; for (cmark = 0; cmark < NMARKS; cmark++) { curbp->b_markp[cmark] = curwp->w_markp[cmark]; curbp->b_marko[cmark] = curwp->w_marko[cmark]; } curbp->b_fcol = curwp->w_fcol; } curbp = bp; /* Switch. */ if (curbp->b_active != TRUE) { /* buffer not active yet*/ /* read it in and activate it */ readin(curbp->b_fname, TRUE); curbp->b_dotp = lforw(curbp->b_linep); curbp->b_doto = 0; curbp->b_active = TRUE; } curwp->w_bufp = bp; curwp->w_linep = bp->b_linep; /* For macros, ignored. */ curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */ if (bp->b_nwnd++ == 0) { /* First use. */ curwp->w_dotp = bp->b_dotp; curwp->w_doto = bp->b_doto; for (cmark = 0; cmark < NMARKS; cmark++) { curwp->w_markp[cmark] = bp->b_markp[cmark]; curwp->w_marko[cmark] = bp->b_marko[cmark]; } curwp->w_fcol = bp->b_fcol; } else { wp = wheadp; /* Look for old */ while (wp != NULL) { if (wp!=curwp && wp->w_bufp==bp) { curwp->w_dotp = wp->w_dotp; curwp->w_doto = wp->w_doto; for (cmark = 0; cmark < NMARKS; cmark++) { curwp->w_markp[cmark] = wp->w_markp[cmark]; curwp->w_marko[cmark] = wp->w_marko[cmark]; } curwp->w_fcol = wp->w_fcol; break; } wp = wp->w_wndp; } } /* let a user macro get hold of things...if he wants */ execkey(&bufhook, FALSE, 1); return(TRUE); } /* * Dispose of a buffer, by name. * Ask for the name. Look it up (don't get too * upset if it isn't there at all!). Get quite upset * if the buffer is being displayed. Clear the buffer (ask * if the buffer has been changed). Then free the header * line and the buffer header. Bound to "C-X K". */ PASCAL NEAR killbuffer(f, n) { register BUFFER *bp; /* ptr to buffer to dump */ /* get the buffer name to kill */ bp = getdefb(); bp = getcbuf(TEXT26, bp ? bp->b_bname : "main", TRUE); /* "Kill buffer" */ if (bp == NULL) return(ABORT); return(zotbuf(bp)); } BUFFER *PASCAL NEAR getdefb() /* get the default buffer for a use or kill */ { BUFFER *bp; /* default buffer */ /* Find the next buffer, which will be the default */ bp = curbp->b_bufp; /* cycle through the buffers to find an eligable one */ while (bp == NULL || bp->b_flag & BFINVS) { if (bp == NULL) bp = bheadp; else bp = bp->b_bufp; /* don't get caught in an infinite loop! */ if (bp == curbp) { bp = NULL; break; } } return(bp); } PASCAL NEAR zotbuf(bp) /* kill the buffer pointed to by bp */ register BUFFER *bp; { register BUFFER *bp1; register BUFFER *bp2; register int s; if (bp->b_nwnd != 0) { /* Error if on screen. */ mlwrite(TEXT28); /* "Buffer is being displayed" */ return(FALSE); } if ((s=bclear(bp)) != TRUE) /* Blow text away. */ return(s); free((char *) bp->b_linep); /* Release header line. */ bp1 = NULL; /* Find the header. */ bp2 = bheadp; while (bp2 != bp) { bp1 = bp2; bp2 = bp2->b_bufp; } bp2 = bp2->b_bufp; /* Next one in chain. */ if (bp1 == NULL) /* Unlink it. */ bheadp = bp2; else bp1->b_bufp = bp2; free((char *) bp); /* Release buffer block */ return(TRUE); } PASCAL NEAR namebuffer(f,n) /* Rename the current buffer */ int f, n; /* default Flag & Numeric arg */ { register BUFFER *bp; /* pointer to scan through all buffers */ char bufn[NBUFN]; /* buffer to hold buffer name */ /* prompt for and get the new buffer name */ ask: if (mlreply(TEXT29, bufn, NBUFN) != TRUE) /* "Change buffer name to: " */ return(FALSE); /* and check for duplicates */ bp = bheadp; while (bp != NULL) { if (bp != curbp) { /* if the names the same */ if (strcmp(bufn, bp->b_bname) == 0) goto ask; /* try again */ } bp = bp->b_bufp; /* onward */ } strcpy(curbp->b_bname, bufn); /* copy buffer name to structure */ curwp->w_flag |= WFMODE; /* make mode line replot */ mlerase(); return(TRUE); } /* List all of the active buffers. First update the special buffer that holds the list. Next make sure at least 1 window is displaying the buffer list, splitting the screen if this is what it takes. Lastly, repaint all of the windows that are displaying the list. Bound to "C-X C-B". A numeric argument forces it to list invisable buffers as well. */ PASCAL NEAR listbuffers(f, n) { register WINDOW *wp; register BUFFER *bp; register int s; register int cmark; /* current mark */ if ((s=makelist(f)) != TRUE) return(s); if (blistp->b_nwnd == 0) { /* Not on screen yet. */ if ((wp=wpopup()) == NULL) return(FALSE); bp = wp->w_bufp; if (--bp->b_nwnd == 0) { bp->b_dotp = wp->w_dotp; bp->b_doto = wp->w_doto; for (cmark = 0; cmark < NMARKS; cmark++) { bp->b_markp[cmark] = wp->w_markp[cmark]; bp->b_marko[cmark] = wp->w_marko[cmark]; } bp->b_fcol = wp->w_fcol; } wp->w_bufp = blistp; ++blistp->b_nwnd; } wp = wheadp; while (wp != NULL) { if (wp->w_bufp == blistp) { wp->w_linep = lforw(blistp->b_linep); wp->w_dotp = lforw(blistp->b_linep); wp->w_doto = 0; for (cmark = 0; cmark < NMARKS; cmark++) { wp->w_markp[cmark] = NULL; wp->w_marko[cmark] = 0; } wp->w_flag |= WFMODE|WFHARD; } wp = wp->w_wndp; } return(TRUE); } /* * This routine rebuilds the * text in the special secret buffer * that holds the buffer list. It is called * by the list buffers command. Return TRUE * if everything works. Return FALSE if there * is an error (if there is no memory). Iflag * indecates weather to list hidden buffers. */ PASCAL NEAR makelist(iflag) int iflag; /* list hidden buffer flag */ { register char *cp1; register char *cp2; register int c; register BUFFER *bp; register LINE *lp; register int s; register int i; long nbytes; /* # of bytes in current buffer */ char b[7+1]; char line[128]; blistp->b_flag &= ~BFCHG; /* Don't complain! */ if ((s=bclear(blistp)) != TRUE) /* Blow old text away */ return(s); strcpy(blistp->b_fname, ""); if (addline(TEXT30) == FALSE /* "ACT Modes Size Buffer File" */ || addline("--- --------- ------- --------------- ----") == FALSE) return(FALSE); bp = bheadp; /* For all buffers */ /* build line to report global mode settings */ cp1 = &line[0]; *cp1++ = ' '; *cp1++ = ' '; *cp1++ = ' '; *cp1++ = ' '; /* output the mode codes */ for (i = 0; i < NUMMODES; i++) if (gmode & (1 << i)) *cp1++ = modecode[i]; else *cp1++ = '.'; strcpy(cp1, TEXT31); /* " Global Modes" */ if (addline(line) == FALSE) return(FALSE); /* output the list of buffers */ while (bp != NULL) { /* skip invisable buffers if iflag is false */ if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) { bp = bp->b_bufp; continue; } cp1 = &line[0]; /* Start at left edge */ /* output status of ACTIVE flag (has the file been read in? */ if (bp->b_active == TRUE) /* "@" if activated */ *cp1++ = '@'; else *cp1++ = ' '; /* output status of changed flag */ if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */ *cp1++ = '*'; else *cp1++ = ' '; /* report if the file is truncated */ if ((bp->b_flag&BFTRUNC) != 0) *cp1++ = '#'; else *cp1++ = ' '; *cp1++ = ' '; /* space */ /* output the mode codes */ for (i = 0; i < NUMMODES; i++) { if (bp->b_mode & (1 << i)) *cp1++ = modecode[i]; else *cp1++ = '.'; } *cp1++ = ' '; /* Gap. */ nbytes = 0L; /* Count bytes in buf. */ lp = lforw(bp->b_linep); while (lp != bp->b_linep) { nbytes += (long)llength(lp)+1L; lp = lforw(lp); } long_asc(b, 7, nbytes); /* 6 digit buffer size. */ cp2 = &b[0]; while ((c = *cp2++) != 0) *cp1++ = c; *cp1++ = ' '; /* Gap. */ cp2 = &bp->b_bname[0]; /* Buffer name */ while ((c = *cp2++) != 0) *cp1++ = c; *cp1++ = ' '; /* Gap. */ cp2 = &bp->b_fname[0]; /* File name */ if (*cp2 != 0) { while (cp1 < &line[22+NBUFN]) *cp1++ = ' '; while ((c = *cp2++) != 0) { if (cp1 < &line[128-1]) *cp1++ = c; } } *cp1 = 0; /* Add to the buffer. */ if (addline(line) == FALSE) return(FALSE); bp = bp->b_bufp; } return(TRUE); /* All done */ } /* Translate a long to ascii form. Don't trust various systems ltoa() routines.. they aren't consistand */ PASCAL NEAR long_asc(buf, width, num) char buf[]; int width; long num; { buf[width] = 0; /* End of string. */ while (num >= 10) { /* Conditional digits. */ buf[--width] = (int)(num%10L) + '0'; num /= 10L; } buf[--width] = (int)num + '0'; /* Always 1 digit. */ while (width != 0) /* Pad with blanks. */ buf[--width] = ' '; } /* * The argument "text" points to * a string. Append this line to the * buffer list buffer. Handcraft the EOL * on the end. Return TRUE if it worked and * FALSE if you ran out of room. */ PASCAL NEAR addline(text) char *text; { register LINE *lp; register int i; register int ntext; ntext = strlen(text); if ((lp=lalloc(ntext)) == NULL) return(FALSE); for (i=0; i<ntext; ++i) lputc(lp, i, text[i]); blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */ lp->l_bp = blistp->b_linep->l_bp; blistp->b_linep->l_bp = lp; lp->l_fp = blistp->b_linep; if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */ blistp->b_dotp = lp; /* move it to new line */ return(TRUE); } /* * Look through the list of * buffers. Return TRUE if there * are any changed buffers. Buffers * that hold magic internal stuff are * not considered; who cares if the * list of buffer names is hacked. * Return FALSE if no buffers * have been changed. */ PASCAL NEAR anycb() { register BUFFER *bp; bp = bheadp; while (bp != NULL) { if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0) return(TRUE); bp = bp->b_bufp; } return(FALSE); } /* * Find a buffer, by name. Return a pointer * to the BUFFER structure associated with it. * If the buffer is not found * and the "cflag" is TRUE, create it. The "bflag" is * the settings for the flags in in buffer. */ BUFFER *PASCAL NEAR bfind(bname, cflag, bflag) register char *bname; /* name of buffer to find */ int cflag; /* create it if not found? */ int bflag; /* bit settings for a new buffer */ { register BUFFER *bp; register BUFFER *sb; /* buffer to insert after */ register LINE *lp; int cmark; /* current mark */ bp = bheadp; while (bp != NULL) { if (strcmp(bname, bp->b_bname) == 0) return(bp); bp = bp->b_bufp; } if (cflag != FALSE) { if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) return(NULL); if ((lp=lalloc(0)) == NULL) { free((char *) bp); return(NULL); } /* find the place in the list to insert this buffer */ if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) { /* insert at the beginning */ bp->b_bufp = bheadp; bheadp = bp; } else { sb = bheadp; while (sb->b_bufp != NULL) { if (strcmp(sb->b_bufp->b_bname, bname) > 0) break; sb = sb->b_bufp; } /* and insert it */ bp->b_bufp = sb->b_bufp; sb->b_bufp = bp; } /* and set up the other buffer fields */ bp->b_topline = NULL; bp->b_botline = NULL; bp->b_active = TRUE; bp->b_dotp = lp; bp->b_doto = 0; for (cmark = 0; cmark < NMARKS; cmark++) { bp->b_markp[cmark] = NULL; bp->b_marko[cmark] = 0; } bp->b_fcol = 0; bp->b_flag = bflag; bp->b_mode = gmode; bp->b_nwnd = 0; bp->b_linep = lp; strcpy(bp->b_fname, ""); strcpy(bp->b_bname, bname); #if CRYPT bp->b_key[0] = 0; #endif lp->l_fp = lp; lp->l_bp = lp; } return(bp); } /* * This routine blows away all of the text * in a buffer. If the buffer is marked as changed * then we ask if it is ok to blow it away; this is * to save the user the grief of losing text. The * window chain is nearly always wrong if this gets * called; the caller must arrange for the updates * that are required. Return TRUE if everything * looks good. */ PASCAL NEAR bclear(bp) register BUFFER *bp; { register LINE *lp; register int s; int cmark; /* current mark */ if ((bp->b_flag&BFINVS) == 0 /* Not scratch buffer. */ && (bp->b_flag&BFCHG) != 0 /* Something changed */ && (s=mlyesno(TEXT32)) != TRUE) /* "Discard changes" */ return(s); bp->b_flag &= ~BFCHG; /* Not changed */ while ((lp=lforw(bp->b_linep)) != bp->b_linep) lfree(lp); bp->b_dotp = bp->b_linep; /* Fix "." */ bp->b_doto = 0; for (cmark = 0; cmark < NMARKS; cmark++) { bp->b_markp[cmark] = NULL; /* Invalidate "mark" */ bp->b_marko[cmark] = 0; } bp->b_fcol = 0; return(TRUE); } PASCAL NEAR unmark(f, n) /* unmark the current buffers change flag */ int f, n; /* unused command arguments */ { register WINDOW *wp; /* unmark the buffer */ curbp->b_flag &= ~BFCHG; /* unmark all windows as well */ upmode(); return(TRUE); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.