diff options
author | peter <peter@FreeBSD.org> | 1996-11-01 06:45:43 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1996-11-01 06:45:43 +0000 |
commit | 59cc89c2c2e686da3bdab2d5cfac4f33462d29fe (patch) | |
tree | 88f923c9c0be2e2a225a9b21716fd582de668b42 /contrib/nvi/vi/v_ulcase.c | |
download | FreeBSD-src-59cc89c2c2e686da3bdab2d5cfac4f33462d29fe.zip FreeBSD-src-59cc89c2c2e686da3bdab2d5cfac4f33462d29fe.tar.gz |
Import of nvi-1.79, minus a few bits that we dont need (eg: postscript
files, curses, db, regex etc that we already have). The other glue will
follow shortly.
Obtained from: Keith Bostic <bostic@bostic.com>
Diffstat (limited to 'contrib/nvi/vi/v_ulcase.c')
-rw-r--r-- | contrib/nvi/vi/v_ulcase.c | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/contrib/nvi/vi/v_ulcase.c b/contrib/nvi/vi/v_ulcase.c new file mode 100644 index 0000000..179beba --- /dev/null +++ b/contrib/nvi/vi/v_ulcase.c @@ -0,0 +1,179 @@ +/*- + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1992, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + * + * See the LICENSE file for redistribution information. + */ + +#include "config.h" + +#ifndef lint +static const char sccsid[] = "@(#)v_ulcase.c 10.7 (Berkeley) 3/6/96"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/time.h> + +#include <bitstring.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../common/common.h" +#include "vi.h" + +static int ulcase __P((SCR *, recno_t, CHAR_T *, size_t, size_t, size_t)); + +/* + * v_ulcase -- [count]~ + * Toggle upper & lower case letters. + * + * !!! + * Historic vi didn't permit ~ to cross newline boundaries. I can + * think of no reason why it shouldn't, which at least lets the user + * auto-repeat through a paragraph. + * + * !!! + * In historic vi, the count was ignored. It would have been better + * if there had been an associated motion, but it's too late to make + * that the default now. + * + * PUBLIC: int v_ulcase __P((SCR *, VICMD *)); + */ +int +v_ulcase(sp, vp) + SCR *sp; + VICMD *vp; +{ + recno_t lno; + size_t cno, lcnt, len; + u_long cnt; + char *p; + + lno = vp->m_start.lno; + cno = vp->m_start.cno; + + for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt > 0; cno = 0) { + /* SOF is an error, EOF is an infinite count sink. */ + if (db_get(sp, lno, 0, &p, &len)) { + if (lno == 1) { + v_emsg(sp, NULL, VIM_EMPTY); + return (1); + } + --lno; + break; + } + + /* Empty lines decrement the count by one. */ + if (len == 0) { + --cnt; + vp->m_final.cno = 0; + continue; + } + + if (cno + cnt >= len) { + lcnt = len - 1; + cnt -= len - cno; + + vp->m_final.cno = len - 1; + } else { + lcnt = cno + cnt - 1; + cnt = 0; + + vp->m_final.cno = lcnt + 1; + } + + if (ulcase(sp, lno, p, len, cno, lcnt)) + return (1); + + if (cnt > 0) + ++lno; + } + + vp->m_final.lno = lno; + return (0); +} + +/* + * v_mulcase -- [count]~[count]motion + * Toggle upper & lower case letters over a range. + * + * PUBLIC: int v_mulcase __P((SCR *, VICMD *)); + */ +int +v_mulcase(sp, vp) + SCR *sp; + VICMD *vp; +{ + CHAR_T *p; + size_t len; + recno_t lno; + + for (lno = vp->m_start.lno;;) { + if (db_get(sp, lno, DBG_FATAL, &p, &len)) + return (1); + if (len != 0 && ulcase(sp, lno, p, len, + lno == vp->m_start.lno ? vp->m_start.cno : 0, + !F_ISSET(vp, VM_LMODE) && + lno == vp->m_stop.lno ? vp->m_stop.cno : len)) + return (1); + + if (++lno > vp->m_stop.lno) + break; + } + + /* + * XXX + * I didn't create a new motion command when I added motion semantics + * for ~. While that's the correct way to do it, that choice would + * have required changes all over the vi directory for little gain. + * Instead, we pretend it's a yank command. Note, this means that we + * follow the cursor motion rules for yank commands, but that seems + * reasonable to me. + */ + return (0); +} + +/* + * ulcase -- + * Change part of a line's case. + */ +static int +ulcase(sp, lno, lp, len, scno, ecno) + SCR *sp; + recno_t lno; + CHAR_T *lp; + size_t len, scno, ecno; +{ + size_t blen; + int change, rval; + CHAR_T ch, *p, *t; + char *bp; + + GET_SPACE_RET(sp, bp, blen, len); + memmove(bp, lp, len); + + change = rval = 0; + for (p = bp + scno, t = bp + ecno + 1; p < t; ++p) { + ch = *(u_char *)p; + if (islower(ch)) { + *p = toupper(ch); + change = 1; + } else if (isupper(ch)) { + *p = tolower(ch); + change = 1; + } + } + + if (change && db_set(sp, lno, bp, len)) + rval = 1; + + FREE_SPACE(sp, bp, blen); + return (rval); +} |