summaryrefslogtreecommitdiff
path: root/pico/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'pico/buffer.c')
-rw-r--r--pico/buffer.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/pico/buffer.c b/pico/buffer.c
new file mode 100644
index 00000000..87423d28
--- /dev/null
+++ b/pico/buffer.c
@@ -0,0 +1,354 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: buffer.c 761 2007-10-23 22:35:18Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ *
+ * Program: Buffer management routines
+ */
+
+/*
+ * 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 "headers.h"
+
+int sgetline(char **, int *, char *, int);
+
+
+/*
+ * 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.
+ */
+int
+anycb(void)
+{
+ register BUFFER *bp;
+
+ bp = bheadp;
+ while (bp != NULL) {
+ if ((bp->b_flag&BFTEMP)==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 named buffer is found, but is a TEMP buffer (like
+ * the buffer list) conplain. 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 *
+bfind(char *bname, int cflag, int bflag)
+{
+ register BUFFER *bp;
+ register BUFFER *sb; /* buffer to insert after */
+ register LINE *lp;
+
+ bp = bheadp;
+ while (bp != NULL) {
+ if (strcmp(bname, bp->b_bname) == 0) {
+ if ((bp->b_flag&BFTEMP) != 0) {
+ mlwrite_utf8("Cannot select builtin buffer", NULL);
+ return (NULL);
+ }
+ 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 begining */
+ 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_active = TRUE;
+ bp->b_dotp = lp;
+ bp->b_doto = 0;
+ bp->b_markp = NULL;
+ bp->b_marko = 0;
+ bp->b_flag = bflag;
+ bp->b_mode = gmode;
+ bp->b_nwnd = 0;
+ bp->b_linep = lp;
+ strncpy(bp->b_fname, "", sizeof(bp->b_fname));
+ bp->b_fname[sizeof(bp->b_fname)-1] = '\0';
+ strncpy(bp->b_bname, bname, sizeof(bp->b_bname));
+ bp->b_bname[sizeof(bp->b_bname)-1] = '\0';
+ 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.
+ */
+int
+bclear(BUFFER *bp)
+{
+ register LINE *lp;
+ register int s = FALSE;
+
+ if(Pmaster){
+ if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */
+ && (bp->b_flag&BFCHG) != 0){ /* Something changed */
+ emlwrite("buffer lines not freed.", NULL);
+ return (s);
+ }
+ }
+ else{
+ if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */
+ && (bp->b_flag&BFCHG) != 0 /* Something changed */
+ /* TRANSLATORS: A question asking whether to forget about
+ the changes and revert to the unchanged version. */
+ && (s=mlyesno_utf8(_("Discard changes"), -1)) != TRUE){
+ 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;
+ bp->b_markp = NULL; /* Invalidate "mark" */
+ bp->b_marko = 0;
+ return (TRUE);
+}
+
+
+/*
+ * packbuf - will pack up the main buffer in the buffer provided
+ * to be returned to the program that called pico.
+ * if need be, allocate memory for the new message.
+ * will also free the memory associated with the editor
+ * buffer, by calling zotedit.
+ */
+int
+packbuf(char **buf,
+ int *blen,
+ int lcrlf) /* EOLs are local or CRLF */
+{
+ register int i = 0;
+ register LINE *lp;
+ register int retval = 0;
+ register char *bufp;
+ register char *eobuf;
+
+ if(anycb() != FALSE){
+
+ lp = lforw(curbp->b_linep);
+ do{ /* how many chars? */
+ i += llength(lp);
+ /*
+ * add extra for new lines to be inserted later
+ */
+ i += 2;
+ lp = lforw(lp);
+ }
+ while(lp != curbp->b_linep);
+
+ if(i > *blen){ /* new buffer ? */
+ /*
+ * don't forget to add one for the null terminator!!!
+ */
+ if((bufp = (char *)malloc((i+1)*sizeof(char))) == NULL){
+ zotedit(); /* bag it! */
+ return(COMP_FAILED);
+ }
+ free(*buf);
+ *buf = bufp;
+ *blen = i;
+ }
+ else{
+ bufp = *buf;
+ }
+
+ eobuf = bufp + *blen;
+ lp = lforw(curbp->b_linep); /* First line. */
+ do {
+ for (i = 0; i < llength(lp); i++){ /* copy into buffer */
+ if((bufp+1) < eobuf){
+ *bufp++ = (lp->l_text[i].c & 0xFF);
+ }
+ else{
+ /*
+ * the idea is to malloc enough space for the new
+ * buffer...
+ */
+ *bufp = '\0';
+ zotedit();
+ return(BUF_CHANGED|COMP_FAILED);
+ }
+ }
+ if(lcrlf){
+ *bufp++ = '\n'; /* EOLs use local convention */
+ }
+ else{
+ *bufp++ = 0x0D; /* EOLs use net standard */
+ *bufp++ = 0x0A;
+ }
+ lp = lforw(lp);
+ }
+ while (lp != curbp->b_linep);
+ if(lcrlf)
+ *--bufp = '\0';
+ else
+ *bufp = '\0';
+ retval = BUF_CHANGED;
+ }
+
+ zotedit();
+ return(retval);
+}
+
+
+/*
+ * readbuf - reads in a buffer.
+ */
+void
+readbuf(char **buf)
+{
+ register LINE *lp1;
+ register LINE *lp2;
+ register BUFFER *bp;
+ register WINDOW *wp;
+ register int i;
+ register int s;
+ char *sptr; /* pointer into buffer string */
+ int nbytes;
+ char line[NLINE];
+ CELL ac;
+
+ bp = curbp;
+ bp->b_flag &= ~(BFTEMP|BFCHG);
+ sptr = *buf;
+ ac.a = 0;
+
+ while((s=sgetline(&sptr,&nbytes,line,NLINE)) == FIOSUC || s == FIOLNG){
+
+ if ((lp1=lalloc(nbytes)) == NULL) {
+ s = FIOERR; /* Keep message on the */
+ break; /* display. */
+ }
+ lp2 = lback(curbp->b_linep);
+ lp2->l_fp = lp1;
+ lp1->l_fp = curbp->b_linep;
+ lp1->l_bp = lp2;
+ curbp->b_linep->l_bp = lp1;
+ for (i=0; i<nbytes; ++i){
+ ac.c = line[i];
+ lputc(lp1, i, ac);
+ }
+ }
+
+ for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
+ if (wp->w_bufp == curbp) {
+ wheadp->w_linep = lforw(curbp->b_linep);
+ wheadp->w_dotp = lback(curbp->b_linep);
+ wheadp->w_doto = 0;
+ wheadp->w_markp = NULL;
+ wheadp->w_marko = 0;
+ wheadp->w_flag |= WFHARD;
+ }
+ }
+
+ strncpy(bp->b_bname, "main", sizeof(bp->b_bname));
+ bp->b_bname[sizeof(bp->b_bname)-1] = '\0';
+ strncpy(bp->b_fname, "", sizeof(bp->b_fname));
+ bp->b_fname[sizeof(bp->b_fname)-1] = '\0';
+
+ bp->b_dotp = bp->b_linep;
+ bp->b_doto = 0;
+}
+
+
+/*
+ * sgetline - copy characters from ibuf to obuf, ending at the first
+ * newline. return with ibuf pointing to first char after
+ * newline.
+ */
+int
+sgetline(char **ibuf, int *nchars, char *obuf, int blen)
+{
+ register char *len;
+ register char *cbuf = *ibuf;
+ register char *bufp = obuf;
+ register int retval = FIOSUC;
+#define CR '\015'
+#define LF '\012'
+
+ *nchars = 0;
+ if(*cbuf == '\0'){
+ retval = FIOEOF;
+ }
+ else{
+ len = obuf + blen;
+ while (*cbuf != CR && *cbuf != LF && *cbuf != '\0'){
+ if(bufp < len){
+ *bufp++ = *cbuf++;
+ (*nchars)++;
+ }
+ else{
+ *bufp = '\0';
+ retval = FIOLNG;
+ break;
+ }
+ }
+ }
+ *bufp = '\0'; /* end retured line */
+ *ibuf = (*cbuf == CR) ? ++cbuf : cbuf;
+ *ibuf = (*cbuf == LF) ? ++cbuf : cbuf;
+ return(retval);
+}