home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / vi / v_match.c < prev    next >
C/C++ Source or Header  |  1996-04-27  |  4KB  |  171 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_match.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 <string.h>
  24.  
  25. #include "../common/common.h"
  26. #include "vi.h"
  27.  
  28. /*
  29.  * v_match -- %
  30.  *    Search to matching character.
  31.  *
  32.  * PUBLIC: int v_match __P((SCR *, VICMD *));
  33.  */
  34. int
  35. v_match(sp, vp)
  36.     SCR *sp;
  37.     VICMD *vp;
  38. {
  39.     VCS cs;
  40.     MARK *mp;
  41.     size_t cno, len, off;
  42.     int cnt, isempty, matchc, startc, (*gc)__P((SCR *, VCS *));
  43.     char *p;
  44.  
  45.     /*
  46.      * !!!
  47.      * Historic practice; ignore the count.
  48.      *
  49.      * !!!
  50.      * Historical practice was to search for the initial character in the
  51.      * forward direction only.
  52.      */
  53.     if (db_eget(sp, vp->m_start.lno, &p, &len, &isempty)) {
  54.         if (isempty)
  55.             goto nomatch;
  56.         return (1);
  57.     }
  58.     for (off = vp->m_start.cno;; ++off) {
  59.         if (off >= len) {
  60. nomatch:        msgq(sp, M_BERR, "184|No match character on this line");
  61.             return (1);
  62.         }
  63.         switch (startc = p[off]) {
  64.         case '(':
  65.             matchc = ')';
  66.             gc = cs_next;
  67.             break;
  68.         case ')':
  69.             matchc = '(';
  70.             gc = cs_prev;
  71.             break;
  72.         case '[':
  73.             matchc = ']';
  74.             gc = cs_next;
  75.             break;
  76.         case ']':
  77.             matchc = '[';
  78.             gc = cs_prev;
  79.             break;
  80.         case '{':
  81.             matchc = '}';
  82.             gc = cs_next;
  83.             break;
  84.         case '}':
  85.             matchc = '{';
  86.             gc = cs_prev;
  87.             break;
  88.         case '<':
  89.             matchc = '>';
  90.             gc = cs_next;
  91.             break;
  92.         case '>':
  93.             matchc = '<';
  94.             gc = cs_prev;
  95.             break;
  96.         default:
  97.             continue;
  98.         }
  99.         break;
  100.     }
  101.  
  102.     cs.cs_lno = vp->m_start.lno;
  103.     cs.cs_cno = off;
  104.     if (cs_init(sp, &cs))
  105.         return (1);
  106.     for (cnt = 1;;) {
  107.         if (gc(sp, &cs))
  108.             return (1);
  109.         if (cs.cs_flags != 0) {
  110.             if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF)
  111.                 break;
  112.             continue;
  113.         }
  114.         if (cs.cs_ch == startc)
  115.             ++cnt;
  116.         else if (cs.cs_ch == matchc && --cnt == 0)
  117.             break;
  118.     }
  119.     if (cnt) {
  120.         msgq(sp, M_BERR, "185|Matching character not found");
  121.         return (1);
  122.     }
  123.  
  124.     vp->m_stop.lno = cs.cs_lno;
  125.     vp->m_stop.cno = cs.cs_cno;
  126.  
  127.     /*
  128.      * If moving right, non-motion commands move to the end of the range.
  129.      * Delete and yank stay at the start.
  130.      *
  131.      * If moving left, all commands move to the end of the range.
  132.      *
  133.      * !!!
  134.      * Don't correct for leftward movement -- historic vi deleted the
  135.      * starting cursor position when deleting to a match.
  136.      */
  137.     if (vp->m_start.lno < vp->m_stop.lno ||
  138.         vp->m_start.lno == vp->m_stop.lno &&
  139.         vp->m_start.cno < vp->m_stop.cno)
  140.         vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
  141.     else
  142.         vp->m_final = vp->m_stop;
  143.  
  144.     /*
  145.      * !!!
  146.      * If the motion is across lines, and the earliest cursor position
  147.      * is at or before any non-blank characters in the line, i.e. the
  148.      * movement is cutting all of the line's text, and the later cursor
  149.      * position has nothing other than whitespace characters between it
  150.      * and the end of its line, the buffer is in line mode.
  151.      */
  152.     if (!ISMOTION(vp) || vp->m_start.lno == vp->m_stop.lno)
  153.         return (0);
  154.     mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_start : &vp->m_stop;
  155.     if (mp->cno != 0) {
  156.         cno = 0;
  157.         if (nonblank(sp, mp->lno, &cno))
  158.             return (1);
  159.         if (cno < mp->cno)
  160.             return (0);
  161.     }
  162.     mp = vp->m_start.lno < vp->m_stop.lno ? &vp->m_stop : &vp->m_start;
  163.     if (db_get(sp, mp->lno, DBG_FATAL, &p, &len))
  164.         return (1);
  165.     for (p += mp->cno + 1, len -= mp->cno; --len; ++p)
  166.         if (!isblank(*p))
  167.             return (0);
  168.     F_SET(vp, VM_LMODE);
  169.     return (0);
  170. }
  171.