home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / vi / v_ch.c < prev    next >
C/C++ Source or Header  |  1996-04-27  |  6KB  |  296 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_ch.c    10.8 (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 <limits.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24.  
  25. #include "../common/common.h"
  26. #include "vi.h"
  27.  
  28. static void notfound __P((SCR *, ARG_CHAR_T));
  29. static void noprev __P((SCR *));
  30.  
  31. /*
  32.  * v_chrepeat -- [count];
  33.  *    Repeat the last F, f, T or t search.
  34.  *
  35.  * PUBLIC: int v_chrepeat __P((SCR *, VICMD *));
  36.  */
  37. int
  38. v_chrepeat(sp, vp)
  39.     SCR *sp;
  40.     VICMD *vp;
  41. {
  42.     vp->character = VIP(sp)->lastckey;
  43.  
  44.     switch (VIP(sp)->csearchdir) {
  45.     case CNOTSET:
  46.         noprev(sp);
  47.         return (1);
  48.     case FSEARCH:
  49.         return (v_chF(sp, vp));
  50.     case fSEARCH:
  51.         return (v_chf(sp, vp));
  52.     case TSEARCH:
  53.         return (v_chT(sp, vp));
  54.     case tSEARCH:
  55.         return (v_cht(sp, vp));
  56.     default:
  57.         abort();
  58.     }
  59.     /* NOTREACHED */
  60. }
  61.  
  62. /*
  63.  * v_chrrepeat -- [count],
  64.  *    Repeat the last F, f, T or t search in the reverse direction.
  65.  *
  66.  * PUBLIC: int v_chrrepeat __P((SCR *, VICMD *));
  67.  */
  68. int
  69. v_chrrepeat(sp, vp)
  70.     SCR *sp;
  71.     VICMD *vp;
  72. {
  73.     cdir_t savedir;
  74.     int rval;
  75.  
  76.     vp->character = VIP(sp)->lastckey;
  77.     savedir = VIP(sp)->csearchdir;
  78.  
  79.     switch (VIP(sp)->csearchdir) {
  80.     case CNOTSET:
  81.         noprev(sp);
  82.         return (1);
  83.     case FSEARCH:
  84.         rval = v_chf(sp, vp);
  85.         break;
  86.     case fSEARCH:
  87.         rval = v_chF(sp, vp);
  88.         break;
  89.     case TSEARCH:
  90.         rval = v_cht(sp, vp);
  91.         break;
  92.     case tSEARCH:
  93.         rval = v_chT(sp, vp);
  94.         break;
  95.     default:
  96.         abort();
  97.     }
  98.     VIP(sp)->csearchdir = savedir;
  99.     return (rval);
  100. }
  101.  
  102. /*
  103.  * v_cht -- [count]tc
  104.  *    Search forward in the line for the character before the next
  105.  *    occurrence of the specified character.
  106.  *
  107.  * PUBLIC: int v_cht __P((SCR *, VICMD *));
  108.  */
  109. int
  110. v_cht(sp, vp)
  111.     SCR *sp;
  112.     VICMD *vp;
  113. {
  114.     if (v_chf(sp, vp))
  115.         return (1);
  116.  
  117.     /*
  118.      * v_chf places the cursor on the character, where the 't'
  119.      * command wants it to its left.  We know this is safe since
  120.      * we had to move right for v_chf() to have succeeded.
  121.      */
  122.     --vp->m_stop.cno;
  123.  
  124.     /*
  125.      * Make any necessary correction to the motion decision made
  126.      * by the v_chf routine.
  127.      */
  128.     if (!ISMOTION(vp))
  129.         vp->m_final = vp->m_stop;
  130.  
  131.     VIP(sp)->csearchdir = tSEARCH;
  132.     return (0);
  133. }
  134.  
  135. /*
  136.  * v_chf -- [count]fc
  137.  *    Search forward in the line for the next occurrence of the
  138.  *    specified character.
  139.  *
  140.  * PUBLIC: int v_chf __P((SCR *, VICMD *));
  141.  */
  142. int
  143. v_chf(sp, vp)
  144.     SCR *sp;
  145.     VICMD *vp;
  146. {
  147.     size_t len;
  148.     u_long cnt;
  149.     int isempty, key;
  150.     char *endp, *p, *startp;
  151.  
  152.     /*
  153.      * !!!
  154.      * If it's a dot command, it doesn't reset the key for which we're
  155.      * searching, e.g. in "df1|f2|.|;", the ';' searches for a '2'.
  156.      */
  157.     key = vp->character;
  158.     if (!F_ISSET(vp, VC_ISDOT))
  159.         VIP(sp)->lastckey = key;
  160.     VIP(sp)->csearchdir = fSEARCH;
  161.  
  162.     if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
  163.         if (isempty)
  164.             goto empty;
  165.         return (1);
  166.     }
  167.  
  168.     if (len == 0) {
  169. empty:        notfound(sp, key);
  170.         return (1);
  171.     }
  172.  
  173.     endp = (startp = p) + len;
  174.     p += vp->m_start.cno;
  175.     for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
  176.         while (++p < endp && *p != key);
  177.         if (p == endp) {
  178.             notfound(sp, key);
  179.             return (1);
  180.         }
  181.     }
  182.  
  183.     vp->m_stop.cno = p - startp;
  184.  
  185.     /*
  186.      * Non-motion commands move to the end of the range.
  187.      * Delete and yank stay at the start, ignore others.
  188.      */
  189.     vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
  190.     return (0);
  191. }
  192.  
  193. /*
  194.  * v_chT -- [count]Tc
  195.  *    Search backward in the line for the character after the next
  196.  *    occurrence of the specified character.
  197.  *
  198.  * PUBLIC: int v_chT __P((SCR *, VICMD *));
  199.  */
  200. int
  201. v_chT(sp, vp)
  202.     SCR *sp;
  203.     VICMD *vp;
  204. {
  205.     if (v_chF(sp, vp))
  206.         return (1);
  207.  
  208.     /*
  209.      * v_chF places the cursor on the character, where the 'T'
  210.      * command wants it to its right.  We know this is safe since
  211.      * we had to move left for v_chF() to have succeeded.
  212.      */
  213.     ++vp->m_stop.cno;
  214.     vp->m_final = vp->m_stop;
  215.  
  216.     VIP(sp)->csearchdir = TSEARCH;
  217.     return (0);
  218. }
  219.  
  220. /*
  221.  * v_chF -- [count]Fc
  222.  *    Search backward in the line for the next occurrence of the
  223.  *    specified character.
  224.  *
  225.  * PUBLIC: int v_chF __P((SCR *, VICMD *));
  226.  */
  227. int
  228. v_chF(sp, vp)
  229.     SCR *sp;
  230.     VICMD *vp;
  231. {
  232.     size_t len;
  233.     u_long cnt;
  234.     int isempty, key;
  235.     char *endp, *p;
  236.  
  237.     /*
  238.      * !!!
  239.      * If it's a dot command, it doesn't reset the key for which
  240.      * we're searching, e.g. in "df1|f2|.|;", the ';' searches
  241.      * for a '2'.
  242.      */
  243.     key = vp->character;
  244.     if (!F_ISSET(vp, VC_ISDOT))
  245.         VIP(sp)->lastckey = key;
  246.     VIP(sp)->csearchdir = FSEARCH;
  247.  
  248.     if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
  249.         if (isempty)
  250.             goto empty;
  251.         return (1);
  252.     }
  253.  
  254.     if (len == 0) {
  255. empty:        notfound(sp, key);
  256.         return (1);
  257.     }
  258.  
  259.     endp = p - 1;
  260.     p += vp->m_start.cno;
  261.     for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
  262.         while (--p > endp && *p != key);
  263.         if (p == endp) {
  264.             notfound(sp, key);
  265.             return (1);
  266.         }
  267.     }
  268.  
  269.     vp->m_stop.cno = (p - endp) - 1;
  270.  
  271.     /*
  272.      * All commands move to the end of the range.  Motion commands
  273.      * adjust the starting point to the character before the current
  274.      * one.
  275.      */
  276.     vp->m_final = vp->m_stop;
  277.     if (ISMOTION(vp))
  278.         --vp->m_start.cno;
  279.     return (0);
  280. }
  281.  
  282. static void
  283. noprev(sp)
  284.     SCR *sp;
  285. {
  286.     msgq(sp, M_BERR, "178|No previous F, f, T or t search");
  287. }
  288.  
  289. static void
  290. notfound(sp, ch)
  291.     SCR *sp;
  292.     ARG_CHAR_T ch;
  293. {
  294.     msgq(sp, M_BERR, "179|%s not found", KEY_NAME(sp, ch));
  295. }
  296.