Changing all of the occurences of the "vi" and "ex" directory to "vi.d"
[unix-history] / usr.bin / vi / nvi / v_ulcase.c
CommitLineData
18ae9d6b
AS
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)v_ulcase.c 8.3 (Berkeley) 12/9/93";
36#endif /* not lint */
37
38#include <sys/types.h>
39
40#include <ctype.h>
41#include <errno.h>
42#include <stdlib.h>
43#include <string.h>
44
45#include "vi.h"
46#include "vcmd.h"
47
48/*
49 * v_ulcase -- [count]~
50 * Toggle upper & lower case letters.
51 *
52 * !!!
53 * In historic vi, the count was ignored. It would have been better
54 * if there had been an associated motion, but it's too late to change
55 * it now.
56 */
57int
58v_ulcase(sp, ep, vp, fm, tm, rp)
59 SCR *sp;
60 EXF *ep;
61 VICMDARG *vp;
62 MARK *fm, *tm, *rp;
63{
64 recno_t lno;
65 size_t blen, lcnt, len;
66 u_long cnt;
67 int ch, change, rval;
68 char *bp, *p;
69
70 /* Figure out what memory to use. */
71 GET_SPACE_RET(sp, bp, blen, 256);
72
73 /*
74 * !!!
75 * Historic vi didn't permit ~ to cross newline boundaries.
76 * I can think of no reason why it shouldn't, which at least
77 * lets you auto-repeat through a paragraph.
78 */
79 rval = 0;
80 for (change = -1, cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt;) {
81 /* Get the line; EOF is an infinite sink. */
82 if ((p = file_gline(sp, ep, fm->lno, &len)) == NULL) {
83 if (file_lline(sp, ep, &lno))
84 return (1);
85 if (lno >= fm->lno) {
86 GETLINE_ERR(sp, fm->lno);
87 rval = 1;
88 break;
89 }
90 if (change == -1) {
91 v_eof(sp, ep, NULL);
92 return (1);
93 }
94 break;
95 }
96
97 /* Set current line number. */
98 lno = fm->lno;
99
100 /* Empty lines just decrement the count. */
101 if (len == 0) {
102 --cnt;
103 ++fm->lno;
104 fm->cno = 0;
105 change = 0;
106 continue;
107 }
108
109 /* Get a copy of the line. */
110 ADD_SPACE_RET(sp, bp, blen, len);
111 memmove(bp, p, len);
112
113 /* Set starting pointer. */
114 if (change == -1)
115 p = bp + fm->cno;
116 else
117 p = bp;
118
119 /*
120 * Figure out how many characters get changed in this
121 * line. Set the final cursor column.
122 */
123 if (fm->cno + cnt >= len) {
124 lcnt = len - fm->cno;
125 ++fm->lno;
126 fm->cno = 0;
127 } else
128 fm->cno += lcnt = cnt;
129 cnt -= lcnt;
130
131 /* Change the line. */
132 for (change = 0; lcnt--; ++p) {
133 ch = *(u_char *)p;
134 if (islower(ch)) {
135 *p = toupper(ch);
136 change = 1;
137 } else if (isupper(ch)) {
138 *p = tolower(ch);
139 change = 1;
140 }
141 }
142
143 /* Update the line if necessary. */
144 if (change && file_sline(sp, ep, lno, bp, len)) {
145 rval = 1;
146 break;
147 }
148 }
149
150 /* If changed lines, could be on an illegal line. */
151 if (fm->lno != lno && file_gline(sp, ep, fm->lno, &len) == NULL) {
152 --fm->lno;
153 fm->cno = len ? len - 1 : 0;
154 }
155 *rp = *fm;
156
157 FREE_SPACE(sp, bp, blen);
158 return (rval);
159}