/* buffer.c, Atto Emacs, Hugh Barney, Public Domain, 2015 */ #include #include #include "header.h" void buffer_init(buffer_t *bp) { bp->b_mark = NOMARK; bp->b_point = 0; bp->b_cpoint = 0; bp->b_page = 0; bp->b_epage = 0; bp->b_reframe = 0; bp->b_size = 0; bp->b_psize = 0; bp->b_flags = 0; bp->b_cnt = 0; bp->b_buf = NULL; bp->b_ebuf = NULL; bp->b_gap = NULL; bp->b_egap = NULL; bp->b_next = NULL; bp->b_fname[0] = '\0'; bp->b_bname[0] = '\0'; } /* Find a buffer by filename or create if requested */ buffer_t* find_buffer (const char *fname, int cflag) { buffer_t *bp = NULL; buffer_t *sb = NULL; bp = bheadp; while (bp != NULL) { if (strcmp (fname, bp->b_fname) == 0 || strcmp(fname, bp->b_bname) == 0) { return (bp); } bp = bp->b_next; } if (cflag != FALSE) { if ((bp = malloc (sizeof (buffer_t))) == NULL) return (0); buffer_init(bp); assert(bp != NULL); /* find the place in the list to insert this buffer */ if (bheadp == NULL) { bheadp = bp; } else if (strcmp (bheadp->b_fname, fname) > 0) { /* insert at the beginning */ bp->b_next = bheadp; bheadp = bp; } else { for (sb = bheadp; sb->b_next != NULL; sb = sb->b_next) if (strcmp (sb->b_next->b_fname, fname) > 0) break; /* and insert it */ bp->b_next = sb->b_next; sb->b_next = bp; } } return bp; } /* unlink from the list of buffers, free associated memory, assumes buffer has been saved if modified */ int delete_buffer (buffer_t *bp) { buffer_t *sb = NULL; window_t *wp; /* we must have switched to a different buffer first */ assert(bp != curbp); /* if buffer is the head buffer */ if (bp == bheadp) { bheadp = bp->b_next; } else { /* find place where the bp buffer is next */ for (sb = bheadp; sb->b_next != bp && sb->b_next != NULL; sb = sb->b_next) ; assert(sb->b_next == bp || sb->b_next == NULL); sb->b_next = bp->b_next; } /* repoint any other window still showing bp at the current buffer */ for (wp = wheadp; wp != NULL; wp = wp->w_next) { if (wp->w_bufp != bp) continue; disassociate_b(wp); associate_b2w(curbp, wp); b2w(wp); wp->w_update = TRUE; } assert(bp->b_cnt == 0); /* now we can delete */ free(bp->b_buf); free(bp); return TRUE; } void next_buffer(void) { assert(curbp != NULL); assert(bheadp != NULL); disassociate_b(curwp); curbp = (curbp->b_next != NULL ? curbp->b_next : bheadp); associate_b2w(curbp,curwp); } char* get_buffer_name(buffer_t *bp) { return (strlen(bp->b_fname) > 0) ? bp->b_fname : bp->b_bname; } int count_buffers(void) { buffer_t* bp; int i; for (i=0, bp=bheadp; bp != NULL; bp = bp->b_next) i++; return i; } int modified_buffers(void) { buffer_t* bp; for (bp=bheadp; bp != NULL; bp = bp->b_next) if (bp->b_flags & B_MODIFIED) return TRUE; return FALSE; } buffer_t *create_scratch(void) { buffer_t *bp = find_buffer("*scratch*", TRUE); if (bp == NULL) return NULL; strlcpy(bp->b_bname, "*scratch*", sizeof(bp->b_bname)); return bp; }