Home | History | Annotate | Line # | Download | only in vi
v_ulcase.c revision 1.3.8.2
      1  1.3.8.2  tls /*	$NetBSD: v_ulcase.c,v 1.3.8.2 2014/08/19 23:51:53 tls Exp $ */
      2  1.3.8.2  tls /*-
      3  1.3.8.2  tls  * Copyright (c) 1992, 1993, 1994
      4  1.3.8.2  tls  *	The Regents of the University of California.  All rights reserved.
      5  1.3.8.2  tls  * Copyright (c) 1992, 1993, 1994, 1995, 1996
      6  1.3.8.2  tls  *	Keith Bostic.  All rights reserved.
      7  1.3.8.2  tls  *
      8  1.3.8.2  tls  * See the LICENSE file for redistribution information.
      9  1.3.8.2  tls  */
     10  1.3.8.2  tls 
     11  1.3.8.2  tls #include "config.h"
     12  1.3.8.2  tls 
     13  1.3.8.2  tls #include <sys/cdefs.h>
     14  1.3.8.2  tls #if 0
     15  1.3.8.2  tls #ifndef lint
     16  1.3.8.2  tls static const char sccsid[] = "Id: v_ulcase.c,v 10.11 2001/06/25 15:19:36 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:36 ";
     17  1.3.8.2  tls #endif /* not lint */
     18  1.3.8.2  tls #else
     19  1.3.8.2  tls __RCSID("$NetBSD: v_ulcase.c,v 1.3.8.2 2014/08/19 23:51:53 tls Exp $");
     20  1.3.8.2  tls #endif
     21  1.3.8.2  tls 
     22  1.3.8.2  tls #include <sys/types.h>
     23  1.3.8.2  tls #include <sys/queue.h>
     24  1.3.8.2  tls #include <sys/time.h>
     25  1.3.8.2  tls 
     26  1.3.8.2  tls #include <bitstring.h>
     27  1.3.8.2  tls #include <ctype.h>
     28  1.3.8.2  tls #include <errno.h>
     29  1.3.8.2  tls #include <limits.h>
     30  1.3.8.2  tls #include <stdio.h>
     31  1.3.8.2  tls #include <stdlib.h>
     32  1.3.8.2  tls #include <string.h>
     33  1.3.8.2  tls 
     34  1.3.8.2  tls #include "../common/common.h"
     35  1.3.8.2  tls #include "vi.h"
     36  1.3.8.2  tls 
     37  1.3.8.2  tls static int ulcase __P((SCR *, db_recno_t, CHAR_T *, size_t, size_t, size_t));
     38  1.3.8.2  tls 
     39  1.3.8.2  tls /*
     40  1.3.8.2  tls  * v_ulcase -- [count]~
     41  1.3.8.2  tls  *	Toggle upper & lower case letters.
     42  1.3.8.2  tls  *
     43  1.3.8.2  tls  * !!!
     44  1.3.8.2  tls  * Historic vi didn't permit ~ to cross newline boundaries.  I can
     45  1.3.8.2  tls  * think of no reason why it shouldn't, which at least lets the user
     46  1.3.8.2  tls  * auto-repeat through a paragraph.
     47  1.3.8.2  tls  *
     48  1.3.8.2  tls  * !!!
     49  1.3.8.2  tls  * In historic vi, the count was ignored.  It would have been better
     50  1.3.8.2  tls  * if there had been an associated motion, but it's too late to make
     51  1.3.8.2  tls  * that the default now.
     52  1.3.8.2  tls  *
     53  1.3.8.2  tls  * PUBLIC: int v_ulcase __P((SCR *, VICMD *));
     54  1.3.8.2  tls  */
     55  1.3.8.2  tls int
     56  1.3.8.2  tls v_ulcase(SCR *sp, VICMD *vp)
     57  1.3.8.2  tls {
     58  1.3.8.2  tls 	db_recno_t lno;
     59  1.3.8.2  tls 	size_t cno, lcnt, len;
     60  1.3.8.2  tls 	u_long cnt;
     61  1.3.8.2  tls 	CHAR_T *p;
     62  1.3.8.2  tls 
     63  1.3.8.2  tls 	lno = vp->m_start.lno;
     64  1.3.8.2  tls 	cno = vp->m_start.cno;
     65  1.3.8.2  tls 
     66  1.3.8.2  tls 	for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt > 0; cno = 0) {
     67  1.3.8.2  tls 		/* SOF is an error, EOF is an infinite count sink. */
     68  1.3.8.2  tls 		if (db_get(sp, lno, 0, &p, &len)) {
     69  1.3.8.2  tls 			if (lno == 1) {
     70  1.3.8.2  tls 				v_emsg(sp, NULL, VIM_EMPTY);
     71  1.3.8.2  tls 				return (1);
     72  1.3.8.2  tls 			}
     73  1.3.8.2  tls 			--lno;
     74  1.3.8.2  tls 			break;
     75  1.3.8.2  tls 		}
     76  1.3.8.2  tls 
     77  1.3.8.2  tls 		/* Empty lines decrement the count by one. */
     78  1.3.8.2  tls 		if (len == 0) {
     79  1.3.8.2  tls 			--cnt;
     80  1.3.8.2  tls 			vp->m_final.cno = 0;
     81  1.3.8.2  tls 			continue;
     82  1.3.8.2  tls 		}
     83  1.3.8.2  tls 
     84  1.3.8.2  tls 		if (cno + cnt >= len) {
     85  1.3.8.2  tls 			lcnt = len - 1;
     86  1.3.8.2  tls 			cnt -= len - cno;
     87  1.3.8.2  tls 
     88  1.3.8.2  tls 			vp->m_final.cno = len - 1;
     89  1.3.8.2  tls 		} else {
     90  1.3.8.2  tls 			lcnt = cno + cnt - 1;
     91  1.3.8.2  tls 			cnt = 0;
     92  1.3.8.2  tls 
     93  1.3.8.2  tls 			vp->m_final.cno = lcnt + 1;
     94  1.3.8.2  tls 		}
     95  1.3.8.2  tls 
     96  1.3.8.2  tls 		if (ulcase(sp, lno, p, len, cno, lcnt))
     97  1.3.8.2  tls 			return (1);
     98  1.3.8.2  tls 
     99  1.3.8.2  tls 		if (cnt > 0)
    100  1.3.8.2  tls 			++lno;
    101  1.3.8.2  tls 	}
    102  1.3.8.2  tls 
    103  1.3.8.2  tls 	vp->m_final.lno = lno;
    104  1.3.8.2  tls 	return (0);
    105  1.3.8.2  tls }
    106  1.3.8.2  tls 
    107  1.3.8.2  tls /*
    108  1.3.8.2  tls  * v_mulcase -- [count]~[count]motion
    109  1.3.8.2  tls  *	Toggle upper & lower case letters over a range.
    110  1.3.8.2  tls  *
    111  1.3.8.2  tls  * PUBLIC: int v_mulcase __P((SCR *, VICMD *));
    112  1.3.8.2  tls  */
    113  1.3.8.2  tls int
    114  1.3.8.2  tls v_mulcase(SCR *sp, VICMD *vp)
    115  1.3.8.2  tls {
    116  1.3.8.2  tls 	CHAR_T *p;
    117  1.3.8.2  tls 	size_t len;
    118  1.3.8.2  tls 	db_recno_t lno;
    119  1.3.8.2  tls 
    120  1.3.8.2  tls 	for (lno = vp->m_start.lno;;) {
    121  1.3.8.2  tls 		if (db_get(sp, lno, DBG_FATAL, &p, &len))
    122  1.3.8.2  tls 			return (1);
    123  1.3.8.2  tls 		if (len != 0 && ulcase(sp, lno, p, len,
    124  1.3.8.2  tls 		    lno == vp->m_start.lno ? vp->m_start.cno : 0,
    125  1.3.8.2  tls 		    !F_ISSET(vp, VM_LMODE) &&
    126  1.3.8.2  tls 		    lno == vp->m_stop.lno ? vp->m_stop.cno : len))
    127  1.3.8.2  tls 			return (1);
    128  1.3.8.2  tls 
    129  1.3.8.2  tls 		if (++lno > vp->m_stop.lno)
    130  1.3.8.2  tls 			break;
    131  1.3.8.2  tls 	}
    132  1.3.8.2  tls 
    133  1.3.8.2  tls 	/*
    134  1.3.8.2  tls 	 * XXX
    135  1.3.8.2  tls 	 * I didn't create a new motion command when I added motion semantics
    136  1.3.8.2  tls 	 * for ~.  While that's the correct way to do it, that choice would
    137  1.3.8.2  tls 	 * have required changes all over the vi directory for little gain.
    138  1.3.8.2  tls 	 * Instead, we pretend it's a yank command.  Note, this means that we
    139  1.3.8.2  tls 	 * follow the cursor motion rules for yank commands, but that seems
    140  1.3.8.2  tls 	 * reasonable to me.
    141  1.3.8.2  tls 	 */
    142  1.3.8.2  tls 	return (0);
    143  1.3.8.2  tls }
    144  1.3.8.2  tls 
    145  1.3.8.2  tls /*
    146  1.3.8.2  tls  * ulcase --
    147  1.3.8.2  tls  *	Change part of a line's case.
    148  1.3.8.2  tls  */
    149  1.3.8.2  tls static int
    150  1.3.8.2  tls ulcase(SCR *sp, db_recno_t lno, CHAR_T *lp, size_t len, size_t scno, size_t ecno)
    151  1.3.8.2  tls {
    152  1.3.8.2  tls 	size_t blen;
    153  1.3.8.2  tls 	int change, rval;
    154  1.3.8.2  tls 	ARG_CHAR_T ch;
    155  1.3.8.2  tls 	CHAR_T *p, *t, *bp;
    156  1.3.8.2  tls 
    157  1.3.8.2  tls 	GET_SPACE_RETW(sp, bp, blen, len);
    158  1.3.8.2  tls 	MEMMOVEW(bp, lp, len);
    159  1.3.8.2  tls 
    160  1.3.8.2  tls 	change = rval = 0;
    161  1.3.8.2  tls 	for (p = bp + scno, t = bp + ecno + 1; p < t; ++p) {
    162  1.3.8.2  tls 		ch = (UCHAR_T)*p;
    163  1.3.8.2  tls 		if (ISLOWER(ch)) {
    164  1.3.8.2  tls 			*p = TOUPPER(ch);
    165  1.3.8.2  tls 			change = 1;
    166  1.3.8.2  tls 		} else if (ISUPPER(ch)) {
    167  1.3.8.2  tls 			*p = TOLOWER(ch);
    168  1.3.8.2  tls 			change = 1;
    169  1.3.8.2  tls 		}
    170  1.3.8.2  tls 	}
    171  1.3.8.2  tls 
    172  1.3.8.2  tls 	if (change && db_set(sp, lno, bp, len))
    173  1.3.8.2  tls 		rval = 1;
    174  1.3.8.2  tls 
    175  1.3.8.2  tls 	FREE_SPACEW(sp, bp, blen);
    176  1.3.8.2  tls 	return (rval);
    177  1.3.8.2  tls }
    178