home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / elvis184.zip / src / move2.c < prev    next >
C/C++ Source or Header  |  1995-05-26  |  6KB  |  318 lines

  1. /* move2.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    1500 SW Park #326
  6.  *    Portland OR, 97201
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This function contains the movement functions that perform RE searching */
  12.  
  13. #include "config.h"
  14. #include "vi.h"
  15. #include "regexp.h"
  16. #include <string.h>
  17.  
  18.  
  19. static regexp    *re;    /* compiled version of the pattern to search for */
  20. static        prevsf;    /* boolean: previous search direction was forward? */
  21.  
  22. #ifndef NO_EXTENSIONS
  23. /*ARGSUSED*/
  24. MARK m_wsrch(word, m, cnt)
  25.     char    *word;    /* the word to search for */
  26.     MARK    m;    /* the starting point */
  27.     int    cnt;    /* ignored */
  28. {
  29.     char    buffer[WSRCH_MAX + 6];
  30.  
  31.     /* wrap \< and \> around the word */
  32.     strncpy(buffer, "/\\<", WSRCH_MAX + 6);
  33.     strncat(buffer, word, WSRCH_MAX);
  34.     strcat(buffer, "\\>");
  35.  
  36.     /* show the searched-for word on the bottom line */
  37.     move(LINES - 1, 0);
  38.     qaddstr(buffer);
  39.     clrtoeol();
  40.     refresh();
  41.  
  42.     /* search for the word */
  43.     return m_fsrch(m, buffer);
  44. }
  45. #endif
  46.  
  47. MARK    m_nsrch(m, cnt, cmd)
  48.     MARK    m;    /* where to start searching */
  49.     long    cnt;    /* number of searches to do */
  50.     int    cmd;    /* command character -- 'n' or 'N' */
  51. {
  52.     int    oldprevsf; /* original value of prevsf, so we can fix any changes */
  53.  
  54.     DEFAULT(1L);
  55.  
  56.     /* clear the bottom line.  In particular, we want to loose any
  57.      * "(wrapped)" notice.
  58.      */
  59.     move(LINES - 1, 0);
  60.     clrtoeol();
  61.  
  62.     /* if 'N' command, then invert the "prevsf" variable */
  63.     oldprevsf = prevsf;
  64.     if (cmd == 'N')
  65.     {
  66.         prevsf = !prevsf;
  67.     }
  68.  
  69.     /* search forward if prevsf -- i.e., if previous search was forward */
  70.     while (--cnt >= 0L && m != MARK_UNSET)
  71.     {
  72.         if (prevsf)
  73.         {
  74.             m = m_fsrch(m, (char *)0);
  75.         }
  76.         else
  77.         {
  78.             m = m_bsrch(m, (char *)0);
  79.         }
  80.     }
  81.  
  82.     /* restore the old value of prevsf -- if cmd=='N' then it was inverted,
  83.      * and the m_fsrch() and m_bsrch() functions force it to a (possibly
  84.      * incorrect) value.  The value of prevsf isn't supposed to be changed
  85.      * at all here!
  86.      */
  87.     prevsf = oldprevsf;
  88.     return m;
  89. }
  90.  
  91.  
  92. MARK    m_fsrch(m, ptrn)
  93.     MARK    m;    /* where to start searching */
  94.     char    *ptrn;    /* pattern to search for */
  95. {
  96.     long    l;    /* line# of line to be searched */
  97.     char    *line;    /* text of line to be searched */
  98.     int    wrapped;/* boolean: has our search wrapped yet? */
  99.     int    pos;    /* where we are in the line */
  100. #ifndef CRUNCH
  101.     long    delta = INFINITY;/* line offset, for things like "/foo/+1" */
  102. #endif
  103.  
  104.     /* remember: "previous search was forward" */
  105.     prevsf = TRUE;
  106.  
  107.     if (ptrn && *ptrn)
  108.     {
  109.         /* locate the closing '/', if any */
  110.         line = parseptrn(ptrn);
  111. #ifndef CRUNCH
  112.         if (*line)
  113.         {
  114.             delta = atol(line);
  115.         }
  116. #endif
  117.         ptrn++;
  118.  
  119.         /* free the previous pattern */
  120.         if (re) _free_(re);
  121.  
  122.         /* compile the pattern */
  123.         re = regcomp(ptrn);
  124.         if (!re)
  125.         {
  126.             return MARK_UNSET;
  127.         }
  128.     }
  129.     else if (!re)
  130.     {
  131.         msg("No previous expression");
  132.         return MARK_UNSET;
  133.     }
  134.  
  135.     /* search forward for the pattern */
  136.     pos = markidx(m) + 1;
  137.     pfetch(markline(m));
  138.     if (pos >= plen)
  139.     {
  140.         pos = 0;
  141.         m = (m | (BLKSIZE - 1)) + 1;
  142.     }
  143.     wrapped = FALSE;
  144.     for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
  145.     {
  146.         /* wrap search */
  147.         if (l > nlines)
  148.         {
  149.             /* if we wrapped once already, then the search failed */
  150.             if (wrapped)
  151.             {
  152.                 break;
  153.             }
  154.  
  155.             /* else maybe we should wrap now? */
  156.             if (*o_wrapscan)
  157.             {
  158.                 l = 0;
  159.                 wrapped = TRUE;
  160.                 continue;
  161.             }
  162.             else
  163.             {
  164.                 break;
  165.             }
  166.         }
  167.  
  168.         /* get this line */
  169.         line = fetchline(l);
  170.  
  171.         /* check this line */
  172.         if (regexec(re, &line[pos], (pos == 0)))
  173.         {
  174.             /* match! */
  175.             if (wrapped && *o_warn)
  176.                 msg("(wrapped)");
  177. #ifndef CRUNCH
  178.             if (delta != INFINITY)
  179.             {
  180.                 l += delta;
  181.                 if (l < 1 || l > nlines)
  182.                 {
  183.                     msg("search offset too big");
  184.                     return MARK_UNSET;
  185.                 }
  186.                 force_flags = LNMD|INCL;
  187.                 return MARK_AT_LINE(l);
  188.             }
  189. #endif
  190.             if (re->leavep)
  191.                 return MARK_AT_LINE(l) + (int)(re->leavep - line);
  192.             else
  193.                 return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
  194.         }
  195.         pos = 0;
  196.     }
  197.  
  198.     /* not found */
  199. #ifdef DEBUG
  200.     msg("/%s/ not found", ptrn);
  201. #else
  202.     msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
  203. #endif
  204.     return MARK_UNSET;
  205. }
  206.  
  207. MARK    m_bsrch(m, ptrn)
  208.     MARK    m;    /* where to start searching */
  209.     char    *ptrn;    /* pattern to search for */
  210. {
  211.     long    l;    /* line# of line to be searched */
  212.     char    *line;    /* text of line to be searched */
  213.     int    wrapped;/* boolean: has our search wrapped yet? */
  214.     int    pos;    /* last acceptable idx for a match on this line */
  215.     int    last;    /* remembered idx of the last acceptable match on this line */
  216.     int    try;    /* an idx at which we strat searching for another match */
  217. #ifndef CRUNCH
  218.     long    delta = INFINITY;/* line offset, for things like "/foo/+1" */
  219. #endif
  220.  
  221.     /* remember: "previous search was not forward" */
  222.     prevsf = FALSE;
  223.  
  224.     if (ptrn && *ptrn)
  225.     {
  226.         /* locate the closing '?', if any */
  227.         line = parseptrn(ptrn);
  228. #ifndef CRUNCH
  229.         if (*line)
  230.         {
  231.             delta = atol(line);
  232.         }
  233. #endif
  234.         ptrn++;
  235.  
  236.         /* free the previous pattern, if any */
  237.         if (re) _free_(re);
  238.  
  239.         /* compile the pattern */
  240.         re = regcomp(ptrn);
  241.         if (!re)
  242.         {
  243.             return MARK_UNSET;
  244.         }
  245.     }
  246.     else if (!re)
  247.     {
  248.         msg("No previous expression");
  249.         return MARK_UNSET;
  250.     }
  251.  
  252.     /* search backward for the pattern */
  253.     pos = markidx(m);
  254.     wrapped = FALSE;
  255.     for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
  256.     {
  257.         /* wrap search */
  258.         if (l < 1)
  259.         {
  260.             if (*o_wrapscan)
  261.             {
  262.                 l = nlines + 1;
  263.                 wrapped = TRUE;
  264.                 continue;
  265.             }
  266.             else
  267.             {
  268.                 break;
  269.             }
  270.         }
  271.  
  272.         /* get this line */
  273.         line = fetchline(l);
  274.  
  275.         /* check this line */
  276.         if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
  277.         {
  278.             /* match!  now find the last acceptable one in this line */
  279.             do
  280.             {
  281.                 if (re->leavep)
  282.                     last = (int)(re->leavep - line);
  283.                 else
  284.                     last = (int)(re->startp[0] - line);
  285.                 try = (int)(re->endp[0] - line);
  286.             } while (try > 0
  287.                  && regexec(re, &line[try], FALSE)
  288.                  && (int)(re->startp[0] - line) < pos);
  289.  
  290.             if (wrapped && *o_warn)
  291.                 msg("(wrapped)");
  292. #ifndef CRUNCH
  293.             if (delta != INFINITY)
  294.             {
  295.                 l += delta;
  296.                 if (l < 1 || l > nlines)
  297.                 {
  298.                     msg("search offset too big");
  299.                     return MARK_UNSET;
  300.                 }
  301.                 force_flags = LNMD|INCL;
  302.                 return MARK_AT_LINE(l);
  303.             }
  304. #endif
  305.             return MARK_AT_LINE(l) + last;
  306.         }
  307.         pos = BLKSIZE;
  308.     }
  309.  
  310.     /* not found */
  311. #ifdef DEBUG
  312.     msg("?%s? not found", ptrn);
  313. #else
  314.     msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
  315. #endif
  316.     return MARK_UNSET;
  317. }
  318.