File: [local] / src / usr.bin / vi / vi / v_ulcase.c (download)
Revision 1.10, Fri May 27 09:18:12 2016 UTC (8 years ago) by martijn
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, OPENBSD_6_9_BASE, OPENBSD_6_9, OPENBSD_6_8_BASE, OPENBSD_6_8, OPENBSD_6_7_BASE, OPENBSD_6_7, OPENBSD_6_6_BASE, OPENBSD_6_6, OPENBSD_6_5_BASE, OPENBSD_6_5, OPENBSD_6_4_BASE, OPENBSD_6_4, OPENBSD_6_3_BASE, OPENBSD_6_3, OPENBSD_6_2_BASE, OPENBSD_6_2, OPENBSD_6_1_BASE, OPENBSD_6_1, OPENBSD_6_0_BASE, OPENBSD_6_0, HEAD Changes since 1.9: +5 -5 lines
Revert CHAR_T removal. Some signedness flaws were introduced.
Found the hard way by jca@
|
/* $OpenBSD: v_ulcase.c,v 1.10 2016/05/27 09:18:12 martijn Exp $ */
/*-
* 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"
#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(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(SCR *, VICMD *);
*/
int
v_ulcase(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(SCR *, VICMD *);
*/
int
v_mulcase(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, (char **) &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(SCR *sp, recno_t lno, CHAR_T *lp, size_t len, size_t scno, size_t 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);
}