diff options
Diffstat (limited to 'usr.bin/vi/cut.c')
-rw-r--r-- | usr.bin/vi/cut.c | 323 |
1 files changed, 63 insertions, 260 deletions
diff --git a/usr.bin/vi/cut.c b/usr.bin/vi/cut.c index 5a9b292ce1757..a4e277a10228b 100644 --- a/usr.bin/vi/cut.c +++ b/usr.bin/vi/cut.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1992, 1993 + * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,23 +32,33 @@ */ #ifndef lint -static char sccsid[] = "@(#)cut.c 8.20 (Berkeley) 1/23/94"; +static char sccsid[] = "@(#)cut.c 8.26 (Berkeley) 3/14/94"; #endif /* not lint */ #include <sys/types.h> +#include <queue.h> +#include <sys/time.h> +#include <bitstring.h> #include <ctype.h> #include <errno.h> #include <fcntl.h> +#include <limits.h> +#include <signal.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> +#include <termios.h> + +#include <db.h> +#include <regex.h> #include "vi.h" -static int cb_line __P((SCR *, EXF *, recno_t, size_t, size_t, TEXT **)); +static int cb_line __P((SCR *, EXF *, recno_t, size_t, size_t, CB *)); static int cb_rotate __P((SCR *)); -/* +/* * cut -- * Put a range of lines/columns into a buffer. * @@ -57,7 +67,7 @@ static int cb_rotate __P((SCR *)); * default buffer storage. There is a pointer, too, which is the current * default buffer, i.e. it may point to the default buffer or a named buffer * depending on into what buffer the last text was cut. In both delete and - * yank operations, text is cut into either the buffer named by the user, or + * yank operations, text is cut into either the buffer named by the user or * the default buffer. If it's a delete of information on more than a single * line, the contents of the numbered buffers are rotated up one, the contents * of the buffer named '9' are discarded, and the text is also cut into the @@ -68,14 +78,15 @@ static int cb_rotate __P((SCR *)); * of replaced. * * !!! - * The contents of the default buffer would disappear after most operations in - * historic vi. It's unclear that this is useful, so we don't bother. + * The contents of the default buffer would disappear after most operations + * in historic vi. It's unclear that this is useful, so we don't bother. * * When users explicitly cut text into the numeric buffers, historic vi became * genuinely strange. I've never been able to figure out what was supposed to * happen. It behaved differently if you deleted text than if you yanked text, * and, in the latter case, the text was appended to the buffer instead of - * replacing the contents. Hopefully it's not worth getting right. + * replacing the contents. Hopefully it's not worth getting right, and here + * we just treat the numeric buffers like any other named buffer. */ int cut(sp, ep, cbp, namep, fm, tm, flags) @@ -87,33 +98,26 @@ cut(sp, ep, cbp, namep, fm, tm, flags) MARK *fm, *tm; { CHAR_T name; - TEXT *tp; recno_t lno; - size_t len; int append, namedbuffer, setdefcb; -#if defined(DEBUG) && 0 - TRACE(sp, "cut: from {%lu, %d}, to {%lu, %d}%s\n", - fm->lno, fm->cno, tm->lno, tm->cno, - LF_ISSET(CUT_LINEMODE) ? " LINE MODE" : ""); -#endif if (cbp == NULL) { - if (LF_ISSET(CUT_DELETE) && - (LF_ISSET(CUT_LINEMODE) || fm->lno != tm->lno)) { - (void)cb_rotate(sp); - name = '1'; - goto defcb; - } if (namep == NULL) { + if (LF_ISSET(CUT_DELETE) && + (LF_ISSET(CUT_LINEMODE) || fm->lno != tm->lno)) { + (void)cb_rotate(sp); + name = '1'; + goto defcb; + } cbp = sp->gp->dcb_store; append = namedbuffer = 0; - setdefcb = 1; } else { name = *namep; defcb: CBNAME(sp, cbp, name); append = isupper(name); - namedbuffer = setdefcb = 1; + namedbuffer = 1; } + setdefcb = 1; } else append = namedbuffer = setdefcb = 0; @@ -135,45 +139,35 @@ defcb: CBNAME(sp, cbp, name); cbp->flags = 0; } +#define ENTIRE_LINE 0 /* In line mode, it's pretty easy, just cut the lines. */ if (LF_ISSET(CUT_LINEMODE)) { - for (lno = fm->lno; lno <= tm->lno; ++lno) { - if (cb_line(sp, ep, lno, 0, 0, &tp)) - goto mem; - CIRCLEQ_INSERT_TAIL(&cbp->textq, tp, q); - cbp->len += tp->len; - } cbp->flags |= CB_LMODE; + for (lno = fm->lno; lno <= tm->lno; ++lno) + if (cb_line(sp, ep, lno, 0, 0, cbp)) + goto cb_line_fail; } else { - /* Get the first line. */ - len = fm->lno < tm->lno ? 0 : tm->cno - fm->cno; - if (cb_line(sp, ep, fm->lno, fm->cno, len, &tp)) - goto mem; - CIRCLEQ_INSERT_TAIL(&cbp->textq, tp, q); - cbp->len += tp->len; + /* + * Get the first line. A length of 0 causes cb_line + * to cut from the MARK to the end of the line. + */ + if (cb_line(sp, ep, fm->lno, fm->cno, + fm->lno != tm->lno ? ENTIRE_LINE : (tm->cno - fm->cno) + 1, + cbp)) + goto cb_line_fail; /* Get the intermediate lines. */ - for (lno = fm->lno; ++lno < tm->lno;) { - if (cb_line(sp, ep, lno, 0, 0, &tp)) - goto mem; - CIRCLEQ_INSERT_TAIL(&cbp->textq, tp, q); - cbp->len += tp->len; - } + for (lno = fm->lno; ++lno < tm->lno;) + if (cb_line(sp, ep, lno, 0, ENTIRE_LINE, cbp)) + goto cb_line_fail; /* Get the last line. */ - if (tm->lno > fm->lno && tm->cno > 0) { - if (cb_line(sp, ep, lno, 0, tm->cno, &tp)) { -mem: if (append) - msgq(sp, M_ERR, - "Contents of %s buffer lost.", - charname(sp, name)); - text_lfree(&cbp->textq); - cbp->len = 0; - cbp->flags = 0; - return (1); - } - CIRCLEQ_INSERT_TAIL(&cbp->textq, tp, q); - cbp->len += tp->len; + if (tm->lno != fm->lno && + cb_line(sp, ep, lno, 0, tm->cno + 1, cbp)) { +cb_line_fail: text_lfree(&cbp->textq); + cbp->len = 0; + cbp->flags = 0; + return (1); } } if (setdefcb) @@ -235,28 +229,30 @@ cb_rotate(sp) * Cut a portion of a single line. */ static int -cb_line(sp, ep, lno, fcno, clen, newp) +cb_line(sp, ep, lno, fcno, clen, cbp) SCR *sp; EXF *ep; recno_t lno; size_t fcno, clen; - TEXT **newp; + CB *cbp; { TEXT *tp; size_t len; char *p; + /* Get the line. */ if ((p = file_gline(sp, ep, lno, &len)) == NULL) { GETLINE_ERR(sp, lno); return (1); } - if ((*newp = tp = text_init(sp, NULL, 0, len)) == NULL) + /* Create a TEXT structure that can hold the entire line. */ + if ((tp = text_init(sp, NULL, 0, len)) == NULL) return (1); /* - * A length of zero means to cut from the MARK to the end - * of the line. + * If the line isn't empty and it's not the entire line, + * copy the portion we want, and reset the TEXT length. */ if (len != 0) { if (clen == 0) @@ -264,6 +260,11 @@ cb_line(sp, ep, lno, fcno, clen, newp) memmove(tp->lb, p + fcno, clen); tp->len = clen; } + + /* Append to the end of the cut buffer. */ + CIRCLEQ_INSERT_TAIL(&cbp->textq, tp, q); + cbp->len += tp->len; + return (0); } @@ -279,11 +280,11 @@ text_init(sp, p, len, total_len) { TEXT *tp; - MALLOC(sp, tp, TEXT *, sizeof(TEXT)); + CALLOC(sp, tp, TEXT *, 1, sizeof(TEXT)); if (tp == NULL) return (NULL); /* ANSI C doesn't define a call to malloc(2) for 0 bytes. */ - if (tp->lb_len = total_len) { + if ((tp->lb_len = total_len) != 0) { MALLOC(sp, tp->lb, CHAR_T *, tp->lb_len); if (tp->lb == NULL) { free(tp); @@ -291,12 +292,8 @@ text_init(sp, p, len, total_len) } if (p != NULL && len != 0) memmove(tp->lb, p, len); - } else - tp->lb = NULL; + } tp->len = len; - tp->ai = tp->insert = tp->offset = tp->owrite = 0; - tp->wd = NULL; - tp->wd_len = 0; return (tp); } @@ -330,197 +327,3 @@ text_free(tp) FREE(tp->wd, tp->wd_len); FREE(tp, sizeof(TEXT)); } - -/* - * put -- - * Put text buffer contents into the file. - * - * !!! - * Historically, pasting into a file with no lines in vi would preserve - * the single blank line. This is almost certainly a result of the fact - * that historic vi couldn't deal with a file that had no lines in it. - * This implementation treats that as a bug, and does not retain the - * blank line. - */ -int -put(sp, ep, cbp, namep, cp, rp, append) - SCR *sp; - EXF *ep; - CB *cbp; - CHAR_T *namep; - MARK *cp, *rp; - int append; -{ - CHAR_T name; - TEXT *ltp, *tp; - recno_t lno; - size_t blen, clen, len; - char *bp, *p, *t; - - if (cbp == NULL) - if (namep == NULL) { - cbp = sp->gp->dcbp; - if (cbp == NULL) { - msgq(sp, M_ERR, "The default buffer is empty."); - return (1); - } - } else { - name = *namep; - CBNAME(sp, cbp, name); - if (cbp == NULL) { - msgq(sp, M_ERR, - "Buffer %s is empty.", charname(sp, name)); - return (1); - } - } - tp = cbp->textq.cqh_first; - - /* - * It's possible to do a put into an empty file, meaning that the - * cut buffer simply becomes the file. It's a special case so - * that we can ignore it in general. - * - * Historical practice is that the cursor ends up on the first - * non-blank character of the first line inserted. - */ - if (cp->lno == 1) { - if (file_lline(sp, ep, &lno)) - return (1); - if (lno == 0) { - for (; tp != (void *)&cbp->textq; - ++lno, tp = tp->q.cqe_next) - if (file_aline(sp, ep, 1, lno, tp->lb, tp->len)) - return (1); - rp->lno = 1; - rp->cno = 0; - (void)nonblank(sp, ep, rp->lno, &rp->cno); - goto ret; - } - } - - /* If a line mode buffer, append each new line into the file. */ - if (F_ISSET(cbp, CB_LMODE)) { - lno = append ? cp->lno : cp->lno - 1; - rp->lno = lno + 1; - for (; tp != (void *)&cbp->textq; ++lno, tp = tp->q.cqe_next) - if (file_aline(sp, ep, 1, lno, tp->lb, tp->len)) - return (1); - rp->cno = 0; - (void)nonblank(sp, ep, rp->lno, &rp->cno); - goto ret; - } - - /* - * If buffer was cut in character mode, replace the current line with - * one built from the portion of the first line to the left of the - * split plus the first line in the CB. Append each intermediate line - * in the CB. Append a line built from the portion of the first line - * to the right of the split plus the last line in the CB. - * - * Get the first line. - */ - lno = cp->lno; - if ((p = file_gline(sp, ep, lno, &len)) == NULL) { - GETLINE_ERR(sp, lno); - return (1); - } - - GET_SPACE_RET(sp, bp, blen, tp->len + len + 1); - t = bp; - - /* Original line, left of the split. */ - if (len > 0 && (clen = cp->cno + (append ? 1 : 0)) > 0) { - memmove(bp, p, clen); - p += clen; - t += clen; - } - - /* First line from the CB. */ - memmove(t, tp->lb, tp->len); - t += tp->len; - - /* Calculate length left in original line. */ - clen = len ? len - cp->cno - (append ? 1 : 0) : 0; - - /* - * If no more lines in the CB, append the rest of the original - * line and quit. Otherwise, build the last line before doing - * the intermediate lines, because the line changes will lose - * the cached line. - */ - if (tp->q.cqe_next == (void *)&cbp->textq) { - /* - * Historical practice is that if a non-line mode put - * is inside a single line, the cursor ends up on the - * last character inserted. - */ - rp->lno = lno; - rp->cno = (t - bp) - 1; - - if (clen > 0) { - memmove(t, p, clen); - t += clen; - } - if (file_sline(sp, ep, lno, bp, t - bp)) - goto mem; - } else { - /* - * Have to build both the first and last lines of the - * put before doing any sets or we'll lose the cached - * line. Build both the first and last lines in the - * same buffer, so we don't have to have another buffer - * floating around. - * - * Last part of original line; check for space, reset - * the pointer into the buffer. - */ - ltp = cbp->textq.cqh_last; - len = t - bp; - ADD_SPACE_RET(sp, bp, blen, ltp->len + clen); - t = bp + len; - - /* Add in last part of the CB. */ - memmove(t, ltp->lb, ltp->len); - if (clen) - memmove(t + ltp->len, p, clen); - clen += ltp->len; - - /* - * Now: bp points to the first character of the first - * line, t points to the last character of the last - * line, t - bp is the length of the first line, and - * clen is the length of the last. Just figured you'd - * want to know. - * - * Output the line replacing the original line. - */ - if (file_sline(sp, ep, lno, bp, t - bp)) - goto mem; - - /* - * Historical practice is that if a non-line mode put - * covers multiple lines, the cursor ends up on the - * first character inserted. (Of course.) - */ - rp->lno = lno; - rp->cno = (t - bp) - 1; - - /* Output any intermediate lines in the CB. */ - for (tp = tp->q.cqe_next; - tp->q.cqe_next != (void *)&cbp->textq; - ++lno, tp = tp->q.cqe_next) - if (file_aline(sp, ep, 1, lno, tp->lb, tp->len)) - goto mem; - - if (file_aline(sp, ep, 1, lno, t, clen)) { -mem: FREE_SPACE(sp, bp, blen); - return (1); - } - } - FREE_SPACE(sp, bp, blen); - - /* Reporting... */ -ret: sp->rptlines[L_PUT] += lno - cp->lno; - - return (0); -} |