home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / vi / v_ulcase.c < prev    next >
C/C++ Source or Header  |  1996-04-27  |  4KB  |  180 lines

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