home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume7 / rvi / part3 / rv_search.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-09  |  4.8 KB  |  231 lines

  1. #include "rv.h"
  2. #include "regexp.h"
  3.  
  4. #ifdef CRAY
  5. #define move_cursor_flag   mc_flag
  6. #endif
  7.  
  8. static char prev_search[256];   /* Buffer holding previous search string */
  9. static char buf[256];        /* Buffer holding current search string */
  10. static regexp *cmp;        /* Compiled regular expression (RE) */
  11.  
  12. boolean
  13. search(direction, txt, move_cursor_flag)
  14. /*
  15.  * Search file for match
  16.  *
  17.  * Scan current line using regexec() for txt
  18.  * If not found, xmit search request to ed
  19.  *      Scan line that ed finds using regex()
  20.  * Put cursor at new location, if move_cursor_flag
  21.  */
  22. INT  direction;   /* Direction of search (-1, 1) */
  23. char *txt;        /* Regular expression to search for */
  24. boolean move_cursor_flag; /* TRUE if cursor to be moved to match */
  25. {
  26.     register struct sc_screen *sc;
  27.     register char *s, *s2;
  28.     register INT i, ch;
  29.     struct li_line   *line;
  30.     INT offset = 0;
  31.     char *found, numbuf[20];
  32.  
  33.     sc = &screen;
  34.     sc->sc_validcol = TRUE;
  35.     sc->sc_firstcol = sc->sc_lastcol = sc->sc_column;
  36.     sc->sc_firstline = sc->sc_lastline = sc->sc_lineno;
  37.  
  38.     if (txt == NULL)
  39.         return FALSE;
  40.     strcpy(buf, txt);
  41.     if (direction >= 0)
  42.         ch = '/';
  43.     else
  44.         ch = '?';
  45.     s = buf;
  46.     /*
  47.      * Scan for first / or ? not preceeded by an odd number of backslashes
  48.      */
  49.     i = 0;
  50.     while (*s != '\0' && (*s != ch || i & 1)) {
  51.         i = *s == '\\' ? i+1 : 0;
  52.         ++s;
  53.     }
  54.     /*
  55.      * Drop '\0' into matching / or ?
  56.      */
  57.     if (*s != '\0')
  58.         *s++ = '\0';
  59.     ch = *s;
  60.  
  61.     /*
  62.      * Check for +/- offset
  63.      */
  64.     if (ch == '+' || ch == '-') {
  65.         offset = atoi(s);
  66.         if (offset == 0 && *(s+1) != '0')
  67.             offset = 1;
  68.         if (*s == '-')
  69.             offset = -offset;
  70.         sc->sc_validcol = FALSE;
  71.     }
  72.  
  73.     if (*buf == '\0')
  74.         strcpy(buf, prev_search);
  75.     if (*buf == '\0') {
  76.         botprint(TRUE, "No remembered search string");
  77.         return FALSE;
  78.     }
  79.     /*
  80.      * Compile RE
  81.      */
  82.     if (cmp)
  83.         free(cmp);
  84.     if ((cmp = regcomp(buf)) == 0) {
  85.         return FALSE;
  86.     }
  87.  
  88.     strcpy(prev_search, buf);
  89.  
  90.     line = sc->sc_curline;
  91.     s = &line->li_text[sc->sc_column];
  92.     found = NULL;
  93.     if (direction >= 0) {
  94.         /*
  95.          * Search current line after cursor 
  96.          */
  97.         if (*buf != '^' && *++s != '\0')
  98.             if (regexec(cmp, s) != 0) {
  99.                 found = cmp->startp[0];
  100.                 sc->sc_lastcol = found - line->li_text - 1;
  101.             }
  102.     } else {
  103.         /*
  104.          * Search current line before cursor
  105.          */
  106.         s2 = line->li_text;
  107.         while (s2 < s) {
  108.             if (regexec(cmp, s2) == 0 || cmp->startp[0] >= s)
  109.                 break;
  110.             found = cmp->startp[0];
  111.             if (*buf == '^') /* If anchored */
  112.                 break;
  113.             s2 = cmp->startp[0]+1;
  114.         }
  115.         if (found) {
  116.             sc->sc_lastcol--;
  117.             sc->sc_firstcol = found - line->li_text;
  118.         }
  119.     }
  120.  
  121.     if (found) {
  122.         /*
  123.          * Found match on current line
  124.          */
  125.          if (offset != 0) {
  126.             /*
  127.              * Line offset requested from current line (sigh)
  128.              */
  129.             sc->sc_validcol = FALSE;
  130.             if ((i = sc->sc_lineno + offset) < 1) {
  131.                 botprint(TRUE, "Negative address");
  132.                 return FALSE;
  133.             }
  134.             if (i > file.fi_numlines) {
  135.                 botprint(TRUE, "Not that many lines in buffer");
  136.                 return FALSE;
  137.             }
  138.             if (i < sc->sc_lineno)
  139.                 sc->sc_firstline = i;
  140.             else if (i > sc->sc_lineno)
  141.                 sc->sc_lastline = i-1;
  142.             if (move_cursor_flag)
  143.                 move_abs_cursor(i, COL_FIRST_NONWHITE);
  144.             return TRUE;
  145.         }
  146.         if (move_cursor_flag)
  147.             if (sc->sc_firstcol != sc->sc_column)
  148.                 move_cursor(sc->sc_lineno, sc->sc_firstcol);
  149.             else
  150.                 move_cursor(sc->sc_lineno, sc->sc_lastcol+1);
  151.         return TRUE;
  152.         }
  153.  
  154.     sc->sc_validcol = FALSE;
  155.     /*
  156.      * Xmit search to ed
  157.      */
  158.     xmit_curline();
  159.     i = sc->sc_lineno;
  160.     if (direction >= 0)
  161.         xmit_ed("%d\n/%s/\n", i, buf);
  162.     else
  163.         xmit_ed("%d\n?%s?\n", i, buf);
  164.     xmit_sync();
  165.     xmit_ed(".=\n");
  166.     (void) recv_sync(FALSE);
  167.     (void) fgets(numbuf, 18, file.fi_fpin);
  168.     if ((i = atoi(numbuf)) == sc->sc_lineno) {
  169.         botprint(TRUE, "Pattern not found");
  170.         return FALSE;
  171.     }
  172.     if (set_wrapscan == FALSE && 
  173.         ((direction > 0 && i < sc->sc_lineno) ||
  174.          (direction < 0 && i > sc->sc_lineno))) { /* If wrapped */
  175.         botprint(TRUE, "Address search hit %s without matching pattern",
  176.             direction < 0 ? "TOP" : "BOTTOM");
  177.         return FALSE;
  178.     }
  179.         
  180.     i += offset;
  181.  
  182.     if (i < 1) {
  183.         botprint(TRUE, "Negative address");
  184.         return FALSE;
  185.     }
  186.     if (i > file.fi_numlines) {
  187.         botprint(TRUE, "Not that many lines in buffer");
  188.         return FALSE;
  189.     }
  190.  
  191.     if (i < sc->sc_lineno)
  192.         sc->sc_firstline = i;
  193.     else if (i > sc->sc_lineno)
  194.         sc->sc_lastline = i-1;
  195.     if (!move_cursor_flag)
  196.         return TRUE;
  197.         
  198.     /*
  199.      * Cursor movement requested
  200.      */
  201.  
  202.     /*
  203.      * Move to line,col of match
  204.      */
  205.     if (offset != 0) {
  206.         move_abs_cursor(i, COL_FIRST_NONWHITE);
  207.         return TRUE;
  208.     }
  209.     move_abs_cursor(i, 0);
  210.     line = sc->sc_curline;
  211.     if (direction >= 0) {
  212.         if (regexec(cmp, line->li_text) != 0)
  213.             sc->sc_column = cmp->startp[0] - line->li_text;
  214.     } else {
  215.         s2 = line->li_text;
  216.         found = NULL;
  217.         while (*s2 != '\0') {
  218.             if (regexec(cmp, s2) == 0)
  219.                 break;
  220.             found = cmp->startp[0];
  221.             if (*buf == '^') /* If anchored */
  222.                 break;
  223.             s2 = cmp->startp[0]+1;
  224.         }
  225.         if (found)
  226.             sc->sc_column = found - line->li_text;
  227.     }
  228.     move_cursor(sc->sc_lineno, sc->sc_column);
  229.     return TRUE;
  230. }
  231.