summaryrefslogtreecommitdiffstats
path: root/contrib/nvi/vi/v_ulcase.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/nvi/vi/v_ulcase.c')
-rw-r--r--contrib/nvi/vi/v_ulcase.c179
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);
+}
OpenPOWER on IntegriCloud