update to 1.01
[nvi.git] / vi / v_ulcase.c
blobc1384640895d5951fafb9fada36ddd9d7679d44f
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: v_ulcase.c,v 8.3 1993/12/09 19:43:21 bostic Exp $ (Berkeley) $Date: 1993/12/09 19:43:21 $";
10 #endif /* not lint */
12 #include <sys/types.h>
14 #include <ctype.h>
15 #include <errno.h>
16 #include <stdlib.h>
17 #include <string.h>
19 #include "vi.h"
20 #include "vcmd.h"
23 * v_ulcase -- [count]~
24 * Toggle upper & lower case letters.
26 * !!!
27 * In historic vi, the count was ignored. It would have been better
28 * if there had been an associated motion, but it's too late to change
29 * it now.
31 int
32 v_ulcase(sp, ep, vp, fm, tm, rp)
33 SCR *sp;
34 EXF *ep;
35 VICMDARG *vp;
36 MARK *fm, *tm, *rp;
38 recno_t lno;
39 size_t blen, lcnt, len;
40 u_long cnt;
41 int ch, change, rval;
42 char *bp, *p;
44 /* Figure out what memory to use. */
45 GET_SPACE_RET(sp, bp, blen, 256);
48 * !!!
49 * Historic vi didn't permit ~ to cross newline boundaries.
50 * I can think of no reason why it shouldn't, which at least
51 * lets you auto-repeat through a paragraph.
53 rval = 0;
54 for (change = -1, cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt;) {
55 /* Get the line; EOF is an infinite sink. */
56 if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
57 if (file_lline(sp, ep, &lno))
58 return (1);
59 if (lno >= fm->lno) {
60 GETLINE_ERR(sp, fm->lno);
61 rval = 1;
62 break;
64 if (change == -1) {
65 v_eof(sp, ep, NULL);
66 return (1);
68 break;
71 /* Set current line number. */
72 lno = fm->lno;
74 /* Empty lines just decrement the count. */
75 if (len == 0) {
76 --cnt;
77 ++fm->lno;
78 fm->cno = 0;
79 change = 0;
80 continue;
83 /* Get a copy of the line. */
84 ADD_SPACE_RET(sp, bp, blen, len);
85 memmove(bp, p, len);
87 /* Set starting pointer. */
88 if (change == -1)
89 p = bp + fm->cno;
90 else
91 p = bp;
94 * Figure out how many characters get changed in this
95 * line. Set the final cursor column.
97 if (fm->cno + cnt >= len) {
98 lcnt = len - fm->cno;
99 ++fm->lno;
100 fm->cno = 0;
101 } else
102 fm->cno += lcnt = cnt;
103 cnt -= lcnt;
105 /* Change the line. */
106 for (change = 0; lcnt--; ++p) {
107 ch = *(u_char *)p;
108 if (islower(ch)) {
109 *p = toupper(ch);
110 change = 1;
111 } else if (isupper(ch)) {
112 *p = tolower(ch);
113 change = 1;
117 /* Update the line if necessary. */
118 if (change && file_sline(sp, ep, lno, bp, len)) {
119 rval = 1;
120 break;
124 /* If changed lines, could be on an illegal line. */
125 if (fm->lno != lno && file_gline(sp, ep, fm->lno, &len) == NULL) {
126 --fm->lno;
127 fm->cno = len ? len - 1 : 0;
129 *rp = *fm;
131 FREE_SPACE(sp, bp, blen);
132 return (rval);